aboutsummaryrefslogtreecommitdiff
path: root/gcc/c-decl.c
diff options
context:
space:
mode:
authorJoseph Myers <joseph@codesourcery.com>2010-05-09 17:19:28 +0100
committerJoseph Myers <jsm28@gcc.gnu.org>2010-05-09 17:19:28 +0100
commit492fc0eec511c06f6f159b7d88bc7a8212ce5c23 (patch)
tree40f3750c5c0d3e75e4ae38fc558b95bd1d59a14b /gcc/c-decl.c
parent44f276c65fc93a5ced092eca774c772cb10acd66 (diff)
downloadgcc-492fc0eec511c06f6f159b7d88bc7a8212ce5c23.zip
gcc-492fc0eec511c06f6f159b7d88bc7a8212ce5c23.tar.gz
gcc-492fc0eec511c06f6f159b7d88bc7a8212ce5c23.tar.bz2
re PR c/4784 (Anonymous structs issues)
PR c/4784 * c-decl.c (detect_field_duplicates_hash): New. Handle anonymous structures and unions recursively. (detect_field_duplicates): Move duplicate detection with a hash to detect_field_duplicates_hash. Always use a hash if anonymous structures or unions are present. * doc/extend.texi (Unnamed Fields): Document that duplicate fields give errors. testsuite: * gcc.dg/anon-struct-9.c: New test. From-SVN: r159204
Diffstat (limited to 'gcc/c-decl.c')
-rw-r--r--gcc/c-decl.c48
1 files changed, 33 insertions, 15 deletions
diff --git a/gcc/c-decl.c b/gcc/c-decl.c
index dd07b65..03211d6 100644
--- a/gcc/c-decl.c
+++ b/gcc/c-decl.c
@@ -6629,6 +6629,31 @@ grokfield (location_t loc,
return value;
}
+/* Subroutine of detect_field_duplicates: add the fields of FIELDLIST
+ to HTAB, giving errors for any duplicates. */
+
+static void
+detect_field_duplicates_hash (tree fieldlist, htab_t htab)
+{
+ tree x, y;
+ 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 ("duplicate member %q+D", x);
+ DECL_NAME (x) = NULL_TREE;
+ }
+ *slot = y;
+ }
+ else if (TREE_CODE (TREE_TYPE (x)) == RECORD_TYPE
+ || TREE_CODE (TREE_TYPE (x)) == UNION_TYPE)
+ detect_field_duplicates_hash (TYPE_FIELDS (TREE_TYPE (x)), htab);
+}
+
/* Generate an error for any duplicate field names in FIELDLIST. Munge
the list such that this does not present a problem later. */
@@ -6647,11 +6672,16 @@ detect_field_duplicates (tree fieldlist)
return;
do {
timeout--;
+ if (DECL_NAME (x) == NULL_TREE
+ && (TREE_CODE (TREE_TYPE (x)) == RECORD_TYPE
+ || TREE_CODE (TREE_TYPE (x)) == UNION_TYPE))
+ timeout = 0;
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 there were "few" fields and no anonymous structures or unions,
+ 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))
@@ -6668,20 +6698,8 @@ detect_field_duplicates (tree fieldlist)
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 ("duplicate member %q+D", x);
- DECL_NAME (x) = NULL_TREE;
- }
- *slot = y;
- }
+ detect_field_duplicates_hash (fieldlist, htab);
htab_delete (htab);
}
}