diff options
author | Jason Merrill <jason@redhat.com> | 2022-04-26 11:15:04 -0400 |
---|---|---|
committer | Jason Merrill <jason@redhat.com> | 2022-05-17 18:09:24 -0400 |
commit | 2b0c8377729a3c62a05897136666574ab939aaab (patch) | |
tree | 7e773340c84575e560cb9d78468a761c16866b08 /gcc | |
parent | 2c05a2d1a8e4697ea95d65c5da601aeae327e7a7 (diff) | |
download | gcc-2b0c8377729a3c62a05897136666574ab939aaab.zip gcc-2b0c8377729a3c62a05897136666574ab939aaab.tar.gz gcc-2b0c8377729a3c62a05897136666574ab939aaab.tar.bz2 |
c++: constexpr ref to array of array [PR102307]
The problem here is that first check_initializer calls
build_aggr_init_full_exprs, which does overload resolution, but then in the
case of failed constexpr throws away the result and does it again in
build_functional_cast. But in the first overload resolution,
reshape_init_array_1 decided to reuse the inner CONSTRUCTORs because
tf_error is set, so we know we're committed. But the second pass gets
confused by the CONSTRUCTORs with non-init-list types.
Fixed by avoiding a second pass: instead, pass the call from build_aggr_init
to build_cplus_new, which will turn it into a TARGET_EXPR. I don't bother
to change the object argument because it will be replaced later in
simplify_aggr_init_expr.
PR c++/102307
gcc/cp/ChangeLog:
* decl.cc (check_initializer): Use build_cplus_new in case of
constexpr failure.
gcc/testsuite/ChangeLog:
* g++.dg/cpp1z/constexpr-array2.C: New test.
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/cp/decl.cc | 17 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp1z/constexpr-array2.C | 12 |
2 files changed, 24 insertions, 5 deletions
diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc index 5654bc75..381259c 100644 --- a/gcc/cp/decl.cc +++ b/gcc/cp/decl.cc @@ -7413,12 +7413,19 @@ check_initializer (tree decl, tree init, int flags, vec<tree, va_gc> **cleanups) /* Declared constexpr or constinit, but no suitable initializer; massage init appropriately so we can pass it into store_init_value for the error. */ - if (CLASS_TYPE_P (type) - && (!init || TREE_CODE (init) == TREE_LIST)) + tree new_init = NULL_TREE; + if (!processing_template_decl + && TREE_CODE (init_code) == CALL_EXPR) + new_init = build_cplus_new (type, init_code, tf_none); + else if (CLASS_TYPE_P (type) + && (!init || TREE_CODE (init) == TREE_LIST)) + new_init = build_functional_cast (input_location, type, + init, tf_none); + if (new_init) { - init = build_functional_cast (input_location, type, - init, tf_none); - if (TREE_CODE (init) == TARGET_EXPR) + init = new_init; + if (TREE_CODE (init) == TARGET_EXPR + && !(flags & LOOKUP_ONLYCONVERTING)) TARGET_EXPR_DIRECT_INIT_P (init) = true; } init_code = NULL_TREE; diff --git a/gcc/testsuite/g++.dg/cpp1z/constexpr-array2.C b/gcc/testsuite/g++.dg/cpp1z/constexpr-array2.C new file mode 100644 index 0000000..c30e3f2 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1z/constexpr-array2.C @@ -0,0 +1,12 @@ +// PR c++/102307 +// { dg-do compile { target c++11 } } + +#include <array> +template <unsigned N, unsigned M> struct Matrix { + constexpr Matrix(double const (&arr)[N][M]); // { dg-warning "never defined" } + constexpr Matrix(std::array<std::array<double, M>, N> const &arr); +}; +int main() { + constexpr Matrix<2, 3> + mat {{ {1.0, 2.0, 3.0}, {4.0, 5.0, 6.0} }}; // { dg-error "before its definition" } +} |