diff options
Diffstat (limited to 'contrib/gcc/cp/decl.c')
-rw-r--r-- | contrib/gcc/cp/decl.c | 746 |
1 files changed, 405 insertions, 341 deletions
diff --git a/contrib/gcc/cp/decl.c b/contrib/gcc/cp/decl.c index a5d9c64..ebff32f 100644 --- a/contrib/gcc/cp/decl.c +++ b/contrib/gcc/cp/decl.c @@ -46,15 +46,11 @@ Boston, MA 02111-1307, USA. */ #include "tm_p.h" #include "target.h" #include "c-common.h" +#include "c-pragma.h" #include "diagnostic.h" extern const struct attribute_spec *lang_attribute_table; -#ifndef BOOL_TYPE_SIZE -/* `bool' has size and alignment `1', on all platforms. */ -#define BOOL_TYPE_SIZE CHAR_TYPE_SIZE -#endif - static tree grokparms PARAMS ((tree)); static const char *redeclaration_error_message PARAMS ((tree, tree)); @@ -81,11 +77,14 @@ static tree grokfndecl PARAMS ((tree, tree, tree, tree, int, enum overload_flags, tree, tree, int, int, int, int, int, int, tree)); static tree grokvardecl PARAMS ((tree, tree, RID_BIT_TYPE *, int, int, tree)); +static tree follow_tag_typedef PARAMS ((tree)); static tree lookup_tag PARAMS ((enum tree_code, tree, struct binding_level *, int)); static void set_identifier_type_value_with_scope PARAMS ((tree, tree, struct binding_level *)); static void record_unknown_type PARAMS ((tree, const char *)); +static tree builtin_function_1 PARAMS ((const char *, tree, tree, int, + enum built_in_class, const char *)); static tree build_library_fn_1 PARAMS ((tree, enum tree_code, tree)); static int member_function_or_else PARAMS ((tree, tree, enum overload_flags)); static void bad_specifiers PARAMS ((tree, const char *, int, int, int, int, @@ -395,10 +394,6 @@ struct binding_level /* The binding level which this one is contained in (inherits from). */ struct binding_level *level_chain; - /* List of decls in `names' that have incomplete - structure or union types. */ - tree incomplete; - /* List of VAR_DECLS saved from a previous for statement. These would be dead in ISO-conforming code, but might be referenced in ARM-era code. These are stored in a @@ -481,6 +476,12 @@ static struct binding_level *global_binding_level; static int keep_next_level_flag; +/* A TREE_LIST of VAR_DECLs. The TREE_PURPOSE is a RECORD_TYPE or + UNION_TYPE; the TREE_VALUE is a VAR_DECL with that type. At the + time the VAR_DECL was declared, the type was incomplete. */ + +static tree incomplete_vars; + #if defined(DEBUG_CP_BINDING_LEVELS) static int binding_depth = 0; static int is_class_level = 0; @@ -842,7 +843,6 @@ pushlevel (tag_transparent) newlevel = make_binding_level (); push_binding_level (newlevel, tag_transparent, keep_next_level_flag); - GNU_xref_start_scope ((size_t) newlevel); keep_next_level_flag = 0; } @@ -1301,11 +1301,6 @@ poplevel (keep, reverse, functionbody) rather than the end. This hack is no longer used. */ my_friendly_assert (keep == 0 || keep == 1, 0); - GNU_xref_end_scope ((size_t) current_binding_level, - (size_t) current_binding_level->level_chain, - current_binding_level->parm_flag, - current_binding_level->keep); - if (current_binding_level->keep == 1) keep = 1; @@ -1727,11 +1722,6 @@ poplevel_class () shadowed = TREE_CHAIN (shadowed)) pop_binding (TREE_PURPOSE (shadowed), TREE_TYPE (shadowed)); - GNU_xref_end_scope ((size_t) class_binding_level, - (size_t) class_binding_level->level_chain, - class_binding_level->parm_flag, - class_binding_level->keep); - /* Now, pop out of the binding level which we created up in the `pushlevel_class' routine. */ #if defined(DEBUG_CP_BINDING_LEVELS) @@ -1965,7 +1955,6 @@ mark_binding_level (arg) ggc_mark_tree (lvl->shadowed_labels); ggc_mark_tree (lvl->blocks); ggc_mark_tree (lvl->this_class); - ggc_mark_tree (lvl->incomplete); ggc_mark_tree (lvl->dead_vars_from_for); } } @@ -2003,8 +1992,6 @@ print_binding_level (lvl) int i = 0, len; fprintf (stderr, " blocks="); fprintf (stderr, HOST_PTR_PRINTF, lvl->blocks); - fprintf (stderr, " n_incomplete=%d parm_flag=%d keep=%d", - list_length (lvl->incomplete), lvl->parm_flag, lvl->keep); if (lvl->tag_transparent) fprintf (stderr, " tag-transparent"); if (lvl->more_cleanups_ok) @@ -2405,7 +2392,6 @@ mark_saved_scope (arg) ggc_mark_tree (t->x_previous_class_type); ggc_mark_tree (t->x_previous_class_values); ggc_mark_tree (t->x_saved_tree); - ggc_mark_tree (t->incomplete); ggc_mark_tree (t->lookups); mark_stmt_tree (&t->x_stmt_tree); @@ -2511,6 +2497,7 @@ maybe_push_to_top_level (pseudo) s->bindings = b; s->need_pop_function_context = need_pop; s->function_decl = current_function_decl; + s->last_parms = last_function_parms; scope_chain = s; current_function_decl = NULL_TREE; @@ -2552,6 +2539,7 @@ pop_from_top_level () if (s->need_pop_function_context) pop_function_context_from (NULL_TREE); current_function_decl = s->function_decl; + last_function_parms = s->last_parms; free (s); } @@ -3153,6 +3141,10 @@ duplicate_decls (newdecl, olddecl) { if (TREE_CODE (newdecl) != FUNCTION_DECL) { + /* Avoid warnings redeclaring anticipated built-ins. */ + if (DECL_ANTICIPATED (olddecl)) + return 0; + /* If you declare a built-in or predefined function name as static, the old definition is overridden, but optionally warn this was a bad choice of name. */ @@ -3180,7 +3172,10 @@ duplicate_decls (newdecl, olddecl) } else if (!types_match) { - if ((DECL_EXTERN_C_P (newdecl) + /* Avoid warnings redeclaring anticipated built-ins. */ + if (DECL_ANTICIPATED (olddecl)) + ; /* Do nothing yet. */ + else if ((DECL_EXTERN_C_P (newdecl) && DECL_EXTERN_C_P (olddecl)) || compparms (TYPE_ARG_TYPES (TREE_TYPE (newdecl)), TYPE_ARG_TYPES (TREE_TYPE (olddecl)))) @@ -3201,6 +3196,9 @@ duplicate_decls (newdecl, olddecl) else /* Discard the old built-in function. */ return 0; + + /* Replace the old RTL to avoid problems with inlining. */ + SET_DECL_RTL (olddecl, DECL_RTL (newdecl)); } if (DECL_THIS_STATIC (newdecl) && !DECL_THIS_STATIC (olddecl)) @@ -3215,9 +3213,6 @@ duplicate_decls (newdecl, olddecl) will be banished. */ SET_DECL_LANGUAGE (olddecl, DECL_LANGUAGE (newdecl)); SET_DECL_RTL (olddecl, DECL_RTL (newdecl)); - COPY_DECL_ASSEMBLER_NAME (olddecl, newdecl); - SET_IDENTIFIER_GLOBAL_VALUE (DECL_ASSEMBLER_NAME (newdecl), - newdecl); } } else if (TREE_CODE (olddecl) != TREE_CODE (newdecl)) @@ -3355,6 +3350,7 @@ duplicate_decls (newdecl, olddecl) && namespace_bindings_p ()) ? "`%#D' previously defined here" : "`%#D' previously declared here", olddecl); + return 0; } else if (TREE_CODE (olddecl) == FUNCTION_DECL && DECL_INITIAL (olddecl) != NULL_TREE @@ -3400,13 +3396,10 @@ duplicate_decls (newdecl, olddecl) if (1 == simple_cst_equal (TREE_PURPOSE (t1), TREE_PURPOSE (t2))) { - if (pedantic) - { - pedwarn ("default argument given for parameter %d of `%#D'", - i, newdecl); - cp_pedwarn_at ("after previous specification in `%#D'", - olddecl); - } + pedwarn ("default argument given for parameter %d of `%#D'", + i, newdecl); + cp_pedwarn_at ("after previous specification in `%#D'", + olddecl); } else { @@ -3429,6 +3422,18 @@ duplicate_decls (newdecl, olddecl) } } + /* Do not merge an implicit typedef with an explicit one. In: + + class A; + ... + typedef class A A __attribute__ ((foo)); + + the attribute should apply only to the typedef. */ + if (TREE_CODE (olddecl) == TYPE_DECL + && (DECL_IMPLICIT_TYPEDEF_P (olddecl) + || DECL_IMPLICIT_TYPEDEF_P (newdecl))) + return 0; + /* If new decl is `static' and an `extern' was seen previously, warn about it. */ warn_extern_redeclared_static (newdecl, olddecl); @@ -3495,6 +3500,7 @@ duplicate_decls (newdecl, olddecl) except for any that we copy here from the old type. */ DECL_ATTRIBUTES (newdecl) = (*targetm.merge_decl_attributes) (olddecl, newdecl); + decl_attributes (&newdecl, DECL_ATTRIBUTES (newdecl), 0); if (TREE_CODE (newdecl) == TEMPLATE_DECL) { @@ -3526,16 +3532,16 @@ duplicate_decls (newdecl, olddecl) tree newtype; /* Merge the data types specified in the two decls. */ - newtype = common_type (TREE_TYPE (newdecl), TREE_TYPE (olddecl)); + newtype = merge_types (TREE_TYPE (newdecl), TREE_TYPE (olddecl)); - /* If common_type produces a non-typedef type, just use the old type. */ + /* If merge_types produces a non-typedef type, just use the old type. */ if (TREE_CODE (newdecl) == TYPE_DECL && newtype == DECL_ORIGINAL_TYPE (newdecl)) newtype = oldtype; if (TREE_CODE (newdecl) == VAR_DECL) DECL_THIS_EXTERN (newdecl) |= DECL_THIS_EXTERN (olddecl); - /* Do this after calling `common_type' so that default + /* Do this after calling `merge_types' so that default parameters don't confuse us. */ else if (TREE_CODE (newdecl) == FUNCTION_DECL && (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (newdecl)) @@ -3599,15 +3605,23 @@ duplicate_decls (newdecl, olddecl) if (DECL_SECTION_NAME (newdecl) == NULL_TREE) DECL_SECTION_NAME (newdecl) = DECL_SECTION_NAME (olddecl); - /* Keep the old rtl since we can safely use it. */ - COPY_DECL_RTL (olddecl, newdecl); - if (TREE_CODE (newdecl) == FUNCTION_DECL) { DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (newdecl) |= DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (olddecl); DECL_NO_LIMIT_STACK (newdecl) |= DECL_NO_LIMIT_STACK (olddecl); + /* Keep the old RTL. */ + COPY_DECL_RTL (olddecl, newdecl); + } + else if (TREE_CODE (newdecl) == VAR_DECL + && (DECL_SIZE (olddecl) || !DECL_SIZE (newdecl))) + { + /* Keep the old RTL. We cannot keep the old RTL if the old + declaration was for an incomplete object and the new + declaration is not since many attributes of the RTL will + change. */ + COPY_DECL_RTL (olddecl, newdecl); } } /* If cannot merge, then use the new type and qualifiers, @@ -3626,7 +3640,8 @@ duplicate_decls (newdecl, olddecl) } /* Merge the storage class information. */ - DECL_WEAK (newdecl) |= DECL_WEAK (olddecl); + merge_weak (newdecl, olddecl); + DECL_ONE_ONLY (newdecl) |= DECL_ONE_ONLY (olddecl); DECL_DEFER_OUTPUT (newdecl) |= DECL_DEFER_OUTPUT (olddecl); TREE_PUBLIC (newdecl) = TREE_PUBLIC (olddecl); @@ -4242,22 +4257,8 @@ pushdecl (x) if (TREE_CODE (x) == FUNCTION_DECL) check_default_args (x); - /* Keep count of variables in this level with incomplete type. */ - if (TREE_CODE (x) == VAR_DECL - && TREE_TYPE (x) != error_mark_node - && ((!COMPLETE_TYPE_P (TREE_TYPE (x)) - && PROMOTES_TO_AGGR_TYPE (TREE_TYPE (x), ARRAY_TYPE)) - /* RTTI TD entries are created while defining the type_info. */ - || (TYPE_LANG_SPECIFIC (TREE_TYPE (x)) - && TYPE_BEING_DEFINED (TREE_TYPE (x))))) - { - if (namespace_bindings_p ()) - namespace_scope_incomplete - = tree_cons (NULL_TREE, x, namespace_scope_incomplete); - else - current_binding_level->incomplete - = tree_cons (NULL_TREE, x, current_binding_level->incomplete); - } + if (TREE_CODE (x) == VAR_DECL) + maybe_register_incomplete_var (x); } if (need_new_binding) @@ -5301,6 +5302,47 @@ storetags (tags) current_binding_level->tags = tags; } +/* Return the type that should be used when TYPE's name is preceded + by a tag such as 'struct' or 'union', or null if the name cannot + be used in this way. + + For example, when processing the third line of: + + struct A; + typedef struct A A; + struct A; + + lookup of A will find the typedef. Given A's typedef, this function + will return the type associated with "struct A". For the tag to be + anything other than TYPE, TYPE must be a typedef whose original type + has the same name and context as TYPE itself. + + It is not valid for a typedef of an anonymous type to be used with + an explicit tag: + + typedef struct { ... } B; + struct B; + + Return null for this case. */ + +static tree +follow_tag_typedef (type) + tree type; +{ + tree original; + + original = original_type (type); + if (! TYPE_NAME (original)) + return NULL_TREE; + if (TYPE_IDENTIFIER (original) == TYPE_IDENTIFIER (type) + && (CP_DECL_CONTEXT (TYPE_NAME (original)) + == CP_DECL_CONTEXT (TYPE_NAME (type))) + && !(CLASS_TYPE_P (original) && TYPE_WAS_ANONYMOUS (original))) + return original; + else + return NULL_TREE; +} + /* Given NAME, an IDENTIFIER_NODE, return the structure (or union or enum) definition for that name. Searches binding levels from BINDING_LEVEL up to the global level. @@ -5352,18 +5394,23 @@ lookup_tag (form, name, binding_level, thislevel_only) else old = BINDING_TYPE (old); - /* If it has an original type, it is a typedef, and we - should not return it. */ - if (old && DECL_ORIGINAL_TYPE (TYPE_NAME (old))) - old = NULL_TREE; - if (old && TREE_CODE (old) != form - && !(form != ENUMERAL_TYPE && TREE_CODE (old) == TEMPLATE_DECL)) + if (old) { - error ("`%#D' redeclared as %C", old, form); - return NULL_TREE; + /* We've found something at this binding level. If it is + a typedef, extract the tag it refers to. Lookup fails + if the typedef doesn't refer to a taggable type. */ + old = follow_tag_typedef (old); + if (!old) + return NULL_TREE; + if (TREE_CODE (old) != form + && (form == ENUMERAL_TYPE + || TREE_CODE (old) == ENUMERAL_TYPE)) + { + error ("`%#D' redeclared as %C", old, form); + return NULL_TREE; + } + return old; } - if (old) - return old; if (thislevel_only || tail == global_namespace) return NULL_TREE; } @@ -5373,14 +5420,12 @@ lookup_tag (form, name, binding_level, thislevel_only) if (TREE_PURPOSE (tail) == name) { enum tree_code code = TREE_CODE (TREE_VALUE (tail)); - /* Should tighten this up; it'll probably permit - UNION_TYPE and a struct template, for example. */ + if (code != form - && !(form != ENUMERAL_TYPE && code == TEMPLATE_DECL)) + && (form == ENUMERAL_TYPE || code == ENUMERAL_TYPE)) { /* Definition isn't the kind we were looking for. */ - error ("`%#D' redeclared as %C", TREE_VALUE (tail), - form); + error ("`%#D' redeclared as %C", TREE_VALUE (tail), form); return NULL_TREE; } return TREE_VALUE (tail); @@ -5502,7 +5547,7 @@ lookup_namespace_name (namespace, name) /*in_decl=*/NULL_TREE, /*context=*/NULL_TREE, /*entering_scope=*/0, - /*complain=*/1); + tf_error | tf_warning); else if (DECL_FUNCTION_TEMPLATE_P (val) || TREE_CODE (val) == OVERLOAD) val = lookup_template_function (val, @@ -5518,7 +5563,12 @@ lookup_namespace_name (namespace, name) /* If we have a single function from a using decl, pull it out. */ if (TREE_CODE (val) == OVERLOAD && ! really_overloaded_fn (val)) val = OVL_FUNCTION (val); - return val; + + /* Ignore built-in functions that haven't been prototyped yet. */ + if (!val || !DECL_P(val) + || !DECL_LANG_SPECIFIC(val) + || !DECL_ANTICIPATED (val)) + return val; } error ("`%D' undeclared in namespace `%D'", name, namespace); @@ -5621,12 +5671,15 @@ build_typename_type (context, name, fullname, base_type) /* Resolve `typename CONTEXT::NAME'. Returns an appropriate type, unless an error occurs, in which case error_mark_node is returned. - If COMPLAIN zero, don't complain about any errors that occur. */ + If we locate a non-artificial TYPE_DECL and TF_KEEP_TYPE_DECL is + set, we return that, rather than the _TYPE it corresponds to, in + other cases we look through the type decl. If TF_ERROR is set, + complain about errors, otherwise be quiet. */ tree make_typename_type (context, name, complain) tree context, name; - int complain; + tsubst_flags_t complain; { tree fullname; @@ -5665,7 +5718,7 @@ make_typename_type (context, name, complain) { /* We can get here from typename_sub0 in the explicit_template_type expansion. Just fail. */ - if (complain) + if (complain & tf_error) error ("no class template named `%#T' in `%#T'", name, context); return error_mark_node; @@ -5681,7 +5734,7 @@ make_typename_type (context, name, complain) tmpl = lookup_field (context, name, 0, 0); if (!tmpl || !DECL_CLASS_TEMPLATE_P (tmpl)) { - if (complain) + if (complain & tf_error) error ("no class template named `%#T' in `%#T'", name, context); return error_mark_node; @@ -5691,7 +5744,7 @@ make_typename_type (context, name, complain) TREE_OPERAND (fullname, 1), NULL_TREE, context, /*entering_scope=*/0, - /*complain=*/1); + tf_error | tf_warning); } else { @@ -5699,14 +5752,29 @@ make_typename_type (context, name, complain) if (!IS_AGGR_TYPE (context)) { - if (complain) + if (complain & tf_error) error ("no type named `%#T' in `%#T'", name, context); return error_mark_node; } t = lookup_field (context, name, 0, 1); if (t) - return TREE_TYPE (t); + { + if (DECL_ARTIFICIAL (t) || !(complain & tf_keep_type_decl)) + t = TREE_TYPE (t); + if (IMPLICIT_TYPENAME_P (t)) + { + /* Lookup found an implicit typename that we had + injected into the current scope. Doing things + properly would have located the exact same type, + so there is no error here. We must remove the + implicitness so that we do not warn about it. */ + t = copy_node (t); + TREE_TYPE (t) = NULL_TREE; + } + + return t; + } } } @@ -5714,7 +5782,7 @@ make_typename_type (context, name, complain) there now or its never going to be. */ if (!uses_template_parms (context)) { - if (complain) + if (complain & tf_error) error ("no type named `%#T' in `%#T'", name, context); return error_mark_node; } @@ -5725,7 +5793,9 @@ make_typename_type (context, name, complain) /* Resolve `CONTEXT::template NAME'. Returns an appropriate type, unless an error occurs, in which case error_mark_node is returned. - If COMPLAIN zero, don't complain about any errors that occur. */ + If we locate a TYPE_DECL, we return that, rather than the _TYPE it + corresponds to. If COMPLAIN zero, don't complain about any errors + that occur. */ tree make_unbound_class_template (context, name, complain) @@ -5788,14 +5858,6 @@ select_decl (binding, flags) tree val; val = BINDING_VALUE (binding); - /* When we implicitly declare some builtin entity, we mark it - DECL_ANTICIPATED, so that we know to ignore it until it is - really declared. */ - if (val && DECL_P (val) - && DECL_LANG_SPECIFIC (val) - && DECL_ANTICIPATED (val)) - return NULL_TREE; - if (LOOKUP_NAMESPACES_ONLY (flags)) { /* We are not interested in types. */ @@ -5845,9 +5907,21 @@ unqualified_namespace_lookup (name, flags, spacesp) *spacesp = tree_cons (scope, NULL_TREE, *spacesp); val = binding_for_name (name, scope); - /* Initialize binding for this context. */ - BINDING_VALUE (b) = BINDING_VALUE (val); - BINDING_TYPE (b) = BINDING_TYPE (val); + /* Ignore anticipated built-in functions. */ + if (val && BINDING_VALUE (val) + && DECL_P (BINDING_VALUE (val)) + && DECL_LANG_SPECIFIC (BINDING_VALUE (val)) + && DECL_ANTICIPATED (BINDING_VALUE (val))) + { + BINDING_VALUE (b) = NULL_TREE; + BINDING_TYPE (b) = NULL_TREE; + } + else + { + /* Initialize binding for this context. */ + BINDING_VALUE (b) = BINDING_VALUE (val); + BINDING_TYPE (b) = BINDING_TYPE (val); + } /* Add all _DECLs seen through local using-directives. */ for (level = current_binding_level; @@ -6437,12 +6511,6 @@ cxx_init_decl_processing () flag_inline_functions = 0; } - /* In C++, we never create builtin functions whose name does not - begin with `__'. Users should be using headers to get prototypes - in C++. It would be nice if we could warn when `-fbuiltin' is - used explicitly, but we do not have that information. */ - flag_no_builtin = 1; - /* Initially, C. */ current_lang_name = lang_name_c; @@ -6640,6 +6708,7 @@ cxx_init_decl_processing () ggc_add_tree_root (¤t_lang_name, 1); ggc_add_tree_root (&static_aggregates, 1); ggc_add_tree_root (&free_bindings, 1); + ggc_add_tree_root (&incomplete_vars, 1); } /* Generate an initializer for a function naming variable from @@ -6707,10 +6776,9 @@ cp_make_fname_decl (id, type_dep) return decl; } -/* Entry point for the benefit of c_common_nodes_and_builtins. - - Make a definition for a builtin function named NAME and whose data type - is TYPE. TYPE should be a function type with argument types. +/* Make a definition for a builtin function named NAME in the current + namespace, whose data type is TYPE and whose context is CONTEXT. + TYPE should be a function type with argument types. CLASS and CODE tell later passes how to compile calls to this function. See tree.h for possible values. @@ -6718,10 +6786,11 @@ cp_make_fname_decl (id, type_dep) If LIBNAME is nonzero, use that for DECL_ASSEMBLER_NAME, the name to be called if we can't opencode the function. */ -tree -builtin_function (name, type, code, class, libname) +static tree +builtin_function_1 (name, type, context, code, class, libname) const char *name; tree type; + tree context; int code; enum built_in_class class; const char *libname; @@ -6729,19 +6798,13 @@ builtin_function (name, type, code, class, libname) tree decl = build_library_fn_1 (get_identifier (name), ERROR_MARK, type); DECL_BUILT_IN_CLASS (decl) = class; DECL_FUNCTION_CODE (decl) = code; + DECL_CONTEXT (decl) = context; - my_friendly_assert (DECL_CONTEXT (decl) == NULL_TREE, 392); + /* The return builtins leave the current function. */ + if (code == BUILT_IN_RETURN || code == BUILT_IN_EH_RETURN) + TREE_THIS_VOLATILE (decl) = 1; - /* All builtins that don't begin with an `_' should go in the `std' - namespace. */ - if (name[0] != '_') - { - push_namespace (std_identifier); - DECL_CONTEXT (decl) = std_node; - } pushdecl (decl); - if (name[0] != '_') - pop_namespace (); /* Since `pushdecl' relies on DECL_ASSEMBLER_NAME instead of DECL_NAME, we cannot change DECL_ASSEMBLER_NAME until we have installed this @@ -6761,6 +6824,39 @@ builtin_function (name, type, code, class, libname) return decl; } +/* Entry point for the benefit of c_common_nodes_and_builtins. + + Make a defintion for a builtin function named NAME and whose data type + is TYPE. TYPE should be a function type with argument types. This + function places the anticipated declaration in the global namespace + and additionally in the std namespace if appropriate. + + CLASS and CODE tell later passes how to compile calls to this function. + See tree.h for possible values. + + If LIBNAME is nonzero, use that for DECL_ASSEMBLER_NAME, + the name to be called if we can't opencode the function. */ + +tree +builtin_function (name, type, code, class, libname) + const char *name; + tree type; + int code; + enum built_in_class class; + const char *libname; +{ + /* All builtins that don't begin with an '_' should additionally + go in the 'std' namespace. */ + if (name[0] != '_') + { + push_namespace (std_identifier); + builtin_function_1 (name, type, std_node, code, class, libname); + pop_namespace (); + } + + return builtin_function_1 (name, type, NULL_TREE, code, class, libname); +} + /* Generate a FUNCTION_DECL with the typical flags for a runtime library function. Not called directly. */ @@ -7258,6 +7354,10 @@ start_decl (declarator, declspecs, initialized, attributes, prefix_attributes) /* Set attributes here so if duplicate decl, will have proper attributes. */ cplus_decl_attributes (&decl, attributes, 0); + /* If #pragma weak was used, mark the decl weak now. */ + if (current_binding_level == global_binding_level) + maybe_apply_pragma_weak (decl); + if (TREE_CODE (decl) == FUNCTION_DECL && DECL_DECLARED_INLINE_P (decl) && DECL_UNINLINABLE (decl) @@ -7390,7 +7490,7 @@ start_decl_1 (decl) if ((! processing_template_decl || ! uses_template_parms (type)) && !COMPLETE_TYPE_P (complete_type (type))) { - error ("aggregate `%#D' has incomplete type and cannot be initialized", + error ("aggregate `%#D' has incomplete type and cannot be defined", decl); /* Change the type so that assemble_variable will give DECL an rtl we can live with: (mem (const_int 0)). */ @@ -7868,8 +7968,9 @@ make_rtl_for_nonlocal_decl (decl, init, asmspec) && toplev && !TREE_PUBLIC (decl)) { - /* Fool with the linkage according to #pragma interface. */ - if (!interface_unknown) + /* Fool with the linkage of static consts according to #pragma + interface. */ + if (!interface_unknown && !TREE_PUBLIC (decl)) { TREE_PUBLIC (decl) = 1; DECL_EXTERNAL (decl) = interface_only; @@ -7877,6 +7978,9 @@ make_rtl_for_nonlocal_decl (decl, init, asmspec) defer_p = 1; } + /* Likewise for template instantiations. */ + else if (DECL_COMDAT (decl)) + defer_p = 1; /* If we're deferring the variable, we only need to make RTL if there's an ASMSPEC. Otherwise, we'll lazily create it later when @@ -8029,8 +8133,7 @@ destroy_local_var (decl) cleanup = maybe_build_cleanup (decl); /* Record the cleanup required for this declaration. */ - if (DECL_SIZE (decl) && TREE_TYPE (decl) != error_mark_node - && cleanup) + if (DECL_SIZE (decl) && cleanup) finish_decl_cleanup (decl, cleanup); } @@ -8064,8 +8167,10 @@ cp_finish_decl (decl, init, asmspec_tree, flags) } /* If a name was specified, get the string. */ + if (current_binding_level == global_binding_level) + asmspec_tree = maybe_apply_renaming_pragma (decl, asmspec_tree); if (asmspec_tree) - asmspec = TREE_STRING_POINTER (asmspec_tree); + asmspec = TREE_STRING_POINTER (asmspec_tree); if (init && TREE_CODE (init) == NAMESPACE_DECL) { @@ -8130,7 +8235,6 @@ cp_finish_decl (decl, init, asmspec_tree, flags) set_identifier_type_value (DECL_NAME (decl), type); CLASSTYPE_GOT_SEMICOLON (type) = 1; } - GNU_xref_decl (current_function_decl, decl); /* If we have installed this as the canonical typedef for this type, and that type has not been defined yet, delay emitting @@ -8171,8 +8275,6 @@ cp_finish_decl (decl, init, asmspec_tree, flags) init = check_initializer (decl, init); maybe_deduce_size_from_array_init (decl, init); - GNU_xref_decl (current_function_decl, decl); - /* Add this declaration to the statement-tree. This needs to happen after the call to check_initializer so that the DECL_STMT for a reference temp is added before the DECL_STMT for the reference itself. */ @@ -8506,7 +8608,9 @@ register_dtor_fn (decl) cleanup = build_unary_op (ADDR_EXPR, cleanup, 0); if (flag_use_cxa_atexit) { - args = tree_cons (NULL_TREE, get_dso_handle_node (), NULL_TREE); + args = tree_cons (NULL_TREE, + build_unary_op (ADDR_EXPR, get_dso_handle_node (), 0), + NULL_TREE); args = tree_cons (NULL_TREE, null_pointer_node, args); args = tree_cons (NULL_TREE, cleanup, args); } @@ -9617,15 +9721,13 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist) tree spec; tree type = NULL_TREE; int longlong = 0; - int constp; - int restrictp; - int volatilep; int type_quals; int virtualp, explicitp, friendp, inlinep, staticp; int explicit_int = 0; int explicit_char = 0; int defaulted_int = 0; int extern_langp = 0; + tree dependant_name = NULL_TREE; tree typedef_decl = NULL_TREE; const char *name; @@ -9867,11 +9969,10 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist) else if (TREE_CODE (cname) == TEMPLATE_TYPE_PARM || TREE_CODE (cname) == BOUND_TEMPLATE_TEMPLATE_PARM) { - error ("`%T::%D' is not a valid declarator", cname, - TREE_OPERAND (decl, 1)); - error (" perhaps you want `typename %T::%D' to make it a type", - cname, TREE_OPERAND (decl, 1)); - return void_type_node; + /* This might be declaring a member of a template + parm to be a friend. */ + ctype = cname; + dependant_name = TREE_OPERAND (decl, 1); } else if (ctype == NULL_TREE) ctype = cname; @@ -10083,7 +10184,6 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist) } } } - /* C++ aggregate types. */ else if (TREE_CODE (id) == TYPE_DECL) { if (type) @@ -10093,6 +10193,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist) { type = TREE_TYPE (id); TREE_VALUE (spec) = type; + typedef_decl = id; } goto found; } @@ -10107,10 +10208,6 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist) else { type = TREE_TYPE (t); -#if 0 - /* See the code below that used this. */ - decl_attr = DECL_ATTRIBUTES (id); -#endif typedef_decl = t; } } @@ -10121,6 +10218,11 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist) found: ; } +#if 0 + /* See the code below that used this. */ + if (typedef_decl) + decl_attr = DECL_ATTRIBUTES (typedef_decl); +#endif typedef_type = type; /* No type at all: default to `int', and set DEFAULTED_INT @@ -10167,7 +10269,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist) type = integer_type_node; } - if (type && TREE_CODE (type) == TYPENAME_TYPE && TREE_TYPE (type)) + if (type && IMPLICIT_TYPENAME_P (type)) { /* The implicit typename extension is deprecated and will be removed. Warn about its use now. */ @@ -10324,26 +10426,24 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist) type = build_complex_type (type); } - if (sfk == sfk_conversion - && (RIDBIT_SETP (RID_CONST, specbits) - || RIDBIT_SETP (RID_VOLATILE, specbits) - || RIDBIT_SETP (RID_RESTRICT, specbits))) + type_quals = TYPE_UNQUALIFIED; + if (RIDBIT_SETP (RID_CONST, specbits)) + type_quals |= TYPE_QUAL_CONST; + if (RIDBIT_SETP (RID_VOLATILE, specbits)) + type_quals |= TYPE_QUAL_VOLATILE; + if (RIDBIT_SETP (RID_RESTRICT, specbits)) + type_quals |= TYPE_QUAL_RESTRICT; + if (sfk == sfk_conversion && type_quals != TYPE_UNQUALIFIED) error ("qualifiers are not allowed on declaration of `operator %T'", ctor_return_type); - /* Set CONSTP if this declaration is `const', whether by - explicit specification or via a typedef. - Likewise for VOLATILEP. */ - - constp = !! RIDBIT_SETP (RID_CONST, specbits) + CP_TYPE_CONST_P (type); - restrictp = - !! RIDBIT_SETP (RID_RESTRICT, specbits) + CP_TYPE_RESTRICT_P (type); - volatilep = - !! RIDBIT_SETP (RID_VOLATILE, specbits) + CP_TYPE_VOLATILE_P (type); - type_quals = ((constp ? TYPE_QUAL_CONST : 0) - | (restrictp ? TYPE_QUAL_RESTRICT : 0) - | (volatilep ? TYPE_QUAL_VOLATILE : 0)); - type = cp_build_qualified_type (type, type_quals); + type_quals |= cp_type_quals (type); + type = cp_build_qualified_type_real + (type, type_quals, ((typedef_decl && !DECL_ARTIFICIAL (typedef_decl) + ? tf_ignore_bad_quals : 0) | tf_error | tf_warning)); + /* We might have ignored or rejected some of the qualifiers. */ + type_quals = cp_type_quals (type); + staticp = 0; inlinep = !! RIDBIT_SETP (RID_INLINE, specbits); virtualp = RIDBIT_SETP (RID_VIRTUAL, specbits); @@ -10363,6 +10463,12 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist) friendp = RIDBIT_SETP (RID_FRIEND, specbits); RIDBIT_RESET (RID_FRIEND, specbits); + if (dependant_name && !friendp) + { + error ("`%T::%D' is not a valid declarator", ctype, dependant_name); + return void_type_node; + } + /* Warn if two storage classes are given. Default to `auto'. */ if (RIDBIT_ANY_SET (specbits)) @@ -10830,21 +10936,30 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist) { register tree typemodlist; int erred = 0; - - constp = 0; - volatilep = 0; - restrictp = 0; + int constp = 0; + int volatilep = 0; + int restrictp = 0; + for (typemodlist = TREE_TYPE (declarator); typemodlist; typemodlist = TREE_CHAIN (typemodlist)) { tree qualifier = TREE_VALUE (typemodlist); if (qualifier == ridpointers[(int) RID_CONST]) - constp++; + { + constp++; + type_quals |= TYPE_QUAL_CONST; + } else if (qualifier == ridpointers[(int) RID_VOLATILE]) - volatilep++; + { + volatilep++; + type_quals |= TYPE_QUAL_VOLATILE; + } else if (qualifier == ridpointers[(int) RID_RESTRICT]) - restrictp++; + { + restrictp++; + type_quals |= TYPE_QUAL_RESTRICT; + } else if (!erred) { erred = 1; @@ -10857,20 +10972,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist) pedwarn ("duplicate `volatile'"); if (restrictp > 1) pedwarn ("duplicate `restrict'"); - - type_quals = ((constp ? TYPE_QUAL_CONST : 0) - | (restrictp ? TYPE_QUAL_RESTRICT : 0) - | (volatilep ? TYPE_QUAL_VOLATILE : 0)); - if (TREE_CODE (declarator) == ADDR_EXPR - && (constp || volatilep)) - { - if (constp) - pedwarn ("discarding `const' applied to a reference"); - if (volatilep) - pedwarn ("discarding `volatile' applied to a reference"); - type_quals &= ~(TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE); - } type = cp_build_qualified_type (type, type_quals); + type_quals = cp_type_quals (type); } declarator = TREE_OPERAND (declarator, 0); ctype = NULL_TREE; @@ -10914,7 +11017,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist) && uses_template_parms (current_class_type)) { tree args = current_template_args (); - type = tsubst (type, args, /*complain=*/1, NULL_TREE); + type = tsubst (type, args, tf_error | tf_warning, + NULL_TREE); } /* This pop_nested_class corresponds to the @@ -11113,7 +11217,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist) else if (type_quals & TYPE_QUAL_CONST) { error ("const `%s' cannot be declared `mutable'", name); - RIDBIT_RESET (RID_MUTABLE, specbits); + RIDBIT_RESET (RID_MUTABLE, specbits); } } @@ -11166,6 +11270,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist) && TYPE_NAME (type) && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL && TYPE_ANONYMOUS_P (type) + /* Don't do this if there are attributes. */ + && (!attrlist || !*attrlist) && cp_type_quals (type) == TYPE_UNQUALIFIED) { tree oldname = TYPE_NAME (type); @@ -11224,16 +11330,13 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist) /* Detect the case of an array type of unspecified size which came, as such, direct from a typedef name. - We must copy the type, so that each identifier gets - a distinct type, so that each identifier's size can be - controlled separately by its own initializer. */ + We must copy the type, so that the array's domain can be + individually set by the object's initializer. */ - if (type != 0 && typedef_type != 0 - && TREE_CODE (type) == ARRAY_TYPE && TYPE_DOMAIN (type) == 0 + if (type && typedef_type + && TREE_CODE (type) == ARRAY_TYPE && !TYPE_DOMAIN (type) && TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (typedef_type)) - { - type = build_cplus_array_type (TREE_TYPE (type), TYPE_DOMAIN (type)); - } + type = build_cplus_array_type (TREE_TYPE (type), NULL_TREE); /* Detect where we're using a typedef of function type to declare a function. last_function_parms will not be set, so we must create @@ -11300,9 +11403,7 @@ friend declaration requires class-key, i.e. `friend %#T'", /* Only try to do this stuff if we didn't already give up. */ if (type != integer_type_node) { - /* DR 209. The friendly class does not need to be accessible - in the scope of the class granting friendship. */ - skip_type_access_control (); + decl_type_access_control (TYPE_NAME (type)); /* A friendly class? */ if (current_class_type) @@ -11564,33 +11665,32 @@ friend declaration requires class-key, i.e. `friend %#T'", if (friendp) { /* Friends are treated specially. */ - tree t = NULL_TREE; - - /* DR 209. The friend does not need to be accessible at this - point. */ - skip_type_access_control (); - if (ctype == current_class_type) warning ("member functions are implicitly friends of their class"); - - if (decl && DECL_NAME (decl)) - { - if (template_class_depth (current_class_type) == 0) - { - decl = check_explicit_specialization - (declarator, decl, - template_count, 2 * (funcdef_flag != 0) + 4); - if (decl == error_mark_node) - return error_mark_node; - } - - t = do_friend (ctype, declarator, decl, - last_function_parms, *attrlist, flags, quals, - funcdef_flag); - } - if (t && funcdef_flag) - return t; - return void_type_node; + else + { + tree t = NULL_TREE; + if (decl && DECL_NAME (decl)) + { + if (template_class_depth (current_class_type) == 0) + { + decl + = check_explicit_specialization + (declarator, decl, + template_count, 2 * (funcdef_flag != 0) + 4); + if (decl == error_mark_node) + return error_mark_node; + } + + t = do_friend (ctype, declarator, decl, + last_function_parms, *attrlist, + flags, quals, funcdef_flag); + } + if (t && funcdef_flag) + return t; + + return void_type_node; + } } /* Structure field. It may not be a function, except for C++ */ @@ -12589,10 +12689,12 @@ grok_op_properties (decl, friendp) /* Effective C++ rule 23. */ if (warn_ecpp && arity == 2 + && !DECL_ASSIGNMENT_OPERATOR_P (decl) && (operator_code == PLUS_EXPR || operator_code == MINUS_EXPR || operator_code == TRUNC_DIV_EXPR - || operator_code == MULT_EXPR) + || operator_code == MULT_EXPR + || operator_code == TRUNC_MOD_EXPR) && TREE_CODE (TREE_TYPE (TREE_TYPE (decl))) == REFERENCE_TYPE) warning ("`%D' should return by value", decl); @@ -12654,7 +12756,6 @@ xref_tag (code_type_node, name, globalize) enum tree_code code; register tree ref, t; struct binding_level *b = current_binding_level; - int got_type = 0; tree attributes = NULL_TREE; tree context = NULL_TREE; @@ -12691,7 +12792,6 @@ xref_tag (code_type_node, name, globalize) { t = name; name = TYPE_IDENTIFIER (t); - got_type = 1; } else t = IDENTIFIER_TYPE_VALUE (name); @@ -12736,18 +12836,20 @@ xref_tag (code_type_node, name, globalize) { if (t) { + ref = follow_tag_typedef (t); + /* [dcl.type.elab] If the identifier resolves to a typedef-name or a template type-parameter, the elaborated-type-specifier is ill-formed. */ - if (t != TYPE_MAIN_VARIANT (t) - || (CLASS_TYPE_P (t) && TYPE_WAS_ANONYMOUS (t))) - pedwarn ("using typedef-name `%D' after `%s'", - TYPE_NAME (t), tag_name (tag_code)); + if (!ref) + { + pedwarn ("using typedef-name `%D' after `%s'", + TYPE_NAME (t), tag_name (tag_code)); + ref = t; + } else if (TREE_CODE (t) == TEMPLATE_TYPE_PARM) error ("using template type parameter `%T' after `%s'", - t, tag_name (tag_code)); - - ref = t; + t, tag_name (tag_code)); } else ref = lookup_tag (code, name, b, 0); @@ -12868,19 +12970,6 @@ xref_tag (code_type_node, name, globalize) redeclare_class_template (ref, current_template_parms); } - /* Until the type is defined, tentatively accept whatever - structure tag the user hands us. */ - if (!COMPLETE_TYPE_P (ref) - && ref != current_class_type - /* Have to check this, in case we have contradictory tag info. */ - && IS_AGGR_TYPE_CODE (TREE_CODE (ref))) - { - if (tag_code == class_type) - CLASSTYPE_DECLARED_CLASS (ref) = 1; - else if (tag_code == record_type) - CLASSTYPE_DECLARED_CLASS (ref) = 0; - } - TYPE_ATTRIBUTES (ref) = attributes; return ref; @@ -12914,7 +13003,8 @@ xref_tag_from_type (old, id, globalize) void xref_basetypes (code_type_node, name, ref, binfo) tree code_type_node; - tree name, ref; + tree name ATTRIBUTE_UNUSED; + tree ref; tree binfo; { /* In the declaration `A : X, Y, ... Z' we mark all the types @@ -12985,8 +13075,6 @@ xref_basetypes (code_type_node, name, ref, binfo) continue; } - GNU_xref_hier (name, basetype, via_public, via_virtual, 0); - /* This code replaces similar code in layout_basetypes. We put the complete_type first for implicit `typename'. */ if (!COMPLETE_TYPE_P (basetype) @@ -13124,10 +13212,6 @@ start_enum (name) pushtag (name, enumtype, 0); } - if (current_class_type) - TREE_ADDRESSABLE (b->tags) = 1; - - GNU_xref_decl (current_function_decl, enumtype); return enumtype; } @@ -13373,10 +13457,7 @@ build_enumerator (name, value, enumtype) things like `S::i' later.) */ finish_member_declaration (decl); else - { - pushdecl (decl); - GNU_xref_decl (current_function_decl, decl); - } + pushdecl (decl); /* Add this enumeration constant to the list for this type. */ TYPE_VALUES (enumtype) = tree_cons (name, decl, TYPE_VALUES (enumtype)); @@ -13500,7 +13581,14 @@ start_function (declspecs, declarator, attrs, flags) decl1 = grokdeclarator (declarator, declspecs, FUNCDEF, 1, NULL); /* If the declarator is not suitable for a function definition, cause a syntax error. */ - if (decl1 == NULL_TREE || TREE_CODE (decl1) != FUNCTION_DECL) return 0; + if (decl1 == NULL_TREE || TREE_CODE (decl1) != FUNCTION_DECL) + return 0; + + cplus_decl_attributes (&decl1, attrs, 0); + + /* If #pragma weak was used, mark the decl weak now. */ + if (current_binding_level == global_binding_level) + maybe_apply_pragma_weak (decl1); fntype = TREE_TYPE (decl1); @@ -13614,19 +13702,16 @@ start_function (declspecs, declarator, attrs, flags) /* Build the return declaration for the function. */ restype = TREE_TYPE (fntype); - if (!processing_template_decl) + /* Promote the value to int before returning it. */ + if (c_promoting_integer_type_p (restype)) + restype = type_promotes_to (restype); + if (DECL_RESULT (decl1) == NULL_TREE) { - if (!DECL_RESULT (decl1)) - { - DECL_RESULT (decl1) - = build_decl (RESULT_DECL, 0, TYPE_MAIN_VARIANT (restype)); - c_apply_type_quals_to_decl (cp_type_quals (restype), - DECL_RESULT (decl1)); - } + DECL_RESULT (decl1) + = build_decl (RESULT_DECL, 0, TYPE_MAIN_VARIANT (restype)); + c_apply_type_quals_to_decl (cp_type_quals (restype), + DECL_RESULT (decl1)); } - else - /* Just use `void'. Nobody will ever look at this anyhow. */ - DECL_RESULT (decl1) = build_decl (RESULT_DECL, 0, void_type_node); /* Initialize RTL machinery. We cannot do this until CURRENT_FUNCTION_DECL and DECL_RESULT are set up. We do this @@ -13787,20 +13872,6 @@ start_function (declspecs, declarator, attrs, flags) pushlevel (0); current_binding_level->parm_flag = 1; - cplus_decl_attributes (&decl1, attrs, 0); - - /* Promote the value to int before returning it. */ - if (c_promoting_integer_type_p (restype)) - restype = type_promotes_to (restype); - - if (DECL_RESULT (decl1) == NULL_TREE) - { - DECL_RESULT (decl1) - = build_decl (RESULT_DECL, 0, TYPE_MAIN_VARIANT (restype)); - TREE_READONLY (DECL_RESULT (decl1)) = CP_TYPE_CONST_P (restype); - TREE_THIS_VOLATILE (DECL_RESULT (decl1)) = CP_TYPE_VOLATILE_P (restype); - } - ++function_depth; if (DECL_DESTRUCTOR_P (decl1)) @@ -14006,10 +14077,6 @@ begin_destructor_body () finish_compound_stmt (/*has_no_scope=*/0, compound_stmt); finish_then_clause (if_stmt); finish_if_stmt (); - - /* And insert cleanups for our bases and members so that they - will be properly destroyed if we throw. */ - push_base_cleanups (); } /* At the end of every destructor we generate code to delete the object if @@ -14020,6 +14087,9 @@ finish_destructor_body () { tree exprstmt; + /* And perform cleanups for our bases and members. */ + perform_base_cleanups (); + /* In a virtual destructor, we must call delete. */ if (DECL_VIRTUAL_P (current_function_decl)) { @@ -14247,6 +14317,19 @@ finish_function (flags) if (!processing_template_decl && calls_setjmp_p (fndecl)) DECL_UNINLINABLE (fndecl) = 1; + /* Complain if there's just no return statement. */ + if (warn_return_type + && !processing_template_decl + && TREE_CODE (TREE_TYPE (fntype)) != VOID_TYPE + && !current_function_returns_value && !current_function_returns_null + /* Don't complain if we abort or throw. */ + && !current_function_returns_abnormally + && !DECL_NAME (DECL_RESULT (fndecl)) + /* Normally, with -Wreturn-type, flow will complain. Unless we're an + inline function, as we might never be compiled separately. */ + && DECL_INLINE (fndecl)) + warning ("no return statement in function returning non-void"); + /* Clear out memory we no longer need. */ free_after_parsing (cfun); /* Since we never call rest_of_compilation, we never clear @@ -14407,11 +14490,6 @@ finish_method (decl) DECL_CONTEXT (link) = NULL_TREE; } - GNU_xref_end_scope ((size_t) current_binding_level, - (size_t) current_binding_level->level_chain, - current_binding_level->parm_flag, - current_binding_level->keep); - poplevel (0, 0, 0); DECL_INITIAL (fndecl) = old_initial; @@ -14429,72 +14507,58 @@ finish_method (decl) return decl; } -/* Called when a new struct TYPE is defined. - If this structure or union completes the type of any previous - variable declaration, lay it out and output its rtl. */ + +/* VAR is a VAR_DECL. If its type is incomplete, remember VAR so that + we can lay it out later, when and if its type becomes complete. */ void -hack_incomplete_structures (type) - tree type; +maybe_register_incomplete_var (var) + tree var; { - tree *list; - struct binding_level *level; + my_friendly_assert (TREE_CODE (var) == VAR_DECL, 20020406); - if (!type) /* Don't do this for class templates. */ - return; - - if (namespace_bindings_p ()) + /* Keep track of variables with incomplete types. */ + if (!processing_template_decl && TREE_TYPE (var) != error_mark_node + && DECL_EXTERNAL (var)) { - level = 0; - list = &namespace_scope_incomplete; - } - else - { - level = innermost_nonclass_level (); - list = &level->incomplete; + tree inner_type = TREE_TYPE (var); + + while (TREE_CODE (inner_type) == ARRAY_TYPE) + inner_type = TREE_TYPE (inner_type); + inner_type = TYPE_MAIN_VARIANT (inner_type); + + if ((!COMPLETE_TYPE_P (inner_type) && CLASS_TYPE_P (inner_type)) + /* RTTI TD entries are created while defining the type_info. */ + || (TYPE_LANG_SPECIFIC (inner_type) + && TYPE_BEING_DEFINED (inner_type))) + incomplete_vars = tree_cons (inner_type, var, incomplete_vars); } +} - while (1) - { - while (*list) - { - tree decl = TREE_VALUE (*list); - if ((decl && TREE_TYPE (decl) == type) - || (TREE_TYPE (decl) - && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE - && TREE_TYPE (TREE_TYPE (decl)) == type)) - { - int toplevel = toplevel_bindings_p (); - if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE - && TREE_TYPE (TREE_TYPE (decl)) == type) - layout_type (TREE_TYPE (decl)); - layout_decl (decl, 0); - rest_of_decl_compilation (decl, NULL, toplevel, 0); - if (! toplevel) - { - tree cleanup; - expand_decl (decl); - cleanup = maybe_build_cleanup (decl); - expand_decl_init (decl); - if (! expand_decl_cleanup (decl, cleanup)) - error ("parser lost in parsing declaration of `%D'", - decl); - } - *list = TREE_CHAIN (*list); - } - else - list = &TREE_CHAIN (*list); - } +/* Called when a class type (given by TYPE) is defined. If there are + any existing VAR_DECLs whose type hsa been completed by this + declaration, update them now. */ + +void +complete_vars (type) + tree type; +{ + tree *list = &incomplete_vars; - /* Keep looking through artificial binding levels generated - for local variables. */ - if (level && level->keep == 2) + my_friendly_assert (CLASS_TYPE_P (type), 20020406); + while (*list) + { + if (same_type_p (type, TREE_PURPOSE (*list))) { - level = level->level_chain; - list = &level->incomplete; + tree var = TREE_VALUE (*list); + /* Complete the type of the variable. The VAR_DECL itself + will be laid out in expand_expr. */ + complete_type (TREE_TYPE (var)); + /* Remove this entry from the list. */ + *list = TREE_CHAIN (*list); } else - break; + list = &TREE_CHAIN (*list); } } @@ -14535,7 +14599,7 @@ maybe_build_cleanup (decl) return rval; } - return 0; + return NULL_TREE; } /* When a stmt has been parsed, this function is called. */ |