constexpr. */
CP_PARSER_FLAGS_ONLY_TYPE_OR_CONSTEXPR = 0x8,
/* When parsing a decl-specifier-seq, only allow mutable or constexpr. */
- CP_PARSER_FLAGS_ONLY_MUTABLE_OR_CONSTEXPR = 0x10
+ CP_PARSER_FLAGS_ONLY_MUTABLE_OR_CONSTEXPR = 0x10,
+ /* When parsing a decl-specifier-seq, allow missing typename. */
+ CP_PARSER_FLAGS_TYPENAME_OPTIONAL = 0x20
};
/* This type is used for parameters and variables which hold
(cp_parser *, cp_decl_specifier_seq *, cp_parser_flags);
static tree cp_parser_type_name
(cp_parser *, bool);
-static tree cp_parser_type_name
- (cp_parser *);
static tree cp_parser_nonclass_name
(cp_parser* parser);
static tree cp_parser_elaborated_type_specifier
/* Declarators [gram.dcl.decl] */
static tree cp_parser_init_declarator
- (cp_parser *, cp_decl_specifier_seq *, vec<deferred_access_check, va_gc> *,
- bool, bool, int, bool *, tree *, location_t *, tree *);
+ (cp_parser *, cp_parser_flags, cp_decl_specifier_seq *,
+ vec<deferred_access_check, va_gc> *, bool, bool, int, bool *, tree *,
+ location_t *, tree *);
static cp_declarator *cp_parser_declarator
- (cp_parser *, cp_parser_declarator_kind, int *, bool *, bool, bool);
+ (cp_parser *, cp_parser_declarator_kind, cp_parser_flags, int *, bool *,
+ bool, bool);
static cp_declarator *cp_parser_direct_declarator
- (cp_parser *, cp_parser_declarator_kind, int *, bool, bool);
+ (cp_parser *, cp_parser_declarator_kind, cp_parser_flags, int *, bool, bool);
static enum tree_code cp_parser_ptr_operator
(cp_parser *, tree *, cp_cv_quals *, tree *);
static cp_cv_quals cp_parser_cv_qualifier_seq_opt
static tree cp_parser_declarator_id
(cp_parser *, bool);
static tree cp_parser_type_id
- (cp_parser *, location_t * = NULL);
+ (cp_parser *, cp_parser_flags = CP_PARSER_FLAGS_NONE, location_t * = NULL);
static tree cp_parser_template_type_arg
(cp_parser *);
static tree cp_parser_trailing_type_id (cp_parser *);
static tree cp_parser_type_id_1
- (cp_parser *, bool, bool, location_t *);
+ (cp_parser *, cp_parser_flags, bool, bool, location_t *);
static void cp_parser_type_specifier_seq
- (cp_parser *, bool, bool, cp_decl_specifier_seq *);
+ (cp_parser *, cp_parser_flags, bool, bool, cp_decl_specifier_seq *);
static tree cp_parser_parameter_declaration_clause
- (cp_parser *);
+ (cp_parser *, cp_parser_flags);
static tree cp_parser_parameter_declaration_list
- (cp_parser *);
+ (cp_parser *, cp_parser_flags);
static cp_parameter_declarator *cp_parser_parameter_declaration
- (cp_parser *, bool, bool *);
+ (cp_parser *, cp_parser_flags, bool, bool *);
static tree cp_parser_default_argument
(cp_parser *, bool);
static void cp_parser_function_body
/* Parse the type to which we are casting. */
saved_in_type_id_in_expr_p = parser->in_type_id_in_expr_p;
parser->in_type_id_in_expr_p = true;
- type = cp_parser_type_id (parser);
+ type = cp_parser_type_id (parser, CP_PARSER_FLAGS_TYPENAME_OPTIONAL,
+ NULL);
parser->in_type_id_in_expr_p = saved_in_type_id_in_expr_p;
/* Look for the closing `>'. */
cp_parser_require (parser, CPP_GREATER, RT_GREATER);
parser->type_definition_forbidden_message
= G_("types may not be defined in a new-type-id");
/* Parse the type-specifier-seq. */
- cp_parser_type_specifier_seq (parser, /*is_declaration=*/false,
+ cp_parser_type_specifier_seq (parser, CP_PARSER_FLAGS_TYPENAME_OPTIONAL,
+ /*is_declaration=*/false,
/*is_trailing_return=*/false,
&type_specifier_seq);
/* Restore the old message. */
begin_scope (sk_function_parms, /*entity=*/NULL_TREE);
/* Parse parameters. */
- param_list = cp_parser_parameter_declaration_clause (parser);
+ param_list
+ = cp_parser_parameter_declaration_clause
+ (parser, CP_PARSER_FLAGS_TYPENAME_OPTIONAL);
/* Default arguments shall not be specified in the
parameter-declaration-clause of a lambda-declarator. */
/* Parse the declarator. */
declarator = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED,
+ CP_PARSER_FLAGS_NONE,
/*ctor_dtor_or_conv_p=*/NULL,
/*parenthesized_p=*/NULL,
/*member_p=*/false,
saw_declarator = true;
/* Parse the init-declarator. */
- decl = cp_parser_init_declarator (parser, &decl_specifiers,
+ decl = cp_parser_init_declarator (parser,
+ CP_PARSER_FLAGS_NONE,
+ &decl_specifiers,
/*checks=*/NULL,
function_definition_allowed_p,
/*member_p=*/false,
= G_("types may not be defined in a conversion-type-id");
/* Parse the type-specifiers. */
- cp_parser_type_specifier_seq (parser, /*is_declaration=*/false,
+ cp_parser_type_specifier_seq (parser, CP_PARSER_FLAGS_NONE,
+ /*is_declaration=*/false,
/*is_trailing_return=*/false,
&type_specifiers);
/* Parse the default-argument. */
push_deferring_access_checks (dk_no_deferred);
- tree default_argument = cp_parser_type_id (parser);
+ tree default_argument = cp_parser_type_id (parser,
+ CP_PARSER_FLAGS_TYPENAME_OPTIONAL,
+ NULL);
pop_deferring_access_checks ();
if (flag_concepts && type_uses_auto (default_argument))
of the template parameter-list rather than a greater-than
operator. */
parameter_declarator
- = cp_parser_parameter_declaration (parser, /*template_parm_p=*/true,
+ = cp_parser_parameter_declaration (parser,
+ CP_PARSER_FLAGS_TYPENAME_OPTIONAL,
+ /*template_parm_p=*/true,
/*parenthesized_p=*/NULL);
if (!parameter_declarator)
/* Parse the declarator. */
declarator
= cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED,
+ CP_PARSER_FLAGS_NONE,
/*ctor_dtor_or_conv_p=*/NULL,
/*parenthesized_p=*/NULL,
/*member_p=*/false,
{
bool qualified_p;
bool global_p;
+ const bool typename_p = (cxx_dialect >= cxx2a
+ && (flags & CP_PARSER_FLAGS_TYPENAME_OPTIONAL));
/* Don't gobble tokens or issue error messages if this is an
optional type-specifier. */
luck. */
if (TREE_CODE (type) != TYPE_DECL)
{
- cp_parser_error (parser, "expected template-id for type");
- type = NULL_TREE;
+ /* ...unless we pretend we have seen 'typename'. */
+ if (typename_p)
+ type = cp_parser_make_typename_type (parser, type,
+ token->location);
+ else
+ {
+ cp_parser_error (parser, "expected template-id for type");
+ type = NULL_TREE;
+ }
}
}
/* Otherwise, look for a type-name. */
else
- type = cp_parser_type_name (parser);
+ type = cp_parser_type_name (parser, (qualified_p && typename_p));
+
/* Keep track of all name-lookups performed in class scopes. */
if (type
&& !global_p
Returns a TYPE_DECL for the type. */
-static tree
-cp_parser_type_name (cp_parser* parser)
-{
- return cp_parser_type_name (parser, /*typename_keyword_p=*/false);
-}
-
-/* See above. */
static tree
cp_parser_type_name (cp_parser* parser, bool typename_keyword_p)
{
cp_lexer_consume_token (parser->lexer);
/* Parse the type-specifier-seq. */
- cp_parser_type_specifier_seq (parser, /*is_declaration=*/false,
+ cp_parser_type_specifier_seq (parser, CP_PARSER_FLAGS_NONE,
+ /*is_declaration=*/false,
/*is_trailing_return=*/false,
&type_specifiers);
G_("types may not be defined in alias template declarations");
}
- type = cp_parser_type_id (parser, &type_location);
+ type = cp_parser_type_id (parser, CP_PARSER_FLAGS_TYPENAME_OPTIONAL,
+ &type_location);
/* Restore the error message if need be. */
if (parser->num_template_parameter_lists)
function-definition:
decl-specifier-seq [opt] declarator function-transaction-block
+ The parser flags FLAGS is used to control type-specifier parsing.
+
The DECL_SPECIFIERS apply to this declarator. Returns a
representation of the entity declared. If MEMBER_P is TRUE, then
this declarator appears in a class scope. The new DECL created by
static tree
cp_parser_init_declarator (cp_parser* parser,
+ cp_parser_flags flags,
cp_decl_specifier_seq *decl_specifiers,
vec<deferred_access_check, va_gc> *checks,
bool function_definition_allowed_p,
/* Parse the declarator. */
declarator
= cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED,
- &ctor_dtor_or_conv_p,
+ flags, &ctor_dtor_or_conv_p,
/*parenthesized_p=*/NULL,
member_p, friend_p);
/* Gather up the deferred checks. */
attributes [opt] ptr-operator abstract-declarator [opt]
attributes [opt] direct-abstract-declarator
+ The parser flags FLAGS is used to control type-specifier parsing.
+
If CTOR_DTOR_OR_CONV_P is not NULL, *CTOR_DTOR_OR_CONV_P is used to
detect constructors, destructors, deduction guides, or conversion operators.
It is set to -1 if the declarator is a name, and +1 if it is a
static cp_declarator *
cp_parser_declarator (cp_parser* parser,
cp_parser_declarator_kind dcl_kind,
+ cp_parser_flags flags,
int* ctor_dtor_or_conv_p,
bool* parenthesized_p,
bool member_p, bool friend_p)
/* Parse the dependent declarator. */
declarator = cp_parser_declarator (parser, dcl_kind,
+ CP_PARSER_FLAGS_NONE,
/*ctor_dtor_or_conv_p=*/NULL,
/*parenthesized_p=*/NULL,
/*member_p=*/false,
*parenthesized_p = cp_lexer_next_token_is (parser->lexer,
CPP_OPEN_PAREN);
declarator = cp_parser_direct_declarator (parser, dcl_kind,
- ctor_dtor_or_conv_p,
+ flags, ctor_dtor_or_conv_p,
member_p, friend_p);
}
we are parsing a direct-declarator. It is
CP_PARSER_DECLARATOR_EITHER, if we can accept either - in the case
of ambiguity we prefer an abstract declarator, as per
- [dcl.ambig.res]. CTOR_DTOR_OR_CONV_P, MEMBER_P, and FRIEND_P are
+ [dcl.ambig.res].
+ The parser flags FLAGS is used to control type-specifier parsing.
+ CTOR_DTOR_OR_CONV_P, MEMBER_P, and FRIEND_P are
as for cp_parser_declarator. */
static cp_declarator *
cp_parser_direct_declarator (cp_parser* parser,
cp_parser_declarator_kind dcl_kind,
+ cp_parser_flags flags,
int* ctor_dtor_or_conv_p,
bool member_p, bool friend_p)
{
begin_scope (sk_function_parms, NULL_TREE);
/* Parse the parameter-declaration-clause. */
- params = cp_parser_parameter_declaration_clause (parser);
+ params
+ = cp_parser_parameter_declaration_clause (parser, flags);
/* Consume the `)'. */
parens.require_close (parser);
saved_in_type_id_in_expr_p = parser->in_type_id_in_expr_p;
parser->in_type_id_in_expr_p = true;
declarator
- = cp_parser_declarator (parser, dcl_kind, ctor_dtor_or_conv_p,
+ = cp_parser_declarator (parser, dcl_kind, flags,
+ ctor_dtor_or_conv_p,
/*parenthesized_p=*/NULL,
member_p, friend_p);
parser->in_type_id_in_expr_p = saved_in_type_id_in_expr_p;
type-id:
type-specifier-seq abstract-declarator [opt]
+ The parser flags FLAGS is used to control type-specifier parsing.
+
+ If IS_TEMPLATE_ARG is true, we are parsing a template argument.
+
+ If IS_TRAILING_RETURN is true, we are in a trailing-return-type,
+ i.e. we've just seen "->".
+
Returns the TYPE specified. */
static tree
-cp_parser_type_id_1 (cp_parser* parser, bool is_template_arg,
- bool is_trailing_return, location_t * type_location)
+cp_parser_type_id_1 (cp_parser *parser, cp_parser_flags flags,
+ bool is_template_arg, bool is_trailing_return,
+ location_t *type_location)
{
cp_decl_specifier_seq type_specifier_seq;
cp_declarator *abstract_declarator;
/* Parse the type-specifier-seq. */
- cp_parser_type_specifier_seq (parser, /*is_declaration=*/false,
+ cp_parser_type_specifier_seq (parser, flags,
+ /*is_declaration=*/false,
is_trailing_return,
&type_specifier_seq);
if (type_location)
cp_parser_parse_tentatively (parser);
/* Look for the declarator. */
abstract_declarator
- = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_ABSTRACT, NULL,
+ = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_ABSTRACT,
+ CP_PARSER_FLAGS_NONE, NULL,
/*parenthesized_p=*/NULL,
/*member_p=*/false,
/*friend_p=*/false);
is_template_arg);
}
+/* Wrapper for cp_parser_type_id_1. */
+
static tree
-cp_parser_type_id (cp_parser *parser, location_t * type_location)
+cp_parser_type_id (cp_parser *parser, cp_parser_flags flags,
+ location_t *type_location)
{
- return cp_parser_type_id_1 (parser, false, false, type_location);
+ return cp_parser_type_id_1 (parser, flags, false, false, type_location);
}
+/* Wrapper for cp_parser_type_id_1. */
+
static tree
cp_parser_template_type_arg (cp_parser *parser)
{
const char *saved_message = parser->type_definition_forbidden_message;
parser->type_definition_forbidden_message
= G_("types may not be defined in template arguments");
- r = cp_parser_type_id_1 (parser, true, false, NULL);
+ r = cp_parser_type_id_1 (parser, CP_PARSER_FLAGS_NONE, true, false, NULL);
parser->type_definition_forbidden_message = saved_message;
if (cxx_dialect >= cxx14 && !flag_concepts && type_uses_auto (r))
{
return r;
}
+/* Wrapper for cp_parser_type_id_1. */
+
static tree
cp_parser_trailing_type_id (cp_parser *parser)
{
- return cp_parser_type_id_1 (parser, false, true, NULL);
+ return cp_parser_type_id_1 (parser, CP_PARSER_FLAGS_TYPENAME_OPTIONAL,
+ false, true, NULL);
}
/* Parse a type-specifier-seq.
type-specifier-seq:
attributes type-specifier-seq [opt]
+ The parser flags FLAGS is used to control type-specifier parsing.
+
If IS_DECLARATION is true, we are at the start of a "condition" or
exception-declaration, so we might be followed by a declarator-id.
static void
cp_parser_type_specifier_seq (cp_parser* parser,
+ cp_parser_flags flags,
bool is_declaration,
bool is_trailing_return,
cp_decl_specifier_seq *type_specifier_seq)
{
bool seen_type_specifier = false;
- cp_parser_flags flags = CP_PARSER_FLAGS_OPTIONAL;
cp_token *start_token = NULL;
/* Clear the TYPE_SPECIFIER_SEQ. */
clear_decl_specs (type_specifier_seq);
+ flags |= CP_PARSER_FLAGS_OPTIONAL;
/* In the context of a trailing return type, enum E { } is an
elaborated-type-specifier followed by a function-body, not an
enum-specifier. */
parameter-declaration-list [opt] ... [opt]
parameter-declaration-list , ...
+ The parser flags FLAGS is used to control type-specifier parsing.
+
Returns a representation for the parameter declarations. A return
value of NULL indicates a parameter-declaration-clause consisting
only of an ellipsis. */
static tree
-cp_parser_parameter_declaration_clause (cp_parser* parser)
+cp_parser_parameter_declaration_clause (cp_parser* parser,
+ cp_parser_flags flags)
{
tree parameters;
cp_token *token;
}
/* Parse the parameter-declaration-list. */
- parameters = cp_parser_parameter_declaration_list (parser);
+ parameters = cp_parser_parameter_declaration_list (parser, flags);
/* If a parse error occurred while parsing the
parameter-declaration-list, then the entire
parameter-declaration-clause is erroneous. */
parameter-declaration
parameter-declaration-list , parameter-declaration
+ The parser flags FLAGS is used to control type-specifier parsing.
+
Returns a representation of the parameter-declaration-list, as for
cp_parser_parameter_declaration_clause. However, the
`void_list_node' is never appended to the list. */
static tree
-cp_parser_parameter_declaration_list (cp_parser* parser)
+cp_parser_parameter_declaration_list (cp_parser* parser, cp_parser_flags flags)
{
tree parameters = NULL_TREE;
tree *tail = ¶meters;
/* Parse the parameter. */
parameter
- = cp_parser_parameter_declaration (parser,
+ = cp_parser_parameter_declaration (parser, flags,
/*template_parm_p=*/false,
&parenthesized_p);
decl-specifier-seq ... [opt] abstract-declarator [opt]
decl-specifier-seq abstract-declarator [opt] = assignment-expression
+ The parser flags FLAGS is used to control type-specifier parsing.
+
If TEMPLATE_PARM_P is TRUE, then this parameter-declaration
declares a template parameter. (In that case, a non-nested `>'
token encountered during the parsing of the assignment-expression
static cp_parameter_declarator *
cp_parser_parameter_declaration (cp_parser *parser,
+ cp_parser_flags flags,
bool template_parm_p,
bool *parenthesized_p)
{
/* Parse the declaration-specifiers. */
cp_token *decl_spec_token_start = cp_lexer_peek_token (parser->lexer);
cp_parser_decl_specifier_seq (parser,
- CP_PARSER_FLAGS_NONE,
+ flags,
&decl_specifiers,
&declares_class_or_enum);
declarator_token_start = token;
declarator = cp_parser_declarator (parser,
CP_PARSER_DECLARATOR_EITHER,
+ CP_PARSER_FLAGS_NONE,
/*ctor_dtor_or_conv_p=*/NULL,
parenthesized_p,
/*member_p=*/false,
/* Parse the decl-specifier-seq. */
decl_spec_token_start = cp_lexer_peek_token (parser->lexer);
cp_parser_decl_specifier_seq (parser,
- CP_PARSER_FLAGS_OPTIONAL,
+ (CP_PARSER_FLAGS_OPTIONAL
+ | CP_PARSER_FLAGS_TYPENAME_OPTIONAL),
&decl_specifiers,
&declares_class_or_enum);
/* Check for an invalid type-name. */
/* Parse the declarator. */
declarator
= cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED,
+ CP_PARSER_FLAGS_TYPENAME_OPTIONAL,
&ctor_dtor_or_conv_p,
/*parenthesized_p=*/NULL,
/*member_p=*/true,
= G_("types may not be defined in exception-declarations");
/* Parse the type-specifier-seq. */
- cp_parser_type_specifier_seq (parser, /*is_declaration=*/true,
+ cp_parser_type_specifier_seq (parser, CP_PARSER_FLAGS_NONE,
+ /*is_declaration=*/true,
/*is_trailing_return=*/false,
&type_specifiers);
/* If it's a `)', then there is no declarator. */
declarator = NULL;
else
declarator = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_EITHER,
+ CP_PARSER_FLAGS_NONE,
/*ctor_dtor_or_conv_p=*/NULL,
/*parenthesized_p=*/NULL,
/*member_p=*/false,
if (!parens.require_open (parser))
return error_mark_node;
- tree parms = cp_parser_parameter_declaration_clause (parser);
+ tree parms
+ = cp_parser_parameter_declaration_clause (parser, CP_PARSER_FLAGS_NONE);
if (!parens.require_close (parser))
return error_mark_node;
/*type_p=*/false,
/*is_declaration=*/false));
+ /* Resolve the TYPENAME_TYPE, because the call above didn't do it. */
+ if (nested_name_specifier
+ && TREE_CODE (nested_name_specifier) == TYPENAME_TYPE)
+ {
+ tree s = resolve_typename_type (nested_name_specifier,
+ /*only_current_p=*/false);
+ if (TREE_CODE (s) != TYPENAME_TYPE)
+ nested_name_specifier = s;
+ }
+
outside_class_specifier_p = (!at_class_scope_p ()
|| !TYPE_BEING_DEFINED (current_class_type)
|| friend_p);
alternative. */
decl_spec_token_start = cp_lexer_peek_token (parser->lexer);
cp_parser_decl_specifier_seq (parser,
- CP_PARSER_FLAGS_OPTIONAL,
+ (CP_PARSER_FLAGS_OPTIONAL
+ | CP_PARSER_FLAGS_TYPENAME_OPTIONAL),
&decl_specifiers,
&declares_class_or_enum);
if (friend_p)
|| decl_specifiers.type != error_mark_node))
{
decl = cp_parser_init_declarator (parser,
+ CP_PARSER_FLAGS_TYPENAME_OPTIONAL,
&decl_specifiers,
checks,
/*function_definition_allowed_p=*/true,
int ctor_dtor_or_conv_p;
cp_lexer_consume_token (parser->lexer);
cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED,
+ CP_PARSER_FLAGS_NONE,
&ctor_dtor_or_conv_p,
/*parenthesized_p=*/NULL,
/*member_p=*/true,
{
cp_lexer_consume_token (parser->lexer);
begin_scope (sk_function_parms, NULL_TREE);
- if (cp_parser_parameter_declaration_list (parser)
- == error_mark_node)
+ tree t = cp_parser_parameter_declaration_list
+ (parser, CP_PARSER_FLAGS_NONE);
+ if (t == error_mark_node)
error = true;
pop_bindings_and_leave_scope ();
}
}
/* TODO: parse attributes for tail parameters. */
- parmdecl = cp_parser_parameter_declaration (parser, false, NULL);
+ parmdecl = cp_parser_parameter_declaration (parser, CP_PARSER_FLAGS_NONE,
+ false, NULL);
parm = grokdeclarator (parmdecl->declarator,
&parmdecl->decl_specifiers,
PARM, /*initialized=*/0,
/* Parse the declarator. */
declarator
= cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED,
+ CP_PARSER_FLAGS_NONE,
&ctor_dtor_or_conv_p,
/*parenthesized_p=*/NULL,
/*member_p=*/false,
{
/* We have "@catch (NSException *exception)" or something
like that. Parse the parameter declaration. */
- parm = cp_parser_parameter_declaration (parser, false, NULL);
+ parm = cp_parser_parameter_declaration (parser, CP_PARSER_FLAGS_NONE,
+ false, NULL);
if (parm == NULL)
parameter_declaration = error_mark_node;
else
/* Parse the declarator. */
declarator = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED,
+ CP_PARSER_FLAGS_NONE,
NULL, NULL, false, false);
/* Look for attributes that apply to the ivar. */
cp_parser_condition, from whence the bulk of this is copied. */
cp_parser_parse_tentatively (parser);
- cp_parser_type_specifier_seq (parser, /*is_declaration=*/true,
+ cp_parser_type_specifier_seq (parser, CP_PARSER_FLAGS_NONE,
+ /*is_declaration=*/true,
/*is_trailing_return=*/false,
&type_specifiers);
if (cp_parser_parse_definitely (parser))
declarator = cp_parser_declarator (parser,
CP_PARSER_DECLARATOR_NAMED,
+ CP_PARSER_FLAGS_NONE,
/*ctor_dtor_or_conv_p=*/NULL,
/*parenthesized_p=*/NULL,
/*member_p=*/false,