From cc600f3318f8e805fa2d9015f8f25e7f83c33a33 Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Thu, 4 Jun 1998 00:34:57 +0000 Subject: [PATCH] method.c (make_thunk): Use overload machinery to make name. * method.c (make_thunk): Use overload machinery to make name. * search.c (covariant_return_p): New fn. (get_matching_virtual): Use it. * init.c (build_new_1): Fix check for void. From-SVN: r20215 --- gcc/cp/ChangeLog | 8 +++++ gcc/cp/init.c | 2 +- gcc/cp/method.c | 23 ++++++++----- gcc/cp/search.c | 87 ++++++++++++++++++++++++++++++++---------------- 4 files changed, 83 insertions(+), 37 deletions(-) diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index ef04867d361e..6f115d65c102 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,11 @@ +1998-06-03 Jason Merrill + + * method.c (make_thunk): Use overload machinery to make name. + * search.c (covariant_return_p): New fn. + (get_matching_virtual): Use it. + + * init.c (build_new_1): Fix check for void. + 1998-06-01 Per Bothner * cp-tree.h (TYPE_FOR_JAVA): New macro. diff --git a/gcc/cp/init.c b/gcc/cp/init.c index c706a04ba31f..4eca6b630576 100644 --- a/gcc/cp/init.c +++ b/gcc/cp/init.c @@ -2261,7 +2261,7 @@ build_new_1 (exp) else size = size_in_bytes (type); - if (true_type == void_type_node) + if (TREE_CODE (true_type) == VOID_TYPE) { error ("invalid type `void' for new"); return error_mark_node; diff --git a/gcc/cp/method.c b/gcc/cp/method.c index effaf333d838..cc01371a5c67 100644 --- a/gcc/cp/method.c +++ b/gcc/cp/method.c @@ -1917,23 +1917,30 @@ make_thunk (function, delta) tree function; int delta; { - char *buffer; tree thunk_id; tree thunk; - char *func_name; tree func_decl; + if (TREE_CODE (function) != ADDR_EXPR) abort (); func_decl = TREE_OPERAND (function, 0); if (TREE_CODE (func_decl) != FUNCTION_DECL) abort (); - func_name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (func_decl)); - buffer = (char *)alloca (strlen (func_name) + 32); - if (delta<=0) - sprintf (buffer, "__thunk_%d_%s", -delta, func_name); + + OB_INIT (); + OB_PUTS ("__thunk_"); + if (delta > 0) + { + OB_PUTC ('n'); + icat (delta); + } else - sprintf (buffer, "__thunk_n%d_%s", delta, func_name); - thunk_id = get_identifier (buffer); + icat (-delta); + OB_PUTC ('_'); + OB_PUTID (DECL_ASSEMBLER_NAME (func_decl)); + OB_FINISH (); + thunk_id = get_identifier (obstack_base (&scratch_obstack)); + thunk = IDENTIFIER_GLOBAL_VALUE (thunk_id); if (thunk && TREE_CODE (thunk) != THUNK_DECL) { diff --git a/gcc/cp/search.c b/gcc/cp/search.c index f199b2f2cc18..d2ad247d38ae 100644 --- a/gcc/cp/search.c +++ b/gcc/cp/search.c @@ -2133,6 +2133,57 @@ tree_has_any_destructor_p (binfo, i) return TYPE_NEEDS_DESTRUCTOR (type); } +/* Returns > 0 if a function with type DRETTYPE overriding a function + with type BRETTYPE is covariant, as defined in [class.virtual]. + + Returns 1 if trivial covariance, 2 if non-trivial (requiring runtime + adjustment), or -1 if pedantically invalid covariance. */ + +int +covariant_return_p (brettype, drettype) + tree brettype, drettype; +{ + tree binfo; + + if (TREE_CODE (brettype) == FUNCTION_DECL + || TREE_CODE (brettype) == THUNK_DECL) + { + brettype = TREE_TYPE (TREE_TYPE (brettype)); + drettype = TREE_TYPE (TREE_TYPE (drettype)); + } + else if (TREE_CODE (brettype) == METHOD_TYPE) + { + brettype = TREE_TYPE (brettype); + drettype = TREE_TYPE (drettype); + } + + if (comptypes (brettype, drettype, 1)) + return 0; + + if (! (TREE_CODE (brettype) == TREE_CODE (drettype) + && (TREE_CODE (brettype) == POINTER_TYPE + || TREE_CODE (brettype) == REFERENCE_TYPE) + && TYPE_READONLY (brettype) == TYPE_READONLY (drettype) + && TYPE_VOLATILE (brettype) == TYPE_VOLATILE (drettype))) + return 0; + + if (! can_convert (brettype, drettype)) + return 0; + + brettype = TREE_TYPE (brettype); + drettype = TREE_TYPE (drettype); + + /* If not pedantic, allow any standard pointer conversion. */ + if (! IS_AGGR_TYPE (drettype) || ! IS_AGGR_TYPE (brettype)) + return -1; + + binfo = get_binfo (brettype, drettype, 0); + + if (! BINFO_OFFSET_ZEROP (binfo) || TREE_VIA_VIRTUAL (binfo)) + return 2; + return 1; +} + /* Given a class type TYPE, and a function decl FNDECL, look for a virtual function in TYPE's hierarchy which FNDECL could match as a virtual function. It doesn't matter which one we find. @@ -2146,6 +2197,7 @@ get_matching_virtual (binfo, fndecl, dtorp) int dtorp; { tree tmp = NULL_TREE; + int i; /* Breadth first search routines start searching basetypes of TYPE, so we must perform first ply of search here. */ @@ -2209,36 +2261,15 @@ get_matching_virtual (binfo, fndecl, dtorp) tree brettype = TREE_TYPE (TREE_TYPE (tmp)); if (comptypes (brettype, drettype, 1)) /* OK */; - else if - (TREE_CODE (brettype) == TREE_CODE (drettype) - && (TREE_CODE (brettype) == POINTER_TYPE - || TREE_CODE (brettype) == REFERENCE_TYPE) - && comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (brettype)), - TYPE_MAIN_VARIANT (TREE_TYPE (drettype)), - 0)) - /* covariant return type */ + else if ((i = covariant_return_p (brettype, drettype))) { - tree b = TREE_TYPE (brettype), d = TREE_TYPE (drettype); - if (TYPE_MAIN_VARIANT (b) != TYPE_MAIN_VARIANT (d)) + if (i == 2) + sorry ("adjusting pointers for covariant returns"); + + if (pedantic && i == -1) { - tree binfo = get_binfo (b, d, 1); - if (binfo != error_mark_node - && (! BINFO_OFFSET_ZEROP (binfo) - || TREE_VIA_VIRTUAL (binfo))) - sorry ("adjusting pointers for covariant returns"); - } - if (TYPE_READONLY (d) > TYPE_READONLY (b)) - { - cp_error_at ("return type of `%#D' adds const", fndecl); - cp_error_at (" overriding definition as `%#D'", - tmp); - } - else if (TYPE_VOLATILE (d) > TYPE_VOLATILE (b)) - { - cp_error_at ("return type of `%#D' adds volatile", - fndecl); - cp_error_at (" overriding definition as `%#D'", - tmp); + cp_pedwarn_at ("invalid covariant return type for `%#D' (must be pointer or reference to class)", fndecl); + cp_pedwarn_at (" overriding `%#D'", tmp); } } else if (IS_AGGR_TYPE_2 (brettype, drettype)