diff options
author | paolo <paolo@138bc75d-0d04-0410-961f-82ee72b054a4> | 2006-12-01 15:55:11 +0000 |
---|---|---|
committer | paolo <paolo@138bc75d-0d04-0410-961f-82ee72b054a4> | 2006-12-01 15:55:11 +0000 |
commit | 894342c13b2795fc72fda324c138bfd716930d80 (patch) | |
tree | ce2a5f0b7bbe59c508fd8ca9dae17ecf20026a7b /gcc | |
parent | 351ae60b82798f1b558434bf7358c62238295608 (diff) | |
download | gcc-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/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/cp/typeck.c | 87 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/expr/pr29066.C | 42 |
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; +} |