From: Marek Polacek Date: Fri, 24 Apr 2026 21:30:43 +0000 (-0400) Subject: c++/reflection: disallow reflecting block-scope externs (CWG 3065) [PR124756] X-Git-Url: http://git.ipfire.org/gitweb/?a=commitdiff_plain;h=HEAD;p=thirdparty%2Fgcc.git 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 --- diff --git a/gcc/cp/reflect.cc b/gcc/cp/reflect.cc index 27e1efee106..6ef718e560f 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 00000000000..8d61b7f192c --- /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 +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(); +} + +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 5383de07dd2..266b43471ae 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 +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 97da7bbdd0e..0dee4ed4f65 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 +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." } } }