diff options
Diffstat (limited to 'gcc/c-decl.c')
-rw-r--r-- | gcc/c-decl.c | 43 |
1 files changed, 38 insertions, 5 deletions
diff --git a/gcc/c-decl.c b/gcc/c-decl.c index 075ac6d..96233e3 100644 --- a/gcc/c-decl.c +++ b/gcc/c-decl.c @@ -629,6 +629,10 @@ c_decode_option (argc, argv) flag_no_asm = 0; else if (!strcmp (p, "-fno-asm")) flag_no_asm = 1; + else if (!strcmp (p, "-fms-extensions")) + flag_ms_extensions = 1; + else if (!strcmp (p, "-fno-ms-extensions")) + flag_ms_extensions = 0; else if (!strcmp (p, "-fbuiltin")) flag_no_builtin = 0; else if (!strcmp (p, "-fno-builtin")) @@ -5359,15 +5363,44 @@ grokfield (filename, line, declarator, declspecs, width) if (declarator == NULL_TREE && width == NULL_TREE) { - /* This is an unnamed decl. We only support unnamed - structs/unions, so check for other things and refuse them. */ + /* This is an unnamed decl. + + If we have something of the form "union { list } ;" then this + 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. + 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 MS 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 consiously + took this from Plan 9 or if it was an accident of implementation + that took root before someone noticed the bug... */ + tree type = TREE_VALUE (declspecs); - if (TREE_CODE (type) == TYPE_DECL) + if (flag_ms_extensions && TREE_CODE (type) == TYPE_DECL) type = TREE_TYPE (type); - if (TREE_CODE (type) != RECORD_TYPE && TREE_CODE (type) != UNION_TYPE) + if (TREE_CODE (type) == RECORD_TYPE || TREE_CODE (type) == UNION_TYPE) + { + if (flag_ms_extensions) + ; /* ok */ + else if (flag_iso) + goto warn_unnamed_field; + else if (TYPE_NAME (type) == NULL) + ; /* ok */ + else + goto warn_unnamed_field; + } + else { - error ("unnamed fields of type other than struct or union are not allowed"); + warn_unnamed_field: + warning ("declaration does not declare anything"); return NULL_TREE; } } |