* [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