http://gcc.gnu.org/bugzilla/show_bug.cgi?id=46866
Summary: [4.5/4.6 Regression] ICE: type mismatch in address expression Product: gcc Version: 4.6.0 Status: UNCONFIRMED Keywords: ice-checking Severity: normal Priority: P3 Component: tree-optimization AssignedTo: unassig...@gcc.gnu.org ReportedBy: rgue...@gcc.gnu.org extern void *malloc(__SIZE_TYPE__); typedef struct T T; struct T { void (*destroy)(void *); }; void destroy(union { void *this; } __attribute__((transparent_union))); static const typeof(destroy) *_destroy = (const typeof(destroy)*)destroy; void destroy(void *this); static T *create_empty(void) { T *this = malloc(sizeof(*this)); *this = (typeof(*this)){ _destroy }; return this; } void openssl_crl_load(void) { T *this = create_empty(); destroy(this); } ICEs with > ./cc1 -quiet openssl_crl.3.3.3.i -O openssl_crl.3.3.3.i: In function 'openssl_crl_load': openssl_crl.3.3.3.i:15:6: error: type mismatch in address expression void (*<T357>) (union { void * this; }) void <T9d> (void *) _destroy.0_6 = destroy; openssl_crl.3.3.3.i:15:6: internal compiler error: verify_stmts failed Please submit a full bug report, with preprocessed source if appropriate. See <http://gcc.gnu.org/bugs.html> for instructions. because of the appearant mismatch of the function prototye of destroy with regarting to the transparent_union attribute. Appearantly the C frontend has the transparent union prototype type in function create_empty () while it has the other prototype type in effect after IPA inlining (after the address-expression is built). The types are munged together without diagnostic here: Old value = (tree) 0x7ffff5cfa738 New value = (tree) 0x7ffff7efe7e0 0x000000000049c987 in merge_decls (newdecl=0x7ffff5d16100, olddecl=0x7ffff5d16000, newtype=0x7ffff7efe7e0, oldtype=0x7ffff5cfa738) at /space/rguenther/src/svn/trunk/gcc/c-decl.c:2173 2172 /* Merge the data types specified in the two decls. */ 2173 TREE_TYPE (newdecl) 2174 = TREE_TYPE (olddecl) 2175 = composite_type (newtype, oldtype); but existing TYPE_POINTER/REFERENCE_TO are not merged. (gdb) p newdecl->base.addressable_flag $9 = 0 (gdb) p olddecl->base.addressable_flag $10 = 1 with unit-at-a-time gimplification we try to fixup here, but we never visit static initializers like static const typeof(destroy) *_destroy = (const typeof(destroy)*)destroy; I have a patch.