This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH] fix #69251 - [6 Regression] ICE in unify_array_domain on a flexible array member


On 02/02/2016 05:28 AM, Jason Merrill wrote:
On 01/25/2016 05:55 PM, Martin Sebor wrote:
The downside of this approach is that it prevents everything but
the front end from distinguishing flexible array members from
arrays of unspecified or unknown bounds.  The immediate impact
is that prevents us from maintaining ABI compatibility with GCC
5 (with -fabi-version=9) and from diagnosing the mangling change.
This means should we decide to adopt this approach, the final
version of the patch for c++/69277 mentioned above that's still
pending approval will need to be tweaked to have the ABI checks
removed.

That's unfortunate, but I think acceptable.

    * decl.c (compute_array_index_type): Return null for flexible array
    members.

Instead of this, I would think we can remove the calls to
compute_array_index_type added by your earlier patch, as well as many
other changes from that patch to handle null TYPE_MAX_VALUE.

Yes, that's possible but it didn't seem essential at this stage.
I wanted to make only conservative changes to avoid any further
fallout.  I also wasn't sure whether the ABI issue above would
make this approach unviable.


    * tree.c (array_of_runtime_bound_p): Handle gracefully array types
    with null TYPE_MAX_VALUE.

This seems unneeded.

    (build_ctor_subob_ref): Loosen debug checking to handle flexible
    array members.

And this shouldn't need the TYPE_MAX_VALUE check.

I went ahead and made the requested changes.  They might seem
perfectly innocuous to you but the removal of the tests for
TYPE_MAX_VALUE(t) being null makes me nervous at this stage.
I'm not nearly comfortable enough with the code to be confident
that they're all 100% safe.  I defer to your better judgment
on this.

In the patch, I also corrected some transgressions against
the GNU formatting rules I introduced in the the original
change.

I've regtested the patch on x86_64.

Please let me know if this patch is good to commit.  In light
of his today's comment on bug 69277 I have the impression
Jakub would like to have the mangling change in the Fedora
mass rebuild or release and I don't want to hold that up.

Thanks
Martin
PR c++/69251 - [6 Regression] ICE in unify_array_domain on a flexible array
               member
PR c++/69253 - [6 Regression] ICE in cxx_incomplete_type_diagnostic initializing
               a flexible array member with empty string
PR c++/69290 - [6 Regression] ICE on invalid initialization of a flexible array
               member
PR c++/69277 - [6 Regression] ICE mangling a flexible array member
PR c++/69349 - template substitution error for flexible array members

gcc/testsuite/ChangeLog:
2016-02-02  Martin Sebor  <msebor@redhat.com>

	PR c++/69251
	PR c++/69253
	PR c++/69290
	PR c++/69277
	PR c++/69349
	* g++.dg/ext/flexarray-mangle-2.C: New test.
	* g++.dg/ext/flexarray-mangle.C: New test.
	* g++.dg/ext/flexarray-subst.C: New test.
	* g++.dg/ext/flexary11.C: New test.
	* g++.dg/ext/flexary12.C: New test.
	* g++.dg/ext/flexary13.C: New test.
	* g++.dg/ext/flexary14.C: New test.
	* g++.dg/other/dump-ada-spec-2.C: Adjust.

gcc/cp/ChangeLog:
2016-02-02  Martin Sebor  <msebor@redhat.com>

	PR c++/69251
	PR c++/69253
	PR c++/69290
	PR c++/69277
	PR c++/69349
	* class.c (walk_subobject_offsets): Avoid testing the upper bound
	of a flexible array member for equality to null.
	(find_flexarrays): Remove spurious whitespace introduced in r231665.
	(diagnose_flexarrays): Avoid checking the upper bound of arrays.
	(check_flexarrays): Same.
	* decl.c (compute_array_index_type): Avoid special case for flexible
	array members.
	(grokdeclarator): Avoid calling compute_array_index_type for flexible
	array members.
	* error.c (dump_type_suffix): Revert changes introduced in r231665
	and rendered unnecessary by the changes above.
	* pt.c (tsubst):  Same.
	* tree.c (build_ctor_subob_ref): Handle flexible array members.
	* typeck2.c (digest_init_r): Revert changes introduced in r231665.
	(process_init_constructor_array): Same.
	(process_init_constructor_record): Same.

diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index 45d8a24..9876197 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -4120,9 +4120,8 @@ walk_subobject_offsets (tree type,
       /* Avoid recursing into objects that are not interesting.  */
       if (!CLASS_TYPE_P (element_type)
 	  || !CLASSTYPE_CONTAINS_EMPTY_CLASS_P (element_type)
-	  || !domain
-	  /* Flexible array members have no upper bound.  */
-	  || !TYPE_MAX_VALUE (domain))
+	  /* Flexible array members have a null domain.  */
+	  || !domain)
 	return 0;
 
       /* Step through each of the elements in the array.  */
@@ -6645,7 +6644,7 @@ find_flexarrays (tree t, flexmems_t *fmem)
       for (next = fld;
 	   (next = DECL_CHAIN (next))
 	     && TREE_CODE (next) != FIELD_DECL; );
-      
+
       tree fldtype = TREE_TYPE (fld);
       if (TREE_CODE (fld) != TYPE_DECL
 	  && RECORD_OR_UNION_TYPE_P (fldtype)
@@ -6672,22 +6671,20 @@ find_flexarrays (tree t, flexmems_t *fmem)
 	  /* Remember the first non-static data member.  */
 	  if (!fmem->first)
 	    fmem->first = fld;
-	  
+
 	  /* Remember the first non-static data member after the flexible
 	     array member, if one has been found, or the zero-length array
 	     if it has been found.  */
 	  if (!fmem->after && fmem->array)
 	    fmem->after = fld;
 	}
-	    
+
       /* Skip non-arrays.  */
       if (TREE_CODE (fldtype) != ARRAY_TYPE)
 	continue;
 
       /* Determine the upper bound of the array if it has one.  */
-      tree dom = TYPE_DOMAIN (fldtype);
-
-      if (dom && TYPE_MAX_VALUE (dom))
+      if (tree dom = TYPE_DOMAIN (fldtype))
 	{
 	  if (fmem->array)
 	    {
@@ -6710,14 +6707,13 @@ find_flexarrays (tree t, flexmems_t *fmem)
 	    {
 	      /* Replace the zero-length array if it's been stored and
 		 reset the after pointer.  */
-	      dom = TYPE_DOMAIN (TREE_TYPE (fmem->array));
-	      if (dom && TYPE_MAX_VALUE (dom))
+	      if (TYPE_DOMAIN (TREE_TYPE (fmem->array)))
 		{
 		  fmem->array = fld;
 		  fmem->after = NULL_TREE;
 		}
 	    }
-	  else	
+	  else
 	    fmem->array = fld;
 	}
     }
@@ -6737,8 +6733,7 @@ diagnose_flexarrays (tree t, const flexmems_t *fmem)
 
   const char *msg = 0;
 
-  const_tree dom = TYPE_DOMAIN (TREE_TYPE (fmem->array));
-  if (dom && TYPE_MAX_VALUE (dom))
+  if (TYPE_DOMAIN (TREE_TYPE (fmem->array)))
     {
       if (fmem->after)
 	msg = G_("zero-size array member %qD not at end of %q#T");
@@ -6770,7 +6765,7 @@ diagnose_flexarrays (tree t, const flexmems_t *fmem)
 	      inform (DECL_SOURCE_LOCATION (fmem->after),
 		      "next member %q#D declared here",
 		      fmem->after);
-	  
+
 	  inform (location_of (t), "in the definition of %q#T", t);
 	}
     }
@@ -6844,7 +6839,7 @@ check_flexarrays (tree t, flexmems_t *fmem /* = NULL */)
   find_flexarrays (t, fmem);
 
   if (fmem == &flexmems)
-    { 
+    {
       /* Issue diagnostics for invalid flexible and zero-length array members
 	 found in base classes or among the members of the current class.  */
       diagnose_flexarrays (t, fmem);
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 8da87d3..2c337bc 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -8645,10 +8645,9 @@ fold_sizeof_expr (tree t)
   return r;
 }
 
-/* Given the SIZE (i.e., number of elements) in an array, compute an
-   appropriate index type for the array.  When SIZE is null, the array
-   is a flexible array member.  If non-NULL, NAME is the name of
-   the entity being declared.  */
+/* Given the SIZE (i.e., number of elements) in an array, compute
+   an appropriate index type for the array.  If non-NULL, NAME is
+   the name of the entity being declared.  */
 
 tree
 compute_array_index_type (tree name, tree size, tsubst_flags_t complain)
@@ -8656,9 +8655,6 @@ compute_array_index_type (tree name, tree size, tsubst_flags_t complain)
   tree itype;
   tree osize = size;
 
-  if (size == NULL_TREE)
-    return build_index_type (NULL_TREE);
-
   if (error_operand_p (size))
     return error_mark_node;
 
@@ -10967,11 +10963,10 @@ grokdeclarator (const cp_declarator *declarator,
 		error ("flexible array member in union");
 		type = error_mark_node;
 	      }
-	    else
+	    else 
 	      {
-		tree itype = compute_array_index_type (dname, NULL_TREE,
-						       tf_warning_or_error);
-		type = build_cplus_array_type (TREE_TYPE (type), itype);
+		/* Flexible array member has a null domain.  */
+		type = build_cplus_array_type (TREE_TYPE (type), NULL_TREE);
 	      }
 	  }
 
diff --git a/gcc/cp/error.c b/gcc/cp/error.c
index 89a00a0..4948fab 100644
--- a/gcc/cp/error.c
+++ b/gcc/cp/error.c
@@ -875,10 +875,11 @@ dump_type_suffix (cxx_pretty_printer *pp, tree t, int flags)
     case ARRAY_TYPE:
       pp_maybe_space (pp);
       pp_cxx_left_bracket (pp);
-      if (TYPE_DOMAIN (t) && TYPE_MAX_VALUE (TYPE_DOMAIN (t)))
+      /* C++ flexible array members have a null domain.  */
+      if (tree dtype = TYPE_DOMAIN (t))
 	{
-	  tree dtype = TYPE_DOMAIN (t);
 	  tree max = TYPE_MAX_VALUE (dtype);
+	  /* Zero-length arrays have an upper bound of SIZE_MAX.  */
 	  if (integer_all_onesp (max))
 	    pp_character (pp, '0');
 	  else if (tree_fits_shwi_p (max))
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 27dfdf86..1dea519 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -12846,14 +12846,9 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
       if (t == integer_type_node)
 	return t;
 
-      if (TREE_CODE (TYPE_MIN_VALUE (t)) == INTEGER_CST)
-        {
-          if (!TYPE_MAX_VALUE (t))
-            return compute_array_index_type (NULL_TREE, NULL_TREE, complain);
-          
-          if (TREE_CODE (TYPE_MAX_VALUE (t)) == INTEGER_CST)
-            return t;
-        }
+      if (TREE_CODE (TYPE_MIN_VALUE (t)) == INTEGER_CST
+          && TREE_CODE (TYPE_MAX_VALUE (t)) == INTEGER_CST)
+        return t;
 
       {
 	tree max, omax = TREE_OPERAND (TYPE_MAX_VALUE (t), 0);
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index 2bf37bca..3203aca 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -2586,8 +2586,19 @@ build_ctor_subob_ref (tree index, tree type, tree obj)
     obj = build_class_member_access_expr (obj, index, NULL_TREE,
 					  /*reference*/false, tf_none);
   if (obj)
-    gcc_assert (same_type_ignoring_top_level_qualifiers_p (type,
-							   TREE_TYPE (obj)));
+    {
+      tree objtype = TREE_TYPE (obj);
+      if (TREE_CODE (objtype) == ARRAY_TYPE && !TYPE_DOMAIN (objtype))
+	{
+	  /* When the destination object refers to a flexible array member
+	     verify that it matches the type of the source object except
+	     for its domain.  */
+	  gcc_assert (comptypes (type, objtype, COMPARE_REDECLARATION));
+	}
+      else
+	gcc_assert (same_type_ignoring_top_level_qualifiers_p (type, objtype));
+    }
+
   return obj;
 }
 
diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c
index ac2f3c3..419faa2 100644
--- a/gcc/cp/typeck2.c
+++ b/gcc/cp/typeck2.c
@@ -1015,14 +1015,13 @@ digest_init_r (tree type, tree init, bool nested, int flags,
      them if they were present.  */
   if (code == ARRAY_TYPE)
     {
-      if (nested
-	  && (!TYPE_DOMAIN (type) || !TYPE_MAX_VALUE (TYPE_DOMAIN (type))))
+      if (nested && !TYPE_DOMAIN (type))
 	{
-	  /* Flexible array members do not have an upper bound.  */
+	  /* C++ flexible array members have a null domain.  */
 	  pedwarn (EXPR_LOC_OR_LOC (init, input_location), OPT_Wpedantic,
 		   "initialization of a flexible array member");
 	}
-      
+
       tree typ1 = TYPE_MAIN_VARIANT (TREE_TYPE (type));
       if (char_type_p (typ1)
 	  /*&& init */
@@ -1061,9 +1060,7 @@ digest_init_r (tree type, tree init, bool nested, int flags,
 	      init = copy_node (init);
 	      TREE_TYPE (init) = type;
 	    }
-	  if (TYPE_DOMAIN (type)
-	      && TYPE_MAX_VALUE (TYPE_DOMAIN (type))
-	      && TREE_CONSTANT (TYPE_SIZE (type)))
+	  if (TYPE_DOMAIN (type) && TREE_CONSTANT (TYPE_SIZE (type)))
 	    {
 	      /* Not a flexible array member.  */
 	      int size = TREE_INT_CST_LOW (TYPE_SIZE (type));
@@ -1252,12 +1249,11 @@ process_init_constructor_array (tree type, tree init,
 
   if (TREE_CODE (type) == ARRAY_TYPE)
     {
+      /* C++ flexible array members have a null domain.  */
       tree domain = TYPE_DOMAIN (type);
-      /* Flexible array members have no upper bound.  */
-      tree maxval = domain ? TYPE_MAX_VALUE (domain) : NULL_TREE;
-      if (domain && maxval && TREE_CONSTANT (maxval))
-	len = wi::ext (wi::to_offset (maxval)
-		       - wi::to_offset (TYPE_MIN_VALUE (domain)) + 1,
+      if (domain && TREE_CONSTANT (TYPE_MAX_VALUE (domain)))
+	len = wi::ext (wi::to_offset (TYPE_MAX_VALUE (domain))
+                       - wi::to_offset (TYPE_MIN_VALUE (domain)) + 1,
 		       TYPE_PRECISION (TREE_TYPE (domain)),
 		       TYPE_SIGN (TREE_TYPE (domain))).to_uhwi ();
       else
@@ -1451,9 +1447,7 @@ process_init_constructor_record (tree type, tree init,
 	  /* Warn when some struct elements are implicitly initialized
 	     to zero.  However, avoid issuing the warning for flexible
 	     array members since they need not have any elements.  */
-	  if ((TREE_CODE (fldtype) != ARRAY_TYPE
-	       || (TYPE_DOMAIN (fldtype)
-		   && TYPE_MAX_VALUE (TYPE_DOMAIN (fldtype))))
+	  if ((TREE_CODE (fldtype) != ARRAY_TYPE || TYPE_DOMAIN (fldtype))
 	      && (complain & tf_warning)
 	      && !EMPTY_CONSTRUCTOR_P (init))
 	    warning (OPT_Wmissing_field_initializers,
diff --git a/gcc/testsuite/g++.dg/ext/flexarray-mangle-2.C b/gcc/testsuite/g++.dg/ext/flexarray-mangle-2.C
new file mode 100644
index 0000000..98bd5f5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/flexarray-mangle-2.C
@@ -0,0 +1,46 @@
+// PR c++/69277 - [6 Regression] ICE mangling a flexible array member
+// { dg-do compile { target c++11 } }
+
+struct A {
+  int n;
+  char a [];
+};
+
+// Declare but do not define function templates.
+template <class T>
+void foo ();
+
+template <typename T>
+void fooref (T&);
+
+// Rvalue references are a C++ 11 feature.
+template <typename T>
+void foorefref (T&&);
+
+void bar (A a)
+{
+  // Decltype is also a C++ 11 feature.
+  // Verify that decltype gets the right type and that foo is
+  // mangled correctly.
+  foo<decltype (a.a)>();
+
+  // Verify that function templates taking a reference and an rvalue
+  // references (as in PR c++/69277) are also mangled correctly.
+  fooref (a.a);
+  foorefref (a.a);
+}
+
+// In G++ versions prior to 6, flexible array members were incorrectly
+// mangled as arrays of zero elements.  Verify that flexible array
+// members are mangled correctly as arrays of an unspecified number
+// of elements.
+
+// void foo<char []>():
+// { dg-final { scan-assembler _Z3fooIA_cEvv } }
+
+// The following is derived from PR c++/69277:
+// void fooref<char []>(char (&) [])
+// { dg-final { scan-assembler _Z6foorefIA_cEvRT_ } }
+
+// void foorefref<char (&) []>(char (&) [])
+// { dg-final { scan-assembler _Z9foorefrefIRA_cEvOT_ } }
diff --git a/gcc/testsuite/g++.dg/ext/flexarray-mangle.C b/gcc/testsuite/g++.dg/ext/flexarray-mangle.C
new file mode 100644
index 0000000..d8a8c0a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/flexarray-mangle.C
@@ -0,0 +1,24 @@
+// PR c++/69277 - [6 Regression] ICE mangling a flexible array member
+// { dg-do compile }
+
+struct A {
+  int n;
+  char a [];
+};
+
+// Declare but do not define function templates.
+template <typename T>
+void fooref (T&);
+
+void bar (A a)
+{
+  fooref (a.a);
+}
+
+// In G++ versions prior to 6, flexible array members were incorrectly
+// mangled as arrays of zero elements.  Verify that flexible array
+// members are mangled correctly as arrays of an unspecified number
+// of elements.
+
+// void fooref<char []>(char (&) [])
+// { dg-final { scan-assembler _Z6foorefIA_cEvRT_ } }
diff --git a/gcc/testsuite/g++.dg/ext/flexarray-subst.C b/gcc/testsuite/g++.dg/ext/flexarray-subst.C
new file mode 100644
index 0000000..f644636
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/flexarray-subst.C
@@ -0,0 +1,33 @@
+// PR c++/69251 - [6 Regression] ICE (segmentation fault) in unify_array_domain
+// on i686-linux-gnu
+// { dg-do compile }
+
+struct A { int n; char a[]; };
+
+template <class>
+struct B;
+
+// The following definition shouldn't be needed but is provided to prevent
+// the test from failing with an error due to PR c++/69349 - template
+// substitution error for flexible array members.  (This doesn't compromise
+// the validity of this test since all it tests for is the absennce of
+// the ICE.)
+template <class>
+struct B { typedef int X; };
+
+template <class T>
+struct B<T[]> { typedef int X; };
+
+template <class T>
+struct C { typedef typename B<T>::X X; };
+
+template <class T>
+int foo (T&, typename C<T>::X = 0)
+{
+  return 0;
+}
+
+void bar (A *a)
+{
+  foo (a->a);
+}
diff --git a/gcc/testsuite/g++.dg/ext/flexary11.C b/gcc/testsuite/g++.dg/ext/flexary11.C
new file mode 100644
index 0000000..5bf774f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/flexary11.C
@@ -0,0 +1,19 @@
+// PR c++/69253 - [6 Regression] g++ ICE at -O0 on x86_64-linux-gnu
+//                in "cxx_incomplete_type_diagnostic"
+// { dg-do compile }
+
+struct A {
+  int n;
+  char a [];
+};
+
+void f ()
+{
+  // Compound literals and flexible array members are G++ extensions
+  // accepted for compatibility with C and GCC.
+
+  // The following use of a flexible array member in a compound literal
+  // is invalid in C and rejected by GCC in C mode and so it's also
+  // rejected in C++ mode.
+  (struct A){ 1, "" };   // { dg-error "forbids compound-literals|initialization of a flexible array member|invalid use of a flexible array member" }
+}
diff --git a/gcc/testsuite/g++.dg/ext/flexary12.C b/gcc/testsuite/g++.dg/ext/flexary12.C
new file mode 100644
index 0000000..3d8c805
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/flexary12.C
@@ -0,0 +1,63 @@
+// PR c++/69290 - [6 Regression] g++ ICE on invalid initialization
+//     of a flexible array member
+// { dg-do compile }
+
+// Suppress pedantic errors about initialization of a flexible array member.
+// { dg-options "-Wno-pedantic" }
+
+struct A {
+  int a [];  // { dg-error "flexible array member .A::a. in an otherwise empty .struct A." }
+};
+
+void f1 ()
+{
+  // This is the meat of the test from c++/69290:
+  struct A a
+    = { "c" };   // { dg-error "invalid conversion from .const char\\*. to .int." }
+
+  (void)&a;
+}
+
+
+// Exercise other forms of invalid initialization besides the one in the bug.
+struct B {
+  int n;
+  int a [];
+};
+
+void f2 ()
+{
+  struct B b1
+    = { 0, "c" };   // { dg-error "invalid conversion from .const char\\*. to .int." }
+
+  (void)&b1;
+
+  const char s[] = "c";
+  struct B b2
+    = { 0, s };   // { dg-error "invalid conversion from .const char\\*. to .int." }
+
+  (void)&b2;
+}
+
+struct D {
+  int a [];  // { dg-error "flexible array member .D::a. in an otherwise empty .struct D." }
+  D ();
+};
+
+D::D ():
+  a ("c")   // { dg-error "incompatible types in assignment of .const char \\\[2\\\]. to .int \\\[\\\]." }
+{ }
+
+
+template <class T>
+struct C {
+  T a [];  // { dg-error "flexible array member" }
+};
+
+void f3 ()
+{
+  struct C<double> cd
+    = { "c" };   // { dg-error "cannot convert .const char\\*. to .double." }
+
+  (void)&cd;
+}
diff --git a/gcc/testsuite/g++.dg/ext/flexary13.C b/gcc/testsuite/g++.dg/ext/flexary13.C
new file mode 100644
index 0000000..462ed65
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/flexary13.C
@@ -0,0 +1,64 @@
+// { dg-do compile }
+// { dg-options -Wno-pedantic }
+
+#define STR(s) #s
+#define ASSERT(exp) \
+  ((exp) ? (void)0 : (void)(__builtin_printf ("%s:%i: assertion %s failed\n", \
+                     __FILE__, __LINE__, STR(exp)), \
+                      __builtin_abort ()))
+
+struct Ax { int n, a[]; };
+struct AAx { int i; Ax ax; };
+
+int i = 12345678;
+
+int main ()
+{
+  {
+    Ax s = { 0 };
+    ASSERT (s.n == 0);
+  }
+  {
+    Ax s =
+      { 0, { } };   // dg-warning "initialization of a flexible array member" }
+    ASSERT (s.n == 0);
+  }
+  {
+    Ax s =
+      { 1, { 2 } };   // dg-warning "initialization of a flexible array member" }
+    ASSERT (s.n == 1 && s.a [0] == 2);
+  }
+  {
+    Ax s =
+      { 2, { 3, 4 } }; // dg-warning "initialization of a flexible array member" }
+    ASSERT (s.n = 2 && s.a [0] == 3 && s.a [1] == 4);
+  }
+  {
+    Ax s =
+      { 123, i };   // dg-warning "initialization of a flexible array member" }
+    ASSERT (s.n == 123 && s.a [0] == i);
+  }
+  {
+    Ax s =
+      { 456, { i } }; // dg-warning "initialization of a flexible array member" }
+    ASSERT (s.n == 456 && s.a [0] == i);
+  }
+  {
+    int j = i + 1, k = j + 1;
+    Ax s =
+      { 3, { i, j, k } }; // dg-warning "initialization of a flexible array member" }
+    ASSERT (s.n == 3 && s.a [0] == i && s.a [1] == j && s.a [2] == k);
+  }
+
+  {
+    AAx s =
+      { 1, { 2 } };   // dg-warning "initialization of a flexible array member" }
+    ASSERT (s.i == 1 && s.ax.n == 2);
+  }
+
+  {
+    AAx s =
+      { 1, { 2, { 3 } } };   // dg-warning "initialization of a flexible array member" }
+    ASSERT (s.i == 1 && s.ax.n == 2 && s.ax.a [0] == 3);
+  }
+}
diff --git a/gcc/testsuite/g++.dg/ext/flexary14.C b/gcc/testsuite/g++.dg/ext/flexary14.C
new file mode 100644
index 0000000..7365357
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/flexary14.C
@@ -0,0 +1,17 @@
+// PR c++/69349 - template substitution error for flexible array members
+// { dg-do compile }
+
+template <class>
+struct A;
+
+template <class T>
+struct A<T[]> { typedef int X; };
+
+template <class T> int foo (T&, typename A<T>::X = 0) { return 0; }
+
+struct B { int n, a[]; };
+
+void bar (B *b)
+{
+    foo (b->a);
+}
diff --git a/gcc/testsuite/g++.dg/other/dump-ada-spec-2.C b/gcc/testsuite/g++.dg/other/dump-ada-spec-2.C
index d1af7e0..608b5be 100644
--- a/gcc/testsuite/g++.dg/other/dump-ada-spec-2.C
+++ b/gcc/testsuite/g++.dg/other/dump-ada-spec-2.C
@@ -7,5 +7,5 @@ struct S
   __extension__ unsigned char data[];
 };
 
-/* { dg-final { scan-ada-spec "array \\(0 .. 0\\)" } } */
+/* { dg-final { scan-ada-spec "array \\(size_t\\)" } } */
 /* { dg-final { cleanup-ada-spec } } */

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]