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. * 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. From-SVN: r268428
This commit is contained in:
parent
1d4b4f4979
commit
b27f74e777
11 changed files with 215 additions and 12 deletions
|
@ -1,3 +1,11 @@
|
|||
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.
|
||||
|
|
|
@ -1291,7 +1291,12 @@ adjust_temp_type (tree type, tree temp)
|
|||
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));
|
||||
|
|
|
@ -6154,20 +6154,29 @@ reshape_init_r (tree type, reshape_iter *d, bool first_initializer_p,
|
|||
{
|
||||
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);
|
||||
|
|
|
@ -1,3 +1,14 @@
|
|||
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
|
||||
|
|
24
gcc/testsuite/g++.dg/cpp0x/initlist107.C
Normal file
24
gcc/testsuite/g++.dg/cpp0x/initlist107.C
Normal file
|
@ -0,0 +1,24 @@
|
|||
// 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);
|
||||
}
|
34
gcc/testsuite/g++.dg/cpp0x/initlist108.C
Normal file
34
gcc/testsuite/g++.dg/cpp0x/initlist108.C
Normal file
|
@ -0,0 +1,34 @@
|
|||
// 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>();
|
||||
}
|
15
gcc/testsuite/g++.dg/cpp0x/initlist109.C
Normal file
15
gcc/testsuite/g++.dg/cpp0x/initlist109.C
Normal file
|
@ -0,0 +1,15 @@
|
|||
// 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;
|
32
gcc/testsuite/g++.dg/cpp0x/initlist110.C
Normal file
32
gcc/testsuite/g++.dg/cpp0x/initlist110.C
Normal file
|
@ -0,0 +1,32 @@
|
|||
// 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);
|
||||
}
|
32
gcc/testsuite/g++.dg/cpp0x/initlist111.C
Normal file
32
gcc/testsuite/g++.dg/cpp0x/initlist111.C
Normal file
|
@ -0,0 +1,32 @@
|
|||
// 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>();
|
||||
}
|
14
gcc/testsuite/g++.dg/cpp0x/initlist112.C
Normal file
14
gcc/testsuite/g++.dg/cpp0x/initlist112.C
Normal file
|
@ -0,0 +1,14 @@
|
|||
// 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;
|
19
gcc/testsuite/g++.dg/init/ptrfn4.C
Normal file
19
gcc/testsuite/g++.dg/init/ptrfn4.C
Normal file
|
@ -0,0 +1,19 @@
|
|||
// { 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 }
|
||||
};
|
Loading…
Add table
Reference in a new issue