Index: gcc/gcc/cp/call.c =================================================================== RCS file: /cvsroot/gcc/gcc/gcc/cp/call.c,v retrieving revision 1.307.2.6 diff -c -3 -p -r1.307.2.6 call.c *** gcc/gcc/cp/call.c 13 Apr 2002 01:31:06 -0000 1.307.2.6 --- gcc/gcc/cp/call.c 10 Jun 2002 19:39:34 -0000 *************** static tree convert_class_to_reference P *** 102,107 **** --- 102,108 ---- static tree direct_reference_binding PARAMS ((tree, tree)); static int promoted_arithmetic_type_p PARAMS ((tree)); static tree conditional_conversion PARAMS ((tree, tree)); + static void debug_candidates PARAMS ((struct z_candidate *)); /* DCH 2002.05.22 */ tree build_vfield_ref (datum, type) *************** struct z_candidate { *** 592,597 **** --- 593,627 ---- ((struct z_candidate *)WRAPPER_PTR (TREE_OPERAND (NODE, 1))) #define USER_CONV_FN(NODE) (USER_CONV_CAND (NODE)->fn) + /* DCH 2002.05.22 -- CHANGES_BEGIN */ + static void + debug_candidates ( struct z_candidate *candidates ) + { + int i; + + i = 0; + while ( candidates ) + { + fprintf ( stderr, "<<< Candidate #%d follows : >>>", i ); + fprintf ( stderr, "--- fn\n" ); + debug_tree ( candidates->fn ); + fprintf ( stderr, "--- convs\n" ); + debug_tree ( candidates->convs ); + fprintf ( stderr, "--- second_conv\n" ); + debug_tree ( candidates->second_conv ); + fprintf ( stderr, "--- viable : %d\n", candidates->viable ); + fprintf ( stderr, "--- basetype_path\n" ); + debug_tree ( candidates->basetype_path ); + fprintf ( stderr, "--- template\n" ); + debug_tree ( candidates->template ); + fprintf ( stderr, "--- warnings\n" ); + debug_tree ( candidates->warnings ); + candidates = candidates->next; + } + fprintf ( stderr, "<<< End of candidate dump >>>\n" ); + } + /* DCH 2002.05.22 -- CHANGES_END */ + int null_ptr_cst_p (t) tree t; *************** add_function_candidate (candidates, fn, *** 1333,1338 **** --- 1363,1371 ---- tree convs; tree parmnode, argnode; int viable = 1; + tree classtype_parm; /* DCH */ /* The saved classtype parameter */ + + classtype_parm = NULL_TREE; /*DCH*/ /* Used to flag */ /* The `this', `in_chrg' and VTT arguments to constructors are not considered in overload resolution. */ *************** add_function_candidate (candidates, fn, *** 1342,1347 **** --- 1375,1389 ---- arglist = skip_artificial_parms_for (fn, arglist); } + /* DCH 2002.05.22 -- CHANGES_BEGIN */ + if ( decl_has_classtype_parm_p (fn) ) + { + classtype_parm = TREE_CHAIN (parmlist); + + TREE_CHAIN (parmlist) = TREE_CHAIN (classtype_parm); + } + /* DCH 2002.05.22 -- CHANGES_END */ + len = list_length (arglist); convs = make_tree_vec (len); *************** add_function_candidate (candidates, fn, *** 1438,1443 **** --- 1480,1491 ---- } out: + + /* DCH 2002.05.22 -- CHANGES_BEGIN */ + if ( classtype_parm != NULL_TREE ) + TREE_CHAIN (parmlist) = classtype_parm; + /* DCH 2002.05.22 -- CHANGES_END */ + return add_candidate (candidates, fn, convs, viable); } *************** build_over_call (cand, args, flags) *** 4150,4157 **** --- 4198,4229 ---- tree converted_args = NULL_TREE; tree parm = TYPE_ARG_TYPES (TREE_TYPE (fn)); tree conv, arg, val; + tree new_convs; /*DCH*/ int i = 0; int is_method = 0; + + /* DCH 2002.05.23 --- CHANGES_BEGIN */ + if (TREE_CODE (TREE_TYPE (fn)) == METHOD_TYPE + && decl_has_classtype_parm_p ( fn ) ) + { + args = set_classtype_arg ( fn, args, 1 ); + + new_convs = make_tree_vec ( TREE_VEC_LENGTH ( convs ) + 1 ); + + TREE_VEC_ELT ( new_convs, 0 ) = TREE_VEC_ELT ( convs, 0 ); + TREE_VEC_ELT ( new_convs, 1 ) = build1 ( IDENTITY_CONV, TREE_TYPE ( TREE_CHAIN ( args ) ), TREE_CHAIN ( args ) ); + + for ( i = 2; i < TREE_VEC_LENGTH ( new_convs ); i++ ) + { + TREE_VEC_ELT ( new_convs, i ) = TREE_VEC_ELT ( convs, i - 1 ); + } + + + i = 0; + + cand->convs = convs = new_convs; + } + /* DCH 2002.05.23 -- CHANGES_END */ /* Give any warnings we noticed during overload resolution. */ if (cand->warnings) Index: gcc/gcc/cp/cp-tree.h =================================================================== RCS file: /cvsroot/gcc/gcc/gcc/cp/cp-tree.h,v retrieving revision 1.681.2.10 diff -c -3 -p -r1.681.2.10 cp-tree.h *** gcc/gcc/cp/cp-tree.h 23 Apr 2002 21:51:13 -0000 1.681.2.10 --- gcc/gcc/cp/cp-tree.h 10 Jun 2002 19:39:51 -0000 *************** enum cp_tree_index *** 568,573 **** --- 568,574 ---- CPTI_PFN_IDENTIFIER, CPTI_VPTR_IDENTIFIER, CPTI_STD_IDENTIFIER, + CPTI_CLASSTYPE_PARM_IDENTIFIER, /* DCH 2002.05.22 */ CPTI_LANG_NAME_C, CPTI_LANG_NAME_CPLUSPLUS, *************** extern tree cp_global_trees[CPTI_MAX]; *** 677,682 **** --- 678,684 ---- #define vptr_identifier cp_global_trees[CPTI_VPTR_IDENTIFIER] /* The name of the std namespace. */ #define std_identifier cp_global_trees[CPTI_STD_IDENTIFIER] + #define classtype_parm_identifier cp_global_trees[CPTI_CLASSTYPE_PARM_IDENTIFIER] /* DCH 2002.05.22 */ #define lang_name_c cp_global_trees[CPTI_LANG_NAME_C] #define lang_name_cplusplus cp_global_trees[CPTI_LANG_NAME_CPLUSPLUS] #define lang_name_java cp_global_trees[CPTI_LANG_NAME_JAVA] *************** extern void begin_init_stmts *** 3915,3920 **** --- 3917,3923 ---- extern tree finish_init_stmts PARAMS ((tree, tree)); extern void initialize_vtbl_ptrs PARAMS ((tree)); extern tree build_java_class_ref PARAMS ((tree)); + extern tree get_raw_vtbl_address PARAMS ((tree)); /* DCH 2002.06.02 */ /* in input.c */ *************** extern tree cp_copy_res_decl_for_inlinin *** 4282,4287 **** --- 4285,4292 ---- int*, void*)); extern int cp_start_inlining PARAMS ((tree)); extern void cp_end_inlining PARAMS ((tree)); + extern void add_classtype_parm PARAMS ((tree)); /* DCH 2002.05.22 */ + extern tree set_classtype_arg PARAMS ((tree,tree,int)); /* DCH 2002.05.22 */ /* in typeck.c */ extern int string_conv_p PARAMS ((tree, tree, int)); *************** extern tree composite_pointer_type *** 4345,4350 **** --- 4350,4357 ---- const char*)); extern tree merge_types PARAMS ((tree, tree)); extern tree check_return_expr PARAMS ((tree)); + extern int decl_needs_classtype_parm_p PARAMS ((tree)); /* DCH 2002.05.07 -- CHANGE_BEGIN CHANGE_END */ + extern int decl_has_classtype_parm_p PARAMS ((tree)); /* DCH 2002.05.22 */ #define cp_build_binary_op(code, arg1, arg2) \ build_binary_op(code, arg1, arg2, 1) Index: gcc/gcc/cp/decl.c =================================================================== RCS file: /cvsroot/gcc/gcc/gcc/cp/decl.c,v retrieving revision 1.866.2.32 diff -c -3 -p -r1.866.2.32 decl.c *** gcc/gcc/cp/decl.c 3 May 2002 18:55:23 -0000 1.866.2.32 --- gcc/gcc/cp/decl.c 10 Jun 2002 19:40:08 -0000 *************** initialize_predefined_identifiers () *** 6453,6458 **** --- 6453,6459 ---- { "_vptr", &vptr_identifier, 0 }, { "__vtt_parm", &vtt_parm_identifier, 0 }, { "std", &std_identifier, 0 }, + { "__classtype_parm", &classtype_parm_identifier, 0 }, /* DCH 2002.05.22 */ { NULL, NULL, 0 } }; *************** grokfndecl (ctype, type, declarator, ori *** 9166,9171 **** --- 9167,9183 ---- /* Attempt to merge the declarations. This can fail, in the case of some illegal specialization declarations. */ + + /* DCH 2002.05.21 -- CHANGES_BEGIN */ + + /* We use "old_decl" because "decl" doesn't have the virtual flag + set. */ + if ( decl_needs_classtype_parm_p ( old_decl ) ) + { + add_classtype_parm ( decl ); + } + /* DCH 2002.05.21 -- CHANGES_END */ + if (!duplicate_decls (decl, old_decl)) error ("no `%#D' member function declared in class `%T'", decl, ctype); Index: gcc/gcc/cp/decl2.c =================================================================== RCS file: /cvsroot/gcc/gcc/gcc/cp/decl2.c,v retrieving revision 1.520.2.5 diff -c -3 -p -r1.520.2.5 decl2.c *** gcc/gcc/cp/decl2.c 17 Apr 2002 17:13:39 -0000 1.520.2.5 --- gcc/gcc/cp/decl2.c 10 Jun 2002 19:40:14 -0000 *************** check_classfn (ctype, function) *** 1331,1346 **** if (DECL_STATIC_FUNCTION_P (fndecl) && TREE_CODE (TREE_TYPE (function)) == METHOD_TYPE) p1 = TREE_CHAIN (p1); ! if (same_type_p (TREE_TYPE (TREE_TYPE (function)), ! TREE_TYPE (TREE_TYPE (fndecl))) ! && compparms (p1, p2) ! && (DECL_TEMPLATE_SPECIALIZATION (function) ! == DECL_TEMPLATE_SPECIALIZATION (fndecl)) ! && (!DECL_TEMPLATE_SPECIALIZATION (function) ! || (DECL_TI_TEMPLATE (function) ! == DECL_TI_TEMPLATE (fndecl)))) ! return fndecl; } } break; /* loser */ --- 1331,1378 ---- if (DECL_STATIC_FUNCTION_P (fndecl) && TREE_CODE (TREE_TYPE (function)) == METHOD_TYPE) p1 = TREE_CHAIN (p1); + /* DCH 2002.05.13 - CHANGES_BEGIN */ ! /* If the function has a covariant return, we need to ! skip over the type parameter. */ ! if ( decl_has_classtype_parm_p ( fndecl ) ) ! { ! tree void_param; ! ! /* We need to remove the faked parameter. */ ! void_param = TREE_CHAIN (p2); ! TREE_CHAIN (p2) = TREE_CHAIN ( TREE_CHAIN ( p2 ) ); ! ! if (same_type_p (TREE_TYPE (TREE_TYPE (function)), ! TREE_TYPE (TREE_TYPE (fndecl))) ! && compparms (p1, p2) ! && (DECL_TEMPLATE_SPECIALIZATION (function) ! == DECL_TEMPLATE_SPECIALIZATION (fndecl)) ! && (!DECL_TEMPLATE_SPECIALIZATION (function) ! || (DECL_TI_TEMPLATE (function) ! == DECL_TI_TEMPLATE (fndecl)))) ! { ! /* Restore the dropped parameter */ ! TREE_CHAIN (p2) = void_param; ! ! return fndecl; ! } /* end of if functions match */ ! ! /* Restore the dropped parameter */ ! TREE_CHAIN (p2) = void_param; ! } ! else ! ! if (same_type_p (TREE_TYPE (TREE_TYPE (function)), ! TREE_TYPE (TREE_TYPE (fndecl))) ! && compparms (p1, p2) ! && (DECL_TEMPLATE_SPECIALIZATION (function) ! == DECL_TEMPLATE_SPECIALIZATION (fndecl)) ! && (!DECL_TEMPLATE_SPECIALIZATION (function) ! || (DECL_TI_TEMPLATE (function) ! == DECL_TI_TEMPLATE (fndecl)))) ! return fndecl; ! /* DCH 2002.05.13 -- CHANGES_END */ } } break; /* loser */ Index: gcc/gcc/cp/init.c =================================================================== RCS file: /cvsroot/gcc/gcc/gcc/cp/init.c,v retrieving revision 1.264.2.10 diff -c -3 -p -r1.264.2.10 init.c *** gcc/gcc/cp/init.c 2 May 2002 20:02:41 -0000 1.264.2.10 --- gcc/gcc/cp/init.c 10 Jun 2002 19:40:21 -0000 *************** build_vec_delete (base, maxindex, auto_d *** 3419,3421 **** --- 3419,3461 ---- return build_vec_delete_1 (base, maxindex, type, auto_delete_vec, use_global_delete); } + + /* DCH 2002.06.02 -- CHANGES_BEGIN */ + tree + get_raw_vtbl_address (binfo) + tree binfo; /* BINFO */ + { + tree retval; /* Return value; an ADDR_EXPR */ + tree vtbl; /* Temporary; a VAR_DECL */ + + /* From build_vtbl_address, make sure that the table gets emitted */ + vtbl = get_vtbl_decl_for_binfo (binfo); + assemble_external (vtbl); + TREE_USED (vtbl) = 1; + + /* Retrieve the binfo's vtable */ + retval = BINFO_VTABLE (binfo); + + switch (TREE_CODE (retval)) + { + case PLUS_EXPR : + retval = TREE_OPERAND (retval, 0); + break; + + case VAR_DECL : + retval = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (retval)), retval); + break; + } + + if ( TREE_CODE (retval) != ADDR_EXPR ) + { + retval = error_mark_node; + error ( "internal compiler error; unable to take address of vtable" ); + } + + /* ??? This is necessary, but I have no idea why... */ + retval = build (PLUS_EXPR, TREE_TYPE (retval), retval, integer_zero_node); + return retval; + } + + /* DCH 2002.06.02 -- CHANGES_END */ Index: gcc/gcc/cp/search.c =================================================================== RCS file: /cvsroot/gcc/gcc/gcc/cp/search.c,v retrieving revision 1.223.2.3 diff -c -3 -p -r1.223.2.3 search.c *** gcc/gcc/cp/search.c 18 Apr 2002 13:59:00 -0000 1.223.2.3 --- gcc/gcc/cp/search.c 10 Jun 2002 19:40:47 -0000 *************** lookup_base (t, base, access, kind_ptr) *** 327,333 **** /* Ensure that the types are instantiated. */ t = complete_type (TYPE_MAIN_VARIANT (t)); base = complete_type (TYPE_MAIN_VARIANT (base)); ! bk = lookup_base_r (TYPE_BINFO (t), base, access & ~ba_quiet, 0, 0, 0, &binfo); --- 327,333 ---- /* Ensure that the types are instantiated. */ t = complete_type (TYPE_MAIN_VARIANT (t)); base = complete_type (TYPE_MAIN_VARIANT (base)); ! bk = lookup_base_r (TYPE_BINFO (t), base, access & ~ba_quiet, 0, 0, 0, &binfo); *************** check_final_overrider (overrider, basefn *** 1816,1823 **** /* OK */; else if ((i = covariant_return_p (base_return, over_return))) { ! if (i == 2) ! sorry ("adjusting pointers for covariant returns"); if (pedantic && i == -1) { --- 1816,1825 ---- /* OK */; else if ((i = covariant_return_p (base_return, over_return))) { ! /* DCH 2002.05.29 -- CHANGES_BEGIN */ ! /*if (i == 2) ! sorry ("adjusting pointers for covariant returns");*/ ! /* DCH 20002.05.29 -- CHANGES_END */ if (pedantic && i == -1) { Index: gcc/gcc/cp/semantics.c =================================================================== RCS file: /cvsroot/gcc/gcc/gcc/cp/semantics.c,v retrieving revision 1.252.2.6 diff -c -3 -p -r1.252.2.6 semantics.c *** gcc/gcc/cp/semantics.c 17 Apr 2002 01:44:01 -0000 1.252.2.6 --- gcc/gcc/cp/semantics.c 10 Jun 2002 19:40:50 -0000 *************** finish_return_stmt (expr) *** 389,394 **** --- 389,396 ---- tree expr; { tree r; + int n_baseclasses; /*DCH*/ + int i; /*DCH*/ if (!processing_template_decl) expr = check_return_expr (expr); *************** finish_return_stmt (expr) *** 403,411 **** return finish_goto_stmt (dtor_label); } } - r = add_stmt (build_stmt (RETURN_STMT, expr)); - finish_stmt (); return r; } --- 405,470 ---- return finish_goto_stmt (dtor_label); } } + /* DCH 2002.05.27 -- CHANGES_BEGIN */ + + /* This statement bears some explanation. First, we only need to process + covariant return functions if the function has __classtype_parm. Second, + we only need to do something if the return value has extant base classes. + The gross triple TREE_TYPE is to get the RECORD_TYPE for the function + return value. */ + + n_baseclasses = decl_has_classtype_parm_p (current_function_decl) && !DECL_THUNK_P (current_function_decl) + ? CLASSTYPE_N_BASECLASSES (TREE_TYPE (TREE_TYPE (TREE_TYPE (current_function_decl)))) + : 0; + + if (n_baseclasses) + { + tree binfos = TYPE_BINFO_BASETYPES (TREE_TYPE (TREE_TYPE (TREE_TYPE (current_function_decl)))); + tree parameter = TREE_CHAIN (DECL_ARGUMENTS (current_function_decl)); + tree cast_expr; + + /* Evaluate the expression and store it into RESULT_DECL */ + finish_expr_stmt (expr); + + for ( i = 0; i < n_baseclasses; i++ ) + { + tree classtype = get_raw_vtbl_address (TYPE_BINFO (TREE_TYPE (TREE_VEC_ELT (binfos, i)))); + tree condition = build_x_binary_op (EQ_EXPR, classtype, parameter); + tree new_return_type; + tree if_stmt; + + /* First, initialize the new_return_type. We want it to be basically + the same, just a different record. */ + new_return_type = build_qualified_type (TREE_TYPE (TREE_VEC_ELT (binfos,i)), TYPE_QUALS (TREE_TYPE (TREE_TYPE (expr)))); + new_return_type = build_pointer_type (new_return_type); + new_return_type = build_qualified_type (new_return_type, TYPE_QUALS (TREE_TYPE (expr))); + + /* Create the if statement */ + if_stmt = begin_if_stmt(); + finish_if_stmt_cond (condition, if_stmt); + + /* Create an expression of the form "RESULT_DECL = static_cast ( RESULT_DECL )" */ + cast_expr = build_static_cast (new_return_type, TREE_OPERAND (expr,0)); + cast_expr = build (INIT_EXPR, TREE_TYPE (expr), TREE_OPERAND (expr,0), cast_expr); + + /* Add the return statmenet and end the if */ + r = add_stmt (build_stmt (RETURN_STMT, cast_expr)); + finish_stmt(); + finish_then_clause (if_stmt); + finish_if_stmt(); + } + + /* The final return statement is one without a cast */ + r = add_stmt (build_stmt (RETURN_STMT, NULL_TREE)); + finish_stmt(); + } + else + { + r = add_stmt (build_stmt (RETURN_STMT, expr)); + finish_stmt(); + } + /* DCH 2002.05.27 -- CHANGES_END */ return r; } *************** finish_member_declaration (decl) *** 1818,1823 **** --- 1877,1899 ---- if (TREE_CODE (decl) == FUNCTION_DECL || DECL_FUNCTION_TEMPLATE_P (decl)) { + /* DCH 2002.05.07 -- CHANGE_BEGIN + If the member could be covariant, we need to give it another hidden + parameter. This parameter will contain the address of the (ordinary) + destructor for the class whose type is desired. */ + + + /* ??? This code does not currently handle covariance of + the form "A **", but I'm not even sure that such a construct + is legal. */ + + if ( decl_needs_classtype_parm_p (decl) + && !decl_has_classtype_parm_p (decl) ) + { + add_classtype_parm ( decl ); + } + /* DCH 2002.05.07 -- Changes end. */ + /* We also need to add this function to the CLASSTYPE_METHOD_VEC. */ add_method (current_class_type, decl, /*error_p=*/0); Index: gcc/gcc/cp/tree.c =================================================================== RCS file: /cvsroot/gcc/gcc/gcc/cp/tree.c,v retrieving revision 1.268.2.3 diff -c -3 -p -r1.268.2.3 tree.c *** gcc/gcc/cp/tree.c 25 Apr 2002 00:14:25 -0000 1.268.2.3 --- gcc/gcc/cp/tree.c 10 Jun 2002 19:40:53 -0000 *************** decl_linkage (decl) *** 2501,2503 **** --- 2501,2576 ---- /* Everything else has internal linkage. */ return lk_internal; } + + /* DCH 2002.05.22 -- CHANGES_BEGIN */ + + /* Inserts the artificial classtype parameter into the argument list following + the this pointer. */ + + void + add_classtype_parm (fndecl) + tree fndecl; /* FUNCTION_DECL or OVERLOAD */ + { + tree type_parm; /* Holds the new link for the void * parameter */ + tree arg_list; /* List of arguments for the function */ + + /* Get rid of those single function overloads which are all over the place. */ + fndecl = OVL_CURRENT ( fndecl ); + + /* First, we set up the actual parameter declaration. */ + type_parm = build_pointer_type (TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (get_identifier ("void")))); + arg_list = DECL_ARGUMENTS (fndecl); + + type_parm = build_artificial_parm (classtype_parm_identifier, type_parm); + + /* Insert after the 'this' pointer */ + TREE_CHAIN (type_parm) = TREE_CHAIN (arg_list); + TREE_CHAIN (arg_list) = type_parm; + + /* Now, we insert the argument type in the type list */ + type_parm = build_pointer_type (TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (get_identifier ("void")))); + arg_list = TYPE_ARG_TYPES (TREE_TYPE (fndecl)); + + type_parm = build_tree_list (NULL_TREE, type_parm); + + /* Insert after the 'this' pointer */ + TREE_CHAIN (type_parm) = TREE_CHAIN (arg_list); + TREE_CHAIN (arg_list) = type_parm; + } + + /* Sets the argument value for the artificial classtype parameter. Note that + the function assumes the this pointer is NOT on the list; this seems to be + correct. */ + tree + set_classtype_arg (fndecl, args, has_this ) + tree fndecl; /* FUNCTION_DECL or OVERLOAD */ + tree args; /* TREE_LIST */ + int has_this; /* boolean */ + { + tree type_vptr; + tree return_type; + + fndecl = OVL_CURRENT ( fndecl ); + + /* YOW! I know. We need to descend through the "function_decl", + "method_type", and "pointer_type" levels to get the actual + "record_type". */ + return_type = TREE_TYPE (TREE_TYPE (TREE_TYPE (fndecl))); + type_vptr = get_raw_vtbl_address (TYPE_BINFO (return_type)); + + if ( has_this ) + { + TREE_CHAIN (type_vptr) = TREE_CHAIN (args); + TREE_CHAIN (args) = type_vptr; + + return args; + } + else + { + TREE_CHAIN (type_vptr) = args; + + return type_vptr; + } + } + + /* DCH 2002.05.22 -- CHANGES_END */ Index: gcc/gcc/cp/typeck.c =================================================================== RCS file: /cvsroot/gcc/gcc/gcc/cp/typeck.c,v retrieving revision 1.388.2.9 diff -c -3 -p -r1.388.2.9 typeck.c *** gcc/gcc/cp/typeck.c 25 Apr 2002 00:14:24 -0000 1.388.2.9 --- gcc/gcc/cp/typeck.c 10 Jun 2002 19:41:01 -0000 *************** strip_all_pointer_quals (type) *** 6920,6922 **** --- 6920,6990 ---- else return TYPE_MAIN_VARIANT (type); } + + /* DCH 2002.05.07 -- CHANGE_BEGIN */ + + /* Returns TRUE if "fndecl" is a virtual member function with a covariant + return type. FALSE for all other cases. */ + + int + decl_needs_classtype_parm_p (fndecl) + tree fndecl; /* FUNCTION_DECL or OVERLOAD */ + { + /* ??? This code does not currently handle covariance of the form "A **", + but I'm not even sure that such a construct is legal. */ + + tree rettype; /* xxx_TYPE */ + + if (fndecl != NULL_TREE ) + { + /* Get the actual function in case of an overload */ + fndecl = OVL_CURRENT ( fndecl ); + + if (TREE_CODE (fndecl) == FUNCTION_DECL + && DECL_VIRTUAL_P (fndecl)) + { + /* What's going on here? Since member functions can be either static + or methods, the parser indicates that the function is a method by + making the type of decl "METHOD_TYPE". In that case, the TREE_TYPE + of the METHOD_TYPE is the actual return type. We do not check to + make sure that the first TREE_TYPE gives us a METHOD_TYPE; it must + be since DECL_VIRTUAL_P is true! */ + rettype = TREE_TYPE (TREE_TYPE (fndecl)); + + if (rettype != NULL_TREE + && (TREE_CODE (rettype) == POINTER_TYPE + || TREE_CODE (rettype) == REFERENCE_TYPE)) + { + return (TREE_CODE (TREE_TYPE (rettype)) == RECORD_TYPE); + } + } + } + + return 0; + } + + int + decl_has_classtype_parm_p (fndecl) + tree fndecl; /* FUNCTION_DECL or OVERLOAD */ + { + tree classtype_parm; + + if ( fndecl != NULL_TREE ) + { + /* Get the actual function in case of an overload */ + fndecl = OVL_CURRENT ( fndecl ); + + if (TREE_CODE (fndecl) == FUNCTION_DECL + && DECL_NONSTATIC_MEMBER_FUNCTION_P (fndecl)) + { + /* The classtype parameter is the second parameter... */ + classtype_parm = TREE_CHAIN ( DECL_ARGUMENTS ( fndecl ) ); + + return ( classtype_parm != NULL_TREE + && classtype_parm_identifier == DECL_NAME ( classtype_parm ) ); + } + } + return 0; + } + /* DCH 2002.05.07 -- CHANGE_END */ +