/* Process declarations and variables for C++ compiler.
Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+ 1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
Hacked by Michael Tiemann (tiemann@cygnus.com)
This file is part of GCC.
#include "tree-mudflap.h"
#include "cgraph.h"
#include "tree-inline.h"
+#include "c-pragma.h"
extern cpp_reader *parse_in;
} *priority_info;
static void mark_vtable_entries (tree);
-static void grok_function_init (tree, tree);
static bool maybe_emit_vtables (tree);
-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);
/* A list of static class variables. This is needed, because a
static class variable can be declared inside the class without
an initializer, and then initialized, statically, outside the class. */
-static GTY(()) varray_type pending_statics;
-#define pending_statics_used \
- (pending_statics ? pending_statics->elements_used : 0)
+static GTY(()) VEC(tree,gc) *pending_statics;
/* A list of functions which were declared inline, but which we
may need to emit outline anyway. */
-static GTY(()) varray_type deferred_fns;
-#define deferred_fns_used \
- (deferred_fns ? deferred_fns->elements_used : 0)
-
-/* Flag used when debugging spew.c */
-
-extern int spew_debug;
+static GTY(()) VEC(tree,gc) *deferred_fns;
/* Nonzero if we're done parsing and into end-of-file activities. */
/* Returns a PARM_DECL for a parameter of the indicated TYPE, with the
indicated NAME. */
-tree
+static tree
build_artificial_parm (tree name, tree type)
{
tree parm = cp_build_parm_decl (name, type);
/* We don't need an in-charge parameter for constructors that don't
have virtual bases. */
if (DECL_CONSTRUCTOR_P (fn)
- && !TYPE_USES_VIRTUAL_BASECLASSES (DECL_CONTEXT (fn)))
+ && !CLASSTYPE_VBASECLASSES (DECL_CONTEXT (fn)))
return;
arg_types = TYPE_ARG_TYPES (TREE_TYPE (fn));
/* If this is a subobject constructor or destructor, our caller will
pass us a pointer to our VTT. */
- if (TYPE_USES_VIRTUAL_BASECLASSES (DECL_CONTEXT (fn)))
+ if (CLASSTYPE_VBASECLASSES (DECL_CONTEXT (fn)))
{
parm = build_artificial_parm (vtt_parm_identifier, vtt_parm_type);
this_quals |= TYPE_QUAL_CONST;
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);
+ cp_apply_type_quals_to_decl (this_quals, parm);
TREE_CHAIN (parm) = DECL_ARGUMENTS (function);
DECL_ARGUMENTS (function) = parm;
}
}
type = TREE_TYPE (array_expr);
- my_friendly_assert (type, 20030626);
+ gcc_assert (type);
type = non_reference (type);
/* If they have an `operator[]', use that. */
array_expr = p2, index_exp = i1;
else
{
- error ("invalid types `%T[%T]' for array subscript",
- type, TREE_TYPE (index_exp));
+ error ("invalid types %<%T[%T]%> for array subscript",
+ type, TREE_TYPE (index_exp));
return error_mark_node;
}
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);
+ warning (0, "deleting array %q#D", exp);
t = build_expr_type_conversion (WANT_POINTER, exp, true);
if (t == NULL_TREE || t == error_mark_node)
{
- error ("type `%#T' argument given to `delete', expected pointer",
- TREE_TYPE (exp));
+ error ("type %q#T argument given to %<delete%>, expected pointer",
+ TREE_TYPE (exp));
return error_mark_node;
}
/* You can't delete functions. */
if (TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE)
{
- error ("cannot delete a function. Only pointer-to-objects are valid arguments to `delete'");
+ error ("cannot delete a function. Only pointer-to-objects are "
+ "valid arguments to %<delete%>");
return error_mark_node;
}
/* Deleting ptr to void is undefined behavior [expr.delete/3]. */
if (TREE_CODE (TREE_TYPE (type)) == VOID_TYPE)
{
- warning ("deleting `%T' is undefined", type);
+ warning (0, "deleting %qT is undefined", type);
doing_vec = 0;
}
{
tree decl;
- my_friendly_assert (TREE_CODE (tmpl) == TEMPLATE_DECL, 0);
+ gcc_assert (TREE_CODE (tmpl) == TEMPLATE_DECL);
decl = DECL_TEMPLATE_RESULT (tmpl);
if (TREE_CODE (decl) == FUNCTION_DECL
/* 14.5.2.2 [temp.mem]
A local class shall not have member templates. */
- error ("invalid declaration of member template `%#D' in local class",
- decl);
+ error ("invalid declaration of member template %q#D in local class",
+ decl);
if (TREE_CODE (decl) == FUNCTION_DECL && DECL_VIRTUAL_P (decl))
{
A member function template shall not be virtual. */
error
- ("invalid use of `virtual' in template declaration of `%#D'",
+ ("invalid use of %<virtual%> in template declaration of %q#D",
decl);
DECL_VIRTUAL_P (decl) = 0;
}
DECL_IGNORED_P (tmpl) = 1;
}
else
- error ("template declaration of `%#D'", decl);
+ error ("template declaration of %q#D", decl);
}
/* Return true iff TYPE is a valid Java parameter or return type. */
if (!acceptable_java_type (ret_type))
{
- error ("Java method '%D' has non-Java return type `%T'",
- method, ret_type);
+ error ("Java method %qD has non-Java return type %qT",
+ method, ret_type);
jerr = true;
}
tree type = TREE_VALUE (arg_types);
if (!acceptable_java_type (type))
{
- error ("Java method '%D' has non-Java parameter type `%T'",
- method, type);
+ error ("Java method %qD has non-Java parameter type %qT",
+ method, type);
jerr = true;
}
}
/* Sanity check: report error if this function FUNCTION is not
really a member of the class (CTYPE) it is supposed to belong to.
- TEMPLATE_PARMS is used to specifiy the template parameters of a member
+ TEMPLATE_PARMS is used to specify 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
if (DECL_USE_TEMPLATE (function)
&& !(TREE_CODE (function) == TEMPLATE_DECL
&& DECL_TEMPLATE_SPECIALIZATION (function))
- && is_member_template (DECL_TI_TEMPLATE (function)))
+ && DECL_MEMBER_TEMPLATE_P (DECL_TI_TEMPLATE (function)))
/* Since this is a specialization of a member template,
we're not going to find the declaration in the class.
For example, in:
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);
+ gcc_assert (!template_parms
+ || comp_template_parms (template_parms,
+ DECL_TEMPLATE_PARMS (function)));
template_parms = DECL_TEMPLATE_PARMS (function);
}
/* OK, is this a definition of a member template? */
is_template = (template_parms != NULL_TREE);
- ix = lookup_fnfields_1 (complete_type (ctype),
- DECL_CONSTRUCTOR_P (function) ? ctor_identifier :
- DECL_DESTRUCTOR_P (function) ? dtor_identifier :
- DECL_NAME (function));
-
+ ix = class_method_index_for_fn (complete_type (ctype), function);
if (ix >= 0)
{
- VEC(tree) *methods = CLASSTYPE_METHOD_VEC (ctype);
+ VEC(tree,gc) *methods = CLASSTYPE_METHOD_VEC (ctype);
tree fndecls, fndecl = 0;
bool is_conv_op;
- bool pop_p;
+ tree pushed_scope;
const char *format = NULL;
- pop_p = push_scope (ctype);
+ pushed_scope = push_scope (ctype);
for (fndecls = VEC_index (tree, methods, ix);
fndecls; fndecls = OVL_NEXT (fndecls))
{
== DECL_TI_TEMPLATE (fndecl))))
break;
}
- if (pop_p)
- pop_scope (ctype);
+ if (pushed_scope)
+ pop_scope (pushed_scope);
if (fndecls)
return OVL_CURRENT (fndecls);
- error ("prototype for `%#D' does not match any in class `%T'",
+ error ("prototype for %q#D does not match any in class %qT",
function, ctype);
is_conv_op = DECL_CONV_FN_P (fndecl);
else if (!COMPLETE_TYPE_P (ctype))
cxx_incomplete_type_error (function, ctype);
else
- error ("no `%#D' member function declared in class `%T'",
+ error ("no %q#D member function declared in class %qT",
function, ctype);
/* If we did not find the method in the class, add it to avoid
{
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);
+ VEC_safe_push (tree, gc, deferred_fns, decl);
}
}
static void
note_vague_linkage_var (tree var)
{
- if (!pending_statics)
- VARRAY_TREE_INIT (pending_statics, 32, "pending_statics");
- VARRAY_PUSH_TREE (pending_statics, var);
+ VEC_safe_push (tree, gc, pending_statics, var);
}
/* We have just processed the DECL, which is a static data member.
finish_static_data_member_decl (tree decl, tree init, tree asmspec_tree,
int flags)
{
- my_friendly_assert (TREE_PUBLIC (decl), 0);
+ gcc_assert (TREE_PUBLIC (decl));
DECL_CONTEXT (decl) = current_class_type;
note_vague_linkage_var (decl);
if (LOCAL_CLASS_P (current_class_type))
- pedwarn ("local class `%#T' shall not have static data member `%#D'",
+ pedwarn ("local class %q#T shall not have static data member %q#D",
current_class_type, decl);
/* Static consts need not be initialized in the class definition. */
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))
+ && declarator->u.id.qualifying_scope
+ && TREE_CODE (declarator->u.id.unqualified_name) == IDENTIFIER_NODE)
/* Access declaration */
- return do_class_using_decl (declarator->u.id.name);
+ return do_class_using_decl (declarator->u.id.qualifying_scope,
+ declarator->u.id.unqualified_name);
if (init
&& TREE_CODE (init) == TREE_LIST
if (TREE_CODE (value) == TYPE_DECL && init)
{
- error ("typedef `%D' is initialized (use __typeof__ instead)", value);
+ error ("typedef %qD is initialized (use __typeof__ instead)", value);
init = NULL_TREE;
}
if (DECL_NAME (value) != NULL_TREE
&& IDENTIFIER_POINTER (DECL_NAME (value))[0] == '_'
&& ! strcmp (IDENTIFIER_POINTER (DECL_NAME (value)), "_vptr"))
- error ("member `%D' conflicts with virtual function table field name",
- value);
+ error ("member %qD conflicts with virtual function table field name",
+ value);
/* Stash away type declarations. */
if (TREE_CODE (value) == TYPE_DECL)
if (processing_template_decl)
value = push_template_decl (value);
+ if (attrlist)
+ {
+ /* Avoid storing attributes in template parameters:
+ tsubst is not ready to handle them. */
+ tree type = TREE_TYPE (value);
+ if (TREE_CODE (type) == TEMPLATE_TYPE_PARM
+ || TREE_CODE (type) == BOUND_TEMPLATE_TEMPLATE_PARM)
+ sorry ("applying attributes to template parameters is not implemented");
+ else
+ cplus_decl_attributes (&value, attrlist, 0);
+ }
+
return value;
}
if (DECL_IN_AGGR_P (value))
{
- error ("`%D' is already defined in `%T'", value,
- DECL_CONTEXT (value));
+ error ("%qD is already defined in %qT", value, DECL_CONTEXT (value));
return void_type_node;
}
{
if (TREE_CODE (value) == FUNCTION_DECL)
{
- grok_function_init (value, init);
- init = NULL_TREE;
+ /* Initializers for functions are rejected early in the parser.
+ If we get here, it must be a pure specifier for a method. */
+ gcc_assert (TREE_CODE (TREE_TYPE (value)) == METHOD_TYPE);
+ gcc_assert (error_operand_p (init) || integer_zerop (init));
+ DECL_PURE_VIRTUAL_P (value) = 1;
}
else if (pedantic && TREE_CODE (value) != VAR_DECL)
/* Already complained in grokdeclarator. */
if (!processing_template_decl)
{
- if (TREE_CODE (init) == CONST_DECL)
- init = DECL_INITIAL (init);
- else if (TREE_READONLY_DECL_P (init))
- init = decl_constant_value (init);
- else if (TREE_CODE (init) == CONSTRUCTOR)
+ if (TREE_CODE (init) == CONSTRUCTOR)
init = digest_init (TREE_TYPE (value), init, (tree *)0);
+ else
+ init = integral_constant_value (init);
+
if (init != error_mark_node && ! TREE_CONSTANT (init))
{
/* We can allow references to things that are effectively
if (attrlist)
cplus_decl_attributes (&value, attrlist, 0);
- if (TREE_CODE (value) == VAR_DECL)
+ switch (TREE_CODE (value))
{
+ case VAR_DECL:
finish_static_data_member_decl (value, init, asmspec_tree,
flags);
return value;
- }
- if (TREE_CODE (value) == FIELD_DECL)
- {
+
+ case FIELD_DECL:
if (asmspec)
- error ("`asm' specifiers are not permitted on non-static data members");
+ error ("%<asm%> specifiers are not permitted on non-static data members");
if (DECL_INITIAL (value) == error_mark_node)
init = error_mark_node;
cp_finish_decl (value, init, NULL_TREE, flags);
DECL_INITIAL (value) = init;
DECL_IN_AGGR_P (value) = 1;
return value;
- }
- if (TREE_CODE (value) == FUNCTION_DECL)
- {
+
+ case FUNCTION_DECL:
if (asmspec)
set_user_assembler_name (value, asmspec);
if (!DECL_FRIEND_P (value))
DECL_IN_AGGR_P (value) = 1;
return value;
+
+ default:
+ gcc_unreachable ();
}
- abort ();
- /* NOTREACHED */
return NULL_TREE;
}
if (TREE_CODE (value) == TYPE_DECL)
{
- error ("cannot declare `%D' to be a bit-field type", value);
+ error ("cannot declare %qD to be a bit-field type", value);
return NULL_TREE;
}
check here. */
if (TREE_CODE (value) == FUNCTION_DECL)
{
- error ("cannot declare bit-field `%D' with function type",
+ error ("cannot declare bit-field %qD with function type",
DECL_NAME (value));
return NULL_TREE;
}
if (DECL_IN_AGGR_P (value))
{
- error ("`%D' is already defined in the class %T", value,
- DECL_CONTEXT (value));
+ error ("%qD is already defined in the class %qT", value,
+ DECL_CONTEXT (value));
return void_type_node;
}
if (TREE_STATIC (value))
{
- error ("static member `%D' cannot be a bit-field", value);
+ error ("static member %qD cannot be a bit-field", value);
return NULL_TREE;
}
cp_finish_decl (value, NULL_TREE, NULL_TREE, 0);
return value;
}
-/* When a function is declared with an initializer,
- do the right thing. Currently, there are two possibilities:
-
- class B
- {
- public:
- // initialization possibility #1.
- virtual void f () = 0;
- int g ();
- };
-
- class D1 : B
- {
- public:
- int d1;
- // error, no f ();
- };
-
- class D2 : B
- {
- public:
- int d2;
- void f ();
- };
-
- class D3 : B
- {
- public:
- int d3;
- // initialization possibility #2
- void f () = B::f;
- };
-
-*/
-
-static void
-grok_function_init (tree decl, tree init)
-{
- /* An initializer for a function tells how this function should
- be inherited. */
- tree type = TREE_TYPE (decl);
-
- if (TREE_CODE (type) == FUNCTION_TYPE)
- error ("initializer specified for non-member function `%D'", decl);
- else if (integer_zerop (init))
- DECL_PURE_VIRTUAL_P (decl) = 1;
- else
- error ("invalid initializer for virtual method `%D'", decl);
-}
\f
void
cplus_decl_attributes (tree *decl, tree attributes, int flags)
SET_IDENTIFIER_TYPE_VALUE (DECL_NAME (*decl), TREE_TYPE (*decl));
}
\f
-/* 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. */
+/* Walks through the namespace- or function-scope anonymous union
+ OBJECT, with the indicated TYPE, building appropriate ALIAS_DECLs.
+ Returns one of the fields for use in the mangled name. */
static tree
-build_anon_union_vars (tree object)
+build_anon_union_vars (tree type, tree object)
{
- tree type = TREE_TYPE (object);
tree main_decl = NULL_TREE;
tree field;
continue;
if (TREE_CODE (field) != FIELD_DECL)
{
- cp_pedwarn_at ("\
-`%#D' invalid; an anonymous union can only have non-static data members",
+ cp_pedwarn_at ("%q#D invalid; an anonymous union can only "
+ "have non-static data members",
field);
continue;
}
if (TREE_PRIVATE (field))
- cp_pedwarn_at ("private member `%#D' in anonymous union", field);
+ cp_pedwarn_at ("private member %q#D in anonymous union", field);
else if (TREE_PROTECTED (field))
- cp_pedwarn_at ("protected member `%#D' in anonymous union", field);
+ cp_pedwarn_at ("protected member %q#D in anonymous union", field);
if (processing_template_decl)
ref = build_min_nt (COMPONENT_REF, object,
decl = pushdecl (decl);
}
else if (ANON_AGGR_TYPE_P (TREE_TYPE (field)))
- decl = build_anon_union_vars (ref);
+ decl = build_anon_union_vars (TREE_TYPE (field), ref);
else
decl = 0;
void
finish_anon_union (tree anon_union_decl)
{
- tree type = TREE_TYPE (anon_union_decl);
+ tree type;
tree main_decl;
- bool public_p = TREE_PUBLIC (anon_union_decl);
+ bool public_p;
+
+ if (anon_union_decl == error_mark_node)
+ return;
+
+ type = TREE_TYPE (anon_union_decl);
+ public_p = TREE_PUBLIC (anon_union_decl);
/* The VAR_DECL's context is the same as the TYPE's context. */
DECL_CONTEXT (anon_union_decl) = DECL_CONTEXT (TYPE_NAME (type));
return;
}
- main_decl = build_anon_union_vars (anon_union_decl);
+ main_decl = build_anon_union_vars (type, anon_union_decl);
if (main_decl == NULL_TREE)
{
- warning ("anonymous union with no members");
+ warning (0, "anonymous union with no members");
return;
}
int e = 0;
tree args = TYPE_ARG_TYPES (type);
- my_friendly_assert (TREE_CODE (type) == FUNCTION_TYPE, 20001107);
+ gcc_assert (TREE_CODE (type) == FUNCTION_TYPE);
if (!same_type_p (TREE_TYPE (type), ptr_type_node))
- e = 1, error ("`operator new' must return type `%T'", ptr_type_node);
+ {
+ e = 1;
+ error ("%<operator new%> must return type %qT", ptr_type_node);
+ }
if (!args || args == void_list_node
|| !same_type_p (TREE_VALUE (args), size_type_node))
e = 2;
if (args && args != void_list_node)
args = TREE_CHAIN (args);
- pedwarn ("`operator new' takes type `size_t' (`%T') as first parameter", size_type_node);
+ pedwarn ("%<operator new%> takes type %<size_t%> (%qT) "
+ "as first parameter", size_type_node);
}
switch (e)
{
int e = 0;
tree args = TYPE_ARG_TYPES (type);
- my_friendly_assert (TREE_CODE (type) == FUNCTION_TYPE, 20001107);
+ gcc_assert (TREE_CODE (type) == FUNCTION_TYPE);
if (!same_type_p (TREE_TYPE (type), void_type_node))
- e = 1, error ("`operator delete' must return type `%T'", void_type_node);
+ {
+ e = 1;
+ error ("%<operator delete%> must return type %qT", void_type_node);
+ }
if (!args || args == void_list_node
|| !same_type_p (TREE_VALUE (args), ptr_type_node))
e = 2;
if (args && args != void_list_node)
args = TREE_CHAIN (args);
- error ("`operator delete' takes type `%T' as first parameter", ptr_type_node);
+ error ("%<operator delete%> takes type %qT as first parameter",
+ ptr_type_node);
}
switch (e)
{
if (! flag_weak)
return;
- /* We can't set DECL_COMDAT on functions, or finish_file will think
+ /* We can't set DECL_COMDAT on functions, or cp_finish_file will think
we can get away with not emitting them if they aren't used. We need
to for variables so that cp_finish_decl will update their linkage,
because their DECL_INITIAL may not have been set properly yet. */
non-abstract virtual member function has been defined in this
translation unit. But, we can't possibly know that until we've
seen the entire translation unit. */
- my_friendly_assert (at_eof, 20000226);
+ gcc_assert (at_eof);
if (CLASSTYPE_INTERFACE_KNOWN (ctype))
return;
- /* If MULTIPLE_SYMBOL_SPACES is defined and we saw a #pragma interface,
+ /* If MULTIPLE_SYMBOL_SPACES is set and we saw a #pragma interface,
we will have CLASSTYPE_INTERFACE_ONLY set but not
CLASSTYPE_INTERFACE_KNOWN. In that case, we don't want to use this
heuristic because someone will supply a #pragma implementation
import_export = (DECL_REALLY_EXTERN (method) ? -1 : 1);
}
-#ifdef MULTIPLE_SYMBOL_SPACES
- if (import_export == -1)
+ /* When MULTIPLE_SYMBOL_SPACES is set, we cannot count on seeing
+ a definition anywhere else. */
+ if (MULTIPLE_SYMBOL_SPACES && import_export == -1)
import_export = 0;
-#endif
/* Allow backends the chance to overrule the decision. */
if (targetm.cxx.import_export_class)
bool
decl_needed_p (tree decl)
{
- my_friendly_assert (TREE_CODE (decl) == VAR_DECL
- || TREE_CODE (decl) == FUNCTION_DECL,
- 20040726);
+ gcc_assert (TREE_CODE (decl) == VAR_DECL
+ || TREE_CODE (decl) == FUNCTION_DECL);
/* This function should only be called at the end of the translation
unit. We cannot be sure of whether or not something will be
COMDAT until that point. */
- my_friendly_assert (at_eof, 20040726);
+ gcc_assert (at_eof);
/* All entities with external linkage that are not COMDAT should be
emitted; they may be referred to from other object files. */
if (TREE_TYPE (primary_vtbl) == void_type_node)
return false;
+ /* On some targets, we cannot determine the key method until the end
+ of the translation unit -- which is when this function is
+ called. */
+ if (!targetm.cxx.key_method_may_be_inline ())
+ determine_key_method (ctype);
+
/* See if any of the vtables are needed. */
for (vtbl = CLASSTYPE_VTABLES (ctype); vtbl; vtbl = TREE_CHAIN (vtbl))
{
if (TREE_TYPE (DECL_INITIAL (vtbl)) == 0)
{
+ tree expr = 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 ();
+ gcc_assert (!expr);
}
/* Write it out. */
/* Cloned constructors and destructors get the same visibility as
the underlying function. That should be set up in
maybe_clone_body. */
- my_friendly_assert (!DECL_CLONED_FUNCTION_P (decl), 20040804);
+ gcc_assert (!DECL_CLONED_FUNCTION_P (decl));
/* Give the common code a chance to make a determination. */
if (c_determine_visibility (decl))
{
/* Virtual tables have DECL_CONTEXT set to their associated class,
so they are automatically handled above. */
- my_friendly_assert (!(TREE_CODE (decl) == VAR_DECL
- && DECL_VTABLE_OR_VTT_P (decl)), 20040803);
+ gcc_assert (TREE_CODE (decl) != VAR_DECL
+ || !DECL_VTABLE_OR_VTT_P (decl));
/* Entities not associated with any class just get the
visibility specified by their attributes. */
return;
{
DECL_VISIBILITY (decl) = VISIBILITY_DEFAULT;
DECL_VISIBILITY_SPECIFIED (decl) = 1;
- return;
}
-
- if (TREE_CODE (decl) == FUNCTION_DECL
- && DECL_DECLARED_INLINE_P (decl)
- && visibility_options.inlines_hidden)
+ else if (TREE_CODE (decl) == FUNCTION_DECL
+ && DECL_DECLARED_INLINE_P (decl)
+ && visibility_options.inlines_hidden)
+ {
+ /* Don't change it if it has been set explicitly by user. */
+ if (!DECL_VISIBILITY_SPECIFIED (decl))
+ {
+ DECL_VISIBILITY (decl) = VISIBILITY_HIDDEN;
+ DECL_VISIBILITY_SPECIFIED (decl) = 1;
+ }
+ }
+ else if (CLASSTYPE_VISIBILITY_SPECIFIED (class_type))
{
- DECL_VISIBILITY (decl) = VISIBILITY_HIDDEN;
+ DECL_VISIBILITY (decl) = CLASSTYPE_VISIBILITY (class_type);
DECL_VISIBILITY_SPECIFIED (decl) = 1;
}
- else
+ else if (!DECL_VISIBILITY_SPECIFIED (decl))
{
DECL_VISIBILITY (decl) = CLASSTYPE_VISIBILITY (class_type);
- DECL_VISIBILITY_SPECIFIED (decl)
- = CLASSTYPE_VISIBILITY_SPECIFIED (class_type);
+ DECL_VISIBILITY_SPECIFIED (decl) = 0;
}
}
}
int emit_p;
bool comdat_p;
bool import_p;
+ tree class_type = NULL_TREE;
if (DECL_INTERFACE_KNOWN (decl))
return;
"-frepo" it would be incorrect to make decisions about what
entities to emit when building the PCH; those decisions must be
delayed until the repository information has been processed. */
- my_friendly_assert (at_eof, 20040727);
+ gcc_assert (at_eof);
/* Object file linkage for explicit instantiations is handled in
mark_decl_instantiated. For static variables in functions with
vague linkage, maybe_commonize_var is used.
Therefore, the only declarations that should be provided to this
- function are those with external linkage that:
+ function are those with external linkage that are:
* implicit instantiations of function templates
definition available in this translation unit.
The following assertions check these conditions. */
- my_friendly_assert (TREE_CODE (decl) == FUNCTION_DECL
- || TREE_CODE (decl) == VAR_DECL,
- 2004725);
+ gcc_assert (TREE_CODE (decl) == FUNCTION_DECL
+ || TREE_CODE (decl) == VAR_DECL);
/* Any code that creates entities with TREE_PUBLIC cleared should
also set DECL_INTERFACE_KNOWN. */
- my_friendly_assert (TREE_PUBLIC (decl), 20040725);
+ gcc_assert (TREE_PUBLIC (decl));
if (TREE_CODE (decl) == FUNCTION_DECL)
- my_friendly_assert (DECL_IMPLICIT_INSTANTIATION (decl)
- || DECL_FRIEND_PSEUDO_TEMPLATE_INSTANTIATION (decl)
- || DECL_DECLARED_INLINE_P (decl),
- 20040725);
+ gcc_assert (DECL_IMPLICIT_INSTANTIATION (decl)
+ || DECL_FRIEND_PSEUDO_TEMPLATE_INSTANTIATION (decl)
+ || DECL_DECLARED_INLINE_P (decl));
else
- my_friendly_assert (DECL_IMPLICIT_INSTANTIATION (decl)
- || DECL_VTABLE_OR_VTT_P (decl)
- || DECL_TINFO_P (decl),
- 20040725);
+ gcc_assert (DECL_IMPLICIT_INSTANTIATION (decl)
+ || DECL_VTABLE_OR_VTT_P (decl)
+ || DECL_TINFO_P (decl));
/* Check that a definition of DECL is available in this translation
unit. */
- my_friendly_assert (!DECL_REALLY_EXTERN (decl), 20040725);
+ gcc_assert (!DECL_REALLY_EXTERN (decl));
/* Assume that DECL will not have COMDAT linkage. */
comdat_p = false;
;
else if (TREE_CODE (decl) == VAR_DECL && DECL_VTABLE_OR_VTT_P (decl))
{
- tree type = DECL_CONTEXT (decl);
- import_export_class (type);
- if (TYPE_FOR_JAVA (type))
+ class_type = DECL_CONTEXT (decl);
+ import_export_class (class_type);
+ if (TYPE_FOR_JAVA (class_type))
import_p = true;
- else if (CLASSTYPE_INTERFACE_KNOWN (type)
- && CLASSTYPE_INTERFACE_ONLY (type))
+ else if (CLASSTYPE_INTERFACE_KNOWN (class_type)
+ && CLASSTYPE_INTERFACE_ONLY (class_type))
import_p = true;
- else if (TARGET_WEAK_NOT_IN_ARCHIVE_TOC
- && !CLASSTYPE_USE_TEMPLATE (type)
- && CLASSTYPE_KEY_METHOD (type)
- && !DECL_DECLARED_INLINE_P (CLASSTYPE_KEY_METHOD (type)))
+ else if ((!flag_weak || TARGET_WEAK_NOT_IN_ARCHIVE_TOC)
+ && !CLASSTYPE_USE_TEMPLATE (class_type)
+ && CLASSTYPE_KEY_METHOD (class_type)
+ && !DECL_DECLARED_INLINE_P (CLASSTYPE_KEY_METHOD (class_type)))
/* The ABI requires that all virtual tables be emitted with
COMDAT linkage. However, on systems where COMDAT symbols
don't show up in the table of contents for a static
- archive, the linker will report errors about undefined
- symbols because it will not see the virtual table
- definition. Therefore, in the case that we know that the
- virtual table will be emitted in only one translation
- unit, we make the virtual table an ordinary definition
- with external linkage. */
+ archive, or on systems without weak symbols (where we
+ approximate COMDAT linkage by using internal linkage), the
+ linker will report errors about undefined symbols because
+ it will not see the virtual table definition. Therefore,
+ in the case that we know that the virtual table will be
+ emitted in only one translation unit, we make the virtual
+ table an ordinary definition with external linkage. */
DECL_EXTERNAL (decl) = 0;
- else if (CLASSTYPE_INTERFACE_KNOWN (type))
+ else if (CLASSTYPE_INTERFACE_KNOWN (class_type))
{
- /* TYPE is being exported from this translation unit, so DECL
- should be defined here. The ABI requires COMDAT
- linkage. Normally, we only emit COMDAT things when they
- are needed; make sure that we realize that this entity is
- indeed needed. */
- comdat_p = true;
- mark_needed (decl);
+ /* CLASS_TYPE is being exported from this translation unit,
+ so DECL should be defined here. */
+ if (!flag_weak && CLASSTYPE_EXPLICIT_INSTANTIATION (class_type))
+ /* If a class is declared in a header with the "extern
+ template" extension, then it will not be instantiated,
+ even in translation units that would normally require
+ it. Often such classes are explicitly instantiated in
+ one translation unit. Therefore, the explicit
+ instantiation must be made visible to other translation
+ units. */
+ DECL_EXTERNAL (decl) = 0;
+ else
+ {
+ /* The generic C++ ABI says that class data is always
+ COMDAT, even if there is a key function. Some
+ variants (e.g., the ARM EABI) says that class data
+ only has COMDAT linkage if the the class data might
+ be emitted in more than one translation unit. */
+ if (!CLASSTYPE_KEY_METHOD (class_type)
+ || targetm.cxx.class_data_always_comdat ())
+ {
+ /* The ABI requires COMDAT linkage. Normally, we
+ only emit COMDAT things when they are needed;
+ make sure that we realize that this entity is
+ indeed needed. */
+ comdat_p = true;
+ mark_needed (decl);
+ }
+ }
}
else if (!flag_implicit_templates
- && CLASSTYPE_IMPLICIT_INSTANTIATION (type))
+ && CLASSTYPE_IMPLICIT_INSTANTIATION (class_type))
import_p = true;
else
comdat_p = true;
tree type = TREE_TYPE (DECL_NAME (decl));
if (CLASS_TYPE_P (type))
{
+ class_type = type;
import_export_class (type);
if (CLASSTYPE_INTERFACE_KNOWN (type)
&& TYPE_POLYMORPHIC_P (type)
import_p = true;
else
{
- comdat_p = true;
if (CLASSTYPE_INTERFACE_KNOWN (type)
&& !CLASSTYPE_INTERFACE_ONLY (type))
- mark_needed (decl);
+ {
+ comdat_p = targetm.cxx.class_data_always_comdat ();
+ mark_needed (decl);
+ if (!flag_weak)
+ {
+ comdat_p = false;
+ DECL_EXTERNAL (decl) = 0;
+ }
+ }
+ else
+ comdat_p = true;
}
}
else
comdat_linkage (decl);
}
+ /* Give the target a chance to override the visibility associated
+ with DECL. */
+ if (TREE_CODE (decl) == VAR_DECL
+ && (DECL_TINFO_P (decl)
+ || (DECL_VTABLE_OR_VTT_P (decl)
+ /* Construction virtual tables are not exported because
+ they cannot be referred to from other object files;
+ their name is not standardized by the ABI. */
+ && !DECL_CONSTRUCTION_VTABLE_P (decl)))
+ && TREE_PUBLIC (decl)
+ && !DECL_REALLY_EXTERN (decl)
+ && DECL_VISIBILITY_SPECIFIED (decl)
+ && (!class_type || !CLASSTYPE_VISIBILITY_SPECIFIED (class_type)))
+ targetm.cxx.determine_class_data_visibility (decl);
+
DECL_INTERFACE_KNOWN (decl) = 1;
}
/* This function should only be called for declarations that really
require cleanups. */
- my_friendly_assert (!TYPE_HAS_TRIVIAL_DESTRUCTOR (type), 20030106);
+ gcc_assert (!TYPE_HAS_TRIVIAL_DESTRUCTOR (type));
/* Treat all objects with destructors as used; the destructor may do
something substantive. */
DECL_WEAK (guard) = DECL_WEAK (decl);
DECL_ARTIFICIAL (guard) = 1;
+ DECL_IGNORED_P (guard) = 1;
TREE_USED (guard) = 1;
pushdecl_top_level_and_finish (guard, NULL_TREE);
}
if (targetm.have_ctors_dtors)
{
rtx fnsym = XEXP (DECL_RTL (fn), 0);
+ cgraph_mark_needed_node (cgraph_node (fn));
if (method_type == 'I')
(* targetm.asm_out.constructor) (fnsym, initp);
else
/* All the static storage duration functions created in this
translation unit. */
-static GTY(()) varray_type ssdf_decls;
+static GTY(()) VEC(tree,gc) *ssdf_decls;
/* A map from priority levels to information about that priority
level. There may be many such levels, so efficient lookup is
static constructors and destructors. */
if (!ssdf_decls)
{
- VARRAY_TREE_INIT (ssdf_decls, 32, "ssdf_decls");
+ ssdf_decls = VEC_alloc (tree, gc, 32);
/* Take this opportunity to initialize the map from priority
numbers to information about that priority level. */
get_priority_info (DEFAULT_INIT_PRIORITY);
}
- VARRAY_PUSH_TREE (ssdf_decls, ssdf_decl);
+ VEC_safe_push (tree, gc, ssdf_decls, ssdf_decl);
/* Create the argument list. */
initialize_p_decl = cp_build_parm_decl
guard_if_stmt = begin_if_stmt ();
cond = cp_build_binary_op (EQ_EXPR,
priority_decl,
- build_int_cst (NULL_TREE, priority, 0));
+ build_int_cst (NULL_TREE, priority));
init_cond = initp ? integer_one_node : integer_zero_node;
init_cond = cp_build_binary_op (EQ_EXPR,
initialize_p_decl,
{
/* When using __cxa_atexit, we never try to destroy
anything from a static destructor. */
- my_friendly_assert (initp, 20000629);
+ gcc_assert (initp);
guard_cond = get_guard_cond (guard);
}
/* If we don't have __cxa_atexit, then we will be running
if (init)
finish_expr_stmt (init);
- /* If we're using __cxa_atexit, register a a function that calls the
+ /* If we're using __cxa_atexit, register a function that calls the
destructor for the object. */
if (flag_use_cxa_atexit)
- register_dtor_fn (decl);
+ finish_expr_stmt (register_dtor_fn (decl));
/* Finish up. */
finish_static_initialization_or_destruction (guard_if_stmt);
/* If we're using __cxa_atexit, then destructors are registered
immediately after objects are initialized. */
- my_friendly_assert (!flag_use_cxa_atexit, 20000121);
+ gcc_assert (!flag_use_cxa_atexit);
/* If we don't need a destructor, there's nothing to do. */
if (TYPE_HAS_TRIVIAL_DESTRUCTOR (TREE_TYPE (decl)))
}
/* The only things that can be initialized are variables. */
- my_friendly_assert (TREE_CODE (decl) == VAR_DECL, 19990420);
+ gcc_assert (TREE_CODE (decl) == VAR_DECL);
/* If this object is not defined, we don't need to do anything
here. */
global constructors and destructors. */
body = NULL_TREE;
+ /* For Objective-C++, we may need to initialize metadata found in this module.
+ This must be done _before_ any other static initializations. */
+ if (c_dialect_objc () && (priority == DEFAULT_INIT_PRIORITY)
+ && constructor_p && objc_static_init_needed_p ())
+ {
+ body = start_objects (function_key, priority);
+ static_ctors = objc_generate_static_init_call (static_ctors);
+ }
+
/* Call the static storage duration function with appropriate
arguments. */
- if (ssdf_decls)
- for (i = 0; i < ssdf_decls->elements_used; ++i)
- {
- fndecl = VARRAY_TREE (ssdf_decls, i);
-
- /* Calls to pure or const functions will expand to nothing. */
- if (! (flags_from_decl_or_type (fndecl) & (ECF_CONST | ECF_PURE)))
- {
- if (! body)
- body = start_objects (function_key, priority);
-
- arguments = tree_cons (NULL_TREE,
- build_int_cst (NULL_TREE, priority, 0),
- NULL_TREE);
- arguments = tree_cons (NULL_TREE,
- build_int_cst (NULL_TREE, constructor_p, 0),
- arguments);
- finish_expr_stmt (build_function_call (fndecl, arguments));
- }
- }
+ for (i = 0; VEC_iterate (tree, ssdf_decls, i, fndecl); ++i)
+ {
+ /* Calls to pure or const functions will expand to nothing. */
+ if (! (flags_from_decl_or_type (fndecl) & (ECF_CONST | ECF_PURE)))
+ {
+ if (! body)
+ body = start_objects (function_key, priority);
+
+ arguments = tree_cons (NULL_TREE,
+ build_int_cst (NULL_TREE, priority),
+ NULL_TREE);
+ arguments = tree_cons (NULL_TREE,
+ build_int_cst (NULL_TREE, constructor_p),
+ arguments);
+ finish_expr_stmt (build_function_call (fndecl, arguments));
+ }
+ }
/* If we're generating code for the DEFAULT_INIT_PRIORITY, throw in
calls to any functions marked with attributes indicating that
first, since that way we only need to reverse the decls once. */
void
-finish_file (void)
+cp_finish_file (void)
{
tree vars;
bool reconsider;
size_t i;
location_t locus;
unsigned ssdf_count = 0;
+ int retries = 0;
+ tree decl;
locus = input_location;
at_eof = 1;
input_line -= 1;
#endif
- interface_unknown = 1;
- interface_only = 0;
-
/* We now have to write out all the stuff we put off writing out.
These include:
do
{
tree t;
- size_t n_old, n_new;
+ tree decl;
reconsider = false;
/* If there are templates that we've put off instantiating, do
them now. */
- instantiate_pending_templates ();
+ instantiate_pending_templates (retries);
ggc_collect ();
/* Write out virtual tables as required. Note that writing out
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)))
{
next = TREE_CHAIN (t);
}
}
-
+
/* Write out needed type info variables. We have to be careful
looping through unemitted decls, because emit_tinfo_decl may
- cause other variables to be needed. We stick new elements
- (and old elements that we may need to reconsider) at the end
- of the array, then shift them back to the beginning once we're
- done. */
-
- n_old = VARRAY_ACTIVE_SIZE (unemitted_tinfo_decls);
- for (i = 0; i < n_old; ++i)
- {
- tree tinfo_decl = VARRAY_TREE (unemitted_tinfo_decls, i);
- if (emit_tinfo_decl (tinfo_decl))
- reconsider = true;
- else
- VARRAY_PUSH_TREE (unemitted_tinfo_decls, tinfo_decl);
- }
-
- /* The only elements we want to keep are the new ones. Copy
- them to the beginning of the array, then get rid of the
- leftovers. */
- n_new = VARRAY_ACTIVE_SIZE (unemitted_tinfo_decls) - n_old;
- 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));
- VARRAY_ACTIVE_SIZE (unemitted_tinfo_decls) = n_new;
+ cause other variables to be needed. New elements will be
+ appended, and we remove from the vector those that actually
+ get emitted. */
+ for (i = VEC_length (tree, unemitted_tinfo_decls);
+ VEC_iterate (tree, unemitted_tinfo_decls, --i, t);)
+ if (emit_tinfo_decl (t))
+ {
+ reconsider = true;
+ VEC_unordered_remove (tree, unemitted_tinfo_decls, i);
+ }
/* The list of objects with static storage duration is built up
in reverse order. We clear STATIC_AGGREGATES so that any new
/* Go through the set of inline functions whose bodies have not
been emitted yet. If out-of-line copies of these functions
are required, emit them. */
- for (i = 0; i < deferred_fns_used; ++i)
+ for (i = 0; VEC_iterate (tree, deferred_fns, i, decl); ++i)
{
- tree decl = VARRAY_TREE (deferred_fns, i);
-
/* Does it need synthesizing? */
if (DECL_ARTIFICIAL (decl) && ! DECL_INITIAL (decl)
&& (! DECL_REALLY_EXTERN (decl) || DECL_INLINE (decl)))
reconsider = true;
/* Static data members are just like namespace-scope globals. */
- for (i = 0; i < pending_statics_used; ++i)
+ for (i = 0; VEC_iterate (tree, pending_statics, i, decl); ++i)
{
- tree decl = VARRAY_TREE (pending_statics, i);
if (var_finalized_p (decl) || DECL_REALLY_EXTERN (decl))
continue;
import_export_decl (decl);
if (DECL_NOT_REALLY_EXTERN (decl) && decl_needed_p (decl))
DECL_EXTERNAL (decl) = 0;
}
- if (pending_statics
- && wrapup_global_declarations (&VARRAY_TREE (pending_statics, 0),
- pending_statics_used))
+ if (VEC_length (tree, pending_statics) != 0
+ && wrapup_global_declarations (VEC_address (tree, pending_statics),
+ VEC_length (tree, pending_statics)))
reconsider = true;
- /* Ask the back end to emit functions and variables that are
- enqued. These emissions may result in marking more entities
- as needed. */
- if (cgraph_assemble_pending_functions ())
- reconsider = true;
- if (cgraph_varpool_assemble_pending_decls ())
- reconsider = true;
+ retries++;
}
while (reconsider);
/* All used inline functions must have a definition at this point. */
- for (i = 0; i < deferred_fns_used; ++i)
+ for (i = 0; VEC_iterate (tree, deferred_fns, i, decl); ++i)
{
- tree decl = VARRAY_TREE (deferred_fns, i);
-
if (/* Check online inline functions that were actually used. */
TREE_USED (decl) && DECL_DECLARED_INLINE_P (decl)
/* But not defined. */
already verified there was a definition. */
&& !DECL_EXPLICIT_INSTANTIATION (decl))
{
- cp_warning_at ("inline function `%D' used but never defined", decl);
+ cp_warning_at ("inline function %qD used but never defined", decl);
/* This symbol is effectively an "extern" declaration now.
This is not strictly necessary, but removes a duplicate
warning. */
if (priority_info_map)
splay_tree_delete (priority_info_map);
+ /* Generate any missing aliases. */
+ maybe_apply_pending_pragma_weaks ();
+
/* We're done with static constructors, so we can go back to "C++"
linkage now. */
pop_lang_context ();
cgraph_finalize_compilation_unit ();
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);
- if (pending_statics)
- check_global_declarations (&VARRAY_TREE (pending_statics, 0),
- pending_statics_used);
+ if (VEC_length (tree, pending_statics) != 0)
+ check_global_declarations (VEC_address (tree, pending_statics),
+ VEC_length (tree, pending_statics));
finish_repo ();
if (processing_template_decl)
{
- my_friendly_assert (TREE_CODE (fn) == DOTSTAR_EXPR
- || TREE_CODE (fn) == MEMBER_REF,
- 20030708);
+ gcc_assert (TREE_CODE (fn) == DOTSTAR_EXPR
+ || TREE_CODE (fn) == MEMBER_REF);
if (type_dependent_expression_p (fn)
|| any_type_dependent_arguments_p (args))
return build_min_nt (CALL_EXPR, fn, args, NULL_TREE);
saw_def = true;
else if (saw_def)
{
- cp_error_at ("default argument missing for parameter %P of `%+#D'",
+ cp_error_at ("default argument missing for parameter %P of %q+#D",
i, x);
break;
}
&& DECL_ARTIFICIAL (decl)
&& !DECL_THUNK_P (decl)
&& ! DECL_INITIAL (decl)
- /* Kludge: don't synthesize for default args. */
+ /* Kludge: don't synthesize for default args. Unfortunately this
+ rules out initializers of namespace-scoped objects too, but
+ it's sort-of ok if the implicit ctor or dtor decl keeps
+ pointing to the class location. */
&& current_function_decl)
{
+ /* Put the function definition at the position where it is needed,
+ rather than within the body of the class. That way, an error
+ during the generation of the implicit body points at the place
+ where the attempt to generate the function occurs, giving the
+ user a hint as to why we are attempting to generate the
+ function. */
+ DECL_SOURCE_LOCATION (decl) = input_location;
+
synthesize_method (decl);
/* If we've already synthesized the method we don't need to
instantiate it, so we can return right away. */