From 0727299846d3cfaa6c1f537019f9a9e583d07d8d Mon Sep 17 00:00:00 2001 From: Marek Polacek Date: Wed, 29 Apr 2026 17:24:19 -0400 Subject: [PATCH] c++/reflection: propagate cv-quals for SPLICE_SCOPE [PR125096] tsubst_splice_scope isn't propagating cv-quals from the template tree to the result, which means wrongly failed asserts in the new test due to a missing 'const'. So let's add the cv-quals like we do in so many other places in tsubst. PR c++/125096 gcc/cp/ChangeLog: * pt.cc (tsubst_splice_scope): Don't return early for dependent_splice_p. Propagate cv-qualifiers from the SPLICE_SCOPE to the result. * reflect.cc (valid_splice_scope_p): Accept SPLICE_SCOPE. gcc/testsuite/ChangeLog: * g++.dg/reflect/mangle4.C: Move dg-error. * g++.dg/reflect/dep16.C: New test. Reviewed-by: Jason Merrill --- gcc/cp/pt.cc | 8 ++++++-- gcc/cp/reflect.cc | 3 ++- gcc/testsuite/g++.dg/reflect/dep16.C | 28 ++++++++++++++++++++++++++ gcc/testsuite/g++.dg/reflect/mangle4.C | 5 ++--- 4 files changed, 38 insertions(+), 6 deletions(-) create mode 100644 gcc/testsuite/g++.dg/reflect/dep16.C diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc index 9a5eb7ef9b0..6992b5196fe 100644 --- a/gcc/cp/pt.cc +++ b/gcc/cp/pt.cc @@ -16904,8 +16904,8 @@ tsubst_splice_scope (tree t, tree args, tsubst_flags_t complain, tree in_decl) return r; const bool type_p = SPLICE_SCOPE_TYPE_P (t); if (dependent_splice_p (r)) - return make_splice_scope (r, type_p); - if (type_p && ctad_template_p (r)) + r = make_splice_scope (r, type_p); + else if (type_p && ctad_template_p (r)) r = make_template_placeholder (r); if (type_p ? !valid_splice_type_p (r) @@ -16925,6 +16925,10 @@ tsubst_splice_scope (tree t, tree args, tsubst_flags_t complain, tree in_decl) return error_mark_node; } + if (type_p) + r = cp_build_qualified_type (r, cp_type_quals (t) | cp_type_quals (r), + complain | tf_ignore_bad_quals); + return r; } diff --git a/gcc/cp/reflect.cc b/gcc/cp/reflect.cc index c6b0f6f2bd1..3b9f56ea548 100644 --- a/gcc/cp/reflect.cc +++ b/gcc/cp/reflect.cc @@ -8912,7 +8912,8 @@ valid_splice_scope_p (const_tree t) { return (CLASS_TYPE_P (t) || TREE_CODE (t) == ENUMERAL_TYPE - || TREE_CODE (t) == NAMESPACE_DECL); + || TREE_CODE (t) == NAMESPACE_DECL + || TREE_CODE (t) == SPLICE_SCOPE); } /* Return true if T is a valid result of the splice in a class member access, diff --git a/gcc/testsuite/g++.dg/reflect/dep16.C b/gcc/testsuite/g++.dg/reflect/dep16.C new file mode 100644 index 00000000000..70ec9bf4858 --- /dev/null +++ b/gcc/testsuite/g++.dg/reflect/dep16.C @@ -0,0 +1,28 @@ +// PR c++/125096 +// { dg-do compile { target c++26 } } +// { dg-additional-options "-freflection" } + +#include +#include + +namespace ctp { + template struct Reflect; + + namespace impl { + template using custom_target = Reflect::target_type; + } + + template + using target = [: is_scalar_type(^^T) ? ^^T : substitute(^^impl::custom_target, {^^T}) :]; + + template + struct Reflect> { + using underlying = target const; + using target_type = std::span>; + }; +} + +static_assert(dealias(^^ctp::target) == ^^int); +static_assert(dealias(^^ctp::target>) == ^^std::span); +static_assert(dealias(^^ctp::Reflect>::underlying) == ^^int const); +static_assert(dealias(^^ctp::Reflect>::target_type) == ^^std::span); diff --git a/gcc/testsuite/g++.dg/reflect/mangle4.C b/gcc/testsuite/g++.dg/reflect/mangle4.C index 3880468daff..f9ac44ba869 100644 --- a/gcc/testsuite/g++.dg/reflect/mangle4.C +++ b/gcc/testsuite/g++.dg/reflect/mangle4.C @@ -20,7 +20,6 @@ template } int main() { - // ??? It's not clear which of these should error. - std::default_accessor _ = std::iterator_accessor(); - std::default_accessor _ = std::iterator_accessor(); // { dg-error "conversion" } + std::default_accessor _ = std::iterator_accessor(); // { dg-error "conversion" } + std::default_accessor _ = std::iterator_accessor(); }