/* Process declarations and variables for C++ compiler.
Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+ 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
Hacked by Michael Tiemann (tiemann@cygnus.com)
This file is part of GCC.
#include "flags.h"
#include "cp-tree.h"
#include "decl.h"
-#include "lex.h"
#include "output.h"
#include "except.h"
#include "toplev.h"
#include "cpplib.h"
#include "target.h"
#include "c-common.h"
+#include "tree-mudflap.h"
#include "cgraph.h"
#include "tree-inline.h"
+
extern cpp_reader *parse_in;
/* This structure contains information about the initializations
static void mark_vtable_entries (tree);
static void grok_function_init (tree, tree);
static bool maybe_emit_vtables (tree);
-static void add_using_namespace (tree, tree, bool);
-static cxx_binding *ambiguous_decl (tree, cxx_binding *, cxx_binding *, int);
static tree build_anon_union_vars (tree);
static bool acceptable_java_type (tree);
static tree start_objects (int, int);
static void finish_objects (int, int, tree);
-static tree merge_functions (tree, tree);
-static tree decl_namespace (tree);
-static tree validate_nonmember_using_decl (tree, tree *, tree *);
-static void do_nonmember_using_decl (tree, tree, tree, tree, tree *, tree *);
static tree start_static_storage_duration_function (unsigned);
static void finish_static_storage_duration_function (tree);
static priority_info get_priority_info (int);
tree static_ctors;
tree static_dtors;
-/* The :: namespace. */
-
-tree global_namespace;
\f
/* Incorporate `const' and `volatile' qualifiers for member functions.
FUNCTION is a TYPE_DECL or a FUNCTION_DECL.
TYPE_UNQUALIFIED will be an extension. */
int
-grok_method_quals (tree ctype, tree function, tree quals)
+grok_method_quals (tree ctype, tree function, cp_cv_quals quals)
{
tree fntype = TREE_TYPE (function);
tree raises = TYPE_RAISES_EXCEPTIONS (fntype);
int type_quals = TYPE_UNQUALIFIED;
- int dup_quals = TYPE_UNQUALIFIED;
int this_quals = TYPE_UNQUALIFIED;
- do
- {
- int tq = cp_type_qual_from_rid (TREE_VALUE (quals));
-
- if ((type_quals | this_quals) & tq)
- dup_quals |= tq;
- else if (tq & TYPE_QUAL_RESTRICT)
- this_quals |= tq;
- else
- type_quals |= tq;
- quals = TREE_CHAIN (quals);
- }
- while (quals);
-
- if (dup_quals != TYPE_UNQUALIFIED)
- error ("duplicate type qualifiers in %s declaration",
- TREE_CODE (function) == FUNCTION_DECL
- ? "member function" : "type");
+ type_quals = quals & ~TYPE_QUAL_RESTRICT;
+ this_quals = quals & TYPE_QUAL_RESTRICT;
ctype = cp_build_qualified_type (ctype, type_quals);
- fntype = build_cplus_method_type (ctype, TREE_TYPE (fntype),
- (TREE_CODE (fntype) == METHOD_TYPE
- ? TREE_CHAIN (TYPE_ARG_TYPES (fntype))
- : TYPE_ARG_TYPES (fntype)));
+ fntype = build_method_type_directly (ctype, TREE_TYPE (fntype),
+ (TREE_CODE (fntype) == METHOD_TYPE
+ ? TREE_CHAIN (TYPE_ARG_TYPES (fntype))
+ : TYPE_ARG_TYPES (fntype)));
if (raises)
fntype = build_exception_variant (fntype, raises);
return this_quals;
}
-/* Warn when -fexternal-templates is used and #pragma
- interface/implementation is not used all the times it should be,
- inform the user. */
-
-void
-warn_if_unknown_interface (tree decl)
-{
- static int already_warned = 0;
- if (already_warned++)
- return;
-
- if (flag_alt_external_templates)
- {
- tree til = tinst_for_decl ();
- location_t saved_loc = input_location;
-
- if (til)
- {
- input_line = TINST_LINE (til);
- input_filename = TINST_FILE (til);
- }
- warning ("template `%#D' instantiated in file without #pragma interface",
- decl);
- input_location = saved_loc;
- }
- else
- cp_warning_at ("template `%#D' defined in file without #pragma interface",
- decl);
-}
-
-/* A subroutine of the parser, to handle a component list. */
-
-void
-grok_x_components (tree specs)
-{
- tree t;
-
- specs = strip_attrs (specs);
-
- check_tag_decl (specs);
- t = groktypename (build_tree_list (specs, NULL_TREE));
-
- /* The only case where we need to do anything additional here is an
- anonymous union field, e.g.: `struct S { union { int i; }; };'. */
- if (t == NULL_TREE || !ANON_AGGR_TYPE_P (t))
- return;
-
- fixup_anonymous_aggr (t);
- finish_member_declaration (build_decl (FIELD_DECL, NULL_TREE, t));
-}
-
/* Build a PARM_DECL with NAME and TYPE, and set DECL_ARG_TYPE
appropriately. */
cp_build_parm_decl (tree name, tree type)
{
tree parm = build_decl (PARM_DECL, name, type);
- DECL_ARG_TYPE (parm) = type_passed_as (type);
+ /* DECL_ARG_TYPE is only used by the back end and the back end never
+ sees templates. */
+ if (!processing_template_decl)
+ DECL_ARG_TYPE (parm) = type_passed_as (type);
return parm;
}
/* When processing templates we can't know, in general, whether or
not we're going to have virtual baseclasses. */
- if (uses_template_parms (fn))
+ if (processing_template_decl)
return;
/* We don't need an in-charge parameter for constructors that don't
TREE_CHAIN (DECL_ARGUMENTS (fn)) = parms;
/* And rebuild the function type. */
- fntype = build_cplus_method_type (basetype, TREE_TYPE (TREE_TYPE (fn)),
- arg_types);
+ fntype = build_method_type_directly (basetype, TREE_TYPE (TREE_TYPE (fn)),
+ arg_types);
if (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (fn)))
fntype = build_exception_variant (fntype,
TYPE_RAISES_EXCEPTIONS (TREE_TYPE (fn)));
QUALS are the qualifiers for the this pointer. */
void
-grokclassfn (tree ctype, tree function, enum overload_flags flags, tree quals)
+grokclassfn (tree ctype, tree function, enum overload_flags flags,
+ cp_cv_quals quals)
{
tree fn_name = DECL_NAME (function);
- int this_quals = TYPE_UNQUALIFIED;
+ cp_cv_quals this_quals = TYPE_UNQUALIFIED;
/* Even within an `extern "C"' block, members get C++ linkage. See
[dcl.link] for details. */
qual_type = cp_build_qualified_type (type, this_quals);
parm = build_artificial_parm (this_identifier, qual_type);
c_apply_type_quals_to_decl (this_quals, parm);
- TREE_CHAIN (parm) = last_function_parms;
- last_function_parms = parm;
+ TREE_CHAIN (parm) = DECL_ARGUMENTS (function);
+ DECL_ARGUMENTS (function) = parm;
}
- DECL_ARGUMENTS (function) = last_function_parms;
DECL_CONTEXT (function) = ctype;
if (flags == DTOR_FLAG)
if (flags == DTOR_FLAG || DECL_CONSTRUCTOR_P (function))
maybe_retrofit_in_chrg (function);
-
- if (flags == DTOR_FLAG)
- {
- DECL_DESTRUCTOR_P (function) = 1;
- TYPE_HAS_DESTRUCTOR (ctype) = 1;
- }
}
/* Create an ARRAY_REF, checking for the user doing things backwards
{
if (type_dependent_expression_p (array_expr)
|| type_dependent_expression_p (index_exp))
- return build_min_nt (ARRAY_REF, array_expr, index_exp);
+ return build_min_nt (ARRAY_REF, array_expr, index_exp,
+ NULL_TREE, NULL_TREE);
array_expr = build_non_dependent_expr (array_expr);
index_exp = build_non_dependent_expr (index_exp);
}
/* If they have an `operator[]', use that. */
if (IS_AGGR_TYPE (type) || IS_AGGR_TYPE (TREE_TYPE (index_exp)))
expr = build_new_op (ARRAY_REF, LOOKUP_NORMAL,
- array_expr, index_exp, NULL_TREE);
+ array_expr, index_exp, NULL_TREE,
+ /*overloaded_p=*/NULL);
else
{
tree p1, p2, i1, i2;
expr = build_array_ref (array_expr, index_exp);
}
if (processing_template_decl && expr != error_mark_node)
- return build_min (ARRAY_REF, TREE_TYPE (expr), orig_array_expr,
- orig_index_exp);
+ return build_min_non_dep (ARRAY_REF, expr, orig_array_expr, orig_index_exp,
+ NULL_TREE, NULL_TREE);
return expr;
}
/* Given the cast expression EXP, checking out its validity. Either return
an error_mark_node if there was an unavoidable error, return a cast to
void for trying to delete a pointer w/ the value 0, or return the
- call to delete. If DOING_VEC is 1, we handle things differently
- for doing an array delete. If DOING_VEC is 2, they gave us the
- array size as an argument to delete.
+ call to delete. If DOING_VEC is true, we handle things differently
+ for doing an array delete.
Implements ARM $5.3.4. This is called from the parser. */
tree
-delete_sanity (tree exp, tree size, int doing_vec, int use_global_delete)
+delete_sanity (tree exp, tree size, bool doing_vec, int use_global_delete)
{
tree t, type;
- /* For a regular vector delete (aka, no size argument) we will pass
- this down as a NULL_TREE into build_vec_delete. */
- tree maxindex = NULL_TREE;
if (exp == error_mark_node)
return exp;
t = build_min (DELETE_EXPR, void_type_node, exp, size);
DELETE_EXPR_USE_GLOBAL (t) = use_global_delete;
DELETE_EXPR_USE_VEC (t) = doing_vec;
+ TREE_SIDE_EFFECTS (t) = 1;
return t;
}
exp = convert_from_reference (exp);
+
+ /* An array can't have been allocated by new, so complain. */
+ if (TREE_CODE (exp) == VAR_DECL
+ && TREE_CODE (TREE_TYPE (exp)) == ARRAY_TYPE)
+ warning ("deleting array `%#D'", exp);
+
t = build_expr_type_conversion (WANT_POINTER, exp, true);
if (t == NULL_TREE || t == error_mark_node)
return error_mark_node;
}
- if (doing_vec == 2)
- {
- maxindex = cp_build_binary_op (MINUS_EXPR, size, integer_one_node);
- pedwarn ("anachronistic use of array size in vector delete");
- }
-
type = TREE_TYPE (t);
/* As of Valley Forge, you can delete a pointer to const. */
doing_vec = 0;
}
- /* An array can't have been allocated by new, so complain. */
- if (TREE_CODE (t) == ADDR_EXPR
- && TREE_CODE (TREE_OPERAND (t, 0)) == VAR_DECL
- && TREE_CODE (TREE_TYPE (TREE_OPERAND (t, 0))) == ARRAY_TYPE)
- warning ("deleting array `%#D'", TREE_OPERAND (t, 0));
-
/* Deleting a pointer with the value zero is valid and has no effect. */
if (integer_zerop (t))
return build1 (NOP_EXPR, void_type_node, t);
if (doing_vec)
- return build_vec_delete (t, maxindex, sfk_deleting_destructor,
+ return build_vec_delete (t, /*maxindex=*/NULL_TREE,
+ sfk_deleting_destructor,
use_global_delete);
else
return build_delete (type, t, sfk_deleting_destructor,
bool jerr = false;
tree arg_types = TYPE_ARG_TYPES (TREE_TYPE (method));
tree ret_type = TREE_TYPE (TREE_TYPE (method));
+
if (!acceptable_java_type (ret_type))
{
error ("Java method '%D' has non-Java return type `%T'",
method, ret_type);
jerr = true;
}
+
+ arg_types = TREE_CHAIN (arg_types);
+ if (DECL_HAS_IN_CHARGE_PARM_P (method))
+ arg_types = TREE_CHAIN (arg_types);
+ if (DECL_HAS_VTT_PARM_P (method))
+ arg_types = TREE_CHAIN (arg_types);
+
for (; arg_types != NULL_TREE; arg_types = TREE_CHAIN (arg_types))
{
tree type = TREE_VALUE (arg_types);
/* Sanity check: report error if this function FUNCTION is not
really a member of the class (CTYPE) it is supposed to belong to.
- CNAME is the same here as it is for grokclassfn above. */
+ TEMPLATE_PARMS is used to specifiy the template parameters of a member
+ template passed as FUNCTION_DECL. If the member template is passed as a
+ TEMPLATE_DECL, it can be NULL since the parameters can be extracted
+ from the declaration. If the function is not a function template, it
+ must be NULL.
+ It returns the original declaration for the function, or NULL_TREE
+ if no declaration was found (and an error was emitted). */
tree
-check_classfn (tree ctype, tree function)
+check_classfn (tree ctype, tree function, tree template_parms)
{
int ix;
- int is_template;
+ bool is_template;
if (DECL_USE_TEMPLATE (function)
&& !(TREE_CODE (function) == TEMPLATE_DECL
find the method, but we don't complain. */
return NULL_TREE;
+ /* Basic sanity check: for a template function, the template parameters
+ either were not passed, or they are the same of DECL_TEMPLATE_PARMS. */
+ if (TREE_CODE (function) == TEMPLATE_DECL)
+ {
+ my_friendly_assert (!template_parms
+ || comp_template_parms
+ (template_parms,
+ DECL_TEMPLATE_PARMS (function)),
+ 20040303);
+ template_parms = DECL_TEMPLATE_PARMS (function);
+ }
+
/* OK, is this a definition of a member template? */
- is_template = (TREE_CODE (function) == TEMPLATE_DECL
- || (processing_template_decl - template_class_depth (ctype)));
+ is_template = (template_parms != NULL_TREE);
ix = lookup_fnfields_1 (complete_type (ctype),
DECL_CONSTRUCTOR_P (function) ? ctor_identifier :
tree methods = CLASSTYPE_METHOD_VEC (ctype);
tree fndecls, fndecl = 0;
bool is_conv_op;
+ bool pop_p;
const char *format = NULL;
- push_scope (ctype);
+ pop_p = push_scope (ctype);
for (fndecls = TREE_VEC_ELT (methods, ix);
fndecls; fndecls = OVL_NEXT (fndecls))
{
if (same_type_p (TREE_TYPE (TREE_TYPE (function)),
TREE_TYPE (TREE_TYPE (fndecl)))
&& compparms (p1, p2)
+ && (!is_template
+ || comp_template_parms (template_parms,
+ DECL_TEMPLATE_PARMS (fndecl)))
&& (DECL_TEMPLATE_SPECIALIZATION (function)
== DECL_TEMPLATE_SPECIALIZATION (fndecl))
&& (!DECL_TEMPLATE_SPECIALIZATION (function)
== DECL_TI_TEMPLATE (fndecl))))
break;
}
- pop_scope (ctype);
+ if (pop_p)
+ pop_scope (ctype);
if (fndecls)
return OVL_CURRENT (fndecls);
error ("prototype for `%#D' does not match any in class `%T'",
CHANGES TO CODE IN `start_method'. */
tree
-grokfield (tree declarator, tree declspecs, tree init, tree asmspec_tree,
+grokfield (const cp_declarator *declarator,
+ cp_decl_specifier_seq *declspecs,
+ tree init, tree asmspec_tree,
tree attrlist)
{
tree value;
const char *asmspec = 0;
int flags = LOOKUP_ONLYCONVERTING;
- if (declspecs == NULL_TREE
- && TREE_CODE (declarator) == SCOPE_REF
- && TREE_CODE (TREE_OPERAND (declarator, 1)) == IDENTIFIER_NODE)
+ if (!declspecs->any_specifiers_p
+ && declarator->kind == cdk_id
+ && TREE_CODE (declarator->u.id.name) == SCOPE_REF
+ && (TREE_CODE (TREE_OPERAND (declarator->u.id.name, 1))
+ == IDENTIFIER_NODE))
{
/* Access declaration */
- if (! IS_AGGR_TYPE_CODE (TREE_CODE (TREE_OPERAND (declarator, 0))))
+ if (! IS_AGGR_TYPE_CODE (TREE_CODE
+ (TREE_OPERAND (declarator->u.id.name, 0))))
;
- else if (TREE_COMPLEXITY (declarator) == current_class_depth)
+ else if (TREE_COMPLEXITY (declarator->u.id.name) == current_class_depth)
pop_nested_class ();
- return do_class_using_decl (declarator);
+ return do_class_using_decl (declarator->u.id.name);
}
if (init
init = NULL_TREE;
value = grokdeclarator (declarator, declspecs, FIELD, init != 0, &attrlist);
- if (! value || value == error_mark_node)
+ if (! value || error_operand_p (value))
/* friend or constructor went bad. */
- return value;
- if (TREE_TYPE (value) == error_mark_node)
return error_mark_node;
if (TREE_CODE (value) == TYPE_DECL && init)
DECL_NONLOCAL (value) = 1;
DECL_CONTEXT (value) = current_class_type;
- if (CLASS_TYPE_P (TREE_TYPE (value)))
- CLASSTYPE_GOT_SEMICOLON (TREE_TYPE (value)) = 1;
-
if (processing_template_decl)
value = push_template_decl (value);
if (processing_template_decl
&& (TREE_CODE (value) == VAR_DECL || TREE_CODE (value) == FUNCTION_DECL))
- value = push_template_decl (value);
+ {
+ value = push_template_decl (value);
+ if (error_operand_p (value))
+ return error_mark_node;
+ }
if (attrlist)
cplus_decl_attributes (&value, attrlist, 0);
/* This must override the asm specifier which was placed
by grokclassfn. Lay this out fresh. */
SET_DECL_RTL (value, NULL_RTX);
- SET_DECL_ASSEMBLER_NAME (value, get_identifier (asmspec));
+ change_decl_assembler_name (value, get_identifier (asmspec));
}
if (!DECL_FRIEND_P (value))
grok_special_member_properties (value);
WIDTH is non-NULL for bit fields only, and is an INTEGER_CST node. */
tree
-grokbitfield (tree declarator, tree declspecs, tree width)
+grokbitfield (const cp_declarator *declarator,
+ cp_decl_specifier_seq *declspecs, tree width)
{
- register tree value = grokdeclarator (declarator, declspecs, BITFIELD,
- 0, NULL);
+ tree value = grokdeclarator (declarator, declspecs, BITFIELD, 0, NULL);
if (! value) return NULL_TREE; /* friends went bad. */
SET_IDENTIFIER_TYPE_VALUE (DECL_NAME (*decl), TREE_TYPE (*decl));
}
\f
-/* Return the name for the constructor (or destructor) for the
- specified class TYPE. When given a template, this routine doesn't
- lose the specialization. */
-
-tree
-constructor_name_full (tree type)
-{
- type = TYPE_MAIN_VARIANT (type);
- if (CLASS_TYPE_P (type) && TYPE_WAS_ANONYMOUS (type)
- && TYPE_HAS_CONSTRUCTOR (type))
- return DECL_NAME (OVL_CURRENT (CLASSTYPE_CONSTRUCTORS (type)));
- else
- return TYPE_IDENTIFIER (type);
-}
-
-/* Return the name for the constructor (or destructor) for the
- specified class. When given a template, return the plain
- unspecialized name. */
-
-tree
-constructor_name (tree type)
-{
- tree name;
- name = constructor_name_full (type);
- if (IDENTIFIER_TEMPLATE (name))
- name = IDENTIFIER_TEMPLATE (name);
- return name;
-}
-
-/* Returns TRUE if NAME is the name for the constructor for TYPE. */
-
-bool
-constructor_name_p (tree name, tree type)
-{
- tree ctor_name;
-
- if (!name)
- return false;
-
- if (TREE_CODE (name) != IDENTIFIER_NODE)
- return false;
-
- ctor_name = constructor_name_full (type);
- if (name == ctor_name)
- return true;
- if (IDENTIFIER_TEMPLATE (ctor_name)
- && name == IDENTIFIER_TEMPLATE (ctor_name))
- return true;
- return false;
-}
-
-\f
-/* Defer the compilation of the FN until the end of compilation. */
-
-void
-defer_fn (tree fn)
-{
- if (DECL_DEFERRED_FN (fn))
- return;
- DECL_DEFERRED_FN (fn) = 1;
- DECL_DEFER_OUTPUT (fn) = 1;
- if (!deferred_fns)
- VARRAY_TREE_INIT (deferred_fns, 32, "deferred_fns");
-
- VARRAY_PUSH_TREE (deferred_fns, fn);
-}
-
/* Walks through the namespace- or function-scope anonymous union OBJECT,
building appropriate ALIAS_DECLs. Returns one of the fields for use in
the mangled name. */
cp_pedwarn_at ("protected member `%#D' in anonymous union", field);
if (processing_template_decl)
- ref = build_min_nt (COMPONENT_REF, object, DECL_NAME (field));
+ ref = build_min_nt (COMPONENT_REF, object,
+ DECL_NAME (field), NULL_TREE);
else
ref = build_class_member_access_expr (object, field, NULL_TREE,
false);
pushdecl (anon_union_decl);
if (building_stmt_tree ()
&& at_function_scope_p ())
- add_decl_stmt (anon_union_decl);
+ add_decl_expr (anon_union_decl);
else if (!processing_template_decl)
rest_of_decl_compilation (anon_union_decl, NULL,
toplevel_bindings_p (), at_eof);
{
case 2:
args = tree_cons (NULL_TREE, size_type_node, args);
- /* FALLTHROUGH */
+ /* Fall through. */
case 1:
type = build_exception_variant
(build_function_type (ptr_type_node, args),
TYPE_RAISES_EXCEPTIONS (type));
- /* FALLTHROUGH */
+ /* Fall through. */
default:;
}
return type;
{
case 2:
args = tree_cons (NULL_TREE, ptr_type_node, args);
- /* FALLTHROUGH */
+ /* Fall through. */
case 1:
type = build_exception_variant
(build_function_type (void_type_node, args),
TYPE_RAISES_EXCEPTIONS (type));
- /* FALLTHROUGH */
+ /* Fall through. */
default:;
}
/* For win32 we also want to put explicit instantiations in
linkonce sections, so that they will be merged with implicit
- instantiations; otherwise we get duplicate symbol errors. */
+ instantiations; otherwise we get duplicate symbol errors.
+ For Darwin we do not want explicit instantiations to be
+ linkonce. */
void
maybe_make_one_only (tree decl)
to for variables so that cp_finish_decl will update their linkage,
because their DECL_INITIAL may not have been set properly yet. */
- make_decl_one_only (decl);
-
- if (TREE_CODE (decl) == VAR_DECL)
+ if (!TARGET_WEAK_NOT_IN_ARCHIVE_TOC
+ || (! DECL_EXPLICIT_INSTANTIATION (decl)
+ && ! DECL_TEMPLATE_SPECIALIZATION (decl)))
{
- DECL_COMDAT (decl) = 1;
- /* Mark it needed so we don't forget to emit it. */
- TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)) = 1;
+ make_decl_one_only (decl);
+
+ if (TREE_CODE (decl) == VAR_DECL)
+ {
+ DECL_COMDAT (decl) = 1;
+ /* Mark it needed so we don't forget to emit it. */
+ mark_decl_referenced (decl);
+ }
}
}
&& TYPE_POLYMORPHIC_P (ctype))
{
tree method = CLASSTYPE_KEY_METHOD (ctype);
- if (method)
+
+ /* If weak symbol support is not available, then we must be
+ careful not to emit the vtable when the key function is
+ inline. An inline function can be defined in multiple
+ translation units. If we were to emit the vtable in each
+ translation unit containing a definition, we would get
+ multiple definition errors at link-time. */
+ if (method && (flag_weak || ! DECL_DECLARED_INLINE_P (method)))
import_export = (DECL_REALLY_EXTERN (method) ? -1 : 1);
}
import_export = 0;
#endif
+ /* Allow backends the chance to overrule the decision. */
+ if (targetm.cxx.import_export_class)
+ import_export = targetm.cxx.import_export_class (ctype, import_export);
+
if (import_export)
{
SET_CLASSTYPE_INTERFACE_KNOWN (ctype);
CLASSTYPE_INTERFACE_ONLY (ctype) = (import_export < 0);
}
}
-
-/* We need to describe to the assembler the relationship between
- a vtable and the vtable of the parent class. */
-void
-prepare_assemble_variable (tree vars)
+/* Return true if VAR has already been provided to the back end; in that
+ case VAR should not be modified further by the front end. */
+static bool
+var_finalized_p (tree var)
{
- tree parent;
- rtx child_rtx, parent_rtx;
-
- if (!flag_vtable_gc || TREE_CODE (vars) != VAR_DECL
- || !DECL_VTABLE_OR_VTT_P (vars))
- return;
-
- child_rtx = XEXP (DECL_RTL (vars), 0); /* strip the mem ref */
-
- parent = binfo_for_vtable (vars);
-
- if (parent == TYPE_BINFO (DECL_CONTEXT (vars)))
- parent_rtx = const0_rtx;
- else if (parent)
- {
- parent = get_vtbl_decl_for_binfo (TYPE_BINFO (BINFO_TYPE (parent)));
- parent_rtx = XEXP (DECL_RTL (parent), 0); /* strip the mem ref */
- }
+ if (flag_unit_at_a_time)
+ return cgraph_varpool_node (var)->finalized;
else
- abort ();
-
- assemble_vtable_inherit (child_rtx, parent_rtx);
+ return TREE_ASM_WRITTEN (var);
}
/* If necessary, write out the vtables for the dynamic class CTYPE.
tree vtbl;
tree primary_vtbl;
bool needed = false;
+ bool weaken_vtables;
/* If the vtables for this class have already been emitted there is
nothing more to do. */
primary_vtbl = CLASSTYPE_VTABLES (ctype);
- if (TREE_ASM_WRITTEN (primary_vtbl))
+ if (var_finalized_p (primary_vtbl))
return false;
/* Ignore dummy vtables made by get_vtable_decl. */
if (TREE_TYPE (primary_vtbl) == void_type_node)
return false;
import_export_class (ctype);
- import_export_vtable (primary_vtbl, ctype, 1);
/* See if any of the vtables are needed. */
for (vtbl = CLASSTYPE_VTABLES (ctype); vtbl; vtbl = TREE_CHAIN (vtbl))
- if (!DECL_EXTERNAL (vtbl) && DECL_NEEDED_P (vtbl))
- break;
+ {
+ import_export_vtable (vtbl, ctype, 1);
+ if (!DECL_EXTERNAL (vtbl) && DECL_NEEDED_P (vtbl))
+ break;
+ }
if (!vtbl)
{
/* If the references to this class' vtables are optimized away,
else if (TREE_PUBLIC (vtbl) && !DECL_COMDAT (vtbl))
needed = true;
+ /* Determine whether to make vtables weak. The ABI requires that we
+ do so. There are two cases in which we have to violate the ABI
+ specification: targets where we don't have weak symbols
+ (obviously), and targets where weak symbols don't appear in
+ static archives' tables of contents. On such targets, avoiding
+ undefined symbol link errors requires that we only make a symbol
+ weak if we know that it will be emitted everywhere it's needed.
+ So on such targets we don't make vtables weak in the common case
+ where we're emitting a vtable of a nontemplate class in the
+ translation unit containing the definition of a noninline key
+ method. */
+ if (flag_weak && !TARGET_WEAK_NOT_IN_ARCHIVE_TOC)
+ weaken_vtables = true;
+ else if (flag_weak)
+ {
+ if (CLASSTYPE_USE_TEMPLATE (ctype))
+ weaken_vtables = CLASSTYPE_IMPLICIT_INSTANTIATION (ctype);
+ else
+ weaken_vtables = !CLASSTYPE_KEY_METHOD (ctype)
+ || DECL_DECLARED_INLINE_P (CLASSTYPE_KEY_METHOD (ctype));
+ }
+ else
+ weaken_vtables = false;
/* The ABI requires that we emit all of the vtables if we emit any
of them. */
cgraph_varpool_mark_needed_node (cgraph_varpool_node (vtbl));
if (TREE_TYPE (DECL_INITIAL (vtbl)) == 0)
- store_init_value (vtbl, DECL_INITIAL (vtbl));
+ {
+ /* It had better be all done at compile-time. */
+ if (store_init_value (vtbl, DECL_INITIAL (vtbl)))
+ abort ();
+ }
if (write_symbols == DWARF_DEBUG || write_symbols == DWARF2_DEBUG)
{
DECL_IGNORED_P (vtbl) = 1;
}
- /* Always make vtables weak. */
- if (flag_weak)
+ /* Always make vtables weak. Or at least almost always; see above. */
+ if (weaken_vtables)
comdat_linkage (vtbl);
rest_of_decl_compilation (vtbl, NULL, 1, 1);
if ((DECL_IMPLICIT_INSTANTIATION (decl)
|| DECL_FRIEND_PSEUDO_TEMPLATE_INSTANTIATION (decl))
&& (flag_implicit_templates
- || (flag_implicit_inline_templates
+ || (flag_implicit_inline_templates
+ && TREE_CODE (decl) == FUNCTION_DECL
&& DECL_DECLARED_INLINE_P (decl))))
{
if (!TREE_PUBLIC (decl))
/* We use a type that is big enough to contain a mutex as well
as an integer counter. */
- guard_type = long_long_integer_type_node;
+ guard_type = targetm.cxx.guard_type ();
guard = build_decl (VAR_DECL, sname, guard_type);
/* The guard should have the same linkage as what it guards. */
static tree
get_guard_bits (tree guard)
{
- /* We only set the first byte of the guard, in order to leave room
- for a mutex in the high-order bits. */
- guard = build1 (ADDR_EXPR,
- build_pointer_type (TREE_TYPE (guard)),
- guard);
- guard = build1 (NOP_EXPR,
- build_pointer_type (char_type_node),
- guard);
- guard = build1 (INDIRECT_REF, char_type_node, guard);
+ if (!targetm.cxx.guard_mask_bit ())
+ {
+ /* We only set the first byte of the guard, in order to leave room
+ for a mutex in the high-order bits. */
+ guard = build1 (ADDR_EXPR,
+ build_pointer_type (TREE_TYPE (guard)),
+ guard);
+ guard = build1 (NOP_EXPR,
+ build_pointer_type (char_type_node),
+ guard);
+ guard = build1 (INDIRECT_REF, char_type_node, guard);
+ }
return guard;
}
/* Check to see if the GUARD is zero. */
guard = get_guard_bits (guard);
+
+ /* Mask off all but the low bit. */
+ if (targetm.cxx.guard_mask_bit ())
+ {
+ guard_value = integer_one_node;
+ if (!same_type_p (TREE_TYPE (guard_value), TREE_TYPE (guard)))
+ guard_value = convert (TREE_TYPE (guard), guard_value);
+ guard = cp_build_binary_op (BIT_AND_EXPR, guard, guard_value);
+ }
+
guard_value = integer_zero_node;
if (!same_type_p (TREE_TYPE (guard_value), TREE_TYPE (guard)))
guard_value = convert (TREE_TYPE (guard), guard_value);
static tree
start_objects (int method_type, int initp)
{
- tree fnname;
tree body;
+ tree fndecl;
char type[10];
/* Make ctor or dtor function. METHOD_TYPE may be 'I' or 'D'. */
else
sprintf (type, "%c", method_type);
- fnname = get_file_function_name_long (type);
-
- start_function (void_list_node,
- make_call_declarator (fnname, void_list_node, NULL_TREE,
- NULL_TREE),
- NULL_TREE, SF_DEFAULT);
+ fndecl = build_lang_decl (FUNCTION_DECL,
+ get_file_function_name_long (type),
+ build_function_type (void_type_node,
+ void_list_node));
+ start_preparsed_function (fndecl, /*attrs=*/NULL_TREE, SF_PRE_PARSED);
/* It can be a static function as long as collect2 does not have
to scan the object file to find its ctor/dtor routine. */
DECL_GLOBAL_DTOR_P (current_function_decl) = 1;
DECL_LANG_SPECIFIC (current_function_decl)->decl_flags.u2sel = 1;
- body = begin_compound_stmt (/*has_no_scope=*/false);
+ body = begin_compound_stmt (BCS_FN_BODY);
/* We cannot allow these functions to be elided, even if they do not
have external linkage. And, there's no point in deferring
compilation of thes functions; they're all going to have to be
out anyhow. */
- current_function_cannot_inline
- = "static constructors and destructors cannot be inlined";
+ DECL_INLINE (current_function_decl) = 0;
+ DECL_UNINLINABLE (current_function_decl) = 1;
return body;
}
/* Put the function in the global scope. */
pushdecl (ssdf_decl);
- /* Start the function itself. This is equivalent to declarating the
+ /* Start the function itself. This is equivalent to declaring the
function as:
static void __ssdf (int __initialize_p, init __priority_p);
It is static because we only need to call this function from the
various constructor and destructor functions for this module. */
- start_function (/*specs=*/NULL_TREE,
- ssdf_decl,
- /*attrs=*/NULL_TREE,
- SF_PRE_PARSED);
+ start_preparsed_function (ssdf_decl,
+ /*attrs=*/NULL_TREE,
+ SF_PRE_PARSED);
/* Set up the scope of the outermost block in the function. */
- body = begin_compound_stmt (/*has_no_scope=*/false);
+ body = begin_compound_stmt (BCS_FN_BODY);
/* This function must not be deferred because we are depending on
its compilation to tell us what is TREE_SYMBOL_REFERENCED. */
- current_function_cannot_inline
- = "static storage duration functions cannot be inlined";
+ DECL_INLINE (ssdf_decl) = 0;
+ DECL_UNINLINABLE (ssdf_decl) = 1;
return body;
}
finish_static_initialization_or_destruction (tree guard_if_stmt)
{
finish_then_clause (guard_if_stmt);
- finish_if_stmt ();
+ finish_if_stmt (guard_if_stmt);
/* Now that we're done with DECL we don't need to pretend to be a
member of its class any longer. */
if (flag_use_cxa_atexit)
register_dtor_fn (decl);
- /* Finsh up. */
+ /* Finish up. */
finish_static_initialization_or_destruction (guard_if_stmt);
}
tree v;
for (v = vars; v; v = TREE_CHAIN (v))
- if (! TREE_ASM_WRITTEN (TREE_VALUE (v)))
+ if (!var_finalized_p (TREE_VALUE (v)))
rest_of_decl_compilation (TREE_VALUE (v), 0, 1, 1);
}
size_t i;
input_location = *locus;
+#ifdef USE_MAPPED_LOCATION
+ /* ??? */
+#else
locus->line++;
+#endif
/* We use `I' to indicate initialization and `D' to indicate
destruction. */
return 0;
}
-/* Callgraph code does not understand the member pointers. Mark the methods
- referenced as used. */
-static tree
-mark_member_pointers (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED,
- void *data ATTRIBUTE_UNUSED)
-{
- if (TREE_CODE (*tp) == PTRMEM_CST
- && TYPE_PTRMEMFUNC_P (TREE_TYPE (*tp)))
- cgraph_mark_needed_node (cgraph_node (PTRMEM_CST_MEMBER (*tp)), 1);
- return 0;
-}
+/* Called via LANGHOOK_CALLGRAPH_ANALYZE_EXPR. It is supposed to mark
+ decls referenced from frontend specific constructs; it will be called
+ only for language-specific tree nodes.
-/* Called via LANGHOOK_CALLGRAPH_LOWER_FUNCTION. It is supposed to lower
- frontend specific constructs that would otherwise confuse the middle end. */
-void
-lower_function (tree fn)
+ Here we must deal with member pointers. */
+
+tree
+cxx_callgraph_analyze_expr (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED,
+ tree from ATTRIBUTE_UNUSED)
{
- walk_tree_without_duplicates (&DECL_SAVED_TREE (fn), mark_member_pointers,
- NULL);
+ tree t = *tp;
+
+ if (flag_unit_at_a_time)
+ switch (TREE_CODE (t))
+ {
+ case PTRMEM_CST:
+ if (TYPE_PTRMEMFUNC_P (TREE_TYPE (t)))
+ cgraph_mark_needed_node (cgraph_node (PTRMEM_CST_MEMBER (t)));
+ break;
+ case BASELINK:
+ if (TREE_CODE (BASELINK_FUNCTIONS (t)) == FUNCTION_DECL)
+ cgraph_mark_needed_node (cgraph_node (BASELINK_FUNCTIONS (t)));
+ break;
+
+ default:
+ break;
+ }
+
+ return NULL;
}
/* This routine is called from the last rule in yyparse ().
first, since that way we only need to reverse the decls once. */
void
-finish_file ()
+finish_file (void)
{
tree vars;
bool reconsider;
if (pch_file)
c_common_write_pch ();
+#ifdef USE_MAPPED_LOCATION
+ /* FIXME - huh? */
+#else
/* Otherwise, GDB can get confused, because in only knows
about source for LINENO-1 lines. */
input_line -= 1;
+#endif
interface_unknown = 1;
interface_only = 0;
timevar_push (TV_VARCONST);
emit_support_tinfos ();
-
+
do
{
tree t;
/* If there are templates that we've put off instantiating, do
them now. */
instantiate_pending_templates ();
+ ggc_collect ();
/* Write out virtual tables as required. Note that writing out
the virtual table for a template class may cause the
them to the beginning of the array, then get rid of the
leftovers. */
n_new = VARRAY_ACTIVE_SIZE (unemitted_tinfo_decls) - n_old;
- memmove (&VARRAY_TREE (unemitted_tinfo_decls, 0),
- &VARRAY_TREE (unemitted_tinfo_decls, n_old),
- n_new * sizeof (tree));
+ if (n_new)
+ memmove (&VARRAY_TREE (unemitted_tinfo_decls, 0),
+ &VARRAY_TREE (unemitted_tinfo_decls, n_old),
+ n_new * sizeof (tree));
memset (&VARRAY_TREE (unemitted_tinfo_decls, n_new),
- 0,
- n_old * sizeof (tree));
+ 0, n_old * sizeof (tree));
VARRAY_ACTIVE_SIZE (unemitted_tinfo_decls) = n_new;
/* The list of objects with static storage duration is built up
instantiations, etc. */
reconsider = true;
ssdf_count++;
+#ifdef USE_MAPPED_LOCATION
+ /* ??? */
+#else
locus.line++;
+#endif
}
for (i = 0; i < deferred_fns_used; ++i)
{
tree decl = VARRAY_TREE (deferred_fns, i);
+ if (! DECL_DECLARED_INLINE_P (decl) || ! TREE_USED (decl))
+ abort ();
+
/* Does it need synthesizing? */
if (DECL_ARTIFICIAL (decl) && ! DECL_INITIAL (decl)
&& TREE_USED (decl)
reconsider = true;
}
- /* If the function has no body, avoid calling
- import_export_decl. On a system without weak symbols,
- calling import_export_decl will make an inline template
- instantiation "static", which will result in errors about
- the use of undefined functions if there is no body for
- the function. */
if (!DECL_SAVED_TREE (decl))
continue;
gotten around to synthesizing yet.) */
if (!DECL_EXTERNAL (decl)
&& DECL_NEEDED_P (decl)
- && DECL_SAVED_TREE (decl)
&& !TREE_ASM_WRITTEN (decl)
&& (!flag_unit_at_a_time
|| !cgraph_node (decl)->local.finalized))
for (i = 0; i < pending_statics_used; ++i)
{
tree decl = VARRAY_TREE (pending_statics, i);
- if (TREE_ASM_WRITTEN (decl))
+ if (var_finalized_p (decl))
continue;
import_export_decl (decl);
if (DECL_NOT_REALLY_EXTERN (decl) && ! DECL_IN_AGGR_P (decl))
&& wrapup_global_declarations (&VARRAY_TREE (pending_statics, 0),
pending_statics_used))
reconsider = true;
+
+ if (cgraph_assemble_pending_functions ())
+ reconsider = true;
}
while (reconsider);
{
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)))
+ if (!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);
/* This symbol is effectively an "extern" declaration now.
cgraph_optimize ();
}
+ /* Emit mudflap static registration function. This must be done
+ after all the user functions have been expanded. */
+ if (flag_mudflap)
+ mudflap_finish_file ();
+
/* Now, issue warnings about static, but not defined, functions,
etc., and emit debugging information. */
walk_namespaces (wrapup_globals_for_namespace, /*data=*/&reconsider);
to a file. */
{
int flags;
- FILE *stream = dump_begin (TDI_all, &flags);
+ FILE *stream = dump_begin (TDI_tu, &flags);
if (stream)
{
dump_node (global_namespace, flags & ~TDF_SLIM, stream);
- dump_end (TDI_all, stream);
+ dump_end (TDI_tu, stream);
}
}
dump_time_statistics ();
}
input_location = locus;
+
+#ifdef ENABLE_CHECKING
+ validate_conversion_obstack ();
+#endif /* ENABLE_CHECKING */
}
-/* FN is an OFFSET_REF indicating the function to call in parse-tree
- form; it has not yet been semantically analyzed. ARGS are the
- arguments to the function. They have already been semantically
- analzyed. */
+/* FN is an OFFSET_REF, DOTSTAR_EXPR or MEMBER_REF indicating the
+ function to call in parse-tree form; it has not yet been
+ semantically analyzed. ARGS are the arguments to the function.
+ They have already been semantically analyzed. */
tree
build_offset_ref_call_from_tree (tree fn, tree args)
{
- tree object_addr;
tree orig_fn;
tree orig_args;
tree expr;
+ tree object;
orig_fn = fn;
orig_args = args;
+ object = TREE_OPERAND (fn, 0);
if (processing_template_decl)
{
- tree object;
- tree object_type;
-
my_friendly_assert (TREE_CODE (fn) == DOTSTAR_EXPR
|| TREE_CODE (fn) == MEMBER_REF,
20030708);
if (type_dependent_expression_p (fn)
|| any_type_dependent_arguments_p (args))
- return build_min_nt (CALL_EXPR, fn, args);
+ return build_min_nt (CALL_EXPR, fn, args, NULL_TREE);
/* Transform the arguments and add the implicit "this"
parameter. That must be done before the FN is transformed
because we depend on the form of FN. */
args = build_non_dependent_args (args);
- object_type = TREE_TYPE (TREE_OPERAND (fn, 0));
if (TREE_CODE (fn) == DOTSTAR_EXPR)
- object_type = build_pointer_type (non_reference (object_type));
- object = build (NON_DEPENDENT_EXPR, object_type);
+ object = build_unary_op (ADDR_EXPR, object, 0);
+ object = build_non_dependent_expr (object);
args = tree_cons (NULL_TREE, object, args);
/* Now that the arguments are done, transform FN. */
fn = build_non_dependent_expr (fn);
void B::g() { (this->*p)(); } */
if (TREE_CODE (fn) == OFFSET_REF)
{
- object_addr = build_unary_op (ADDR_EXPR, TREE_OPERAND (fn, 0), 0);
+ tree object_addr = build_unary_op (ADDR_EXPR, object, 0);
fn = TREE_OPERAND (fn, 1);
fn = get_member_function_from_ptrfunc (&object_addr, fn);
args = tree_cons (NULL_TREE, object_addr, args);
expr = build_function_call (fn, args);
if (processing_template_decl && expr != error_mark_node)
- return build_min (CALL_EXPR, TREE_TYPE (expr), orig_fn, orig_args);
+ return build_min_non_dep (CALL_EXPR, expr, orig_fn, orig_args, NULL_TREE);
return expr;
}
-
-/* Returns true if ROOT (a namespace, class, or function) encloses
- CHILD. CHILD may be either a class type or a namespace. */
-
-bool
-is_ancestor (tree root, tree child)
-{
- 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
- || CLASS_TYPE_P (child)),
- 20030307);
- /* The global namespace encloses everything. */
- if (root == global_namespace)
- return true;
- while (true)
+void
+check_default_args (tree x)
+{
+ tree arg = TYPE_ARG_TYPES (TREE_TYPE (x));
+ bool saw_def = false;
+ int i = 0 - (TREE_CODE (TREE_TYPE (x)) == METHOD_TYPE);
+ for (; arg && arg != void_list_node; arg = TREE_CHAIN (arg), ++i)
{
- /* 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);
+ if (TREE_PURPOSE (arg))
+ saw_def = true;
+ else if (saw_def)
+ {
+ cp_error_at ("default argument missing for parameter %P of `%+#D'",
+ i, x);
+ break;
+ }
}
}
-
-
-/* Return the namespace that is the common ancestor
- of two given namespaces. */
-tree
-namespace_ancestor (tree ns1, tree ns2)
+void
+mark_used (tree decl)
{
- 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));
-}
+ TREE_USED (decl) = 1;
+ if (processing_template_decl || skip_evaluation)
+ return;
-/* Insert USED into the using list of USER. Set INDIRECT_flag if this
- directive is not directly from the source. Also find the common
- ancestor and let our users know about the new namespace */
-static void
-add_using_namespace (tree user, tree used, bool indirect)
-{
- tree t;
- timevar_push (TV_NAME_LOOKUP);
- /* Using oneself is a no-op. */
- if (user == used)
+ if (TREE_CODE (decl) == FUNCTION_DECL && DECL_DECLARED_INLINE_P (decl)
+ && !TREE_ASM_WRITTEN (decl))
+ /* Remember it, so we can check it was defined. */
{
- timevar_pop (TV_NAME_LOOKUP);
- return;
+ if (DECL_DEFERRED_FN (decl))
+ return;
+ DECL_DEFERRED_FN (decl) = 1;
+ DECL_DEFER_OUTPUT (decl) = 1;
+ if (!deferred_fns)
+ VARRAY_TREE_INIT (deferred_fns, 32, "deferred_fns");
+
+ VARRAY_PUSH_TREE (deferred_fns, decl);
}
- my_friendly_assert (TREE_CODE (user) == NAMESPACE_DECL, 380);
- my_friendly_assert (TREE_CODE (used) == NAMESPACE_DECL, 380);
- /* Check if we already have this. */
- t = purpose_member (used, DECL_NAMESPACE_USING (user));
- if (t != NULL_TREE)
+
+ assemble_external (decl);
+
+ /* Is it a synthesized method that needs to be synthesized? */
+ if (TREE_CODE (decl) == FUNCTION_DECL
+ && DECL_NONSTATIC_MEMBER_FUNCTION_P (decl)
+ && DECL_ARTIFICIAL (decl)
+ && !DECL_THUNK_P (decl)
+ && ! DECL_INITIAL (decl)
+ /* Kludge: don't synthesize for default args. */
+ && current_function_decl)
{
- if (!indirect)
- /* Promote to direct usage. */
- TREE_INDIRECT_USING (t) = 0;
- timevar_pop (TV_NAME_LOOKUP);
+ synthesize_method (decl);
+ /* If we've already synthesized the method we don't need to
+ instantiate it, so we can return right away. */
return;
}
- /* Add used to the user's using list. */
- DECL_NAMESPACE_USING (user)
- = tree_cons (used, namespace_ancestor (user, used),
- DECL_NAMESPACE_USING (user));
-
- TREE_INDIRECT_USING (DECL_NAMESPACE_USING (user)) = indirect;
-
- /* Add user to the used's users list. */
- DECL_NAMESPACE_USERS (used)
- = tree_cons (user, 0, DECL_NAMESPACE_USERS (used));
-
- /* Recursively add all namespaces used. */
- for (t = DECL_NAMESPACE_USING (used); t; t = TREE_CHAIN (t))
- /* indirect usage */
- add_using_namespace (user, TREE_PURPOSE (t), 1);
-
- /* 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
- duplicates. The first list becomes the tail of the result.
-
- The algorithm is O(n^2). We could get this down to O(n log n) by
- doing a sort on the addresses of the functions, if that becomes
- necessary. */
-
-static tree
-merge_functions (tree s1, tree s2)
-{
- for (; s2; s2 = OVL_NEXT (s2))
+ /* If this is a function or variable that is an instance of some
+ template, we now know that we will need to actually do the
+ instantiation. We check that DECL is not an explicit
+ instantiation because that is not checked in instantiate_decl. */
+ if ((DECL_NON_THUNK_FUNCTION_P (decl) || TREE_CODE (decl) == VAR_DECL)
+ && DECL_LANG_SPECIFIC (decl) && DECL_TEMPLATE_INFO (decl)
+ && (!DECL_EXPLICIT_INSTANTIATION (decl)
+ || (TREE_CODE (decl) == FUNCTION_DECL
+ && DECL_INLINE (DECL_TEMPLATE_RESULT
+ (template_for_substitution (decl))))))
{
- tree fn2 = OVL_CURRENT (s2);
- tree fns1;
+ bool defer;
- for (fns1 = s1; fns1; fns1 = OVL_NEXT (fns1))
- {
- tree fn1 = OVL_CURRENT (fns1);
-
- /* If the function from S2 is already in S1, there is no
- need to add it again. For `extern "C"' functions, we
- might have two FUNCTION_DECLs for the same function, in
- different namespaces; again, we only need one of them. */
- if (fn1 == fn2
- || (DECL_EXTERN_C_P (fn1) && DECL_EXTERN_C_P (fn2)
- && DECL_NAME (fn1) == DECL_NAME (fn2)))
- break;
- }
-
- /* If we exhausted all of the functions in S1, FN2 is new. */
- if (!fns1)
- s1 = build_overload (fn2, s1);
- }
- return s1;
-}
+ /* Normally, we put off instantiating functions in order to
+ improve compile times. Maintaining a stack of active
+ functions is expensive, and the inliner knows to
+ instantiate any functions it might need.
-/* This should return an error not all definitions define functions.
- It is not an error if we find two functions with exactly the
- same signature, only if these are selected in overload resolution.
- old is the current set of bindings, new the freshly-found binding.
- XXX Do we want to give *all* candidates in case of ambiguity?
- XXX In what way should I treat extern declarations?
- XXX I don't want to repeat the entire duplicate_decls here */
+ However, if instantiating this function might help us mark
+ the current function TREE_NOTHROW, we go ahead and
+ instantiate it now.
+
+ This is not needed for unit-at-a-time since we reorder the functions
+ in topological order anyway.
+ */
+ defer = (!flag_exceptions
+ || flag_unit_at_a_time
+ || !optimize
+ || TREE_CODE (decl) != FUNCTION_DECL
+ /* If the called function can't throw, we don't need to
+ generate its body to find that out. */
+ || TREE_NOTHROW (decl)
+ || !cfun
+ || !current_function_decl
+ /* If we already know the current function can't throw,
+ then we don't need to work hard to prove it. */
+ || TREE_NOTHROW (current_function_decl)
+ /* If we already know that the current function *can*
+ throw, there's no point in gathering more
+ information. */
+ || cp_function_chain->can_throw);
-static cxx_binding *
-ambiguous_decl (tree name, cxx_binding *old, cxx_binding *new, int flags)
-{
- tree val, type;
- my_friendly_assert (old != NULL, 393);
- /* Copy the value. */
- val = BINDING_VALUE (new);
- if (val)
- switch (TREE_CODE (val))
- {
- case TEMPLATE_DECL:
- /* If we expect types or namespaces, and not templates,
- or this is not a template class. */
- if (LOOKUP_QUALIFIERS_ONLY (flags)
- && !DECL_CLASS_TEMPLATE_P (val))
- val = NULL_TREE;
- break;
- case TYPE_DECL:
- if (LOOKUP_NAMESPACES_ONLY (flags))
- val = NULL_TREE;
- break;
- case NAMESPACE_DECL:
- if (LOOKUP_TYPES_ONLY (flags))
- val = NULL_TREE;
- break;
- case FUNCTION_DECL:
- /* Ignore built-in functions that are still anticipated. */
- if (LOOKUP_QUALIFIERS_ONLY (flags) || DECL_ANTICIPATED (val))
- val = NULL_TREE;
- break;
- default:
- if (LOOKUP_QUALIFIERS_ONLY (flags))
- val = NULL_TREE;
- }
-
- if (!BINDING_VALUE (old))
- BINDING_VALUE (old) = val;
- else if (val && val != BINDING_VALUE (old))
- {
- if (is_overloaded_fn (BINDING_VALUE (old)) && is_overloaded_fn (val))
- BINDING_VALUE (old) = merge_functions (BINDING_VALUE (old), val);
- else
- {
- /* Some declarations are functions, some are not. */
- if (flags & LOOKUP_COMPLAIN)
- {
- /* If we've already given this error for this lookup,
- BINDING_VALUE (old) is error_mark_node, so let's not
- repeat ourselves. */
- if (BINDING_VALUE (old) != error_mark_node)
- {
- error ("use of `%D' is ambiguous", name);
- cp_error_at (" first declared as `%#D' here",
- BINDING_VALUE (old));
- }
- cp_error_at (" also declared as `%#D' here", val);
- }
- BINDING_VALUE (old) = error_mark_node;
- }
+ instantiate_decl (decl, defer, /*undefined_ok=*/0);
}
- /* ... and copy the type. */
- type = BINDING_TYPE (new);
- if (LOOKUP_NAMESPACES_ONLY (flags))
- type = NULL_TREE;
- if (!BINDING_TYPE (old))
- BINDING_TYPE (old) = type;
- else if (type && BINDING_TYPE (old) != type)
- {
- if (flags & LOOKUP_COMPLAIN)
- {
- error ("`%D' denotes an ambiguous type",name);
- error ("%H first type here",
- &DECL_SOURCE_LOCATION (TYPE_MAIN_DECL (BINDING_TYPE (old))));
- error ("%H other type here",
- &DECL_SOURCE_LOCATION (TYPE_MAIN_DECL (type)));
- }
- }
- return old;
-}
-
-/* Subroutine of unualified_namespace_lookup:
- Add the bindings of NAME in used namespaces to VAL.
- We are currently looking for names in namespace SCOPE, so we
- look through USINGS for using-directives of namespaces
- which have SCOPE as a common ancestor with the current scope.
- Returns false on errors. */
-
-bool
-lookup_using_namespace (tree name, cxx_binding *val, tree usings, tree scope,
- int flags, tree *spacesp)
-{
- tree iter;
- 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))
- if (TREE_VALUE (iter) == scope)
- {
- tree used = ORIGINAL_NAMESPACE (TREE_PURPOSE (iter));
- cxx_binding *val1 =
- cxx_scope_find_binding_for_name (NAMESPACE_LEVEL (used), name);
- if (spacesp)
- *spacesp = tree_cons (used, NULL_TREE, *spacesp);
- /* Resolve ambiguities. */
- if (val1)
- val = ambiguous_decl (name, val, val1, flags);
- }
- 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 cxx_binding *RESULT,
- or false on error. */
-
-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->value != error_mark_node)
- {
- cxx_binding *binding =
- cxx_scope_find_binding_for_name (NAMESPACE_LEVEL (scope), name);
- seen = tree_cons (scope, NULL_TREE, seen);
- if (binding)
- result = ambiguous_decl (name, result, binding, flags);
- if (!BINDING_VALUE (result) && !BINDING_TYPE (result))
- /* Consider using directives. */
- for (usings = DECL_NAMESPACE_USING (scope); usings;
- usings = TREE_CHAIN (usings))
- /* If this was a real directive, and we have not seen it. */
- if (!TREE_INDIRECT_USING (usings)
- && !purpose_member (TREE_PURPOSE (usings), seen))
- todo = tree_cons (TREE_PURPOSE (usings), NULL_TREE, todo);
- if (todo)
- {
- scope = TREE_PURPOSE (todo);
- todo = TREE_CHAIN (todo);
- }
- else
- scope = NULL_TREE; /* If there never was a todo list. */
- }
- POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, result->value != error_mark_node);
-}
-
-/* [namespace.memdef]/2 */
-
-/* Set the context of a declaration to scope. Complain if we are not
- outside scope. */
-
-void
-set_decl_namespace (tree decl, tree scope, bool friendp)
-{
- tree old;
-
- /* Get rid of namespace aliases. */
- scope = ORIGINAL_NAMESPACE (scope);
-
- /* It is ok for friends to be qualified in parallel space. */
- 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);
- if (scope != current_namespace)
- {
- /* See whether this has been declared in the namespace. */
- old = namespace_binding (DECL_NAME (decl), scope);
- if (!old)
- /* No old declaration at all. */
- goto complain;
- /* A template can be explicitly specialized in any namespace. */
- if (processing_explicit_instantiation)
- return;
- if (!is_overloaded_fn (decl))
- /* Don't compare non-function decls with decls_match here,
- since it can't check for the correct constness at this
- point. pushdecl will find those errors later. */
- return;
- /* Since decl is a function, old should contain a function decl. */
- if (!is_overloaded_fn (old))
- goto complain;
- if (processing_template_decl || processing_specialization)
- /* We have not yet called push_template_decl to turn a
- FUNCTION_DECL into a TEMPLATE_DECL, so the declarations
- won't match. But, we'll check later, when we construct the
- template. */
- return;
- if (is_overloaded_fn (old))
- {
- for (; old; old = OVL_NEXT (old))
- if (decls_match (decl, OVL_CURRENT (old)))
- return;
- }
- else
- if (decls_match (decl, old))
- return;
- }
- else
- return;
- complain:
- error ("`%D' should have been declared inside `%D'",
- decl, scope);
-}
-
-/* Compute the namespace where a declaration is defined. */
-
-static tree
-decl_namespace (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)
- POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, decl);
- if (TYPE_P (decl))
- decl = TYPE_STUB_DECL (decl);
- my_friendly_assert (DECL_P (decl), 390);
- }
-
- POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, global_namespace);
-}
-
-/* Return the namespace where the current declaration is declared. */
-
-tree
-current_decl_namespace (void)
-{
- tree result;
- /* If we have been pushed into a different namespace, use it. */
- if (decl_namespace_list)
- return TREE_PURPOSE (decl_namespace_list);
-
- if (current_class_type)
- result = decl_namespace (TYPE_STUB_DECL (current_class_type));
- else if (current_function_decl)
- result = decl_namespace (current_function_decl);
- else
- result = current_namespace;
- return result;
-}
-
-/* Temporarily set the namespace for the current declaration. */
-
-void
-push_decl_namespace (tree decl)
-{
- if (TREE_CODE (decl) != NAMESPACE_DECL)
- decl = decl_namespace (decl);
- decl_namespace_list = tree_cons (ORIGINAL_NAMESPACE (decl),
- NULL_TREE, decl_namespace_list);
-}
-
-void
-pop_decl_namespace (void)
-{
- decl_namespace_list = TREE_CHAIN (decl_namespace_list);
-}
-
-/* Enter a class or namespace scope. */
-
-void
-push_scope (tree t)
-{
- if (TREE_CODE (t) == NAMESPACE_DECL)
- push_decl_namespace (t);
- else if CLASS_TYPE_P (t)
- push_nested_class (t);
-}
-
-/* Leave scope pushed by push_scope. */
-
-void
-pop_scope (tree t)
-{
- if (TREE_CODE (t) == NAMESPACE_DECL)
- pop_decl_namespace ();
- else if CLASS_TYPE_P (t)
- pop_nested_class ();
-}
-
-/* [basic.lookup.koenig] */
-/* A nonzero return value in the functions below indicates an error. */
-
-struct arg_lookup
-{
- tree name;
- tree namespaces;
- tree classes;
- tree functions;
-};
-
-static bool arg_assoc (struct arg_lookup*, tree);
-static bool arg_assoc_args (struct arg_lookup*, tree);
-static bool arg_assoc_type (struct arg_lookup*, tree);
-static bool add_function (struct arg_lookup *, tree);
-static bool arg_assoc_namespace (struct arg_lookup *, tree);
-static bool arg_assoc_class (struct arg_lookup *, tree);
-static bool arg_assoc_template_arg (struct arg_lookup*, tree);
-
-/* Add a function to the lookup structure.
- Returns true on error. */
-
-static bool
-add_function (struct arg_lookup *k, tree fn)
-{
- /* We used to check here to see if the function was already in the list,
- but that's O(n^2), which is just too expensive for function lookup.
- Now we deal with the occasional duplicate in joust. In doing this, we
- assume that the number of duplicates will be small compared to the
- total number of functions being compared, which should usually be the
- case. */
-
- /* We must find only functions, or exactly one non-function. */
- if (!k->functions)
- k->functions = fn;
- else if (is_overloaded_fn (k->functions) && is_overloaded_fn (fn))
- k->functions = build_overload (fn, k->functions);
- else
- {
- tree f1 = OVL_CURRENT (k->functions);
- tree f2 = fn;
- if (is_overloaded_fn (f1))
- {
- fn = f1; f1 = f2; f2 = fn;
- }
- cp_error_at ("`%D' is not a function,", f1);
- cp_error_at (" conflict with `%D'", f2);
- error (" in call to `%D'", k->name);
- return true;
- }
-
- return false;
-}
-
-/* Add functions of a namespace to the lookup structure.
- Returns true on error. */
-
-static bool
-arg_assoc_namespace (struct arg_lookup *k, tree scope)
-{
- tree value;
-
- if (purpose_member (scope, k->namespaces))
- return 0;
- k->namespaces = tree_cons (scope, NULL_TREE, k->namespaces);
-
- value = namespace_binding (k->name, scope);
- if (!value)
- return false;
-
- for (; value; value = OVL_NEXT (value))
- if (add_function (k, OVL_CURRENT (value)))
- return true;
-
- return false;
-}
-
-/* Adds everything associated with a template argument to the lookup
- structure. Returns true on error. */
-
-static bool
-arg_assoc_template_arg (struct arg_lookup *k, tree arg)
-{
- /* [basic.lookup.koenig]
-
- If T is a template-id, its associated namespaces and classes are
- ... the namespaces and classes associated with the types of the
- template arguments provided for template type parameters
- (excluding template template parameters); the namespaces in which
- any template template arguments are defined; and the classes in
- which any member templates used as template template arguments
- are defined. [Note: non-type template arguments do not
- contribute to the set of associated namespaces. ] */
-
- /* Consider first template template arguments. */
- if (TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM
- || TREE_CODE (arg) == UNBOUND_CLASS_TEMPLATE)
- return false;
- else if (TREE_CODE (arg) == TEMPLATE_DECL)
- {
- tree ctx = CP_DECL_CONTEXT (arg);
-
- /* It's not a member template. */
- if (TREE_CODE (ctx) == NAMESPACE_DECL)
- return arg_assoc_namespace (k, ctx);
- /* Otherwise, it must be member template. */
- else
- return arg_assoc_class (k, ctx);
- }
- /* It's not a template template argument, but it is a type template
- argument. */
- else if (TYPE_P (arg))
- return arg_assoc_type (k, arg);
- /* It's a non-type template argument. */
- else
- return false;
-}
-
-/* Adds everything associated with class to the lookup structure.
- Returns true on error. */
-
-static bool
-arg_assoc_class (struct arg_lookup *k, tree type)
-{
- tree list, friends, context;
- int i;
-
- /* Backend build structures, such as __builtin_va_list, aren't
- affected by all this. */
- if (!CLASS_TYPE_P (type))
- return false;
-
- if (purpose_member (type, k->classes))
- return false;
- k->classes = tree_cons (type, NULL_TREE, k->classes);
-
- context = decl_namespace (TYPE_MAIN_DECL (type));
- if (arg_assoc_namespace (k, context))
- return true;
-
- /* Process baseclasses. */
- for (i = 0; i < CLASSTYPE_N_BASECLASSES (type); i++)
- if (arg_assoc_class (k, TYPE_BINFO_BASETYPE (type, i)))
- return true;
-
- /* Process friends. */
- for (list = DECL_FRIENDLIST (TYPE_MAIN_DECL (type)); list;
- list = TREE_CHAIN (list))
- if (k->name == FRIEND_NAME (list))
- for (friends = FRIEND_DECLS (list); friends;
- friends = TREE_CHAIN (friends))
- /* Only interested in global functions with potentially hidden
- (i.e. unqualified) declarations. */
- if (CP_DECL_CONTEXT (TREE_VALUE (friends)) == context)
- if (add_function (k, TREE_VALUE (friends)))
- return true;
-
- /* Process template arguments. */
- if (CLASSTYPE_TEMPLATE_INFO (type))
- {
- list = INNERMOST_TEMPLATE_ARGS (CLASSTYPE_TI_ARGS (type));
- for (i = 0; i < TREE_VEC_LENGTH (list); ++i)
- arg_assoc_template_arg (k, TREE_VEC_ELT (list, i));
- }
-
- return false;
-}
-
-/* Adds everything associated with a given type.
- Returns 1 on error. */
-
-static bool
-arg_assoc_type (struct arg_lookup *k, tree type)
-{
- /* As we do not get the type of non-type dependent expressions
- right, we can end up with such things without a type. */
- if (!type)
- return false;
-
- if (TYPE_PTRMEM_P (type))
- {
- /* Pointer to member: associate class type and value type. */
- if (arg_assoc_type (k, TYPE_PTRMEM_CLASS_TYPE (type)))
- return true;
- return arg_assoc_type (k, TYPE_PTRMEM_POINTED_TO_TYPE (type));
- }
- else switch (TREE_CODE (type))
- {
- case ERROR_MARK:
- return false;
- case VOID_TYPE:
- case INTEGER_TYPE:
- case REAL_TYPE:
- case COMPLEX_TYPE:
- case VECTOR_TYPE:
- case CHAR_TYPE:
- case BOOLEAN_TYPE:
- return false;
- case RECORD_TYPE:
- if (TYPE_PTRMEMFUNC_P (type))
- return arg_assoc_type (k, TYPE_PTRMEMFUNC_FN_TYPE (type));
- return arg_assoc_class (k, type);
- case POINTER_TYPE:
- case REFERENCE_TYPE:
- case ARRAY_TYPE:
- return arg_assoc_type (k, TREE_TYPE (type));
- case UNION_TYPE:
- case ENUMERAL_TYPE:
- return arg_assoc_namespace (k, decl_namespace (TYPE_MAIN_DECL (type)));
- case METHOD_TYPE:
- /* The basetype is referenced in the first arg type, so just
- fall through. */
- case FUNCTION_TYPE:
- /* Associate the parameter types. */
- if (arg_assoc_args (k, TYPE_ARG_TYPES (type)))
- return true;
- /* Associate the return type. */
- return arg_assoc_type (k, TREE_TYPE (type));
- case TEMPLATE_TYPE_PARM:
- case BOUND_TEMPLATE_TEMPLATE_PARM:
- return false;
- case TYPENAME_TYPE:
- return false;
- case LANG_TYPE:
- if (type == unknown_type_node)
- return false;
- /* else fall through */
- default:
- abort ();
- }
- return false;
-}
-
-/* Adds everything associated with arguments. Returns true on error. */
-
-static bool
-arg_assoc_args (struct arg_lookup *k, tree args)
-{
- for (; args; args = TREE_CHAIN (args))
- if (arg_assoc (k, TREE_VALUE (args)))
- return true;
- return false;
-}
-
-/* Adds everything associated with a given tree_node. Returns 1 on error. */
-
-static bool
-arg_assoc (struct arg_lookup *k, tree n)
-{
- if (n == error_mark_node)
- return false;
-
- if (TYPE_P (n))
- return arg_assoc_type (k, n);
-
- if (! type_unknown_p (n))
- return arg_assoc_type (k, TREE_TYPE (n));
-
- if (TREE_CODE (n) == ADDR_EXPR)
- n = TREE_OPERAND (n, 0);
- if (TREE_CODE (n) == COMPONENT_REF)
- n = TREE_OPERAND (n, 1);
- if (TREE_CODE (n) == OFFSET_REF)
- n = TREE_OPERAND (n, 1);
- while (TREE_CODE (n) == TREE_LIST)
- n = TREE_VALUE (n);
- if (TREE_CODE (n) == BASELINK)
- n = BASELINK_FUNCTIONS (n);
-
- if (TREE_CODE (n) == FUNCTION_DECL)
- return arg_assoc_type (k, TREE_TYPE (n));
- if (TREE_CODE (n) == TEMPLATE_ID_EXPR)
- {
- /* [basic.lookup.koenig]
-
- If T is a template-id, its associated namespaces and classes
- are the namespace in which the template is defined; for
- member templates, the member template's class... */
- tree template = TREE_OPERAND (n, 0);
- tree args = TREE_OPERAND (n, 1);
- tree ctx;
- tree arg;
-
- if (TREE_CODE (template) == COMPONENT_REF)
- template = TREE_OPERAND (template, 1);
-
- /* First, the template. There may actually be more than one if
- this is an overloaded function template. But, in that case,
- we only need the first; all the functions will be in the same
- namespace. */
- template = OVL_CURRENT (template);
-
- ctx = CP_DECL_CONTEXT (template);
-
- if (TREE_CODE (ctx) == NAMESPACE_DECL)
- {
- if (arg_assoc_namespace (k, ctx) == 1)
- return true;
- }
- /* It must be a member template. */
- else if (arg_assoc_class (k, ctx) == 1)
- return true;
-
- /* Now the arguments. */
- for (arg = args; arg != NULL_TREE; arg = TREE_CHAIN (arg))
- if (arg_assoc_template_arg (k, TREE_VALUE (arg)) == 1)
- return true;
- }
- else
- {
- my_friendly_assert (TREE_CODE (n) == OVERLOAD, 980715);
-
- for (; n; n = OVL_CHAIN (n))
- if (arg_assoc_type (k, TREE_TYPE (OVL_FUNCTION (n))))
- return true;
- }
-
- return false;
-}
-
-/* Performs Koenig lookup depending on arguments, where fns
- are the functions found in normal lookup. */
-
-tree
-lookup_arg_dependent (tree name, tree fns, tree args)
-{
- struct arg_lookup k;
- tree fn = NULL_TREE;
-
- timevar_push (TV_NAME_LOOKUP);
- k.name = name;
- k.functions = fns;
- k.classes = NULL_TREE;
-
- /* Note that we've already looked at some namespaces during normal
- unqualified lookup, unless we found a decl in function scope. */
- if (fns)
- fn = OVL_CURRENT (fns);
- if (fn && TREE_CODE (fn) == FUNCTION_DECL && DECL_LOCAL_FUNCTION_P (fn))
- k.namespaces = NULL_TREE;
- else
- unqualified_namespace_lookup (name, 0, &k.namespaces);
-
- arg_assoc_args (&k, args);
- POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, k.functions);
-}
-
-/* Process a namespace-alias declaration. */
-
-void
-do_namespace_alias (tree alias, tree namespace)
-{
- if (TREE_CODE (namespace) != NAMESPACE_DECL)
- {
- /* The parser did not find it, so it's not there. */
- error ("unknown namespace `%D'", namespace);
- return;
- }
-
- namespace = ORIGINAL_NAMESPACE (namespace);
-
- /* Build the alias. */
- alias = build_lang_decl (NAMESPACE_DECL, alias, void_type_node);
- DECL_NAMESPACE_ALIAS (alias) = namespace;
- DECL_EXTERNAL (alias) = 1;
- pushdecl (alias);
-}
-
-/* Check a non-member using-declaration. Return the name and scope
- being used, and the USING_DECL, or NULL_TREE on failure. */
-
-static tree
-validate_nonmember_using_decl (tree decl, tree *scope, tree *name)
-{
- *scope = global_namespace;
- *name = NULL_TREE;
-
- if (TREE_CODE (decl) == TEMPLATE_ID_EXPR)
- {
- *name = TREE_OPERAND (decl, 0);
- /* 7.3.3/5
- A using-declaration shall not name a template-id. */
- error ("a using-declaration cannot specify a template-id. Try `using %D'", *name);
- return NULL_TREE;
- }
-
- if (TREE_CODE (decl) == NAMESPACE_DECL)
- {
- error ("namespace `%D' not allowed in using-declaration", decl);
- return NULL_TREE;
- }
-
- if (TREE_CODE (decl) == SCOPE_REF)
- {
- /* It's a nested name with template parameter dependent scope.
- This can only be using-declaration for class member. */
- error ("`%T' is not a namespace", TREE_OPERAND (decl, 0));
- return NULL_TREE;
- }
-
- if (is_overloaded_fn (decl))
- decl = get_first_fn (decl);
-
- my_friendly_assert (DECL_P (decl), 20020908);
-
- if (TREE_CODE (decl) == CONST_DECL)
- /* Enumeration constants to not have DECL_CONTEXT set. */
- *scope = TYPE_CONTEXT (TREE_TYPE (decl));
- else
- *scope = DECL_CONTEXT (decl);
- if (!*scope)
- *scope = global_namespace;
-
- /* [namespace.udecl]
- A using-declaration for a class member shall be a
- member-declaration. */
- if (TYPE_P (*scope))
- {
- error ("`%T' is not a namespace", *scope);
- return NULL_TREE;
- }
- *name = DECL_NAME (decl);
- /* Make a USING_DECL. */
- return push_using_decl (*scope, *name);
-}
-
-/* Process local and global using-declarations. */
-
-static void
-do_nonmember_using_decl (tree scope, tree name, tree oldval, tree oldtype,
- tree *newval, tree *newtype)
-{
- cxx_binding decls;
-
- *newval = *newtype = NULL_TREE;
- cxx_binding_clear (&decls);
- if (!qualified_lookup_using_namespace (name, scope, &decls, 0))
- /* Lookup error */
- return;
-
- if (!decls.value && !decls.type)
- {
- error ("`%D' not declared", name);
- return;
- }
-
- /* Check for using functions. */
- if (decls.value && is_overloaded_fn (decls.value))
- {
- tree tmp, tmp1;
-
- if (oldval && !is_overloaded_fn (oldval))
- {
- if (!DECL_IMPLICIT_TYPEDEF_P (oldval))
- error ("`%D' is already declared in this scope", name);
- oldval = NULL_TREE;
- }
-
- *newval = oldval;
- for (tmp = decls.value; tmp; tmp = OVL_NEXT (tmp))
- {
- tree new_fn = OVL_CURRENT (tmp);
-
- /* [namespace.udecl]
-
- If a function declaration in namespace scope or block
- scope has the same name and the same parameter types as a
- function introduced by a using declaration the program is
- ill-formed. */
- for (tmp1 = oldval; tmp1; tmp1 = OVL_NEXT (tmp1))
- {
- tree old_fn = OVL_CURRENT (tmp1);
-
- if (new_fn == old_fn)
- /* The function already exists in the current namespace. */
- break;
- else if (OVL_USED (tmp1))
- continue; /* this is a using decl */
- else if (compparms (TYPE_ARG_TYPES (TREE_TYPE (new_fn)),
- TYPE_ARG_TYPES (TREE_TYPE (old_fn))))
- {
- /* 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))
- {
- /* 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. */
- }
- }
-
- /* If we broke out of the loop, there's no reason to add
- this function to the using declarations for this
- scope. */
- if (tmp1)
- continue;
-
- *newval = build_overload (OVL_CURRENT (tmp), *newval);
- if (TREE_CODE (*newval) != OVERLOAD)
- *newval = ovl_cons (*newval, NULL_TREE);
- OVL_USED (*newval) = 1;
- }
- }
- else
- {
- *newval = decls.value;
- if (oldval && !decls_match (*newval, oldval))
- error ("`%D' is already declared in this scope", name);
- }
-
- *newtype = decls.type;
- if (oldtype && *newtype && !same_type_p (oldtype, *newtype))
- {
- error ("using declaration `%D' introduced ambiguous type `%T'",
- name, oldtype);
- return;
- }
-}
-
-/* Process a using-declaration not appearing in class or local scope. */
-
-void
-do_toplevel_using_decl (tree decl)
-{
- tree scope, name;
- tree oldval, oldtype, newval, newtype;
- cxx_binding *binding;
-
- decl = validate_nonmember_using_decl (decl, &scope, &name);
- if (decl == NULL_TREE)
- return;
-
- binding = binding_for_name (NAMESPACE_LEVEL (current_namespace), name);
-
- oldval = BINDING_VALUE (binding);
- oldtype = BINDING_TYPE (binding);
-
- do_nonmember_using_decl (scope, name, oldval, oldtype, &newval, &newtype);
-
- /* Copy declarations found. */
- if (newval)
- BINDING_VALUE (binding) = newval;
- if (newtype)
- BINDING_TYPE (binding) = newtype;
- return;
-}
-
-/* Process a using-declaration at function scope. */
-
-void
-do_local_using_decl (tree decl)
-{
- tree scope, name;
- tree oldval, oldtype, newval, newtype;
-
- decl = validate_nonmember_using_decl (decl, &scope, &name);
- if (decl == NULL_TREE)
- return;
-
- if (building_stmt_tree ()
- && at_function_scope_p ())
- add_decl_stmt (decl);
-
- oldval = lookup_name_current_level (name);
- oldtype = lookup_type_current_level (name);
-
- do_nonmember_using_decl (scope, name, oldval, oldtype, &newval, &newtype);
-
- if (newval)
- {
- if (is_overloaded_fn (newval))
- {
- tree fn, term;
-
- /* We only need to push declarations for those functions
- that were not already bound in the current level.
- The old value might be NULL_TREE, it might be a single
- function, or an OVERLOAD. */
- if (oldval && TREE_CODE (oldval) == OVERLOAD)
- term = OVL_FUNCTION (oldval);
- else
- term = oldval;
- for (fn = newval; fn && OVL_CURRENT (fn) != term;
- fn = OVL_NEXT (fn))
- push_overloaded_decl (OVL_CURRENT (fn),
- PUSH_LOCAL | PUSH_USING);
- }
- else
- push_local_binding (name, newval, PUSH_USING);
- }
- if (newtype)
- set_identifier_type_value (name, newtype);
-}
-
-tree
-do_class_using_decl (tree decl)
-{
- tree name, value;
-
- if (TREE_CODE (decl) != SCOPE_REF
- || !TREE_OPERAND (decl, 0)
- || !TYPE_P (TREE_OPERAND (decl, 0)))
- {
- error ("using-declaration for non-member at class scope");
- return NULL_TREE;
- }
- name = TREE_OPERAND (decl, 1);
- if (TREE_CODE (name) == BIT_NOT_EXPR)
- {
- error ("using-declaration for destructor");
- return NULL_TREE;
- }
- else if (TREE_CODE (name) == TEMPLATE_ID_EXPR)
- {
- name = TREE_OPERAND (name, 0);
- error ("a using-declaration cannot specify a template-id. Try `using %T::%D'", TREE_OPERAND (decl, 0), name);
- return NULL_TREE;
- }
- if (TREE_CODE (name) == TYPE_DECL)
- {
- tree type = TREE_TYPE (name);
- if (CLASSTYPE_USE_TEMPLATE (TREE_TYPE (name)))
- {
- name = DECL_NAME (CLASSTYPE_TI_TEMPLATE (type));
- error ("a using-declaration cannot specify a template-id.");
- return NULL_TREE;
- }
- name = DECL_NAME (name);
- }
- else if (TREE_CODE (name) == TEMPLATE_DECL)
- name = DECL_NAME (name);
- else if (BASELINK_P (name))
- {
- tree fns;
-
- fns = BASELINK_FUNCTIONS (name);
- if (TREE_CODE (fns) == TEMPLATE_ID_EXPR)
- {
- fns = TREE_OPERAND (fns, 0);
- error ("a using-declaration cannot specify a template-id. Try `using %T::%D'",
- BASELINK_ACCESS_BINFO (name),
- DECL_NAME (get_first_fn (fns)));
- }
- name = DECL_NAME (get_first_fn (fns));
- }
-
- my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 980716);
-
- value = build_lang_decl (USING_DECL, name, void_type_node);
- DECL_INITIAL (value) = TREE_OPERAND (decl, 0);
- return value;
-}
-
-/* Process a using-directive. */
-
-void
-do_using_directive (tree namespace)
-{
- if (building_stmt_tree ())
- add_stmt (build_stmt (USING_STMT, namespace));
-
- /* using namespace A::B::C; */
- if (TREE_CODE (namespace) == SCOPE_REF)
- namespace = TREE_OPERAND (namespace, 1);
- if (TREE_CODE (namespace) == IDENTIFIER_NODE)
- {
- /* Lookup in lexer did not find a namespace. */
- if (!processing_template_decl)
- error ("namespace `%T' undeclared", namespace);
- return;
- }
- if (TREE_CODE (namespace) != NAMESPACE_DECL)
- {
- if (!processing_template_decl)
- error ("`%T' is not a namespace", namespace);
- return;
- }
- namespace = ORIGINAL_NAMESPACE (namespace);
- if (!toplevel_bindings_p ())
- push_using_directive (namespace);
- else
- /* direct usage */
- add_using_namespace (current_namespace, namespace, 0);
-}
-
-void
-check_default_args (tree x)
-{
- tree arg = TYPE_ARG_TYPES (TREE_TYPE (x));
- bool saw_def = false;
- int i = 0 - (TREE_CODE (TREE_TYPE (x)) == METHOD_TYPE);
- for (; arg && arg != void_list_node; arg = TREE_CHAIN (arg), ++i)
- {
- if (TREE_PURPOSE (arg))
- saw_def = true;
- else if (saw_def)
- {
- cp_error_at ("default argument missing for parameter %P of `%+#D'",
- i, x);
- break;
- }
- }
-}
-
-void
-mark_used (tree decl)
-{
- TREE_USED (decl) = 1;
- if (processing_template_decl || skip_evaluation)
- 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);
-
- assemble_external (decl);
-
- /* Is it a synthesized method that needs to be synthesized? */
- if (TREE_CODE (decl) == FUNCTION_DECL
- && DECL_NONSTATIC_MEMBER_FUNCTION_P (decl)
- && DECL_ARTIFICIAL (decl)
- && !DECL_THUNK_P (decl)
- && ! DECL_INITIAL (decl)
- /* Kludge: don't synthesize for default args. */
- && current_function_decl)
- {
- synthesize_method (decl);
- /* If we've already synthesized the method we don't need to
- instantiate it, so we can return right away. */
- return;
- }
-
- /* If this is a function or variable that is an instance of some
- template, we now know that we will need to actually do the
- instantiation. We check that DECL is not an explicit
- instantiation because that is not checked in instantiate_decl. */
- if ((DECL_NON_THUNK_FUNCTION_P (decl) || TREE_CODE (decl) == VAR_DECL)
- && DECL_LANG_SPECIFIC (decl) && DECL_TEMPLATE_INFO (decl)
- && (!DECL_EXPLICIT_INSTANTIATION (decl)
- || (TREE_CODE (decl) == FUNCTION_DECL
- && DECL_INLINE (DECL_TEMPLATE_RESULT
- (template_for_substitution (decl))))))
- {
- bool defer;
-
- /* Normally, we put off instantiating functions in order to
- improve compile times. Maintaining a stack of active
- functions is expensive, and the inliner knows to
- instantiate any functions it might need.
-
- However, if instantiating this function might help us mark
- the current function TREE_NOTHROW, we go ahead and
- instantiate it now. */
- defer = (!flag_exceptions
- || TREE_CODE (decl) != FUNCTION_DECL
- /* If the called function can't throw, we don't need to
- generate its body to find that out. */
- || TREE_NOTHROW (decl)
- || !cfun
- /* If we already know the current function can't throw,
- then we don't need to work hard to prove it. */
- || TREE_NOTHROW (current_function_decl)
- /* If we already know that the current function *can*
- throw, there's no point in gathering more
- information. */
- || cp_function_chain->can_throw);
-
- instantiate_decl (decl, defer);
- }
-}
-
-/* Called when a class-head is encountered. TAG_KIND is the class-key
- for the class. SCOPE, if non-NULL, is the type or namespace
- indicated in the nested-name-specifier for the declaration of the
- class. ID is the name of the class, if any; it may be a TYPE_DECL,
- or an IDENTIFIER_NODE. ATTRIBUTES are attributes that apply to the
- class.
-
- Return a TYPE_DECL for the class being defined. */
-
-tree
-handle_class_head (enum tag_types tag_kind, tree scope, tree id,
- tree attributes)
-{
- tree decl = NULL_TREE;
- tree current = current_scope ();
- bool xrefd_p = false;
- bool new_type_p;
- tree context;
-
- if (current == NULL_TREE)
- current = current_namespace;
-
- if (scope)
- {
- if (TREE_CODE (id) == TYPE_DECL)
- /* We must bash typedefs back to the main decl of the
- type. Otherwise we become confused about scopes. */
- decl = TYPE_MAIN_DECL (TREE_TYPE (id));
- else if (DECL_CLASS_TEMPLATE_P (id))
- decl = DECL_TEMPLATE_RESULT (id);
- else
- {
- if (TYPE_P (scope))
- {
- /* According to the suggested resolution of core issue
- 180, 'typename' is assumed after a class-key. */
- decl = make_typename_type (scope, id, tf_error);
- if (decl != error_mark_node)
- decl = TYPE_MAIN_DECL (decl);
- else
- decl = NULL_TREE;
- }
- else if (scope == current)
- {
- /* We've been given AGGR SCOPE::ID, when we're already
- inside SCOPE. Be nice about it. */
- if (pedantic)
- pedwarn ("extra qualification `%T::' on member `%D' ignored",
- scope, id);
- }
- else
- error ("`%T' does not have a class or union named `%D'",
- scope, id);
- }
- }
-
- if (!decl)
- {
- decl = xref_tag (tag_kind, id, attributes, false);
- if (decl == error_mark_node)
- return error_mark_node;
- decl = TYPE_MAIN_DECL (decl);
- xrefd_p = true;
- }
-
- if (!TYPE_BINFO (TREE_TYPE (decl)))
- {
- error ("`%T' is not a class or union type", decl);
- return error_mark_node;
- }
-
- /* For a definition, we want to enter the containing scope before
- looking up any base classes etc. Only do so, if this is different
- to the current scope. */
- context = CP_DECL_CONTEXT (decl);
-
- new_type_p = (current != context
- && TREE_CODE (context) != TEMPLATE_TYPE_PARM
- && TREE_CODE (context) != BOUND_TEMPLATE_TEMPLATE_PARM);
- if (new_type_p)
- push_scope (context);
-
- if (!xrefd_p
- && PROCESSING_REAL_TEMPLATE_DECL_P ()
- && !CLASSTYPE_TEMPLATE_SPECIALIZATION (TREE_TYPE (decl)))
- decl = push_template_decl (decl);
-
- return decl;
}
#include "gt-cp-decl2.h"