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