@@ -112,6 +112,10 @@ static GTY (()) tree sizeof_biggest_empty_class;
declaration order. */
VEC(tree,gc) *local_classes;
+/* A list of the dynamic classes whose vtables may have to be
+ emitted in this translation unit. */
+VEC(tree,gc) *keyed_classes;
+
static tree get_vfield_name (tree);
static void finish_struct_anon (tree);
static tree get_vtable_name (tree);
@@ -5450,7 +5454,7 @@ finish_struct_1 (tree t)
/* If a polymorphic class has no key method, we may emit the vtable
in every translation unit where the class definition appears. */
if (CLASSTYPE_KEY_METHOD (t) == NULL_TREE)
- keyed_classes = tree_cons (NULL_TREE, t, keyed_classes);
+ VEC_safe_push (tree, gc, keyed_classes, t);
}
/* Layout the class itself. */
@@ -793,8 +793,6 @@ enum cp_tree_index
CPTI_DSO_HANDLE,
CPTI_DCAST,
- CPTI_KEYED_CLASSES,
-
CPTI_NULLPTR,
CPTI_NULLPTR_TYPE,
@@ -906,11 +904,6 @@ extern GTY(()) tree cp_global_trees[CPTI_MAX];
destructors. */
#define vtt_parm_type cp_global_trees[CPTI_VTT_PARM_TYPE]
-/* A TREE_LIST of the dynamic classes whose vtables may have to be
- emitted in this translation unit. */
-
-#define keyed_classes cp_global_trees[CPTI_KEYED_CLASSES]
-
/* Node to indicate default access. This must be distinct from the
access nodes in tree.h. */
@@ -4029,6 +4022,10 @@ extern int current_class_depth;
/* An array of all local classes present in this translation unit, in
declaration order. */
extern GTY(()) VEC(tree,gc) *local_classes;
+
+/* A list of the dynamic classes whose vtables may have to be
+ emitted in this translation unit. */
+extern GTY(()) VEC(tree,gc) *keyed_classes;
/* Here's where we control how name mangling takes place. */
@@ -12577,7 +12577,7 @@ record_key_method_defined (tree fndecl)
{
tree fnclass = DECL_CONTEXT (fndecl);
if (fndecl == CLASSTYPE_KEY_METHOD (fnclass))
- keyed_classes = tree_cons (NULL_TREE, fnclass, keyed_classes);
+ VEC_safe_push (tree, gc, keyed_classes, fnclass);
}
}
@@ -3643,30 +3643,38 @@ cp_write_global_declarations (void)
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)))
+ while (!VEC_empty (tree, keyed_classes)
+ && maybe_emit_vtables (VEC_last (tree, keyed_classes)))
{
reconsider = true;
- keyed_classes = TREE_CHAIN (keyed_classes);
+ VEC_pop (tree, keyed_classes);
}
- t = keyed_classes;
- if (t != NULL_TREE)
+ /* The last element of the vector (if it exists) has not been
+ written out. We still need to iterate through any remaining
+ members and write them out if necessary. Do this by
+ maintaining two indices into the vector: one for the next
+ candidate to consider and another for the point at which known
+ unwritten entries start. */
+
+ if (!VEC_empty (tree, keyed_classes))
{
- tree next = TREE_CHAIN (t);
+ int unwritten = VEC_length (tree, keyed_classes) - 1;
+ int next_idx = unwritten - 1;
- while (next)
+ while (next_idx >= 0)
{
- if (maybe_emit_vtables (TREE_VALUE (next)))
- {
- reconsider = true;
- TREE_CHAIN (t) = TREE_CHAIN (next);
- }
+ tree candidate = VEC_index (tree, keyed_classes, next_idx--);
+ if (maybe_emit_vtables (candidate))
+ reconsider = true;
else
- t = next;
-
- next = TREE_CHAIN (t);
+ /* We didn't write out CANDIDATE. We need to slide it
+ to the front of the unwritten entries. */
+ VEC_replace (tree, keyed_classes, --unwritten, candidate);
}
+
+ /* All done. Slide all the unwritten elements down. */
+ VEC_block_remove (tree, keyed_classes, 0, unwritten);
}
/* Write out needed type info variables. We have to be careful
@@ -8251,7 +8251,7 @@ instantiate_class_template (tree type)
method, however, finish_struct_1 will already have added TYPE to
the keyed_classes list. */
if (TYPE_CONTAINS_VPTR_P (type) && CLASSTYPE_KEY_METHOD (type))
- keyed_classes = tree_cons (NULL_TREE, type, keyed_classes);
+ VEC_safe_push (tree, gc, keyed_classes, type);
return type;
}