diff mbox

fix #69277 - [6 Regression] ICE mangling a flexible array member

Message ID 569C31CF.4070603@gmail.com
State New
Headers show

Commit Message

Martin Sebor Jan. 18, 2016, 12:29 a.m. UTC
On 01/15/2016 02:01 PM, Jason Merrill wrote:
> On 01/14/2016 10:01 PM, Martin Sebor wrote:
>> In anticipation of needing to do something I put together the attached
>> patch that rolls this change into version 10, letting version 9 and
>> prior roll it back.  I also mention it in the manual.  What the patch
>> doesn't do is add a warning.
>
> Looks good, but please also add a warning.  See the use of
> abi_warn_or_compat_version_crosses elsewhere in mangle.c.

Attached is an updated patch with the warning plus a test for it.
The test depends on the fix that I posted yesterday for #69317 -
[6 regression] wrong ABI version in -Wabi warning.

Martin
diff mbox

Patch

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

	PR c++/69277
	* gcc/testsuite/g++.dg/abi/flexarray-abi-v9.C: New test.
	* g++.dg/ext/flexarray-mangle-2.C: New test.
	* g++.dg/ext/flexarray-mangle.C: New test.
	* g++.dg/abi/flexarray-Wabi-9-10.C: New test.
gcc/cp/ChangeLog:
2016-01-14  Martin Sebor  <msebor@redhat.com>

	PR c++/69277
	* mangle.c (write_array_type): Mangle flexible array members
	the same as arrays with an unspecified size.

gcc/ChangeLog:
2016-01-14  Martin Sebor  <msebor@redhat.com>

	PR c++/69277
	* invoke.texi (-fabi-version=, -Wabi): Update version 10.

Index: gcc/cp/mangle.c
===================================================================
--- gcc/cp/mangle.c	(revision 232296)
+++ gcc/cp/mangle.c	(working copy)
@@ -3280,8 +3280,10 @@  write_template_template_arg (const tree
 		  ::= A <expression> _ </element/ type>
 
      "Array types encode the dimension (number of elements) and the
-     element type. For variable length arrays, the dimension (but not
-     the '_' separator) is omitted."  */
+     element type.  For variable length arrays, the dimension (but not
+     the '_' separator) is omitted."
+     Note that for flexible array members, like for other arrays of
+     unspecified size, the dimension is also omitted.  */
 
 static void
 write_array_type (const tree type)
@@ -3289,30 +3291,42 @@  write_array_type (const tree type)
   write_char ('A');
   if (TYPE_DOMAIN (type))
     {
-      tree index_type;
-      tree max;
-
-      index_type = TYPE_DOMAIN (type);
-      /* The INDEX_TYPE gives the upper and lower bounds of the
-	 array.  */
-      max = TYPE_MAX_VALUE (index_type);
-      if (TREE_CODE (max) == INTEGER_CST)
+      tree index_type = TYPE_DOMAIN (type);
+      /* The INDEX_TYPE gives the upper and lower bounds of the array.
+	 It's null for flexible array members which have no upper bound
+	 (this is a change from GCC 5 and prior where such members were
+	 incorrectly mangled as zero-length arrays).  */
+      if (tree max = TYPE_MAX_VALUE (index_type))
 	{
-	  /* The ABI specifies that we should mangle the number of
-	     elements in the array, not the largest allowed index.  */
-	  offset_int wmax = wi::to_offset (max) + 1;
-	  /* Truncate the result - this will mangle [0, SIZE_INT_MAX]
-	     number of elements as zero.  */
-	  wmax = wi::zext (wmax, TYPE_PRECISION (TREE_TYPE (max)));
-	  gcc_assert (wi::fits_uhwi_p (wmax));
-	  write_unsigned_number (wmax.to_uhwi ());
+	  if (TREE_CODE (max) == INTEGER_CST)
+	    {
+	      /* The ABI specifies that we should mangle the number of
+		 elements in the array, not the largest allowed index.  */
+	      offset_int wmax = wi::to_offset (max) + 1;
+	      /* Truncate the result - this will mangle [0, SIZE_INT_MAX]
+		 number of elements as zero.  */
+	      wmax = wi::zext (wmax, TYPE_PRECISION (TREE_TYPE (max)));
+	      gcc_assert (wi::fits_uhwi_p (wmax));
+	      write_unsigned_number (wmax.to_uhwi ());
+	    }
+	  else
+	    {
+	      max = TREE_OPERAND (max, 0);
+	      write_expression (max);
+	    }
 	}
       else
-	{
-	  max = TREE_OPERAND (max, 0);
-	  write_expression (max);
-	}
+	{	  
+	  if (!abi_version_at_least (10))
+	    {
+	      /* In ABI versions prior to 10 mangle flexible array members
+		 the same as zero-length arrays for compatibility.  */
+	      write_unsigned_number (0);
+	    }
 
+	  if (abi_warn_or_compat_version_crosses (10))
+	    G.need_abi_warning = true;
+	}
     }
   write_char ('_');
   write_type (TREE_TYPE (type));
Index: gcc/doc/invoke.texi
===================================================================
--- gcc/doc/invoke.texi	(revision 232296)
+++ gcc/doc/invoke.texi	(working copy)
@@ -2173,7 +2173,8 @@  Version 9, which first appeared in G++ 5
 
 Version 10, which first appeared in G++ 6.1, adds mangling of
 attributes that affect type identity, such as ia32 calling convention
-attributes (e.g. @samp{stdcall}).
+attributes (e.g. @samp{stdcall}).  This version also corrects the mangling
+of flexible array members.
 
 See also @option{-Wabi}.
 
@@ -2605,16 +2606,16 @@  have meanings only for C++ programs:
 @item -Wabi @r{(C, Objective-C, C++ and Objective-C++ only)}
 @opindex Wabi
 @opindex Wno-abi
-Warn when G++ it generates code that is probably not compatible with
-the vendor-neutral C++ ABI@.  Since G++ now defaults to updating the
+Warn when G++ generates code that is probably not compatible with
+the vendor-neutral C++ ABI.  Since G++ defaults to updating the
 ABI with each major release, normally @option{-Wabi} will warn only if
 there is a check added later in a release series for an ABI issue
 discovered since the initial release.  @option{-Wabi} will warn about
-more things if an older ABI version is selected (with
+more changes if an older ABI version is selected (with
 @option{-fabi-version=@var{n}}).
 
 @option{-Wabi} can also be used with an explicit version number to
-warn about compatibility with a particular @option{-fabi-version}
+warn about incompatibility with a particular @option{-fabi-version}
 level, e.g. @option{-Wabi=2} to warn about changes relative to
 @option{-fabi-version=2}.
 
@@ -2703,7 +2704,11 @@  ia32 calling conventions on a function t
 did not affect the mangled name, leading to name collisions when
 function pointers were used as template arguments.
 
-This was fixed in @option{-fabi-version=10}, the default for GCC 6.1.
+Flexible array members were mangled as zero-length arrays rather than
+as arrays of unspecified size as expected.
+
+These problems were fixed in @option{-fabi-version=10}, the default
+for GCC 6.1.
 
 @end itemize
 
Index: gcc/testsuite/g++.dg/ext/flexarray-mangle-2.C
===================================================================
--- gcc/testsuite/g++.dg/ext/flexarray-mangle-2.C	(revision 0)
+++ gcc/testsuite/g++.dg/ext/flexarray-mangle-2.C	(working copy)
@@ -0,0 +1,48 @@ 
+// 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 (ABI version 9 and prior), 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 by default (ABI version 10 and
+// newer).  See g++.dg/abi/flexarray-abi-v9.C for the compatibility
+// test.
+
+// 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_ } }
Index: gcc/testsuite/g++.dg/ext/flexarray-mangle.C
===================================================================
--- gcc/testsuite/g++.dg/ext/flexarray-mangle.C	(revision 0)
+++ gcc/testsuite/g++.dg/ext/flexarray-mangle.C	(working copy)
@@ -0,0 +1,26 @@ 
+// 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 (ABI version 9 and prior), 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 by default (ABI version 10 and
+// newer).  See g++.dg/abi/flexarray-abi-v9.C for the compatibility
+// test.
+
+// void fooref<char []>(char (&) [])
+// { dg-final { scan-assembler _Z6foorefIA_cEvRT_ } }
Index: gcc/testsuite/g++.dg/abi/flexarray-abi-v9.C
===================================================================
--- gcc/testsuite/g++.dg/abi/flexarray-abi-v9.C	(revision 0)
+++ gcc/testsuite/g++.dg/abi/flexarray-abi-v9.C	(working copy)
@@ -0,0 +1,49 @@ 
+// Test to verify ABI version 9 (and prior) compatibility mangling
+// of a flexible array member.  See also PR c++/69277.
+// { dg-do compile { target c++11 } }
+// { dg-options "-fabi-version=9" }
+
+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 (ABI version 10), flexible array members
+// were incorrectly mangled as arrays of zero elements.  Verify that
+// they are still mangled that way with -fabi-version=9 (i.e., unless
+// -fabi-version=10 is used.  See g++.dg/ext/flexarray-mangle-3.C
+// for that test.)
+
+// void foo<char [0]>():
+// { dg-final { scan-assembler _Z3fooIA0_cEvv } }
+
+// The following is derived from PR c++/69277:
+// void fooref<char [0]>(char (&) [0])
+// { dg-final { scan-assembler _Z6foorefIA0_cEvRT_ } }
+
+// void foorefref<char (&) [0]>(char (&) [0])
+// { dg-final { scan-assembler _Z9foorefrefIRA0_cEvOT_ } }
Index: gcc/testsuite/g++.dg/abi/flexarray-Wabi-9-10.C
===================================================================
--- gcc/testsuite/g++.dg/abi/flexarray-Wabi-9-10.C	(revision 0)
+++ gcc/testsuite/g++.dg/abi/flexarray-Wabi-9-10.C	(working copy)
@@ -0,0 +1,23 @@ 
+// Test to verify that -Wabi issues a warning for the change in
+// how flexible array members are mangled between ABI versions
+// 9 and 10.  See also PR c++/69277.
+// { dg-do compile }
+// { dg-options "-Wabi=9 -fabi-version=10" }
+
+struct A {
+  int n;
+  char a [];
+};
+
+// In G++ versions prior to 6 (ABI version 10), flexible array members
+// were incorrectly mangled as arrays of zero elements.  Verify that
+// the -Wabi=9 option elicits a warning pointing out the change in
+// how they get mangled in version 10 and later.
+//
+template <typename T>
+void foo (T&) { }   // { dg-warning "the mangled name of .void foo\\(T&\\) \\\[with T = char \\\[\\\]\\\]. changed between -fabi-version=10 \\(_Z3fooIA0_cEvRT_\\) and -fabi-version=9 \\(_Z3fooIA_cEvRT_\\)" }
+
+void bar (A *a)
+{
+  foo (a->a);
+}