From 52361fddf8a982d13e271b907ff2ae88b3f548a8 Mon Sep 17 00:00:00 2001 From: Joseph Myers Date: Sun, 9 May 2010 16:19:28 +0000 Subject: 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. git-svn-id: https://gcc.gnu.org/svn/gcc/trunk@159204 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 11 +++ gcc/c-decl.c | 48 +++++++++---- gcc/doc/extend.texi | 3 +- gcc/testsuite/ChangeLog | 5 ++ gcc/testsuite/gcc.dg/anon-struct-9.c | 129 +++++++++++++++++++++++++++++++++++ 5 files changed, 179 insertions(+), 17 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/anon-struct-9.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 3a9d1f9dd05..8879737b91c 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,14 @@ +2010-05-09 Joseph Myers + + 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. + 2010-05-09 H.J. Lu PR target/44046 diff --git a/gcc/c-decl.c b/gcc/c-decl.c index dd07b6582d8..03211d674d7 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); } } diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi index bf748636083..7a495ebfd64 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -12760,8 +12760,7 @@ struct @{ @end smallexample It is ambiguous which @code{a} is being referred to with @samp{foo.a}. -Such constructs are not supported and must be avoided. In the future, -such constructs may be detected and treated as compilation errors. +The compiler gives errors for such constructs. @opindex fms-extensions Unless @option{-fms-extensions} is used, the unnamed field must be a diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index bd28f187622..cf4140d7691 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2010-05-09 Joseph Myers + + PR c/4784 + * gcc.dg/anon-struct-9.c: New test. + 2010-05-09 Richard Guenther PR middle-end/44043 diff --git a/gcc/testsuite/gcc.dg/anon-struct-9.c b/gcc/testsuite/gcc.dg/anon-struct-9.c new file mode 100644 index 00000000000..2658ccb7948 --- /dev/null +++ b/gcc/testsuite/gcc.dg/anon-struct-9.c @@ -0,0 +1,129 @@ +/* Test for diagnostics for duplicate member names in anonymous + structures and unions. PR 4784. */ +/* { dg-do compile } */ +/* { dg-options "" } */ + +struct s1 +{ + int x; + struct + { + int x; /* { dg-error "duplicate member" } */ + }; +}; + +struct s2 +{ + struct + { + int a; + struct + { + int b; + }; + }; + struct + { + int b; /* { dg-error "duplicate member" } */ + }; +}; + +struct s3 +{ + struct + { + int a; + struct + { + int b; + }; + }; + struct + { + int b; /* { dg-error "duplicate member" } */ + int c; + }; +}; + +struct s4 +{ + int x; + struct + { + int x; + } y; +}; + +union u1 +{ + int x; + union + { + int x; /* { dg-error "duplicate member" } */ + }; +}; + +union u2 +{ + union + { + int a; + union + { + int b; + }; + }; + union + { + int b; /* { dg-error "duplicate member" } */ + }; +}; + +union u3 +{ + union + { + int a; + union + { + int b; + }; + }; + union + { + int b; /* { dg-error "duplicate member" } */ + int c; + }; +}; + +union u4 +{ + int x; + union + { + int x; + } y; +}; + +#define D10(x) int x##0; int x##1; int x##2; int x##3; int x##4; int x##5; int x##6; int x##7; int x##8; int x##9; +#define D100(x) D10(x##0) D10(x##1) D10(x##2) D10(x##3) D10(x##4) D10(x##5) D10(x##6) D10(x##7) D10(x##8) D10(x##9) + +#define S10(x) struct { D100(x##0) }; struct { D100(x##1) }; struct { D100(x##2) }; struct { D100(x##3) }; struct { D100(x##4) }; struct { D100(x##5) }; struct { D100(x##6) }; struct { D100(x##7) }; struct { D100(x##8) }; struct { D100(x##9) }; + +struct sbig +{ + S10(a) + S10(b) + S10(c) + S10(d) + S10(e) + S10(f) + S10(g) + S10(h) + S10(i) + S10(j) + struct + { + int a123; /* { dg-error "duplicate member" } */ + }; +}; -- cgit v1.2.3