https://gcc.gnu.org/g:269a933b80d3b5c716ef1fa83f4f938077dd5da8
commit r16-9165-g269a933b80d3b5c716ef1fa83f4f938077dd5da8 Author: Marek Polacek <[email protected]> Date: Wed Jun 24 13:35:14 2026 -0400 c++/reflection: type traits and reference collapsing [PR125939] This PR shows that some of our meta type traits don't work with references: we emit bogus error: 'const' qualifiers cannot be applied to 'int&' errors. The problem is that build_stub_type is trying to add const to a reference, which you can only do through a typedef, but here we don't have a typedef. Resolved by passing tf_ignore_bad_quals to cp_build_qualified_type. PR c++/125939 gcc/cp/ChangeLog: * method.cc (build_stub_type): Pass tf_ignore_bad_quals to cp_build_qualified_type. gcc/testsuite/ChangeLog: * g++.dg/reflect/type_trait15.C: New test. Reviewed-by: Jason Merrill <[email protected]> Diff: --- gcc/cp/method.cc | 4 +- gcc/testsuite/g++.dg/reflect/type_trait15.C | 133 ++++++++++++++++++++++++++++ 2 files changed, 136 insertions(+), 1 deletion(-) diff --git a/gcc/cp/method.cc b/gcc/cp/method.cc index fe26b5130ff2..6272ed3aa9b7 100644 --- a/gcc/cp/method.cc +++ b/gcc/cp/method.cc @@ -1902,7 +1902,9 @@ maybe_synthesize_method (tree fndecl) tree build_stub_type (tree type, int quals, bool rvalue) { - tree argtype = cp_build_qualified_type (type, quals); + tree argtype + = cp_build_qualified_type (type, quals, + tf_warning_or_error | tf_ignore_bad_quals); return cp_build_reference_type (argtype, rvalue); } diff --git a/gcc/testsuite/g++.dg/reflect/type_trait15.C b/gcc/testsuite/g++.dg/reflect/type_trait15.C new file mode 100644 index 000000000000..f0ce2e41e0b8 --- /dev/null +++ b/gcc/testsuite/g++.dg/reflect/type_trait15.C @@ -0,0 +1,133 @@ +// PR c++/125939 +// { dg-do compile { target c++26 } } +// { dg-additional-options "-freflection" } + +#include <meta> + +template<typename T> +constexpr bool cct = std::meta::is_copy_constructible_type(^^T); + +int main() { + using T = int&; + static_assert(std::meta::is_copy_constructible_type(^^T)); + static_assert(cct<int&>); +} + +static_assert (is_copy_constructible_type (^^int)); +static_assert (std::is_copy_constructible_v<int>); +static_assert (is_copy_constructible_type (^^const int)); +static_assert (std::is_copy_constructible_v<const int>); +static_assert (is_copy_constructible_type (^^int &)); +static_assert (std::is_copy_constructible_v<int &>); +static_assert (is_copy_constructible_type (^^const int &)); +static_assert (std::is_copy_constructible_v<const int &>); +static_assert (!is_copy_constructible_type (^^int &&)); +static_assert (!std::is_copy_constructible_v<int &&>); +static_assert (!is_copy_constructible_type (^^const int &&)); +static_assert (!std::is_copy_constructible_v<const int &&>); +static_assert (!is_copy_constructible_type (^^void)); +static_assert (!std::is_copy_constructible_v<void>); +static_assert (!is_copy_constructible_type (^^int() const &)); +static_assert (!std::is_copy_constructible_v<int() const &>); + +static_assert (is_trivially_copy_constructible_type (^^int)); +static_assert (std::is_trivially_copy_constructible_v<int>); +static_assert (is_trivially_copy_constructible_type (^^const int)); +static_assert (std::is_trivially_copy_constructible_v<const int>); +static_assert (is_trivially_copy_constructible_type (^^int &)); +static_assert (std::is_trivially_copy_constructible_v<int &>); +static_assert (is_trivially_copy_constructible_type (^^const int &)); +static_assert (std::is_trivially_copy_constructible_v<const int &>); +static_assert (!is_trivially_copy_constructible_type (^^int &&)); +static_assert (!std::is_trivially_copy_constructible_v<int &&>); +static_assert (!is_trivially_copy_constructible_type (^^const int &&)); +static_assert (!std::is_trivially_copy_constructible_v<const int &&>); +static_assert (!is_trivially_copy_constructible_type (^^void)); +static_assert (!std::is_trivially_copy_constructible_v<void>); +static_assert (!is_trivially_copy_constructible_type (^^int() const &)); +static_assert (!std::is_trivially_copy_constructible_v<int() const &>); + +static_assert (is_nothrow_copy_constructible_type (^^int)); +static_assert (std::is_nothrow_copy_constructible_v<int>); +static_assert (is_nothrow_copy_constructible_type (^^const int)); +static_assert (std::is_nothrow_copy_constructible_v<const int>); +static_assert (is_nothrow_copy_constructible_type (^^int &)); +static_assert (std::is_nothrow_copy_constructible_v<int &>); +static_assert (is_nothrow_copy_constructible_type (^^const int &)); +static_assert (std::is_nothrow_copy_constructible_v<const int &>); +static_assert (!is_nothrow_copy_constructible_type (^^int &&)); +static_assert (!std::is_nothrow_copy_constructible_v<int &&>); +static_assert (!is_nothrow_copy_constructible_type (^^const int &&)); +static_assert (!std::is_nothrow_copy_constructible_v<const int &&>); +static_assert (!is_nothrow_copy_constructible_type (^^void)); +static_assert (!std::is_nothrow_copy_constructible_v<void>); +static_assert (!is_nothrow_copy_constructible_type (^^int() const &)); +static_assert (!std::is_nothrow_copy_constructible_v<int() const &>); + +static_assert (!is_assignable_type (^^int, ^^int)); +static_assert (!std::is_assignable_v<int, int>); +static_assert (!is_assignable_type (^^const int, ^^int)); +static_assert (!std::is_assignable_v<const int, int>); +static_assert (is_assignable_type (^^int &, ^^int)); +static_assert (std::is_assignable_v<int &, int>); +static_assert (!is_assignable_type (^^const int &, ^^int)); +static_assert (!std::is_assignable_v<const int &, int>); +static_assert (!is_assignable_type (^^int &&, ^^int)); +static_assert (!std::is_assignable_v<int &&, int>); +static_assert (!is_assignable_type (^^const int &&, ^^int)); +static_assert (!std::is_assignable_v<const int &&, int>); +static_assert (!is_assignable_type (^^void, ^^int)); +static_assert (!std::is_assignable_v<void, int>); +static_assert (!is_assignable_type (^^int() const &, ^^int)); +static_assert (!std::is_assignable_v<int() const &, int>); + +static_assert (is_copy_assignable_type (^^int)); +static_assert (std::is_copy_assignable_v<int>); +static_assert (!is_copy_assignable_type (^^const int)); +static_assert (!std::is_copy_assignable_v<const int>); +static_assert (is_copy_assignable_type (^^int &)); +static_assert (std::is_copy_assignable_v<int &>); +static_assert (!is_copy_assignable_type (^^const int &)); +static_assert (!std::is_copy_assignable_v<const int &>); +static_assert (is_copy_assignable_type (^^int &&)); +static_assert (std::is_copy_assignable_v<int &&>); +static_assert (!is_copy_assignable_type (^^const int &&)); +static_assert (!std::is_copy_assignable_v<const int &&>); +static_assert (!is_copy_assignable_type (^^void)); +static_assert (!std::is_copy_assignable_v<void>); +static_assert (!is_copy_assignable_type (^^int() const &)); +static_assert (!std::is_copy_assignable_v<int() const &>); + +static_assert (is_trivially_copy_assignable_type (^^int)); +static_assert (std::is_trivially_copy_assignable_v<int>); +static_assert (!is_trivially_copy_assignable_type (^^const int)); +static_assert (!std::is_trivially_copy_assignable_v<const int>); +static_assert (is_trivially_copy_assignable_type (^^int &)); +static_assert (std::is_trivially_copy_assignable_v<int &>); +static_assert (!is_trivially_copy_assignable_type (^^const int &)); +static_assert (!std::is_trivially_copy_assignable_v<const int &>); +static_assert (is_trivially_copy_assignable_type (^^int &&)); +static_assert (std::is_trivially_copy_assignable_v<int &&>); +static_assert (!is_trivially_copy_assignable_type (^^const int &&)); +static_assert (!std::is_trivially_copy_assignable_v<const int &&>); +static_assert (!is_trivially_copy_assignable_type (^^void)); +static_assert (!std::is_trivially_copy_assignable_v<void>); +static_assert (!is_trivially_copy_assignable_type (^^int() const &)); +static_assert (!std::is_trivially_copy_assignable_v<int() const &>); + +static_assert (is_nothrow_copy_assignable_type (^^int)); +static_assert (std::is_nothrow_copy_assignable_v<int>); +static_assert (!is_nothrow_copy_assignable_type (^^const int)); +static_assert (!std::is_nothrow_copy_assignable_v<const int>); +static_assert (is_nothrow_copy_assignable_type (^^int &)); +static_assert (std::is_nothrow_copy_assignable_v<int &>); +static_assert (!is_nothrow_copy_assignable_type (^^const int &)); +static_assert (!std::is_nothrow_copy_assignable_v<const int &>); +static_assert (is_nothrow_copy_assignable_type (^^int &&)); +static_assert (std::is_nothrow_copy_assignable_v<int &&>); +static_assert (!is_nothrow_copy_assignable_type (^^const int &&)); +static_assert (!std::is_nothrow_copy_assignable_v<const int &&>); +static_assert (!is_nothrow_copy_assignable_type (^^void)); +static_assert (!std::is_nothrow_copy_assignable_v<void>); +static_assert (!is_nothrow_copy_assignable_type (^^int() const &)); +static_assert (!std::is_nothrow_copy_assignable_v<int() const &>);
