Refactor implicit function template implementation and fix 58534, 58536, 58548, 58549 and 58637.
gcc/ * tree.c (grow_tree_vec_stat): New function ... * tree.h (grow_tree_vec_stat) (grow_tree_vec): ... and its declaration and macro front-end. gcc/cp/ PR c++/58534 PR c++/58536 PR c++/58548 PR c++/58549 PR c++/58637 * parser.h (struct cp_parser): New members implicit_template_parms, implicit_template_scope and auto_is_implicit_function_template_parm_p. * parser.c (add_implicit_template_parms): Refactor as ... (synthesize_implicit_template_parm): ... this to append a new template type parm to the current template parameter list (introducing a new list if necessary). Removed push_deferring_access_checks. (finish_fully_implicit_template): Removed pop_deferring_access_checks. (cp_parser_new): Initialize new cp_parser members. (cp_parser_parameter_declaration_clause): Consider auto as implicit template parm when parsing a parameter declaration (unless parsing an explicit specialization). (cp_parser_parameter_declaration_list): Remove local implicit_template_parms counter and reset cp_parser implicit template state when complete. (cp_parser_lambda_expression): Reset implicit template cp_parser members whilst generating lambda class. (cp_parser_function_definition_after_declarator): Reset implicit template cp_parser members whilst parsing function definition. (make_generic_type_name): Respell '<autoN>' as 'auto:N' which works better with template diagnostics. (cp_parser_simple_type_specifier): Synthesize implicit template parm on parsing 'auto' if auto_is_implicit_function_template_parm_p and provide diagnostics ... * decl.c (grokdeclarator): ... that were previously done here. gcc/testsuite/g++.dg/ * cpp1y/pr58534.C: New testcase. * cpp1y/pr58536.C: New testcase. * cpp1y/pr58548.C: New testcase. * cpp1y/pr58549.C: New testcase. * cpp1y/pr58637.C: New testcase. From-SVN: r204714
This commit is contained in:
parent
27297d2d1b
commit
0dca5025f0
|
@ -1,3 +1,9 @@
|
||||||
|
2013-11-12 Adam Butcher <adam@jessamine.co.uk>
|
||||||
|
|
||||||
|
* tree.c (grow_tree_vec_stat): New function ...
|
||||||
|
* tree.h (grow_tree_vec_stat) (grow_tree_vec): ... and its declaration
|
||||||
|
and macro front-end.
|
||||||
|
|
||||||
2013-11-12 Marek Polacek <polacek@redhat.com>
|
2013-11-12 Marek Polacek <polacek@redhat.com>
|
||||||
|
|
||||||
* final.c (update_alignments): Initialize label to NULL_RTX.
|
* final.c (update_alignments): Initialize label to NULL_RTX.
|
||||||
|
|
|
@ -1,3 +1,35 @@
|
||||||
|
2013-11-12 Adam Butcher <adam@jessamine.co.uk>
|
||||||
|
|
||||||
|
PR c++/58534
|
||||||
|
PR c++/58536
|
||||||
|
PR c++/58548
|
||||||
|
PR c++/58549
|
||||||
|
PR c++/58637
|
||||||
|
* parser.h (struct cp_parser): New members implicit_template_parms,
|
||||||
|
implicit_template_scope and auto_is_implicit_function_template_parm_p.
|
||||||
|
* parser.c (add_implicit_template_parms): Refactor as ...
|
||||||
|
(synthesize_implicit_template_parm): ... this to append a new template
|
||||||
|
type parm to the current template parameter list (introducing a new list
|
||||||
|
if necessary). Removed push_deferring_access_checks.
|
||||||
|
(finish_fully_implicit_template): Removed pop_deferring_access_checks.
|
||||||
|
(cp_parser_new): Initialize new cp_parser members.
|
||||||
|
(cp_parser_parameter_declaration_clause): Consider auto as implicit
|
||||||
|
template parm when parsing a parameter declaration (unless parsing an
|
||||||
|
explicit specialization).
|
||||||
|
(cp_parser_parameter_declaration_list): Remove local
|
||||||
|
implicit_template_parms counter and reset cp_parser implicit template
|
||||||
|
state when complete.
|
||||||
|
(cp_parser_lambda_expression): Reset implicit template cp_parser members
|
||||||
|
whilst generating lambda class.
|
||||||
|
(cp_parser_function_definition_after_declarator): Reset implicit
|
||||||
|
template cp_parser members whilst parsing function definition.
|
||||||
|
(make_generic_type_name): Respell '<autoN>' as 'auto:N' which works
|
||||||
|
better with template diagnostics.
|
||||||
|
(cp_parser_simple_type_specifier): Synthesize implicit template parm on
|
||||||
|
parsing 'auto' if auto_is_implicit_function_template_parm_p and provide
|
||||||
|
diagnostics ...
|
||||||
|
* decl.c (grokdeclarator): ... that were previously done here.
|
||||||
|
|
||||||
2013-11-12 Paolo Carlini <paolo.carlini@oracle.com>
|
2013-11-12 Paolo Carlini <paolo.carlini@oracle.com>
|
||||||
|
|
||||||
PR c++/57734
|
PR c++/57734
|
||||||
|
|
|
@ -10381,33 +10381,11 @@ grokdeclarator (const cp_declarator *declarator,
|
||||||
|
|
||||||
if (type_uses_auto (type))
|
if (type_uses_auto (type))
|
||||||
{
|
{
|
||||||
if (template_parm_flag)
|
if (cxx_dialect >= cxx1y)
|
||||||
{
|
error ("%<auto%> parameter not permitted in this context");
|
||||||
error ("template parameter declared %<auto%>");
|
|
||||||
type = error_mark_node;
|
|
||||||
}
|
|
||||||
else if (decl_context == CATCHPARM)
|
|
||||||
{
|
|
||||||
error ("catch parameter declared %<auto%>");
|
|
||||||
type = error_mark_node;
|
|
||||||
}
|
|
||||||
else if (current_class_type && LAMBDA_TYPE_P (current_class_type))
|
|
||||||
{
|
|
||||||
if (cxx_dialect < cxx1y)
|
|
||||||
pedwarn (location_of (type), 0,
|
|
||||||
"use of %<auto%> in lambda parameter declaration "
|
|
||||||
"only available with "
|
|
||||||
"-std=c++1y or -std=gnu++1y");
|
|
||||||
}
|
|
||||||
else if (cxx_dialect < cxx1y)
|
|
||||||
pedwarn (location_of (type), 0,
|
|
||||||
"use of %<auto%> in parameter declaration "
|
|
||||||
"only available with "
|
|
||||||
"-std=c++1y or -std=gnu++1y");
|
|
||||||
else
|
else
|
||||||
pedwarn (location_of (type), OPT_Wpedantic,
|
error ("parameter declared %<auto%>");
|
||||||
"ISO C++ forbids use of %<auto%> in parameter "
|
type = error_mark_node;
|
||||||
"declaration");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* A parameter declared as an array of T is really a pointer to T.
|
/* A parameter declared as an array of T is really a pointer to T.
|
||||||
|
|
279
gcc/cp/parser.c
279
gcc/cp/parser.c
|
@ -2107,8 +2107,8 @@ static bool cp_parser_ctor_initializer_opt_and_function_body
|
||||||
static tree cp_parser_late_parsing_omp_declare_simd
|
static tree cp_parser_late_parsing_omp_declare_simd
|
||||||
(cp_parser *, tree);
|
(cp_parser *, tree);
|
||||||
|
|
||||||
static tree add_implicit_template_parms
|
static tree synthesize_implicit_template_parm
|
||||||
(cp_parser *, size_t, tree);
|
(cp_parser *);
|
||||||
static tree finish_fully_implicit_template
|
static tree finish_fully_implicit_template
|
||||||
(cp_parser *, tree);
|
(cp_parser *, tree);
|
||||||
|
|
||||||
|
@ -3443,7 +3443,10 @@ cp_parser_new (void)
|
||||||
parser->num_template_parameter_lists = 0;
|
parser->num_template_parameter_lists = 0;
|
||||||
|
|
||||||
/* Not declaring an implicit function template. */
|
/* Not declaring an implicit function template. */
|
||||||
|
parser->auto_is_implicit_function_template_parm_p = false;
|
||||||
parser->fully_implicit_function_template_p = false;
|
parser->fully_implicit_function_template_p = false;
|
||||||
|
parser->implicit_template_parms = 0;
|
||||||
|
parser->implicit_template_scope = 0;
|
||||||
|
|
||||||
return parser;
|
return parser;
|
||||||
}
|
}
|
||||||
|
@ -8660,12 +8663,17 @@ cp_parser_lambda_expression (cp_parser* parser)
|
||||||
= parser->num_template_parameter_lists;
|
= parser->num_template_parameter_lists;
|
||||||
unsigned char in_statement = parser->in_statement;
|
unsigned char in_statement = parser->in_statement;
|
||||||
bool in_switch_statement_p = parser->in_switch_statement_p;
|
bool in_switch_statement_p = parser->in_switch_statement_p;
|
||||||
bool fully_implicit_function_template_p = parser->fully_implicit_function_template_p;
|
bool fully_implicit_function_template_p
|
||||||
|
= parser->fully_implicit_function_template_p;
|
||||||
|
tree implicit_template_parms = parser->implicit_template_parms;
|
||||||
|
cp_binding_level* implicit_template_scope = parser->implicit_template_scope;
|
||||||
|
|
||||||
parser->num_template_parameter_lists = 0;
|
parser->num_template_parameter_lists = 0;
|
||||||
parser->in_statement = 0;
|
parser->in_statement = 0;
|
||||||
parser->in_switch_statement_p = false;
|
parser->in_switch_statement_p = false;
|
||||||
parser->fully_implicit_function_template_p = false;
|
parser->fully_implicit_function_template_p = false;
|
||||||
|
parser->implicit_template_parms = 0;
|
||||||
|
parser->implicit_template_scope = 0;
|
||||||
|
|
||||||
/* By virtue of defining a local class, a lambda expression has access to
|
/* By virtue of defining a local class, a lambda expression has access to
|
||||||
the private variables of enclosing classes. */
|
the private variables of enclosing classes. */
|
||||||
|
@ -8689,7 +8697,10 @@ cp_parser_lambda_expression (cp_parser* parser)
|
||||||
parser->num_template_parameter_lists = saved_num_template_parameter_lists;
|
parser->num_template_parameter_lists = saved_num_template_parameter_lists;
|
||||||
parser->in_statement = in_statement;
|
parser->in_statement = in_statement;
|
||||||
parser->in_switch_statement_p = in_switch_statement_p;
|
parser->in_switch_statement_p = in_switch_statement_p;
|
||||||
parser->fully_implicit_function_template_p = fully_implicit_function_template_p;
|
parser->fully_implicit_function_template_p
|
||||||
|
= fully_implicit_function_template_p;
|
||||||
|
parser->implicit_template_parms = implicit_template_parms;
|
||||||
|
parser->implicit_template_scope = implicit_template_scope;
|
||||||
}
|
}
|
||||||
|
|
||||||
pop_deferring_access_checks ();
|
pop_deferring_access_checks ();
|
||||||
|
@ -14096,7 +14107,7 @@ cp_parser_explicit_specialization (cp_parser* parser)
|
||||||
cp_parser_single_declaration (parser,
|
cp_parser_single_declaration (parser,
|
||||||
/*checks=*/NULL,
|
/*checks=*/NULL,
|
||||||
/*member_p=*/false,
|
/*member_p=*/false,
|
||||||
/*explicit_specialization_p=*/true,
|
/*explicit_specialization_p=*/true,
|
||||||
/*friend_p=*/NULL);
|
/*friend_p=*/NULL);
|
||||||
/* We're done with the specialization. */
|
/* We're done with the specialization. */
|
||||||
end_specialization ();
|
end_specialization ();
|
||||||
|
@ -14398,10 +14409,33 @@ cp_parser_simple_type_specifier (cp_parser* parser,
|
||||||
case RID_VOID:
|
case RID_VOID:
|
||||||
type = void_type_node;
|
type = void_type_node;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case RID_AUTO:
|
case RID_AUTO:
|
||||||
maybe_warn_cpp0x (CPP0X_AUTO);
|
maybe_warn_cpp0x (CPP0X_AUTO);
|
||||||
type = make_auto ();
|
if (parser->auto_is_implicit_function_template_parm_p)
|
||||||
|
{
|
||||||
|
type = synthesize_implicit_template_parm (parser);
|
||||||
|
|
||||||
|
if (current_class_type && LAMBDA_TYPE_P (current_class_type))
|
||||||
|
{
|
||||||
|
if (cxx_dialect < cxx1y)
|
||||||
|
pedwarn (location_of (type), 0,
|
||||||
|
"use of %<auto%> in lambda parameter declaration "
|
||||||
|
"only available with "
|
||||||
|
"-std=c++1y or -std=gnu++1y");
|
||||||
|
}
|
||||||
|
else if (cxx_dialect < cxx1y)
|
||||||
|
pedwarn (location_of (type), 0,
|
||||||
|
"use of %<auto%> in parameter declaration "
|
||||||
|
"only available with "
|
||||||
|
"-std=c++1y or -std=gnu++1y");
|
||||||
|
else
|
||||||
|
pedwarn (location_of (type), OPT_Wpedantic,
|
||||||
|
"ISO C++ forbids use of %<auto%> in parameter "
|
||||||
|
"declaration");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
type = make_auto ();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case RID_DECLTYPE:
|
case RID_DECLTYPE:
|
||||||
|
@ -17980,6 +18014,20 @@ cp_parser_parameter_declaration_clause (cp_parser* parser)
|
||||||
bool ellipsis_p;
|
bool ellipsis_p;
|
||||||
bool is_error;
|
bool is_error;
|
||||||
|
|
||||||
|
struct cleanup {
|
||||||
|
cp_parser* parser;
|
||||||
|
int auto_is_implicit_function_template_parm_p;
|
||||||
|
~cleanup() {
|
||||||
|
parser->auto_is_implicit_function_template_parm_p
|
||||||
|
= auto_is_implicit_function_template_parm_p;
|
||||||
|
}
|
||||||
|
} cleanup = { parser, parser->auto_is_implicit_function_template_parm_p };
|
||||||
|
|
||||||
|
(void) cleanup;
|
||||||
|
|
||||||
|
if (!processing_specialization)
|
||||||
|
parser->auto_is_implicit_function_template_parm_p = true;
|
||||||
|
|
||||||
/* Peek at the next token. */
|
/* Peek at the next token. */
|
||||||
token = cp_lexer_peek_token (parser->lexer);
|
token = cp_lexer_peek_token (parser->lexer);
|
||||||
/* Check for trivial parameter-declaration-clauses. */
|
/* Check for trivial parameter-declaration-clauses. */
|
||||||
|
@ -18067,7 +18115,6 @@ cp_parser_parameter_declaration_list (cp_parser* parser, bool *is_error)
|
||||||
tree *tail = ¶meters;
|
tree *tail = ¶meters;
|
||||||
bool saved_in_unbraced_linkage_specification_p;
|
bool saved_in_unbraced_linkage_specification_p;
|
||||||
int index = 0;
|
int index = 0;
|
||||||
int implicit_template_parms = 0;
|
|
||||||
|
|
||||||
/* Assume all will go well. */
|
/* Assume all will go well. */
|
||||||
*is_error = false;
|
*is_error = false;
|
||||||
|
@ -18095,18 +18142,11 @@ cp_parser_parameter_declaration_list (cp_parser* parser, bool *is_error)
|
||||||
deprecated_state = DEPRECATED_SUPPRESS;
|
deprecated_state = DEPRECATED_SUPPRESS;
|
||||||
|
|
||||||
if (parameter)
|
if (parameter)
|
||||||
{
|
decl = grokdeclarator (parameter->declarator,
|
||||||
decl = grokdeclarator (parameter->declarator,
|
¶meter->decl_specifiers,
|
||||||
¶meter->decl_specifiers,
|
PARM,
|
||||||
PARM,
|
parameter->default_argument != NULL_TREE,
|
||||||
parameter->default_argument != NULL_TREE,
|
¶meter->decl_specifiers.attributes);
|
||||||
¶meter->decl_specifiers.attributes);
|
|
||||||
|
|
||||||
if (TREE_TYPE (decl) != error_mark_node
|
|
||||||
&& parameter->decl_specifiers.type
|
|
||||||
&& is_auto_or_concept (parameter->decl_specifiers.type))
|
|
||||||
++implicit_template_parms;
|
|
||||||
}
|
|
||||||
|
|
||||||
deprecated_state = DEPRECATED_NORMAL;
|
deprecated_state = DEPRECATED_NORMAL;
|
||||||
|
|
||||||
|
@ -18194,10 +18234,12 @@ cp_parser_parameter_declaration_list (cp_parser* parser, bool *is_error)
|
||||||
parser->in_unbraced_linkage_specification_p
|
parser->in_unbraced_linkage_specification_p
|
||||||
= saved_in_unbraced_linkage_specification_p;
|
= saved_in_unbraced_linkage_specification_p;
|
||||||
|
|
||||||
if (parameters != error_mark_node && implicit_template_parms)
|
if (cp_binding_level *its = parser->implicit_template_scope)
|
||||||
parameters = add_implicit_template_parms (parser,
|
if (current_binding_level->level_chain == its)
|
||||||
implicit_template_parms,
|
{
|
||||||
parameters);
|
parser->implicit_template_parms = 0;
|
||||||
|
parser->implicit_template_scope = 0;
|
||||||
|
}
|
||||||
|
|
||||||
return parameters;
|
return parameters;
|
||||||
}
|
}
|
||||||
|
@ -22461,6 +22503,15 @@ cp_parser_function_definition_after_declarator (cp_parser* parser,
|
||||||
bool saved_in_function_body;
|
bool saved_in_function_body;
|
||||||
unsigned saved_num_template_parameter_lists;
|
unsigned saved_num_template_parameter_lists;
|
||||||
cp_token *token;
|
cp_token *token;
|
||||||
|
bool fully_implicit_function_template_p
|
||||||
|
= parser->fully_implicit_function_template_p;
|
||||||
|
parser->fully_implicit_function_template_p = false;
|
||||||
|
tree implicit_template_parms
|
||||||
|
= parser->implicit_template_parms;
|
||||||
|
parser->implicit_template_parms = 0;
|
||||||
|
cp_binding_level* implicit_template_scope
|
||||||
|
= parser->implicit_template_scope;
|
||||||
|
parser->implicit_template_scope = 0;
|
||||||
|
|
||||||
saved_in_function_body = parser->in_function_body;
|
saved_in_function_body = parser->in_function_body;
|
||||||
parser->in_function_body = true;
|
parser->in_function_body = true;
|
||||||
|
@ -22533,6 +22584,13 @@ cp_parser_function_definition_after_declarator (cp_parser* parser,
|
||||||
= saved_num_template_parameter_lists;
|
= saved_num_template_parameter_lists;
|
||||||
parser->in_function_body = saved_in_function_body;
|
parser->in_function_body = saved_in_function_body;
|
||||||
|
|
||||||
|
parser->fully_implicit_function_template_p
|
||||||
|
= fully_implicit_function_template_p;
|
||||||
|
parser->implicit_template_parms
|
||||||
|
= implicit_template_parms;
|
||||||
|
parser->implicit_template_scope
|
||||||
|
= implicit_template_scope;
|
||||||
|
|
||||||
if (parser->fully_implicit_function_template_p)
|
if (parser->fully_implicit_function_template_p)
|
||||||
finish_fully_implicit_template (parser, /*member_decl_opt=*/0);
|
finish_fully_implicit_template (parser, /*member_decl_opt=*/0);
|
||||||
|
|
||||||
|
@ -31116,7 +31174,7 @@ static tree
|
||||||
make_generic_type_name ()
|
make_generic_type_name ()
|
||||||
{
|
{
|
||||||
char buf[32];
|
char buf[32];
|
||||||
sprintf (buf, "<auto%d>", ++generic_parm_count);
|
sprintf (buf, "auto:%d", ++generic_parm_count);
|
||||||
return get_identifier (buf);
|
return get_identifier (buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31130,110 +31188,138 @@ tree_type_is_auto_or_concept (const_tree t)
|
||||||
return TREE_TYPE (t) && is_auto_or_concept (TREE_TYPE (t));
|
return TREE_TYPE (t) && is_auto_or_concept (TREE_TYPE (t));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Add EXPECT_COUNT implicit template parameters gleaned from the generic
|
/* Add an implicit template type parameter to the CURRENT_TEMPLATE_PARMS
|
||||||
type parameters in PARAMETERS to the CURRENT_TEMPLATE_PARMS (creating a new
|
(creating a new template parameter list if necessary). Returns the newly
|
||||||
template parameter list if necessary). Returns PARAMETERS suitably rewritten
|
created template type parm. */
|
||||||
to reference the newly created types or ERROR_MARK_NODE on failure. */
|
|
||||||
|
|
||||||
tree
|
tree
|
||||||
add_implicit_template_parms (cp_parser *parser, size_t expect_count,
|
synthesize_implicit_template_parm (cp_parser *parser)
|
||||||
tree parameters)
|
|
||||||
{
|
{
|
||||||
gcc_assert (current_binding_level->kind == sk_function_parms);
|
gcc_assert (current_binding_level->kind == sk_function_parms);
|
||||||
|
|
||||||
cp_binding_level *fn_parms_scope = current_binding_level;
|
/* We are either continuing a function template that already contains implicit
|
||||||
|
template parameters, creating a new fully-implicit function template, or
|
||||||
|
extending an existing explicit function template with implicit template
|
||||||
|
parameters. */
|
||||||
|
|
||||||
bool become_template =
|
cp_binding_level *const entry_scope = current_binding_level;
|
||||||
fn_parms_scope->level_chain->kind != sk_template_parms;
|
|
||||||
|
|
||||||
size_t synth_count = 0;
|
bool become_template = false;
|
||||||
|
cp_binding_level *parent_scope = 0;
|
||||||
|
|
||||||
/* Roll back a scope level and either introduce a new template parameter list
|
if (parser->implicit_template_scope)
|
||||||
or update an existing one. The function scope is added back after template
|
|
||||||
parameter synthesis below. */
|
|
||||||
current_binding_level = fn_parms_scope->level_chain;
|
|
||||||
|
|
||||||
/* TPARMS tracks the function's template parameter list. This is either a new
|
|
||||||
chain in the case of a fully implicit function template or an extension of
|
|
||||||
the function's explicitly specified template parameter list. */
|
|
||||||
tree tparms = NULL_TREE;
|
|
||||||
|
|
||||||
if (become_template)
|
|
||||||
{
|
{
|
||||||
push_deferring_access_checks (dk_deferred);
|
gcc_assert (parser->implicit_template_parms);
|
||||||
begin_template_parm_list ();
|
|
||||||
|
|
||||||
parser->fully_implicit_function_template_p = true;
|
current_binding_level = parser->implicit_template_scope;
|
||||||
++parser->num_template_parameter_lists;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Roll back the innermost template parameter list such that it may be
|
/* Roll back to the existing template parameter scope (in the case of
|
||||||
extended in the loop below as if it were being explicitly declared. */
|
extending an explicit function template) or introduce a new template
|
||||||
|
parameter scope ahead of the function parameter scope (or class scope
|
||||||
|
in the case of out-of-line member definitions). The function scope is
|
||||||
|
added back after template parameter synthesis below. */
|
||||||
|
|
||||||
gcc_assert (current_template_parms);
|
cp_binding_level *scope = entry_scope;
|
||||||
|
|
||||||
/* Pop the innermost template parms into TPARMS. */
|
while (scope->kind == sk_function_parms)
|
||||||
tree inner_vec = INNERMOST_TEMPLATE_PARMS (current_template_parms);
|
|
||||||
current_template_parms = TREE_CHAIN (current_template_parms);
|
|
||||||
|
|
||||||
size_t inner_vec_len = TREE_VEC_LENGTH (inner_vec);
|
|
||||||
if (inner_vec_len != 0)
|
|
||||||
{
|
{
|
||||||
tree t = tparms = TREE_VEC_ELT (inner_vec, 0);
|
parent_scope = scope;
|
||||||
for (size_t n = 1; n < inner_vec_len; ++n)
|
scope = scope->level_chain;
|
||||||
t = TREE_CHAIN (t) = TREE_VEC_ELT (inner_vec, n);
|
|
||||||
}
|
}
|
||||||
|
if (current_class_type && !LAMBDA_TYPE_P (current_class_type)
|
||||||
|
&& parser->num_classes_being_defined == 0)
|
||||||
|
while (scope->kind == sk_class)
|
||||||
|
{
|
||||||
|
parent_scope = scope;
|
||||||
|
scope = scope->level_chain;
|
||||||
|
}
|
||||||
|
|
||||||
++processing_template_parmlist;
|
current_binding_level = scope;
|
||||||
}
|
|
||||||
|
|
||||||
for (tree p = parameters; p && synth_count < expect_count; p = TREE_CHAIN (p))
|
if (scope->kind != sk_template_parms)
|
||||||
{
|
{
|
||||||
tree generic_type_ptr
|
/* Introduce a new template parameter list for implicit template
|
||||||
= find_type_usage (TREE_VALUE (p), tree_type_is_auto_or_concept);
|
parameters. */
|
||||||
|
|
||||||
if (!generic_type_ptr)
|
become_template = true;
|
||||||
continue;
|
|
||||||
|
|
||||||
++synth_count;
|
parser->implicit_template_scope
|
||||||
|
= begin_scope (sk_template_parms, NULL);
|
||||||
|
|
||||||
tree synth_id = make_generic_type_name ();
|
++processing_template_decl;
|
||||||
tree synth_tmpl_parm = finish_template_type_parm (class_type_node,
|
|
||||||
synth_id);
|
|
||||||
tparms = process_template_parm (tparms, DECL_SOURCE_LOCATION (TREE_VALUE
|
|
||||||
(p)),
|
|
||||||
build_tree_list (NULL_TREE,
|
|
||||||
synth_tmpl_parm),
|
|
||||||
/*non_type=*/false,
|
|
||||||
/*param_pack=*/false);
|
|
||||||
|
|
||||||
/* Rewrite the type of P to be the template_parm added above (getdecls is
|
parser->fully_implicit_function_template_p = true;
|
||||||
used to retrieve it since it is the most recent declaration in this
|
++parser->num_template_parameter_lists;
|
||||||
scope). Qualifiers need to be preserved also. */
|
}
|
||||||
|
|
||||||
tree& cur_type = TREE_TYPE (generic_type_ptr);
|
|
||||||
tree new_type = TREE_TYPE (getdecls ());
|
|
||||||
|
|
||||||
if (TYPE_QUALS (cur_type))
|
|
||||||
cur_type = cp_build_qualified_type (new_type, TYPE_QUALS (cur_type));
|
|
||||||
else
|
else
|
||||||
cur_type = new_type;
|
{
|
||||||
|
/* Synthesize implicit template parameters at the end of the explicit
|
||||||
|
template parameter list. */
|
||||||
|
|
||||||
|
gcc_assert (current_template_parms);
|
||||||
|
|
||||||
|
parser->implicit_template_scope = scope;
|
||||||
|
|
||||||
|
tree v = INNERMOST_TEMPLATE_PARMS (current_template_parms);
|
||||||
|
parser->implicit_template_parms
|
||||||
|
= TREE_VEC_ELT (v, TREE_VEC_LENGTH (v) - 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
gcc_assert (synth_count == expect_count);
|
/* Synthesize a new template parameter and track the current template
|
||||||
|
parameter chain with implicit_template_parms. */
|
||||||
|
|
||||||
push_binding_level (fn_parms_scope);
|
tree synth_id = make_generic_type_name ();
|
||||||
|
tree synth_tmpl_parm = finish_template_type_parm (class_type_node,
|
||||||
|
synth_id);
|
||||||
|
tree new_parm
|
||||||
|
= process_template_parm (parser->implicit_template_parms,
|
||||||
|
input_location,
|
||||||
|
build_tree_list (NULL_TREE, synth_tmpl_parm),
|
||||||
|
/*non_type=*/false,
|
||||||
|
/*param_pack=*/false);
|
||||||
|
|
||||||
end_template_parm_list (tparms);
|
|
||||||
|
|
||||||
return parameters;
|
if (parser->implicit_template_parms)
|
||||||
|
parser->implicit_template_parms
|
||||||
|
= TREE_CHAIN (parser->implicit_template_parms);
|
||||||
|
else
|
||||||
|
parser->implicit_template_parms = new_parm;
|
||||||
|
|
||||||
|
tree new_type = TREE_TYPE (getdecls ());
|
||||||
|
|
||||||
|
/* If creating a fully implicit function template, start the new implicit
|
||||||
|
template parameter list with this synthesized type, otherwise grow the
|
||||||
|
current template parameter list. */
|
||||||
|
|
||||||
|
if (become_template)
|
||||||
|
{
|
||||||
|
parent_scope->level_chain = current_binding_level;
|
||||||
|
|
||||||
|
tree new_parms = make_tree_vec (1);
|
||||||
|
TREE_VEC_ELT (new_parms, 0) = parser->implicit_template_parms;
|
||||||
|
current_template_parms = tree_cons (size_int (processing_template_decl),
|
||||||
|
new_parms, current_template_parms);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tree& new_parms = INNERMOST_TEMPLATE_PARMS (current_template_parms);
|
||||||
|
int new_parm_idx = TREE_VEC_LENGTH (new_parms);
|
||||||
|
new_parms = grow_tree_vec_stat (new_parms, new_parm_idx + 1);
|
||||||
|
TREE_VEC_ELT (new_parms, new_parm_idx) = parser->implicit_template_parms;
|
||||||
|
}
|
||||||
|
|
||||||
|
current_binding_level = entry_scope;
|
||||||
|
|
||||||
|
return new_type;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Finish the declaration of a fully implicit function template. Such a
|
/* Finish the declaration of a fully implicit function template. Such a
|
||||||
template has no explicit template parameter list so has not been through the
|
template has no explicit template parameter list so has not been through the
|
||||||
normal template head and tail processing. add_implicit_template_parms tries
|
normal template head and tail processing. synthesize_implicit_template_parm
|
||||||
to do the head; this tries to do the tail. MEMBER_DECL_OPT should be
|
tries to do the head; this tries to do the tail. MEMBER_DECL_OPT should be
|
||||||
provided if the declaration is a class member such that its template
|
provided if the declaration is a class member such that its template
|
||||||
declaration can be completed. If MEMBER_DECL_OPT is provided the finished
|
declaration can be completed. If MEMBER_DECL_OPT is provided the finished
|
||||||
form is returned. Otherwise NULL_TREE is returned. */
|
form is returned. Otherwise NULL_TREE is returned. */
|
||||||
|
@ -31251,7 +31337,6 @@ finish_fully_implicit_template (cp_parser *parser, tree member_decl_opt)
|
||||||
DECL_VIRTUAL_P (member_decl_opt) = false;
|
DECL_VIRTUAL_P (member_decl_opt) = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
pop_deferring_access_checks ();
|
|
||||||
if (member_decl_opt)
|
if (member_decl_opt)
|
||||||
member_decl_opt = finish_member_template_decl (member_decl_opt);
|
member_decl_opt = finish_member_template_decl (member_decl_opt);
|
||||||
end_template_decl ();
|
end_template_decl ();
|
||||||
|
|
|
@ -360,11 +360,30 @@ typedef struct GTY(()) cp_parser {
|
||||||
data structure with everything needed for parsing the clauses. */
|
data structure with everything needed for parsing the clauses. */
|
||||||
cp_omp_declare_simd_data * GTY((skip)) omp_declare_simd;
|
cp_omp_declare_simd_data * GTY((skip)) omp_declare_simd;
|
||||||
|
|
||||||
|
/* Nonzero if parsing a parameter list where 'auto' should trigger an implicit
|
||||||
|
template parameter. */
|
||||||
|
bool auto_is_implicit_function_template_parm_p;
|
||||||
|
|
||||||
/* TRUE if the function being declared was made a template due to its
|
/* TRUE if the function being declared was made a template due to its
|
||||||
parameter list containing generic type specifiers (`auto' or concept
|
parameter list containing generic type specifiers (`auto' or concept
|
||||||
identifiers) rather than an explicit template parameter list. */
|
identifiers) rather than an explicit template parameter list. */
|
||||||
bool fully_implicit_function_template_p;
|
bool fully_implicit_function_template_p;
|
||||||
|
|
||||||
|
/* Tracks the function's template parameter list when declaring a function
|
||||||
|
using generic type parameters. This is either a new chain in the case of a
|
||||||
|
fully implicit function template or an extension of the function's existing
|
||||||
|
template parameter list. This is tracked to optimize calls subsequent
|
||||||
|
calls to synthesize_implicit_template_parm during
|
||||||
|
cp_parser_parameter_declaration. */
|
||||||
|
tree implicit_template_parms;
|
||||||
|
|
||||||
|
/* The scope into which an implicit template parameter list has been
|
||||||
|
introduced or an existing template parameter list is being extended with
|
||||||
|
implicit template paramaters. In most cases this is the sk_function_parms
|
||||||
|
scope containing the use of a generic type. In the case of an out-of-line
|
||||||
|
member definition using a generic type, it is the sk_class scope. */
|
||||||
|
cp_binding_level* implicit_template_scope;
|
||||||
|
|
||||||
} cp_parser;
|
} cp_parser;
|
||||||
|
|
||||||
/* In parser.c */
|
/* In parser.c */
|
||||||
|
|
|
@ -1,3 +1,16 @@
|
||||||
|
2013-11-12 Adam Butcher <adam@jessamine.co.uk>
|
||||||
|
|
||||||
|
PR c++/58534
|
||||||
|
PR c++/58536
|
||||||
|
PR c++/58548
|
||||||
|
PR c++/58549
|
||||||
|
PR c++/58637
|
||||||
|
* g++.dg/cpp1y/pr58534.C: New testcase.
|
||||||
|
* g++.dg/cpp1y/pr58536.C: New testcase.
|
||||||
|
* g++.dg/cpp1y/pr58548.C: New testcase.
|
||||||
|
* g++.dg/cpp1y/pr58549.C: New testcase.
|
||||||
|
* g++.dg/cpp1y/pr58637.C: New testcase.
|
||||||
|
|
||||||
2013-11-12 Joseph Myers <joseph@codesourcery.com>
|
2013-11-12 Joseph Myers <joseph@codesourcery.com>
|
||||||
|
|
||||||
* gcc.dg/c90-thread-local-1.c, gcc.dg/c99-thread-local-1.c,
|
* gcc.dg/c90-thread-local-1.c, gcc.dg/c99-thread-local-1.c,
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
// { dg-do compile }
|
||||||
|
// { dg-options "-std=gnu++1y" }
|
||||||
|
|
||||||
|
// PR c++/58534
|
||||||
|
|
||||||
|
template<typename> void foo(const auto&) {}
|
||||||
|
|
||||||
|
template<typename, typename...T> void foo(const auto&, T...) {}
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
// { dg-do compile }
|
||||||
|
// { dg-options "-std=gnu++1y" }
|
||||||
|
|
||||||
|
// PR c++/58536
|
||||||
|
|
||||||
|
struct A
|
||||||
|
{
|
||||||
|
A(auto);
|
||||||
|
};
|
||||||
|
|
||||||
|
A::A(auto) {}
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
// { dg-do compile }
|
||||||
|
// { dg-options "-std=gnu++1y" }
|
||||||
|
|
||||||
|
// PR c++/58548
|
||||||
|
|
||||||
|
void foo(auto)
|
||||||
|
{
|
||||||
|
struct A { int i; };
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
// { dg-do compile }
|
||||||
|
// { dg-options "-std=gnu++1y" }
|
||||||
|
|
||||||
|
// PR c++/58549
|
||||||
|
|
||||||
|
void foo(auto)
|
||||||
|
{
|
||||||
|
void bar();
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
// { dg-do compile }
|
||||||
|
// { dg-options "-std=gnu++1y" }
|
||||||
|
|
||||||
|
// PR c++/58637
|
||||||
|
|
||||||
|
template<> void foo(auto); // { dg-error "auto|not a template" }
|
||||||
|
|
22
gcc/tree.c
22
gcc/tree.c
|
@ -1864,6 +1864,28 @@ make_tree_vec_stat (int len MEM_STAT_DECL)
|
||||||
|
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Grow a TREE_VEC node to new length LEN. */
|
||||||
|
|
||||||
|
tree
|
||||||
|
grow_tree_vec_stat (tree v, int len MEM_STAT_DECL)
|
||||||
|
{
|
||||||
|
gcc_assert (TREE_CODE (v) == TREE_VEC);
|
||||||
|
|
||||||
|
int oldlen = TREE_VEC_LENGTH (v);
|
||||||
|
gcc_assert (len > oldlen);
|
||||||
|
|
||||||
|
int oldlength = (oldlen - 1) * sizeof (tree) + sizeof (struct tree_vec);
|
||||||
|
int length = (len - 1) * sizeof (tree) + sizeof (struct tree_vec);
|
||||||
|
|
||||||
|
record_node_allocation_statistics (TREE_VEC, length - oldlength);
|
||||||
|
|
||||||
|
v = (tree) ggc_realloc_stat (v, length PASS_MEM_STAT);
|
||||||
|
|
||||||
|
TREE_VEC_LENGTH (v) = len;
|
||||||
|
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
/* Return 1 if EXPR is the integer constant zero or a complex constant
|
/* Return 1 if EXPR is the integer constant zero or a complex constant
|
||||||
of zero. */
|
of zero. */
|
||||||
|
|
|
@ -3430,6 +3430,11 @@ extern tree make_tree_binfo_stat (unsigned MEM_STAT_DECL);
|
||||||
extern tree make_tree_vec_stat (int MEM_STAT_DECL);
|
extern tree make_tree_vec_stat (int MEM_STAT_DECL);
|
||||||
#define make_tree_vec(t) make_tree_vec_stat (t MEM_STAT_INFO)
|
#define make_tree_vec(t) make_tree_vec_stat (t MEM_STAT_INFO)
|
||||||
|
|
||||||
|
/* Grow a TREE_VEC. */
|
||||||
|
|
||||||
|
extern tree grow_tree_vec_stat (tree v, int MEM_STAT_DECL);
|
||||||
|
#define grow_tree_vec(v, t) grow_tree_vec_stat (v, t MEM_STAT_INFO)
|
||||||
|
|
||||||
/* Return the (unique) IDENTIFIER_NODE node for a given name.
|
/* Return the (unique) IDENTIFIER_NODE node for a given name.
|
||||||
The name is supplied as a char *. */
|
The name is supplied as a char *. */
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue