From b1c9b3c3408c1ec8043f9b9e1a148f84bb7f3b25 Mon Sep 17 00:00:00 2001
From: Patrick Palka <ppalka@redhat.com>
Date: Wed, 11 Nov 2020 15:11:23 -0500
Subject: [PATCH] c++: Change the mangling of __alignof__ [PR88115]

This patch changes the mangling of __alignof__ to v111__alignof__,
making its mangling distinct from that of alignof(type) and
alignof(expr).

How we mangle ALIGNOF_EXPR now depends on its ALIGNOF_EXPR_STD_P flag,
which after the previous patch gets consistently set for alignof(type)
as well as alignof(expr).

gcc/c-family/ChangeLog:

	PR c++/88115
	* c-opts.c (c_common_post_options): Update latest_abi_version.

gcc/ChangeLog:

	PR c++/88115
	* common.opt (-fabi-version): Document =15.
	* doc/invoke.texi (C++ Dialect Options): Likewise.

gcc/cp/ChangeLog:

	PR c++/88115
	* mangle.c (write_expression): Mangle __alignof_ differently
	from alignof when the ABI version is at least 15.

libiberty/ChangeLog:

	PR c++/88115
	* cp-demangle.c (d_print_comp_inner)
	<case DEMANGLE_COMPONENT_EXTENDED_OPERATOR>: Don't print the
	"operator " prefix for __alignof__.
	<case DEMANGLE_COMPONENT_UNARY>: Always print parens around the
	operand of __alignof__.
	* testsuite/demangle-expected: Test demangling for __alignof__.

gcc/testsuite/ChangeLog:

	PR c++/88115
	* g++.dg/abi/macro0.C: Adjust.
	* g++.dg/cpp0x/alignof7.C: New test.
	* g++.dg/cpp0x/alignof8.C: New test.
---
 gcc/c-family/c-opts.c                 |  2 +-
 gcc/common.opt                        |  4 ++++
 gcc/cp/mangle.c                       | 27 +++++++++++++++++++++++----
 gcc/doc/invoke.texi                   |  3 +++
 gcc/testsuite/g++.dg/abi/macro0.C     |  2 +-
 gcc/testsuite/g++.dg/cpp0x/alignof7.C | 22 ++++++++++++++++++++++
 gcc/testsuite/g++.dg/cpp0x/alignof8.C | 13 +++++++++++++
 libiberty/cp-demangle.c               | 25 ++++++++++++++++++++-----
 libiberty/testsuite/demangle-expected |  7 +++++++
 9 files changed, 94 insertions(+), 11 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/alignof7.C
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/alignof8.C

diff --git a/gcc/c-family/c-opts.c b/gcc/c-family/c-opts.c
index 0698e58a335d..40e92229d8ac 100644
--- a/gcc/c-family/c-opts.c
+++ b/gcc/c-family/c-opts.c
@@ -945,7 +945,7 @@ c_common_post_options (const char **pfilename)
 
   /* Change flag_abi_version to be the actual current ABI level, for the
      benefit of c_cpp_builtins, and to make comparison simpler.  */
-  const int latest_abi_version = 14;
+  const int latest_abi_version = 15;
   /* Generate compatibility aliases for ABI v11 (7.1) by default.  */
   const int abi_compat_default = 11;
 
diff --git a/gcc/common.opt b/gcc/common.opt
index 7d0e0d9c88a8..9552cebe0d6c 100644
--- a/gcc/common.opt
+++ b/gcc/common.opt
@@ -960,9 +960,13 @@ Driver Undocumented
 ; 13: Fixes the accidental change in 12 to the calling convention for classes
 ;     with deleted copy constructor and trivial move constructor.
 ;     Default in G++ 8.2.
+;
 ; 14: Corrects the mangling of nullptr expression.
 ;     Default in G++ 10.
 ;
+; 15: Changes the mangling of __alignof__ to be distinct from that of alignof.
+;     Default in G++ 11.
+;
 ; Additional positive integers will be assigned as new versions of
 ; the ABI become the default version of the ABI.
 fabi-version=
diff --git a/gcc/cp/mangle.c b/gcc/cp/mangle.c
index 9fd300112886..5548e51d39d1 100644
--- a/gcc/cp/mangle.c
+++ b/gcc/cp/mangle.c
@@ -3049,11 +3049,30 @@ write_expression (tree expr)
       else
 	goto normal_expr;
     }
-  else if (TREE_CODE (expr) == ALIGNOF_EXPR
-	   && TYPE_P (TREE_OPERAND (expr, 0)))
+  else if (TREE_CODE (expr) == ALIGNOF_EXPR)
     {
-      write_string ("at");
-      write_type (TREE_OPERAND (expr, 0));
+      if (!ALIGNOF_EXPR_STD_P (expr))
+	{
+	  if (abi_warn_or_compat_version_crosses (15))
+	    G.need_abi_warning = true;
+	  if (abi_version_at_least (15))
+	    {
+	      /* We used to mangle __alignof__ like alignof.  */
+	      write_string ("v111__alignof__");
+	      if (TYPE_P (TREE_OPERAND (expr, 0)))
+		write_type (TREE_OPERAND (expr, 0));
+	      else
+		write_expression (TREE_OPERAND (expr, 0));
+	      return;
+	    }
+	}
+      if (TYPE_P (TREE_OPERAND (expr, 0)))
+	{
+	  write_string ("at");
+	  write_type (TREE_OPERAND (expr, 0));
+	}
+      else
+	goto normal_expr;
     }
   else if (code == SCOPE_REF
 	   || code == BASELINK)
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 8d0d2136831a..553cc07e3306 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -2807,6 +2807,9 @@ change in version 12.
 Version 14, which first appeared in G++ 10, corrects the mangling of
 the nullptr expression.
 
+Version 15, which first appeared in G++ 11, changes the mangling of
+@code{__alignof__} to be distinct from that of @code{alignof}.
+
 See also @option{-Wabi}.
 
 @item -fabi-compat-version=@var{n}
diff --git a/gcc/testsuite/g++.dg/abi/macro0.C b/gcc/testsuite/g++.dg/abi/macro0.C
index 08106004c4d0..7c3c17051ed6 100644
--- a/gcc/testsuite/g++.dg/abi/macro0.C
+++ b/gcc/testsuite/g++.dg/abi/macro0.C
@@ -1,6 +1,6 @@
 // This testcase will need to be kept in sync with c_common_post_options.
 // { dg-options "-fabi-version=0" }
 
-#if __GXX_ABI_VERSION != 1014
+#if __GXX_ABI_VERSION != 1015
 #error "Incorrect value of __GXX_ABI_VERSION"
 #endif
diff --git a/gcc/testsuite/g++.dg/cpp0x/alignof7.C b/gcc/testsuite/g++.dg/cpp0x/alignof7.C
new file mode 100644
index 000000000000..a4d7f24a4d75
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/alignof7.C
@@ -0,0 +1,22 @@
+// PR c++/88115
+// { dg-do compile { target c++11 } }
+// { dg-additional-options "-Wno-pedantic" }
+
+// Verify we mangle __alignof__ differently from alignof.
+
+#include <cstddef>
+
+template <class T> void f1(decltype(alignof(T))) { }
+template <class T> void f2(decltype(alignof(T{}))) { }
+template <class T> void f3(decltype(__alignof__(T))) { }
+template <class T> void f4(decltype(__alignof__(T{}))) { }
+
+template void f1<int>(std::size_t);
+template void f2<int>(std::size_t);
+template void f3<int>(std::size_t);
+template void f4<int>(std::size_t);
+
+// { dg-final { scan-assembler "_Z2f1IiEvDTatT_E" } }
+// { dg-final { scan-assembler "_Z2f2IiEvDTaztlT_EE" } }
+// { dg-final { scan-assembler "_Z2f3IiEvDTv111__alignof__T_E" } }
+// { dg-final { scan-assembler "_Z2f4IiEvDTv111__alignof__tlT_EE" } }
diff --git a/gcc/testsuite/g++.dg/cpp0x/alignof8.C b/gcc/testsuite/g++.dg/cpp0x/alignof8.C
new file mode 100644
index 000000000000..a9368e21b0b8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/alignof8.C
@@ -0,0 +1,13 @@
+// PR c++/88115
+// { dg-do compile { target c++11 } }
+// { dg-additional-options "-Wno-pedantic -fabi-version=14 -Wabi" }
+
+#include "alignof7.C"
+
+// { dg-warning "changes between" "" { target *-*-* } 11 }
+// { dg-warning "changes between" "" { target *-*-* } 12 }
+
+// { dg-final { scan-assembler "_Z2f1IiEvDTatT_E" } }
+// { dg-final { scan-assembler "_Z2f2IiEvDTaztlT_EE" } }
+// { dg-final { scan-assembler "_Z2f3IiEvDTatT_E" } }
+// { dg-final { scan-assembler "_Z2f4IiEvDTaztlT_EE" } }
diff --git a/libiberty/cp-demangle.c b/libiberty/cp-demangle.c
index aede23fbf6b6..a9f8e759ff53 100644
--- a/libiberty/cp-demangle.c
+++ b/libiberty/cp-demangle.c
@@ -5458,9 +5458,18 @@ d_print_comp_inner (struct d_print_info *dpi, int options,
       }
 
     case DEMANGLE_COMPONENT_EXTENDED_OPERATOR:
-      d_append_string (dpi, "operator ");
-      d_print_comp (dpi, options, dc->u.s_extended_operator.name);
-      return;
+      {
+	struct demangle_component *name = dc->u.s_extended_operator.name;
+	if (name->type == DEMANGLE_COMPONENT_NAME
+	    && !strncmp (name->u.s_name.s, "__alignof__", name->u.s_name.len))
+	  d_print_comp (dpi, options, dc->u.s_extended_operator.name);
+	else
+	  {
+	    d_append_string (dpi, "operator ");
+	    d_print_comp (dpi, options, dc->u.s_extended_operator.name);
+	  }
+	return;
+      }
 
     case DEMANGLE_COMPONENT_CONVERSION:
       d_append_string (dpi, "operator ");
@@ -5525,8 +5534,14 @@ d_print_comp_inner (struct d_print_info *dpi, int options,
 	if (code && !strcmp (code, "gs"))
 	  /* Avoid parens after '::'.  */
 	  d_print_comp (dpi, options, operand);
-	else if (code && !strcmp (code, "st"))
-	  /* Always print parens for sizeof (type).  */
+	else if ((code && !strcmp (code, "st"))
+		 || (op->type == DEMANGLE_COMPONENT_EXTENDED_OPERATOR
+		     && (op->u.s_extended_operator.name->type
+			 == DEMANGLE_COMPONENT_NAME)
+		     && !strncmp (op->u.s_extended_operator.name->u.s_name.s,
+				  "__alignof__",
+				  op->u.s_extended_operator.name->u.s_name.len)))
+	  /* Always print parens for sizeof (type) and __alignof__.  */
 	  {
 	    d_append_char (dpi, '(');
 	    d_print_comp (dpi, options, operand);
diff --git a/libiberty/testsuite/demangle-expected b/libiberty/testsuite/demangle-expected
index 0850db3d6dd4..4ad9da82f2c7 100644
--- a/libiberty/testsuite/demangle-expected
+++ b/libiberty/testsuite/demangle-expected
@@ -1469,3 +1469,10 @@ f(A<X{.a.b[3 ... 4]=(1)}>)
 # PR 96143
 _Z2F2IZ1FvEUlvE_EN1AIT_E1XES2_
 A<F()::{lambda()#1}>::X F2<F()::{lambda()#1}>(F()::{lambda()#1})
+
+# PR 88115
+_Z1fIiEvDTv111__alignof__T_E
+void f<int>(decltype (__alignof__(int)))
+
+_Z1fIiEvDTv111__alignof__tlT_EE
+void f<int>(decltype (__alignof__(int{})))
-- 
GitLab