Patchwork RFC [ABI]: C++ PATCH for c++/44540 - avoid mangling attribute noreturn

login
register
mail settings
Submitter Jason Merrill
Date July 13, 2010, 10:37 p.m.
Message ID <4C3CEA9E.4050102@redhat.com>
Download mbox | patch
Permalink /patch/58822/
State New
Headers show

Comments

Jason Merrill - July 13, 2010, 10:37 p.m.
On 07/07/2010 11:14 AM, Mark Mitchell wrote:
> I agree that an orthogonal improvement would be to stop abusing
> TYPE_CONST and TYPE_VOLATILE for these attributes and record them on
> TYPE_ATTRIBUTES.  But, that would be much bigger than Jason's patch.

I've done a lot of the work toward this, but decided to put it aside 
because it was taking up too much time for a minor internal cleanup. 
Perhaps I'll pick it up again after the August C++ meeting.

In any case, here's the patch I'm checking in for this PR.

Patch

commit aef7a793c2e2a942e546d8df4245495ac74d536a
Author: Jason Merrill <jason@redhat.com>
Date:   Tue Jul 13 15:46:15 2010 -0400

    	PR c++/44540
    	* mangle.c (write_type): Canonicalize.
    	(canonicalize_for_substitution): Retain cv-quals on FUNCTION_TYPE.
    	(write_CV_qualifiers_for_type): Ignore them in abi>=5.

diff --git a/gcc/cp/mangle.c b/gcc/cp/mangle.c
index e825952..9390a92 100644
--- a/gcc/cp/mangle.c
+++ b/gcc/cp/mangle.c
@@ -346,11 +346,19 @@  canonicalize_for_substitution (tree node)
   if (TYPE_P (node)
       && TYPE_CANONICAL (node) != node
       && TYPE_MAIN_VARIANT (node) != node)
+    {
       /* Here we want to strip the topmost typedef only.
          We need to do that so is_std_substitution can do proper
          name matching.  */
-    node = cp_build_qualified_type (TYPE_MAIN_VARIANT (node),
-                                    cp_type_quals (node));
+      if (TREE_CODE (node) == FUNCTION_TYPE)
+	/* Use build_qualified_type and TYPE_QUALS here to preserve
+	   the old buggy mangling of attribute noreturn with abi<5.  */
+	node = build_qualified_type (TYPE_MAIN_VARIANT (node),
+				     TYPE_QUALS (node));
+      else
+	node = cp_build_qualified_type (TYPE_MAIN_VARIANT (node),
+					cp_type_quals (node));
+    }
   return node;
 }
 
@@ -1776,6 +1784,7 @@  write_type (tree type)
   if (type == error_mark_node)
     return;
 
+  type = canonicalize_for_substitution (type);
   if (find_substitution (type))
     return;
 
@@ -1978,6 +1987,12 @@  write_CV_qualifiers_for_type (const tree type)
      array.  */
   cp_cv_quals quals = TYPE_QUALS (type);
 
+  /* Attribute const/noreturn are not reflected in mangling.  */
+  if (abi_version_at_least (5)
+      && (TREE_CODE (type) == FUNCTION_TYPE
+	  || TREE_CODE (type) == METHOD_TYPE))
+    return 0;
+
   if (quals & TYPE_QUAL_RESTRICT)
     {
       write_char ('r');
diff --git a/gcc/testsuite/g++.dg/abi/noreturn1.C b/gcc/testsuite/g++.dg/abi/noreturn1.C
new file mode 100644
index 0000000..0532cf2
--- /dev/null
+++ b/gcc/testsuite/g++.dg/abi/noreturn1.C
@@ -0,0 +1,14 @@ 
+// Test that attribute noreturn is not part of the mangled name.
+// { dg-options -fabi-version=0 }
+
+void baz (const char *fmt, ...);
+
+// { dg-final { scan-assembler "_Z3barPFvPKczE" } }
+void bar (void (*baz) (const char *fmt, ...)
+			   __attribute__ ((noreturn, format (printf, 1, 2))));
+
+void
+foo ()
+{
+  bar (&baz);
+}
diff --git a/gcc/testsuite/g++.dg/abi/noreturn2.C b/gcc/testsuite/g++.dg/abi/noreturn2.C
new file mode 100644
index 0000000..72accaf
--- /dev/null
+++ b/gcc/testsuite/g++.dg/abi/noreturn2.C
@@ -0,0 +1,14 @@ 
+// Test for buggy mangling of attribute noreturn in abi<=4
+// { dg-options -fabi-version=4 }
+
+void baz (const char *fmt, ...);
+
+// { dg-final { scan-assembler "_Z3barPVFvPKczE" } }
+void bar (void (*baz) (const char *fmt, ...)
+			   __attribute__ ((noreturn, format (printf, 1, 2))));
+
+void
+foo ()
+{
+  bar (&baz);
+}