c++/reflection: bogus error with block-scope using [:ns:]::S [PR126654]
Commit Message
Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk/16?
-- >8 --
Here we emit error "'::' is not a class, namespace, or
enumeration" for
using [:ns:]::S; // where ns=^^::
which is clearly wrong. tsubst_stmt/DECL_EXPR has
scope = tsubst (scope, args, complain, in_decl);
if (!MAYBE_CLASS_TYPE_P (scope)
&& TREE_CODE (scope) != ENUMERAL_TYPE)
{
if (complain & tf_error)
error_at (DECL_SOURCE_LOCATION (decl), "%qT is not a "
"class, namespace, or enumeration", scope);
return error_mark_node;
}
but it never checked for a NAMESPACE_DECL. That was ok before P2996
which brought dependent namespaces but now we need to allow them.
As it so happens, I found another problem in this space, a failure
to propagate USING_DECL_TYPENAME_P (127707).
PR c++/126654
gcc/cp/ChangeLog:
* pt.cc (tsubst_stmt) <case DECL_EXPR>: If tsubst returns
error_mark_node, return error_mark_node. Allow NAMESPACE_DECL.
gcc/testsuite/ChangeLog:
* g++.dg/reflect/ns11.C: New test.
---
gcc/cp/pt.cc | 3 ++
gcc/testsuite/g++.dg/reflect/ns11.C | 70 +++++++++++++++++++++++++++++
2 files changed, 73 insertions(+)
create mode 100644 gcc/testsuite/g++.dg/reflect/ns11.C
base-commit: d27e275b54ca0eb44ad136bc9f0488b846355e19
Comments
On 10/2/26 11:19 PM, Marek Polacek wrote:
> Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk/16?
OK.
> -- >8 --
> Here we emit error "'::' is not a class, namespace, or
> enumeration" for
>
> using [:ns:]::S; // where ns=^^::
>
> which is clearly wrong. tsubst_stmt/DECL_EXPR has
>
> scope = tsubst (scope, args, complain, in_decl);
> if (!MAYBE_CLASS_TYPE_P (scope)
> && TREE_CODE (scope) != ENUMERAL_TYPE)
> {
> if (complain & tf_error)
> error_at (DECL_SOURCE_LOCATION (decl), "%qT is not a "
> "class, namespace, or enumeration", scope);
> return error_mark_node;
> }
>
> but it never checked for a NAMESPACE_DECL. That was ok before P2996
> which brought dependent namespaces but now we need to allow them.
>
> As it so happens, I found another problem in this space, a failure
> to propagate USING_DECL_TYPENAME_P (127707).
>
> PR c++/126654
>
> gcc/cp/ChangeLog:
>
> * pt.cc (tsubst_stmt) <case DECL_EXPR>: If tsubst returns
> error_mark_node, return error_mark_node. Allow NAMESPACE_DECL.
>
> gcc/testsuite/ChangeLog:
>
> * g++.dg/reflect/ns11.C: New test.
> ---
> gcc/cp/pt.cc | 3 ++
> gcc/testsuite/g++.dg/reflect/ns11.C | 70 +++++++++++++++++++++++++++++
> 2 files changed, 73 insertions(+)
> create mode 100644 gcc/testsuite/g++.dg/reflect/ns11.C
>
> diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
> index 6c8d0e2de71..2b68ceb0cd2 100644
> --- a/gcc/cp/pt.cc
> +++ b/gcc/cp/pt.cc
> @@ -19908,7 +19908,10 @@ tsubst_stmt (tree t, tree args, tsubst_flags_t complain, tree in_decl)
> if (DECL_DEPENDENT_P (decl))
> {
> scope = tsubst (scope, args, complain, in_decl);
> + if (scope == error_mark_node)
> + return error_mark_node;
> if (!MAYBE_CLASS_TYPE_P (scope)
> + && TREE_CODE (scope) != NAMESPACE_DECL
> && TREE_CODE (scope) != ENUMERAL_TYPE)
> {
> if (complain & tf_error)
> diff --git a/gcc/testsuite/g++.dg/reflect/ns11.C b/gcc/testsuite/g++.dg/reflect/ns11.C
> new file mode 100644
> index 00000000000..0bdd9131a1d
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/reflect/ns11.C
> @@ -0,0 +1,70 @@
> +// PR c++/126654
> +// { dg-do compile { target c++26 } }
> +// { dg-additional-options "-freflection" }
> +
> +int v;
> +
> +namespace N {
> + struct S {};
> + namespace M {
> + struct S {};
> + int v;
> + }
> + int v;
> +}
> +namespace A = N;
> +struct S {};
> +enum class E { S };
> +struct C { struct S {}; };
> +
> +template<auto ns>
> +void
> +f ()
> +{
> + using [:ns:]::S;
> + using [:ns:]::v;
> + v = 42;
> +}
> +
> +template<auto ns>
> +void
> +fe ()
> +{
> + using [:ns:]::S;
> + auto e = S;
> +}
> +
> +template<auto ns>
> +void
> +f2 ()
> +{
> + using [:ns:]::S; // { dg-error "expected a reflection of a class, namespace, or enumeration" }
> +// { dg-message "but .int. is a type" "" { target *-*-* } .-1 }
> +}
> +
> +template<auto ns>
> +void
> +f3 ()
> +{
> + using [:ns:]::S; // { dg-error "using-declaration for member at non-class scope" }
> +}
> +
> +template<typename T>
> +void
> +f4 ()
> +{
> + using T::x; // { dg-error "is not a class, namespace, or enumeration" }
> +}
> +
> +void
> +g ()
> +{
> + f<^^::>();
> + f<^^N>();
> + f<^^A>();
> + f<^^N::M>();
> + fe<^^E>();
> + f2<^^int>();
> + f3<^^C>();
> + f4<int>();
> +}
>
> base-commit: d27e275b54ca0eb44ad136bc9f0488b846355e19
@@ -19908,7 +19908,10 @@ tsubst_stmt (tree t, tree args, tsubst_flags_t complain, tree in_decl)
if (DECL_DEPENDENT_P (decl))
{
scope = tsubst (scope, args, complain, in_decl);
+ if (scope == error_mark_node)
+ return error_mark_node;
if (!MAYBE_CLASS_TYPE_P (scope)
+ && TREE_CODE (scope) != NAMESPACE_DECL
&& TREE_CODE (scope) != ENUMERAL_TYPE)
{
if (complain & tf_error)
new file mode 100644
@@ -0,0 +1,70 @@
+// PR c++/126654
+// { dg-do compile { target c++26 } }
+// { dg-additional-options "-freflection" }
+
+int v;
+
+namespace N {
+ struct S {};
+ namespace M {
+ struct S {};
+ int v;
+ }
+ int v;
+}
+namespace A = N;
+struct S {};
+enum class E { S };
+struct C { struct S {}; };
+
+template<auto ns>
+void
+f ()
+{
+ using [:ns:]::S;
+ using [:ns:]::v;
+ v = 42;
+}
+
+template<auto ns>
+void
+fe ()
+{
+ using [:ns:]::S;
+ auto e = S;
+}
+
+template<auto ns>
+void
+f2 ()
+{
+ using [:ns:]::S; // { dg-error "expected a reflection of a class, namespace, or enumeration" }
+// { dg-message "but .int. is a type" "" { target *-*-* } .-1 }
+}
+
+template<auto ns>
+void
+f3 ()
+{
+ using [:ns:]::S; // { dg-error "using-declaration for member at non-class scope" }
+}
+
+template<typename T>
+void
+f4 ()
+{
+ using T::x; // { dg-error "is not a class, namespace, or enumeration" }
+}
+
+void
+g ()
+{
+ f<^^::>();
+ f<^^N>();
+ f<^^A>();
+ f<^^N::M>();
+ fe<^^E>();
+ f2<^^int>();
+ f3<^^C>();
+ f4<int>();
+}