diff options
author | rsandifo <rsandifo@138bc75d-0d04-0410-961f-82ee72b054a4> | 2013-12-04 12:54:49 +0000 |
---|---|---|
committer | rsandifo <rsandifo@138bc75d-0d04-0410-961f-82ee72b054a4> | 2013-12-04 12:54:49 +0000 |
commit | bdff91a14bf8e5d18b1eb47bb529894482065762 (patch) | |
tree | 4515b21fe5d3e25b4d5c8f907d3e78834e1e40ac /gcc/gengtype.c | |
parent | 0158370253d4aef042c4d67b2c0278ded58d83fd (diff) | |
parent | 8192796762b4781de57ce2a6c104a71dcbd874e3 (diff) | |
download | gcc-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.c | 45 |
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. */ |