From: Marek Polacek Date: Wed, 11 Feb 2026 20:58:46 +0000 (-0500) Subject: c++: missing type-only context [PR124045] X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=4b12cc841f32903c0d53dd973d703f0722b23cf3;p=thirdparty%2Fgcc.git c++: missing type-only context [PR124045] [temp.res.general]/4.4.1 says that a decl-specifier of the decl-specifier-seq of a simple-declaration in namespace scope is a type-only context. I think this goes back to P0634R3. So [: ^^int :] a = 42; shouldn't require a 'typename' when in a namespace scope. The _diagnose_invalid_type_name change is so that we don't emit extra error: '' in '...' does not name a type in concepts-return-req4.C, variadic74.C, and variadic-nested3.C. PR c++/124045 gcc/cp/ChangeLog: * parser.cc (cp_parser_parse_and_diagnose_invalid_type_name): Also abort the tentative parse when id is error_mark_node. (cp_parser_simple_declaration): Set CP_PARSER_FLAGS_TYPENAME_OPTIONAL when in a namespace scope. (cp_parser_single_declaration): Use cp_parser_flags instead of int. gcc/testsuite/ChangeLog: * g++.dg/reflect/type1.C: Don't expect an error for a missing typename in a namespace scope. Reviewed-by: Patrick Palka Reviewed-by: Jason Merrill --- diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc index 8c46b260fff..0f53ff90215 100644 --- a/gcc/cp/parser.cc +++ b/gcc/cp/parser.cc @@ -4171,7 +4171,8 @@ cp_parser_parse_and_diagnose_invalid_type_name (cp_parser *parser) /* If the next token is a (, this is a function with no explicit return type, i.e. constructor, destructor or conversion op. */ if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN) - || TREE_CODE (id) == TYPE_DECL) + || TREE_CODE (id) == TYPE_DECL + || id == error_mark_node) { cp_parser_abort_tentative_parse (parser); return false; @@ -17924,9 +17925,12 @@ cp_parser_simple_declaration (cp_parser* parser, omitted only when declaring a class or enumeration, that is when the decl-specifier-seq contains either a class-specifier, an elaborated-type-specifier, or an enum-specifier. */ - cp_parser_decl_specifier_seq (parser, - CP_PARSER_FLAGS_OPTIONAL, - &decl_specifiers, + cp_parser_flags flags = CP_PARSER_FLAGS_OPTIONAL; + /* [temp.res.general]/4.4.1: a decl-specifier of the decl-specifier-seq + of a simple-declaration in namespace scope is a type-only context. */ + if (at_namespace_scope_p ()) + flags |= CP_PARSER_FLAGS_TYPENAME_OPTIONAL; + cp_parser_decl_specifier_seq (parser, flags, &decl_specifiers, &declares_class_or_enum); /* We no longer need to defer access checks. */ stop_deferring_access_checks (); @@ -36481,7 +36485,7 @@ cp_parser_single_declaration (cp_parser* parser, && (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON) || decl_specifiers.type != error_mark_node)) { - int flags = CP_PARSER_FLAGS_TYPENAME_OPTIONAL; + cp_parser_flags flags = CP_PARSER_FLAGS_TYPENAME_OPTIONAL; /* FIXME: Delay parsing for all template friends, not just class template scope ones (PR114764). */ if (member_p && (!(friend_p && *friend_p) diff --git a/gcc/testsuite/g++.dg/reflect/type1.C b/gcc/testsuite/g++.dg/reflect/type1.C index 74bc27282b3..bcdb9d6c122 100644 --- a/gcc/testsuite/g++.dg/reflect/type1.C +++ b/gcc/testsuite/g++.dg/reflect/type1.C @@ -21,11 +21,11 @@ constexpr info g7 = ^^T; constexpr info g8 = ^^decltype(^^int); constexpr info g9 = ^^void() const & noexcept; -[: g1 :] u1; // { dg-error "expected unqualified-id" } +[: g1 :] u1; typename [: g1 :] u2; namespace N { - [: g1 :] nu1; // { dg-error "expected unqualified-id" } + [: g1 :] nu1; typename [: g1 :] nu2; }