+2019-01-31 Marek Polacek <polacek@redhat.com>
+
+ PR c++/89083, c++/80864 - ICE with list initialization in template.
+ * constexpr.c (adjust_temp_type): Use copy_node and change the type
+ instead of using build_constructor.
+ * decl.c (reshape_init_r): Don't reshape a digested initializer.
+ Return the initializer for COMPOUND_LITERAL_P.
+
2019-01-30 Jason Merrill <jason@redhat.com>
PR c++/88752 - ICE with lambda and constexpr if.
return temp;
/* Avoid wrapping an aggregate value in a NOP_EXPR. */
if (TREE_CODE (temp) == CONSTRUCTOR)
- return build_constructor (type, CONSTRUCTOR_ELTS (temp));
+ {
+ /* build_constructor wouldn't retain various CONSTRUCTOR flags. */
+ tree t = copy_node (temp);
+ TREE_TYPE (t) = type;
+ return t;
+ }
if (TREE_CODE (temp) == EMPTY_CLASS_EXPR)
return build0 (EMPTY_CLASS_EXPR, type);
gcc_assert (scalarish_type_p (type));
{
if (TREE_CODE (stripped_init) == CONSTRUCTOR)
{
- if (TREE_TYPE (init) && TYPE_PTRMEMFUNC_P (TREE_TYPE (init)))
- /* There is no need to reshape pointer-to-member function
- initializers, as they are always constructed correctly
- by the front end. */
- ;
- else if (COMPOUND_LITERAL_P (stripped_init))
+ tree init_type = TREE_TYPE (init);
+ if (init_type && TYPE_PTRMEMFUNC_P (init_type))
+ /* There is no need to call reshape_init for pointer-to-member
+ function initializers, as they are always constructed correctly
+ by the front end. Here we have e.g. {.__pfn=0B, .__delta=0},
+ which is missing outermost braces. We should warn below, and
+ one of the routines below will wrap it in additional { }. */;
/* For a nested compound literal, there is no need to reshape since
- brace elision is not allowed. Even if we decided to allow it,
- we should add a call to reshape_init in finish_compound_literal,
- before calling digest_init, so changing this code would still
- not be necessary. */
- gcc_assert (!BRACE_ENCLOSED_INITIALIZER_P (stripped_init));
+ we called reshape_init in finish_compound_literal, before calling
+ digest_init. */
+ else if (COMPOUND_LITERAL_P (stripped_init)
+ /* Similarly, a CONSTRUCTOR of the target's type is a
+ previously digested initializer. */
+ || same_type_ignoring_top_level_qualifiers_p (type,
+ init_type))
+ {
+ ++d->cur;
+ gcc_assert (!BRACE_ENCLOSED_INITIALIZER_P (stripped_init));
+ return init;
+ }
else
{
+ /* Something that hasn't been reshaped yet. */
++d->cur;
gcc_assert (BRACE_ENCLOSED_INITIALIZER_P (stripped_init));
return reshape_init (type, init, complain);
+2019-01-31 Marek Polacek <polacek@redhat.com>
+
+ PR c++/89083, c++/80864 - ICE with list initialization in template.
+ * g++.dg/cpp0x/initlist107.C: New test.
+ * g++.dg/cpp0x/initlist108.C: New test.
+ * g++.dg/cpp0x/initlist109.C: New test.
+ * g++.dg/cpp0x/initlist110.C: New test.
+ * g++.dg/cpp0x/initlist111.C: New test.
+ * g++.dg/cpp0x/initlist112.C: New test.
+ * g++.dg/init/ptrfn4.C: New test.
+
2019-01-31 David Malcolm <dmalcolm@redhat.com>
PR c/89122
--- /dev/null
+// PR c++/89083
+// { dg-do compile { target c++11 } }
+// { dg-options "-Wmissing-braces" }
+
+struct A { int x[3]; };
+
+template<class T>
+decltype(A{1, 2}, T()) fn1(T t) // { dg-warning "missing braces" }
+{
+ return t;
+}
+
+template<class T>
+decltype(A{{1, 2}}, T()) fn2(T t)
+{
+ return t;
+}
+
+void
+f()
+{
+ fn1(1);
+ fn2(1);
+}
--- /dev/null
+// PR c++/80864
+// { dg-do compile { target c++11 } }
+// { dg-options "-Wmissing-braces" }
+
+struct S {
+ char c[1];
+};
+
+template <typename T>
+void
+fn ()
+{
+ constexpr S s1 = S{};
+ constexpr S s2 = S{{}};
+ constexpr S s3 = S{{{}}};
+ constexpr S s4 = {};
+ constexpr S s5 = {{}};
+ constexpr S s6 = {{{}}};
+ constexpr S s7{{}};
+ constexpr S s8{S{}};
+ constexpr S s9{S{{}}};
+ constexpr S s10{S{{{}}}};
+ constexpr S s11 = S();
+ constexpr S s12 = S({});
+ constexpr S s13 = S({{}});
+ constexpr S s14 = {{}};
+ constexpr S s15 = {{{}}};
+}
+
+void
+foo ()
+{
+ fn<int>();
+}
--- /dev/null
+// PR c++/80864
+// { dg-do compile { target c++11 } }
+// { dg-options "-Wmissing-braces" }
+
+struct S {};
+struct A { S s[1]; };
+
+template <typename>
+struct R { static constexpr auto h = A{S{}}; }; // { dg-warning "missing braces" }
+
+template <typename>
+struct R2 { static constexpr auto h = A{{S{}}}; };
+
+A foo = R<int>::h;
+A foo2 = R2<int>::h;
--- /dev/null
+// PR c++/89083
+// { dg-do compile { target c++11 } }
+
+struct C { int a[3]; int i; };
+struct B { C c[3]; };
+struct A { B b[3]; };
+
+template<class T, int N>
+decltype(A{N, N}, T()) fn1(T t)
+{
+ return t;
+}
+
+template<class T, int N>
+decltype(A{{{N, N, N}, {N + 1}}}, T()) fn2(T t)
+{
+ return t;
+}
+
+template<class T, int N, int M>
+decltype(A{{N + M}}, T()) fn3(T t)
+{
+ return t;
+}
+
+void
+f()
+{
+ fn1<int, 10>(1);
+ fn2<int, 10>(1);
+ fn3<int, 10, 20>(1);
+}
--- /dev/null
+// PR c++/80864
+// { dg-do compile { target c++11 } }
+
+struct S {
+ int c[3];
+};
+
+template <typename T, int N>
+void
+fn ()
+{
+ constexpr S s1 = S{N};
+ constexpr S s2 = S{{N, N}};
+ constexpr S s3 = S{N, N};
+ constexpr S s4 = {N};
+ constexpr S s5 = {{N}};
+ constexpr S s6 = {N, N};
+ constexpr S s7{{N}};
+ constexpr S s8{S{N}};
+ constexpr S s9{S{{N}}};
+ constexpr S s10{S{{N}}};
+ constexpr S s11 = S({N});
+ constexpr S s12 = S({{N}});
+ constexpr S s13 = {{N}};
+ constexpr S s14 = {{N, N, N}};
+}
+
+void
+foo ()
+{
+ fn<int, 10>();
+}
--- /dev/null
+// PR c++/80864
+// { dg-do compile { target c++11 } }
+
+struct S {int a[2]; };
+struct A { S s[1]; };
+
+template <typename, int N>
+struct R { static constexpr auto h = A{S{N}}; };
+
+template <typename, int N>
+struct R2 { static constexpr auto h = A{S{{N, N}}}; };
+
+A foo = R<int, 10>::h;
+A foo2 = R2<int, 10>::h;
--- /dev/null
+// { dg-do compile }
+// { dg-options "-Wmissing-braces" }
+
+struct S { };
+typedef void (S::*fptr1) (int);
+
+struct A {
+ fptr1 f;
+};
+
+A a[] =
+{
+ (fptr1) 0,
+}; // { dg-warning "missing braces around initializer" }
+
+A a2[] =
+{
+ { (fptr1) 0 }
+};