PR c++/90947 - Simple lookup table of array of strings is miscompiled
gcc/cp/ChangeLog: PR c++/90947 * decl.c (reshape_init_array_1): Avoid truncating initializer lists containing string literals. gcc/testsuite/ChangeLog: PR c++/90947 * c-c++-common/array-1.c: New test. * g++.dg/abi/mangle73.C: New test. * g++.dg/cpp2a/nontype-class23.C: New test. * g++.dg/init/array53.C: New test. gcc/ChangeLog: PR c++/90947 * tree.c (type_initializer_zero_p): Define. * tree.h (type_initializer_zero_p): New function. From-SVN: r273989
This commit is contained in:
parent
f3b4eae6c3
commit
b74f15a88e
10 changed files with 574 additions and 2 deletions
|
@ -1,3 +1,9 @@
|
|||
2019-08-01 Martin Sebor <msebor@redhat.com>
|
||||
|
||||
PR c++/90947
|
||||
* tree.c (type_initializer_zero_p): Define.
|
||||
* tree.h (type_initializer_zero_p): New function.
|
||||
|
||||
2019-08-01 Eric Botcazou <ebotcazou@adacore.com>
|
||||
|
||||
* cfgrtl.c (relink_block_chain): Add line returns in dump file.
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
2019-08-01 Martin Sebor <msebor@redhat.com>
|
||||
|
||||
PR c++/90947
|
||||
* decl.c (reshape_init_array_1): Avoid truncating initializer
|
||||
lists containing string literals.
|
||||
|
||||
2019-08-01 Marek Polacek <polacek@redhat.com>
|
||||
|
||||
PR c++/90805 - detect narrowing in case values.
|
||||
|
|
|
@ -5899,8 +5899,9 @@ reshape_init_array_1 (tree elt_type, tree max_index, reshape_iter *d,
|
|||
/* Pointers initialized to strings must be treated as non-zero
|
||||
even if the string is empty. */
|
||||
tree init_type = TREE_TYPE (elt_init);
|
||||
if ((POINTER_TYPE_P (elt_type) != POINTER_TYPE_P (init_type))
|
||||
|| !initializer_zerop (elt_init))
|
||||
if ((POINTER_TYPE_P (elt_type) != POINTER_TYPE_P (init_type)))
|
||||
last_nonzero = index;
|
||||
else if (!type_initializer_zero_p (elt_type, elt_init))
|
||||
last_nonzero = index;
|
||||
|
||||
/* This can happen with an invalid initializer (c++/54501). */
|
||||
|
|
|
@ -1,3 +1,11 @@
|
|||
2019-08-01 Martin Sebor <msebor@redhat.com>
|
||||
|
||||
PR c++/90947
|
||||
* c-c++-common/array-1.c: New test.
|
||||
* g++.dg/abi/mangle73.C: New test.
|
||||
* g++.dg/cpp2a/nontype-class23.C: New test.
|
||||
* g++.dg/init/array53.C: New test.
|
||||
|
||||
2019-08-01 Uroš Bizjak <ubizjak@gmail.com>
|
||||
|
||||
PR target/85693
|
||||
|
|
247
gcc/testsuite/c-c++-common/array-1.c
Normal file
247
gcc/testsuite/c-c++-common/array-1.c
Normal file
|
@ -0,0 +1,247 @@
|
|||
// PR c++/90947 - Simple lookup table of array of strings is miscompiled
|
||||
// { dg-do compile }
|
||||
// { dg-options "-O1 -fdump-tree-optimized" }
|
||||
|
||||
#define assert(expr) ((expr) ? (void)0 : __builtin_abort ())
|
||||
|
||||
void pr90947 (void)
|
||||
{
|
||||
int vecsize = 4;
|
||||
int index = 0;
|
||||
static const char *a[4][4] =
|
||||
{
|
||||
{ ".x", ".y", ".z", ".w" },
|
||||
{ ".xy", ".yz", ".zw", 0 },
|
||||
{ ".xyz", ".yzw", 0, 0 },
|
||||
{ "", 0, 0, 0 },
|
||||
};
|
||||
|
||||
assert (vecsize >= 1 && vecsize <= 4);
|
||||
assert (index >= 0 && index < 4);
|
||||
assert (a[vecsize - 1][index]);
|
||||
}
|
||||
|
||||
void f_a1_1 (void)
|
||||
{
|
||||
{
|
||||
const char* a[1][1] = { { 0 } };
|
||||
assert (0 == a[0][0]);
|
||||
}
|
||||
{
|
||||
const char* a[1][1] = { { "" } };
|
||||
assert ('\0' == *a[0][0]);
|
||||
}
|
||||
}
|
||||
|
||||
void f_a2_1 (void)
|
||||
{
|
||||
{
|
||||
const char* a[2][1] = { { "" }, { "" } };
|
||||
assert ('\0' == *a[0][0] && '\0' == *a[1][0]);
|
||||
}
|
||||
{
|
||||
const char* a[2][1] = { { 0 }, { "" } };
|
||||
assert (0 == a[0][0] && '\0' == *a[1][0]);
|
||||
}
|
||||
{
|
||||
const char* a[2][1] = { { }, { "" } };
|
||||
assert (0 == a[0][0] && '\0' == *a[1][0]);
|
||||
}
|
||||
}
|
||||
|
||||
void f_a2_2 (void)
|
||||
{
|
||||
{
|
||||
const char* a[2][2] = { { "", "" }, { "", "" } };
|
||||
assert ('\0' == *a[0][0] && '\0' == *a[0][1]);
|
||||
assert ('\0' == *a[1][0] && '\0' == *a[1][1]);
|
||||
}
|
||||
{
|
||||
const char* a[2][2] = { { "", "" }, { "", 0 } };
|
||||
assert ('\0' == *a[0][0] && '\0' == *a[0][1]);
|
||||
assert ('\0' == *a[1][0] && 0 == a[1][1]);
|
||||
}
|
||||
{
|
||||
const char* a[2][2] = { { "", "" }, { "" } };
|
||||
assert ('\0' == *a[0][0] && '\0' == *a[0][1]);
|
||||
assert ('\0' == *a[1][0] && 0 == a[1][1]);
|
||||
}
|
||||
{
|
||||
const char* a[2][2] = { { "", "" }, { 0, "" } };
|
||||
assert ('\0' == *a[0][0] && '\0' == *a[0][1]);
|
||||
assert (0 == a[1][0] && '\0' == *a[1][1]);
|
||||
}
|
||||
{
|
||||
const char* a[2][2] = { { "", 0 }, { 0, "" } };
|
||||
assert ('\0' == *a[0][0] && 0 == a[0][1]);
|
||||
assert (0 == a[1][0] && '\0' == *a[1][1]);
|
||||
}
|
||||
{
|
||||
const char* a[2][2] = { { 0, 0 }, { 0, "" } };
|
||||
assert (0 == a[0][0] && 0 == a[0][1]);
|
||||
assert (0 == a[1][0] && '\0' == *a[1][1]);
|
||||
}
|
||||
{
|
||||
const char* a[2][2] = { { 0 }, { 0, "" } };
|
||||
assert (0 == a[0][0] && 0 == a[0][1]);
|
||||
assert (0 == a[1][0] && '\0' == *a[1][1]);
|
||||
}
|
||||
{
|
||||
const char* a[2][2] = { { }, { 0, "" } };
|
||||
assert (0 == a[0][0] && 0 == a[0][1]);
|
||||
assert (0 == a[1][0] && '\0' == *a[1][1]);
|
||||
}
|
||||
}
|
||||
|
||||
void f_a2_2_2 (void)
|
||||
{
|
||||
{
|
||||
const char* a[2][2][2] =
|
||||
{ { { "", "" }, { "", "" } }, { { "", "" }, { "", "" } } };
|
||||
|
||||
assert ('\0' == *a[0][0][0] && '\0' == *a[0][0][1]);
|
||||
assert ('\0' == *a[0][1][0] && '\0' == *a[0][1][1]);
|
||||
assert ('\0' == *a[1][0][0] && '\0' == *a[1][0][1]);
|
||||
assert ('\0' == *a[1][1][0] && '\0' == *a[1][1][1]);
|
||||
}
|
||||
|
||||
{
|
||||
const char* a[2][2][2] =
|
||||
{ { { "", "" }, { "", "" } }, { { "", "" }, { 0, "" } } };
|
||||
|
||||
assert ('\0' == *a[0][0][0] && '\0' == *a[0][0][1]);
|
||||
assert ('\0' == *a[0][1][0] && '\0' == *a[0][1][1]);
|
||||
assert ('\0' == *a[1][0][0] && '\0' == *a[1][0][1]);
|
||||
assert (0 == a[1][1][0] && '\0' == *a[1][1][1]);
|
||||
}
|
||||
|
||||
{
|
||||
const char* a[2][2][2] =
|
||||
{ { { "", "" }, { "", "" } }, { { 0, 0 }, { 0, "" } } };
|
||||
|
||||
assert ('\0' == *a[0][0][0] && '\0' == *a[0][0][1]);
|
||||
assert ('\0' == *a[0][1][0] && '\0' == *a[0][1][1]);
|
||||
assert (0 == a[1][0][0] && 0 == a[1][0][1]);
|
||||
assert (0 == a[1][1][0] && '\0' == *a[1][1][1]);
|
||||
}
|
||||
|
||||
{
|
||||
const char* a[2][2][2] =
|
||||
{ { { "", "" }, { 0, 0 } }, { { 0, 0 }, { 0, "" } } };
|
||||
|
||||
assert ('\0' == *a[0][0][0] && '\0' == *a[0][0][1]);
|
||||
assert (0 == a[0][1][0] && 0 == a[0][1][1]);
|
||||
assert (0 == a[1][0][0] && 0 == a[1][0][1]);
|
||||
assert (0 == a[1][1][0] && '\0' == *a[1][1][1]);
|
||||
}
|
||||
|
||||
{
|
||||
const char* a[2][2][2] =
|
||||
{ { { 0, 0 }, { 0, 0 } }, { { 0, 0 }, { 0, "" } } };
|
||||
|
||||
assert (0 == a[0][0][0] && 0 == a[0][0][1]);
|
||||
assert (0 == a[0][1][0] && 0 == a[0][1][1]);
|
||||
assert (0 == a[1][0][0] && 0 == a[1][0][1]);
|
||||
assert (0 == a[1][1][0] && '\0' == *a[1][1][1]);
|
||||
}
|
||||
|
||||
{
|
||||
const char* a[2][2][2] =
|
||||
{ { { }, { } }, { { }, { 0, "" } } };
|
||||
|
||||
assert (0 == a[0][0][0] && 0 == a[0][0][1]);
|
||||
assert (0 == a[0][1][0] && 0 == a[0][1][1]);
|
||||
assert (0 == a[1][0][0] && 0 == a[1][0][1]);
|
||||
assert (0 == a[1][1][0] && '\0' == *a[1][1][1]);
|
||||
}
|
||||
}
|
||||
|
||||
void f_sa2_2_2 (void)
|
||||
{
|
||||
struct S { const char a[2], *s, c; };
|
||||
|
||||
{
|
||||
const struct S a[2][2][2] = {
|
||||
{ },
|
||||
{
|
||||
{ { }, { "", "" } },
|
||||
{ }
|
||||
}
|
||||
};
|
||||
|
||||
assert ('\0' == *a[0][0][0].a && 0 == a[0][0][0].s && 0 == a[0][0][0].c);
|
||||
assert ('\0' == *a[0][0][1].a && 0 == a[0][0][1].s && 0 == a[0][0][1].c);
|
||||
assert ('\0' == *a[0][1][0].a && 0 == a[0][1][0].s && 0 == a[0][1][0].c);
|
||||
assert ('\0' == *a[0][1][1].a && 0 == a[0][1][1].s && 0 == a[0][1][1].c);
|
||||
|
||||
assert ('\0' == *a[1][0][0].a && 0 == a[1][0][0].s && 0 == a[1][0][0].c);
|
||||
assert ('\0' == *a[1][0][1].a && '\0' == *a[1][0][1].s && 0 == a[1][0][1].c);
|
||||
assert ('\0' == *a[1][1][0].a && 0 == a[1][1][0].s && 0 == a[1][1][0].c);
|
||||
assert ('\0' == *a[1][1][1].a && 0 == a[1][1][1].s && 0 == a[1][1][1].c);
|
||||
}
|
||||
|
||||
{
|
||||
const struct S a[2][2][2] = {
|
||||
{ },
|
||||
{
|
||||
{ { } },
|
||||
{ { "", "" } }
|
||||
}
|
||||
};
|
||||
|
||||
assert ('\0' == *a[0][0][0].a && 0 == a[0][0][0].s);
|
||||
assert ('\0' == *a[0][0][1].a && 0 == a[0][0][1].s);
|
||||
assert ('\0' == *a[0][1][0].a && 0 == a[0][1][0].s);
|
||||
assert ('\0' == *a[0][1][1].a && 0 == a[0][1][1].s);
|
||||
|
||||
assert ('\0' == *a[1][0][0].a && 0 == a[1][0][0].s);
|
||||
assert ('\0' == *a[1][0][1].a && 0 == a[1][0][1].s);
|
||||
assert ('\0' == *a[1][1][0].a && '\0' == *a[1][1][0].s);
|
||||
assert ('\0' == *a[1][1][1].a && 0 == a[1][1][1].s);
|
||||
}
|
||||
|
||||
{
|
||||
const struct S a[2][2][2] = {
|
||||
{ },
|
||||
{
|
||||
{ { }, { } },
|
||||
{ { }, { "", "", 0 } }
|
||||
}
|
||||
};
|
||||
|
||||
assert ('\0' == *a[0][0][0].a && 0 == a[0][0][0].s);
|
||||
assert ('\0' == *a[0][0][1].a && 0 == a[0][0][1].s);
|
||||
assert ('\0' == *a[0][1][0].a && 0 == a[0][1][0].s);
|
||||
assert ('\0' == *a[0][1][1].a && 0 == a[0][1][1].s);
|
||||
|
||||
assert ('\0' == *a[1][0][0].a && 0 == a[1][0][0].s);
|
||||
assert ('\0' == *a[1][0][1].a && 0 == a[1][0][1].s);
|
||||
assert ('\0' == *a[1][1][0].a && 0 == a[1][1][0].s);
|
||||
assert ('\0' == *a[1][1][1].a && '\0' == *a[1][1][1].s);
|
||||
}
|
||||
|
||||
{
|
||||
const struct S a[2][2][2] = {
|
||||
{
|
||||
{ { { 0 }, 0, 0 }, { { 0 } , 0, 0 } },
|
||||
{ { { 0 }, 0, 0 }, { { 0 } , 0, 0 } },
|
||||
},
|
||||
{
|
||||
{ { { 0 }, 0, 0 }, { { 0 } , 0, 0 } },
|
||||
{ { }, { "", "", 0 } }
|
||||
}
|
||||
};
|
||||
|
||||
assert ('\0' == *a[0][0][0].a && 0 == a[0][0][0].s);
|
||||
assert ('\0' == *a[0][0][1].a && 0 == a[0][0][1].s);
|
||||
assert ('\0' == *a[0][1][0].a && 0 == a[0][1][0].s);
|
||||
assert ('\0' == *a[0][1][1].a && 0 == a[0][1][1].s);
|
||||
|
||||
assert ('\0' == *a[1][0][0].a && 0 == a[1][0][0].s);
|
||||
assert ('\0' == *a[1][0][1].a && 0 == a[1][0][1].s);
|
||||
assert ('\0' == *a[1][1][0].a && 0 == a[1][1][0].s);
|
||||
assert ('\0' == *a[1][1][1].a && '\0' == *a[1][1][1].s);
|
||||
}
|
||||
}
|
||||
|
||||
// { dg-final { scan-tree-dump-not "abort" "optimized" } }
|
96
gcc/testsuite/g++.dg/abi/mangle73.C
Normal file
96
gcc/testsuite/g++.dg/abi/mangle73.C
Normal file
|
@ -0,0 +1,96 @@
|
|||
// { dg-do compile { target c++2a } }
|
||||
|
||||
struct A
|
||||
{
|
||||
char a[2][2];
|
||||
};
|
||||
|
||||
template <A> struct B { };
|
||||
|
||||
typedef B<A{ { { 0, 0 }, { 0, 0 } } }> AZZZZ;
|
||||
typedef B<A{ { { 0, 0 }, { 0 } } }> AZZZ_;
|
||||
typedef B<A{ { { 0, 0 } } }> AZZ__;
|
||||
typedef B<A{ { { 0 } } }> AZ___;
|
||||
typedef B<A{ { { } } }> A____;
|
||||
|
||||
typedef B<A{ { { "" }, { "" } } }> AS_S_;
|
||||
typedef B<A{ { { "" }, { 0, 0 } } }> AS_ZZ;
|
||||
typedef B<A{ { { "" }, { 0 } } }> AS_Z_;
|
||||
typedef B<A{ { { "" } } }> AS___;
|
||||
|
||||
|
||||
// Verify that the types mangle the same.
|
||||
void a_zzzz (AZZZZ) { }
|
||||
// { dg-final { scan-assembler "_Z6a_zzzz1BIXtl1AEEE" } }
|
||||
|
||||
void a_zzz_ (AZZZ_) { }
|
||||
// { dg-final { scan-assembler "_Z6a_zzz_1BIXtl1AEEE" } }
|
||||
|
||||
void a_zz__ (AZZ__) { }
|
||||
// { dg-final { scan-assembler "_Z6a_zz__1BIXtl1AEEE" } }
|
||||
|
||||
void a_z___ (AZ___) { }
|
||||
// { dg-final { scan-assembler "_Z6a_z___1BIXtl1AEEE" } }
|
||||
|
||||
void a_____ (A____) { }
|
||||
// { dg-final { scan-assembler "_Z6a_____1BIXtl1AEEE" } }
|
||||
|
||||
void a_s_s_ (AS_S_) { }
|
||||
// { dg-final { scan-assembler "_Z6a_s_s_1BIXtl1AEEE" } }
|
||||
|
||||
void a_s_zz (AS_ZZ) { }
|
||||
// { dg-final { scan-assembler "_Z6a_s_zz1BIXtl1AEEE" } }
|
||||
|
||||
void a_s_z_ (AS_Z_) { }
|
||||
// { dg-final { scan-assembler "_Z6a_s_z_1BIXtl1AEEE" } }
|
||||
|
||||
void a_s___ (AS___) { }
|
||||
// { dg-final { scan-assembler "_Z6a_s___1BIXtl1AEEE" } }
|
||||
|
||||
|
||||
struct C
|
||||
{
|
||||
struct { const char a[2][2], *p; } a[2];
|
||||
};
|
||||
|
||||
template <C> struct D { };
|
||||
|
||||
typedef D<C{{{{{ 0, 0 }, { 0, 0 }}, 0 }, {{{ 0, 0 }, { 0, 0 }}, 0 }}}> DZZZZZZZZZZ;
|
||||
typedef D<C{{{{{ 0, 0 }, { 0, 0 }}, 0 }, {{{ 0, 0 }, { 0, 0 }}}}}> DZZZZZZZZZ_;
|
||||
typedef D<C{{{{{ 0, 0 }, { 0, 0 }}, 0 }, {{{ 0, 0 }, { 0 }}}}}> DZZZZZZZZ__;
|
||||
typedef D<C{{{{{ 0, 0 }, { 0, 0 }}, 0 }, {{{ 0, 0 } }}}}> DZZZZZZZ___;
|
||||
typedef D<C{{{{{ 0, 0 }, { 0, 0 }}, 0 }, {{{ 0 } }}}}> DZZZZZZ____;
|
||||
typedef D<C{{{{{ 0, 0 }, { 0, 0 }}, 0 }}}> DZZZZZ_____;
|
||||
typedef D<C{{{{{ 0, 0 }, { 0, 0 }}}}}> DZZZZ______;
|
||||
typedef D<C{{{{{ 0, 0 }, { 0 }}}}}> DZZZ_______;
|
||||
typedef D<C{{{{{ 0, 0 }}}}}> DZZ________;
|
||||
typedef D<C{{{{{ 0 }}}}}> DZ_________;
|
||||
typedef D<C{ }> D__________;
|
||||
|
||||
typedef D<C{{{{{ "" }, { "" }}, 0 }, {{{ "" }, { "" }}, 0 }}}> DS_S_ZS_S_Z;
|
||||
|
||||
void d_zzzzzzzzzz (DZZZZZZZZZZ) { }
|
||||
// { dg-final { scan-assembler "_Z12d_zzzzzzzzzz1DIXtl1CEEE" } }
|
||||
void d_zzzzzzzzz_ (DZZZZZZZZZ_) { }
|
||||
// { dg-final { scan-assembler "_Z12d_zzzzzzzzz_1DIXtl1CEEE" } }
|
||||
void d_zzzzzzzz__ (DZZZZZZZZ__) { }
|
||||
// { dg-final { scan-assembler "_Z12d_zzzzzzzz__1DIXtl1CEEE" } }
|
||||
void d_zzzzzzz___ (DZZZZZZZ___) { }
|
||||
// { dg-final { scan-assembler "_Z12d_zzzzzzz___1DIXtl1CEEE" } }
|
||||
void d_zzzzzz____ (DZZZZZZ____) { }
|
||||
// { dg-final { scan-assembler "_Z12d_zzzzzz____1DIXtl1CEEE" } }
|
||||
void d_zzzzz_____ (DZZZZZ_____) { }
|
||||
// { dg-final { scan-assembler "_Z12d_zzzzz_____1DIXtl1CEEE" } }
|
||||
void d_zzzz______ (DZZZZ______) { }
|
||||
// { dg-final { scan-assembler "_Z12d_zzzz______1DIXtl1CEEE" } }
|
||||
void d_zzz_______ (DZZZ_______) { }
|
||||
// { dg-final { scan-assembler "_Z12d_zzz_______1DIXtl1CEEE" } }
|
||||
void d_zz________ (DZZ________) { }
|
||||
// { dg-final { scan-assembler "_Z12d_zz________1DIXtl1CEEE" } }
|
||||
void d_z_________ (DZ_________) { }
|
||||
// { dg-final { scan-assembler "_Z12d_z_________1DIXtl1CEEE" } }
|
||||
void d___________ (D__________) { }
|
||||
// { dg-final { scan-assembler "_Z12d___________1DIXtl1CEEE" } }
|
||||
|
||||
void d_s_s_zs_s_z (DS_S_ZS_S_Z) { }
|
||||
// { dg-final { scan-assembler "_Z12d_s_s_zs_s_z1DIXtl1CEEE" } }
|
102
gcc/testsuite/g++.dg/cpp2a/nontype-class23.C
Normal file
102
gcc/testsuite/g++.dg/cpp2a/nontype-class23.C
Normal file
|
@ -0,0 +1,102 @@
|
|||
// PR c++/90947 - Simple lookup table of array of strings is miscompiled
|
||||
// Test to verify that the same specializations on non-type template
|
||||
// parameters of class types are in fact treated as the same. Unlike
|
||||
// nontype-class15.C which involves only one-dimensional arrays this
|
||||
// test involves arrays of arrays and arrays of structs.
|
||||
// { dg-do compile { target c++2a } }
|
||||
|
||||
struct AA3
|
||||
{
|
||||
const char a[2][2][2];
|
||||
};
|
||||
|
||||
template <AA3> struct BAA3 { };
|
||||
|
||||
// Redeclare the same variable using different initialization forms
|
||||
// of the same constant to verify that they are in fact all recognized
|
||||
// as the same.
|
||||
extern BAA3<AA3{{{ "", "" }, { "", "" }}}> baa3;
|
||||
extern BAA3<AA3{{{ "", "" }, { "", { 0, 0 } }}}> baa3;
|
||||
extern BAA3<AA3{{{ "", "" }, { "", { 0 } }}}> baa3;
|
||||
extern BAA3<AA3{{{ "", "" }, { "", {} }}}> baa3;
|
||||
extern BAA3<AA3{{{ "", "" }, { "" }}}> baa3;
|
||||
extern BAA3<AA3{{{ "", "" }, { { 0, 0 } }}}> baa3;
|
||||
extern BAA3<AA3{{{ "", "" }, { { 0 } }}}> baa3;
|
||||
extern BAA3<AA3{{{ "", "" }, { {} }}}> baa3;
|
||||
extern BAA3<AA3{{{ "", "" }, { }}}> baa3;
|
||||
extern BAA3<AA3{{{ "", "" }}}> baa3;
|
||||
extern BAA3<AA3{{{ "", { 0, 0 } }}}> baa3;
|
||||
extern BAA3<AA3{{{ "", { 0 } }}}> baa3;
|
||||
extern BAA3<AA3{{{ "", {} }}}> baa3;
|
||||
extern BAA3<AA3{{{ "" }}}> baa3;
|
||||
extern BAA3<AA3{{{ { 0, 0 } }}}> baa3;
|
||||
extern BAA3<AA3{{{ { 0 } }}}> baa3;
|
||||
extern BAA3<AA3{{{ {} }}}> baa3;
|
||||
extern BAA3<AA3{{{ }}}> baa3;
|
||||
extern BAA3<AA3{{ }}> baa3;
|
||||
extern BAA3<AA3{ }> baa3;
|
||||
|
||||
extern BAA3<AA3{{{ "", "" }, { "", "1" }}}> baa3_1;
|
||||
extern BAA3<AA3{{{ "", "" }, { "", { '1', 0 } }}}> baa3_1;
|
||||
extern BAA3<AA3{{{ "", "" }, { "", { '1' } }}}> baa3_1;
|
||||
|
||||
extern BAA3<AA3{{{ "", "" }, { "1", {} }}}> baa3_2;
|
||||
extern BAA3<AA3{{{ "", "" }, { "1" }}}> baa3_2;
|
||||
extern BAA3<AA3{{{ "", "" }, { { '1', 0 } }}}> baa3_2;
|
||||
extern BAA3<AA3{{{ "", "" }, { { '1' } }}}> baa3_2;
|
||||
|
||||
extern BAA3<AA3{{{ "", "1" }}}> baa3_3;
|
||||
extern BAA3<AA3{{{ "", { '1', 0 } }}}> baa3_3;
|
||||
extern BAA3<AA3{{{ "", { '1' } }}}> baa3_3;
|
||||
|
||||
extern BAA3<AA3{{{ "1" }}}> baa3_4;
|
||||
extern BAA3<AA3{{{ { '1', 0 } }}}> baa3_4;
|
||||
extern BAA3<AA3{{{ { '1' } }}}> baa3_4;
|
||||
|
||||
struct AS2
|
||||
{
|
||||
struct S { const char a[2], *p; } a[2];
|
||||
};
|
||||
|
||||
template <AS2> struct BAS2 { };
|
||||
|
||||
extern BAS2<AS2{{{ "", 0 }, { "", 0 }}}> bas2;
|
||||
extern BAS2<AS2{{{ "", 0 }, { {}, 0 }}}> bas2;
|
||||
extern BAS2<AS2{{{ "", 0 }, { "" }}}> bas2;
|
||||
extern BAS2<AS2{{{ "", 0 }, { {} }}}> bas2;
|
||||
extern BAS2<AS2{{{ "", 0 }, { }}}> bas2;
|
||||
extern BAS2<AS2{{{ "", 0 }}}> bas2;
|
||||
extern BAS2<AS2{{{ {}, 0 }}}> bas2;
|
||||
extern BAS2<AS2{{{ "" }}}> bas2;
|
||||
extern BAS2<AS2{{{ {} }}}> bas2;
|
||||
extern BAS2<AS2{{{ }}}> bas2;
|
||||
extern BAS2<AS2{{ }}> bas2;
|
||||
extern BAS2<AS2{ }> bas2;
|
||||
|
||||
struct AS2_2
|
||||
{
|
||||
struct S { const char a[2], *p; } a[2][2];
|
||||
};
|
||||
|
||||
template <AS2_2> struct BAS2_2 { };
|
||||
|
||||
extern BAS2_2<AS2_2{{{{ "", 0 }, { "", 0 } }, { { "", 0 }, { "", 0 }}}}> b2_2;
|
||||
extern BAS2_2<AS2_2{{{{ "", 0 }, { "", 0 } }, { { "", 0 }, { "" }}}}> b2_2;
|
||||
extern BAS2_2<AS2_2{{{{ "", 0 }, { "", 0 } }, { { "", 0 }, { {} }}}}> b2_2;
|
||||
extern BAS2_2<AS2_2{{{{ "", 0 }, { "", 0 } }, { { "", 0 }, { }}}}> b2_2;
|
||||
extern BAS2_2<AS2_2{{{{ "", 0 }, { "", 0 } }, { { "", 0 } }}}> b2_2;
|
||||
extern BAS2_2<AS2_2{{{{ "", 0 }, { "", 0 } }, { { "" } }}}> b2_2;
|
||||
extern BAS2_2<AS2_2{{{{ "", 0 }, { "", 0 } }, { { {} } }}}> b2_2;
|
||||
extern BAS2_2<AS2_2{{{{ "", 0 }, { "", 0 } }, { { }}}}> b2_2;
|
||||
extern BAS2_2<AS2_2{{{{ "", 0 }, { "", 0 } }, { }}}> b2_2;
|
||||
extern BAS2_2<AS2_2{{{{ "", 0 }, { "", 0 }}}}> b2_2;
|
||||
extern BAS2_2<AS2_2{{{{ "", 0 }, { "" }}}}> b2_2;
|
||||
extern BAS2_2<AS2_2{{{{ "", 0 }, { {} }}}}> b2_2;
|
||||
extern BAS2_2<AS2_2{{{{ "", 0 }, { }}}}> b2_2;
|
||||
extern BAS2_2<AS2_2{{{{ "", 0 }}}}> b2_2;
|
||||
extern BAS2_2<AS2_2{{{{ "" }}}}> b2_2;
|
||||
extern BAS2_2<AS2_2{{{{ {} }}}}> b2_2;
|
||||
extern BAS2_2<AS2_2{{{{ }}}}> b2_2;
|
||||
extern BAS2_2<AS2_2{{{ }}}> b2_2;
|
||||
extern BAS2_2<AS2_2{{ }}> b2_2;
|
||||
extern BAS2_2<AS2_2{ }> b2_2;
|
33
gcc/testsuite/g++.dg/init/array53.C
Normal file
33
gcc/testsuite/g++.dg/init/array53.C
Normal file
|
@ -0,0 +1,33 @@
|
|||
// PR c++/90947 - Simple lookup table of array of strings is miscompiled
|
||||
// Verify that initializers for arrays of elements of a class type with
|
||||
// "unusual" data members are correctly recognized as non-zero.
|
||||
// { dg-do compile }
|
||||
// { dg-options "-O1 -fdump-tree-optimized" }
|
||||
|
||||
struct S
|
||||
{
|
||||
const char *p;
|
||||
static int i;
|
||||
enum { e };
|
||||
typedef int X;
|
||||
int: 1, b:1;
|
||||
union {
|
||||
int c;
|
||||
};
|
||||
const char *q;
|
||||
};
|
||||
|
||||
void f (void)
|
||||
{
|
||||
const struct S a[2] =
|
||||
{
|
||||
{ /* .p = */ "", /* .b = */ 0, /* .c = */ 0, /* .q = */ "" },
|
||||
{ /* .p = */ "", /* .b = */ 0, /* .c = */ 0, /* .q = */ "" }
|
||||
};
|
||||
|
||||
if (!a[0].p || *a[0].p || !a[0].q || *a[0].q
|
||||
|| !a[1].p || *a[1].p || !a[1].q || *a[1].q)
|
||||
__builtin_abort ();
|
||||
}
|
||||
|
||||
// { dg-final { scan-tree-dump-not "abort" "optimized" } }
|
67
gcc/tree.c
67
gcc/tree.c
|
@ -11376,6 +11376,73 @@ initializer_each_zero_or_onep (const_tree expr)
|
|||
}
|
||||
}
|
||||
|
||||
/* Given an initializer INIT for a TYPE, return true if INIT is zero
|
||||
so that it can be replaced by value initialization. This function
|
||||
distinguishes betwen empty strings as initializers for arrays and
|
||||
for pointers (which make it return false). */
|
||||
|
||||
bool
|
||||
type_initializer_zero_p (tree type, tree init)
|
||||
{
|
||||
if (type == error_mark_node || init == error_mark_node)
|
||||
return false;
|
||||
|
||||
STRIP_NOPS (init);
|
||||
|
||||
if (POINTER_TYPE_P (type))
|
||||
return TREE_CODE (init) != STRING_CST && initializer_zerop (init);
|
||||
|
||||
if (TREE_CODE (init) != CONSTRUCTOR)
|
||||
return initializer_zerop (init);
|
||||
|
||||
if (TREE_CODE (type) == ARRAY_TYPE)
|
||||
{
|
||||
tree elt_type = TREE_TYPE (type);
|
||||
elt_type = TYPE_MAIN_VARIANT (elt_type);
|
||||
if (elt_type == char_type_node)
|
||||
return initializer_zerop (init);
|
||||
|
||||
tree elt_init;
|
||||
unsigned HOST_WIDE_INT i;
|
||||
FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (init), i, elt_init)
|
||||
if (!type_initializer_zero_p (elt_type, elt_init))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (TREE_CODE (type) != RECORD_TYPE)
|
||||
return initializer_zerop (init);
|
||||
|
||||
tree fld = TYPE_FIELDS (type);
|
||||
|
||||
tree fld_init;
|
||||
unsigned HOST_WIDE_INT i;
|
||||
FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (init), i, fld_init)
|
||||
{
|
||||
/* Advance to the next member, skipping over everything that
|
||||
canot be initialized (including unnamed bit-fields). */
|
||||
while (TREE_CODE (fld) != FIELD_DECL
|
||||
|| DECL_ARTIFICIAL (fld)
|
||||
|| (DECL_BIT_FIELD (fld) && !DECL_NAME (fld)))
|
||||
{
|
||||
fld = DECL_CHAIN (fld);
|
||||
if (!fld)
|
||||
return true;
|
||||
continue;
|
||||
}
|
||||
|
||||
tree fldtype = TREE_TYPE (fld);
|
||||
if (!type_initializer_zero_p (fldtype, fld_init))
|
||||
return false;
|
||||
|
||||
fld = DECL_CHAIN (fld);
|
||||
if (!fld)
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Check if vector VEC consists of all the equal elements and
|
||||
that the number of elements corresponds to the type of VEC.
|
||||
The function returns first element of the vector
|
||||
|
|
|
@ -4623,6 +4623,12 @@ extern tree first_field (const_tree);
|
|||
extern bool initializer_zerop (const_tree, bool * = NULL);
|
||||
extern bool initializer_each_zero_or_onep (const_tree);
|
||||
|
||||
/* Analogous to initializer_zerop but also examines the type for
|
||||
which the initializer is being used. Unlike initializer_zerop,
|
||||
considers empty strings to be zero initializers for arrays and
|
||||
non-zero for pointers. */
|
||||
extern bool type_initializer_zero_p (tree, tree);
|
||||
|
||||
extern wide_int vector_cst_int_elt (const_tree, unsigned int);
|
||||
extern tree vector_cst_elt (const_tree, unsigned int);
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue