aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/parser.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/cp/parser.c')
-rw-r--r--gcc/cp/parser.c46
1 files changed, 38 insertions, 8 deletions
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index cff735b..6db5e84 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -981,6 +981,7 @@ cp_keyword_starts_decl_specifier_p (enum rid keyword)
/* C++0x extensions. */
case RID_DECLTYPE:
case RID_UNDERLYING_TYPE:
+ case RID_CONSTEXPR:
return true;
default:
@@ -1800,7 +1801,9 @@ enum
CP_PARSER_FLAGS_NO_TYPE_DEFINITIONS = 0x4,
/* When parsing a decl-specifier-seq, only allow type-specifier or
constexpr. */
- CP_PARSER_FLAGS_ONLY_TYPE_OR_CONSTEXPR = 0x8
+ 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
};
/* This type is used for parameters and variables which hold
@@ -10035,7 +10038,7 @@ cp_parser_lambda_introducer (cp_parser* parser, tree lambda_expr)
< template-parameter-list [opt] >
( parameter-declaration-clause [opt] )
attribute-specifier [opt]
- mutable [opt]
+ decl-specifier-seq [opt]
exception-specification [opt]
lambda-return-type-clause [opt]
@@ -10054,6 +10057,8 @@ cp_parser_lambda_declarator_opt (cp_parser* parser, tree lambda_expr)
tree exception_spec = NULL_TREE;
tree template_param_list = NULL_TREE;
tree tx_qual = NULL_TREE;
+ cp_decl_specifier_seq lambda_specs;
+ clear_decl_specs (&lambda_specs);
/* The template-parameter-list is optional, but must begin with
an opening angle if present. */
@@ -10097,12 +10102,20 @@ cp_parser_lambda_declarator_opt (cp_parser* parser, tree lambda_expr)
attributes = cp_parser_attributes_opt (parser);
- /* Parse optional `mutable' keyword. */
- if (cp_lexer_next_token_is_keyword (parser->lexer, RID_MUTABLE))
- {
- cp_lexer_consume_token (parser->lexer);
- LAMBDA_EXPR_MUTABLE_P (lambda_expr) = 1;
- }
+ /* In the decl-specifier-seq of the lambda-declarator, each
+ decl-specifier shall either be mutable or constexpr. */
+ int declares_class_or_enum;
+ if (cp_lexer_next_token_is_decl_specifier_keyword (parser->lexer))
+ cp_parser_decl_specifier_seq (parser,
+ CP_PARSER_FLAGS_ONLY_MUTABLE_OR_CONSTEXPR,
+ &lambda_specs, &declares_class_or_enum);
+ if (lambda_specs.storage_class == sc_mutable)
+ {
+ LAMBDA_EXPR_MUTABLE_P (lambda_expr) = 1;
+ if (lambda_specs.conflicting_specifiers_p)
+ error_at (lambda_specs.locations[ds_storage_class],
+ "duplicate %<mutable%>");
+ }
tx_qual = cp_parser_tx_qualifier_opt (parser);
@@ -10143,6 +10156,16 @@ cp_parser_lambda_declarator_opt (cp_parser* parser, tree lambda_expr)
/* Maybe we will deduce the return type later. */
return_type_specs.type = make_auto ();
+ if (lambda_specs.locations[ds_constexpr])
+ {
+ if (cxx_dialect >= cxx1z)
+ return_type_specs.locations[ds_constexpr]
+ = lambda_specs.locations[ds_constexpr];
+ else
+ error_at (lambda_specs.locations[ds_constexpr], "%<constexpr%> "
+ "lambda only available with -std=c++1z or -std=gnu++1z");
+ }
+
p = obstack_alloc (&declarator_obstack, 0);
declarator = make_id_declarator (NULL_TREE, ansi_opname (CALL_EXPR),
@@ -12776,6 +12799,13 @@ cp_parser_decl_specifier_seq (cp_parser* parser,
&& token->keyword != RID_CONSTEXPR)
error ("decl-specifier invalid in condition");
+ if (found_decl_spec
+ && (flags & CP_PARSER_FLAGS_ONLY_MUTABLE_OR_CONSTEXPR)
+ && token->keyword != RID_MUTABLE
+ && token->keyword != RID_CONSTEXPR)
+ error_at (token->location, "%qD invalid in lambda",
+ ridpointers[token->keyword]);
+
if (ds != ds_last)
set_and_check_decl_spec_loc (decl_specs, ds, token);