summaryrefslogtreecommitdiff
path: root/gcc/gengtype.c
diff options
context:
space:
mode:
authorrsandifo <rsandifo@138bc75d-0d04-0410-961f-82ee72b054a4>2013-12-04 12:54:49 +0000
committerrsandifo <rsandifo@138bc75d-0d04-0410-961f-82ee72b054a4>2013-12-04 12:54:49 +0000
commitbdff91a14bf8e5d18b1eb47bb529894482065762 (patch)
tree4515b21fe5d3e25b4d5c8f907d3e78834e1e40ac /gcc/gengtype.c
parent0158370253d4aef042c4d67b2c0278ded58d83fd (diff)
parent8192796762b4781de57ce2a6c104a71dcbd874e3 (diff)
downloadgcc-bdff91a14bf8e5d18b1eb47bb529894482065762.tar.gz
Merge with trunk.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/wide-int@205668 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/gengtype.c')
-rw-r--r--gcc/gengtype.c45
1 files changed, 41 insertions, 4 deletions
diff --git a/gcc/gengtype.c b/gcc/gengtype.c
index 0c0195c1606..33684331a93 100644
--- a/gcc/gengtype.c
+++ b/gcc/gengtype.c
@@ -1768,6 +1768,9 @@ open_base_files (void)
"tree.h", "rtl.h", "wide-int.h", "function.h", "insn-config.h", "expr.h",
"hard-reg-set.h", "basic-block.h", "cselib.h", "insn-addr.h",
"optabs.h", "libfuncs.h", "debug.h", "ggc.h", "cgraph.h",
+ "pointer-set.h", "hash-table.h", "vec.h", "ggc.h", "basic-block.h",
+ "tree-ssa-alias.h", "internal-fn.h", "gimple-fold.h", "tree-eh.h",
+ "gimple-expr.h", "is-a.h",
"gimple.h", "gimple-iterator.h", "gimple-ssa.h", "tree-cfg.h",
"tree-phinodes.h", "ssa-iterators.h", "stringpool.h", "tree-ssanames.h",
"tree-ssa-loop.h", "tree-ssa-loop-ivopts.h", "tree-ssa-loop-manip.h",
@@ -2653,15 +2656,48 @@ get_string_option (options_p opt, const char *key)
return NULL;
}
+/* Machinery for avoiding duplicate tags within switch statements. */
+struct seen_tag
+{
+ const char *tag;
+ struct seen_tag *next;
+};
+
+int
+already_seen_tag (struct seen_tag *seen_tags, const char *tag)
+{
+ /* Linear search, so O(n^2), but n is currently small. */
+ while (seen_tags)
+ {
+ if (!strcmp (seen_tags->tag, tag))
+ return 1;
+ seen_tags = seen_tags->next;
+ }
+ /* Not yet seen this tag. */
+ return 0;
+}
+
+void
+mark_tag_as_seen (struct seen_tag **seen_tags, const char *tag)
+{
+ /* Add to front of linked list. */
+ struct seen_tag *new_node = XCNEW (struct seen_tag);
+ new_node->tag = tag;
+ new_node->next = *seen_tags;
+ *seen_tags = new_node;
+}
+
static void
-walk_subclasses (type_p base, struct walk_type_data *d)
+walk_subclasses (type_p base, struct walk_type_data *d,
+ struct seen_tag **seen_tags)
{
for (type_p sub = base->u.s.first_subclass; sub != NULL;
sub = sub->u.s.next_sibling_class)
{
const char *type_tag = get_string_option (sub->u.s.opt, "tag");
- if (type_tag)
+ if (type_tag && !already_seen_tag (*seen_tags, type_tag))
{
+ mark_tag_as_seen (seen_tags, type_tag);
oprintf (d->of, "%*scase %s:\n", d->indent, "", type_tag);
d->indent += 2;
oprintf (d->of, "%*s{\n", d->indent, "");
@@ -2677,7 +2713,7 @@ walk_subclasses (type_p base, struct walk_type_data *d)
oprintf (d->of, "%*sbreak;\n", d->indent, "");
d->indent -= 2;
}
- walk_subclasses (sub, d);
+ walk_subclasses (sub, d, seen_tags);
}
}
@@ -3224,7 +3260,8 @@ walk_type (type_p t, struct walk_type_data *d)
else if (desc)
{
/* Add cases to handle subclasses. */
- walk_subclasses (t, d);
+ struct seen_tag *tags = NULL;
+ walk_subclasses (t, d, &tags);
/* Ensure that if someone forgets a "tag" option that we don't
silent fail to traverse that subclass's fields. */