diff options
author | Ian Lance Taylor <iant@google.com> | 2010-10-04 03:50:39 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@gcc.gnu.org> | 2010-10-04 03:50:39 +0000 |
commit | 478a1c5b906a165853b77a8dd1c0548b66ace018 (patch) | |
tree | c18cd90272c7a2cb06261eb2a6d5a845ebb150f2 /gcc/c-decl.c | |
parent | 3b5269a95e9e50001c2e4fabbb1712c9e984a09d (diff) | |
download | gcc-478a1c5b906a165853b77a8dd1c0548b66ace018.zip gcc-478a1c5b906a165853b77a8dd1c0548b66ace018.tar.gz gcc-478a1c5b906a165853b77a8dd1c0548b66ace018.tar.bz2 |
c-typeck.c (lookup_field): If -fplan9-extensions, permit referring to a field using a typedef name.
gcc/:
* c-typeck.c (lookup_field): If -fplan9-extensions, permit
referring to a field using a typedef name.
(find_anonymous_field_with_type): New static function.
(convert_to_anonymous_field): New static function.
(convert_for_assignment): If -fplan9-extensions, permit converting
pointer to struct to pointer to anonymous field.
* c-decl.c (grokfield): If -fplan9-extensions, permit anonymous
fields.
(is_duplicate_field): New static function.
(detect_field_duplicates_hash): If -fplan9-extensions, check for
typedef names duplicating field names.
(detect_field_duplicates): Likewise.
* doc/invoke.texi (Option Summary): Mention -fplan9-extensions.
(C Dialect Options): Document -fplan9-extensions.
* doc/extend.texi (Unnamed Fields): Document -fplan9-extensions.
gcc/c-family/:
* c.opt (-fplan9-extensions): New option.
gcc/testsuite/:
* gcc.dg/anon-struct-11.c: New test.
* gcc.dg/anon-struct-12.c: New test.
* gcc.dg/anon-struct-13.c: New test.
* gcc.dg/anon-struct-14.c: New test.
From-SVN: r164926
Diffstat (limited to 'gcc/c-decl.c')
-rw-r--r-- | gcc/c-decl.c | 83 |
1 files changed, 75 insertions, 8 deletions
diff --git a/gcc/c-decl.c b/gcc/c-decl.c index 8272d33..91d853f 100644 --- a/gcc/c-decl.c +++ b/gcc/c-decl.c @@ -6614,15 +6614,15 @@ grokfield (location_t loc, is the anonymous union extension. Similarly for struct. If this is something of the form "struct foo;", then - If MS extensions are enabled, this is handled as an - anonymous struct. + If MS or Plan 9 extensions are enabled, this is handled as + an anonymous struct. Otherwise this is a forward declaration of a structure tag. If this is something of the form "foo;" and foo is a TYPE_DECL, then If foo names a structure or union without a tag, then this is an anonymous struct (this is permitted by C1X). - If MS extensions are enabled and foo names a structure, then - again this is an anonymous struct. + If MS or Plan 9 extensions are enabled and foo names a + structure, then again this is an anonymous struct. Otherwise this is an error. Oh what a horrid tangled web we weave. I wonder if MS consciously @@ -6636,7 +6636,7 @@ grokfield (location_t loc, if (type_ok) { - if (flag_ms_extensions) + if (flag_ms_extensions || flag_plan9_extensions) ok = true; else if (TYPE_NAME (TYPE_MAIN_VARIANT (type)) == NULL) ok = true; @@ -6688,6 +6688,50 @@ grokfield (location_t loc, return value; } +/* Subroutine of detect_field_duplicates: return whether X and Y, + which are both fields in the same struct, have duplicate field + names. */ + +static bool +is_duplicate_field (tree x, tree y) +{ + if (DECL_NAME (x) != NULL_TREE && DECL_NAME (x) == DECL_NAME (y)) + return true; + + /* When using -fplan9-extensions, an anonymous field whose name is a + typedef can duplicate a field name. */ + if (flag_plan9_extensions + && (DECL_NAME (x) == NULL_TREE || DECL_NAME (y) == NULL_TREE)) + { + tree xt, xn, yt, yn; + + xt = TREE_TYPE (x); + if (DECL_NAME (x) != NULL_TREE) + xn = DECL_NAME (x); + else if ((TREE_CODE (xt) == RECORD_TYPE || TREE_CODE (xt) == UNION_TYPE) + && TYPE_NAME (xt) != NULL_TREE + && TREE_CODE (TYPE_NAME (xt)) == TYPE_DECL) + xn = DECL_NAME (TYPE_NAME (xt)); + else + xn = NULL_TREE; + + yt = TREE_TYPE (y); + if (DECL_NAME (y) != NULL_TREE) + yn = DECL_NAME (y); + else if ((TREE_CODE (yt) == RECORD_TYPE || TREE_CODE (yt) == UNION_TYPE) + && TYPE_NAME (yt) != NULL_TREE + && TREE_CODE (TYPE_NAME (yt)) == TYPE_DECL) + yn = DECL_NAME (TYPE_NAME (yt)); + else + yn = NULL_TREE; + + if (xn != NULL_TREE && xn == yn) + return true; + } + + return false; +} + /* Subroutine of detect_field_duplicates: add the fields of FIELDLIST to HTAB, giving errors for any duplicates. */ @@ -6710,7 +6754,22 @@ detect_field_duplicates_hash (tree fieldlist, htab_t htab) } 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); + { + detect_field_duplicates_hash (TYPE_FIELDS (TREE_TYPE (x)), htab); + + /* When using -fplan9-extensions, an anonymous field whose + name is a typedef can duplicate a field name. */ + if (flag_plan9_extensions + && TYPE_NAME (TREE_TYPE (x)) != NULL_TREE + && TREE_CODE (TYPE_NAME (TREE_TYPE (x))) == TYPE_DECL) + { + tree xn = DECL_NAME (TYPE_NAME (TREE_TYPE (x))); + slot = htab_find_slot (htab, xn, INSERT); + if (*slot) + error ("duplicate member %q+D", TYPE_NAME (TREE_TYPE (x))); + *slot = xn; + } + } } /* Generate an error for any duplicate field names in FIELDLIST. Munge @@ -6755,10 +6814,18 @@ detect_field_duplicates (tree fieldlist) if (timeout > 0) { for (x = DECL_CHAIN (fieldlist); x; x = DECL_CHAIN (x)) - if (DECL_NAME (x)) + /* When using -fplan9-extensions, we can have duplicates + between typedef names and fields. */ + if (DECL_NAME (x) + || (flag_plan9_extensions + && DECL_NAME (x) == NULL_TREE + && (TREE_CODE (TREE_TYPE (x)) == RECORD_TYPE + || TREE_CODE (TREE_TYPE (x)) == UNION_TYPE) + && TYPE_NAME (TREE_TYPE (x)) != NULL_TREE + && TREE_CODE (TYPE_NAME (TREE_TYPE (x))) == TYPE_DECL)) { for (y = fieldlist; y != x; y = TREE_CHAIN (y)) - if (DECL_NAME (y) == DECL_NAME (x)) + if (is_duplicate_field (y, x)) { error ("duplicate member %q+D", x); DECL_NAME (x) = NULL_TREE; |