diff options
Diffstat (limited to 'gcc/cp/decl2.c')
-rw-r--r-- | gcc/cp/decl2.c | 588 |
1 files changed, 361 insertions, 227 deletions
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index 248fa2d6725..38290be0070 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -1,6 +1,6 @@ /* Process declarations and variables for C compiler. Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, - 1999, 2000, 2001, 2002 Free Software Foundation, Inc. + 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. Hacked by Michael Tiemann (tiemann@cygnus.com) This file is part of GNU CC. @@ -45,6 +45,7 @@ Boston, MA 02111-1307, USA. */ #include "cpplib.h" #include "target.h" #include "c-common.h" +#include "timevar.h" extern cpp_reader *parse_in; /* This structure contains information about the initializations @@ -61,9 +62,8 @@ typedef struct priority_info_s { static void mark_vtable_entries PARAMS ((tree)); static void grok_function_init PARAMS ((tree, tree)); static int maybe_emit_vtables (tree); -static int is_namespace_ancestor PARAMS ((tree, tree)); static void add_using_namespace PARAMS ((tree, tree, int)); -static tree ambiguous_decl PARAMS ((tree, tree, tree,int)); +static cxx_binding *ambiguous_decl (tree, cxx_binding *, cxx_binding *,int); static tree build_anon_union_vars PARAMS ((tree, tree*, int, int)); static int acceptable_java_type PARAMS ((tree)); static void output_vtable_inherit PARAMS ((tree)); @@ -84,10 +84,9 @@ static void finish_static_initialization_or_destruction PARAMS ((tree)); static void generate_ctor_or_dtor_function PARAMS ((int, int)); static int generate_ctor_and_dtor_functions_for_priority PARAMS ((splay_tree_node, void *)); -static tree prune_vars_needing_no_initialization PARAMS ((tree)); +static tree prune_vars_needing_no_initialization PARAMS ((tree *)); static void write_out_vars PARAMS ((tree)); static void import_export_class PARAMS ((tree)); -static tree key_method PARAMS ((tree)); static tree get_guard_bits PARAMS ((tree)); /* A list of static class variables. This is needed, because a @@ -674,11 +673,8 @@ tree check_classfn (ctype, function) tree ctype, function; { - tree fn_name = DECL_NAME (function); - tree fndecl, fndecls; - tree method_vec = CLASSTYPE_METHOD_VEC (complete_type (ctype)); - tree *methods = 0; - tree *end = 0; + int ix; + int is_template; if (DECL_USE_TEMPLATE (function) && !(TREE_CODE (function) == TEMPLATE_DECL @@ -695,81 +691,99 @@ check_classfn (ctype, function) reason we should, either. We let our callers know we didn't find the method, but we don't complain. */ return NULL_TREE; - - if (method_vec != 0) + + /* OK, is this a definition of a member template? */ + is_template = (TREE_CODE (function) == TEMPLATE_DECL + || (processing_template_decl - template_class_depth (ctype))); + + ix = lookup_fnfields_1 (complete_type (ctype), + DECL_CONSTRUCTOR_P (function) ? ctor_identifier : + DECL_DESTRUCTOR_P (function) ? dtor_identifier : + DECL_NAME (function)); + + if (ix >= 0) { - methods = &TREE_VEC_ELT (method_vec, 0); - end = TREE_VEC_END (method_vec); - - /* First suss out ctors and dtors. */ - if (*methods && fn_name == DECL_NAME (OVL_CURRENT (*methods)) - && DECL_CONSTRUCTOR_P (function)) - goto got_it; - if (*++methods && fn_name == DECL_NAME (OVL_CURRENT (*methods)) - && DECL_DESTRUCTOR_P (function)) - goto got_it; - - while (++methods != end && *methods) + tree methods = CLASSTYPE_METHOD_VEC (ctype); + tree fndecls, fndecl = 0; + bool is_conv_op; + const char *format = NULL; + + for (fndecls = TREE_VEC_ELT (methods, ix); + fndecls; fndecls = OVL_NEXT (fndecls)) { - fndecl = *methods; - if (fn_name == DECL_NAME (OVL_CURRENT (*methods))) + tree p1, p2; + + fndecl = OVL_CURRENT (fndecls); + p1 = TYPE_ARG_TYPES (TREE_TYPE (function)); + p2 = TYPE_ARG_TYPES (TREE_TYPE (fndecl)); + + /* We cannot simply call decls_match because this doesn't + work for static member functions that are pretending to + be methods, and because the name may have been changed by + asm("new_name"). */ + + /* Get rid of the this parameter on functions that become + static. */ + if (DECL_STATIC_FUNCTION_P (fndecl) + && TREE_CODE (TREE_TYPE (function)) == METHOD_TYPE) + p1 = TREE_CHAIN (p1); + + /* A member template definition only matches a member template + declaration. */ + if (is_template != (TREE_CODE (fndecl) == TEMPLATE_DECL)) + continue; + + if (same_type_p (TREE_TYPE (TREE_TYPE (function)), + TREE_TYPE (TREE_TYPE (fndecl))) + && compparms (p1, p2) + && (DECL_TEMPLATE_SPECIALIZATION (function) + == DECL_TEMPLATE_SPECIALIZATION (fndecl)) + && (!DECL_TEMPLATE_SPECIALIZATION (function) + || (DECL_TI_TEMPLATE (function) + == DECL_TI_TEMPLATE (fndecl)))) + return fndecl; + } + error ("prototype for `%#D' does not match any in class `%T'", + function, ctype); + is_conv_op = DECL_CONV_FN_P (fndecl); + + if (is_conv_op) + ix = CLASSTYPE_FIRST_CONVERSION_SLOT; + fndecls = TREE_VEC_ELT (methods, ix); + while (fndecls) + { + fndecl = OVL_CURRENT (fndecls); + fndecls = OVL_NEXT (fndecls); + + if (!fndecls && is_conv_op) { - got_it: - for (fndecls = *methods; fndecls != NULL_TREE; - fndecls = OVL_NEXT (fndecls)) + if (TREE_VEC_LENGTH (methods) > ix) { - fndecl = OVL_CURRENT (fndecls); - - /* We cannot simply call decls_match because this - doesn't work for static member functions that are - pretending to be methods, and because the name - may have been changed by asm("new_name"). */ - if (DECL_NAME (function) == DECL_NAME (fndecl)) + ix++; + fndecls = TREE_VEC_ELT (methods, ix); + if (!DECL_CONV_FN_P (OVL_CURRENT (fndecls))) { - tree p1 = TYPE_ARG_TYPES (TREE_TYPE (function)); - tree p2 = TYPE_ARG_TYPES (TREE_TYPE (fndecl)); - - /* Get rid of the this parameter on functions that become - static. */ - if (DECL_STATIC_FUNCTION_P (fndecl) - && TREE_CODE (TREE_TYPE (function)) == METHOD_TYPE) - p1 = TREE_CHAIN (p1); - - if (same_type_p (TREE_TYPE (TREE_TYPE (function)), - TREE_TYPE (TREE_TYPE (fndecl))) - && compparms (p1, p2) - && (DECL_TEMPLATE_SPECIALIZATION (function) - == DECL_TEMPLATE_SPECIALIZATION (fndecl)) - && (!DECL_TEMPLATE_SPECIALIZATION (function) - || (DECL_TI_TEMPLATE (function) - == DECL_TI_TEMPLATE (fndecl)))) - return fndecl; + fndecls = NULL_TREE; + is_conv_op = false; } } - break; /* loser */ + else + is_conv_op = false; } + if (format) + format = " %#D"; + else if (fndecls) + format = "candidates are: %#D"; + else + format = "candidate is: %#D"; + cp_error_at (format, fndecl); } } - - if (methods != end && *methods) - { - tree fndecl = *methods; - error ("prototype for `%#D' does not match any in class `%T'", - function, ctype); - cp_error_at ("candidate%s: %+#D", OVL_NEXT (fndecl) ? "s are" : " is", - OVL_CURRENT (fndecl)); - while (fndecl = OVL_NEXT (fndecl), fndecl) - cp_error_at (" %#D", OVL_CURRENT(fndecl)); - } + else if (!COMPLETE_TYPE_P (ctype)) + cxx_incomplete_type_error (function, ctype); else - { - methods = 0; - if (!COMPLETE_TYPE_P (ctype)) - cxx_incomplete_type_error (function, ctype); - else - error ("no `%#D' member function declared in class `%T'", - function, ctype); - } + error ("no `%#D' member function declared in class `%T'", + function, ctype); /* If we did not find the method in the class, add it to avoid spurious errors (unless the CTYPE is not yet defined, in which @@ -1118,11 +1132,29 @@ grokbitfield (declarator, declspecs, width) return value; } +/* Convert a conversion operator name to an identifier. SCOPE is the + scope of the conversion operator, if explicit. */ + tree -grokoptypename (declspecs, declarator) +grokoptypename (declspecs, declarator, scope) tree declspecs, declarator; + tree scope; { tree t = grokdeclarator (declarator, declspecs, TYPENAME, 0, NULL); + + /* Resolve any TYPENAME_TYPEs that refer to SCOPE, before mangling + the name, so that we mangle the right thing. */ + if (scope && current_template_parms + && uses_template_parms (t) + && uses_template_parms (scope)) + { + tree args = current_template_args (); + + push_scope (scope); + t = tsubst (t, args, tf_error | tf_warning, NULL_TREE); + pop_scope (scope); + } + return mangle_conv_op_name_for_type (t); } @@ -1642,29 +1674,6 @@ maybe_make_one_only (decl) } } -/* Returns the virtual function with which the vtable for TYPE is - emitted, or NULL_TREE if that heuristic is not applicable to TYPE. */ - -static tree -key_method (type) - tree type; -{ - tree method; - - if (TYPE_FOR_JAVA (type) - || CLASSTYPE_TEMPLATE_INSTANTIATION (type) - || CLASSTYPE_INTERFACE_KNOWN (type)) - return NULL_TREE; - - for (method = TYPE_METHODS (type); method != NULL_TREE; - method = TREE_CHAIN (method)) - if (DECL_VINDEX (method) != NULL_TREE - && ! DECL_DECLARED_INLINE_P (method) - && ! DECL_PURE_VIRTUAL_P (method)) - return method; - - return NULL_TREE; -} /* Set TREE_PUBLIC and/or DECL_EXTERN on the vtable DECL, based on TYPE and other static flags. @@ -1698,7 +1707,7 @@ import_export_vtable (decl, type, final) functions in our class, or if we come from a template. */ int found = (CLASSTYPE_TEMPLATE_INSTANTIATION (type) - || key_method (type)); + || CLASSTYPE_KEY_METHOD (type) != NULL_TREE); if (final || ! found) { @@ -1758,7 +1767,7 @@ import_export_class (ctype) if (import_export == 0 && TYPE_POLYMORPHIC_P (ctype)) { - tree method = key_method (ctype); + tree method = CLASSTYPE_KEY_METHOD (ctype); if (method) import_export = (DECL_REALLY_EXTERN (method) ? -1 : 1); } @@ -2004,6 +2013,10 @@ import_export_tinfo (decl, type, is_in_library) DECL_INTERFACE_KNOWN (decl) = 1; } +/* Return an expression that performs the destruction of DECL, which + must be a VAR_DECL whose type has a non-trivial destructor, or is + an array whose (innermost) elements have a non-trivial destructor. */ + tree build_cleanup (decl) tree decl; @@ -2011,6 +2024,14 @@ build_cleanup (decl) tree temp; tree type = TREE_TYPE (decl); + /* This function should only be called for declarations that really + require cleanups. */ + my_friendly_assert (!TYPE_HAS_TRIVIAL_DESTRUCTOR (type), 20030106); + + /* Treat all objects with destructors as used; the destructor may do + something substantive. */ + mark_used (decl); + if (TREE_CODE (type) == ARRAY_TYPE) temp = decl; else @@ -2590,21 +2611,23 @@ do_static_destruction (decl) static tree prune_vars_needing_no_initialization (vars) - tree vars; + tree *vars; { - tree var; - tree result; + tree *var = vars; + tree result = NULL_TREE; - for (var = vars, result = NULL_TREE; - var; - var = TREE_CHAIN (var)) + while (*var) { - tree decl = TREE_VALUE (var); - tree init = TREE_PURPOSE (var); + tree t = *var; + tree decl = TREE_VALUE (t); + tree init = TREE_PURPOSE (t); /* Deal gracefully with error. */ if (decl == error_mark_node) - continue; + { + var = &TREE_CHAIN (t); + continue; + } /* The only things that can be initialized are variables. */ my_friendly_assert (TREE_CODE (decl) == VAR_DECL, 19990420); @@ -2612,17 +2635,25 @@ prune_vars_needing_no_initialization (vars) /* If this object is not defined, we don't need to do anything here. */ if (DECL_EXTERNAL (decl)) - continue; + { + var = &TREE_CHAIN (t); + continue; + } /* Also, if the initializer already contains errors, we can bail out now. */ if (init && TREE_CODE (init) == TREE_LIST && value_member (error_mark_node, init)) - continue; + { + var = &TREE_CHAIN (t); + continue; + } /* This variable is going to need initialization and/or finalization, so we add it to the list. */ - result = tree_cons (init, decl, result); + *var = TREE_CHAIN (t); + TREE_CHAIN (t) = result; + result = t; } return result; @@ -2777,11 +2808,36 @@ finish_file () instantiate_pending_templates (); /* Write out virtual tables as required. Note that writing out - the virtual table for a template class may cause the - instantiation of members of that class. */ - for (t = dynamic_classes; t; t = TREE_CHAIN (t)) - if (maybe_emit_vtables (TREE_VALUE (t))) - reconsider = 1; + the virtual table for a template class may cause the + instantiation of members of that class. If we write out + vtables then we remove the class from our list so we don't + have to look at it again. */ + + while (keyed_classes != NULL_TREE + && maybe_emit_vtables (TREE_VALUE (keyed_classes))) + { + reconsider = 1; + keyed_classes = TREE_CHAIN (keyed_classes); + } + + t = keyed_classes; + if (t != NULL_TREE) + { + tree next = TREE_CHAIN (t); + + while (next) + { + if (maybe_emit_vtables (TREE_VALUE (next))) + { + reconsider = 1; + TREE_CHAIN (t) = TREE_CHAIN (next); + } + else + t = next; + + next = TREE_CHAIN (t); + } + } /* Write out needed type info variables. Writing out one variable might cause others to be needed. */ @@ -2793,8 +2849,7 @@ finish_file () aggregates added during the initialization of these will be initialized in the correct order when we next come around the loop. */ - vars = prune_vars_needing_no_initialization (static_aggregates); - static_aggregates = NULL_TREE; + vars = prune_vars_needing_no_initialization (&static_aggregates); if (vars) { @@ -2842,12 +2897,13 @@ finish_file () reconsider = 1; } - /* Go through the various inline functions, and see if any need - synthesizing. */ for (i = 0; i < deferred_fns_used; ++i) { tree decl = VARRAY_TREE (deferred_fns, i); + import_export_decl (decl); + + /* Does it need synthesizing? */ if (DECL_ARTIFICIAL (decl) && ! DECL_INITIAL (decl) && TREE_USED (decl) && (! DECL_REALLY_EXTERN (decl) || DECL_INLINE (decl))) @@ -2862,30 +2918,21 @@ finish_file () pop_from_top_level (); reconsider = 1; } - } - /* We lie to the back-end, pretending that some functions are - not defined when they really are. This keeps these functions - from being put out unnecessarily. But, we must stop lying - when the functions are referenced, or if they are not comdat - since they need to be put out now. - This is done in a separate for cycle, because if some deferred - function is contained in another deferred function later in - deferred_fns varray, rest_of_compilation would skip this - function and we really cannot expand the same function twice. */ - for (i = 0; i < deferred_fns_used; ++i) - { - tree decl = VARRAY_TREE (deferred_fns, i); - + /* We lie to the back-end, pretending that some functions + are not defined when they really are. This keeps these + functions from being put out unnecessarily. But, we must + stop lying when the functions are referenced, or if they + are not comdat since they need to be put out now. This + is done in a separate for cycle, because if some deferred + function is contained in another deferred function later + in deferred_fns varray, rest_of_compilation would skip + this function and we really cannot expand the same + function twice. */ if (DECL_NOT_REALLY_EXTERN (decl) && DECL_INITIAL (decl) && DECL_NEEDED_P (decl)) DECL_EXTERNAL (decl) = 0; - } - - for (i = 0; i < deferred_fns_used; ++i) - { - tree decl = VARRAY_TREE (deferred_fns, i); /* If we're going to need to write this function out, and there's already a body for it, create RTL for it now. @@ -2941,6 +2988,20 @@ finish_file () } while (reconsider); + /* All used inline functions must have a definition at this point. */ + for (i = 0; i < deferred_fns_used; ++i) + { + tree decl = VARRAY_TREE (deferred_fns, i); + + if (TREE_USED (decl) && DECL_DECLARED_INLINE_P (decl) + && !(TREE_ASM_WRITTEN (decl) || DECL_SAVED_TREE (decl) + /* An explicit instantiation can be used to specify + that the body is in another unit. It will have + already verified there was a definition. */ + || DECL_EXPLICIT_INSTANTIATION (decl))) + cp_warning_at ("inline function `%D' used but never defined", decl); + } + /* We give C linkage to static constructors and destructors. */ push_lang_context (lang_name_c); @@ -3292,16 +3353,18 @@ build_expr_from_tree (t) { tree ref = TREE_OPERAND (t, 0); tree name = TREE_OPERAND (ref, 1); + tree fn, scope, args; if (TREE_CODE (name) == TEMPLATE_ID_EXPR) name = build_nt (TEMPLATE_ID_EXPR, TREE_OPERAND (name, 0), build_expr_from_tree (TREE_OPERAND (name, 1))); - - return build_member_call - (build_expr_from_tree (TREE_OPERAND (ref, 0)), - name, - build_expr_from_tree (TREE_OPERAND (t, 1))); + + scope = build_expr_from_tree (TREE_OPERAND (ref, 0)); + args = build_expr_from_tree (TREE_OPERAND (t, 1)); + fn = resolve_scoped_fn_name (scope, name); + + return build_call_from_tree (fn, args, 1); } else { @@ -3453,15 +3516,15 @@ build_offset_ref_call_from_tree (tree fn, tree args) /* This code is not really correct (for example, it does not handle the case that `A::f' is overloaded), but it is historically how we have handled this situation. */ - object_addr = build_unary_op (ADDR_EXPR, TREE_OPERAND (fn, 0), 0); if (TREE_CODE (TREE_OPERAND (fn, 1)) == FIELD_DECL) fn = resolve_offset_ref (fn); else { + object_addr = build_unary_op (ADDR_EXPR, TREE_OPERAND (fn, 0), 0); fn = TREE_OPERAND (fn, 1); fn = get_member_function_from_ptrfunc (&object_addr, fn); + args = tree_cons (NULL_TREE, object_addr, args); } - args = tree_cons (NULL_TREE, object_addr, args); return build_function_call (fn, args); } @@ -3585,21 +3648,38 @@ finish_decl_parsing (decl) } } -/* Return 1 if root encloses child. */ +/* Returns true if ROOT (a namespace, class, or function) encloses + CHILD. CHILD may be either a class type or a namespace. */ -static int -is_namespace_ancestor (root, child) - tree root, child; +bool +is_ancestor (tree root, tree child) { - if (root == child) - return 1; + my_friendly_assert ((TREE_CODE (root) == NAMESPACE_DECL + || TREE_CODE (root) == FUNCTION_DECL + || CLASS_TYPE_P (root)), 20030307); + my_friendly_assert ((TREE_CODE (child) == NAMESPACE_DECL + || TREE_CODE (root) == FUNCTION_DECL + || CLASS_TYPE_P (child)), + 20030307); + + /* The global namespace encloses everything. */ if (root == global_namespace) - return 1; - if (child == global_namespace) - return 0; - return is_namespace_ancestor (root, CP_DECL_CONTEXT (child)); + return true; + + while (true) + { + /* If we've run out of scopes, stop. */ + if (!child) + return false; + /* If we've reached the ROOT, it encloses CHILD. */ + if (root == child) + return true; + /* Go out one level. */ + if (TYPE_P (child)) + child = TYPE_NAME (child); + child = DECL_CONTEXT (child); + } } - /* Return the namespace that is the common ancestor of two given namespaces. */ @@ -3608,9 +3688,11 @@ tree namespace_ancestor (ns1, ns2) tree ns1, ns2; { - if (is_namespace_ancestor (ns1, ns2)) - return ns1; - return namespace_ancestor (CP_DECL_CONTEXT (ns1), ns2); + timevar_push (TV_NAME_LOOKUP); + if (is_ancestor (ns1, ns2)) + POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, ns1); + POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, + namespace_ancestor (CP_DECL_CONTEXT (ns1), ns2)); } /* Insert used into the using list of user. Set indirect_flag if this @@ -3623,9 +3705,10 @@ add_using_namespace (user, used, indirect) int indirect; { tree t; + timevar_push (TV_NAME_LOOKUP); /* Using oneself is a no-op. */ if (user == used) - return; + POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, (void)0); my_friendly_assert (TREE_CODE (user) == NAMESPACE_DECL, 380); my_friendly_assert (TREE_CODE (used) == NAMESPACE_DECL, 380); /* Check if we already have this. */ @@ -3635,7 +3718,7 @@ add_using_namespace (user, used, indirect) if (!indirect) /* Promote to direct usage. */ TREE_INDIRECT_USING (t) = 0; - return; + POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, (void)0); } /* Add used to the user's using list. */ @@ -3657,6 +3740,7 @@ add_using_namespace (user, used, indirect) /* Tell everyone using us about the new used namespaces. */ for (t = DECL_NAMESPACE_USERS (user); t; t = TREE_CHAIN (t)) add_using_namespace (TREE_PURPOSE (t), used, 1); + timevar_pop (TV_NAME_LOOKUP); } /* Combines two sets of overloaded functions into an OVERLOAD chain, removing @@ -3705,15 +3789,11 @@ merge_functions (s1, s2) XXX In what way should I treat extern declarations? XXX I don't want to repeat the entire duplicate_decls here */ -static tree -ambiguous_decl (name, old, new, flags) - tree name; - tree old; - tree new; - int flags; +static cxx_binding * +ambiguous_decl (tree name, cxx_binding *old, cxx_binding *new, int flags) { tree val, type; - my_friendly_assert (old != NULL_TREE, 393); + my_friendly_assert (old != NULL, 393); /* Copy the value. */ val = BINDING_VALUE (new); if (val) @@ -3798,14 +3878,13 @@ ambiguous_decl (name, old, new, flags) which have SCOPE as a common ancestor with the current scope. Returns zero on errors. */ -int -lookup_using_namespace (name, val, usings, scope, flags, spacesp) - tree name, val, usings, scope; - int flags; - tree *spacesp; +bool +lookup_using_namespace (tree name, cxx_binding *val, tree usings, + tree scope, int flags, tree *spacesp) { tree iter; - tree val1; + cxx_binding *val1; + timevar_push (TV_NAME_LOOKUP); /* Iterate over all used namespaces in current, searching for using directives of scope. */ for (iter = usings; iter; iter = TREE_CHAIN (iter)) @@ -3814,37 +3893,42 @@ lookup_using_namespace (name, val, usings, scope, flags, spacesp) if (spacesp) *spacesp = tree_cons (TREE_PURPOSE (iter), NULL_TREE, *spacesp); - val1 = binding_for_name (name, TREE_PURPOSE (iter)); - /* Resolve ambiguities. */ - val = ambiguous_decl (name, val, val1, flags); + val1 = cxx_scope_find_binding_for_name (TREE_PURPOSE (iter), name); + /* Resolve possible ambiguities. */ + if (val1) + val = ambiguous_decl (name, val, val1, flags); } - return BINDING_VALUE (val) != error_mark_node; + POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, + BINDING_VALUE (val) != error_mark_node); } /* [namespace.qual] Accepts the NAME to lookup and its qualifying SCOPE. - Returns the name/type pair found into the CPLUS_BINDING RESULT, + Returns the name/type pair found into the cxx_binding *RESULT, or 0 on error. */ -int -qualified_lookup_using_namespace (name, scope, result, flags) - tree name; - tree scope; - tree result; - int flags; +bool +qualified_lookup_using_namespace (tree name, tree scope, cxx_binding *result, + int flags) { /* Maintain a list of namespaces visited... */ tree seen = NULL_TREE; /* ... and a list of namespace yet to see. */ tree todo = NULL_TREE; tree usings; + timevar_push (TV_NAME_LOOKUP); /* Look through namespace aliases. */ scope = ORIGINAL_NAMESPACE (scope); - while (scope && (result != error_mark_node)) + while (scope && result->value != error_mark_node) { - seen = tree_cons (scope, NULL_TREE, seen); - result = ambiguous_decl (name, result, - binding_for_name (name, scope), flags); + cxx_binding *b = cxx_scope_find_binding_for_name (scope, name); + /* Record SCOPE and resolve declaration ambiguities if NAME was + bound in SCOPE. */ + if (b) + { + seen = tree_cons (scope, NULL_TREE, seen); + result = ambiguous_decl (name, result, b, flags); + } if (!BINDING_VALUE (result) && !BINDING_TYPE (result)) /* Consider using directives. */ for (usings = DECL_NAMESPACE_USING (scope); usings; @@ -3861,7 +3945,7 @@ qualified_lookup_using_namespace (name, scope, result, flags) else scope = NULL_TREE; /* If there never was a todo list. */ } - return result != error_mark_node; + POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, result->value != error_mark_node); } /* [namespace.memdef]/2 */ @@ -3881,7 +3965,7 @@ set_decl_namespace (decl, scope, friendp) scope = ORIGINAL_NAMESPACE (scope); /* It is ok for friends to be qualified in parallel space. */ - if (!friendp && !is_namespace_ancestor (current_namespace, scope)) + if (!friendp && !is_ancestor (current_namespace, scope)) error ("declaration of `%D' not in a namespace surrounding `%D'", decl, scope); DECL_CONTEXT (decl) = FROB_CONTEXT (scope); @@ -3926,19 +4010,20 @@ static tree decl_namespace (decl) tree decl; { + timevar_push (TV_NAME_LOOKUP); if (TYPE_P (decl)) decl = TYPE_STUB_DECL (decl); while (DECL_CONTEXT (decl)) { decl = DECL_CONTEXT (decl); if (TREE_CODE (decl) == NAMESPACE_DECL) - return decl; + POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, decl); if (TYPE_P (decl)) decl = TYPE_STUB_DECL (decl); my_friendly_assert (DECL_P (decl), 390); } - return global_namespace; + POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, global_namespace); } /* Return the namespace where the current declaration is declared. */ @@ -3986,7 +4071,7 @@ push_scope (t) { if (TREE_CODE (t) == NAMESPACE_DECL) push_decl_namespace (t); - else + else if (CLASS_TYPE_P (t)) pushclass (t, 2); } @@ -3998,7 +4083,7 @@ pop_scope (t) { if (TREE_CODE (t) == NAMESPACE_DECL) pop_decl_namespace (); - else + else if (CLASS_TYPE_P (t)) popclass (); } @@ -4164,7 +4249,7 @@ arg_assoc_class (k, type) /* Only interested in global functions with potentially hidden (i.e. unqualified) declarations. */ if (TREE_PURPOSE (friends) == error_mark_node && TREE_VALUE (friends) - && decl_namespace (TREE_VALUE (friends)) == context) + && CP_DECL_CONTEXT (TREE_VALUE (friends)) == context) if (add_function (k, TREE_VALUE (friends))) return 1; @@ -4340,6 +4425,10 @@ lookup_arg_dependent (name, fns, args) struct arg_lookup k; tree fn = NULL_TREE; + if (fns == error_mark_node) + fns = NULL_TREE; + + timevar_push (TV_NAME_LOOKUP); k.name = name; k.functions = fns; k.classes = NULL_TREE; @@ -4354,7 +4443,7 @@ lookup_arg_dependent (name, fns, args) unqualified_namespace_lookup (name, 0, &k.namespaces); arg_assoc_args (&k, args); - return k.functions; + POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, k.functions); } /* Process a namespace-alias declaration. */ @@ -4444,33 +4533,34 @@ do_nonmember_using_decl (scope, name, oldval, oldtype, newval, newtype) tree oldval, oldtype; tree *newval, *newtype; { - tree decls; + cxx_binding decls; *newval = *newtype = NULL_TREE; - decls = make_node (CPLUS_BINDING); - if (!qualified_lookup_using_namespace (name, scope, decls, 0)) + cxx_binding_clear (&decls); + if (!qualified_lookup_using_namespace (name, scope, &decls, 0)) /* Lookup error */ return; - if (!BINDING_VALUE (decls) && !BINDING_TYPE (decls)) + if (!decls.value && !decls.type) { error ("`%D' not declared", name); return; } /* Check for using functions. */ - if (BINDING_VALUE (decls) && is_overloaded_fn (BINDING_VALUE (decls))) + if (decls.value && is_overloaded_fn (decls.value)) { tree tmp, tmp1; if (oldval && !is_overloaded_fn (oldval)) { - duplicate_decls (OVL_CURRENT (BINDING_VALUE (decls)), oldval); + if (!DECL_IMPLICIT_TYPEDEF_P (oldval)) + error ("`%D' is already declared in this scope", name); oldval = NULL_TREE; } *newval = oldval; - for (tmp = BINDING_VALUE (decls); tmp; tmp = OVL_NEXT (tmp)) + for (tmp = decls.value; tmp; tmp = OVL_NEXT (tmp)) { tree new_fn = OVL_CURRENT (tmp); @@ -4492,21 +4582,27 @@ do_nonmember_using_decl (scope, name, oldval, oldtype, newval, newtype) else if (compparms (TYPE_ARG_TYPES (TREE_TYPE (new_fn)), TYPE_ARG_TYPES (TREE_TYPE (old_fn)))) { - /* If this using declaration introduces a function - recognized as a built-in, no longer mark it as - anticipated in this scope. */ - if (DECL_ANTICIPATED (old_fn)) - { - DECL_ANTICIPATED (old_fn) = 0; - break; - } - /* There was already a non-using declaration in this scope with the same parameter types. If both are the same extern "C" functions, that's ok. */ - if (!decls_match (new_fn, old_fn)) - error ("`%D' is already declared in this scope", name); - break; + if (decls_match (new_fn, old_fn)) + { + /* If the OLD_FN was a builtin, there is now a + real declaration. */ + if (DECL_ANTICIPATED (old_fn)) + DECL_ANTICIPATED (old_fn) = 0; + break; + } + else if (!DECL_ANTICIPATED (old_fn)) + { + /* If the OLD_FN was really declared, the + declarations don't match. */ + error ("`%D' is already declared in this scope", name); + break; + } + + /* If the OLD_FN was not really there, just ignore + it and keep going. */ } } @@ -4524,13 +4620,13 @@ do_nonmember_using_decl (scope, name, oldval, oldtype, newval, newtype) } else { - *newval = BINDING_VALUE (decls); - if (oldval) - duplicate_decls (*newval, oldval); + *newval = decls.value; + if (oldval && !decls_match (*newval, oldval)) + error ("`%D' is already declared in this scope", name); } - *newtype = BINDING_TYPE (decls); - if (oldtype && *newtype && oldtype != *newtype) + *newtype = decls.type; + if (oldtype && *newtype && !same_type_p (oldtype, *newtype)) { error ("using declaration `%D' introduced ambiguous type `%T'", name, oldtype); @@ -4544,13 +4640,16 @@ void do_toplevel_using_decl (decl) tree decl; { - tree scope, name, binding; + tree scope, name; tree oldval, oldtype, newval, newtype; + cxx_binding *binding; decl = validate_nonmember_using_decl (decl, &scope, &name); if (decl == NULL_TREE) return; - + + /* A multiple using-declaration is valid, so we call binding_for_name, + not just cxx_binding_make. */ binding = binding_for_name (name, current_namespace); oldval = BINDING_VALUE (binding); @@ -4714,6 +4813,12 @@ mark_used (decl) TREE_USED (decl) = 1; if (processing_template_decl) return; + + if (TREE_CODE (decl) == FUNCTION_DECL && DECL_DECLARED_INLINE_P (decl) + && !TREE_ASM_WRITTEN (decl)) + /* Remember it, so we can check it was defined. */ + defer_fn (decl); + if (!skip_evaluation) assemble_external (decl); @@ -4759,6 +4864,7 @@ handle_class_head (tag_kind, scope, id, attributes, defn_p, new_type_p) int *new_type_p; { tree decl = NULL_TREE; + tree type; tree current = current_scope (); bool xrefd_p = false; @@ -4807,12 +4913,28 @@ handle_class_head (tag_kind, scope, id, attributes, defn_p, new_type_p) xrefd_p = true; } - if (!TYPE_BINFO (TREE_TYPE (decl))) + type = TREE_TYPE (decl); + + if (!TYPE_BINFO (type)) { error ("`%T' is not a class or union type", decl); return error_mark_node; } - + + /* When `A' is a template class, using `class A' without template + argument is invalid unless + - we are inside the scope of the template class `A' or one of its + specialization. + - we are declaring the template class `A' itself. */ + if (TREE_CODE (type) == RECORD_TYPE + && CLASSTYPE_IS_TEMPLATE (type) + && processing_template_decl <= template_class_depth (current) + && ! is_base_of_enclosing_class (type, current_class_type)) + { + error ("template argument is required for `%T'", type); + return error_mark_node; + } + if (defn_p) { /* For a definition, we want to enter the containing scope @@ -4820,6 +4942,18 @@ handle_class_head (tag_kind, scope, id, attributes, defn_p, new_type_p) is different to the current scope. */ tree context = CP_DECL_CONTEXT (decl); + if (IMPLICIT_TYPENAME_P (context)) + context = TREE_TYPE (context); + + /* If that scope does not contain the scope in which the + class was originally declared, the program is invalid. */ + if (current && !is_ancestor (current, context)) + { + error ("declaration of `%D' in `%D' which does not " + "enclose `%D'", decl, current, CP_DECL_CONTEXT (decl)); + return NULL_TREE; + } + *new_type_p = (current != context && TREE_CODE (context) != TEMPLATE_TYPE_PARM && TREE_CODE (context) != BOUND_TEMPLATE_TEMPLATE_PARM); |