GCC Bugzilla – Bug 34936
ICE with double and attribute may_alias
Last modified: 2008-01-31 20:08:10 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.
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.
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.
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.
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
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
Fixed on mainline