Hi, Jason, this is about C++ frontend producing two copies of same type with different TYPE_CANONICAL but same get_alias_set. Since the types are structurally different, this does not go well with LTO which no longer sees they are same. They are created in if (CLASSTYPE_NON_LAYOUT_POD_P (t) || CLASSTYPE_EMPTY_P (t)) { /* T needs a different layout as a base (eliding virtual bases or whatever). Create that version. */ tree base_t = make_node (TREE_CODE (t));
and later cxx_get_alias_set arranges they have same set by testing IS_FAKE_BASE_TYPE. I am not able to come with a testcase that triggers wrong code with LTO However compiling this testcase: struct E { ~E(); virtual void f() const; }; struct B : E {}; struct G : virtual B {}; struct A { virtual ~A(); }; struct J : E { int val; ~J() {if (val) __builtin_abort ();} void f() const { E *p = 0; p->f(); } }; J h; struct I : A, G, virtual B {}; Front-end produce two versions of J that do not pass gimple_canonical_types_compatible_p thus at compile time they have same alias set and at LTO time they are considered non-conflicting. Both types are mixed in one function: J::~J (struct J * const this) { int _1; struct E * _2; <bb 2> [local count: 1073741824]: this_4(D)->D.2376._vptr.E = &MEM <int (*__vtbl_ptr_type) ()[3]> [(void *)&_ZTV1J + 16B]; _1 = this_4(D)->val; if (_1 != 0) goto <bb 3>; [0.00%] else goto <bb 4>; [100.00%] <bb 3> [count: 0]: abort (); <bb 4> [local count: 1073741824]: _2 = &this_4(D)->D.2376; E::~E (_2); MEM[(struct &)this_4(D)] ={v} {CLOBBER}; return; } Here "(struct &)" cast is turning struct J into the other, incompatible, variant. I can't make FE to use the type anywhere else and this is why I do not get wrong code since we sort of ignore the clobber then (consider that the memory it guards is not used/initialized). Jason, is there a way to actually read/write into the copied structure? Putting same alias set but keeping canonical types different comfuses same_type_for_tbaa, is there a reason why we do not make canonical types same? It seems to me that we want 1) use same TYPE_CANONICAL for both variants of the type 2) teach LTO canonical type merging about fake bases (i.e. add a middle-end flag to do so). Or can we avoid these types from getting into instruction stream? (I suppose not - I guess point of using them in clobber is to get the size right) Honza