location_t class_head_start_location = input_location;
/* Parse the attributes. */
+ /* Save tokens for some unhandled error (PR123609). */
+ cp_token_position attribute_error_position = 0;
+ if (!cp_parser_error_occurred (parser))
+ attribute_error_position = cp_lexer_token_position (parser->lexer, false);
attributes = cp_parser_attributes_opt (parser);
+ if (!cp_parser_error_occurred (parser))
+ attribute_error_position = 0;
/* If the next token is `::', that is invalid -- but sometimes
people do try to write:
/* At this point, we're going ahead with the class-specifier, even
if some other problem occurs. */
cp_parser_commit_to_tentative_parse (parser);
+ /* Some errors while parsing attributes are ignored due to tentative parsing,
+ redo parsing to reject it. */
+ if (attribute_error_position)
+ {
+ auto current_position = cp_lexer_token_position (parser->lexer, false);
+ cp_lexer_set_token_position (parser->lexer, attribute_error_position);
+ cp_parser_attributes_opt (parser);
+ cp_lexer_set_token_position (parser->lexer, current_position);
+ }
/* Issue the error about the overly-qualified name now. */
if (qualified_p)
{
{
struct [[nodiscard]] S1 {};
struct [[nodiscard ("foobar")]] S2 {};
- struct [[nodiscard (0)]] S3 {}; // { dg-error "'nodiscard' attribute argument must be a string constant" }
+ struct [[nodiscard (0)]] S3 {}; // { dg-error "'nodiscard' attribute argument must be a string constant|expected string-literal" }
struct [[nodiscard ("foo", "bar", "baz")]] S4 {}; // { dg-error "wrong number of arguments specified for 'nodiscard' attribute" }
- struct [[nodiscard (0, 1, 2)]] S5 {}; // { dg-error "wrong number of arguments specified for 'nodiscard' attribute" }
+ struct [[nodiscard (0, 1, 2)]] S5 {}; // { dg-error "wrong number of arguments specified for 'nodiscard' attribute|expected string-literal" }
auto a = [] [[nodiscard]] () {};
auto b = [] constexpr [[nodiscard]] {}; // { dg-warning "'nodiscard' attribute can only be applied to functions or to class or enumeration types" }