summaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorpaolo <paolo@138bc75d-0d04-0410-961f-82ee72b054a4>2006-12-01 15:55:11 +0000
committerpaolo <paolo@138bc75d-0d04-0410-961f-82ee72b054a4>2006-12-01 15:55:11 +0000
commit894342c13b2795fc72fda324c138bfd716930d80 (patch)
treece2a5f0b7bbe59c508fd8ca9dae17ecf20026a7b /gcc
parent351ae60b82798f1b558434bf7358c62238295608 (diff)
downloadgcc-894342c13b2795fc72fda324c138bfd716930d80.tar.gz
2006-12-01 Ryan Mansfield <rmansfield@qnx.com>
PR c++/29066 * typeck.c (build_binary_op): Fix pointer to member function comparison for ptrmemfunc_vbit_in_delta targets. 2006-12-01 Ryan Mansfield <rmansfield@qnx.com> PR c++/29066 * g++.dg/expr/pr29066.c: New. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@119403 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog6
-rw-r--r--gcc/cp/typeck.c87
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/g++.dg/expr/pr29066.C42
4 files changed, 124 insertions, 16 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index c9528ca19be..edcb3880e68 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,9 @@
+2006-12-01 Ryan Mansfield <rmansfield@qnx.com>
+
+ PR c++/29066
+ * typeck.c (build_binary_op): Fix pointer to member function
+ comparison for ptrmemfunc_vbit_in_delta targets.
+
2006-12-01 Dirk Mueller <dmueller@suse.de>
PR c++/18313
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 4146bf0e597..c5c9f38bbb9 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -3266,8 +3266,28 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
}
else if (TYPE_PTRMEMFUNC_P (type0) && null_ptr_cst_p (op1))
{
- op0 = build_ptrmemfunc_access_expr (op0, pfn_identifier);
- op1 = cp_convert (TREE_TYPE (op0), integer_zero_node);
+ if (TARGET_PTRMEMFUNC_VBIT_LOCATION
+ == ptrmemfunc_vbit_in_delta)
+ {
+ tree pfn0 = pfn_from_ptrmemfunc (op0);
+ tree delta0 = build_ptrmemfunc_access_expr (op0,
+ delta_identifier);
+ tree e1 = cp_build_binary_op (EQ_EXPR,
+ pfn0,
+ fold_convert (TREE_TYPE (pfn0),
+ integer_zero_node));
+ tree e2 = cp_build_binary_op (BIT_AND_EXPR,
+ delta0,
+ integer_one_node);
+ e2 = cp_build_binary_op (EQ_EXPR, e2, integer_zero_node);
+ op0 = cp_build_binary_op (TRUTH_ANDIF_EXPR, e1, e2);
+ op1 = cp_convert (TREE_TYPE (op0), integer_one_node);
+ }
+ else
+ {
+ op0 = build_ptrmemfunc_access_expr (op0, pfn_identifier);
+ op1 = cp_convert (TREE_TYPE (op0), integer_zero_node);
+ }
result_type = TREE_TYPE (op0);
}
else if (TYPE_PTRMEMFUNC_P (type1) && null_ptr_cst_p (op0))
@@ -3290,26 +3310,61 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
if (TREE_SIDE_EFFECTS (op1))
op1 = save_expr (op1);
- /* We generate:
-
- (op0.pfn == op1.pfn
- && (!op0.pfn || op0.delta == op1.delta))
-
- The reason for the `!op0.pfn' bit is that a NULL
- pointer-to-member is any member with a zero PFN; the
- DELTA field is unspecified. */
pfn0 = pfn_from_ptrmemfunc (op0);
pfn1 = pfn_from_ptrmemfunc (op1);
delta0 = build_ptrmemfunc_access_expr (op0,
delta_identifier);
delta1 = build_ptrmemfunc_access_expr (op1,
delta_identifier);
- e1 = cp_build_binary_op (EQ_EXPR, delta0, delta1);
- e2 = cp_build_binary_op (EQ_EXPR,
- pfn0,
- cp_convert (TREE_TYPE (pfn0),
- integer_zero_node));
- e1 = cp_build_binary_op (TRUTH_ORIF_EXPR, e1, e2);
+ if (TARGET_PTRMEMFUNC_VBIT_LOCATION
+ == ptrmemfunc_vbit_in_delta)
+ {
+ /* We generate:
+
+ (op0.pfn == op1.pfn
+ && ((op0.delta == op1.delta)
+ || (!op0.pfn && op0.delta & 1 == 0
+ && op1.delta & 1 == 0))
+
+ The reason for the `!op0.pfn' bit is that a NULL
+ pointer-to-member is any member with a zero PFN and
+ LSB of the DELTA field is 0. */
+
+ e1 = cp_build_binary_op (BIT_AND_EXPR,
+ delta0,
+ integer_one_node);
+ e1 = cp_build_binary_op (EQ_EXPR, e1, integer_zero_node);
+ e2 = cp_build_binary_op (BIT_AND_EXPR,
+ delta1,
+ integer_one_node);
+ e2 = cp_build_binary_op (EQ_EXPR, e2, integer_zero_node);
+ e1 = cp_build_binary_op (TRUTH_ANDIF_EXPR, e2, e1);
+ e2 = cp_build_binary_op (EQ_EXPR,
+ pfn0,
+ fold_convert (TREE_TYPE (pfn0),
+ integer_zero_node));
+ e2 = cp_build_binary_op (TRUTH_ANDIF_EXPR, e2, e1);
+ e1 = cp_build_binary_op (EQ_EXPR, delta0, delta1);
+ e1 = cp_build_binary_op (TRUTH_ORIF_EXPR, e1, e2);
+ }
+ else
+ {
+ /* We generate:
+
+ (op0.pfn == op1.pfn
+ && (!op0.pfn || op0.delta == op1.delta))
+
+ The reason for the `!op0.pfn' bit is that a NULL
+ pointer-to-member is any member with a zero PFN; the
+ DELTA field is unspecified. */
+
+ e1 = cp_build_binary_op (EQ_EXPR, delta0, delta1);
+ e2 = cp_build_binary_op (EQ_EXPR,
+ pfn0,
+ fold_convert (TREE_TYPE (pfn0),
+ integer_zero_node));
+ e1 = cp_build_binary_op (TRUTH_ORIF_EXPR, e1, e2);
+ }
e2 = build2 (EQ_EXPR, boolean_type_node, pfn0, pfn1);
e = cp_build_binary_op (TRUTH_ANDIF_EXPR, e2, e1);
if (code == EQ_EXPR)
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index a7149088e55..ce14b6d9460 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2006-12-01 Ryan Mansfield <rmansfield@qnx.com>
+
+ PR c++/29066
+ * g++.dg/expr/pr29066.c: New.
+
2006-12-01 H.J. Lu <hongjiu.lu@intel.com>
Zdenek Dvorak <dvorakz@suse.cz>
diff --git a/gcc/testsuite/g++.dg/expr/pr29066.C b/gcc/testsuite/g++.dg/expr/pr29066.C
new file mode 100644
index 00000000000..cd841654104
--- /dev/null
+++ b/gcc/testsuite/g++.dg/expr/pr29066.C
@@ -0,0 +1,42 @@
+// PR c++/29066
+// Test pointer to member function comparison
+// { dg-do run }
+
+extern "C" void abort (void);
+
+struct X
+{
+ virtual void a(void)=0;
+};
+
+struct Z : public X
+{
+ void a(void) {};
+};
+
+
+void f(X *obj)
+{
+ void (X::*xp)(void) = 0;
+ void (X::*xp2)(void) = 0;
+
+ xp = &X::a;
+
+ if (xp == xp2)
+ {
+ abort();
+ }
+
+ if (xp == 0)
+ {
+ abort();
+ }
+}
+
+int main(int argc, char* argv[])
+{
+ Z myobj;
+
+ f(&myobj);
+ return 0;
+}