Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk/16?

-- >8 --
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 adding a new function that handles reference collapsing
correctly.

        PR c++/125939

gcc/cp/ChangeLog:

        * cp-tree.h (build_stub_type): Remove declaration.
        (build_const_lref): Declare.
        * method.cc (build_stub_type): Make static.
        * reflect.cc (build_const_lref): New.
        (get_range_elts): Use it.
        (eval_is_copy_constructible_type): Likewise.
        (eval_is_copy_assignable_type): Likewise.
        (eval_is_trivially_copy_assignable_type): Likewise.
        (eval_is_nothrow_copy_constructible_type): Likewise.
        (eval_is_nothrow_copy_assignable_type): Likewise.
        * tree.cc (trivially_copy_constructible_p): Likewise.
        (handle_annotation_attribute): Likewise.

gcc/testsuite/ChangeLog:

        * g++.dg/reflect/type_trait15.C: New test.
---
 gcc/cp/cp-tree.h                            |   2 +-
 gcc/cp/method.cc                            |   2 +-
 gcc/cp/reflect.cc                           |  32 ++---
 gcc/cp/tree.cc                              |   7 +-
 gcc/testsuite/g++.dg/reflect/type_trait15.C | 133 ++++++++++++++++++++
 5 files changed, 155 insertions(+), 21 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/reflect/type_trait15.C

diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 132139f9d52..b594a51a028 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -8006,7 +8006,6 @@ extern tree get_copy_ctor                 (tree, 
tsubst_flags_t);
 extern tree get_copy_assign                    (tree);
 extern tree get_default_ctor                   (tree);
 extern tree get_dtor                           (tree, tsubst_flags_t);
-extern tree build_stub_type                    (tree, int, bool);
 extern tree build_stub_object                  (tree);
 extern bool is_stub_object                     (tree);
 extern tree build_invoke                       (tree, const_tree,
@@ -9530,6 +9529,7 @@ extern void coro_set_ramp_function                (tree, 
tree);
 
 /* In reflect.cc */
 extern void init_reflection ();
+WARN_UNUSED_RESULT extern tree build_const_lref (tree);
 extern tree maybe_update_function_parm (tree);
 extern bool metafunction_p (tree) ATTRIBUTE_PURE;
 extern tree direct_base_derived (tree) ATTRIBUTE_PURE;
diff --git a/gcc/cp/method.cc b/gcc/cp/method.cc
index c511ea9a064..b710148a7b2 100644
--- a/gcc/cp/method.cc
+++ b/gcc/cp/method.cc
@@ -1899,7 +1899,7 @@ maybe_synthesize_method (tree fndecl)
 /* Build a reference to type TYPE with cv-quals QUALS, which is an
    rvalue if RVALUE is true.  */
 
-tree
+static tree
 build_stub_type (tree type, int quals, bool rvalue)
 {
   tree argtype = cp_build_qualified_type (type, quals);
diff --git a/gcc/cp/reflect.cc b/gcc/cp/reflect.cc
index bf1c41772d3..dd3dc1307d1 100644
--- a/gcc/cp/reflect.cc
+++ b/gcc/cp/reflect.cc
@@ -324,6 +324,18 @@ maybe_update_function_parm (tree parm)
   return ret;
 }
 
+/* Build up const T &.  */
+
+tree
+build_const_lref (tree t)
+{
+  /* Reference collapsing.  If we get int&/int&&, we want to return int&.  */
+  if (TYPE_REF_P (t))
+    return cp_build_reference_type (TREE_TYPE (t), /*rval=*/false);
+  t = cp_build_qualified_type (t, cp_type_quals (t) | TYPE_QUAL_CONST);
+  return cp_build_reference_type (t, /*rval=*/false);
+}
+
 /* Return true if DECL comes from std::meta.  */
 
 static bool
@@ -587,10 +599,7 @@ get_range_elts (location_t loc, const constexpr_ctx *ctx, 
tree call, int n,
              *non_constant_p = true;
              return NULL_TREE;
            }
-         TREE_VEC_ELT (args, 0)
-           = build_stub_type (valuete,
-                              cp_type_quals (valuete) | TYPE_QUAL_CONST,
-                              false);
+         TREE_VEC_ELT (args, 0) = build_const_lref (valuete);
          if (!is_xible (INIT_EXPR, valuete, args))
            {
              if (!cxx_constexpr_quiet_p (ctx))
@@ -4570,8 +4579,7 @@ static tree
 eval_is_copy_constructible_type (tree type)
 {
   tree arg = make_tree_vec (1);
-  TREE_VEC_ELT (arg, 0)
-    = build_stub_type (type, cp_type_quals (type) | TYPE_QUAL_CONST, false);
+  TREE_VEC_ELT (arg, 0) = build_const_lref (type);
   if (is_xible (INIT_EXPR, type, arg))
     return boolean_true_node;
   else
@@ -4605,8 +4613,7 @@ static tree
 eval_is_copy_assignable_type (tree type)
 {
   tree type1 = cp_build_reference_type (type, /*rval=*/false);
-  tree type2 = build_stub_type (type, cp_type_quals (type) | TYPE_QUAL_CONST,
-                               false);
+  tree type2 = build_const_lref (type);
   if (is_xible (MODIFY_EXPR, type1, type2))
     return boolean_true_node;
   else
@@ -4694,8 +4701,7 @@ static tree
 eval_is_trivially_copy_assignable_type (tree type)
 {
   tree type1 = cp_build_reference_type (type, /*rval=*/false);
-  tree type2 = build_stub_type (type, cp_type_quals (type) | TYPE_QUAL_CONST,
-                               false);
+  tree type2 = build_const_lref (type);
   if (is_trivially_xible (MODIFY_EXPR, type1, type2))
     return boolean_true_node;
   else
@@ -4751,8 +4757,7 @@ static tree
 eval_is_nothrow_copy_constructible_type (tree type)
 {
   tree arg = make_tree_vec (1);
-  TREE_VEC_ELT (arg, 0)
-    = build_stub_type (type, cp_type_quals (type) | TYPE_QUAL_CONST, false);
+  TREE_VEC_ELT (arg, 0) = build_const_lref (type);
   if (is_nothrow_xible (INIT_EXPR, type, arg))
     return boolean_true_node;
   else
@@ -4786,8 +4791,7 @@ static tree
 eval_is_nothrow_copy_assignable_type (tree type)
 {
   tree type1 = cp_build_reference_type (type, /*rval=*/false);
-  tree type2 = build_stub_type (type, cp_type_quals (type) | TYPE_QUAL_CONST,
-                               false);
+  tree type2 = build_const_lref (type);
   if (is_nothrow_xible (MODIFY_EXPR, type1, type2))
     return boolean_true_node;
   else
diff --git a/gcc/cp/tree.cc b/gcc/cp/tree.cc
index d9a0583b8b8..dc885e47c01 100644
--- a/gcc/cp/tree.cc
+++ b/gcc/cp/tree.cc
@@ -4915,8 +4915,7 @@ bool
 trivially_copy_constructible_p (tree t)
 {
   tree arg = make_tree_vec (1);
-  TREE_VEC_ELT (arg, 0)
-    = build_stub_type (t, cp_type_quals (t) | TYPE_QUAL_CONST, false);
+  TREE_VEC_ELT (arg, 0) = build_const_lref (t);
   return is_trivially_xible (INIT_EXPR, t, arg);
 }
 
@@ -5982,9 +5981,7 @@ handle_annotation_attribute (tree *node, tree ARG_UNUSED 
(name),
     {
       tree arg = make_tree_vec (1);
       tree type = TREE_TYPE (TREE_VALUE (args));
-      TREE_VEC_ELT (arg, 0)
-       = build_stub_type (type, cp_type_quals (type) | TYPE_QUAL_CONST,
-                          /*rvalue=*/false);
+      TREE_VEC_ELT (arg, 0) = build_const_lref (type);
       if (!is_xible (INIT_EXPR, type, arg))
        {
          auto_diagnostic_group d;
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 00000000000..f0ce2e41e0b
--- /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 &>);

base-commit: bb26018080699913959526c89ce2e618c97768ec
-- 
2.54.0

Reply via email to