diff options
author | Joseph Myers <joseph@codesourcery.com> | 2010-05-09 17:19:28 +0100 |
---|---|---|
committer | Joseph Myers <jsm28@gcc.gnu.org> | 2010-05-09 17:19:28 +0100 |
commit | 492fc0eec511c06f6f159b7d88bc7a8212ce5c23 (patch) | |
tree | 40f3750c5c0d3e75e4ae38fc558b95bd1d59a14b /gcc/c-decl.c | |
parent | 44f276c65fc93a5ced092eca774c772cb10acd66 (diff) | |
download | gcc-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.c | 48 |
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); } } |