PR c++/89974 - ICE on a definition of a non-type specialization on a struct object with pointer to member function

PR c++/89974 - ICE on a definition of a non-type specialization on a struct object with pointer to member function
PR c++/89878 - same specializations on a zero-initialized struct object as a non-type parameter treated as distinct
PR c++/89833 - sorry, unimplemented: string literal in function template signature
PR c++/47488 - sorry, unimplemented: string literal in function template signature

gcc/cp/ChangeLog:

	PR c++/89974
	PR c++/89878
	PR c++/89833
	PR c++/47488
	* decl.c (reshape_init_array_1): Strip trailing zero-initializers
	from arrays of trivial type and known size.
	* mangle.c (write_expression): Convert braced initializer lists
	to STRING_CSTs.
	(write_expression): Trim trailing zero-initializers from arrays
	of trivial type.
	(write_template_arg_literal): Mangle strings the same as braced
	initializer lists.

gcc/testsuite/ChangeLog:

	PR c++/89974
	PR c++/89878
	PR c++/89833
	PR c++/47488
	* gcc/testsuite/g++.dg/abi/mangle69.C: New test.
	* gcc/testsuite/g++.dg/abi/mangle70.C: New test.
	* gcc/testsuite/g++.dg/abi/mangle71.C: New test.
	* gcc/testsuite/g++.dg/abi/mangle72.C: New test.
	* gcc/testsuite/g++.dg/cpp0x/constexpr-array19.C: New test.
	* gcc/testsuite/g++.dg/cpp2a/nontype-class15.C: New test.
	* gcc/testsuite/g++.dg/cpp2a/nontype-class16.C: New test.
	* gcc/testsuite/g++.dg/init/array51.C: New test.

From-SVN: r270155
This commit is contained in:
Martin Sebor 2019-04-04 23:10:23 +00:00 committed by Martin Sebor
parent 1a9b15a7d7
commit 187c6369c0
13 changed files with 1032 additions and 10 deletions

View File

@ -1,3 +1,18 @@
2019-04-04 Martin Sebor <msebor@redhat.com>
PR c++/89974
PR c++/89878
PR c++/89833
PR c++/47488
* decl.c (reshape_init_array_1): Strip trailing zero-initializers
from arrays of trivial type and known size.
* mangle.c (write_expression): Convert braced initializer lists
to STRING_CSTs.
(write_expression): Trim trailing zero-initializers from arrays
of trivial type.
(write_template_arg_literal): Mangle strings the same as braced
initializer lists.
2019-04-03 Jason Merrill <jason@redhat.com>
PR c++/81866 - ICE with member template and default targ.

View File

@ -5799,6 +5799,9 @@ reshape_init_array_1 (tree elt_type, tree max_index, reshape_iter *d,
max_index_cst = tree_to_uhwi (fold_convert (size_type_node, max_index));
}
/* Set to the index of the last element with a non-zero initializer.
Initializers for elements past this one can be dropped. */
unsigned HOST_WIDE_INT last_nonzero = -1;
/* Loop until there are no more initializers. */
for (index = 0;
d->cur != d->end && (!sized_array_p || index <= max_index_cst);
@ -5817,11 +5820,30 @@ reshape_init_array_1 (tree elt_type, tree max_index, reshape_iter *d,
if (!TREE_CONSTANT (elt_init))
TREE_CONSTANT (new_init) = false;
if (!initializer_zerop (elt_init))
last_nonzero = index;
/* This can happen with an invalid initializer (c++/54501). */
if (d->cur == old_cur && !sized_array_p)
break;
}
if (sized_array_p
&& (!CLASS_TYPE_P (elt_type)
|| TYPE_HAS_TRIVIAL_DFLT (elt_type)))
{
/* Strip trailing zero-initializers from an array of a trivial
type of known size. They are redundant and get in the way
of telling them apart from those with implicit zero value. */
unsigned HOST_WIDE_INT nelts = CONSTRUCTOR_NELTS (new_init);
if (last_nonzero > nelts)
nelts = 0;
else if (last_nonzero < nelts - 1)
nelts = last_nonzero + 1;
vec_safe_truncate (CONSTRUCTOR_ELTS (new_init), nelts);
}
return new_init;
}

View File

@ -3136,18 +3136,48 @@ write_expression (tree expr)
}
else if (code == CONSTRUCTOR)
{
vec<constructor_elt, va_gc> *elts = CONSTRUCTOR_ELTS (expr);
unsigned i; tree val;
bool braced_init = BRACE_ENCLOSED_INITIALIZER_P (expr);
tree etype = TREE_TYPE (expr);
if (BRACE_ENCLOSED_INITIALIZER_P (expr))
if (braced_init)
write_string ("il");
else
{
write_string ("tl");
write_type (TREE_TYPE (expr));
write_type (etype);
}
if (!initializer_zerop (expr) || !trivial_type_p (etype))
{
/* Convert braced initializer lists to STRING_CSTs so that
A<"Foo"> mangles the same as A<{'F', 'o', 'o', 0}> while
still using the latter mangling for strings that
originated as braced initializer lists. */
expr = braced_lists_to_strings (etype, expr);
if (TREE_CODE (expr) == CONSTRUCTOR)
{
vec<constructor_elt, va_gc> *elts = CONSTRUCTOR_ELTS (expr);
unsigned last_nonzero = -1, i;
tree val;
FOR_EACH_CONSTRUCTOR_VALUE (elts, i, val)
if (!initializer_zerop (val))
last_nonzero = i;
FOR_EACH_CONSTRUCTOR_VALUE (elts, i, val)
{
if (i > last_nonzero)
break;
write_expression (val);
}
}
else
{
gcc_assert (TREE_CODE (expr) == STRING_CST);
write_expression (expr);
}
}
FOR_EACH_CONSTRUCTOR_VALUE (elts, i, val)
write_expression (val);
write_char ('E');
}
else if (code == LAMBDA_EXPR)
@ -3353,8 +3383,14 @@ write_expression (tree expr)
static void
write_template_arg_literal (const tree value)
{
write_char ('L');
write_type (TREE_TYPE (value));
if (TREE_CODE (value) == STRING_CST)
/* Temporarily mangle strings as braced initializer lists. */
write_string ("tl");
else
write_char ('L');
tree valtype = TREE_TYPE (value);
write_type (valtype);
/* Write a null member pointer value as (type)0, regardless of its
real representation. */
@ -3397,8 +3433,31 @@ write_template_arg_literal (const tree value)
break;
case STRING_CST:
sorry ("string literal in function template signature");
break;
{
/* Mangle strings the same as braced initializer lists. */
unsigned n = TREE_STRING_LENGTH (value);
const char *str = TREE_STRING_POINTER (value);
/* Count the number of trailing nuls and subtract them from
STRSIZE because they don't need to be mangled. */
for (const char *p = str + n - 1; ; --p)
{
if (*p || p == str)
{
n -= str + n - !!*p - p;
break;
}
}
tree eltype = TREE_TYPE (valtype);
for (const char *p = str; n--; ++p)
{
write_char ('L');
write_type (eltype);
write_unsigned_number (*(const unsigned char*)p);
write_string ("E");
}
break;
}
default:
gcc_unreachable ();

View File

@ -1,3 +1,19 @@
2019-04-04 Martin Sebor <msebor@redhat.com>
PR c++/89974
PR c++/89878
PR c++/89833
PR c++/47488
* gcc/testsuite/g++.dg/abi/mangle69.C: New test.
* gcc/testsuite/g++.dg/abi/mangle70.C: New test.
* gcc/testsuite/g++.dg/abi/mangle71.C: New test.
* gcc/testsuite/g++.dg/abi/mangle72.C: New test.
* gcc/testsuite/g++.dg/cpp0x/constexpr-array19.C: New test.
* gcc/testsuite/g++.dg/cpp2a/nontype-class15.C: New test.
* gcc/testsuite/g++.dg/cpp2a/nontype-class16.C: New test.
* gcc/testsuite/g++.dg/init/array51.C: New test.
* gcc/testsuite/g++.dg/template/nontype29.C: New test.
2019-04-04 Martin Sebor <msebor@redhat.com>
PR middle-end/89957

View File

@ -0,0 +1,164 @@
// { dg-do compile { target c++2a } }
struct A1 { char c[5]; };
template <A1> struct B { };
// All of the following name the same type.
typedef B<A1{ }> A______;
typedef B<A1{ { 0 } }> A_Z____;
typedef B<A1{ { 0, 0 } }> A_ZZ___;
typedef B<A1{ { 0, 0, 0 } }> A_ZZZ__;
typedef B<A1{ { 0, 0, 0, 0 } }> A_ZZZZ_;
typedef B<A1{ { 0, 0, 0, 0, 0 } }> A_ZZZZZ;
// Verify that the types mangle the same.
void a______ (A______) { }
// { dg-final { scan-assembler "_Z7a______1BIXtl2A1EEE" } }
void a_z____ (A_Z____) { }
// { dg-final { scan-assembler "_Z7a_z____1BIXtl2A1EEE" } }
void a_zz___ (A_ZZ___) { }
// { dg-final { scan-assembler "_Z7a_zz___1BIXtl2A1EEE" } }
void a_zzz__ (A_ZZZ__) { }
// { dg-final { scan-assembler "_Z7a_zzz__1BIXtl2A1EEE" } }
void a_zzzz_ (A_ZZZZ_) { }
// { dg-final { scan-assembler "_Z7a_zzzz_1BIXtl2A1EEE" } }
void a_zzzzz (A_ZZZZZ) { }
// { dg-final { scan-assembler "_Z7a_zzzzz1BIXtl2A1EEE" } }
// All of the following use a string to initialize the array but
// also name the same type as the above.
typedef B<A1{ "" }> S_z____;
typedef B<A1{ "\0" }> S_Zz___;
typedef B<A1{ "\0\0" }> S_ZZz__;
typedef B<A1{ "\0\0\0" }> S_ZZZz_;
typedef B<A1{ "\0\0\0\0" }> S_ZZZZz;
// Verify that the types mangle the same.
void s_z____ (S_z____) { }
// { dg-final { scan-assembler "_Z7s_z____1BIXtl2A1EEE" } }
void s_Zz___ (S_Zz___) { }
// { dg-final { scan-assembler "_Z7s_Zz___1BIXtl2A1EEE" } }
void s_ZZz__ (S_ZZz__) { }
// { dg-final { scan-assembler "_Z7s_ZZz__1BIXtl2A1EEE" } }
void s_ZZZz_ (S_ZZZz_) { }
// { dg-final { scan-assembler "_Z7s_ZZZz_1BIXtl2A1EEE" } }
void s_ZZZZz (S_ZZZZz) { }
// { dg-final { scan-assembler "_Z7s_ZZZZz1BIXtl2A1EEE" } }
// All of the following also name the same type (distinct from
// the above).
typedef B<A1{ { 'A' } }> A_A____;
typedef B<A1{ { 'A', 0 } }> A_AZ___;
typedef B<A1{ { 'A', 0, 0 } }> A_AZZ__;
typedef B<A1{ { 'A', 0, 0, 0 } }> A_AZZZ_;
typedef B<A1{ { 'A', 0, 0, 0, 0 } }> A_AZZZZ;
void a_A____ (A_A____) { }
// { dg-final { scan-assembler "_Z7a_A____1BIXtl2A1tlA5_cLc65EEEEE" } }
void a_AZ___ (A_AZ___) { }
// { dg-final { scan-assembler "_Z7a_AZ___1BIXtl2A1tlA5_cLc65EEEEE" } }
void a_AZZ__ (A_AZZ__) { }
// { dg-final { scan-assembler "_Z7a_AZZ__1BIXtl2A1tlA5_cLc65EEEEE" } }
void a_AZZZ_ (A_AZZZ_) { }
// { dg-final { scan-assembler "_Z7a_AZZZ_1BIXtl2A1tlA5_cLc65EEEEE" } }
void a_AZZZZ (A_AZZZZ) { }
// { dg-final { scan-assembler "_Z7a_AZZZZ1BIXtl2A1tlA5_cLc65EEEEE" } }
typedef B<A1{ "A" }> S_Az___;
typedef B<A1{ "A\0" }> S_AZz__;
typedef B<A1{ "A\0\0" }> S_AZZz_;
typedef B<A1{ "A\0\0\0" }> S_AZZZz;
void s_Az___ (S_Az___) { }
// { dg-final { scan-assembler "_Z7s_Az___1BIXtl2A1tlA5_cLc65EEEEE" } }
void s_AZz__ (S_AZz__) { }
// { dg-final { scan-assembler "_Z7s_AZz__1BIXtl2A1tlA5_cLc65EEEEE" } }
void s_AZZz_ (S_AZZz_) { }
// { dg-final { scan-assembler "_Z7s_AZZz_1BIXtl2A1tlA5_cLc65EEEEE" } }
void s_AZZZz (S_AZZZz) { }
// { dg-final { scan-assembler "_Z7s_AZZZz1BIXtl2A1tlA5_cLc65EEEEE" } }
typedef B<A1{ 'A', 0, 0, 'D', 0 }> A_AZZDZ;
typedef B<A1{ 'A', 0, 0, 'D' }> A_AZZD_;
void a_AZZDZ (A_AZZDZ) { }
// { dg-final { scan-assembler "_Z7a_AZZD_1BIXtl2A1tlA5_cLc65ELc0ELc0ELc68EEEEE" } }
void a_AZZD_ (A_AZZD_) { }
// { dg-final { scan-assembler "_Z7a_AZZDZ1BIXtl2A1tlA5_cLc65ELc0ELc0ELc68EEEEE" } }
typedef B<A1{ { "AB\0D" } }> S_ABZD_;
typedef B<A1{ { "AB\0\0" } }> S_ABZZ_;
typedef B<A1{ { "AB\0" } }> S_ABZ__;
typedef B<A1{ { "AB" } }> S_AB___;
void s_abzd_ (S_ABZD_) { }
// { dg-final { scan-assembler "_Z7s_abzd_1BIXtl2A1tlA5_cLc65ELc66ELc0ELc68EEEEE" } }
void s_abzz_ (S_ABZZ_) { }
// { dg-final { scan-assembler "_Z7s_abzz_1BIXtl2A1tlA5_cLc65ELc66EEEEE" } }
void s_abz__ (S_ABZ__) { }
// { dg-final { scan-assembler "_Z7s_abz__1BIXtl2A1tlA5_cLc65ELc66EEEEE" } }
void s_ab___ (S_AB___) { }
// { dg-final { scan-assembler "_Z7s_ab___1BIXtl2A1tlA5_cLc65ELc66EEEEE" } }
struct A3 { char a[5], b[5], c[5]; };
template <A3> struct B3 { };
/* These all name the same type. */
typedef B3<A3{ "\1\2", { }, "\3\4\5\6" }> T_123z_______3456z;
typedef B3<A3{ "\1\2", { 0 }, "\3\4\5\6" }> T_123z__Z____3456z;
typedef B3<A3{ "\1\2", { 0, 0 }, "\3\4\5\6" }> T_123z__ZZ___3456z;
typedef B3<A3{ "\1\2", { 0, 0, 0 }, "\3\4\5\6" }> T_123z__ZZZ__3456z;
typedef B3<A3{ "\1\2", { 0, 0, 0, 0 }, "\3\4\5\6" }> T_123z__ZZZZ_3456z;
typedef B3<A3{ "\1\2", "", "\3\4\5\6" }> T_123z__Z____3456z;
typedef B3<A3{ "\1\2", "\0", "\3\4\5\6" }> T_123z__ZZ___3456z;
typedef B3<A3{ "\1\2", "\0\0", "\3\4\5\6" }> T_123z__ZZZ__3456z;
typedef B3<A3{ "\1\2", "\0\0\0", "\3\4\5\6" }> T_123z__ZZZZ_3456z;
typedef B3<A3{ "\1\2", "\0\0\0\0", "\3\4\5\6" }> T_123z__ZZZZZ3456z;
typedef B3<A3{ "\1\2\0", "\0\0\0\0", "\3\4\5\6" }> T_123Zz_ZZZZZ3456z;
typedef B3<A3{ "\1\2\0\0", "\0\0\0\0", "\3\4\5\6" }> T_123ZZzZZZZZ3456z;
void ft0 (T_123z_______3456z) { }
// { dg-final { scan-assembler "_Z3ft02B3IXtl2A3tlA5_cLc1ELc2EEtlS1_EtlS1_Lc3ELc4ELc5ELc6EEEEE" } }
void ft1 (T_123z__Z____3456z) { }
// { dg-final { scan-assembler "_Z3ft12B3IXtl2A3tlA5_cLc1ELc2EEtlS1_EtlS1_Lc3ELc4ELc5ELc6EEEEE" } }
void ft2 (T_123z__ZZ___3456z) { }
// { dg-final { scan-assembler "_Z3ft22B3IXtl2A3tlA5_cLc1ELc2EEtlS1_EtlS1_Lc3ELc4ELc5ELc6EEEEE" } }
void ft3 (T_123z__ZZZ__3456z) { }
// { dg-final { scan-assembler "_Z3ft32B3IXtl2A3tlA5_cLc1ELc2EEtlS1_EtlS1_Lc3ELc4ELc5ELc6EEEEE" } }
void ft4 (T_123z__ZZZZ_3456z) { }
// { dg-final { scan-assembler "_Z3ft42B3IXtl2A3tlA5_cLc1ELc2EEtlS1_EtlS1_Lc3ELc4ELc5ELc6EEEEE" } }
void ft9 (T_123z__ZZZZZ3456z) { }
// { dg-final { scan-assembler "_Z3ft92B3IXtl2A3tlA5_cLc1ELc2EEtlS1_EtlS1_Lc3ELc4ELc5ELc6EEEEE" } }
void fta (T_123Zz_ZZZZZ3456z) { }
// { dg-final { scan-assembler "_Z3fta2B3IXtl2A3tlA5_cLc1ELc2EEtlS1_EtlS1_Lc3ELc4ELc5ELc6EEEEE" } }
void ftb (T_123ZZzZZZZZ3456z) { }
// { dg-final { scan-assembler "_Z3ftb2B3IXtl2A3tlA5_cLc1ELc2EEtlS1_EtlS1_Lc3ELc4ELc5ELc6EEEEE" } }

View File

@ -0,0 +1,29 @@
// Verify that class literals are mangled the same way regardless
// of the underlying type.
// { dg-do compile { target c++2a } }
struct I { int a[5], b[5], c[5]; };
template <I> struct X { };
typedef X<I{ {1,2}, {}, {11,12,13,14} }> Ti;
void f (Ti) { }
// { dg-final { scan-assembler "_Z1f1XIXtl1ItlA5_iLi1ELi2EEtlS1_EtlS1_Li11ELi12ELi13ELi14EEEEE" } }
struct C { char a[5], b[5], c[5]; };
template <C> struct Y { };
typedef Y<C{ {1,2}, {}, {11,12,13,14} }> Tca;
void g (Tca) { }
// { dg-final { scan-assembler "_Z1g1YIXtl1CtlA5_cLc1ELc2EEtlS1_EtlS1_Lc11ELc12ELc13ELc14EEEEE" } }
typedef Y<C{ "\1\2", "", {11,12,13,14} }> Tcs;
void h (Tcs) { }
// { dg-final { scan-assembler "_Z1h1YIXtl1CtlA5_cLc1ELc2EEtlS1_EtlS1_Lc11ELc12ELc13ELc14EEEEE" } }
struct S { signed char a[5], b[5], c[5]; };
template <S> struct Z { };
typedef Z<S{ {1,2}, {}, {11,12,13,14} }> Tsc;
void i (Tsc) { }
// { dg-final { scan-assembler "_Z1i1ZIXtl1StlA5_aLa1ELa2EEtlS1_EtlS1_La11ELa12ELa13ELa14EEEEE" } }

View File

@ -0,0 +1,28 @@
// Verify manglinng of class literals of types with ctors.
// { dg-do compile { target c++2a } }
struct A
{
char i;
constexpr A (): i (1) { }
constexpr A (int i): i (i) { }
};
struct B { A a[3]; };
template <B> struct X { };
void f___ (X<B{{ }}>) { }
// { dg-final { scan-assembler "_Z4f___1XIXtl1BtlA3_1AtlS1_Lc1EEEEEE" } }
void f0__ (X<B{{ 0 }}>) { }
// { dg-final { scan-assembler "_Z4f0__1XIXtl1BtlA3_1AtlS1_Lc0EEtlS1_Lc1EEEEEE" } }
void f00_ (X<B{{ 0, 0 }}>) { }
// { dg-final { scan-assembler "_Z4f00_1XIXtl1BtlA3_1AtlS1_Lc0EEtlS1_Lc0EEtlS1_Lc1EEEEEE" } }
void f000 (X<B{{ 0, 0, 0 }}>) { }
// { dg-final { scan-assembler "_Z4f0001XIXtl1BtlA3_1AtlS1_Lc0EEtlS1_Lc0EEtlS1_Lc0EEEEEE" } }
void f1__ (X<B{{ 1 }}>) { }
// { dg-final { scan-assembler "_Z4f1__1XIXtl1BtlA3_1AtlS1_Lc1EEtlS1_Lc1EEEEEE" } }

View File

@ -0,0 +1,106 @@
// Verify manglinng of class literals with pointers to members.
// Some of the mangling here is wrong. Note the FIXME comments below.
// { dg-do compile { target c++2a } }
struct A { int a[2]; };
template <A> struct X { };
// Let's mangle some non-member pointer literals for comparison.
void f__ (X<A{{ }}>) { }
// { dg-final { scan-assembler "_Z3f001XIXtl1AEEE" } }
void f0_ (X<A{{ 0 }}>) { }
// { dg-final { scan-assembler "_Z3f0_1XIXtl1AEEE" } }
void f00 (X<A{{ 0, 0 }}>) { }
// { dg-final { scan-assembler "_Z3f__1XIXtl1AEEE" } }
// Exercise arrays of pointers to data members.
typedef int (A::*padm_t)[2];
struct B { padm_t a[2]; };
template <B> struct Y { };
void g__ (Y<B{{ }}>) { }
// { dg-final { scan-assembler "_Z3g__1YIXtl1BtlA2_M1AA2_iLS3_0EEEEE" } }
void g0_ (Y<B{{ 0 }}>) { }
// { dg-final { scan-assembler "_Z3g0_1YIXtl1BtlA2_M1AA2_iLS3_0EEEEE" } }
void g00 (Y<B{{ 0, 0 }}>) { }
// { dg-final { scan-assembler "_Z3g001YIXtl1BtlA2_M1AA2_iLS3_0EEEEE" } }
void g0x (Y<B{{ 0, &A::a }}>) { }
// FIXME: This needs to mangle differently from g00. The space at
// the end is intentional to make the directive fail so that the xfail
// can be reminder to change this once the mangling is fixed.
// { dg-final { scan-assembler "_Z3g0x1YIXtl1BtlA2_M1AA2_iLS3_0EEEEE " { xfail *-*-* } } }
void gx_ (Y<B{{ &A::a }}>) { }
// { dg-final { scan-assembler "_Z3gx_1YIXtl1BtlA2_M1AA2_iLS3_0ELS3_0EEEEE" } }
struct C { padm_t a[3]; };
template <C> struct Z { };
void h___ (Z<C{{ }}>) { }
// { dg-final { scan-assembler "_Z4h___1ZIXtl1CtlA3_M1AA2_iLS3_0EEEEE" } }
void h0__ (Z<C{{ 0 }}>) { }
// { dg-final { scan-assembler "_Z4h0__1ZIXtl1CtlA3_M1AA2_iLS3_0EEEEE" } }
void h00_ (Z<C{{ 0, 0 }}>) { }
// { dg-final { scan-assembler "_Z4h00_1ZIXtl1CtlA3_M1AA2_iLS3_0EEEEE" } }
void h000 (Z<C{{ 0, 0, 0 }}>) { }
// { dg-final { scan-assembler "_Z4h0001ZIXtl1CtlA3_M1AA2_iLS3_0EEEEE" } }
void h00x (Z<C{{ 0, 0, &A::a }}>) { }
// FIXME: This needs to mangle differently from hx0_ and hx__.
// { dg-final { scan-assembler "_Z4h00x1ZIXtl1CtlA3_M1AA2_iLS3_0ELS3_0EEEEE " { xfail *-*-*} } }
void h0x0 (Z<C{{ 0, &A::a, 0 }}>) { }
// { dg-final { scan-assembler "_Z4h0x01ZIXtl1CtlA3_M1AA2_iLS3_0ELS3_0ELS3_0EEEEE" } }
void h0x_ (Z<C{{ 0, &A::a }}>) { }
// { dg-final { scan-assembler "_Z4h0x_1ZIXtl1CtlA3_M1AA2_iLS3_0ELS3_0ELS3_0EEEEE" } }
void hx0_ (Z<C{{ &A::a, 0 }}>) { }
// FIXME: This needs to mangle differently from h00x and hx__.
// { dg-final { scan-assembler "_Z4hx0_1ZIXtl1CtlA3_M1AA2_iLS3_0ELS3_0EEEEE " { xfail *-*-*} } }
void hx__ (Z<C{{ &A::a }}>) { }
// FIXME: This needs to mangle differently from h00x and hx0_.
// { dg-final { scan-assembler "_Z4hx__1ZIXtl1CtlA3_M1AA2_iLS3_0ELS3_0EEEEE " { xfail *-*-* } } }
// Exercise arrays of pointers to function members.
struct AF { void f (); };
typedef void (AF::*pafm_t)();
struct D { pafm_t a[2]; };
template <D> struct F { };
void k__ (F<D{{ }}>) { }
// { dg-final { scan-assembler "_Z3k__1FIXtl1DEEE" } }
void k0_ (F<D{{ 0 }}>) { }
// { dg-final { scan-assembler "_Z3k0_1FIXtl1DEEE" } }
void k00 (F<D{{ 0, 0 }}>) { }
// { dg-final { scan-assembler "_Z3k001FIXtl1DEEE" } }
void k0x (F<D{{ 0, &AF::f }}>) { }
// { dg-final { scan-assembler "_Z3k0x1FIXtl1DtlA2_M2AFFvvEtlS3_EtlS3_adL_ZNS1_1fEvEEEEEE" } }
void kx_ (F<D{{ &AF::f }}>) { }
// { dg-final { scan-assembler "_Z3kx_1FIXtl1DtlA2_M2AFFvvEtlS3_adL_ZNS1_1fEvEEEEEE" } }
void kx0 (F<D{{ &AF::f, 0 }}>) { }
// { dg-final { scan-assembler "_Z3kx01FIXtl1DtlA2_M2AFFvvEtlS3_adL_ZNS1_1fEvEEEEEE" } }
void kxx (F<D{{ &AF::f, &AF::f }}>) { }
// { dg-final { scan-assembler "_Z3kxx1FIXtl1DtlA2_M2AFFvvEtlS3_adL_ZNS1_1fEvEEtlS3_adL_ZNS1_1fEvEEEEEE" } }

View File

@ -0,0 +1,137 @@
// PR c++/89833
// Test to verify that constant array elements initialized to zero
// evaluate to zero regardless of the form of their initilizer,
// and irrespective whether it's explicit or implicit.
// { dg-do compile { target c++11 } }
// { dg-options "-Wall" }
static const char all_zero[1024] = { };
namespace test_int
{
constexpr int a[][3] = { { 0, 0 }, { 0 }, { } };
static_assert (sizeof a == sizeof (int) * 3 * 3);
static_assert ( a[0][0] == 0 && a[0][1] == 0 && a[0][2] == 0
&& a[1][0] == 0 && a[1][1] == 0 && a[1][2] == 0
&& a[2][0] == 0 && a[2][1] == 0 && a[2][2] == 0);
constexpr int b[3][3] = { { 0, 0 }, { 0 } };
static_assert (sizeof b == sizeof (int) * 3 * 3);
static_assert ( b[0][0] == 0 && b[0][1] == 0 && b[0][2] == 0
&& b[1][0] == 0 && b[1][1] == 0 && b[1][2] == 0
&& b[2][0] == 0 && b[2][1] == 0 && b[2][2] == 0);
constexpr int c[3][3] = { { } };
static_assert (sizeof c == sizeof (int) * 3 * 3);
static_assert ( c[0][0] == 0 && c[0][1] == 0 && c[0][2] == 0
&& c[1][0] == 0 && c[1][1] == 0 && c[1][2] == 0
&& c[2][0] == 0 && c[2][1] == 0 && c[2][2] == 0);
}
namespace test_char
{
constexpr char a[][3] = { { 0, 0 }, { 0 }, { } };
static_assert (sizeof a == sizeof (char) * 3 * 3);
static_assert ( a[0][0] == 0 && a[0][1] == 0 && a[0][2] == 0
&& a[1][0] == 0 && a[1][1] == 0 && a[1][2] == 0
&& a[2][0] == 0 && a[2][1] == 0 && a[2][2] == 0);
constexpr char b[3][3] = { { 0, 0 }, { 0 } };
static_assert (sizeof b == sizeof (char) * 3 * 3);
static_assert ( b[0][0] == 0 && b[0][1] == 0 && b[0][2] == 0
&& b[1][0] == 0 && b[1][1] == 0 && b[1][2] == 0
&& b[2][0] == 0 && b[2][1] == 0 && b[2][2] == 0);
constexpr char c[3][3] = { { } };
static_assert (sizeof c == sizeof (char) * 3 * 3);
static_assert ( c[0][0] == 0 && c[0][1] == 0 && c[0][2] == 0
&& c[1][0] == 0 && c[1][1] == 0 && c[1][2] == 0
&& c[2][0] == 0 && c[2][1] == 0 && c[2][2] == 0);
}
namespace test_string
{
constexpr char a[][3] = { "\0", "", { } };
static_assert (sizeof a == sizeof (char) * 3 * 3);
static_assert ( a[0][0] == 0 && a[0][1] == 0 && a[0][2] == 0
&& a[1][0] == 0 && a[1][1] == 0 && a[1][2] == 0
&& a[2][0] == 0 && a[2][1] == 0 && a[2][2] == 0);
constexpr char b[3][3] = { "\0", "" };
static_assert (sizeof b == sizeof (char) * 3 * 3);
static_assert ( b[0][0] == 0 && b[0][1] == 0 && b[0][2] == 0
&& b[1][0] == 0 && b[1][1] == 0 && b[1][2] == 0
&& b[2][0] == 0 && b[2][1] == 0 && b[2][2] == 0);
constexpr char c[3][3] = { };
static_assert (sizeof c == sizeof (char) * 3 * 3);
static_assert ( c[0][0] == 0 && c[0][1] == 0 && c[0][2] == 0
&& c[1][0] == 0 && c[1][1] == 0 && c[1][2] == 0
&& c[2][0] == 0 && c[2][1] == 0 && c[2][2] == 0);
}
namespace test_string_member
{
struct B { struct A { char a[5]; } a[2]; };
constexpr B b[3] =
{
/* [0] */
{
/* a = */
{
/* a[0] */ { { 0, 0, 0, 0, 0 } },
/* a[1] */ { { 0, 0 } }
}
},
/* [1] */
{
/* a */
{
/* a[0] */ { "\0\0\0\0" },
/* a[0] */ { "" }
}
},
};
static_assert ( b[0].a[0].a[0] == 0
&& b[0].a[0].a[1] == 0
&& b[0].a[0].a[2] == 0
&& b[0].a[0].a[3] == 0
&& b[0].a[0].a[4] == 0
&& b[0].a[1].a[0] == 0
&& b[0].a[1].a[1] == 0
&& b[0].a[1].a[2] == 0
&& b[0].a[1].a[3] == 0
&& b[0].a[1].a[4] == 0
&& b[1].a[0].a[0] == 0
&& b[1].a[0].a[1] == 0
&& b[1].a[0].a[2] == 0
&& b[1].a[0].a[3] == 0
&& b[1].a[0].a[4] == 0
&& b[2].a[0].a[0] == 0
&& b[2].a[0].a[1] == 0
&& b[2].a[0].a[2] == 0
&& b[2].a[0].a[3] == 0
&& b[2].a[0].a[4] == 0);
}

View File

@ -0,0 +1,222 @@
// PR c++/89833
// Test to verify that the same specializations on non-type template
// parameters of class types are in fact treated as the same.
// { dg-do compile { target c++2a } }
struct A1 { char c[5]; };
template <A1> struct B { };
// All of the following name the same type.
typedef B<A1{ }> A______;
typedef B<A1{ { 0 } }> A_Z____;
typedef B<A1{ { 0, 0 } }> A_ZZ___;
typedef B<A1{ { 0, 0, 0 } }> A_ZZZ__;
typedef B<A1{ { 0, 0, 0, 0 } }> A_ZZZZ_;
typedef B<A1{ { 0, 0, 0, 0, 0 } }> A_ZZZZZ;
// Verify the types are indeed the same by redeclaring the same identifier
// of each of them.
extern A______ same_type_B_A1;
extern A_Z____ same_type_B_A1;
extern A_ZZ___ same_type_B_A1;
extern A_ZZZ__ same_type_B_A1;
extern A_ZZZZ_ same_type_B_A1;
extern A_ZZZZZ same_type_B_A1;
// All of the following use a string to initialize the array but
// also name the same type as the above.
typedef B<A1{ "" }> S_z____;
typedef B<A1{ "\0" }> S_Zz___;
typedef B<A1{ "\0\0" }> S_ZZz__;
typedef B<A1{ "\0\0\0" }> S_ZZZz_;
typedef B<A1{ "\0\0\0\0" }> S_ZZZZz;
// Verify the types are indeed the same by redeclaring the same identifier
// of each of them.
extern S_z____ same_type_B_A1;
extern S_Zz___ same_type_B_A1;
extern S_Zz___ same_type_B_A1;
extern S_ZZz__ same_type_B_A1;
extern S_ZZZz_ same_type_B_A1;
extern S_ZZZZz same_type_B_A1;
// All of the following also name the same type (distinct from
// the above).
typedef B<A1{ { 'A' } }> A_A____;
typedef B<A1{ { 'A', 0 } }> A_AZ___;
typedef B<A1{ { 'A', 0, 0 } }> A_AZZ__;
typedef B<A1{ { 'A', 0, 0, 0 } }> A_AZZZ_;
typedef B<A1{ { 'A', 0, 0, 0, 0 } }> A_AZZZZ;
extern A_A____ same_type_B_A1_A;
extern A_AZ___ same_type_B_A1_A;
extern A_AZZ__ same_type_B_A1_A;
extern A_AZZZ_ same_type_B_A1_A;
extern A_AZZZZ same_type_B_A1_A;
struct A3 { char a[5], b[5], c[5]; };
template <A3> struct B3 { };
// These all name the same type.
typedef B3<A3{ }> B3_A3________________;
typedef B3<A3{ { } }> B3_A3________________;
typedef B3<A3{ { }, { } }> B3_A3________________;
typedef B3<A3{ { }, { }, { } }> B3_A3________________;
typedef B3<A3{ { 0 }, { }, { } }> B3_A3________________;
typedef B3<A3{ { 0 }, { 0 }, { } }> B3_A3________________;
typedef B3<A3{ { 0 }, { 0 }, { 0 } }> B3_A3________________;
typedef B3<A3{ { 0, 0 }, { 0 }, { 0 } }> B3_A3________________;
typedef B3<A3{ { 0, 0 }, { 0, 0 }, { 0 } }> B3_A3________________;
typedef B3<A3{ { 0, 0 }, { 0, 0 }, { 0, 0 } }> B3_A3________________;
// These all name the same type.
typedef B3<A3{ "AB", { }, "IJKL" }> B3_A3_AB________IJKL_;
typedef B3<A3{ "AB", { 0 }, "IJKL" }> B3_A3_AB________IJKL_;
typedef B3<A3{ "AB", { 0, 0 }, "IJKL" }> B3_A3_AB________IJKL_;
typedef B3<A3{ "AB", { 0, 0, 0 }, "IJKL" }> B3_A3_AB________IJKL_;
typedef B3<A3{ "AB", { 0, 0, 0, 0 }, "IJKL" }> B3_A3_AB________IJKL_;
typedef B3<A3{ "AB", "", "IJKL" }> B3_A3_AB________IJKL_;
typedef B3<A3{ "AB", "\0", "IJKL" }> B3_A3_AB________IJKL_;
typedef B3<A3{ "AB", "\0\0", "IJKL" }> B3_A3_AB________IJKL_;
typedef B3<A3{ "AB", "\0\0\0", "IJKL" }> B3_A3_AB________IJKL_;
typedef B3<A3{ "AB", "\0\0\0\0", "IJKL" }> B3_A3_AB________IJKL_;
typedef B3<A3{ "AB\0", "\0\0\0\0", "IJKL" }> B3_A3_AB________IJKL_;
typedef B3<A3{ "AB\0\0", "\0\0\0\0", "IJKL" }> B3_A3_AB________IJKL_;
// Types with the same name must be the same (and so redefinitions
// must be accepted). Likewise, overloads on distinct types must
// be accepted.
typedef B3<A3{ {0,0,0,0,0}, {0,0,0,0,0}, {0,0,0,0,0} }> B3_A3________________;
typedef B3<A3{ {0,0,0,0,0}, {0,0,0,0,0}, {0} }> B3_A3________________;
typedef B3<A3{ {0,0,0,0,0}, {0,0,0,0,0}, {} }> B3_A3________________;
typedef B3<A3{ {0,0,0,0,0}, {0}, {} }> B3_A3________________;
typedef B3<A3{ {0,0,0,0,0}, {}, {} }> B3_A3________________;
typedef B3<A3{ {0}, {0}, {0} }> B3_A3________________;
typedef B3<A3{ {0}, {0}, {} }> B3_A3________________;
typedef B3<A3{ {0}, {}, {0} }> B3_A3________________;
typedef B3<A3{ {}, {}, {} }> B3_A3________________;
typedef B3<A3{ {}, {} }> B3_A3________________;
typedef B3<A3{ {} }> B3_A3________________;
typedef B3<A3{ }> B3_A3________________;
typedef B3<A3{ {0,0,0,0,0}, {0,0,0,0,0}, {0,0,0,0,1} }> B3_A3_______________1;
typedef B3<A3{ {0,0,0,0,0}, {0,0,0,0}, {0,0,0,0,1} }> B3_A3_______________1;
typedef B3<A3{ {0,0,0,0,0}, {0,0,0}, {0,0,0,0,1} }> B3_A3_______________1;
typedef B3<A3{ {0,0,0,0,0}, {0,0}, {0,0,0,0,1} }> B3_A3_______________1;
typedef B3<A3{ {0,0,0,0,0}, {0}, {0,0,0,0,1} }> B3_A3_______________1;
typedef B3<A3{ {0,0,0,0,0}, {}, {0,0,0,0,1} }> B3_A3_______________1;
typedef B3<A3{ {0,0,0,0}, {0,0,0,0,0}, {0,0,0,0,1} }> B3_A3_______________1;
typedef B3<A3{ {0,0,0}, {0,0,0,0}, {0,0,0,0,1} }> B3_A3_______________1;
typedef B3<A3{ {0,0}, {0,0,0}, {0,0,0,0,1} }> B3_A3_______________1;
typedef B3<A3{ {0}, {0,0,}, {0,0,0,0,1} }> B3_A3_______________1;
typedef B3<A3{ {}, {0}, {0,0,0,0,1} }> B3_A3_______________1;
typedef B3<A3{ {}, {}, {0,0,0,0,1} }> B3_A3_______________1;
typedef B3<A3{ {0,0,0}, {0,0}, {0,0,0,1,0} }> B3_A3______________1_;
typedef B3<A3{ {0,0,0}, {0,0}, {0,0,0,1} }> B3_A3______________1_;
typedef B3<A3{ {0}, {}, {0,0,1,0} }> B3_A3_____________1__;
typedef B3<A3{ {0}, {}, {0,0,1} }> B3_A3_____________1__;
typedef B3<A3{ {0,0,0,0,0}, {0,0,0,0,0}, {0,1,0} }> B3_A3____________1___;
typedef B3<A3{ {0,0,0,0,0}, {0,0,0,0,0}, {0,1} }> B3_A3____________1___;
typedef B3<A3{ {0,0,0,0,0}, {0,0,0,0,0}, {1} }> B3_A3___________1____;
typedef B3<A3{ {0,0,0,0,0}, {0,0,0,0,1}, {0,0,0,0,0} }> B3_A3__________1_____;
typedef B3<A3{ {0,0,0,0,0}, {0,0,0,0,1}, {} }> B3_A3__________1_____;
typedef B3<A3{ {0,0,0,0,0}, {0,0,0,0,1} }> B3_A3__________1_____;
typedef B3<A3{ {0,0,0,0,0}, {0,0,0,1,0}, {0,0,0,0,0} }> B3_A3_________1______;
typedef B3<A3{ {0,0,0,0,0}, {0,0,1,0,0}, {0,0,0,0,0} }> B3_A3________1_______;
typedef B3<A3{ {0,0,0,0,0}, {0,1,0,0,0}, {0,0,0,0,0} }> B3_A3_______1________;
typedef B3<A3{ {0,0,0,0,0}, {1,0,0,0,0}, {0,0,0,0,0} }> B3_A3______1_________;
typedef B3<A3{ {0,0,0,0,1}, {0,0,0,0,0}, {0,0,0,0,0} }> B3_A3_____1__________;
typedef B3<A3{ {0,0,0,0,1}, {0,0,0,0,0} }> B3_A3_____1__________;
typedef B3<A3{ {0,0,0,0,1} }> B3_A3_____1__________;
typedef B3<A3{ {0,0,0,1,0}, {0,0,0,0,0}, {0,0,0,0,0} }> B3_A3____1___________;
typedef B3<A3{ {0,0,1,0,0}, {0,0,0,0,0}, {0,0,0,0,0} }> B3_A3___1____________;
typedef B3<A3{ {0,1,0,0,0}, {0,0,0,0,0}, {0,0,0,0,0} }> B3_A3__1_____________;
typedef B3<A3{ {1,0,0,0,0}, {0,0,0,0,0}, {0,0,0,0,0} }> B3_A3_1______________;
typedef B3<A3{ {1,0,0,0,0}, {0,0,0,0,0} }> B3_A3_1______________;
typedef B3<A3{ {1,0,0,0,0} }> B3_A3_1______________;
typedef B3<A3{ {1,0,0,0} }> B3_A3_1______________;
typedef B3<A3{ {1,0,0} }> B3_A3_1______________;
typedef B3<A3{ {1,0} }> B3_A3_1______________;
typedef B3<A3{ {1} }> B3_A3_1______________;
typedef B3<A3{ {1,0,0,0,0}, {0,0,0,0,0}, {0,0,0,0,1} }> B3_A3_1_____________1;
typedef B3<A3{ {1}, {0}, {0,0,0,0,1} }> B3_A3_1_____________1;
typedef B3<A3{ {1}, {}, {0,0,0,0,1} }> B3_A3_1_____________1;
typedef B3<A3{ {0,1,0,0,0}, {0,0,0,0,0}, {0,0,0,1} }> B3_A3__1___________1_;
typedef B3<A3{ {0,1}, {0}, {0,0,0,1} }> B3_A3__1___________1_;
typedef B3<A3{ {0,1}, {}, {0,0,0,1} }> B3_A3__1___________1_;
// Same as above.
typedef B3<A3{ "\0\0\0\0", "\0\0\0\0", "\0\0\0\0" }> B3_A3________________;
typedef B3<A3{ "\0\0\0\0", "\0\0\0\0", "\0\0\0" }> B3_A3________________;
typedef B3<A3{ "\0\0\0\0", "\0\0\0\0", "\0\0" }> B3_A3________________;
typedef B3<A3{ "\0\0\0\0", "\0\0\0\0", "\0" }> B3_A3________________;
typedef B3<A3{ "\0\0\0\0", "\0\0\0\0", "" }> B3_A3________________;
typedef B3<A3{ "\0\0\0\0", "\0\0\0", "" }> B3_A3________________;
typedef B3<A3{ "\0\0\0\0", "\0\0", "" }> B3_A3________________;
typedef B3<A3{ "\0\0\0\0", "\0", "" }> B3_A3________________;
typedef B3<A3{ "\0\0\0\0", "", "" }> B3_A3________________;
typedef B3<A3{ "\0\0\0", "", "" }> B3_A3________________;
typedef B3<A3{ "\0\0", "", "" }> B3_A3________________;
typedef B3<A3{ "\0", "", "" }> B3_A3________________;
typedef B3<A3{ "", "", "" }> B3_A3________________;
typedef B3<A3{ "", "" }> B3_A3________________;
typedef B3<A3{ "" }> B3_A3________________;
typedef B3<A3{ "\0\0\0\0", "\0\0\0", { 0 } }> B3_A3________________;
typedef B3<A3{ "\0\0", { 0 }, "\0" }> B3_A3________________;
typedef B3<A3{ { 0 }, "", "\0\0\0\0" }> B3_A3________________;
typedef B3<A3{ "\0\0\0", "\0\0", { } }> B3_A3________________;
typedef B3<A3{ "\0", { }, "" }> B3_A3________________;
typedef B3<A3{ { }, "\0\0\0\0", "\0\0\0" }> B3_A3________________;
typedef B3<A3{ "\0\0\0\0", "\0\0\0", {0,0,0,0,1} }> B3_A3_______________1;
typedef B3<A3{ "\0\0", "\0", "\0\0\0\1" }> B3_A3______________1_;
typedef B3<A3{ "\0\0\0\0", "\0\0\0", "\0\0\1" }> B3_A3_____________1__;
typedef B3<A3{ "\0\0", "\0", "\0\1" }> B3_A3____________1___;
typedef B3<A3{ "\0\0\0\0", "\0\0\0", "\1" }> B3_A3___________1____;
typedef B3<A3{ "\0\0", {0,0,0,0,1}, "\0" }> B3_A3__________1_____;
typedef B3<A3{ "\0\0\0\0", "\0\0\0\1", "\0\0\0" }> B3_A3_________1______;
typedef B3<A3{ "\0\0", "\0\0\1", "\0" }> B3_A3________1_______;
typedef B3<A3{ "\0\0\0\0", "\0\1", "\0\0\0" }> B3_A3_______1________;
typedef B3<A3{ "\0\0", "\1", "\0" }> B3_A3______1_________;
typedef B3<A3{ {0,0,0,0,1}, "\0\0\0\0", "\0\0\0" }> B3_A3_____1__________;
typedef B3<A3{ "\0\0\0\1", "\0\0", "\0" }> B3_A3____1___________;
typedef B3<A3{ "\0\0\1", "\0\0\0\0", "\0\0\0" }> B3_A3___1____________;
typedef B3<A3{ "\0\1", "\0\0", "\0" }> B3_A3__1_____________;
typedef B3<A3{ "\1", "", "\0\0\0\0" }> B3_A3_1______________;
typedef B3<A3{ "\1", {}, {0,0,0,0,1} }> B3_A3_1_____________1;
typedef B3<A3{ "\1", "", {0,0,0,0,1} }> B3_A3_1_____________1;
typedef B3<A3{ "\0\1", {}, {0,0,0,1} }> B3_A3__1___________1_;
typedef B3<A3{ "\0\1", "", "\0\0\0\1" }> B3_A3__1___________1_;
typedef B3<A3{ "\0\1\0", "\0", "\0\0\0\1" }> B3_A3__1___________1_;
void f_b3_a3 (B3_A3________________) { }
void f_b3_a3 (B3_A3_______________1) { }
void f_b3_a3 (B3_A3______________1_) { }
void f_b3_a3 (B3_A3_____________1__) { }
void f_b3_a3 (B3_A3____________1___) { }
void f_b3_a3 (B3_A3___________1____) { }
void f_b3_a3 (B3_A3__________1_____) { }
void f_b3_a3 (B3_A3_________1______) { }
void f_b3_a3 (B3_A3________1_______) { }
void f_b3_a3 (B3_A3_______1________) { }
void f_b3_a3 (B3_A3______1_________) { }
void f_b3_a3 (B3_A3_____1__________) { }
void f_b3_a3 (B3_A3____1___________) { }
void f_b3_a3 (B3_A3___1____________) { }
void f_b3_a3 (B3_A3__1_____________) { }
void f_b3_a3 (B3_A3_1______________) { }
void f_b3_a3 (B3_A3_1_____________1) { }
void f_b3_a3 (B3_A3__1___________1_) { }
typedef B3<A3{ "AB\0D", { }, "IJKL" }> B3_A3_ABZDZZZZZZIJKLZ;
typedef B3<A3{ "AB\0D", { 0, 0, 1 }, "IJKL" }> B3_A3_ABZDZZZ1ZZIJKLZ;
typedef B3<A3{ "AB\0D", { 0, 1 }, "IJKL" }> B3_A3_ABZDZZ1ZZZIJKLZ;
void f (B3_A3_ABZDZZZZZZIJKLZ) { }
void f (B3_A3_ABZDZZZ1ZZIJKLZ) { }
void f (B3_A3_ABZDZZ1ZZZIJKLZ) { }

View File

@ -0,0 +1,57 @@
// PR c++/89833
// Test to verify that arrays of null pointer to members used as
// non-type template arguments are interprested as null regardless
// of the form of their initialization.
// { dg-do compile { target c++2a } }
// { dg-options "-O2 -Wall -fdump-tree-optimized" }
struct A { int i; };
typedef int A::*pam_t;
struct B { pam_t a[2]; };
template <B x> struct C { static constexpr B b = x; };
B f__ () { return B{ }; }
B f0_ () { return B{ 0 }; }
B f00 () { return B{ 0, 0 }; }
typedef C<B{ }> X__;
typedef C<B{ 0 }> X0_;
typedef C<B{ 0, 0 }> X00;
B g__ () { return X__::b; }
B g0_ () { return X0_::b; }
B g00 () { return X00::b; }
const B b__{ };
const B b0_{ 0 };
const B b00{ 0, 0 };
const pam_t apam__[2] = { };
const pam_t apam0_[2] = { 0 };
const pam_t apam00[2] = { 0, 0 };
#define assert(expr) \
(expr) ? (void)0 : __builtin_abort ()
void test ()
{
assert (f__ ().a[0] == nullptr && f__ ().a[1] == nullptr);
assert (f0_ ().a[0] == nullptr && f0_ ().a[1] == nullptr);
assert (f00 ().a[0] == nullptr && f00 ().a[1] == nullptr);
assert (g__ ().a[0] == nullptr && g__ ().a[1] == nullptr);
assert (g0_ ().a[0] == nullptr && g0_ ().a[1] == nullptr);
assert (g00 ().a[0] == nullptr && g00 ().a[1] == nullptr);
assert (b__.a[0] == nullptr && b__.a[1] == nullptr);
assert (b0_.a[0] == nullptr && b0_.a[1] == nullptr);
assert (b00.a[0] == nullptr && b00.a[1] == nullptr);
assert (apam__[0] == nullptr && apam__[1] == nullptr);
assert (apam0_[0] == nullptr && apam0_[1] == nullptr);
assert (apam00[0] == nullptr && apam00[1] == nullptr);
}
// { dg-final { scan-tree-dump-not "abort" "optimized" } }

View File

@ -0,0 +1,86 @@
// PR c++/89833
// Anal test to verify that arrays of null pointer to members are
// treated as null regardless of the form of their initialization,
// and have all bits set in their representation.
// { dg-do run { target c++11 } }
// { dg-options "-O2 -Wall" }
#define NOIPA __attribute__ ((noipa))
struct A { int i; };
typedef int A::*pam_t;
pam_t apam__[2] = { };
pam_t apam0_[2] = { 0 };
pam_t apam00[2] = { 0, 0 };
struct B { pam_t a[2]; };
NOIPA B f__ () { return B{ }; }
NOIPA B f0_ () { return B{ 0 }; }
NOIPA B f00 () { return B{ 0, 0 }; }
const B c__{ };
const B c0_{ 0 };
const B c00{ 0, 0 };
B b__{ };
B b0_{ 0 };
B b00{ 0, 0 };
#define assert(expr) \
(expr) ? (void)0 : __builtin_abort ()
signed char allones[2 * sizeof (pam_t)];
#define assert_rep(mp, n) \
assert (!test_allones (mp, n))
NOIPA void init_allones ()
{
__builtin_memset (allones, -1, sizeof allones);
}
NOIPA int test_allones (const pam_t *p, unsigned n)
{
return __builtin_memcmp (allones, p, sizeof *p * n);
}
int main ()
{
init_allones ();
assert (apam__[0] == nullptr && apam__[1] == nullptr);
assert (apam0_[0] == nullptr && apam0_[1] == nullptr);
assert (apam00[0] == nullptr && apam00[1] == nullptr);
assert (f__ ().a[0] == nullptr && f__ ().a[1] == nullptr);
assert (f0_ ().a[0] == nullptr && f0_ ().a[1] == nullptr);
assert (f00 ().a[0] == nullptr && f00 ().a[1] == nullptr);
assert (b__.a[0] == nullptr && b__.a[1] == nullptr);
assert (b0_.a[0] == nullptr && b0_.a[1] == nullptr);
assert (b00.a[0] == nullptr && b00.a[1] == nullptr);
assert (c__.a[0] == nullptr && c__.a[1] == nullptr);
assert (c0_.a[0] == nullptr && c0_.a[1] == nullptr);
assert (c00.a[0] == nullptr && c00.a[1] == nullptr);
assert_rep (apam__, 2);
assert_rep (apam0_, 2);
assert_rep (apam00, 2);
assert_rep (f__ ().a, 2);
assert_rep (f0_ ().a, 2);
assert_rep (f0_ ().a, 2);
assert_rep (f00 ().a, 2);
assert_rep (b__.a, 2);
assert_rep (b0_.a, 2);
assert_rep (b00.a, 2);
assert_rep (c__.a, 2);
assert_rep (c0_.a, 2);
assert_rep (c00.a, 2);
}

View File

@ -0,0 +1,81 @@
// PR c++/47488 - sorry, unimplemented: string literal in function
// template signature
// { dg-do compile }
// { dg-options "-Wall" }
#if __cpluspls >= 201103L
// C++ 11 test case from comment #0.
namespace comment_0 {
template <typename T>
int f (const T&, const char *);
template <typename T>
decltype (f (T (), "")) g (const T &);
void h ()
{
g (0);
}
} // comment_0
#endif
// C++ 98 test case from comment #1.
namespace comment_1 {
template <typename T>
int f(const T&, const char *);
template<int> struct N { };
template <typename T>
N<sizeof (f (T (), ""))> g (const T&);
void h ()
{
g (0);
}
} // comment_1
// C++ 98 test case from comment #2.
namespace comment_2 {
template <typename T>
int f (const char *);
template<int> struct N { };
template <typename T>
N<sizeof (f<T>(""))> g (const T &);
void h ()
{
g (0);
}
} // comment_2
#if __cpluspls >= 201103L
// C++ 11 test case from comment #5.
namespace comment_5 {
template <typename T> constexpr T f(const T* p) { return p[0]; }
template <int> struct N { };
template <typename T> void g (T, N<f((const T*)"1")>) { }
template <typename T> void g (T, N<f((const T*)"2")>) { }
void h ()
{
g ('1', N<'1'>());
g ('2', N<'2'>());
}
}
#endif