On Mon, Jan 10, 2022 at 6:11 AM Richard Biener via Gcc-patches
<gcc-patches@gcc.gnu.org> wrote:
>
> On Thu, Jan 6, 2022 at 10:25 AM Jakub Jelinek via Gcc-patches
> <gcc-patches@gcc.gnu.org> wrote:
> >
> > Hi!
> >
> > The following testcase used to be incorrectly accepted.  The match.pd
> > optimization that uses address_compare punts on folding comparison
> > of start of one object and end of another one only when those addresses
> > are cast to integral types, when the comparison is done on pointer types
> > it assumes undefined behavior and decides to fold the comparison such
> > that the addresses don't compare equal even when they at runtime they
> > could be equal.
> > But C++ says it is undefined behavior and so during constant evaluation
> > we should reject those, so this patch adds !folding_initializer &&
> > check to that spot.
> >
> > Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
> >
> > Note, address_compare has some special cases, e.g. it assumes that
> > static vars are never adjacent to automatic vars, which is the case
> > for the usual layout where automatic vars are on the stack and after
> > .rodata/.data sections there is heap:
> >   /* Assume that automatic variables can't be adjacent to global
> >      variables.  */
> >   else if (is_global_var (base0) != is_global_var (base1))
> >     ;
> > Is it ok that during constant evaluation we don't treat those as undefined
> > behavior, or shall that be with !folding_initializer && too?
> >
> > Another special case is:
> >   if ((DECL_P (base0) && TREE_CODE (base1) == STRING_CST)
> >        || (TREE_CODE (base0) == STRING_CST && DECL_P (base1))
> >        || (TREE_CODE (base0) == STRING_CST
> >            && TREE_CODE (base1) == STRING_CST
> >            && ioff0 >= 0 && ioff1 >= 0
> >            && ioff0 < TREE_STRING_LENGTH (base0)
> >            && ioff1 < TREE_STRING_LENGTH (base1)
> >           /* This is a too conservative test that the STRING_CSTs
> >              will not end up being string-merged.  */
> >            && strncmp (TREE_STRING_POINTER (base0) + ioff0,
> >                        TREE_STRING_POINTER (base1) + ioff1,
> >                        MIN (TREE_STRING_LENGTH (base0) - ioff0,
> >                             TREE_STRING_LENGTH (base1) - ioff1)) != 0))
> >     ;
> >   else if (!DECL_P (base0) || !DECL_P (base1))
> >     return 2;
> > Here we similarly assume that vars aren't adjacent to string literals
> > or vice versa.  Do we need to stick !folding_initializer && to those
> > DECL_P vs. STRING_CST cases?  Though, because of the return 2; for
> > non-DECL_P that would mean rejecting comparisons like &var == &"foobar"[3]
> > etc. which ought to be fine, no?  So perhaps we need to watch for
> > decls. vs. STRING_CSTs like for DECLs whether the address is at the start
> > or at the end of the string literal or somewhere in between (at least
> > for folding_initializer)?
> > And yet another chapter but probably unsolvable is comparison of
> > string literal addresses.  I think pedantically in C++
> > &"foo"[0] == &"foo"[0] is undefined behavior, different occurences of
> > the same string literals might still not be merged in some implementations.
> > But constexpr const char *s = "foo"; &s[0] == &s[0] should be well defined,
> > and we aren't tracking anywhere whether the string literal was the same one
> > or different (and I think other compilers don't track that either).
>
> On my TODO list is to make &"foo" invalid and instead require &CONST_DECL
> (and DECL_INITIAL of it then being "foo"), that would make it possible to
> track the "original" string literal and perform string merging in a
> more considerate way.

Interesting because I wrote this would be one way to fix PR88925.

Thanks,
Andrew Pinski

>
> Richard.
>
> >
> > 2022-01-06  Jakub Jelinek  <ja...@redhat.com>
> >
> >         PR c++/89074
> >         * fold-const.c (address_compare): Punt on comparison of address of
> >         one object with address of end of another object if
> >         folding_initializer.
> >
> >         * g++.dg/cpp1y/constexpr-89074-1.C: New test.
> >
> > --- gcc/fold-const.c.jj 2022-01-05 20:30:08.731806756 +0100
> > +++ gcc/fold-const.c    2022-01-05 20:34:52.277822349 +0100
> > @@ -16627,7 +16627,7 @@ address_compare (tree_code code, tree ty
> >    /* If this is a pointer comparison, ignore for now even
> >       valid equalities where one pointer is the offset zero
> >       of one object and the other to one past end of another one.  */
> > -  else if (!INTEGRAL_TYPE_P (type))
> > +  else if (!folding_initializer && !INTEGRAL_TYPE_P (type))
> >      ;
> >    /* Assume that automatic variables can't be adjacent to global
> >       variables.  */
> > --- gcc/testsuite/g++.dg/cpp1y/constexpr-89074-1.C.jj   2022-01-05 
> > 20:43:03.696917484 +0100
> > +++ gcc/testsuite/g++.dg/cpp1y/constexpr-89074-1.C      2022-01-05 
> > 20:42:12.676634044 +0100
> > @@ -0,0 +1,28 @@
> > +// PR c++/89074
> > +// { dg-do compile { target c++14 } }
> > +
> > +constexpr bool
> > +foo ()
> > +{
> > +  int a[] = { 1, 2 };
> > +  int b[] = { 3, 4 };
> > +
> > +  if (&a[0] == &b[0])
> > +    return false;
> > +
> > +  if (&a[1] == &b[0])
> > +    return false;
> > +
> > +  if (&a[1] == &b[1])
> > +    return false;
> > +
> > +  if (&a[2] == &b[1])
> > +    return false;
> > +
> > +  if (&a[2] == &b[0])          // { dg-error "is not a constant 
> > expression" }
> > +    return false;
> > +
> > +  return true;
> > +}
> > +
> > +constexpr bool a = foo ();
> >
> >         Jakub
> >

Reply via email to