]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
c++: missing type-only context [PR124045]
authorMarek Polacek <polacek@redhat.com>
Wed, 11 Feb 2026 20:58:46 +0000 (15:58 -0500)
committerMarek Polacek <polacek@redhat.com>
Thu, 12 Feb 2026 13:31:58 +0000 (08:31 -0500)
[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: '<expression 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 <ppalka@redhat.com>
Reviewed-by: Jason Merrill <jason@redhat.com>
gcc/cp/parser.cc
gcc/testsuite/g++.dg/reflect/type1.C

index 8c46b260fffd90ee9903d71aaee3cb0c611ab413..0f53ff902159829ccdea4fc525f40578c8efb68e 100644 (file)
@@ -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)
index 74bc27282b3bf19db893cfd2493a33349d471408..bcdb9d6c12257e00e1801b6fdb704350acaa9aaf 100644 (file)
@@ -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;
 }