(cp_declarator *, tree);
static int omp_finish_variant_function
(cp_parser *, tree, tree, tree, bool, bool);
+static void maybe_start_implicit_template (cp_parser *parser);
/* Manifest constants. */
#define CP_LEXER_BUFFER_SIZE ((256 * 1024) / sizeof (cp_token))
if (templ == error_mark_node || is_identifier)
return templ;
+ /* If we see a concept name in a parameter-list, it's a type-constraint in an
+ abbreviated function template, so enter template scope before parsing the
+ template arguments. */
+ if (parser->auto_is_implicit_function_template_parm_p
+ && concept_definition_p (templ))
+ maybe_start_implicit_template (parser);
+
/* Since we're going to preserve any side-effects from this parse, set up a
firewall to protect our callers from cp_parser_commit_to_tentative_parse
in the template arguments. */
return get_identifier (buf);
}
-/* Add an implicit template type parameter to the CURRENT_TEMPLATE_PARMS
- (creating a new template parameter list if necessary). Returns the newly
- created template type parm. */
+/* We're declaring an abbreviated function template, make sure that
+ parser->implicit_template_scope is set. */
-static tree
-synthesize_implicit_template_parm (cp_parser *parser, tree constr)
+static void
+maybe_start_implicit_template (cp_parser *parser)
{
- /* A requires-clause is not a function and cannot have placeholders. */
- if (current_binding_level->requires_expression)
- {
- error ("placeholder type not allowed in this context");
- return error_mark_node;
- }
-
- gcc_assert (current_binding_level->kind == sk_function_parms);
-
- /* 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. */
-
- cp_binding_level *const entry_scope = current_binding_level;
-
- bool become_template = false;
- cp_binding_level *parent_scope = 0;
-
if (parser->implicit_template_scope)
- {
- gcc_assert (parser->implicit_template_parms);
-
- current_binding_level = parser->implicit_template_scope;
- }
+ return;
else
{
/* Roll back to the existing template parameter scope (in the case of
in the case of out-of-line member definitions). The function scope is
added back after template parameter synthesis below. */
+ cp_binding_level *const entry_scope = current_binding_level;
cp_binding_level *scope = entry_scope;
+ cp_binding_level *parent_scope = nullptr;
while (scope->kind == sk_function_parms)
{
/* Introduce a new template parameter list for implicit template
parameters. */
- become_template = true;
-
parser->implicit_template_scope
= begin_scope (sk_template_parms, NULL);
parser->fully_implicit_function_template_p = true;
++parser->num_template_parameter_lists;
+
+ parent_scope->level_chain = current_binding_level;
+
+ current_template_parms
+ = tree_cons (size_int (current_template_depth + 1),
+ make_tree_vec (0), current_template_parms);
}
else
{
parser->implicit_template_parms
= TREE_VEC_ELT (v, TREE_VEC_LENGTH (v) - 1);
}
+
+ current_binding_level = entry_scope;
}
+}
+
+/* Add an implicit template type parameter to the CURRENT_TEMPLATE_PARMS
+ (creating a new template parameter list if necessary). Returns the newly
+ created template type parm. */
+
+static tree
+synthesize_implicit_template_parm (cp_parser *parser, tree constr)
+{
+ /* A requires-clause is not a function and cannot have placeholders. */
+ if (current_binding_level->requires_expression)
+ {
+ error ("placeholder type not allowed in this context");
+ return error_mark_node;
+ }
+
+ gcc_assert (current_binding_level->kind == sk_function_parms);
+
+ /* 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. */
+
+ cp_binding_level *const entry_scope = current_binding_level;
+
+ maybe_start_implicit_template (parser);
+ current_binding_level = parser->implicit_template_scope;
/* Synthesize a new template parameter and track the current template
parameter chain with implicit_template_parms. */
gcc_assert(!proto || TREE_CODE (proto) == TYPE_DECL);
tree synth_tmpl_parm = finish_template_type_parm (class_type_node, synth_id);
- if (become_template)
- current_template_parms = tree_cons (size_int (current_template_depth + 1),
- NULL_TREE, current_template_parms);
-
/* Attach the constraint to the parm before processing. */
tree node = build_tree_list (NULL_TREE, synth_tmpl_parm);
TREE_TYPE (node) = constr;
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;
- TREE_VALUE (current_template_parms) = new_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 (new_parms, new_parm_idx + 1);
- TREE_VEC_ELT (new_parms, new_parm_idx) = parser->implicit_template_parms;
- }
+ tree& new_parms = INNERMOST_TEMPLATE_PARMS (current_template_parms);
+ int new_parm_idx = TREE_VEC_LENGTH (new_parms);
+ new_parms = grow_tree_vec (new_parms, new_parm_idx + 1);
+ TREE_VEC_ELT (new_parms, new_parm_idx) = parser->implicit_template_parms;
/* If the new parameter was constrained, we need to add that to the
constraints in the template parameter list. */