From b928a6517e21c8f8929cd21cb78075418a4c3666 Mon Sep 17 00:00:00 2001 From: Mark Mitchell Date: Sat, 22 May 1999 01:30:11 +0000 Subject: [PATCH] cp-tree.h (cplus_expand_constant): Declare. * cp-tree.h (cplus_expand_constant): Declare. * cvt.c (convert_to_pointer): Expand PTRMEM_CSTs when they're converted from one pointer-to-object type to another. * expr.c (cplus_expand_constant): Don't make it static. * typeck.c (build_component_ref): Don't crash when presented with a component which is a TEMPLATE_DECL. (build_ptrmemfunc): Tidy. Clarify comment. Make sure that even a cast from a pointer-to-member constant to its own type does not result in a valid non-type template argument. From-SVN: r27092 --- gcc/cp/ChangeLog | 12 +++++ gcc/cp/cp-tree.h | 1 + gcc/cp/cvt.c | 18 +++++-- gcc/cp/expr.c | 2 +- gcc/cp/typeck.c | 52 ++++++++++++--------- gcc/testsuite/g++.old-deja/g++.pt/crash42.C | 14 ++++++ gcc/testsuite/g++.old-deja/g++.pt/ptrmem6.C | 2 +- 7 files changed, 72 insertions(+), 29 deletions(-) create mode 100644 gcc/testsuite/g++.old-deja/g++.pt/crash42.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 6c64408f1db..39cec748146 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,15 @@ +1999-05-22 Mark Mitchell + + * cp-tree.h (cplus_expand_constant): Declare. + * cvt.c (convert_to_pointer): Expand PTRMEM_CSTs when they're + converted from one pointer-to-object type to another. + * expr.c (cplus_expand_constant): Don't make it static. + * typeck.c (build_component_ref): Don't crash when presented with + a component which is a TEMPLATE_DECL. + (build_ptrmemfunc): Tidy. Clarify comment. Make sure that even a + cast from a pointer-to-member constant to its own type does not + result in a valid non-type template argument. + 1999-05-21 Mark Mitchell Nathan Sidwell diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index b2b6313fd85..ec5ef45ba72 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -3007,6 +3007,7 @@ extern void init_cplus_expand PROTO((void)); extern void fixup_result_decl PROTO((tree, struct rtx_def *)); extern int extract_init PROTO((tree, tree)); extern void do_case PROTO((tree, tree)); +extern tree cplus_expand_constant PROTO((tree)); /* friend.c */ extern int is_friend PROTO((tree, tree)); diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c index 708272660d0..d24dbf1f4ec 100644 --- a/gcc/cp/cvt.c +++ b/gcc/cp/cvt.c @@ -179,19 +179,29 @@ cp_convert_to_pointer (type, expr) if (TYPE_PTRMEM_P (type) && TYPE_PTRMEM_P (intype)) { - tree b1 = TYPE_OFFSET_BASETYPE (TREE_TYPE (type)); - tree b2 = TYPE_OFFSET_BASETYPE (TREE_TYPE (intype)); - tree binfo = get_binfo (b2, b1, 1); - enum tree_code code = PLUS_EXPR; + tree b1; + tree b2; + tree binfo; + enum tree_code code; + + b1 = TYPE_OFFSET_BASETYPE (TREE_TYPE (type)); + b2 = TYPE_OFFSET_BASETYPE (TREE_TYPE (intype)); + binfo = get_binfo (b2, b1, 1); if (binfo == NULL_TREE) { binfo = get_binfo (b1, b2, 1); code = MINUS_EXPR; } + else + code = PLUS_EXPR; if (binfo == error_mark_node) return error_mark_node; + + if (TREE_CODE (expr) == PTRMEM_CST) + expr = cplus_expand_constant (expr); + if (binfo && ! TREE_VIA_VIRTUAL (binfo)) expr = size_binop (code, expr, BINFO_OFFSET (binfo)); } diff --git a/gcc/cp/expr.c b/gcc/cp/expr.c index 83bdff9eba7..d5250ae603f 100644 --- a/gcc/cp/expr.c +++ b/gcc/cp/expr.c @@ -39,7 +39,7 @@ static rtx cplus_expand_expr PROTO((tree, rtx, enum machine_mode, /* Hook used by output_constant to expand language-specific constants. */ -static tree +tree cplus_expand_constant (cst) tree cst; { diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 17147b909f7..1514ed7a9a9 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -2138,6 +2138,11 @@ build_component_ref (datum, component, basetype_path, protect) cp_error ("invalid use of type decl `%#D' as expression", component); return error_mark_node; } + else if (TREE_CODE (component) == TEMPLATE_DECL) + { + cp_error ("invalid use of template `%#D' as expression", component); + return error_mark_node; + } else { tree name = component; @@ -6516,7 +6521,9 @@ build_ptrmemfunc (type, pfn, force) int force; { tree fn; - + tree pfn_type = TREE_TYPE (pfn); + tree to_type = build_ptrmemfunc_type (type); + /* Handle multiple conversions of pointer to member functions. */ if (TYPE_PTRMEMFUNC_P (TREE_TYPE (pfn))) { @@ -6526,27 +6533,21 @@ build_ptrmemfunc (type, pfn, force) tree npfn = NULL_TREE; tree ndelta, ndelta2; tree e1, e2, e3, n; - tree pfn_type; - /* Is is already the right type? */ - if (type == TYPE_PTRMEMFUNC_FN_TYPE (TREE_TYPE (pfn))) - return pfn; - - pfn_type = TYPE_PTRMEMFUNC_FN_TYPE (TREE_TYPE (pfn)); - if (!force - && comp_target_types (type, pfn_type, 1) != 1) - cp_error ("conversion to `%T' from `%T'", type, pfn_type); + if (!force + && !can_convert_arg (to_type, TREE_TYPE (pfn), pfn)) + cp_error ("conversion to `%T' from `%T'", + to_type, pfn_type); if (TREE_CODE (pfn) == PTRMEM_CST) { /* We could just build the resulting CONSTRUCTOR now, but we don't, relying on the general machinery below, together with constant-folding, to do the right thing. We don't - want to return a PTRMEM_CST here, even though we could, - because a pointer-to-member constant ceases to be a - constant (from the point of view of the language) when it - is cast to another type. */ - + want to return a PTRMEM_CST here, since a + pointer-to-member constant is no longer a valid template + argument once it is cast to any type, including its + original type. */ expand_ptrmemfunc_cst (pfn, &ndelta, &idx, &npfn, &ndelta2); if (npfn) /* This constant points to a non-virtual function. @@ -6554,6 +6555,12 @@ build_ptrmemfunc (type, pfn, force) matter since we won't use it anyhow. */ ndelta2 = integer_zero_node; } + else if (same_type_p (to_type, pfn_type)) + /* We don't have to do any conversion. Note that we do this + after checking for a PTRMEM_CST so that a PTRMEM_CST, cast + to its own type, will not be considered a legal non-type + template argument. */ + return pfn; else { ndelta = cp_convert (ptrdiff_type_node, @@ -6565,15 +6572,15 @@ build_ptrmemfunc (type, pfn, force) idx = build_component_ref (pfn, index_identifier, NULL_TREE, 0); } - n = get_delta_difference (TYPE_METHOD_BASETYPE (TREE_TYPE (pfn_type)), - TYPE_METHOD_BASETYPE (TREE_TYPE (type)), + n = get_delta_difference (TYPE_PTRMEMFUNC_OBJECT_TYPE (pfn_type), + TYPE_PTRMEMFUNC_OBJECT_TYPE (to_type), force); delta = build_binary_op (PLUS_EXPR, ndelta, n); delta2 = build_binary_op (PLUS_EXPR, ndelta2, n); e1 = fold (build (GT_EXPR, boolean_type_node, idx, integer_zero_node)); /* If it's a virtual function, this is what we want. */ - e2 = build_ptrmemfunc1 (TYPE_GET_PTRMEMFUNC_TYPE (type), delta, idx, + e2 = build_ptrmemfunc1 (to_type, delta, idx, NULL_TREE, delta2); pfn = PFN_FROM_PTRMEMFUNC (pfn); @@ -6582,7 +6589,7 @@ build_ptrmemfunc (type, pfn, force) /* But if it's a non-virtual function, or NULL, we use this instead. */ - e3 = build_ptrmemfunc1 (TYPE_GET_PTRMEMFUNC_TYPE (type), delta, + e3 = build_ptrmemfunc1 (to_type, delta, idx, npfn, NULL_TREE); return build_conditional_expr (e1, e2, e3); } @@ -6591,7 +6598,7 @@ build_ptrmemfunc (type, pfn, force) if (integer_zerop (pfn)) { pfn = build_c_cast (type, integer_zero_node); - return build_ptrmemfunc1 (TYPE_GET_PTRMEMFUNC_TYPE (type), + return build_ptrmemfunc1 (to_type, integer_zero_node, integer_zero_node, pfn, NULL_TREE); } @@ -6601,7 +6608,7 @@ build_ptrmemfunc (type, pfn, force) fn = TREE_OPERAND (pfn, 0); my_friendly_assert (TREE_CODE (fn) == FUNCTION_DECL, 0); - return make_ptrmem_cst (build_ptrmemfunc_type (type), fn); + return make_ptrmem_cst (to_type, fn); } /* Return the DELTA, IDX, PFN, and DELTA2 values for the PTRMEM_CST @@ -6621,8 +6628,7 @@ expand_ptrmemfunc_cst (cst, delta, idx, pfn, delta2) my_friendly_assert (TREE_CODE (fn) == FUNCTION_DECL, 0); *delta - = get_delta_difference (TYPE_METHOD_BASETYPE - (TREE_TYPE (fn)), + = get_delta_difference (TYPE_METHOD_BASETYPE (TREE_TYPE (fn)), TYPE_PTRMEMFUNC_OBJECT_TYPE (type), /*force=*/0); if (!DECL_VIRTUAL_P (fn)) diff --git a/gcc/testsuite/g++.old-deja/g++.pt/crash42.C b/gcc/testsuite/g++.old-deja/g++.pt/crash42.C new file mode 100644 index 00000000000..69df5352381 --- /dev/null +++ b/gcc/testsuite/g++.old-deja/g++.pt/crash42.C @@ -0,0 +1,14 @@ +// Build don't link: +// Origin: Walter Brisken + +template class list {}; + +class newtype +{ +}; + +void crash() +{ + newtype* n; + n->list.size (); // ERROR - invalid use of template +} diff --git a/gcc/testsuite/g++.old-deja/g++.pt/ptrmem6.C b/gcc/testsuite/g++.old-deja/g++.pt/ptrmem6.C index 946e6244f4a..e7750ddf969 100644 --- a/gcc/testsuite/g++.old-deja/g++.pt/ptrmem6.C +++ b/gcc/testsuite/g++.old-deja/g++.pt/ptrmem6.C @@ -23,7 +23,7 @@ int main() { h<&A::i>(); g<&B::f>(); // ERROR - h<&B::j>(); // ERROR - - g<(void (A::*)()) &A::f>(); // ERROR - XFAIL *-*-* + g<(void (A::*)()) &A::f>(); // ERROR - h<(int A::*) &A::i>(); // ERROR - g<(void (A::*)()) &B::f>(); // ERROR - h<(int A::*) &B::j>(); // ERROR - -- 2.30.2