static int is_type_die (dw_die_ref);
static int is_comdat_die (dw_die_ref);
static int is_symbol_die (dw_die_ref);
+static inline bool is_template_instantiation (dw_die_ref);
static void assign_symbol_names (dw_die_ref);
static void break_out_includes (dw_die_ref);
static int is_declaration_die (dw_die_ref);
CHECKSUM_ATTR (attrs.at_type);
CHECKSUM_ATTR (attrs.at_friend);
- /* Checksum the child DIEs, except for nested types and member functions. */
+ /* Checksum the child DIEs. */
c = die->die_child;
if (c) do {
dw_attr_ref name_attr;
c = c->die_sib;
name_attr = get_AT (c, DW_AT_name);
- if ((is_type_die (c) || c->die_tag == DW_TAG_subprogram)
- && name_attr != NULL)
+ if (is_template_instantiation (c))
{
+ /* Ignore instantiations of member type and function templates. */
+ }
+ else if (name_attr != NULL
+ && (is_type_die (c) || c->die_tag == DW_TAG_subprogram))
+ {
+ /* Use a shallow checksum for named nested types and member
+ functions. */
CHECKSUM_ULEB128 ('S');
CHECKSUM_ULEB128 (c->die_tag);
CHECKSUM_STRING (AT_string (name_attr));
}
else
{
+ /* Use a deep checksum for other children. */
/* Mark this DIE so it gets processed when unmarking. */
if (c->die_mark == 0)
c->die_mark = -1;
|| c->die_tag == DW_TAG_structure_type);
}
+/* Return non-zero if this DIE is a template parameter. */
+
+static inline bool
+is_template_parameter (dw_die_ref die)
+{
+ switch (die->die_tag)
+ {
+ case DW_TAG_template_type_param:
+ case DW_TAG_template_value_param:
+ case DW_TAG_GNU_template_template_param:
+ case DW_TAG_GNU_template_parameter_pack:
+ return true;
+ default:
+ return false;
+ }
+}
+
+/* Return non-zero if this DIE represents a template instantiation. */
+
+static inline bool
+is_template_instantiation (dw_die_ref die)
+{
+ dw_die_ref c;
+
+ if (!is_type_die (die) && die->die_tag != DW_TAG_subprogram)
+ return false;
+ FOR_EACH_CHILD (die, c, if (is_template_parameter (c)) return true);
+ return false;
+}
+
static char *
gen_internal_sym (const char *prefix)
{
node.new_die = NULL;
if (is_declaration_die (c))
{
- /* Clone the existing DIE, move the original to the skeleton
- tree (which is in the main CU), and put the clone, with
- all the original's children, where the original came from. */
- dw_die_ref clone = clone_die (c);
- move_all_children (c, clone);
-
- replace_child (c, clone, prev);
- generate_skeleton_ancestor_tree (parent);
- add_child_die (parent->new_die, c);
- node.new_die = c;
- c = clone;
+ if (is_template_instantiation (c))
+ {
+ /* Instantiated templates do not need to be cloned into the
+ type unit. Just move the DIE and its children back to
+ the skeleton tree (in the main CU). */
+ remove_child_with_prev (c, prev);
+ add_child_die (parent->new_die, c);
+ c = prev;
+ }
+ else
+ {
+ /* Clone the existing DIE, move the original to the skeleton
+ tree (which is in the main CU), and put the clone, with
+ all the original's children, where the original came from
+ (which is about to be moved to the type unit). */
+ dw_die_ref clone = clone_die (c);
+ move_all_children (c, clone);
+
+ replace_child (c, clone, prev);
+ generate_skeleton_ancestor_tree (parent);
+ add_child_die (parent->new_die, c);
+ node.new_die = c;
+ c = clone;
+ }
}
generate_skeleton_bottom_up (&node);
} while (next != NULL);
node.parent = NULL;
/* If this type definition is nested inside another type,
- always leave at least a declaration in its place. */
- if (die->die_parent != NULL && is_type_die (die->die_parent))
+ and is not an instantiation of a template, always leave
+ at least a declaration in its place. */
+ if (die->die_parent != NULL
+ && is_type_die (die->die_parent)
+ && !is_template_instantiation (die))
node.new_die = clone_as_declaration (die);
generate_skeleton_bottom_up (&node);
dw_die_ref replacement;
comdat_type_node_ref type_node;
+ /* Break out nested types into their own type units. */
+ break_out_comdat_types (c);
+
/* Create a new type unit DIE as the root for the new tree, and
add it to the list of comdat types. */
unit = new_die (DW_TAG_type_unit, NULL, NULL);
replacement = remove_child_or_replace_with_skeleton (unit, c, prev);
type_node->skeleton_die = replacement;
- /* Break out nested types into their own type units. */
- break_out_comdat_types (c);
-
/* Add the DIE to the new compunit. */
add_child_die (unit, c);
c = die->die_child;
do
{
- switch (c->die_tag)
- {
- case DW_TAG_template_type_param:
- case DW_TAG_template_value_param:
- case DW_TAG_GNU_template_template_param:
- case DW_TAG_GNU_template_parameter_pack:
- prune_unused_types_mark (c, 1);
- break;
- default:
- break;
- }
+ if (is_template_parameter (c))
+ prune_unused_types_mark (c, 1);
c = c->die_sib;
} while (c && c != die->die_child);
}