-2001-03-20 Jason Merrill <jason@redhat.com>
+2001-03-21 Jason Merrill <jason@redhat.com>
+
+ * pt.c (instantiate_decl): Abort if we see a member constant
+ instantiation that doesn't already have its initializer.
+ Downgrade explicit instantiation without definition to pedwarn.
+
+ * cp-tree.h (DECL_TINFO_FN_P, SET_DECL_TINFO_FN_P): Remove.
+ * class.c (build_vtable_entry): Don't check DECL_TINFO_FN_P.
+ (import_export_decl): Check tinfo_decl_p, not DECL_TINFO_FN_P.
+
+ * cp-tree.h (CLASSTYPE_VTABLE_NEEDS_WRITING): Remove.
+ (pending_vtables): Remove.
+ * decl2.c (pending_vtables): Remove.
+ (import_export_vtable): Use CLASSTYPE_INTERFACE_ONLY, not
+ CLASSTYPE_VTABLE_NEEDS_WRITING.
+ (import_export_class): Likewise.
+ (init_decl2): Don't mark pending_vtables.
+ * lex.c (handle_pragma_vtable): Just sorry.
+ * pt.c (instantiate_class_template): Don't mess with
+ CLASSTYPE_VTABLE_NEEDS_WRITING.
+ (mark_class_instantiated): Likewise.
+ * ptree.c (print_lang_type): Don't print it.
+ * semantics.c (begin_class_definition): Don't set it.
+
+ * pt.c (template_tail): Replace with last_pending_template.
+ (maybe_templates, maybe_template_tail): Remove.
+ (add_pending_template): Adjust.
+ (instantiate_pending_templates): Adjust.
+
+ * cp-tree.h (struct saved_scope): Remove lang_stack field.
+ (current_lang_stack): Remove.
+ * decl.c (maybe_push_to_top_level): Don't initialize it.
+ (duplicate_decls): Use current_lang_depth.
+ (xref_basetypes): Likewise.
+ * class.c (current_lang_depth): New fn.
+ (push_lang_context): Use more varray functionality.
+ (pop_lang_context): Likewise.
* error.c (GLOBAL_THING): Always use '__'.
pop_nested_class ();
}
+/* Returns the number of extern "LANG" blocks we are nested within. */
+
+int
+current_lang_depth ()
+{
+ return VARRAY_ACTIVE_SIZE (current_lang_base);
+}
+
/* Set global variables CURRENT_LANG_NAME to appropriate value
so that behavior of name-mangling machinery is correct. */
push_lang_context (name)
tree name;
{
- *current_lang_stack++ = current_lang_name;
- if (current_lang_stack - &VARRAY_TREE (current_lang_base, 0)
- >= (ptrdiff_t) VARRAY_SIZE (current_lang_base))
- {
- size_t old_size = VARRAY_SIZE (current_lang_base);
-
- VARRAY_GROW (current_lang_base, old_size + 10);
- current_lang_stack = &VARRAY_TREE (current_lang_base, old_size);
- }
+ VARRAY_PUSH_TREE (current_lang_base, current_lang_name);
if (name == lang_name_cplusplus)
{
void
pop_lang_context ()
{
- /* Clear the current entry so that garbage collector won't hold on
- to it. */
- *current_lang_stack = NULL_TREE;
- current_lang_name = *--current_lang_stack;
+ current_lang_name = VARRAY_TOP_TREE (current_lang_base);
+ VARRAY_POP (current_lang_base);
}
\f
/* Type instantiation routines. */
fn = TREE_OPERAND (entry, 0);
if ((!integer_zerop (delta) || vcall_index != NULL_TREE)
- && fn != abort_fndecl
- && !DECL_TINFO_FN_P (fn))
+ && fn != abort_fndecl)
{
entry = make_thunk (entry, delta, vcall_index,
generate_with_vtable_p);
tree access_specifier;
tree function_decl;
varray_type lang_base;
- tree *lang_stack;
tree lang_name;
tree template_parms;
tree x_previous_class_type;
/* Pointer to the top of the language name stack. */
-#define current_lang_stack scope_chain->lang_stack
#define current_lang_base scope_chain->lang_base
#define current_lang_name scope_chain->lang_name
unsigned com_interface : 1;
unsigned non_pod_class : 1;
unsigned nearly_empty_p : 1;
- unsigned vtable_needs_writing : 1;
+ unsigned user_align : 1;
unsigned has_assign_ref : 1;
unsigned has_new : 1;
unsigned has_array_new : 1;
unsigned has_abstract_assign_ref : 1;
unsigned non_aggregate : 1;
unsigned is_partial_instantiation : 1;
- unsigned user_align : 1;
/* When adding a flag here, consider whether or not it ought to
apply to a template instance if it applies to the template. If
/* There are some bits left to fill out a 32-bit word. Keep track
of this by updating the size of this bitfield whenever you add or
remove a flag. */
- unsigned dummy : 8;
+ unsigned dummy : 9;
int vsize;
and there is no need to change it. */
#define CLASSTYPE_NEEDS_VIRTUAL_REINIT(NODE) (TYPE_LANG_SPECIFIC(NODE)->needs_virtual_reinit)
-/* Nonzero means that if this type has virtual functions, that
- the virtual function table will be written out. */
-#define CLASSTYPE_VTABLE_NEEDS_WRITING(NODE) (TYPE_LANG_SPECIFIC(NODE)->vtable_needs_writing)
-
/* Nonzero means that this type has an X() constructor. */
#define TYPE_HAS_DEFAULT_CONSTRUCTOR(NODE) (TYPE_LANG_SPECIFIC(NODE)->has_default_ctor)
unsigned pending_inline_p : 1;
unsigned global_ctor_p : 1;
unsigned global_dtor_p : 1;
- unsigned tinfo_fn_p : 1;
unsigned assignment_operator_p : 1;
unsigned anticipated_p : 1;
unsigned generate_with_vtable_p : 1;
- /* One unused bit. */
+ /* Two unused bits. */
union {
/* In a FUNCTION_DECL, VAR_DECL, TYPE_DECL, or TEMPLATE_DECL, this
#define DECL_HAS_IN_CHARGE_PARM_P(NODE) \
(DECL_LANG_SPECIFIC (NODE)->decl_flags.has_in_charge_parm_p)
-/* Non-zero for a FUNCTION_DECL that declares a type-info function.
- This only happens in the old abi. */
-#define DECL_TINFO_FN_P(NODE) \
- (TREE_CODE (NODE) == FUNCTION_DECL \
- && DECL_ARTIFICIAL (NODE) \
- && DECL_LANG_SPECIFIC(NODE)->decl_flags.tinfo_fn_p)
-
-/* Mark NODE as a type-info function. */
-#define SET_DECL_TINFO_FN_P(NODE) \
- (DECL_LANG_SPECIFIC((NODE))->decl_flags.tinfo_fn_p = 1)
-
/* Nonzero if NODE is an overloaded `operator delete[]' function. */
#define DECL_ARRAY_DELETE_OPERATOR_P(NODE) \
(DECL_OVERLOADED_OPERATOR_P (NODE) == VEC_DELETE_EXPR)
/* A node that is a list (length 1) of error_mark_nodes. */
extern tree error_mark_list;
-/* A list of virtual function tables we must make sure to write out. */
-extern tree pending_vtables;
-
/* Node for "pointer to (virtual) function".
This may be distinct from ptr_type_node so gdb can distinguish them. */
#define vfunc_ptr_type_node \
extern void popclass PARAMS ((void));
extern void push_nested_class PARAMS ((tree, int));
extern void pop_nested_class PARAMS ((void));
+extern int current_lang_depth PARAMS ((void));
extern void push_lang_context PARAMS ((tree));
extern void pop_lang_context PARAMS ((void));
extern tree instantiate_type PARAMS ((tree, tree, enum instantiate_type_flags));
scope_chain = s;
current_function_decl = NULL_TREE;
VARRAY_TREE_INIT (current_lang_base, 10, "current_lang_base");
- current_lang_stack = &VARRAY_TREE (current_lang_base, 0);
current_lang_name = lang_name_cplusplus;
current_namespace = global_namespace;
}
/* extern "C" int foo ();
int foo () { bar (); }
is OK. */
- if (current_lang_stack
- == &VARRAY_TREE (current_lang_base, 0))
+ if (current_lang_depth () == 0)
DECL_LANGUAGE (newdecl) = DECL_LANGUAGE (olddecl);
else
{
}
if (TYPE_FOR_JAVA (basetype)
- && (current_lang_stack
- == &VARRAY_TREE (current_lang_base, 0)))
+ && (current_lang_depth () == 0))
TYPE_FOR_JAVA (ref) = 1;
/* Note that the BINFO records which describe individual
extern int current_class_depth;
-/* A list of virtual function tables we must make sure to write out. */
-tree pending_vtables;
-
/* 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, staticly, outside the class. */
DECL_CONTEXT (decl) = current_class_type;
/* We cannot call pushdecl here, because that would fill in the
- decl of our TREE_CHAIN. Instead, we modify cp_finish_decl to do
+ TREE_CHAIN of our decl. Instead, we modify cp_finish_decl to do
the right thing, namely, to put this decl out straight away. */
/* current_class_type can be NULL_TREE in case of error. */
if (!asmspec_tree && current_class_type)
if (TREE_CODE (fnaddr) != ADDR_EXPR)
/* This entry is an offset: a virtual base class offset, a
- virtual call offset, and RTTI offset, etc. */
+ virtual call offset, an RTTI offset, etc. */
continue;
fn = TREE_OPERAND (fnaddr, 0);
method = TREE_CHAIN (method))
if (DECL_VINDEX (method) != NULL_TREE
&& ! DECL_THIS_INLINE (method)
- && ! DECL_PURE_VIRTUAL_P (method))
+ && (! DECL_PURE_VIRTUAL_P (method) || DECL_DESTRUCTOR_P (method)))
return method;
return NULL_TREE;
else if (CLASSTYPE_INTERFACE_KNOWN (type))
{
TREE_PUBLIC (decl) = 1;
- DECL_EXTERNAL (decl) = ! CLASSTYPE_VTABLE_NEEDS_WRITING (type);
+ DECL_EXTERNAL (decl) = CLASSTYPE_INTERFACE_ONLY (type);
DECL_INTERFACE_KNOWN (decl) = 1;
}
else
if (import_export)
{
SET_CLASSTYPE_INTERFACE_KNOWN (ctype);
- CLASSTYPE_VTABLE_NEEDS_WRITING (ctype) = (import_export > 0);
CLASSTYPE_INTERFACE_ONLY (ctype) = (import_export < 0);
}
}
else
comdat_linkage (decl);
}
- else if (DECL_TINFO_FN_P (decl))
+ else if (tinfo_decl_p (decl, 0))
{
tree ctype = TREE_TYPE (DECL_NAME (decl));
ggc_add_tree_root (&ssdf_decl, 1);
ggc_add_tree_root (&priority_decl, 1);
ggc_add_tree_root (&initialize_p_decl, 1);
- ggc_add_tree_root (&pending_vtables, 1);
}
handle_pragma_vtable (dfile)
cpp_reader *dfile ATTRIBUTE_UNUSED;
{
- tree vtbl = parse_strconst_pragma ("vtable", 0);
-
- if (vtbl && vtbl != (tree)-1)
- pending_vtables = tree_cons (NULL_TREE,
- get_identifier (TREE_STRING_POINTER (vtbl)),
- pending_vtables);
+ parse_strconst_pragma ("vtable", 0);
+ sorry ("#pragma vtable no longer supported");
}
static void
return NULL_TREE;
}
- if (TREE_CODE_CLASS (TREE_CODE (t)) == 't')
+ if (TYPE_P (t))
/* Because types were not copied in copy_body, CALL_EXPRs beneath
them should not be expanded. This can happen if the type is a
dynamic array type, for example. */
(for a function or static data member), or a TYPE (for a class)
indicating what we are hoping to instantiate. */
static tree pending_templates;
-static tree *template_tail = &pending_templates;
-
-static tree maybe_templates;
-static tree *maybe_template_tail = &maybe_templates;
+static tree last_pending_template;
int processing_template_parmlist;
static int template_header_count;
init_pt ()
{
ggc_add_tree_root (&pending_templates, 1);
- ggc_add_tree_root (&maybe_templates, 1);
ggc_add_tree_root (&saved_trees, 1);
ggc_add_tree_root (¤t_tinst_level, 1);
}
tree ti = (TYPE_P (d)
? CLASSTYPE_TEMPLATE_INFO (d)
: DECL_TEMPLATE_INFO (d));
+ tree pt;
int level;
if (TI_PENDING_TEMPLATE_FLAG (ti))
if (level)
push_tinst_level (d);
- *template_tail = tree_cons (current_tinst_level, d, NULL_TREE);
- template_tail = &TREE_CHAIN (*template_tail);
+ pt = tree_cons (current_tinst_level, d, NULL_TREE);
+ if (last_pending_template)
+ TREE_CHAIN (last_pending_template) = pt;
+ else
+ pending_templates = pt;
+
+ last_pending_template = pt;
+
TI_PENDING_TEMPLATE_FLAG (ti) = 1;
if (level)
{
CLASSTYPE_INTERFACE_ONLY (type) = interface_only;
SET_CLASSTYPE_INTERFACE_UNKNOWN_X (type, interface_unknown);
- CLASSTYPE_VTABLE_NEEDS_WRITING (type)
- = (! CLASSTYPE_INTERFACE_ONLY (type)
- && CLASSTYPE_INTERFACE_KNOWN (type));
}
else
{
CLASSTYPE_INTERFACE_ONLY (type) = CLASSTYPE_INTERFACE_ONLY (pattern);
SET_CLASSTYPE_INTERFACE_UNKNOWN_X
(type, CLASSTYPE_INTERFACE_UNKNOWN (pattern));
- CLASSTYPE_VTABLE_NEEDS_WRITING (type)
- = (! CLASSTYPE_INTERFACE_ONLY (type)
- && CLASSTYPE_INTERFACE_KNOWN (type));
}
}
else
{
SET_CLASSTYPE_INTERFACE_UNKNOWN (type);
- CLASSTYPE_VTABLE_NEEDS_WRITING (type) = 1;
}
TYPE_HAS_CONSTRUCTOR (type) = TYPE_HAS_CONSTRUCTOR (pattern);
SET_CLASSTYPE_EXPLICIT_INSTANTIATION (t);
SET_CLASSTYPE_INTERFACE_KNOWN (t);
CLASSTYPE_INTERFACE_ONLY (t) = extern_p;
- CLASSTYPE_VTABLE_NEEDS_WRITING (t) = ! extern_p;
TYPE_DECL_SUPPRESS_DEBUG (TYPE_NAME (t)) = extern_p;
if (! extern_p)
{
import_export_decl (d);
}
- /* We need to set up DECL_INITIAL regardless, if
- the variable is initialized in the class body. */
- if (TREE_CODE (d) == VAR_DECL && DECL_INITIALIZED_IN_CLASS_P (d))
- ;
+ if (TREE_CODE (d) == VAR_DECL && DECL_INITIALIZED_IN_CLASS_P (d)
+ && DECL_INITIAL (d) == NULL_TREE)
+ /* We should have set up DECL_INITIAL in instantiate_class_template. */
+ abort ();
/* Reject all external templates except inline functions. */
else if (DECL_INTERFACE_KNOWN (d)
&& ! DECL_NOT_REALLY_EXTERN (d)
member function or static data member of a class template
shall be present in every translation unit in which it is
explicitly instantiated. */
- cp_error ("explicit instantiation of `%D' but no definition available",
- d);
+ cp_pedwarn
+ ("explicit instantiation of `%D' but no definition available", d);
add_pending_template (d);
goto out;
instantiate_pending_templates ()
{
tree *t;
+ tree last = NULL_TREE;
int instantiated_something = 0;
int reconsider;
/* If INSTANTIATION has been instantiated, then we don't
need to consider it again in the future. */
*t = TREE_CHAIN (*t);
- else
- t = &TREE_CHAIN (*t);
+ else
+ {
+ last = *t;
+ t = &TREE_CHAIN (*t);
+ }
}
else
{
/* If INSTANTIATION has been instantiated, then we don't
need to consider it again in the future. */
*t = TREE_CHAIN (*t);
- else
- t = &TREE_CHAIN (*t);
+ else
+ {
+ last = *t;
+ t = &TREE_CHAIN (*t);
+ }
}
tinst_depth = 0;
current_tinst_level = NULL_TREE;
}
- template_tail = t;
-
- /* Go through the things that are template instantiations if we are
- using guiding declarations. */
- t = &maybe_templates;
- while (*t)
- {
- tree template;
- tree fn;
- tree args;
-
- fn = TREE_VALUE (*t);
-
- if (DECL_INITIAL (fn))
- /* If the FN is already defined, then it was either already
- instantiated or, even though guiding declarations were
- allowed, a non-template definition was provided. */
- ;
- else
- {
- template = TREE_PURPOSE (*t);
- args = get_bindings (template, fn, NULL_TREE);
- fn = instantiate_template (template, args);
- instantiate_decl (fn, /*defer_ok=*/0);
- reconsider = 1;
- }
-
- /* Remove this entry from the chain. */
- *t = TREE_CHAIN (*t);
- }
- maybe_template_tail = t;
+ last_pending_template = last;
}
while (reconsider);
fprintf (file, " interface-only");
if (CLASSTYPE_INTERFACE_UNKNOWN (node))
fprintf (file, " interface-unknown");
- if (CLASSTYPE_VTABLE_NEEDS_WRITING (node))
- fprintf (file, " vtable-needs-writing");
print_node (file, "member-functions", CLASSTYPE_METHOD_VEC (node),
indent + 4);
}
{
/* The tinfo decl is the type_info object itself. We make all
tinfo objects look as type_info, even though they will end up
- being a subclass of that when emitted. This means the we'll
+ being a subclass of that when emitted. This means that we'll
erroneously think we know the dynamic type -- be careful in the
runtime. */
d = build_lang_decl (VAR_DECL, name, tinfo_decl_type);
SET_CLASSTYPE_INTERFACE_UNKNOWN_X
(t, interface_unknown);
}
-
- /* Only leave this bit clear if we know this
- class is part of an interface-only specification. */
- if (! CLASSTYPE_INTERFACE_KNOWN (t)
- || ! CLASSTYPE_INTERFACE_ONLY (t))
- CLASSTYPE_VTABLE_NEEDS_WRITING (t) = 1;
}
reset_specialization();