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 ();

  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: link
Be 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).