summaryrefslogtreecommitdiff
path: root/gcc/c-decl.c
diff options
context:
space:
mode:
authorrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>2003-05-12 03:25:38 +0000
committerrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>2003-05-12 03:25:38 +0000
commit4d2aa485d66d731a3726186c5be15f869b5895f9 (patch)
treed64fee370dcba52f3ebdc46db60f749bc198bad5 /gcc/c-decl.c
parent26398ccb63dde50f8039ed075b55280a2521f4d3 (diff)
downloadgcc-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.c84
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). */