From: Jason Merrill Date: Thu, 21 Dec 2000 17:50:10 +0000 (-0500) Subject: pt.c (tsubst_decl): A FUNCTION_DECL has DECL_RESULT, not DECL_TEMPLATE_RESULT. X-Git-Tag: prereleases/libstdc++-2.92~2098 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=477f6664a4b1316583e5a71f0edd30faefeeaab5;p=thirdparty%2Fgcc.git pt.c (tsubst_decl): A FUNCTION_DECL has DECL_RESULT, not DECL_TEMPLATE_RESULT. * pt.c (tsubst_decl): A FUNCTION_DECL has DECL_RESULT, not DECL_TEMPLATE_RESULT. * search.c (lookup_field_r): Call lookup_fnfields_1, not lookup_fnfields_here. * parse.y (typename_sub2): Return the TYPE_DECL, not the type. * call.c (build_object_call): Also allow conversions that return reference to pointer to function. (add_conv_candidate): Handle totype being ref to ptr to fn. (build_field_call): Also allow members of type reference to function. Lose support for calling pointer to METHOD_TYPE fields. * error.c (dump_expr): Handle *_CAST_EXPR. * typeck2.c (build_scoped_ref): Always convert to the naming class. * tree.c (break_out_cleanups): Lose. * cp-tree.h: Remove prototype. * typeck.c (build_component_ref): Don't break_out_cleanups. (build_compound_expr): Likewise. * semantics.c (finish_expr_stmt): Likewise. From-SVN: r38417 --- diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index fc473fb09fbf..0dd5b81f8568 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,29 @@ +2000-12-20 Jason Merrill + + * pt.c (tsubst_decl): A FUNCTION_DECL has DECL_RESULT, not + DECL_TEMPLATE_RESULT. + + * search.c (lookup_field_r): Call lookup_fnfields_1, not + lookup_fnfields_here. + + * parse.y (typename_sub2): Return the TYPE_DECL, not the type. + + * call.c (build_object_call): Also allow conversions that return + reference to pointer to function. + (add_conv_candidate): Handle totype being ref to ptr to fn. + (build_field_call): Also allow members of type reference to function. + Lose support for calling pointer to METHOD_TYPE fields. + + * error.c (dump_expr): Handle *_CAST_EXPR. + + * typeck2.c (build_scoped_ref): Always convert to the naming class. + + * tree.c (break_out_cleanups): Lose. + * cp-tree.h: Remove prototype. + * typeck.c (build_component_ref): Don't break_out_cleanups. + (build_compound_expr): Likewise. + * semantics.c (finish_expr_stmt): Likewise. + 2000-12-20 Richard Henderson * cp-tree.h: Update declarations. diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 77e29ebe3543..e7de1bab367e 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -156,15 +156,11 @@ build_field_call (basetype_path, instance_ptr, name, parms) if (IS_AGGR_TYPE (TREE_TYPE (instance))) return build_opfncall (CALL_EXPR, LOOKUP_NORMAL, instance, parms, NULL_TREE); - else if (TREE_CODE (TREE_TYPE (instance)) == POINTER_TYPE) - { - if (TREE_CODE (TREE_TYPE (TREE_TYPE (instance))) == FUNCTION_TYPE) - return build_function_call (instance, parms); - else if (TREE_CODE (TREE_TYPE (TREE_TYPE (instance))) - == METHOD_TYPE) - return build_function_call - (instance, tree_cons (NULL_TREE, instance_ptr, parms)); - } + else if (TREE_CODE (TREE_TYPE (instance)) == FUNCTION_TYPE + || (TREE_CODE (TREE_TYPE (instance)) == POINTER_TYPE + && (TREE_CODE (TREE_TYPE (TREE_TYPE (instance))) + == FUNCTION_TYPE))) + return build_function_call (instance, parms); } return NULL_TREE; @@ -1422,13 +1418,19 @@ add_conv_candidate (candidates, fn, obj, arglist) tree fn, obj, arglist; { tree totype = TREE_TYPE (TREE_TYPE (fn)); - tree parmlist = TYPE_ARG_TYPES (TREE_TYPE (totype)); - int i, len = list_length (arglist) + 1; - tree convs = make_tree_vec (len); - tree parmnode = parmlist; - tree argnode = arglist; - int viable = 1; - int flags = LOOKUP_NORMAL; + int i, len, viable, flags; + tree parmlist, convs, parmnode, argnode; + + for (parmlist = totype; TREE_CODE (parmlist) != FUNCTION_TYPE; ) + parmlist = TREE_TYPE (parmlist); + parmlist = TYPE_ARG_TYPES (parmlist); + + len = list_length (arglist) + 1; + convs = make_tree_vec (len); + parmnode = parmlist; + argnode = arglist; + viable = 1; + flags = LOOKUP_NORMAL; /* Don't bother looking up the same type twice. */ if (candidates && candidates->fn == totype) @@ -2659,8 +2661,12 @@ build_object_call (obj, args) tree totype = TREE_TYPE (TREE_TYPE (OVL_CURRENT (fns))); if ((TREE_CODE (totype) == POINTER_TYPE - || TREE_CODE (totype) == REFERENCE_TYPE) - && TREE_CODE (TREE_TYPE (totype)) == FUNCTION_TYPE) + && TREE_CODE (TREE_TYPE (totype)) == FUNCTION_TYPE) + || (TREE_CODE (totype) == REFERENCE_TYPE + && TREE_CODE (TREE_TYPE (totype)) == FUNCTION_TYPE) + || (TREE_CODE (totype) == REFERENCE_TYPE + && TREE_CODE (TREE_TYPE (totype)) == POINTER_TYPE + && TREE_CODE (TREE_TYPE (TREE_TYPE (totype))) == FUNCTION_TYPE)) for (; fns; fns = OVL_NEXT (fns)) { tree fn = OVL_CURRENT (fns); diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index f6d0b826abda..7c3dce43e3db 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -4401,7 +4401,6 @@ extern int lvalue_p PARAMS ((tree)); extern int lvalue_or_else PARAMS ((tree, const char *)); extern tree build_cplus_new PARAMS ((tree, tree)); extern tree get_target_expr PARAMS ((tree)); -extern tree break_out_cleanups PARAMS ((tree)); extern tree break_out_calls PARAMS ((tree)); extern tree build_cplus_method_type PARAMS ((tree, tree, tree)); extern tree build_cplus_staticfn_type PARAMS ((tree, tree, tree)); diff --git a/gcc/cp/error.c b/gcc/cp/error.c index b208e653f2cc..ce11ae1eda82 100644 --- a/gcc/cp/error.c +++ b/gcc/cp/error.c @@ -2051,6 +2051,24 @@ dump_expr (t, flags) } break; + case STATIC_CAST_EXPR: + output_add_string (scratch_buffer, "static_cast<"); + goto cast; + case REINTERPRET_CAST_EXPR: + output_add_string (scratch_buffer, "reinterpret_cast<"); + goto cast; + case CONST_CAST_EXPR: + output_add_string (scratch_buffer, "const_cast<"); + goto cast; + case DYNAMIC_CAST_EXPR: + output_add_string (scratch_buffer, "dynamic_cast<"); + cast: + dump_type (TREE_TYPE (t), flags); + output_add_string (scratch_buffer, ">("); + dump_expr (TREE_OPERAND (t, 0), flags); + print_right_paren (scratch_buffer); + break; + case LOOKUP_EXPR: print_tree_identifier (scratch_buffer, TREE_OPERAND (t, 0)); break; diff --git a/gcc/cp/parse.y b/gcc/cp/parse.y index 15cf72544753..4e763941fc6b 100644 --- a/gcc/cp/parse.y +++ b/gcc/cp/parse.y @@ -3056,6 +3056,8 @@ typename_sub1: { if (TREE_CODE ($1) == IDENTIFIER_NODE) cp_error ("`%T' is not a class or namespace", $1); + else if (TREE_CODE ($1) == TYPE_DECL) + $$ = TREE_TYPE ($1); } | typename_sub1 typename_sub2 { @@ -3078,24 +3080,26 @@ typename_sub1: = make_typename_type ($1, $3, /*complain=*/1); } ; +/* This needs to return a TYPE_DECL for simple names so that we don't + forget what name was used. */ typename_sub2: TYPENAME SCOPE { - if (TREE_CODE ($1) != IDENTIFIER_NODE) - $1 = lastiddecl; + if (TREE_CODE ($1) != TYPE_DECL) + $$ = lastiddecl; /* Retrieve the type for the identifier, which might involve some computation. */ - got_scope = $$ = complete_type (IDENTIFIER_TYPE_VALUE ($1)); + got_scope = complete_type (TREE_TYPE ($$)); if ($$ == error_mark_node) cp_error ("`%T' is not a class or namespace", $1); } | SELFNAME SCOPE { - if (TREE_CODE ($1) != IDENTIFIER_NODE) + if (TREE_CODE ($1) != TYPE_DECL) $$ = lastiddecl; - got_scope = $$ = complete_type (TREE_TYPE ($$)); + got_scope = complete_type (TREE_TYPE ($$)); } | template_type SCOPE { got_scope = $$ = complete_type (TREE_TYPE ($$)); } diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 3a0096e503c8..50e7ddf9da91 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -5715,7 +5715,7 @@ tsubst_decl (t, args, type, in_decl) DECL_ARGUMENTS (r) = tsubst (DECL_ARGUMENTS (t), args, /*complain=*/1, t); - DECL_TEMPLATE_RESULT (r) = NULL_TREE; + DECL_RESULT (r) = NULL_TREE; TREE_STATIC (r) = 0; TREE_PUBLIC (r) = TREE_PUBLIC (t); diff --git a/gcc/cp/search.c b/gcc/cp/search.c index 601f08b0dc13..2f4a3e946714 100644 --- a/gcc/cp/search.c +++ b/gcc/cp/search.c @@ -1251,7 +1251,9 @@ is_subobject_of_p (parent, binfo, most_derived) /* Very similar to lookup_fnfields_1 but it ensures that at least one function was declared inside the class given by TYPE. It really should - only return functions that match the given TYPE. */ + only return functions that match the given TYPE. Therefore, it should + only be called for situations that ignore using-declarations, such as + determining overrides. */ static int lookup_fnfields_here (type, name) @@ -1359,7 +1361,7 @@ lookup_field_r (binfo, data) with the same name, the type is hidden by the function. */ if (!lfi->want_type) { - int idx = lookup_fnfields_here (type, lfi->name); + int idx = lookup_fnfields_1 (type, lfi->name); if (idx >= 0) nval = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type), idx); } diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 856f4ae0aec1..28bf1ccb6842 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -214,9 +214,6 @@ finish_expr_stmt (expr) if (stmts_are_full_exprs_p ()) expr = convert_to_void (expr, "statement"); - if (!processing_template_decl) - expr = break_out_cleanups (expr); - r = add_stmt (build_stmt (EXPR_STMT, expr)); } diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index f86318b1cd59..a1089ce40187 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -317,37 +317,6 @@ get_target_expr (init) return build_target_expr_with_type (init, TREE_TYPE (init)); } -/* Recursively search EXP for CALL_EXPRs that need cleanups and replace - these CALL_EXPRs with tree nodes that will perform the cleanups. */ - -tree -break_out_cleanups (exp) - tree exp; -{ - tree tmp = exp; - - if (TREE_CODE (tmp) == CALL_EXPR - && TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (tmp))) - return build_cplus_new (TREE_TYPE (tmp), tmp); - - while (TREE_CODE (tmp) == NOP_EXPR - || TREE_CODE (tmp) == CONVERT_EXPR - || TREE_CODE (tmp) == NON_LVALUE_EXPR) - { - if (TREE_CODE (TREE_OPERAND (tmp, 0)) == CALL_EXPR - && TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (TREE_OPERAND (tmp, 0)))) - { - TREE_OPERAND (tmp, 0) - = build_cplus_new (TREE_TYPE (TREE_OPERAND (tmp, 0)), - TREE_OPERAND (tmp, 0)); - break; - } - else - tmp = TREE_OPERAND (tmp, 0); - } - return exp; -} - /* Recursively perform a preorder search EXP for CALL_EXPRs, making copies where they are found. Returns a deep copy all nodes transitively containing CALL_EXPRs. */ diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 6d12cbd32623..8de99f6d3abc 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -2278,8 +2278,7 @@ build_component_ref (datum, component, basetype_path, protect) field_type = cp_build_qualified_type (field_type, type_quals); } - ref = fold (build (COMPONENT_REF, field_type, - break_out_cleanups (datum), field)); + ref = fold (build (COMPONENT_REF, field_type, datum, field)); /* Mark the expression const or volatile, as appropriate. Even though we've dealt with the type above, we still have to mark the @@ -5039,8 +5038,7 @@ build_compound_expr (list) if (! TREE_SIDE_EFFECTS (first) && ! pedantic) return rest; - return build (COMPOUND_EXPR, TREE_TYPE (rest), - break_out_cleanups (first), rest); + return build (COMPOUND_EXPR, TREE_TYPE (rest), first, rest); } tree diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c index d8143f88b9bc..c40b81cc6c5d 100644 --- a/gcc/cp/typeck2.c +++ b/gcc/cp/typeck2.c @@ -957,9 +957,10 @@ process_init_constructor (type, init, elts) the A part of the C object named by X. In this case, DATUM would be x, and BASETYPE would be A. - Note that this is nonconformant; the standard specifies that first - we look up ii in A, then convert x to an L& and pull out the ii part. - But narrowing seems to be standard practice, so let's do it anyway. */ + I used to think that this was nonconformant, that the standard specified + that first we look up ii in A, then convert x to an L& and pull out the + ii part. But in fact, it does say that we convert x to an A&; A here + is known as the "naming class". (jason 2000-12-19) */ tree build_scoped_ref (datum, basetype) @@ -967,16 +968,10 @@ build_scoped_ref (datum, basetype) tree basetype; { tree ref; - tree type = TREE_TYPE (datum); if (datum == error_mark_node) return error_mark_node; - /* Don't do this if it would cause an error or if we're being pedantic. */ - if (! ACCESSIBLY_UNIQUELY_DERIVED_P (basetype, type) - || pedantic) - return datum; - ref = build_unary_op (ADDR_EXPR, datum, 0); ref = convert_pointer_to (basetype, ref); diff --git a/gcc/testsuite/g++.old-deja/g++.benjamin/scope01.C b/gcc/testsuite/g++.old-deja/g++.benjamin/scope01.C index 582723ab9f9f..a834f4f49561 100644 --- a/gcc/testsuite/g++.old-deja/g++.benjamin/scope01.C +++ b/gcc/testsuite/g++.old-deja/g++.benjamin/scope01.C @@ -19,8 +19,8 @@ class C : public A, public B {}; void foo() { // straight call C x; - x.A::ii = 5; // ERROR - L is ambiguous base - x.A::foo(x.A::ii); // ERROR - L is ambiguous base + x.A::ii = 5; + x.A::foo(x.A::ii); // 5.1 Primary expressions // p 8 diff --git a/gcc/testsuite/g++.old-deja/g++.brendan/misc15.C b/gcc/testsuite/g++.old-deja/g++.brendan/misc15.C index 30c4feb42a21..a294e4f7e49c 100644 --- a/gcc/testsuite/g++.old-deja/g++.brendan/misc15.C +++ b/gcc/testsuite/g++.old-deja/g++.brendan/misc15.C @@ -9,5 +9,5 @@ struct B : public A { struct C : public A { }; struct D : public C, public B { - void fun() { C::aa = 10; } // ERROR - conversion to A is ambiguous + void fun() { C::aa = 10; } }; diff --git a/gcc/testsuite/g++.old-deja/g++.other/call1.C b/gcc/testsuite/g++.old-deja/g++.other/call1.C new file mode 100644 index 000000000000..7341488d9490 --- /dev/null +++ b/gcc/testsuite/g++.old-deja/g++.other/call1.C @@ -0,0 +1,51 @@ +// Test that various calls to non-functions work. + +void f () { } + +typedef void (*fptr)(); +typedef void (&fref)(); +fptr p = f; +fref r = f; +const fptr &pr = p; + +struct A { + fptr p; + + A (fptr n): p(n) { } + operator fptr () { return p; } +}; + +struct B { + fref r; + + B (fptr n): r(*n) { } + operator const fref () { return r; } +}; + +struct C { + const fptr ≺ + + C (fptr n): pr(n) { } + operator const fptr& () { return pr; } +}; + +int main () +{ + f(); + + p(); + r(); + pr(); + + A a (f); + a(); + a.p(); + + B b (f); + b(); + b.r(); + + C c (f); + c(); + c.pr(); +} diff --git a/gcc/testsuite/g++.old-deja/g++.other/lookup18.C b/gcc/testsuite/g++.old-deja/g++.other/lookup18.C index bec78f845c16..09549f7828c4 100644 --- a/gcc/testsuite/g++.old-deja/g++.other/lookup18.C +++ b/gcc/testsuite/g++.old-deja/g++.other/lookup18.C @@ -1,5 +1,5 @@ -// Test that referring to an ambiguous base in name lookup does not -// interfere with accessing the field, which is not ambiguous. +// Test that referring to an ambiguous base in name lookup prevents +// access to the field, even though the field is not ambiguous. // Build don't link: @@ -14,10 +14,10 @@ struct E: public C, public D { }; void E::f() { - B::i = 0; + B::i = 0; // ERROR - B is ambiguous } void f () { E e; - e.B::i = 0; + e.B::i = 0; // ERROR - B is ambiguous } diff --git a/gcc/testsuite/g++.old-deja/g++.other/lookup20.C b/gcc/testsuite/g++.old-deja/g++.other/lookup20.C new file mode 100644 index 000000000000..930c9ab7ada1 --- /dev/null +++ b/gcc/testsuite/g++.old-deja/g++.other/lookup20.C @@ -0,0 +1,10 @@ +// Bug: typename_sub2 returned the type, so we tried to look up "A" in B. +// Build don't link: + +struct A { struct A1 { }; }; + +struct B { + typedef A Q; +}; + +struct C: public B::Q::A1 { }; diff --git a/gcc/testsuite/g++.old-deja/g++.pt/parms3.C b/gcc/testsuite/g++.old-deja/g++.pt/parms3.C new file mode 100644 index 000000000000..031f3d649123 --- /dev/null +++ b/gcc/testsuite/g++.old-deja/g++.pt/parms3.C @@ -0,0 +1,8 @@ +// Test that we can represent static_casts in template arg lists. +// Build don't link: + +template struct A { }; + +template struct B { + A(3.14)> a; +};