aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/parser.c110
-rw-r--r--gcc/testsuite/g++.dg/cpp23/lambda-specifiers1.C18
2 files changed, 93 insertions, 35 deletions
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 7077579..c52f90c 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -11223,12 +11223,12 @@ cp_parser_lambda_introducer (cp_parser* parser, tree lambda_expr)
/* Parse the (optional) middle of a lambda expression.
lambda-declarator:
- ( parameter-declaration-clause )
- decl-specifier-seq [opt]
- noexcept-specifier [opt]
- attribute-specifier-seq [opt]
- trailing-return-type [opt]
- requires-clause [opt]
+ ( parameter-declaration-clause ) lambda-specifiers requires-clause [opt]
+ lambda-specifiers (C++23)
+
+ lambda-specifiers:
+ decl-specifier-seq [opt] noexcept-specifier [opt]
+ attribute-specifier-seq [opt] trailing-return-type [opt]
LAMBDA_EXPR is the current representation of the lambda expression. */
@@ -11248,6 +11248,8 @@ cp_parser_lambda_declarator_opt (cp_parser* parser, tree lambda_expr)
tree tx_qual = NULL_TREE;
tree return_type = NULL_TREE;
tree trailing_requires_clause = NULL_TREE;
+ bool has_param_list = false;
+ location_t omitted_parms_loc = UNKNOWN_LOCATION;
cp_decl_specifier_seq lambda_specs;
clear_decl_specs (&lambda_specs);
/* A lambda op() is const unless explicitly 'mutable'. */
@@ -11334,42 +11336,80 @@ cp_parser_lambda_declarator_opt (cp_parser* parser, tree lambda_expr)
"default argument specified for lambda parameter");
parens.require_close (parser);
+ has_param_list = true;
+ }
+ else if (cxx_dialect < cxx23)
+ omitted_parms_loc = cp_lexer_peek_token (parser->lexer)->location;
- /* 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_next_tokens_can_be_gnu_attribute_p (parser))
- 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;
- quals = TYPE_UNQUALIFIED;
- if (lambda_specs.conflicting_specifiers_p)
- error_at (lambda_specs.locations[ds_storage_class],
- "duplicate %<mutable%>");
- }
+ /* 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_next_tokens_can_be_gnu_attribute_p (parser))
+ cp_parser_decl_specifier_seq (parser,
+ CP_PARSER_FLAGS_ONLY_MUTABLE_OR_CONSTEXPR,
+ &lambda_specs, &declares_class_or_enum);
- tx_qual = cp_parser_tx_qualifier_opt (parser);
+ if (omitted_parms_loc && lambda_specs.any_specifiers_p)
+ {
+ pedwarn (omitted_parms_loc, 0,
+ "parameter declaration before lambda declaration "
+ "specifiers only optional with %<-std=c++2b%> or "
+ "%<-std=gnu++2b%>");
+ omitted_parms_loc = UNKNOWN_LOCATION;
+ }
- /* Parse optional exception specification. */
- exception_spec
- = cp_parser_exception_specification_opt (parser, CP_PARSER_FLAGS_NONE);
+ if (lambda_specs.storage_class == sc_mutable)
+ {
+ LAMBDA_EXPR_MUTABLE_P (lambda_expr) = 1;
+ quals = TYPE_UNQUALIFIED;
+ if (lambda_specs.conflicting_specifiers_p)
+ error_at (lambda_specs.locations[ds_storage_class],
+ "duplicate %<mutable%>");
+ }
- std_attrs = cp_parser_std_attribute_spec_seq (parser);
+ tx_qual = cp_parser_tx_qualifier_opt (parser);
+ if (omitted_parms_loc && tx_qual)
+ {
+ pedwarn (omitted_parms_loc, 0,
+ "parameter declaration before lambda transaction "
+ "qualifier only optional with %<-std=c++2b%> or "
+ "%<-std=gnu++2b%>");
+ omitted_parms_loc = UNKNOWN_LOCATION;
+ }
- /* Parse optional trailing return type. */
- if (cp_lexer_next_token_is (parser->lexer, CPP_DEREF))
- {
- cp_lexer_consume_token (parser->lexer);
- return_type = cp_parser_trailing_type_id (parser);
- }
+ /* Parse optional exception specification. */
+ exception_spec
+ = cp_parser_exception_specification_opt (parser, CP_PARSER_FLAGS_NONE);
- if (cp_next_tokens_can_be_gnu_attribute_p (parser))
- gnu_attrs = cp_parser_gnu_attributes_opt (parser);
+ if (omitted_parms_loc && exception_spec)
+ {
+ pedwarn (omitted_parms_loc, 0,
+ "parameter declaration before lambda exception "
+ "specification only optional with %<-std=c++2b%> or "
+ "%<-std=gnu++2b%>");
+ omitted_parms_loc = UNKNOWN_LOCATION;
+ }
+ std_attrs = cp_parser_std_attribute_spec_seq (parser);
+
+ /* Parse optional trailing return type. */
+ if (cp_lexer_next_token_is (parser->lexer, CPP_DEREF))
+ {
+ if (omitted_parms_loc)
+ pedwarn (omitted_parms_loc, 0,
+ "parameter declaration before lambda trailing "
+ "return type only optional with %<-std=c++2b%> or "
+ "%<-std=gnu++2b%>");
+ cp_lexer_consume_token (parser->lexer);
+ return_type = cp_parser_trailing_type_id (parser);
+ }
+
+ if (cp_next_tokens_can_be_gnu_attribute_p (parser))
+ gnu_attrs = cp_parser_gnu_attributes_opt (parser);
+
+ if (has_param_list)
+ {
/* Parse optional trailing requires clause. */
trailing_requires_clause = cp_parser_requires_clause_opt (parser, false);
diff --git a/gcc/testsuite/g++.dg/cpp23/lambda-specifiers1.C b/gcc/testsuite/g++.dg/cpp23/lambda-specifiers1.C
new file mode 100644
index 0000000..6729a45
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp23/lambda-specifiers1.C
@@ -0,0 +1,18 @@
+// P1102R2 - Down with ()!
+// { dg-do compile { target c++11 } }
+// { dg-options "" }
+
+void
+foo ()
+{
+ auto a = [] mutable {}; // { dg-warning "parameter declaration before lambda declaration specifiers only optional with" "" { target c++20_down } }
+#if __cpp_constexpr >= 201603L
+ auto b = [] constexpr {}; // { dg-warning "parameter declaration before lambda declaration specifiers only optional with" "" { target { c++17 && c++20_down } } }
+#endif
+#if __cpp_consteval >= 201811L
+ auto c = [] consteval {}; // { dg-warning "parameter declaration before lambda declaration specifiers only optional with" "" { target c++20_only } }
+#endif
+ auto d = [] throw() {}; // { dg-warning "parameter declaration before lambda exception specification only optional with" "" { target c++20_down } }
+ auto e = [] noexcept {}; // { dg-warning "parameter declaration before lambda exception specification only optional with" "" { target c++20_down } }
+ auto f = [] -> int { return 0; }; // { dg-warning "parameter declaration before lambda trailing return type only optional with" "" { target c++20_down } }
+}