aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/rtti.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/cp/rtti.c')
-rw-r--r--gcc/cp/rtti.c157
1 files changed, 96 insertions, 61 deletions
diff --git a/gcc/cp/rtti.c b/gcc/cp/rtti.c
index 63f6cf409c3..41c59bbb85d 100644
--- a/gcc/cp/rtti.c
+++ b/gcc/cp/rtti.c
@@ -1,5 +1,5 @@
/* RunTime Type Identification
- Copyright (C) 1995, 1996 Free Software Foundation, Inc.
+ Copyright (C) 1995, 96-97, 1998, 1999 Free Software Foundation, Inc.
Mostly written by Jason Merrill (jason@cygnus.com).
This file is part of GNU CC.
@@ -35,18 +35,17 @@ Boston, MA 02111-1307, USA. */
extern struct obstack permanent_obstack;
-static tree call_void_fn PROTO((char *));
+static tree call_void_fn PROTO((const char *));
static tree build_headof_sub PROTO((tree));
static tree build_headof PROTO((tree));
static tree get_tinfo_var PROTO((tree));
-static tree get_typeid_1 PROTO((tree));
static tree ifnonnull PROTO((tree, tree));
static tree build_dynamic_cast_1 PROTO((tree, tree));
static void expand_si_desc PROTO((tree, tree));
static void expand_class_desc PROTO((tree, tree));
static void expand_attr_desc PROTO((tree, tree));
static void expand_ptr_desc PROTO((tree, tree));
-static void expand_generic_desc PROTO((tree, tree, char *));
+static void expand_generic_desc PROTO((tree, tree, const char *));
static tree throw_bad_cast PROTO((void));
static tree throw_bad_typeid PROTO((void));
@@ -61,7 +60,8 @@ init_rtti_processing ()
pop_namespace ();
tinfo_fn_id = get_identifier ("__tf");
tinfo_fn_type = build_function_type
- (build_reference_type (build_type_variant (type_info_type_node, 1, 0)),
+ (build_reference_type (build_qualified_type (type_info_type_node,
+ TYPE_QUAL_CONST)),
void_list_node);
}
@@ -119,8 +119,8 @@ build_headof (exp)
else
offset = build_component_ref (aref, delta_identifier, NULL_TREE, 0);
- type = build_type_variant (ptr_type_node, TREE_READONLY (exp),
- TREE_THIS_VOLATILE (exp));
+ type = build_qualified_type (ptr_type_node,
+ CP_TYPE_QUALS (TREE_TYPE (exp)));
return build (PLUS_EXPR, type, exp,
cp_convert (ptrdiff_type_node, offset));
}
@@ -129,7 +129,7 @@ build_headof (exp)
static tree
call_void_fn (name)
- char *name;
+ const char *name;
{
tree d = get_identifier (name);
tree type;
@@ -147,11 +147,10 @@ call_void_fn (name)
DECL_ARTIFICIAL (d) = 1;
pushdecl_top_level (d);
make_function_rtl (d);
- assemble_external (d);
-
pop_obstacks ();
}
+ mark_used (d);
return build_call (d, void_type_node, NULL_TREE);
}
@@ -199,6 +198,12 @@ get_tinfo_fn_dynamic (exp)
/* Peel off cv qualifiers. */
type = TYPE_MAIN_VARIANT (type);
+ if (TYPE_SIZE (complete_type (type)) == NULL_TREE)
+ {
+ cp_error ("taking typeid of incomplete type `%T'", type);
+ return error_mark_node;
+ }
+
/* If exp is a reference to polymorphic type, get the real type_info. */
if (TYPE_VIRTUAL_P (type) && ! resolves_to_fixed_type_p (exp, 0))
{
@@ -206,13 +211,7 @@ get_tinfo_fn_dynamic (exp)
tree t;
if (! flag_rtti)
- {
- warning ("taking dynamic typeid of object without -frtti");
- push_obstacks (&permanent_obstack, &permanent_obstack);
- init_rtti_processing ();
- pop_obstacks ();
- flag_rtti = 1;
- }
+ error ("taking dynamic typeid of object with -fno-rtti");
/* If we don't have rtti stuff, get to a sub-object that does. */
if (! CLASSTYPE_VFIELDS (type))
@@ -251,6 +250,12 @@ build_x_typeid (exp)
tree type = TREE_TYPE (tinfo_fn_type);
int nonnull;
+ if (TYPE_SIZE (type_info_type_node) == NULL_TREE)
+ {
+ error ("must #include <typeinfo> before using typeid");
+ return error_mark_node;
+ }
+
if (processing_template_decl)
return build_min_nt (TYPEID_EXPR, exp);
@@ -298,7 +303,7 @@ get_tinfo_var (type)
/* Figure out how much space we need to allocate for the type_info object.
If our struct layout or the type_info classes are changed, this will
need to be modified. */
- if (TYPE_VOLATILE (type) || TYPE_READONLY (type))
+ if (TYPE_QUALS (type) != TYPE_UNQUALIFIED)
size = 3 * POINTER_SIZE + INT_TYPE_SIZE;
else if (TREE_CODE (type) == POINTER_TYPE
&& ! (TREE_CODE (TREE_TYPE (type)) == OFFSET_TYPE
@@ -367,21 +372,20 @@ get_tinfo_fn (type)
pushdecl_top_level (d);
make_function_rtl (d);
- assemble_external (d);
+ mark_used (d);
mark_inline_for_output (d);
- if (at_eof)
- import_export_decl (d);
-
pop_obstacks ();
return d;
}
-static tree
+tree
get_typeid_1 (type)
tree type;
{
- tree t = build_call
+ tree t;
+
+ t = build_call
(get_tinfo_fn (type), TREE_TYPE (tinfo_fn_type), NULL_TREE);
return convert_from_reference (t);
}
@@ -394,15 +398,15 @@ get_typeid (type)
{
if (type == error_mark_node)
return error_mark_node;
-
- if (! flag_rtti)
+
+ if (TYPE_SIZE (type_info_type_node) == NULL_TREE)
{
- warning ("requesting typeid of object without -frtti");
- push_obstacks (&permanent_obstack, &permanent_obstack);
- init_rtti_processing ();
- pop_obstacks ();
- flag_rtti = 1;
+ error ("must #include <typeinfo> before using typeid");
+ return error_mark_node;
}
+
+ if (! flag_rtti)
+ error ("requesting typeid with -fno-rtti");
if (processing_template_decl)
return build_min_nt (TYPEID_EXPR, type);
@@ -417,6 +421,12 @@ get_typeid (type)
that is the operand of typeid are always ignored. */
type = TYPE_MAIN_VARIANT (type);
+ if (TYPE_SIZE (complete_type (type)) == NULL_TREE)
+ {
+ cp_error ("taking typeid of incomplete type `%T'", type);
+ return error_mark_node;
+ }
+
return get_typeid_1 (type);
}
@@ -441,10 +451,15 @@ build_dynamic_cast_1 (type, expr)
tree type, expr;
{
enum tree_code tc = TREE_CODE (type);
- tree exprtype = TREE_TYPE (expr);
+ tree exprtype;
enum tree_code ec;
tree dcast_fn;
+ tree old_expr = expr;
+ if (TREE_CODE (expr) == OFFSET_REF)
+ expr = resolve_offset_ref (expr);
+
+ exprtype = TREE_TYPE (expr);
assert (exprtype != NULL_TREE);
ec = TREE_CODE (exprtype);
@@ -463,8 +478,8 @@ build_dynamic_cast_1 (type, expr)
goto fail;
if (TYPE_SIZE (complete_type (TREE_TYPE (exprtype))) == NULL_TREE)
goto fail;
- if (TREE_READONLY (TREE_TYPE (exprtype))
- && ! TYPE_READONLY (TREE_TYPE (type)))
+ if (!at_least_as_qualified_p (TREE_TYPE (type),
+ TREE_TYPE (exprtype)))
goto fail;
if (TYPE_MAIN_VARIANT (TREE_TYPE (type)) == void_type_node)
break;
@@ -483,8 +498,6 @@ build_dynamic_cast_1 (type, expr)
/* Apply trivial conversion T -> T& for dereferenced ptrs. */
if (ec == RECORD_TYPE)
{
- exprtype = build_type_variant (exprtype, TREE_READONLY (expr),
- TREE_THIS_VOLATILE (expr));
exprtype = build_reference_type (exprtype);
expr = convert_to_reference (exprtype, expr, CONV_IMPLICIT,
LOOKUP_NORMAL, NULL_TREE);
@@ -499,8 +512,8 @@ build_dynamic_cast_1 (type, expr)
goto fail;
if (TYPE_SIZE (complete_type (TREE_TYPE (exprtype))) == NULL_TREE)
goto fail;
- if (TREE_READONLY (TREE_TYPE (exprtype))
- && ! TYPE_READONLY (TREE_TYPE (type)))
+ if (!at_least_as_qualified_p (TREE_TYPE (type),
+ TREE_TYPE (exprtype)))
goto fail;
}
@@ -512,6 +525,20 @@ build_dynamic_cast_1 (type, expr)
distance = get_base_distance (TREE_TYPE (type), TREE_TYPE (exprtype), 1,
&path);
+
+ if (distance == -2)
+ {
+ cp_error ("dynamic_cast from `%T' to ambiguous base class `%T'",
+ TREE_TYPE (exprtype), TREE_TYPE (type));
+ return error_mark_node;
+ }
+ if (distance == -3)
+ {
+ cp_error ("dynamic_cast from `%T' to private base class `%T'",
+ TREE_TYPE (exprtype), TREE_TYPE (type));
+ return error_mark_node;
+ }
+
if (distance >= 0)
return build_vbase_path (PLUS_EXPR, type, expr, path, 0);
}
@@ -547,11 +574,11 @@ build_dynamic_cast_1 (type, expr)
dynamic_cast<D&>(b) (b an object) cannot succeed. */
if (ec == REFERENCE_TYPE)
{
- if (TREE_CODE (expr) == VAR_DECL
- && TREE_CODE (TREE_TYPE (expr)) == RECORD_TYPE)
+ if (TREE_CODE (old_expr) == VAR_DECL
+ && TREE_CODE (TREE_TYPE (old_expr)) == RECORD_TYPE)
{
cp_warning ("dynamic_cast of `%#D' to `%#T' can never succeed",
- expr, type);
+ old_expr, type);
return throw_bad_cast ();
}
}
@@ -563,7 +590,7 @@ build_dynamic_cast_1 (type, expr)
&& TREE_CODE (TREE_TYPE (op)) == RECORD_TYPE)
{
cp_warning ("dynamic_cast of `%#D' to `%#T' can never succeed",
- expr, type);
+ op, type);
retval = build_int_2 (0, 0);
TREE_TYPE (retval) = type;
return retval;
@@ -621,10 +648,10 @@ build_dynamic_cast_1 (type, expr)
DECL_ARTIFICIAL (dcast_fn) = 1;
pushdecl_top_level (dcast_fn);
make_function_rtl (dcast_fn);
- assemble_external (dcast_fn);
pop_obstacks ();
}
+ mark_used (dcast_fn);
result = build_call
(dcast_fn, TREE_TYPE (TREE_TYPE (dcast_fn)), elems);
@@ -686,7 +713,7 @@ expand_si_desc (tdecl, type)
tree type;
{
tree t, elems, fn;
- char *name = build_overload_name (type, 1, 1);
+ const char *name = build_overload_name (type, 1, 1);
tree name_string = combine_strings (build_string (strlen (name)+1, name));
type = BINFO_TYPE (TREE_VEC_ELT (TYPE_BINFO_BASETYPES (type), 0));
@@ -717,10 +744,10 @@ expand_si_desc (tdecl, type)
DECL_ARTIFICIAL (fn) = 1;
pushdecl_top_level (fn);
make_function_rtl (fn);
- assemble_external (fn);
pop_obstacks ();
}
+ mark_used (fn);
fn = build_call (fn, TREE_TYPE (TREE_TYPE (fn)), elems);
expand_expr_stmt (fn);
}
@@ -734,7 +761,7 @@ expand_class_desc (tdecl, type)
{
tree name_string;
tree fn, tmp;
- char *name;
+ const char *name;
int i = CLASSTYPE_N_BASECLASSES (type);
int base_cnt = 0;
@@ -760,7 +787,9 @@ expand_class_desc (tdecl, type)
/* Actually const __user_type_info * */
fields [0] = build_lang_field_decl
(FIELD_DECL, NULL_TREE,
- build_pointer_type (build_type_variant (type_info_type_node, 1, 0)));
+ build_pointer_type (build_qualified_type
+ (type_info_type_node,
+ TYPE_QUAL_CONST)));
fields [1] = build_lang_field_decl
(FIELD_DECL, NULL_TREE, unsigned_intSI_type_node);
DECL_BIT_FIELD (fields[1]) = 1;
@@ -792,7 +821,7 @@ expand_class_desc (tdecl, type)
if (TREE_VIA_VIRTUAL (binfo))
{
tree t = BINFO_TYPE (binfo);
- char *name;
+ const char *name;
tree field;
FORMAT_VBASE_NAME (name, t);
@@ -896,10 +925,10 @@ expand_class_desc (tdecl, type)
DECL_ARTIFICIAL (fn) = 1;
pushdecl_top_level (fn);
make_function_rtl (fn);
- assemble_external (fn);
pop_obstacks ();
}
+ mark_used (fn);
fn = build_call (fn, TREE_TYPE (TREE_TYPE (fn)), elems);
expand_expr_stmt (fn);
}
@@ -912,7 +941,7 @@ expand_ptr_desc (tdecl, type)
tree type;
{
tree t, elems, fn;
- char *name = build_overload_name (type, 1, 1);
+ const char *name = build_overload_name (type, 1, 1);
tree name_string = combine_strings (build_string (strlen (name)+1, name));
type = TREE_TYPE (type);
@@ -943,10 +972,10 @@ expand_ptr_desc (tdecl, type)
DECL_ARTIFICIAL (fn) = 1;
pushdecl_top_level (fn);
make_function_rtl (fn);
- assemble_external (fn);
pop_obstacks ();
}
+ mark_used (fn);
fn = build_call (fn, TREE_TYPE (TREE_TYPE (fn)), elems);
expand_expr_stmt (fn);
}
@@ -959,10 +988,9 @@ expand_attr_desc (tdecl, type)
tree type;
{
tree elems, t, fn;
- char *name = build_overload_name (type, 1, 1);
+ const char *name = build_overload_name (type, 1, 1);
tree name_string = combine_strings (build_string (strlen (name)+1, name));
- tree attrval = build_int_2
- (TYPE_READONLY (type) | TYPE_VOLATILE (type) * 2, 0);
+ tree attrval = build_int_2 (TYPE_QUALS (type), 0);
expand_expr_stmt (get_typeid_1 (TYPE_MAIN_VARIANT (type)));
t = decay_conversion (get_tinfo_var (TYPE_MAIN_VARIANT (type)));
@@ -992,10 +1020,10 @@ expand_attr_desc (tdecl, type)
DECL_ARTIFICIAL (fn) = 1;
pushdecl_top_level (fn);
make_function_rtl (fn);
- assemble_external (fn);
pop_obstacks ();
}
+ mark_used (fn);
fn = build_call (fn, TREE_TYPE (TREE_TYPE (fn)), elems);
expand_expr_stmt (fn);
}
@@ -1006,9 +1034,9 @@ static void
expand_generic_desc (tdecl, type, fnname)
tree tdecl;
tree type;
- char *fnname;
+ const char *fnname;
{
- char *name = build_overload_name (type, 1, 1);
+ const char *name = build_overload_name (type, 1, 1);
tree name_string = combine_strings (build_string (strlen (name)+1, name));
tree elems = tree_cons
(NULL_TREE, decay_conversion (tdecl), tree_cons
@@ -1032,10 +1060,10 @@ expand_generic_desc (tdecl, type, fnname)
DECL_ARTIFICIAL (fn) = 1;
pushdecl_top_level (fn);
make_function_rtl (fn);
- assemble_external (fn);
pop_obstacks ();
}
+ mark_used (fn);
fn = build_call (fn, TREE_TYPE (TREE_TYPE (fn)), elems);
expand_expr_stmt (fn);
}
@@ -1058,9 +1086,16 @@ synthesize_tinfo_fn (fndecl)
tree fndecl;
{
tree type = TREE_TYPE (DECL_NAME (fndecl));
- tree tmp, addr;
+ tree tmp, addr, tdecl;
+
+ if (at_eof)
+ {
+ import_export_decl (fndecl);
+ if (DECL_REALLY_EXTERN (fndecl))
+ return;
+ }
- tree tdecl = get_tinfo_var (type);
+ tdecl = get_tinfo_var (type);
DECL_EXTERNAL (tdecl) = 0;
TREE_STATIC (tdecl) = 1;
DECL_COMMON (tdecl) = 1;
@@ -1085,7 +1120,7 @@ synthesize_tinfo_fn (fndecl)
expand_generic_desc (tdecl, type, "__rtti_func");
else if (TREE_CODE (type) == ARRAY_TYPE)
expand_generic_desc (tdecl, type, "__rtti_array");
- else if (TYPE_VOLATILE (type) || TYPE_READONLY (type))
+ else if (TYPE_QUALS (type) != TYPE_UNQUALIFIED)
expand_attr_desc (tdecl, type);
else if (TREE_CODE (type) == POINTER_TYPE)
{