diff options
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/cp/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/cp/call.c | 61 | ||||
-rw-r--r-- | gcc/cp/typeck2.c | 5 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/constexpr-initlist11.C | 11 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/constexpr-initlist11a.C | 10 |
5 files changed, 69 insertions, 26 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 5fe18cc..cb74761 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,11 @@ +2019-02-12 Jason Merrill <jason@redhat.com> + + PR c++/89144 - link error with constexpr initializer_list. + * call.c (convert_like_real) [ck_list]: Don't allocate a temporary + array for an empty list. + * typeck2.c (store_init_value): Don't use cxx_constant_init in a + template. + 2019-02-11 Jason Merrill <jason@redhat.com> PR c++/89241 - ICE with __func__ in lambda in template. diff --git a/gcc/cp/call.c b/gcc/cp/call.c index e9c131d..c53eb58 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -7085,34 +7085,42 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum, { /* Conversion to std::initializer_list<T>. */ tree elttype = TREE_VEC_ELT (CLASSTYPE_TI_ARGS (totype), 0); - tree new_ctor = build_constructor (init_list_type_node, NULL); unsigned len = CONSTRUCTOR_NELTS (expr); - tree array, val, field; - vec<constructor_elt, va_gc> *vec = NULL; - unsigned ix; + tree array; - /* Convert all the elements. */ - FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (expr), ix, val) + if (len) { - tree sub = convert_like_real (convs->u.list[ix], val, fn, argnum, - false, false, complain); - if (sub == error_mark_node) - return sub; - if (!BRACE_ENCLOSED_INITIALIZER_P (val) - && !check_narrowing (TREE_TYPE (sub), val, complain)) - return error_mark_node; - CONSTRUCTOR_APPEND_ELT (CONSTRUCTOR_ELTS (new_ctor), NULL_TREE, sub); - if (!TREE_CONSTANT (sub)) - TREE_CONSTANT (new_ctor) = false; + tree val; unsigned ix; + + tree new_ctor = build_constructor (init_list_type_node, NULL); + + /* Convert all the elements. */ + FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (expr), ix, val) + { + tree sub = convert_like_real (convs->u.list[ix], val, fn, + argnum, false, false, complain); + if (sub == error_mark_node) + return sub; + if (!BRACE_ENCLOSED_INITIALIZER_P (val) + && !check_narrowing (TREE_TYPE (sub), val, complain)) + return error_mark_node; + CONSTRUCTOR_APPEND_ELT (CONSTRUCTOR_ELTS (new_ctor), + NULL_TREE, sub); + if (!TREE_CONSTANT (sub)) + TREE_CONSTANT (new_ctor) = false; + } + /* Build up the array. */ + elttype = cp_build_qualified_type + (elttype, cp_type_quals (elttype) | TYPE_QUAL_CONST); + array = build_array_of_n_type (elttype, len); + array = finish_compound_literal (array, new_ctor, complain); + /* Take the address explicitly rather than via decay_conversion + to avoid the error about taking the address of a temporary. */ + array = cp_build_addr_expr (array, complain); } - /* Build up the array. */ - elttype = cp_build_qualified_type - (elttype, cp_type_quals (elttype) | TYPE_QUAL_CONST); - array = build_array_of_n_type (elttype, len); - array = finish_compound_literal (array, new_ctor, complain); - /* Take the address explicitly rather than via decay_conversion - to avoid the error about taking the address of a temporary. */ - array = cp_build_addr_expr (array, complain); + else + array = nullptr_node; + array = cp_convert (build_pointer_type (elttype), array, complain); if (array == error_mark_node) return error_mark_node; @@ -7123,11 +7131,12 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum, totype = complete_type_or_maybe_complain (totype, NULL_TREE, complain); if (!totype) return error_mark_node; - field = next_initializable_field (TYPE_FIELDS (totype)); + tree field = next_initializable_field (TYPE_FIELDS (totype)); + vec<constructor_elt, va_gc> *vec = NULL; CONSTRUCTOR_APPEND_ELT (vec, field, array); field = next_initializable_field (DECL_CHAIN (field)); CONSTRUCTOR_APPEND_ELT (vec, field, size_int (len)); - new_ctor = build_constructor (totype, vec); + tree new_ctor = build_constructor (totype, vec); return get_target_expr_sfinae (new_ctor, complain); } diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c index 05998a3..ac2c253 100644 --- a/gcc/cp/typeck2.c +++ b/gcc/cp/typeck2.c @@ -850,6 +850,11 @@ store_init_value (tree decl, tree init, vec<tree, va_gc>** cleanups, int flags) non-inline in-class-initialized static data member. */ if (!require_constant_expression (value)) value = error_mark_node; + else if (processing_template_decl) + /* In a template we might not have done the necessary + transformations to make value actually constant, + e.g. extend_ref_init_temps. */ + value = maybe_constant_init (value, decl, true); else value = cxx_constant_init (value, decl); } diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-initlist11.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-initlist11.C new file mode 100644 index 0000000..da5eab2 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-initlist11.C @@ -0,0 +1,11 @@ +// PR c++/89144 +// { dg-do link { target c++11 } } + +#include <initializer_list> + +template <class> void b() { + static constexpr std::initializer_list<int> c{ 42 }; + constexpr std::initializer_list<int> l { }; +} + +int main() { b<int>(); } diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-initlist11a.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-initlist11a.C new file mode 100644 index 0000000..2597c38 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-initlist11a.C @@ -0,0 +1,10 @@ +// PR c++/89144 +// { dg-do link { target c++11 } } + +#include <initializer_list> + +template <class> void b() { + constexpr std::initializer_list<int> l { 42 }; // { dg-error "" } +} + +int main() { b<int>(); } |