On Tue, 2 Feb 2016, Jason Merrill wrote:

On 12/22/2015 12:07 AM, Patrick Palka wrote:
+  if (code == EQ_EXPR || code == NE_EXPR)
+    {
+      if (TREE_CODE (lhs) == PTRMEM_CST && CONSTANT_CLASS_P (rhs))
+       lhs = cplus_expand_constant (lhs);
+      if (TREE_CODE (rhs) == PTRMEM_CST && CONSTANT_CLASS_P (lhs))
+       rhs = cplus_expand_constant (rhs);
+    }

If both sides are PTRMEM_CST, we should be able to compare them without expanding, using cp_tree_equal.

Ah, okay.  Here's an updated patch that uses cp_tree_equal and avoids
calling cplus_expand_constant altogether, by assuming that we should
only expect to compare a PTRMEM_CST against another PTRMEM_CST or
against the constant -1.  I also improved the coverage of the test case.
Does this look reasonable?


gcc/cp/ChangeLog:

        * constexpr.c (cxx_eval_binary_expression): Fold equality
        comparisons involving PTRMEM_CSTs.

gcc/testsuite/ChangeLog:

        * g++.dg/cpp0x/constexpr-ptrmem5.C: New test.
---
 gcc/cp/constexpr.c                             | 21 +++++++++++++++++++--
 gcc/testsuite/g++.dg/cpp0x/constexpr-ptrmem5.C | 17 +++++++++++++++++
 2 files changed, 36 insertions(+), 2 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/constexpr-ptrmem5.C

diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c
index b076991..c5e6642 100644
--- a/gcc/cp/constexpr.c
+++ b/gcc/cp/constexpr.c
@@ -1593,7 +1593,7 @@ cxx_eval_binary_expression (const constexpr_ctx *ctx, 
tree t,
                            bool /*lval*/,
                            bool *non_constant_p, bool *overflow_p)
 {
-  tree r;
+  tree r = NULL_TREE;
   tree orig_lhs = TREE_OPERAND (t, 0);
   tree orig_rhs = TREE_OPERAND (t, 1);
   tree lhs, rhs;
@@ -1612,7 +1612,24 @@ cxx_eval_binary_expression (const constexpr_ctx *ctx, 
tree t,
   location_t loc = EXPR_LOCATION (t);
   enum tree_code code = TREE_CODE (t);
   tree type = TREE_TYPE (t);
-  r = fold_binary_loc (loc, code, type, lhs, rhs);
+
+  if ((code == EQ_EXPR || code == NE_EXPR))
+    {
+      bool is_code_eq = (code == EQ_EXPR);
+
+      if (TREE_CODE (lhs) == PTRMEM_CST
+         && TREE_CODE (rhs) == PTRMEM_CST)
+       r = constant_boolean_node (cp_tree_equal (lhs, rhs) == is_code_eq,
+                                  type);
+      else if ((TREE_CODE (lhs) == PTRMEM_CST
+               || TREE_CODE (rhs) == PTRMEM_CST)
+              && (integer_minus_onep (lhs)
+                  || integer_minus_onep (rhs)))
+       r = constant_boolean_node (code == NE_EXPR, type);
+    }
+
+  if (r == NULL_TREE)
+    r = fold_binary_loc (loc, code, type, lhs, rhs);
   if (r == NULL_TREE)
     {
       if (lhs == orig_lhs && rhs == orig_rhs)
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-ptrmem5.C 
b/gcc/testsuite/g++.dg/cpp0x/constexpr-ptrmem5.C
new file mode 100644
index 0000000..b1318c4
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-ptrmem5.C
@@ -0,0 +1,17 @@
+// { dg-do compile { target c++11 } }
+
+#define SA(x) static_assert ((x), #x)
+
+struct X { int a, b; };
+
+void
+foo ()
+{
+  SA (&X::a);
+  SA (&X::a == &X::a);
+  SA (!(&X::a != &X::a));
+  SA (&X::a != &X::b);
+  SA (!(&X::a == &X::b));
+  SA ((!&X::b) == 0);
+  SA (!(&X::b == 0));
+}
--
2.7.0.240.g19e8eb6

Reply via email to