diff options
author | Ollie Wild <aaw@google.com> | 2007-08-31 04:41:52 +0000 |
---|---|---|
committer | Ollie Wild <aaw@gcc.gnu.org> | 2007-08-31 04:41:52 +0000 |
commit | 6e03b280b00030909b9b8204d6b151ad8060d77e (patch) | |
tree | af96dea76799906789882358f9345fac9ddcc51a /gcc | |
parent | 2710d6d70d29b63208de5a8234f1a90dc42c3404 (diff) | |
download | gcc-6e03b280b00030909b9b8204d6b151ad8060d77e.zip gcc-6e03b280b00030909b9b8204d6b151ad8060d77e.tar.gz gcc-6e03b280b00030909b9b8204d6b151ad8060d77e.tar.bz2 |
cvt.c (cp_convert_to_pointer): Remove force parameter.
gcc/cp/
* cvt.c (cp_convert_to_pointer): Remove force parameter. Call
convert_ptrmem for pointer to member conversions.
(convert_to_pointer_force): Update cp_convert_to_pointer call.
(ocp_convert): Update cp_convert_to_pointer call.
* typeck.c (convert_ptrmem): Add conditional for null pointers to
members.
(build_static_cast_1): Check can_convert for conversions in either
direction.
(get_delta_difference_1): New function.
(get_delta_difference): Refactor to call get_delta_difference_1.
gcc/testsuite/
g++.dg/conversion/ptrmem2.C: New test.
g++.dg/conversion/ptrmem3.C: New test.
g++.dg/conversion/ptrmem4.C: New test.
g++.dg/conversion/ptrmem5.C: New test.
g++.dg/conversion/ptrmem6.C: New test.
g++.dg/conversion/ptrmem7.C: New test.
g++.dg/conversion/ptrmem8.C: New test.
From-SVN: r127953
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/cp/ChangeLog | 13 | ||||
-rw-r--r-- | gcc/cp/cvt.c | 66 | ||||
-rw-r--r-- | gcc/cp/typeck.c | 128 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 10 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/conversion/ptrmem2.C | 39 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/conversion/ptrmem3.C | 31 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/conversion/ptrmem4.C | 43 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/conversion/ptrmem5.C | 35 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/conversion/ptrmem6.C | 35 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/conversion/ptrmem7.C | 29 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/conversion/ptrmem8.C | 25 |
11 files changed, 347 insertions, 107 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index a56349b..8f64db4 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,16 @@ +2007-08-30 Ollie Wild <aaw@google.com> + + * cvt.c (cp_convert_to_pointer): Remove force parameter. Call + convert_ptrmem for pointer to member conversions. + (convert_to_pointer_force): Update cp_convert_to_pointer call. + (ocp_convert): Update cp_convert_to_pointer call. + * typeck.c (convert_ptrmem): Add conditional for null pointers to + members. + (build_static_cast_1): Check can_convert for conversions in either + direction. + (get_delta_difference_1): New function. + (get_delta_difference): Refactor to call get_delta_difference_1. + 2007-08-28 Paolo Carlini <pcarlini@suse.de> PR c++/33209 diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c index 26165d9..ebfc7d0 100644 --- a/gcc/cp/cvt.c +++ b/gcc/cp/cvt.c @@ -38,7 +38,7 @@ along with GCC; see the file COPYING3. If not see #include "decl.h" #include "target.h" -static tree cp_convert_to_pointer (tree, tree, bool); +static tree cp_convert_to_pointer (tree, tree); static tree convert_to_pointer_force (tree, tree); static tree build_type_conversion (tree, tree); static tree build_up_reference (tree, tree, int, tree); @@ -71,12 +71,10 @@ static void warn_ref_binding (tree, tree, tree); else if dealing with method pointers, delegate else convert blindly else if converting class, pass off to build_type_conversion - else try C-style pointer conversion. If FORCE is true then allow - conversions via virtual bases (these are permitted by reinterpret_cast, - but not static_cast). */ + else try C-style pointer conversion. */ static tree -cp_convert_to_pointer (tree type, tree expr, bool force) +cp_convert_to_pointer (tree type, tree expr) { tree intype = TREE_TYPE (expr); enum tree_code form; @@ -174,61 +172,17 @@ cp_convert_to_pointer (tree type, tree expr, bool force) return build_nop (type, expr); } - else if (TYPE_PTRMEM_P (type) && TYPE_PTRMEM_P (intype)) - { - tree b1; - tree b2; - tree binfo; - enum tree_code code = PLUS_EXPR; - base_kind bk; - - b1 = TYPE_PTRMEM_CLASS_TYPE (type); - b2 = TYPE_PTRMEM_CLASS_TYPE (intype); - binfo = lookup_base (b1, b2, ba_check, &bk); - if (!binfo) - { - binfo = lookup_base (b2, b1, ba_check, &bk); - code = MINUS_EXPR; - } - if (binfo == error_mark_node) - return error_mark_node; - - if (bk == bk_via_virtual) - { - if (force) - warning (0, "pointer to member cast from %qT to %qT is via" - " virtual base", intype, type); - else - { - error ("pointer to member cast from %qT to %qT is" - " via virtual base", intype, type); - return error_mark_node; - } - /* This is a reinterpret cast, whose result is unspecified. - We choose to do nothing. */ - return build1 (NOP_EXPR, type, expr); - } - - if (TREE_CODE (expr) == PTRMEM_CST) - expr = cplus_expand_constant (expr); - - if (binfo && !integer_zerop (BINFO_OFFSET (binfo))) - expr = size_binop (code, - build_nop (sizetype, expr), - BINFO_OFFSET (binfo)); - return build_nop (type, expr); - } - else if (TYPE_PTRMEMFUNC_P (type) && TYPE_PTRMEMFUNC_P (intype)) - return build_ptrmemfunc (TYPE_PTRMEMFUNC_FN_TYPE (type), expr, 0, - /*c_cast_p=*/false); + else if ((TYPE_PTRMEM_P (type) && TYPE_PTRMEM_P (intype)) + || (TYPE_PTRMEMFUNC_P (type) && TYPE_PTRMEMFUNC_P (intype))) + return convert_ptrmem (type, expr, /*allow_inverse_p=*/false, + /*c_cast_p=*/false); else if (TYPE_PTRMEMFUNC_P (intype)) { if (!warn_pmf2ptr) { if (TREE_CODE (expr) == PTRMEM_CST) return cp_convert_to_pointer (type, - PTRMEM_CST_MEMBER (expr), - force); + PTRMEM_CST_MEMBER (expr)); else if (TREE_CODE (expr) == OFFSET_REF) { tree object = TREE_OPERAND (expr, 0); @@ -333,7 +287,7 @@ convert_to_pointer_force (tree type, tree expr) } } - return cp_convert_to_pointer (type, expr, true); + return cp_convert_to_pointer (type, expr); } /* We are passing something to a function which requires a reference. @@ -720,7 +674,7 @@ ocp_convert (tree type, tree expr, int convtype, int flags) return fold_if_not_in_template (convert_to_integer (type, e)); } if (POINTER_TYPE_P (type) || TYPE_PTR_TO_MEMBER_P (type)) - return fold_if_not_in_template (cp_convert_to_pointer (type, e, false)); + return fold_if_not_in_template (cp_convert_to_pointer (type, e)); if (code == VECTOR_TYPE) { tree in_vtype = TREE_TYPE (e); diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index e996df9..87044be 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -4868,9 +4868,19 @@ convert_ptrmem (tree type, tree expr, bool allow_inverse_p, allow_inverse_p, c_cast_p); if (!integer_zerop (delta)) - expr = cp_build_binary_op (PLUS_EXPR, - build_nop (ptrdiff_type_node, expr), - delta); + { + tree cond, op1, op2; + + cond = cp_build_binary_op (EQ_EXPR, + expr, + build_int_cst (TREE_TYPE (expr), -1)); + op1 = build_nop (ptrdiff_type_node, expr); + op2 = cp_build_binary_op (PLUS_EXPR, op1, delta); + + expr = fold_build3 (COND_EXPR, ptrdiff_type_node, cond, op1, op2); + + } + return build_nop (type, expr); } else @@ -5101,7 +5111,7 @@ build_static_cast_1 (tree type, tree expr, bool c_cast_p, t1 = intype; t2 = type; } - if (can_convert (t1, t2)) + if (can_convert (t1, t2) || can_convert (t2, t1)) { if (!c_cast_p) check_for_casting_away_constness (intype, type, diag_fn, @@ -5967,7 +5977,43 @@ build_x_modify_expr (tree lhs, enum tree_code modifycode, tree rhs) return build_modify_expr (lhs, modifycode, rhs); } - +/* Helper function for get_delta_difference which assumes FROM is a base + class of TO. Returns a delta for the conversion of pointer-to-member + of FROM to pointer-to-member of TO. If the conversion is invalid, + returns zero. If FROM is not a base class of TO, returns NULL_TREE. + If C_CAST_P is true, this conversion is taking place as part of a C-style + cast. */ + +static tree +get_delta_difference_1 (tree from, tree to, bool c_cast_p) +{ + tree binfo; + base_kind kind; + + binfo = lookup_base (to, from, c_cast_p ? ba_unique : ba_check, &kind); + if (kind == bk_inaccessible || kind == bk_ambig) + { + error (" in pointer to member function conversion"); + return size_zero_node; + } + else if (binfo) + { + if (kind != bk_via_virtual) + return BINFO_OFFSET (binfo); + else + /* FROM is a virtual base class of TO. Issue an error or warning + depending on whether or not this is a reinterpret cast. */ + { + error ("pointer to member conversion via virtual base %qT", + BINFO_TYPE (binfo_from_vbase (binfo))); + + return size_zero_node; + } + } + else + return NULL_TREE; +} + /* Get difference in deltas for different pointer to member function types. Returns an integer constant of type PTRDIFF_TYPE_NODE. If the conversion is invalid, the constant is zero. If @@ -5985,56 +6031,36 @@ get_delta_difference (tree from, tree to, bool allow_inverse_p, bool c_cast_p) { - tree binfo; - base_kind kind; tree result; - /* Assume no conversion is required. */ - result = integer_zero_node; - binfo = lookup_base (to, from, c_cast_p ? ba_unique : ba_check, &kind); - if (kind == bk_inaccessible || kind == bk_ambig) - error (" in pointer to member function conversion"); - else if (binfo) - { - if (kind != bk_via_virtual) - result = BINFO_OFFSET (binfo); - else - { - tree virt_binfo = binfo_from_vbase (binfo); - - /* This is a reinterpret cast, we choose to do nothing. */ - if (allow_inverse_p) - warning (0, "pointer to member cast via virtual base %qT", - BINFO_TYPE (virt_binfo)); - else - error ("pointer to member conversion via virtual base %qT", - BINFO_TYPE (virt_binfo)); - } - } - else if (same_type_ignoring_top_level_qualifiers_p (from, to)) - /* Pointer to member of incomplete class is permitted*/; - else if (!allow_inverse_p) - { - error_not_base_type (from, to); - error (" in pointer to member conversion"); - } + if (same_type_ignoring_top_level_qualifiers_p (from, to)) + /* Pointer to member of incomplete class is permitted*/ + result = size_zero_node; else - { - binfo = lookup_base (from, to, c_cast_p ? ba_unique : ba_check, &kind); - if (binfo) - { - if (kind != bk_via_virtual) - result = size_diffop (size_zero_node, BINFO_OFFSET (binfo)); - else - { - /* This is a reinterpret cast, we choose to do nothing. */ - tree virt_binfo = binfo_from_vbase (binfo); + result = get_delta_difference_1 (from, to, c_cast_p); - warning (0, "pointer to member cast via virtual base %qT", - BINFO_TYPE (virt_binfo)); - } - } - } + if (!result) + { + if (!allow_inverse_p) + { + error_not_base_type (from, to); + error (" in pointer to member conversion"); + result = size_zero_node; + } + else + { + result = get_delta_difference_1 (to, from, c_cast_p); + + if (result) + result = size_diffop (size_zero_node, result); + else + { + error_not_base_type (from, to); + error (" in pointer to member conversion"); + result = size_zero_node; + } + } + } return fold_if_not_in_template (convert_to_integer (ptrdiff_type_node, result)); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index cb25b96..80f2033 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,13 @@ +2007-08-30 Ollie Wild <aaw@google.com> + + g++.dg/conversion/ptrmem2.C: New test. + g++.dg/conversion/ptrmem3.C: New test. + g++.dg/conversion/ptrmem4.C: New test. + g++.dg/conversion/ptrmem5.C: New test. + g++.dg/conversion/ptrmem6.C: New test. + g++.dg/conversion/ptrmem7.C: New test. + g++.dg/conversion/ptrmem8.C: New test. + 2007-08-31 Paul Thomas <pault@gcc.gnu.org> PR fortran/31879 diff --git a/gcc/testsuite/g++.dg/conversion/ptrmem2.C b/gcc/testsuite/g++.dg/conversion/ptrmem2.C new file mode 100644 index 0000000..db39fc0 --- /dev/null +++ b/gcc/testsuite/g++.dg/conversion/ptrmem2.C @@ -0,0 +1,39 @@ +// Copyright (C) 2007 Free Software Foundation +// Contributed by Ollie Wild <aaw@google.com> +// { dg-do compile } + +// Assorted pointer to data member static cast tests. + +struct A { int x; }; +struct B : A { int x; }; +struct P : A { int x; }; +struct V { int x; }; +struct D : B, virtual V, private P { int x; }; + +// Valid static casts. +int B::*p1 = static_cast<int B::*>(&D::x); +int D::*p2 = static_cast<int D::*>(&B::x); + +// Virtual base class. +int V::*p3 = static_cast<int V::*>(&D::x); // { dg-error "" } +int D::*p4 = static_cast<int D::*>(&V::x); // { dg-error "" } + +// Inaccessible base class. +int P::*p5 = static_cast<int P::*>(&D::x); // { dg-error "" } +int D::*p6 = static_cast<int D::*>(&P::x); // { dg-error "" } + +// Ambiguous base class. +int A::*p7 = static_cast<int A::*>(&D::x); // { dg-error "" } +int D::*p8 = static_cast<int D::*>(&A::x); // { dg-error "" } + +// Valid conversions which increase cv-qualification. +const int B::*p9 = static_cast<const int B::*>(&D::x); +const int D::*p10 = static_cast<const int D::*>(&B::x); + +// Invalid conversions which decrease cv-qualification. +int B::*p11 = static_cast<int B::*>(p10); // { dg-error "casts away constness" } +int D::*p12 = static_cast<int D::*>(p9); // { dg-error "casts away constness" } + +// Attempts to change member type. +float B::*p13 = static_cast<float B::*>(&D::x); // { dg-error "" } +float D::*p14 = static_cast<float D::*>(&B::x); // { dg-error "" } diff --git a/gcc/testsuite/g++.dg/conversion/ptrmem3.C b/gcc/testsuite/g++.dg/conversion/ptrmem3.C new file mode 100644 index 0000000..13005e4 --- /dev/null +++ b/gcc/testsuite/g++.dg/conversion/ptrmem3.C @@ -0,0 +1,31 @@ +// Copyright (C) 2007 Free Software Foundation +// Contributed by Ollie Wild <aaw@google.com> +// { dg-do compile } + +// Assorted pointer to member function static cast tests. + +struct A { int f (); }; +struct B : A { int f (); }; +struct P : A { int f (); }; +struct V { int f (); }; +struct D : B, virtual V, private P { int f (); }; + +// Valid static casts. +int (B::*p1)() = static_cast<int (B::*)()>(&D::f); +int (D::*p2)() = static_cast<int (D::*)()>(&B::f); + +// Virtual base class. +int (V::*p3)() = static_cast<int (V::*)()>(&D::f); // { dg-error "" } +int (D::*p4)() = static_cast<int (D::*)()>(&V::f); // { dg-error "" } + +// Inaccessible base class. +int (P::*p5)() = static_cast<int (P::*)()>(&D::f); // { dg-error "" } +int (D::*p6)() = static_cast<int (D::*)()>(&P::f); // { dg-error "" } + +// Ambiguous base class. +int (A::*p7)() = static_cast<int (A::*)()>(&D::f); // { dg-error "" } +int (D::*p8)() = static_cast<int (D::*)()>(&A::f); // { dg-error "" } + +// Attempts to change member type. +float (B::*p13)() = static_cast<float (B::*)()>(&D::f); // { dg-error "" } +float (D::*p14)() = static_cast<float (D::*)()>(&B::f); // { dg-error "" } diff --git a/gcc/testsuite/g++.dg/conversion/ptrmem4.C b/gcc/testsuite/g++.dg/conversion/ptrmem4.C new file mode 100644 index 0000000..fd260df --- /dev/null +++ b/gcc/testsuite/g++.dg/conversion/ptrmem4.C @@ -0,0 +1,43 @@ +// Copyright (C) 2007 Free Software Foundation +// Contributed by Ollie Wild <aaw@google.com> +// { dg-do compile } + +// Assorted pointer to data member c-style cast tests. + +struct X {}; +struct A { int x; }; +struct B : A { int x; }; +struct P : A { int x; }; +struct V { int x; }; +struct D : B, virtual V, private P { int x; }; + +// Accessible, non-virtual, non-ambiguous base clas. +int B::*p1 = (int B::*)&D::x; +int D::*p2 = (int D::*)&B::x; + +// Virtual base class. +int V::*p3 = (int V::*)&D::x; // { dg-error "" } +int D::*p4 = (int D::*)&V::x; // { dg-error "" } + +// Inaccessible base class. +int P::*p5 = (int P::*)&D::x; +int D::*p6 = (int D::*)&P::x; + +// Ambiguous base class. +int A::*p7 = (int A::*)&D::x; // { dg-error "" } +int D::*p8 = (int D::*)&A::x; // { dg-error "" } + +// Valid conversions which increase cv-qualification. +const int B::*p9 = (const int B::*)&D::x; +const int D::*p10 = (const int D::*)&B::x; + +// Valid conversions which decrease cv-qualification. +int B::*p11 = (int B::*)p10; +int D::*p12 = (int D::*)p9; + +// Attempts to change member type allowed via reinterpret_cast. +float B::*p13 = (float B::*)&D::x; +float D::*p14 = (float D::*)&B::x; + +// Conversion via unrelated classes allwed via reinterpret_cast. +int X::*p15 = (int X::*)&D::x; diff --git a/gcc/testsuite/g++.dg/conversion/ptrmem5.C b/gcc/testsuite/g++.dg/conversion/ptrmem5.C new file mode 100644 index 0000000..6f06bad --- /dev/null +++ b/gcc/testsuite/g++.dg/conversion/ptrmem5.C @@ -0,0 +1,35 @@ +// Copyright (C) 2007 Free Software Foundation +// Contributed by Ollie Wild <aaw@google.com> +// { dg-do compile } + +// Assorted pointer to member function c-style cast tests. + +struct X {}; +struct A { int f (); }; +struct B : A { int f (); }; +struct P : A { int f (); }; +struct V { int f (); }; +struct D : B, virtual V, private P { int f (); }; + +// Accessible, non-virtual, non-ambiguous base clas. +int (B::*p1)() = (int (B::*)())&D::f; +int (D::*p2)() = (int (D::*)())&B::f; + +// Virtual base class. +int (V::*p3)() = (int (V::*)())&D::f; // { dg-error "" } +int (D::*p4)() = (int (D::*)())&V::f; // { dg-error "" } + +// Inaccessible base class. +int (P::*p5)() = (int (P::*)())&D::f; +int (D::*p6)() = (int (D::*)())&P::f; + +// Ambiguous base class. +int (A::*p7)() = (int (A::*)())&D::f; // { dg-error "" } +int (D::*p8)() = (int (D::*)())&A::f; // { dg-error "" } + +// Attempts to change member type allowed via reinterpret_cast. +float (B::*p13)() = (float (B::*)())&D::f; +float (D::*p14)() = (float (D::*)())&B::f; + +// Conversion via unrelated classes allwed via reinterpret_cast. +int (X::*p15)() = (int (X::*)())&D::f; diff --git a/gcc/testsuite/g++.dg/conversion/ptrmem6.C b/gcc/testsuite/g++.dg/conversion/ptrmem6.C new file mode 100644 index 0000000..a3c0c96 --- /dev/null +++ b/gcc/testsuite/g++.dg/conversion/ptrmem6.C @@ -0,0 +1,35 @@ +// Copyright (C) 2007 Free Software Foundation +// Contributed by Ollie Wild <aaw@google.com> +// { dg-do compile } + +// Assorted pointer to data member implicit cast tests. + +struct A { int x; }; +struct B : A { int x; }; +struct P : A { int x; }; +struct V { int x; }; +struct D : B, virtual V, private P { int x; }; + +// Valid. +int D::*p1 = &B::x; + +// Derived class. +int B::*p2 = &D::x; // { dg-error "" } + +// Virtual base class. +int D::*p3 = &V::x; // { dg-error "" } + +// Inaccessible base class. +int D::*p4 = &P::x; // { dg-error "" } + +// Ambiguous base class. +int D::*p5 = &A::x; // { dg-error "" } + +// Increases cv-qualification. +const int D::*p6 = &B::x; + +// Decreases cv-qualification. +int D::*p7 = static_cast<const int D::*>(&D::x); // { dg-error "" } + +// Different member type. +float D::*p8 = &B::x; // { dg-error "" } diff --git a/gcc/testsuite/g++.dg/conversion/ptrmem7.C b/gcc/testsuite/g++.dg/conversion/ptrmem7.C new file mode 100644 index 0000000..ad75a52 --- /dev/null +++ b/gcc/testsuite/g++.dg/conversion/ptrmem7.C @@ -0,0 +1,29 @@ +// Copyright (C) 2007 Free Software Foundation +// Contributed by Ollie Wild <aaw@google.com> +// { dg-do compile } + +// Assorted pointer to member function implicit cast tests. + +struct A { int f (); }; +struct B : A { int f (); }; +struct P : A { int f (); }; +struct V { int f (); }; +struct D : B, virtual V, private P { int f (); }; + +// Valid. +int (D::*p1)() = &B::f; + +// Derived class. +int (B::*p2)() = &D::f; // { dg-error "" } + +// Virtual base class. +int (D::*p3)() = &V::f; // { dg-error "" } + +// Inaccessible base class. +int (D::*p4)() = &P::f; // { dg-error "" } + +// Ambiguous base class. +int (D::*p5)() = &A::f; // { dg-error "" } + +// Different member type. +float (D::*p6)() = &B::f; // { dg-error "" } diff --git a/gcc/testsuite/g++.dg/conversion/ptrmem8.C b/gcc/testsuite/g++.dg/conversion/ptrmem8.C new file mode 100644 index 0000000..95d902f --- /dev/null +++ b/gcc/testsuite/g++.dg/conversion/ptrmem8.C @@ -0,0 +1,25 @@ +// Copyright (C) 2007 Free Software Foundation +// Contributed by Ollie Wild <aaw@google.com> +// { dg-do run } + +// Test for proper conversion of null pointers to data members. + +struct B1 { + int x; +}; + +struct B2 { + int x; +}; + +struct D : B1, B2 { + int x; +}; + +int main () +{ + int D::*pd = 0; + int B2::*pb2 = 0; + + return pd != pb2; +} |