[Bug c++/34936] [4.1/4.2/4.3 regression] ICE with double and attribute may_alias

jakub at gcc dot gnu dot org gcc-bugzilla@gcc.gnu.org
Wed Jan 23 11:13:00 GMT 2008



------- Comment #2 from jakub at gcc dot gnu dot org  2008-01-23 10:59 -------
This is actually a big can of worms.
may_alias causes a distinct type code to be created.
For mangling I've tried:
--- mangle.c.jj128      2007-10-08 10:44:57.000000000 +0200
+++ mangle.c    2008-01-23 11:11:12.000000000 +0100
@@ -1,5 +1,5 @@
 /* Name mangling for the 3.0 C++ ABI.
-   Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2007
+   Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008
    Free Software Foundation, Inc.
    Written by Alex Samuel <samuel@codesourcery.com>

@@ -1768,6 +1768,8 @@ write_CV_qualifiers_for_type (const tree
 static void
 write_builtin_type (tree type)
 {
+  tree name = NULL;
+
   switch (TREE_CODE (type))
     {
     case VOID_TYPE:
@@ -1781,7 +1783,9 @@ write_builtin_type (tree type)
     case INTEGER_TYPE:
       /* TYPE may still be wchar_t, since that isn't in
         integer_type_nodes.  */
-      if (type == wchar_type_node)
+      if (TYPE_NAME (type))
+       name = DECL_NAME (TYPE_NAME (type));
+      if (name && name == DECL_NAME (TYPE_NAME (wchar_type_node)))
        write_char ('w');
       else if (TYPE_FOR_JAVA (type))
        write_java_integer_type_codes (type);
@@ -1792,7 +1796,7 @@ write_builtin_type (tree type)
             it in the array of these nodes.  */
        iagain:
          for (itk = 0; itk < itk_none; ++itk)
-           if (type == integer_types[itk])
+           if (name && name == DECL_NAME (TYPE_NAME (integer_types[itk])))
              {
                /* Print the corresponding single-letter code.  */
                write_char (integer_type_codes[itk]);
@@ -1837,13 +1841,15 @@ write_builtin_type (tree type)
       break;

     case REAL_TYPE:
-      if (type == float_type_node
-         || type == java_float_type_node)
+      gcc_assert (TYPE_NAME (type));
+      name = DECL_NAME (TYPE_NAME (type));
+      if (name == DECL_NAME (TYPE_NAME (float_type_node))
+         || name == DECL_NAME (TYPE_NAME (java_float_type_node)))
        write_char ('f');
-      else if (type == double_type_node
-              || type == java_double_type_node)
+      else if (name == DECL_NAME (TYPE_NAME (double_type_node))
+              || name == DECL_NAME (TYPE_NAME (java_double_type_node)))
        write_char ('d');
-      else if (type == long_double_type_node)
+      else if (name == DECL_NAME (TYPE_NAME (long_double_type_node)))
        write_char ('e');
       else
        gcc_unreachable ();

i.e. compare type names rather than types, because for distinct type copies
TYPE_MAIN_VARIANT doesn't point us to the original builtin type.
But there are still issues, say on:
// PR c++/34936
// { dg-do compile }

typedef float f __attribute ((may_alias));
typedef double d __attribute ((may_alias));
typedef long double e __attribute ((may_alias));
typedef char c __attribute ((may_alias));
typedef unsigned char uc __attribute ((may_alias));
typedef signed char sc __attribute ((may_alias));
typedef short int s __attribute ((may_alias));
typedef unsigned int u __attribute ((may_alias));
typedef long int l __attribute ((may_alias));
typedef long long int ll __attribute ((may_alias));
typedef wchar_t w __attribute ((may_alias));
typedef bool b __attribute ((may_alias));

void foo1 (char, unsigned char, signed char, short int, unsigned int, long int,
long long int, wchar_t, bool)
{
}
void bar1 (c, uc, sc, s, u, l, ll, w, b)
{
}
void foo2 (float, double, long double)
{
}
void bar2 (f, d, e)
{
}
which IMHO should be mangled the same between foo and bar, after s/bar/foo/g
but e.g. sc is mangled differently from signed char and ll from long long int.
Here the problem is type hashing which disregards type names, so throws
typedef char __attribute__((may_alias)) into the same equivalence set as
typedef signed char __attribute__((may_alias)).

Or consider:
// PR c++/34936
// { dg-do compile }

typedef float f __attribute ((may_alias));
typedef double d __attribute ((may_alias));
typedef long double e __attribute ((may_alias));
typedef char c __attribute ((may_alias));
typedef unsigned char uc __attribute ((may_alias));
typedef signed char sc __attribute ((may_alias));
typedef short int s __attribute ((may_alias));
typedef unsigned int u __attribute ((may_alias));
typedef long int l __attribute ((may_alias));
typedef long long int ll __attribute ((may_alias));
typedef wchar_t w __attribute ((may_alias));
typedef bool b __attribute ((may_alias));

void foo1 (unsigned char, signed char, short int, unsigned int, long int, bool)
{
}
void foo1 (uc, sc, s, u, l, b)
{
}
which isn't rejected (as C++ treats them as overloads), but are mangled the
same,
so this fails to assemble.


-- 

jakub at gcc dot gnu dot org changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
            Summary|ICE with double and         |[4.1/4.2/4.3 regression] ICE
                   |attribute may_alias         |with double and attribute
                   |                            |may_alias
   Target Milestone|---                         |4.1.3


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=34936



More information about the Gcc-bugs mailing list