Bug 34936 - ICE with double and attribute may_alias
: ICE with double and attribute may_alias
Status: RESOLVED FIXED
Product: gcc
Classification: Unclassified
Component: c++
: 4.3.0
: P3 normal
: ---
Assigned To: dgregor
:
: ice-on-valid-code, monitored
:
:
  Show dependency treegraph
 
Reported: 2008-01-23 07:42 UTC by Volker Reichelt
Modified: 2008-01-31 20:08 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2008-01-25 21:16:52


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Volker Reichelt 2008-01-23 07:42:49 UTC
The following valid code snippet triggers an ICE since GCC 3.3:

============================================
typedef double X __attribute((may_alias)) ;

template<typename> struct A
{
  A();
};

A<X> a;
============================================

bug.cc: In function 'void __static_initialization_and_destruction_0(int, int)':
bug.cc:8: internal compiler error: in write_builtin_type, at cp/mangle.c:1849
Please submit a full bug report, [etc.]

The code compiles if I use char or int instead of double.
Comment 1 Richard Guenther 2008-01-23 10:50:51 UTC
This is not a regression.  From write_builtin_type:

    case REAL_TYPE:
      if (type == float_type_node
          || type == java_float_type_node)
        write_char ('f');
      else if (type == double_type_node
               || type == java_double_type_node) 
        write_char ('d');
      else if (type == long_double_type_node)
        write_char ('e');
      else
        gcc_unreachable ();
      break;

this is probably too simplistic and instead should try fancy stuff like
the integer case.

Confirmed.
Comment 2 Jakub Jelinek 2008-01-23 10:59:10 UTC
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.
Comment 3 Jakub Jelinek 2008-01-23 11:01:12 UTC
It is unclear whether this can be considered a regression or not.
In GCC 3.2 and earlier the may_alias attribute was ignored, so while it meant
something else, we weren't ICEing on it.
Comment 4 dgregor 2008-01-25 21:16:52 UTC
I don't know if this is a regression or not, but it's roughly the same issue as
PR 34395 and is fixed by the same patch:

  http://gcc.gnu.org/ml/gcc-patches/2008-01/msg01161.html
Comment 5 dgregor 2008-01-31 20:07:31 UTC
Subject: Bug 34936

Author: dgregor
Date: Thu Jan 31 20:06:33 2008
New Revision: 131984

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=131984
Log:
2008-01-31  Douglas Gregor  <doug.gregor@gmail.com>
           Jakub Jelinek  <jakub@redhat.com>

       PR c++/34935
       PR c++/34936
       * typeck.c (structural_comptypes): Handle comparisons of
       VOID_TYPE, BOOLEAN_TYPE, INTEGER_TYPE, FIXED_POINT_TYPE, and
       REAL_TYPE nodes.
       * mangle.c (write_builtin_type): Map down to the canonical type,
       which will be one of the predefined type nodes.

2008-01-31  Douglas Gregor  <doug.gregor@gmail.com>
           Jakub Jelinek  <jakub@redhat.com>

       PR c++/34935
       PR c++/34936
       * g++.dg/ext/alias-canon.C: New.
       * g++.dg/ext/alias-mangle.C: New.


Added:
    trunk/gcc/testsuite/g++.dg/ext/alias-canon.C
    trunk/gcc/testsuite/g++.dg/ext/alias-mangle.C
Modified:
    trunk/gcc/cp/ChangeLog
    trunk/gcc/cp/mangle.c
    trunk/gcc/cp/typeck.c
    trunk/gcc/testsuite/ChangeLog
Comment 6 dgregor 2008-01-31 20:08:10 UTC
Fixed on mainline