aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/cp/ChangeLog8
-rw-r--r--gcc/cp/init.c2
-rw-r--r--gcc/cp/method.c23
-rw-r--r--gcc/cp/search.c87
4 files changed, 83 insertions, 37 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index ef04867d361..6f115d65c10 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,11 @@
+1998-06-03 Jason Merrill <jason@yorick.cygnus.com>
+
+ * 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 <bothner@cygnus.com>
* cp-tree.h (TYPE_FOR_JAVA): New macro.
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index c706a04ba31..4eca6b63057 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 effaf333d83..cc01371a5c6 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 f199b2f2cc1..d2ad247d38a 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))
- {
- 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))
+ if (i == 2)
+ sorry ("adjusting pointers for covariant returns");
+
+ if (pedantic && i == -1)
{
- 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)