public inbox for gcc-bugs@sourceware.org help / color / mirror / Atom feed
From: "jakub at gcc dot gnu.org" <gcc-bugzilla@gcc.gnu.org> To: gcc-bugs@gcc.gnu.org Subject: [Bug c++/89074] valid pointer equality constexpr comparison rejected Date: Wed, 05 Jan 2022 19:45:20 +0000 [thread overview] Message-ID: <bug-89074-4-O2HRiwQN04@http.gcc.gnu.org/bugzilla/> (raw) In-Reply-To: <bug-89074-4@http.gcc.gnu.org/bugzilla/> 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 ();
next prev parent reply other threads:[~2022-01-05 19:45 UTC|newest] Thread overview: 17+ messages / expand[flat|nested] mbox.gz Atom feed top [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 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 [this message] 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
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=bug-89074-4-O2HRiwQN04@http.gcc.gnu.org/bugzilla/ \ --to=gcc-bugzilla@gcc.gnu.org \ --cc=gcc-bugs@gcc.gnu.org \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: linkBe sure your reply has a Subject: header at the top and a blank line before the message body.
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).