From 46ccf50a6febbed2c9ce0aa03b16c047f7699253 Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Wed, 21 Mar 2001 19:55:13 -0500 Subject: [PATCH] pt.c (instantiate_decl): Abort if we see a member constant instantiation that doesn't already have its... * 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. From-SVN: r40724 --- gcc/cp/ChangeLog | 38 ++++++++++++++++++++- gcc/cp/class.c | 27 +++++++-------- gcc/cp/cp-tree.h | 29 +++------------- gcc/cp/decl.c | 7 ++-- gcc/cp/decl2.c | 15 +++------ gcc/cp/lex.c | 8 ++--- gcc/cp/optimize.c | 2 +- gcc/cp/pt.c | 84 ++++++++++++++++------------------------------ gcc/cp/ptree.c | 2 -- gcc/cp/rtti.c | 2 +- gcc/cp/semantics.c | 6 ---- 11 files changed, 92 insertions(+), 128 deletions(-) diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 578d0b11c53..f1cdaa755bd 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,4 +1,40 @@ -2001-03-20 Jason Merrill +2001-03-21 Jason Merrill + + * 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 '__'. diff --git a/gcc/cp/class.c b/gcc/cp/class.c index f082580e0cf..ea726d8c572 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -5757,6 +5757,14 @@ pop_nested_class () 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. */ @@ -5764,15 +5772,7 @@ void 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) { @@ -5807,10 +5807,8 @@ push_lang_context (name) 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); } /* Type instantiation routines. */ @@ -7847,8 +7845,7 @@ build_vtable_entry (delta, vcall_index, entry, generate_with_vtable_p) 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); diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index eb4bc7c5454..de63fb1813a 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -787,7 +787,6 @@ struct saved_scope { tree access_specifier; tree function_decl; varray_type lang_base; - tree *lang_stack; tree lang_name; tree template_parms; tree x_previous_class_type; @@ -830,7 +829,6 @@ struct saved_scope { /* 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 @@ -1296,7 +1294,7 @@ struct lang_type 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; @@ -1328,7 +1326,6 @@ struct lang_type 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 @@ -1337,7 +1334,7 @@ struct lang_type /* 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; @@ -1573,10 +1570,6 @@ struct lang_type 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) @@ -1824,11 +1817,10 @@ struct lang_decl_flags 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 @@ -2032,17 +2024,6 @@ struct lang_decl #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) @@ -3190,9 +3171,6 @@ extern int warn_nontemplate_friend; /* 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 \ @@ -3727,6 +3705,7 @@ extern void pushclass PARAMS ((tree, int)); 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)); diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index f540cc5475a..67aea126f48 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -2531,7 +2531,6 @@ maybe_push_to_top_level (pseudo) 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; } @@ -3313,8 +3312,7 @@ duplicate_decls (newdecl, olddecl) /* 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 { @@ -12723,8 +12721,7 @@ xref_basetypes (code_type_node, name, ref, binfo) } 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 diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index 1487a5be9e2..a8300b9fc9a 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -94,9 +94,6 @@ static tree get_guard_bits PARAMS ((tree)); 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. */ @@ -1514,7 +1511,7 @@ finish_static_data_member_decl (decl, init, asmspec_tree, flags) 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) @@ -2297,7 +2294,7 @@ mark_vtable_entries (decl) 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); @@ -2411,7 +2408,7 @@ key_method (type) 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; @@ -2440,7 +2437,7 @@ import_export_vtable (decl, type, final) 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 @@ -2525,7 +2522,6 @@ import_export_class (ctype) if (import_export) { SET_CLASSTYPE_INTERFACE_KNOWN (ctype); - CLASSTYPE_VTABLE_NEEDS_WRITING (ctype) = (import_export > 0); CLASSTYPE_INTERFACE_ONLY (ctype) = (import_export < 0); } } @@ -2695,7 +2691,7 @@ import_export_decl (decl) 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)); @@ -5387,5 +5383,4 @@ init_decl2 () 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); } diff --git a/gcc/cp/lex.c b/gcc/cp/lex.c index 690e66a38da..97f74602498 100644 --- a/gcc/cp/lex.c +++ b/gcc/cp/lex.c @@ -1078,12 +1078,8 @@ static void 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 diff --git a/gcc/cp/optimize.c b/gcc/cp/optimize.c index d1bfd0dd3c5..c1cbf52c9fc 100644 --- a/gcc/cp/optimize.c +++ b/gcc/cp/optimize.c @@ -686,7 +686,7 @@ expand_call_inline (tp, walk_subtrees, data) 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. */ diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 1644f739aa0..e4e647167da 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -57,10 +57,7 @@ extern struct obstack permanent_obstack; (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; @@ -176,7 +173,6 @@ void 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); } @@ -3719,6 +3715,7 @@ add_pending_template (d) tree ti = (TYPE_P (d) ? CLASSTYPE_TEMPLATE_INFO (d) : DECL_TEMPLATE_INFO (d)); + tree pt; int level; if (TI_PENDING_TEMPLATE_FLAG (ti)) @@ -3732,8 +3729,14 @@ add_pending_template (d) 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) @@ -4962,24 +4965,17 @@ instantiate_class_template (type) { 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); @@ -9471,7 +9467,6 @@ mark_class_instantiated (t, extern_p) 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) { @@ -9859,10 +9854,10 @@ instantiate_decl (d, defer_ok) 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) @@ -9885,8 +9880,8 @@ instantiate_decl (d, defer_ok) 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; @@ -9979,6 +9974,7 @@ int instantiate_pending_templates () { tree *t; + tree last = NULL_TREE; int instantiated_something = 0; int reconsider; @@ -10017,8 +10013,11 @@ instantiate_pending_templates () /* 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 { @@ -10039,43 +10038,16 @@ instantiate_pending_templates () /* 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); diff --git a/gcc/cp/ptree.c b/gcc/cp/ptree.c index 5c4ac846701..8f2f577cc61 100644 --- a/gcc/cp/ptree.c +++ b/gcc/cp/ptree.c @@ -152,8 +152,6 @@ print_lang_type (file, node, indent) 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); } diff --git a/gcc/cp/rtti.c b/gcc/cp/rtti.c index 49fc1ba5b1a..0cb37753f3d 100644 --- a/gcc/cp/rtti.c +++ b/gcc/cp/rtti.c @@ -340,7 +340,7 @@ get_tinfo_decl (type) { /* 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); diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index dec0e8d0b4a..6e037f4d727 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -1825,12 +1825,6 @@ begin_class_definition (t) 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();