> > gcc/testsuite/ChangeLog: > > 2017-01-12 Martin Liska <mli...@suse.cz> > > PR ipa/71207 > * g++.dg/ipa/pr71207.C: New test. > > gcc/ChangeLog: > > 2017-01-12 Martin Liska <mli...@suse.cz> > > PR ipa/71207 > * ipa-polymorphic-call.c (contains_type_p): Fix wrong > assumption, add comment and renamed otr_type to inner_type. > --- > gcc/ipa-polymorphic-call.c | 22 ++++++++++---------- > gcc/testsuite/g++.dg/ipa/pr71207.C | 42 > ++++++++++++++++++++++++++++++++++++++ > 2 files changed, 53 insertions(+), 11 deletions(-) > create mode 100644 gcc/testsuite/g++.dg/ipa/pr71207.C > > diff --git a/gcc/ipa-polymorphic-call.c b/gcc/ipa-polymorphic-call.c > index da64ce4c6e0..c13fc858c86 100644 > --- a/gcc/ipa-polymorphic-call.c > +++ b/gcc/ipa-polymorphic-call.c > @@ -446,15 +446,15 @@ no_useful_type_info: > } > } > > -/* Return true if OUTER_TYPE contains OTR_TYPE at OFFSET. > - CONSIDER_PLACEMENT_NEW makes function to accept cases where OTR_TYPE can > +/* Return true if OUTER_TYPE contains INNER_TYPE at OFFSET. > + CONSIDER_PLACEMENT_NEW makes function to accept cases where INNER_TYPE can > be built within OUTER_TYPE by means of placement new. CONSIDER_BASES > makes > - function to accept cases where OTR_TYPE appears as base of OUTER_TYPE or > as > + function to accept cases where INNER_TYPE appears as base of OUTER_TYPE > or as > base of one of fields of OUTER_TYPE. */ > > static bool > contains_type_p (tree outer_type, HOST_WIDE_INT offset, > - tree otr_type, > + tree inner_type,
I would actually keep otr_type (or change it consistently in all cases). otr comes from OBJ_TYPE_REF and is used thorough the code (not my invention, comming from original binfo walking routine). OK with that change. I bleive I added the size check only to cut the recurision early which is not a big deal. > bool consider_placement_new, > bool consider_bases) > { > @@ -463,18 +463,18 @@ contains_type_p (tree outer_type, HOST_WIDE_INT offset, > /* Check that type is within range. */ > if (offset < 0) > return false; > - if (TYPE_SIZE (outer_type) && TYPE_SIZE (otr_type) > - && TREE_CODE (TYPE_SIZE (outer_type)) == INTEGER_CST > - && TREE_CODE (TYPE_SIZE (otr_type)) == INTEGER_CST > - && wi::ltu_p (wi::to_offset (TYPE_SIZE (outer_type)), > - (wi::to_offset (TYPE_SIZE (otr_type)) + offset))) > - return false; > + > + /* PR ipa/71207 > + As OUTER_TYPE can be a type which has a diamond virtual inheritance, > + it's not necessary that INNER_TYPE will fit within OUTER_TYPE with > + a given offset. It can happen that INNER_TYPE also contains a base > object, > + however it would point to the same instance in the OUTER_TYPE. */ > > context.offset = offset; > context.outer_type = TYPE_MAIN_VARIANT (outer_type); > context.maybe_derived_type = false; > context.dynamic = false; > - return context.restrict_to_inner_class (otr_type, consider_placement_new, > + return context.restrict_to_inner_class (inner_type, consider_placement_new, > consider_bases); > } > > diff --git a/gcc/testsuite/g++.dg/ipa/pr71207.C > b/gcc/testsuite/g++.dg/ipa/pr71207.C > new file mode 100644 > index 00000000000..19a03998460 > --- /dev/null > +++ b/gcc/testsuite/g++.dg/ipa/pr71207.C > @@ -0,0 +1,42 @@ > +/* PR ipa/71207 */ > +/* { dg-do run } */ > + > +class Class1 > +{ > +public: > + Class1() {}; > + virtual ~Class1() {}; > + > +protected: > + unsigned Field1; > +}; > + > +class Class2 : public virtual Class1 > +{ > +}; > + > +class Class3 : public virtual Class1 > +{ > +public: > + virtual void Method1() = 0; > + > + void Method2() > + { > + Method1(); > + } > +}; > + > +class Class4 : public Class2, public virtual Class3 > +{ > +public: > + Class4() {}; > + virtual void Method1() {}; > +}; > + > +int main() > +{ > + Class4 var1; > + var1.Method2(); > + > + return 0; > +} > -- > 2.11.0 >