On Wed, 27 Mar 2019, Richard Sandiford wrote:

> Richard Biener <rguent...@suse.de> writes:
> > Our beloved condition combining code to BIT_FIELD_REFs miscompiles
> > the testcase because it relies on operand_equal_p to detect equal
> > bases.  For some reason that very same operand_equal_p is
> > treating any dereference of a pointer based on the same pointer
> > or decl the same - idependent on the actual type used for the
> > access (in this case, two different sized structs).  Weirdly
> > it already checks alignment...
> >
> > The following patch makes operand_equal_p behave and more
> > in line with what it does for MEM_REF handling.
> >
> > Bootstrap & regtest running on x86_64-unknown-linux-gnu.
> >
> > Richard.
> >
> > 2019-03-14  Richard Biener  <rguent...@suse.de>
> >
> >     PR middle-end/89698
> >     * fold-const.c (operand_equal_p): For INDIRECT_REF check
> >     that the access types are similar.
> >
> >     * g++.dg/torture/pr89698.C: New testcase.
> >
> > Index: gcc/fold-const.c
> > ===================================================================
> > --- gcc/fold-const.c        (revision 269641)
> > +++ gcc/fold-const.c        (working copy)
> > @@ -3220,10 +3220,16 @@ operand_equal_p (const_tree arg0, const_
> >        switch (TREE_CODE (arg0))
> >     {
> >     case INDIRECT_REF:
> > -     if (!(flags & OEP_ADDRESS_OF)
> > -         && (TYPE_ALIGN (TREE_TYPE (arg0))
> > -             != TYPE_ALIGN (TREE_TYPE (arg1))))
> > -       return 0;
> > +     if (!(flags & OEP_ADDRESS_OF))
> > +       {
> > +         if (TYPE_ALIGN (TREE_TYPE (arg0))
> > +             != TYPE_ALIGN (TREE_TYPE (arg1)))
> > +           return 0;
> > +         /* Verify that the access types are compatible.  */
> > +         if (TYPE_MAIN_VARIANT (TREE_TYPE (arg0))
> > +             != TYPE_MAIN_VARIANT (TREE_TYPE (arg1)))
> > +           return 0;
> 
> Question from the peanut gallery, sorry, but: why's TYPE_MAIN_VARIANT
> rather than types_compatible_p the right check here?  E.g. if the
> dereferenced types are both pointers, but pointers to different types,
> wouldn't they normally be equivalent in gimple?

But this is GENERIC where the above is the usual check for
"same type".  In GIMPLE you never see an INDIRECT_REF.

Richard.

> Thanks,
> Richard
> 
> 
> > +       }
> >       flags &= ~OEP_ADDRESS_OF;
> >       return OP_SAME (0);
> >  
> > Index: gcc/testsuite/g++.dg/torture/pr89698.C
> > ===================================================================
> > --- gcc/testsuite/g++.dg/torture/pr89698.C  (nonexistent)
> > +++ gcc/testsuite/g++.dg/torture/pr89698.C  (working copy)
> > @@ -0,0 +1,28 @@
> > +/* { dg-do run } */
> > +
> > +extern "C" void abort (void);
> > +
> > +class A {
> > +    virtual void f(){};
> > +public:
> > +    int x;
> > +    A(int in): x(in) {};
> > +};
> > +
> > +class B: public A {
> > +public:
> > +    int y;
> > +    B(int in):A(in-1), y(in) {};
> > +};
> > +
> > +int test(void)
> > +{
> > +  int res;
> > +  B b(2);
> > +  A* bp = &b;
> > +  void* vp = dynamic_cast<void*>(bp);
> > +  if (((A*)vp)->x == 1 && ((B*)vp)->y == 2)
> > +    return 1;
> > +  return 0;
> > +}
> > +int main() { if (test() != 1) abort (); return 0; }
> 

-- 
Richard Biener <rguent...@suse.de>
SUSE Linux GmbH, Maxfeldstrasse 5, 90409 Nuernberg, Germany;
GF: Felix Imendörffer, Mary Higgins, Sri Rasiah; HRB 21284 (AG Nürnberg)

Reply via email to