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 &>);

Reply via email to