public inbox for gcc-bugs@sourceware.org
help / color / mirror / Atom feed
* [Bug c++/89074] valid pointer equality constexpr comparison rejected
       [not found] <bug-89074-4@http.gcc.gnu.org/bugzilla/>
@ 2021-07-27  9:30 ` pinskia at gcc dot gnu.org
  2021-11-18 14:18 ` redi at gcc dot gnu.org
                   ` (15 subsequent siblings)
  16 siblings, 0 replies; 17+ messages in thread
From: pinskia at gcc dot gnu.org @ 2021-07-27  9:30 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89074

Andrew Pinski <pinskia at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |bobk-off at yandex dot ru

--- Comment #4 from Andrew Pinski <pinskia at gcc dot gnu.org> ---
*** Bug 81781 has been marked as a duplicate of this bug. ***

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [Bug c++/89074] valid pointer equality constexpr comparison rejected
       [not found] <bug-89074-4@http.gcc.gnu.org/bugzilla/>
  2021-07-27  9:30 ` [Bug c++/89074] valid pointer equality constexpr comparison rejected pinskia at gcc dot gnu.org
@ 2021-11-18 14:18 ` redi at gcc dot gnu.org
  2021-11-18 16:14 ` cvs-commit at gcc dot gnu.org
                   ` (14 subsequent siblings)
  16 siblings, 0 replies; 17+ messages in thread
From: redi at gcc dot gnu.org @ 2021-11-18 14:18 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89074

--- Comment #5 from Jonathan Wakely <redi at gcc dot gnu.org> ---
I think this is another case of the same bug:

constexpr bool
test()
{
  int a[] = { 1, 2 };
  int b[] = { 3, 4 };

  if (a+0 == b+0)       // OK
    return false;

  if (a+1 == b+0)       // ERROR
    return false;

  return true;
}

static_assert( test() );


g++ -std=c++20 ce.C -c

ce.C:16:20: error: non-constant condition for static assertion
   16 | static_assert( test() );
      |                ~~~~^~
ce.C:16:20:   in 'constexpr' expansion of 'test()'
ce.C:10:11: error: '((((int*)(& a)) + 4) == ((int*)(& b)))' is not a constant
expression
   10 |   if (a+1 == b+0)       // ERROR
      |       ~~~~^~~~~~

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [Bug c++/89074] valid pointer equality constexpr comparison rejected
       [not found] <bug-89074-4@http.gcc.gnu.org/bugzilla/>
  2021-07-27  9:30 ` [Bug c++/89074] valid pointer equality constexpr comparison rejected pinskia at gcc dot gnu.org
  2021-11-18 14:18 ` redi at gcc dot gnu.org
@ 2021-11-18 16:14 ` cvs-commit at gcc dot gnu.org
  2022-01-05 16:38 ` ppalka at gcc dot gnu.org
                   ` (13 subsequent siblings)
  16 siblings, 0 replies; 17+ messages in thread
From: cvs-commit at gcc dot gnu.org @ 2021-11-18 16:14 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89074

--- Comment #6 from CVS Commits <cvs-commit at gcc dot gnu.org> ---
The master branch has been updated by Jonathan Wakely <redi@gcc.gnu.org>:

https://gcc.gnu.org/g:ca243ada71656651a8753e88164a1f0f019be1c3

commit r12-5376-gca243ada71656651a8753e88164a1f0f019be1c3
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Thu Nov 18 12:39:20 2021 +0000

    libstdc++: Fix std::char_traits<C>::move for constexpr

    The constexpr branch in __gnu_cxx::char_traits::move compares the string
    arguments to see if they overlap, but relational comparisons between
    unrelated pointers are not core constant expressions.

    I want to replace the comparisons with a loop using pointer equality to
    determine whether the end of the source string is in the destination
    string. However, that doesn't work with GCC, due to PR c++/89074 so
    allocate a temporary buffer instead and copy out into that first, so
    that overlapping source and destination don't matter. The allocation
    isn't supported by the current Intel icc so use the loop as a fallback.

    libstdc++-v3/ChangeLog:

            * include/bits/char_traits.h (__gnu_cxx::char_traits::move):
            Do not compare unrelated pointers during constant evaluation.
            *
testsuite/21_strings/char_traits/requirements/constexpr_functions_c++20.cc:
            Improve tests for char_traits::move.

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [Bug c++/89074] valid pointer equality constexpr comparison rejected
       [not found] <bug-89074-4@http.gcc.gnu.org/bugzilla/>
                   ` (2 preceding siblings ...)
  2021-11-18 16:14 ` cvs-commit at gcc dot gnu.org
@ 2022-01-05 16:38 ` ppalka at gcc dot gnu.org
  2022-01-05 16:56 ` jakub at gcc dot gnu.org
                   ` (12 subsequent siblings)
  16 siblings, 0 replies; 17+ messages in thread
From: ppalka at gcc dot gnu.org @ 2022-01-05 16:38 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89074

Patrick Palka <ppalka at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |ppalka at gcc dot gnu.org

--- Comment #7 from Patrick Palka <ppalka at gcc dot gnu.org> ---
The first three testcases are PR94716 and accepted by GCC 12.

We still incorrectly reject the comment #5 testcase though.

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [Bug c++/89074] valid pointer equality constexpr comparison rejected
       [not found] <bug-89074-4@http.gcc.gnu.org/bugzilla/>
                   ` (3 preceding siblings ...)
  2022-01-05 16:38 ` ppalka at gcc dot gnu.org
@ 2022-01-05 16:56 ` jakub at gcc dot gnu.org
  2022-01-05 17:07 ` ppalka at gcc dot gnu.org
                   ` (11 subsequent siblings)
  16 siblings, 0 replies; 17+ messages in thread
From: jakub at gcc dot gnu.org @ 2022-01-05 16:56 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89074

--- Comment #8 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
At least when not constant evaluating that, a + 2 can be equal to b + 0 or can
be different, shouldn't we reject at least that?
It is true that for automatic variables if at least one of the pointers is into
a middle of some automatic var and the other is to some other var they can't be
equal.

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [Bug c++/89074] valid pointer equality constexpr comparison rejected
       [not found] <bug-89074-4@http.gcc.gnu.org/bugzilla/>
                   ` (4 preceding siblings ...)
  2022-01-05 16:56 ` jakub at gcc dot gnu.org
@ 2022-01-05 17:07 ` ppalka at gcc dot gnu.org
  2022-01-05 19:45 ` jakub at gcc dot gnu.org
                   ` (10 subsequent siblings)
  16 siblings, 0 replies; 17+ messages in thread
From: ppalka at gcc dot gnu.org @ 2022-01-05 17:07 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89074

--- Comment #9 from Patrick Palka <ppalka at gcc dot gnu.org> ---
(In reply to Jakub Jelinek from comment #8)
> At least when not constant evaluating that, a + 2 can be equal to b + 0 or
> can be different, shouldn't we reject at least that?

I think so, according to https://eel.is/c++draft/expr.eq#3.1 and
http://eel.is/c++draft/expr.const#5.25

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [Bug c++/89074] valid pointer equality constexpr comparison rejected
       [not found] <bug-89074-4@http.gcc.gnu.org/bugzilla/>
                   ` (5 preceding siblings ...)
  2022-01-05 17:07 ` ppalka at gcc dot gnu.org
@ 2022-01-05 19:45 ` jakub at gcc dot gnu.org
  2022-01-05 19:56 ` jakub at gcc dot gnu.org
                   ` (9 subsequent siblings)
  16 siblings, 0 replies; 17+ messages in thread
From: jakub at gcc dot gnu.org @ 2022-01-05 19:45 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89074

--- Comment #10 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
So, for #c5,
  if (&a[1] == &b[0])
instead of if (a+1 == b+0) works right, that is handled by the match.pd
  (cmp (convert1?@2 addr@0) (convert2? addr@1))
address_compare simplification.  And it also works for GIMPLE, where we have
in gimple-fold.c the:
            /* Translate &x + CST into an invariant form suitable for
               further propagation.  */
            if (subcode == POINTER_PLUS_EXPR)
              {
                tree op0 = (*valueize) (gimple_assign_rhs1 (stmt));
                tree op1 = (*valueize) (gimple_assign_rhs2 (stmt));
                if (TREE_CODE (op0) == ADDR_EXPR
                    && TREE_CODE (op1) == INTEGER_CST)
                  {
                    tree off = fold_convert (ptr_type_node, op1);
                    return build1_loc
                        (loc, ADDR_EXPR, TREE_TYPE (op0),
                         fold_build2 (MEM_REF,
                                      TREE_TYPE (TREE_TYPE (op0)),
                                      unshare_expr (op0), off));
                  }
              }
I think we don't do this for GENERIC because that can seriously break the
constant evaluation, the details on which exact field is accessed can be lost
in there.
But, if we take e.g.
struct S { int s; };
struct T : public S {};
struct U : public T {};

constexpr bool
test()
{
  U a[] = { 1, 2, 3, 4 };
  U b[] = { 5, 6, 7, 8 };
  T *c = (T *) a + 1;
  S *d = (S *) c + 2;
  S *e = (S *) b + 1;

  if (a+0 == b+0)       // OK
    return false;

  if (d == e)       // ERROR
    return false;

  return true;
}

static_assert( test() );
then we can see the comparison is tried on
‘((((S*)((& a[0].U::<anonymous>) + 4)) + 8) == ((&
b[0].U::<anonymous>.T::<anonymous>) + 4))’ is not a constant expression
so the multiple pointer_plus aren't merged in there either.
Hasving a GENERIC guarded variant of the address_compare with one pointer_plus
in one or the other or both operands might be still doable, but the above shows
that it wouldn't be sufficient.
So, perhaps instead if simple comparison fails during constexpr evaluation,
we could call some helper function that looks through cast and optimizes the
POINTER_PLUS into MEM_REF that it folds and then we'd try to compare it again
(or call that helper function regardless on both comparison operands)?

Another thing is that the following testcase isn't rejected:
2022-01-05  Jakub Jelinek  <jakub@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 ();

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [Bug c++/89074] valid pointer equality constexpr comparison rejected
       [not found] <bug-89074-4@http.gcc.gnu.org/bugzilla/>
                   ` (6 preceding siblings ...)
  2022-01-05 19:45 ` jakub at gcc dot gnu.org
@ 2022-01-05 19:56 ` jakub at gcc dot gnu.org
  2022-01-05 22:07 ` cvs-commit at gcc dot gnu.org
                   ` (8 subsequent siblings)
  16 siblings, 0 replies; 17+ messages in thread
From: jakub at gcc dot gnu.org @ 2022-01-05 19:56 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89074

--- Comment #11 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
There are some further questions though.
E.g. address_compare has a smart code to assume that static vars will never be
adjacent to automatic vars or vice versa (the implementation guarantees that):
  /* Assume that automatic variables can't be adjacent to global
     variables.  */
  else if (is_global_var (base0) != is_global_var (base1))
    ;
or similarly there is code that assumes that string literals won't be adjacent
to  user variables or vice versa:
  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))
    ;
The question is what do we want for folding_initializer cases.
Do we want to add !folding_initializer && to the is_global_var != checks and
the first two above (the STRING_CST vs. STRING_CST in some form is needed I
think)?
Though, there is
  else if (!DECL_P (base0) || !DECL_P (base1))
    return 2;
and so such !folding_initalizer && in there would reject valid cases where
a pointer doesn't point to start of a string or end of it.

And in another PR, we have mentioned that &"foo"[0] != &"foo"[0] is
pedantically
not a constant expression, but if it was e.g. const char *s = "foo"; &s[0] !=
&s[0], then it would be well defined, and we certainly don't track whether it
must be the same string literal or could be another one (neither does clang++
AFAIK).

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [Bug c++/89074] valid pointer equality constexpr comparison rejected
       [not found] <bug-89074-4@http.gcc.gnu.org/bugzilla/>
                   ` (7 preceding siblings ...)
  2022-01-05 19:56 ` jakub at gcc dot gnu.org
@ 2022-01-05 22:07 ` cvs-commit at gcc dot gnu.org
  2022-01-05 22:07 ` cvs-commit at gcc dot gnu.org
                   ` (7 subsequent siblings)
  16 siblings, 0 replies; 17+ messages in thread
From: cvs-commit at gcc dot gnu.org @ 2022-01-05 22:07 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89074

--- Comment #12 from CVS Commits <cvs-commit at gcc dot gnu.org> ---
The releases/gcc-10 branch has been updated by Jonathan Wakely
<redi@gcc.gnu.org>:

https://gcc.gnu.org/g:0d566335a31722f8044852d9a24f492830ae5789

commit r10-10381-g0d566335a31722f8044852d9a24f492830ae5789
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Thu Nov 18 12:39:20 2021 +0000

    libstdc++: Fix std::char_traits<C>::move for constexpr

    The constexpr branch in __gnu_cxx::char_traits::move compares the string
    arguments to see if they overlap, but relational comparisons between
    unrelated pointers are not core constant expressions.

    I want to replace the comparisons with a loop using pointer equality to
    determine whether the end of the source string is in the destination
    string. However, that doesn't work with GCC, due to PR c++/89074 so
    allocate a temporary buffer instead and copy out into that first, so
    that overlapping source and destination don't matter. The allocation
    isn't supported by the current Intel icc so use the loop as a fallback.

    libstdc++-v3/ChangeLog:

            * include/bits/char_traits.h (__gnu_cxx::char_traits::move):
            Do not compare unrelated pointers during constant evaluation.
            *
testsuite/21_strings/char_traits/requirements/constexpr_functions_c++20.cc:
            Improve tests for char_traits::move.

    (cherry picked from commit ca243ada71656651a8753e88164a1f0f019be1c3)

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [Bug c++/89074] valid pointer equality constexpr comparison rejected
       [not found] <bug-89074-4@http.gcc.gnu.org/bugzilla/>
                   ` (8 preceding siblings ...)
  2022-01-05 22:07 ` cvs-commit at gcc dot gnu.org
@ 2022-01-05 22:07 ` cvs-commit at gcc dot gnu.org
  2022-01-06 20:01 ` jakub at gcc dot gnu.org
                   ` (6 subsequent siblings)
  16 siblings, 0 replies; 17+ messages in thread
From: cvs-commit at gcc dot gnu.org @ 2022-01-05 22:07 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89074

--- Comment #13 from CVS Commits <cvs-commit at gcc dot gnu.org> ---
The releases/gcc-11 branch has been updated by Jonathan Wakely
<redi@gcc.gnu.org>:

https://gcc.gnu.org/g:226210894e53259940a8e1453125e37c65299ba4

commit r11-9441-g226210894e53259940a8e1453125e37c65299ba4
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Thu Nov 18 12:39:20 2021 +0000

    libstdc++: Fix std::char_traits<C>::move for constexpr

    The constexpr branch in __gnu_cxx::char_traits::move compares the string
    arguments to see if they overlap, but relational comparisons between
    unrelated pointers are not core constant expressions.

    I want to replace the comparisons with a loop using pointer equality to
    determine whether the end of the source string is in the destination
    string. However, that doesn't work with GCC, due to PR c++/89074 so
    allocate a temporary buffer instead and copy out into that first, so
    that overlapping source and destination don't matter. The allocation
    isn't supported by the current Intel icc so use the loop as a fallback.

    libstdc++-v3/ChangeLog:

            * include/bits/char_traits.h (__gnu_cxx::char_traits::move):
            Do not compare unrelated pointers during constant evaluation.
            *
testsuite/21_strings/char_traits/requirements/constexpr_functions_c++20.cc:
            Improve tests for char_traits::move.

    (cherry picked from commit ca243ada71656651a8753e88164a1f0f019be1c3)

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [Bug c++/89074] valid pointer equality constexpr comparison rejected
       [not found] <bug-89074-4@http.gcc.gnu.org/bugzilla/>
                   ` (9 preceding siblings ...)
  2022-01-05 22:07 ` cvs-commit at gcc dot gnu.org
@ 2022-01-06 20:01 ` jakub at gcc dot gnu.org
  2022-01-08  8:54 ` cvs-commit at gcc dot gnu.org
                   ` (5 subsequent siblings)
  16 siblings, 0 replies; 17+ messages in thread
From: jakub at gcc dot gnu.org @ 2022-01-06 20:01 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89074

Jakub Jelinek <jakub at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|NEW                         |ASSIGNED
           Assignee|unassigned at gcc dot gnu.org      |jakub at gcc dot gnu.org

--- Comment #14 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
Created attachment 52136
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=52136&action=edit
gcc12-pr89074.patch

Another patch on top of
https://gcc.gnu.org/pipermail/gcc-patches/2022-January/587745.html
What should be still done is when constexpr evaluating POINTER_PLUS_EXPR
diagnose out of bounds accesses like e.g. ARRAY_REF evaluation does.

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [Bug c++/89074] valid pointer equality constexpr comparison rejected
       [not found] <bug-89074-4@http.gcc.gnu.org/bugzilla/>
                   ` (10 preceding siblings ...)
  2022-01-06 20:01 ` jakub at gcc dot gnu.org
@ 2022-01-08  8:54 ` cvs-commit at gcc dot gnu.org
  2022-01-14 11:08 ` cvs-commit at gcc dot gnu.org
                   ` (4 subsequent siblings)
  16 siblings, 0 replies; 17+ messages in thread
From: cvs-commit at gcc dot gnu.org @ 2022-01-08  8:54 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89074

--- Comment #15 from CVS Commits <cvs-commit at gcc dot gnu.org> ---
The master branch has been updated by Jakub Jelinek <jakub@gcc.gnu.org>:

https://gcc.gnu.org/g:51d464b608b38b9e2007948d10b1e0f1dcec142c

commit r12-6382-g51d464b608b38b9e2007948d10b1e0f1dcec142c
Author: Jakub Jelinek <jakub@redhat.com>
Date:   Sat Jan 8 09:53:00 2022 +0100

    c++, match.pd: Evaluate in constant evaluation comparisons like &var1 + 12
== &var2 + 24 [PR89074]

    The match.pd address_comparison simplification can only handle
    ADDR_EXPR comparisons possibly converted to some other type (I wonder
    if we shouldn't restrict it in address_compare to casts to pointer
    types or pointer-sized integer types, I think we shouldn't optimize
    (short) (&var) == (short) (&var2) because we really don't know whether
    it will be true or false).  On GIMPLE, most of pointer to pointer
    casts are useless and optimized away and further we have in
    gimple_fold_stmt_to_constant_1 an optimization that folds
    &something p+ const_int
    into
    &MEM_REF[..., off]
    On GENERIC, we don't do that and e.g. for constant evaluation it
    could be pretty harmful if e.g. such pointers are dereferenced, because
    it can lose what exact field it was starting with etc., all it knows
    is the base and offset, type and alias set.
    Instead of teaching the match.pd address_compare about 3 extra variants
    where one or both compared operands are pointer_plus, this patch attempts
    to fold operands of comparisons similarly to gimple_fold_stmt_to_constant_1
    before calling fold_binary on it.
    There is another thing though, while we do have (x p+ y) p+ z to
    x p+ (y + z) simplification which works on GIMPLE well because of the
    useless pointer conversions, on GENERIC we can have pointer casts in
between
    and at that point we can end up with large expressions like
    ((type3) (((type2) ((type1) (&var + 2) + 2) + 2) + 2))
    etc.  Pointer-plus doesn't really care what exact pointer type it has as
    long as it is a pointer, so the following match.pd simplification for
    GENERIC only (it is useless for GIMPLE) also moves the cast so that nested
    p+ can be simplified.

    Note, I've noticed we don't really diagnose going out of bounds with
    pointer_plus (unlike e.g. with ARRAY_REF) during constant evaluation, I
    think another patch for cxx_eval_binary_expression with POINTER_PLUS will
be
    needed.  But it isn't clear to me what exactly it should do in case of
    subobjects.  If we start with address of a whole var, (&var), I guess we
    should diagnose if the pointer_plus gets before start of the var (i.e.
    "negative") or 1 byte past the end of the var, but what if we start with
    &var.field or &var.field[3] ?  For &var.field, shall we diagnose out of
    bounds of field (except perhaps flexible members?) or the whole var?
    For ARRAY_REFs, I assume we must at least strip all the outer ARRAY_REFs
    and so start with &var.field too, right?

    2022-01-08  Jakub Jelinek  <jakub@redhat.com>

            PR c++/89074
    gcc/
            * match.pd ((ptr) (x p+ y) p+ z -> (ptr) (x p+ (y + z))): New
GENERIC
            simplification.
    gcc/cp/
            * constexpr.c (cxx_maybe_fold_addr_pointer_plus): New function.
            (cxx_eval_binary_expression): Use it.
    gcc/testsuite/
            * g++.dg/cpp1y/constexpr-89074-2.C: New test.
            * g++.dg/cpp1z/constexpr-89074-1.C: New test.

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [Bug c++/89074] valid pointer equality constexpr comparison rejected
       [not found] <bug-89074-4@http.gcc.gnu.org/bugzilla/>
                   ` (11 preceding siblings ...)
  2022-01-08  8:54 ` cvs-commit at gcc dot gnu.org
@ 2022-01-14 11:08 ` cvs-commit at gcc dot gnu.org
  2022-01-19  8:26 ` cvs-commit at gcc dot gnu.org
                   ` (3 subsequent siblings)
  16 siblings, 0 replies; 17+ messages in thread
From: cvs-commit at gcc dot gnu.org @ 2022-01-14 11:08 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89074

--- Comment #16 from CVS Commits <cvs-commit at gcc dot gnu.org> ---
The master branch has been updated by Jakub Jelinek <jakub@gcc.gnu.org>:

https://gcc.gnu.org/g:d686d5d85c23451c03799dc55e456b73065f7333

commit r12-6578-gd686d5d85c23451c03799dc55e456b73065f7333
Author: Jakub Jelinek <jakub@redhat.com>
Date:   Fri Jan 14 12:07:49 2022 +0100

    c++: Reject in constant evaluation address comparisons of start of one var
and end of another [PR89074]

    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.

    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).

    2022-01-14  Jakub Jelinek  <jakub@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.

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [Bug c++/89074] valid pointer equality constexpr comparison rejected
       [not found] <bug-89074-4@http.gcc.gnu.org/bugzilla/>
                   ` (12 preceding siblings ...)
  2022-01-14 11:08 ` cvs-commit at gcc dot gnu.org
@ 2022-01-19  8:26 ` cvs-commit at gcc dot gnu.org
  2022-02-06 10:21 ` cvs-commit at gcc dot gnu.org
                   ` (2 subsequent siblings)
  16 siblings, 0 replies; 17+ messages in thread
From: cvs-commit at gcc dot gnu.org @ 2022-01-19  8:26 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89074

--- Comment #17 from CVS Commits <cvs-commit at gcc dot gnu.org> ---
The master branch has been updated by Jakub Jelinek <jakub@gcc.gnu.org>:

https://gcc.gnu.org/g:b834435c8fa4cb9424787fe3044a49fef7992de8

commit r12-6726-gb834435c8fa4cb9424787fe3044a49fef7992de8
Author: Jakub Jelinek <jakub@redhat.com>
Date:   Wed Jan 19 09:26:13 2022 +0100

    fold-const: Optimize &"foo"[0] == "foo" [PR89074]

    This is a non-C++ related part from the PR89074 address_compare changes.
    For "foo" == "foo" we already optimize this from the (cmp @0 @0)
    simplification, because we use operand_equal_p in that case
    and operand_equal_p also compares the STRING_CSTs bytes rather than
    just addresses.

    2022-01-19  Jakub Jelinek  <jakub@redhat.com>

            PR c++/89074
            * fold-const.cc (address_compare): Consider different STRING_CSTs
            with the same lengths that memcmp the same as equal, not different.

            * gcc.dg/tree-ssa/pr89074.c: New test.

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [Bug c++/89074] valid pointer equality constexpr comparison rejected
       [not found] <bug-89074-4@http.gcc.gnu.org/bugzilla/>
                   ` (13 preceding siblings ...)
  2022-01-19  8:26 ` cvs-commit at gcc dot gnu.org
@ 2022-02-06 10:21 ` cvs-commit at gcc dot gnu.org
  2022-07-07 16:38 ` cvs-commit at gcc dot gnu.org
  2022-11-07 14:16 ` ppalka at gcc dot gnu.org
  16 siblings, 0 replies; 17+ messages in thread
From: cvs-commit at gcc dot gnu.org @ 2022-02-06 10:21 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89074

--- Comment #18 from CVS Commits <cvs-commit at gcc dot gnu.org> ---
The master branch has been updated by Jakub Jelinek <jakub@gcc.gnu.org>:

https://gcc.gnu.org/g:f9e900ce9b17dc7d3a3809d0b0648ebe529a87c5

commit r12-7075-gf9e900ce9b17dc7d3a3809d0b0648ebe529a87c5
Author: Jakub Jelinek <jakub@redhat.com>
Date:   Sun Feb 6 11:16:29 2022 +0100

    c++: Further address_compare fixes [PR89074]

    This patch introduces folding_cxx_constexpr, folding_initializer is used
    for both C and C++ initializer/constant expression folding and enables more
    optimizations over what we do normally at runtime, while
folding_cxx_constexpr
    is used only during C++ constant expression folding and disables some
optimizations.

    The patch improves STRING_CST vs. STRING_CST folding, for
folding_initializer
    FUNCTION_DECL vs. FUNCTION_DECL folding, disables some optimizations like
    is_global_var != is_global_var or STRING_CST vs. DECL_P for
folding_cxx_constexpr
    etc.

    2022-02-06  Jakub Jelinek  <jakub@redhat.com>

            PR c++/89074
            PR c++/104033
            * fold-const.h (folding_initializer): Adjust comment.
            (folding_cxx_constexpr): Declare.
            * fold-const.cc (folding_initializer): Adjust comment.
            (folding_cxx_constexpr): New variable.
            (address_compare): Restrict the decl vs. STRING_CST
            or vice versa or STRING_CST vs. STRING_CST or
            is_global_var != is_global_var optimizations to
!folding_cxx_constexpr.
            Punt for FUNCTION_DECLs with non-zero offsets.  If
folding_initializer,
            assume non-aliased functions have non-zero size and have different
            addresses.  For folding_cxx_constexpr, punt on comparisons of start
            of some object and end of another one, regardless whether it is a
decl
            or string literal.  Also punt for folding_cxx_constexpr on
            STRING_CST vs. STRING_CST comparisons if the two literals could be
            overlapping.

            * constexpr.cc (cxx_eval_binary_expression): Temporarily set
            folding_cxx_constexpr.

            * g++.dg/cpp1y/constexpr-89074-3.C: New test.

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [Bug c++/89074] valid pointer equality constexpr comparison rejected
       [not found] <bug-89074-4@http.gcc.gnu.org/bugzilla/>
                   ` (14 preceding siblings ...)
  2022-02-06 10:21 ` cvs-commit at gcc dot gnu.org
@ 2022-07-07 16:38 ` cvs-commit at gcc dot gnu.org
  2022-11-07 14:16 ` ppalka at gcc dot gnu.org
  16 siblings, 0 replies; 17+ messages in thread
From: cvs-commit at gcc dot gnu.org @ 2022-07-07 16:38 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89074

--- Comment #19 from CVS Commits <cvs-commit at gcc dot gnu.org> ---
The master branch has been updated by Jonathan Wakely <redi@gcc.gnu.org>:

https://gcc.gnu.org/g:ad6135e261ced29972e5aa33404e45bcdd99440f

commit r13-1561-gad6135e261ced29972e5aa33404e45bcdd99440f
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Thu Jul 7 13:40:20 2022 +0100

    libstdc++: Remove workaround in __gnu_cxx::char_traits::move [PR89074]

    The front-end bug that prevented this constexpr loop from working has
    been fixed since GCC 12.1 so we can remove the workaround.

    libstdc++-v3/ChangeLog:

            PR c++/89074
            * include/bits/char_traits.h (__gnu_cxx::char_traits::move):
            Remove workaround for front-end bug.

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [Bug c++/89074] valid pointer equality constexpr comparison rejected
       [not found] <bug-89074-4@http.gcc.gnu.org/bugzilla/>
                   ` (15 preceding siblings ...)
  2022-07-07 16:38 ` cvs-commit at gcc dot gnu.org
@ 2022-11-07 14:16 ` ppalka at gcc dot gnu.org
  16 siblings, 0 replies; 17+ messages in thread
From: ppalka at gcc dot gnu.org @ 2022-11-07 14:16 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89074

Patrick Palka <ppalka at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|ASSIGNED                    |RESOLVED
   Target Milestone|---                         |12.0
         Resolution|---                         |FIXED

--- Comment #20 from Patrick Palka <ppalka at gcc dot gnu.org> ---
Thus fixed since GCC 12

^ permalink raw reply	[flat|nested] 17+ messages in thread

end of thread, other threads:[~2022-11-07 14:16 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <bug-89074-4@http.gcc.gnu.org/bugzilla/>
2021-07-27  9:30 ` [Bug c++/89074] valid pointer equality constexpr comparison rejected pinskia at gcc dot gnu.org
2021-11-18 14:18 ` redi at gcc dot gnu.org
2021-11-18 16:14 ` cvs-commit at gcc dot gnu.org
2022-01-05 16:38 ` ppalka at gcc dot gnu.org
2022-01-05 16:56 ` jakub at gcc dot gnu.org
2022-01-05 17:07 ` ppalka at gcc dot gnu.org
2022-01-05 19:45 ` jakub at gcc dot gnu.org
2022-01-05 19:56 ` jakub at gcc dot gnu.org
2022-01-05 22:07 ` cvs-commit at gcc dot gnu.org
2022-01-05 22:07 ` cvs-commit at gcc dot gnu.org
2022-01-06 20:01 ` jakub at gcc dot gnu.org
2022-01-08  8:54 ` cvs-commit at gcc dot gnu.org
2022-01-14 11:08 ` cvs-commit at gcc dot gnu.org
2022-01-19  8:26 ` cvs-commit at gcc dot gnu.org
2022-02-06 10:21 ` cvs-commit at gcc dot gnu.org
2022-07-07 16:38 ` cvs-commit at gcc dot gnu.org
2022-11-07 14:16 ` ppalka at gcc dot gnu.org

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).