aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog8
-rw-r--r--gcc/cp/call.c61
-rw-r--r--gcc/cp/typeck2.c5
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-initlist11.C11
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-initlist11a.C10
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>(); }