[gcc r17-164] c++/reflection: disallow reflecting block-scope externs (CWG 3065) [PR124756]

Marek Polacek mpolacek@gcc.gnu.org
Tue Apr 28 20:54:43 GMT 2026


https://gcc.gnu.org/g:c1977d101524d87642790422134fe170ce00b545

commit r17-164-gc1977d101524d87642790422134fe170ce00b545
Author: Marek Polacek <polacek@redhat.com>
Date:   Fri Apr 24 17:30:43 2026 -0400

    c++/reflection: disallow reflecting block-scope externs (CWG 3065) [PR124756]
    
    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>

Diff:
---
 gcc/cp/reflect.cc                             |  9 ++++++--
 gcc/testsuite/g++.dg/reflect/error13.C        | 30 +++++++++++++++++++++++++++
 gcc/testsuite/g++.dg/reflect/identifier_of3.C | 17 ++++++++-------
 gcc/testsuite/g++.dg/reflect/pr123612.C       | 13 ++++++------
 4 files changed, 53 insertions(+), 16 deletions(-)

diff --git a/gcc/cp/reflect.cc b/gcc/cp/reflect.cc
index 27e1efee106b..6ef718e560fc 100644
--- a/gcc/cp/reflect.cc
+++ b/gcc/cp/reflect.cc
@@ -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
index 000000000000..8d61b7f192ce
--- /dev/null
+++ b/gcc/testsuite/g++.dg/reflect/error13.C
@@ -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." }
+}
diff --git a/gcc/testsuite/g++.dg/reflect/identifier_of3.C b/gcc/testsuite/g++.dg/reflect/identifier_of3.C
index 5383de07dd24..266b43471ae2 100644
--- a/gcc/testsuite/g++.dg/reflect/identifier_of3.C
+++ b/gcc/testsuite/g++.dg/reflect/identifier_of3.C
@@ -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));
diff --git a/gcc/testsuite/g++.dg/reflect/pr123612.C b/gcc/testsuite/g++.dg/reflect/pr123612.C
index 97da7bbdd0e3..0dee4ed4f653 100644
--- a/gcc/testsuite/g++.dg/reflect/pr123612.C
+++ b/gcc/testsuite/g++.dg/reflect/pr123612.C
@@ -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." }
   }
 }


More information about the Gcc-cvs mailing list