The following fixes an issue with nonoverlapping_component_refs_of_decl_p (and the latent same issue in nonoverlapping_component_refs_p). We can't rely on all variant types having the same TYPE_FIELDS, so the following simply uses DECL_FIELD_CONTEXT directly (which is either the same for shared TYPE_FIELDS or not - in which case we can't use TYPE_MAIN_VARIANT anyway).
Bootstrap and regtest pending on x86_64-unknown-linux-gnu. Richard. 2014-06-10 Richard Biener <rguent...@suse.de> PR middle-end/61456 * tree-ssa-alias.c (nonoverlapping_component_refs_of_decl_p): Do not use the main variant for the type comparison. (ncr_compar): Likewise. (nonoverlapping_component_refs_p): Likewise. * g++.dg/opt/pr61456.C: New testcase. Index: gcc/tree-ssa-alias.c =================================================================== --- gcc/tree-ssa-alias.c (revision 211398) +++ gcc/tree-ssa-alias.c (working copy) @@ -835,8 +835,8 @@ nonoverlapping_component_refs_of_decl_p /* ??? We cannot simply use the type of operand #0 of the refs here as the Fortran compiler smuggles type punning into COMPONENT_REFs for common blocks instead of using unions like everyone else. */ - tree type1 = TYPE_MAIN_VARIANT (DECL_CONTEXT (field1)); - tree type2 = TYPE_MAIN_VARIANT (DECL_CONTEXT (field2)); + tree type1 = DECL_CONTEXT (field1); + tree type2 = DECL_CONTEXT (field2); /* We cannot disambiguate fields in a union or qualified union. */ if (type1 != type2 || TREE_CODE (type1) != RECORD_TYPE) @@ -866,10 +866,8 @@ ncr_compar (const void *field1_, const v { const_tree field1 = *(const_tree *) const_cast <void *>(field1_); const_tree field2 = *(const_tree *) const_cast <void *>(field2_); - unsigned int uid1 - = TYPE_UID (TYPE_MAIN_VARIANT (DECL_FIELD_CONTEXT (field1))); - unsigned int uid2 - = TYPE_UID (TYPE_MAIN_VARIANT (DECL_FIELD_CONTEXT (field2))); + unsigned int uid1 = TYPE_UID (DECL_FIELD_CONTEXT (field1)); + unsigned int uid2 = TYPE_UID (DECL_FIELD_CONTEXT (field2)); if (uid1 < uid2) return -1; else if (uid1 > uid2) @@ -893,7 +891,7 @@ nonoverlapping_component_refs_p (const_t while (TREE_CODE (x) == COMPONENT_REF) { tree field = TREE_OPERAND (x, 1); - tree type = TYPE_MAIN_VARIANT (DECL_FIELD_CONTEXT (field)); + tree type = DECL_FIELD_CONTEXT (field); if (TREE_CODE (type) == RECORD_TYPE) fieldsx.safe_push (field); x = TREE_OPERAND (x, 0); @@ -904,7 +902,7 @@ nonoverlapping_component_refs_p (const_t while (TREE_CODE (y) == COMPONENT_REF) { tree field = TREE_OPERAND (y, 1); - tree type = TYPE_MAIN_VARIANT (DECL_FIELD_CONTEXT (field)); + tree type = DECL_FIELD_CONTEXT (field); if (TREE_CODE (type) == RECORD_TYPE) fieldsy.safe_push (TREE_OPERAND (y, 1)); y = TREE_OPERAND (y, 0); @@ -915,8 +913,8 @@ nonoverlapping_component_refs_p (const_t /* Most common case first. */ if (fieldsx.length () == 1 && fieldsy.length () == 1) - return ((TYPE_MAIN_VARIANT (DECL_FIELD_CONTEXT (fieldsx[0])) - == TYPE_MAIN_VARIANT (DECL_FIELD_CONTEXT (fieldsy[0]))) + return ((DECL_FIELD_CONTEXT (fieldsx[0]) + == DECL_FIELD_CONTEXT (fieldsy[0])) && fieldsx[0] != fieldsy[0] && !(DECL_BIT_FIELD (fieldsx[0]) && DECL_BIT_FIELD (fieldsy[0]))); @@ -949,8 +947,8 @@ nonoverlapping_component_refs_p (const_t { const_tree fieldx = fieldsx[i]; const_tree fieldy = fieldsy[j]; - tree typex = TYPE_MAIN_VARIANT (DECL_FIELD_CONTEXT (fieldx)); - tree typey = TYPE_MAIN_VARIANT (DECL_FIELD_CONTEXT (fieldy)); + tree typex = DECL_FIELD_CONTEXT (fieldx); + tree typey = DECL_FIELD_CONTEXT (fieldy); if (typex == typey) { /* We're left with accessing different fields of a structure, Index: gcc/testsuite/g++.dg/opt/pr61456.C =================================================================== --- gcc/testsuite/g++.dg/opt/pr61456.C (revision 0) +++ gcc/testsuite/g++.dg/opt/pr61456.C (working copy) @@ -0,0 +1,26 @@ +// { dg-do compile } +// { dg-options "-O2 -std=c++11 -Werror=uninitialized" } + +int rand (); + +class Funcs +{ +public: + int *f1 (); + int *f2 (); +}; +typedef decltype (&Funcs::f1) pfunc; + +static int Set (Funcs * f, const pfunc & fp) +{ + (f->*fp) (); +} + +void +Foo () +{ + pfunc fp = &Funcs::f1; + if (rand ()) + fp = &Funcs::f2; + Set (0, fp); +}