diff options
author | rth <rth@138bc75d-0d04-0410-961f-82ee72b054a4> | 1999-03-28 09:26:28 +0000 |
---|---|---|
committer | rth <rth@138bc75d-0d04-0410-961f-82ee72b054a4> | 1999-03-28 09:26:28 +0000 |
commit | 9fd68c082693e2db323eee226f8f041a1a596cc9 (patch) | |
tree | 60bd2c4c9dd96be75e26bf7a55c401eb632b6850 /gcc/cp/rtti.c | |
parent | 9f9d16c921fcede880ddba43b970b29f0f888d8f (diff) |
Merge from mainlinebefore_gc_merge_990902egcs_gc_branch
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/egcs_gc_branch@26036 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/cp/rtti.c')
-rw-r--r-- | gcc/cp/rtti.c | 157 |
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) { |