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