]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
c++/reflection: disallow reflecting block-scope externs (CWG 3065) [PR124756] master trunk
authorMarek Polacek <polacek@redhat.com>
Fri, 24 Apr 2026 21:30:43 +0000 (17:30 -0400)
committerMarek Polacek <polacek@redhat.com>
Tue, 28 Apr 2026 20:51:02 +0000 (16:51 -0400)
The proposed resolution of CWG 3065 suggests that reflection on a block-scope
extern declaration be ill-formed.  This patch makes it so, and it also
happens to fix a crash.

PR c++/124756

gcc/cp/ChangeLog:

* reflect.cc (get_reflection): Give an error when taking the
reflection of a block-scope extern.

gcc/testsuite/ChangeLog:

* g++.dg/reflect/identifier_of3.C: Add dg-error.
* g++.dg/reflect/pr123612.C: Likewise.
* g++.dg/reflect/error13.C: New test.

Reviewed-by: Jason Merrill <jason@redhat.com>
gcc/cp/reflect.cc
gcc/testsuite/g++.dg/reflect/error13.C [new file with mode: 0644]
gcc/testsuite/g++.dg/reflect/identifier_of3.C
gcc/testsuite/g++.dg/reflect/pr123612.C

index 27e1efee106b1d325d4ca0f19f386db858b25e69..6ef718e560fc3778c12b6bbf8ce4d93604acaf91 100644 (file)
@@ -238,9 +238,14 @@ get_reflection (location_t loc, tree t, reflect_kind kind/*=REFLECT_UNDEF*/)
        t = dtor;
     }
 
-  /* Look through block scope externs.  */
+  /* Block-scope externs are invalid here as per the proposed resolution
+     of CWG 3065.  */
   if (VAR_OR_FUNCTION_DECL_P (t) && DECL_LOCAL_DECL_P (t))
-    t = DECL_LOCAL_DECL_ALIAS (t);
+    {
+      error_at (loc, "cannot take the reflection of a block-scope extern %qE",
+               t);
+      return error_mark_node;
+    }
 
   if (t == error_mark_node)
     return error_mark_node;
diff --git a/gcc/testsuite/g++.dg/reflect/error13.C b/gcc/testsuite/g++.dg/reflect/error13.C
new file mode 100644 (file)
index 0000000..8d61b7f
--- /dev/null
@@ -0,0 +1,30 @@
+// PR c++/124756
+// { dg-do compile { target c++26 } }
+// { dg-additional-options "-freflection" }
+
+template<typename T>
+consteval void
+f0 ()
+{
+  void fun(T);
+  auto _ = ^^fun;  // { dg-error "cannot take the reflection of a block-scope extern .fun." }
+  extern int arr[3];
+  auto _ = ^^arr;  // { dg-error "cannot take the reflection of a block-scope extern .arr." }
+  extern int e;
+  auto _ = ^^e;  // { dg-error "cannot take the reflection of a block-scope extern .e." }
+}
+
+consteval {
+  f0<int>();
+}
+
+consteval void
+f1 ()
+{
+  void fun(int);
+  auto _ = ^^fun;  // { dg-error "cannot take the reflection of a block-scope extern .fun." }
+  extern int arr[3];
+  auto _ = ^^arr;  // { dg-error "cannot take the reflection of a block-scope extern .arr." }
+  extern int e;
+  auto _ = ^^e;  // { dg-error "cannot take the reflection of a block-scope extern .e." }
+}
index 5383de07dd24f6f51624ed8ab45a0101abf7ca2e..266b43471ae2f8ecb887fbb7ca86b07aaf721e83 100644 (file)
@@ -4,6 +4,7 @@
 // Test std::meta::identifier_of.
 
 #include <meta>
+using namespace std::meta;
 
 void foo (int, int x, int y, int z);
 
@@ -38,10 +39,10 @@ baz ()
   void foo (int w, int, int v, int z);
   int bar (int, int, int v, int z, int u);
   void qux (int, int x, int y, int z);
-  constexpr auto qux1 = parameters_of (^^qux)[0];
-  constexpr auto qux2 = parameters_of (^^qux)[1];
-  constexpr auto qux3 = parameters_of (^^qux)[2];
-  constexpr auto qux4 = parameters_of (^^qux)[3];
+  constexpr auto qux1 = parameters_of (^^qux)[0]; // { dg-error "cannot take the reflection of a block-scope extern .qux." }
+  constexpr auto qux2 = parameters_of (^^qux)[1]; // { dg-error "cannot take the reflection of a block-scope extern .qux." }
+  constexpr auto qux3 = parameters_of (^^qux)[2]; // { dg-error "cannot take the reflection of a block-scope extern .qux." }
+  constexpr auto qux4 = parameters_of (^^qux)[3]; // { dg-error "cannot take the reflection of a block-scope extern .qux." }
   static_assert (!has_identifier (qux1));
   static_assert (identifier_of (qux2) == std::string_view ("x"));
   static_assert (identifier_of (qux3) == std::string_view ("y"));
@@ -62,10 +63,10 @@ void
 fred ()
 {
   void qux (int w, int, int v, int z);
-  constexpr auto qux1 = parameters_of (^^qux)[0];
-  constexpr auto qux2 = parameters_of (^^qux)[1];
-  constexpr auto qux3 = parameters_of (^^qux)[2];
-  constexpr auto qux4 = parameters_of (^^qux)[3];
+  constexpr auto qux1 = parameters_of (^^qux)[0]; // { dg-error "cannot take the reflection of a block-scope extern .qux." }
+  constexpr auto qux2 = parameters_of (^^qux)[1]; // { dg-error "cannot take the reflection of a block-scope extern .qux." }
+  constexpr auto qux3 = parameters_of (^^qux)[2]; // { dg-error "cannot take the reflection of a block-scope extern .qux." }
+  constexpr auto qux4 = parameters_of (^^qux)[3]; // { dg-error "cannot take the reflection of a block-scope extern .qux." }
   static_assert (identifier_of (qux1) == std::string_view ("w"));
   static_assert (identifier_of (qux2) == std::string_view ("x"));
   static_assert (!has_identifier (qux3));
index 97da7bbdd0e3b9eeea11c3e88f74949825acdaa8..0dee4ed4f653b1dce2c66ce766cae7d7bc8fa605 100644 (file)
@@ -3,6 +3,7 @@
 // { dg-additional-options "-freflection" }
 
 #include <meta>
+using namespace std::meta;
 
 int a;
 extern int b;
@@ -12,14 +13,14 @@ consteval auto
 bar ()
 {
   extern int a;
-  return ^^a;
+  return ^^a;  // { dg-error "cannot take the reflection of a block-scope extern .a." }
 }
 
 consteval auto
 baz ()
 {
   extern int b;
-  return ^^b;
+  return ^^b;  // { dg-error "cannot take the reflection of a block-scope extern .b." }
 }
 
 consteval auto
@@ -30,10 +31,10 @@ qux ()
   static_assert (has_default_argument (parameters_of (^^foo)[2]));
   {
     extern int foo (int x, int y = 5, int z = 16);
-    static_assert (!has_default_argument (parameters_of (^^foo)[0]));
-    static_assert (has_default_argument (parameters_of (^^foo)[1]));
-    static_assert (has_default_argument (parameters_of (^^foo)[2]));
-    return ^^foo;
+    static_assert (!has_default_argument (parameters_of (^^foo)[0]));  // { dg-error "cannot take the reflection of a block-scope extern .foo." }
+    static_assert (has_default_argument (parameters_of (^^foo)[1]));  // { dg-error "cannot take the reflection of a block-scope extern .foo." }
+    static_assert (has_default_argument (parameters_of (^^foo)[2]));  // { dg-error "cannot take the reflection of a block-scope extern .foo." }
+    return ^^foo;  // { dg-error "cannot take the reflection of a block-scope extern .foo." }
   }
 }