aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoseph Myers <joseph@codesourcery.com>2010-05-09 16:19:28 +0000
committerJoseph Myers <joseph@codesourcery.com>2010-05-09 16:19:28 +0000
commit52361fddf8a982d13e271b907ff2ae88b3f548a8 (patch)
tree40f3750c5c0d3e75e4ae38fc558b95bd1d59a14b
parent3b5805cbbe8a247ca09b42bebfffc8578c999dbb (diff)
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
-rw-r--r--gcc/ChangeLog11
-rw-r--r--gcc/c-decl.c48
-rw-r--r--gcc/doc/extend.texi3
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.dg/anon-struct-9.c129
5 files changed, 179 insertions, 17 deletions
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 <joseph@codesourcery.com>
+
+ 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 <hongjiu.lu@intel.com>
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 <joseph@codesourcery.com>
+
+ PR c/4784
+ * gcc.dg/anon-struct-9.c: New test.
+
2010-05-09 Richard Guenther <rguenther@suse.de>
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" } */
+ };
+};