diff options
Diffstat (limited to 'gcc/cp/parser.c')
-rw-r--r-- | gcc/cp/parser.c | 46 |
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); |