PR c++/89974 - ICE on a definition of a non-type specialization on a struct object...
authorMartin Sebor <msebor@redhat.com>
Thu, 4 Apr 2019 23:10:23 +0000 (23:10 +0000)
committerMartin Sebor <msebor@gcc.gnu.org>
Thu, 4 Apr 2019 23:10:23 +0000 (17:10 -0600)
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

13 files changed:
gcc/cp/ChangeLog
gcc/cp/decl.c
gcc/cp/mangle.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/abi/mangle69.C [new file with mode: 0644]
gcc/testsuite/g++.dg/abi/mangle70.C [new file with mode: 0644]
gcc/testsuite/g++.dg/abi/mangle71.C [new file with mode: 0644]
gcc/testsuite/g++.dg/abi/mangle72.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/constexpr-array19.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp2a/nontype-class15.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp2a/nontype-class16.C [new file with mode: 0644]
gcc/testsuite/g++.dg/init/array51.C [new file with mode: 0644]
gcc/testsuite/g++.dg/template/nontype29.C [new file with mode: 0644]

index 888b431e09949fd94549c66c83b1e25ad321b976..729b7732565629be07fbec81c2be3d1c6ab249ef 100644 (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.
index c46a39665bd9bb441eb2671acb2c3d909c05302b..400e1a274aa36804626d63eff8503de72b01a5b0 100644 (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;
 }
 
index f40c3e16c5d0d83029e1ebf51b52442394b6f352..a5fd66fe0de3ba9832d91290353e9ce2bc9b1717 100644 (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 ();
index 6954748fa156be58db5a768abaae5b1cf9b7395d..26c5637619fae1b87097f7a8b286dbbccc180cc9 100644 (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
diff --git a/gcc/testsuite/g++.dg/abi/mangle69.C b/gcc/testsuite/g++.dg/abi/mangle69.C
new file mode 100644 (file)
index 0000000..dea3eec
--- /dev/null
@@ -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" } }
diff --git a/gcc/testsuite/g++.dg/abi/mangle70.C b/gcc/testsuite/g++.dg/abi/mangle70.C
new file mode 100644 (file)
index 0000000..39c987d
--- /dev/null
@@ -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" } }
diff --git a/gcc/testsuite/g++.dg/abi/mangle71.C b/gcc/testsuite/g++.dg/abi/mangle71.C
new file mode 100644 (file)
index 0000000..cb9d7d3
--- /dev/null
@@ -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" } }
diff --git a/gcc/testsuite/g++.dg/abi/mangle72.C b/gcc/testsuite/g++.dg/abi/mangle72.C
new file mode 100644 (file)
index 0000000..656a0ca
--- /dev/null
@@ -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" } }
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-array19.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-array19.C
new file mode 100644 (file)
index 0000000..f7e5d35
--- /dev/null
@@ -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);
+}
diff --git a/gcc/testsuite/g++.dg/cpp2a/nontype-class15.C b/gcc/testsuite/g++.dg/cpp2a/nontype-class15.C
new file mode 100644 (file)
index 0000000..d684785
--- /dev/null
@@ -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) { }
diff --git a/gcc/testsuite/g++.dg/cpp2a/nontype-class16.C b/gcc/testsuite/g++.dg/cpp2a/nontype-class16.C
new file mode 100644 (file)
index 0000000..3afb5d2
--- /dev/null
@@ -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" } }
diff --git a/gcc/testsuite/g++.dg/init/array51.C b/gcc/testsuite/g++.dg/init/array51.C
new file mode 100644 (file)
index 0000000..2a90088
--- /dev/null
@@ -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);
+}
diff --git a/gcc/testsuite/g++.dg/template/nontype29.C b/gcc/testsuite/g++.dg/template/nontype29.C
new file mode 100644 (file)
index 0000000..18a3058
--- /dev/null
@@ -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