mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-04-18 05:40:23 +08:00
c++: make __is_constructible work with paren-init of aggrs [PR94149]
In C++20 this is well-formed: using T = int[2]; T t(1, 2); which means that std::is_constructible_v<int[2], int, int> should be true. But constructible_expr immediately returned the error_mark_node when it saw a list with more than one element. To give accurate results in C++20, we have to try initializing the aggregate from a parenthesized list of values. To not repeat the same mistake as in c++/93790, if there's only one element, I'm trying {} only when () didn't succeed. is_constructible5.C verifies this. In paren-init24.C std::is_nothrow_constructible_v doesn't work due to error: invalid 'static_cast' from type 'int' to type 'int [1]' and error: functional cast to array type 'int [2]' This needs to be fixed in libstdc++. PR c++/94149 * method.c (constructible_expr): In C++20, try using parenthesized initialization of aggregates to determine the result of __is_constructible. * g++.dg/cpp2a/paren-init24.C: New test. * g++.dg/cpp2a/paren-init25.C: New test. * g++.dg/ext/is_constructible5.C: New test.
This commit is contained in:
parent
e26bd694c7
commit
62c25d7adb
@ -1,3 +1,10 @@
|
||||
2020-04-10 Marek Polacek <polacek@redhat.com>
|
||||
|
||||
PR c++/94149
|
||||
* method.c (constructible_expr): In C++20, try using parenthesized
|
||||
initialization of aggregates to determine the result of
|
||||
__is_constructible.
|
||||
|
||||
2020-04-10 Bin Cheng <bin.cheng@linux.alibaba.com>
|
||||
|
||||
* coroutines.cc (co_await_expander): Simplify.
|
||||
|
@ -1799,12 +1799,48 @@ constructible_expr (tree to, tree from)
|
||||
{
|
||||
if (from == NULL_TREE)
|
||||
return build_value_init (strip_array_types (to), tf_none);
|
||||
else if (TREE_CHAIN (from))
|
||||
return error_mark_node; // too many initializers
|
||||
from = build_stub_object (TREE_VALUE (from));
|
||||
const int len = list_length (from);
|
||||
if (len > 1)
|
||||
{
|
||||
if (cxx_dialect < cxx2a)
|
||||
/* Too many initializers. */
|
||||
return error_mark_node;
|
||||
|
||||
/* In C++20 this is well-formed:
|
||||
using T = int[2];
|
||||
T t(1, 2);
|
||||
which means that std::is_constructible_v<int[2], int, int>
|
||||
should be true. */
|
||||
vec<constructor_elt, va_gc> *v;
|
||||
vec_alloc (v, len);
|
||||
for (tree t = from; t; t = TREE_CHAIN (t))
|
||||
{
|
||||
tree stub = build_stub_object (TREE_VALUE (t));
|
||||
constructor_elt elt = { NULL_TREE, stub };
|
||||
v->quick_push (elt);
|
||||
}
|
||||
from = build_constructor (init_list_type_node, v);
|
||||
CONSTRUCTOR_IS_DIRECT_INIT (from) = true;
|
||||
CONSTRUCTOR_IS_PAREN_INIT (from) = true;
|
||||
}
|
||||
else
|
||||
from = build_stub_object (TREE_VALUE (from));
|
||||
expr = perform_direct_initialization_if_possible (to, from,
|
||||
/*cast*/false,
|
||||
tf_none);
|
||||
/* If t(e) didn't work, maybe t{e} will. */
|
||||
if (expr == NULL_TREE
|
||||
&& len == 1
|
||||
&& cxx_dialect >= cxx2a)
|
||||
{
|
||||
from = build_constructor_single (init_list_type_node, NULL_TREE,
|
||||
from);
|
||||
CONSTRUCTOR_IS_DIRECT_INIT (from) = true;
|
||||
CONSTRUCTOR_IS_PAREN_INIT (from) = true;
|
||||
expr = perform_direct_initialization_if_possible (to, from,
|
||||
/*cast*/false,
|
||||
tf_none);
|
||||
}
|
||||
}
|
||||
return expr;
|
||||
}
|
||||
|
@ -1,3 +1,10 @@
|
||||
2020-04-10 Marek Polacek <polacek@redhat.com>
|
||||
|
||||
PR c++/94149
|
||||
* g++.dg/cpp2a/paren-init24.C: New test.
|
||||
* g++.dg/cpp2a/paren-init25.C: New test.
|
||||
* g++.dg/ext/is_constructible5.C: New test.
|
||||
|
||||
2020-04-10 Fritz Reese <foreese@gcc.gnu.org>
|
||||
|
||||
* gfortran.dg/asynchronous_5.f03: Fix typo in testcase and add
|
||||
|
26
gcc/testsuite/g++.dg/cpp2a/paren-init24.C
Normal file
26
gcc/testsuite/g++.dg/cpp2a/paren-init24.C
Normal file
@ -0,0 +1,26 @@
|
||||
// PR c++/94149 - make __is_constructible work with paren-init of aggrs.
|
||||
// { dg-do compile { target c++2a } }
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
int main()
|
||||
{
|
||||
using T = int[1];
|
||||
T t(1);
|
||||
|
||||
static_assert(__is_constructible(T, int));
|
||||
static_assert(!__is_constructible(T, int, int));
|
||||
static_assert(std::is_constructible_v<T, int>);
|
||||
//FIXME: libstdc++ problem?
|
||||
//static_assert(std::is_nothrow_constructible_v<T, int>);
|
||||
|
||||
using T2 = int[2];
|
||||
T2 t2(1);
|
||||
T2 t3(1, 2);
|
||||
|
||||
static_assert(__is_constructible(T2, int));
|
||||
static_assert(__is_constructible(T2, int, int));
|
||||
static_assert(std::is_constructible_v<T2, int, int>);
|
||||
// FIXME libstdc++ problem?
|
||||
//static_assert(std::is_nothrow_constructible_v<T2, int, int>);
|
||||
}
|
25
gcc/testsuite/g++.dg/cpp2a/paren-init25.C
Normal file
25
gcc/testsuite/g++.dg/cpp2a/paren-init25.C
Normal file
@ -0,0 +1,25 @@
|
||||
// PR c++/94149 - make __is_constructible work with paren-init of aggrs.
|
||||
// { dg-do compile { target c++2a } }
|
||||
|
||||
struct nonaggr {
|
||||
nonaggr() {}
|
||||
int i;
|
||||
int j;
|
||||
};
|
||||
|
||||
struct aggr {
|
||||
int i;
|
||||
int j;
|
||||
};
|
||||
|
||||
static_assert(__is_constructible(aggr, int, int));
|
||||
static_assert(__is_constructible(aggr, int));
|
||||
static_assert(!__is_constructible(nonaggr, int, int));
|
||||
|
||||
using T = aggr[2];
|
||||
static_assert(__is_constructible(T, aggr));
|
||||
static_assert(__is_constructible(T, aggr, aggr));
|
||||
|
||||
using N = nonaggr[2];
|
||||
static_assert(__is_constructible(N, nonaggr));
|
||||
static_assert(__is_constructible(N, nonaggr, nonaggr));
|
16
gcc/testsuite/g++.dg/ext/is_constructible5.C
Normal file
16
gcc/testsuite/g++.dg/ext/is_constructible5.C
Normal file
@ -0,0 +1,16 @@
|
||||
// PR c++/94149 - make __is_constructible work with paren-init of aggrs.
|
||||
// { dg-do compile { target c++11 } }
|
||||
|
||||
struct S { };
|
||||
|
||||
struct W {
|
||||
S& r;
|
||||
W(S& r_) : r(r_) {}
|
||||
operator S&() { return r; }
|
||||
};
|
||||
|
||||
S s;
|
||||
W w(s);
|
||||
S& s2(w);
|
||||
|
||||
static_assert(__is_constructible(S&, W), "");
|
Loading…
x
Reference in New Issue
Block a user