diff options
author | rth <rth@138bc75d-0d04-0410-961f-82ee72b054a4> | 2003-05-12 03:25:38 +0000 |
---|---|---|
committer | rth <rth@138bc75d-0d04-0410-961f-82ee72b054a4> | 2003-05-12 03:25:38 +0000 |
commit | 4d2aa485d66d731a3726186c5be15f869b5895f9 (patch) | |
tree | d64fee370dcba52f3ebdc46db60f749bc198bad5 /gcc/c-decl.c | |
parent | 26398ccb63dde50f8039ed075b55280a2521f4d3 (diff) | |
download | gcc-4d2aa485d66d731a3726186c5be15f869b5895f9.tar.gz |
PR c/10675
* c-decl.c: Include hashtab.h.
(detect_field_duplicates): New.
(finish_struct): Use it.
* Makefile.in (c-decl.o): Update.
* c-parse.in (structsp_attr): Nreverse component_decl_list results.
(component_decl_list, component_decl_list2,
components, components_notype): Build list in reverse order.
(enumlist): Clarify docs. Use TREE_CHAIN not chainon.
* tree.c (chainon): Special case op2 null as well.
Reorg for clarity.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@66710 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/c-decl.c')
-rw-r--r-- | gcc/c-decl.c | 84 |
1 files changed, 59 insertions, 25 deletions
diff --git a/gcc/c-decl.c b/gcc/c-decl.c index 7ac47391b6f..b27ca06c79d 100644 --- a/gcc/c-decl.c +++ b/gcc/c-decl.c @@ -49,6 +49,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA #include "c-common.h" #include "c-pragma.h" #include "cgraph.h" +#include "hashtab.h" /* In grokdeclarator, distinguish syntactic contexts of declarators. */ enum decl_context @@ -4883,6 +4884,63 @@ grokfield (filename, line, declarator, declspecs, width) return value; } +/* Generate an error for any duplicate field names in FIELDLIST. Munge + the list such that this does not present a problem later. */ + +static void +detect_field_duplicates (tree fieldlist) +{ + tree x, y; + int timeout = 10; + + /* First, see if there are more than "a few" fields. + This is trivially true if there are zero or one fields. */ + if (!fieldlist) + return; + x = TREE_CHAIN (fieldlist); + if (!x) + return; + do { + timeout--; + x = TREE_CHAIN (x); + } while (timeout > 0 && x); + + /* If there were "few" fields, avoid the overhead of allocating + a hash table. Instead just do the nested traversal thing. */ + if (timeout > 0) + { + for (x = TREE_CHAIN (fieldlist); x ; x = TREE_CHAIN (x)) + if (DECL_NAME (x)) + { + for (y = fieldlist; y != x; y = TREE_CHAIN (y)) + if (DECL_NAME (y) == DECL_NAME (x)) + { + error_with_decl (x, "duplicate member `%s'"); + DECL_NAME (x) = NULL_TREE; + } + } + } + else + { + htab_t htab = htab_create (37, htab_hash_pointer, htab_eq_pointer, NULL); + void **slot; + + for (x = fieldlist; x ; x = TREE_CHAIN (x)) + if ((y = DECL_NAME (x)) != 0) + { + slot = htab_find_slot (htab, y, INSERT); + if (*slot) + { + error_with_decl (x, "duplicate member `%s'"); + DECL_NAME (x) = NULL_TREE; + } + *slot = y; + } + + htab_delete (htab); + } +} + /* Fill in the fields of a RECORD_TYPE or UNION_TYPE node, T. FIELDLIST is a chain of FIELD_DECL nodes for the fields. ATTRIBUTES are attributes to be applied to the structure. */ @@ -5062,31 +5120,7 @@ finish_struct (t, fieldlist, attributes) saw_named_field = 1; } - /* Delete all duplicate fields from the fieldlist */ - for (x = fieldlist; x && TREE_CHAIN (x);) - /* Anonymous fields aren't duplicates. */ - if (DECL_NAME (TREE_CHAIN (x)) == 0) - x = TREE_CHAIN (x); - else - { - tree y = fieldlist; - - while (1) - { - if (DECL_NAME (y) == DECL_NAME (TREE_CHAIN (x))) - break; - if (y == x) - break; - y = TREE_CHAIN (y); - } - if (DECL_NAME (y) == DECL_NAME (TREE_CHAIN (x))) - { - error_with_decl (TREE_CHAIN (x), "duplicate member `%s'"); - TREE_CHAIN (x) = TREE_CHAIN (TREE_CHAIN (x)); - } - else - x = TREE_CHAIN (x); - } + detect_field_duplicates (fieldlist); /* Now we have the nearly final fieldlist. Record it, then lay out the structure or union (including the fields). */ |