summaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>2002-06-16 19:09:30 +0000
committerrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>2002-06-16 19:09:30 +0000
commit07ebd0918cf25bb1c655059560f0e61c126ce554 (patch)
tree347f17f792ce0f731598ef624fd0f14c6484bffe /gcc
parent33b24f9d4cc6c2885b6f8b6df8c9035ceb3c0bbb (diff)
downloadgcc-07ebd0918cf25bb1c655059560f0e61c126ce554.tar.gz
* c-common.c (flag_ms_extensions): Move from c++ front end.
* c-common.h (flag_ms_extensions): Declare. * c-decl.c (c_decode_option): Add -fms-extensions. (grokfield): Don't accept anonymous structures in ISO C mode; accept only unnamed anonymous structures in GNU C mode; accept Plan 9 extensions in MS mode. * c-parse.in (SAVE_EXT_FLAGS, RESTORE_EXT_FLAGS): Rename from SAVE/RESTORE_WARN_FLAGS; add flag_iso frobbing; update all callers. (extension): Clear flag_iso. * doc/invoke.texi (C Dialect Options): Add -fms-extensions. * cp-tree.h, decl2.c (flag_ms_extensions): Move to c-common. * g++.dg/ext/anon-struct1.C: New. * g++.dg/ext/anon-struct2.C: New. * g++.dg/ext/anon-struct3.C: New. * gcc.dg/anon-struct-1.c: New. * gcc.dg/anon-struct-2.c: New. * gcc.dg/anon-struct-3.c: New. * gcc.dg/20011008-1.c: Adjust warning text. * gcc.dg/20020527-1.c: Add -fms-extensions. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@54670 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog13
-rw-r--r--gcc/c-common.c3
-rw-r--r--gcc/c-common.h3
-rw-r--r--gcc/c-decl.c43
-rw-r--r--gcc/c-parse.in21
-rw-r--r--gcc/cp/ChangeLog4
-rw-r--r--gcc/cp/cp-tree.h3
-rw-r--r--gcc/cp/decl2.c4
-rw-r--r--gcc/doc/invoke.texi6
-rw-r--r--gcc/testsuite/ChangeLog11
-rw-r--r--gcc/testsuite/g++.dg/ext/anon-struct1.C50
-rw-r--r--gcc/testsuite/g++.dg/ext/anon-struct2.C46
-rw-r--r--gcc/testsuite/g++.dg/ext/anon-struct3.C34
-rw-r--r--gcc/testsuite/gcc.dg/20011008-1.c2
-rw-r--r--gcc/testsuite/gcc.dg/20020527-1.c2
-rw-r--r--gcc/testsuite/gcc.dg/anon-struct-1.c56
-rw-r--r--gcc/testsuite/gcc.dg/anon-struct-2.c48
-rw-r--r--gcc/testsuite/gcc.dg/anon-struct-3.c32
18 files changed, 357 insertions, 24 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index eaa6d067c81..61b694dc278 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,16 @@
+2002-06-16 Richard Henderson <rth@redhat.com>
+
+ * c-common.c (flag_ms_extensions): Move from c++ front end.
+ * c-common.h (flag_ms_extensions): Declare.
+ * c-decl.c (c_decode_option): Add -fms-extensions.
+ (grokfield): Don't accept anonymous structures in ISO C mode;
+ accept only unnamed anonymous structures in GNU C mode; accept
+ Plan 9 extensions in MS mode.
+ * c-parse.in (SAVE_EXT_FLAGS, RESTORE_EXT_FLAGS): Rename from
+ SAVE/RESTORE_WARN_FLAGS; add flag_iso frobbing; update all callers.
+ (extension): Clear flag_iso.
+ * doc/invoke.texi (C Dialect Options): Add -fms-extensions.
+
2002-06-16 Hans-Peter Nilsson <hp@axis.com>
PR target/7042
diff --git a/gcc/c-common.c b/gcc/c-common.c
index 4b9b7cfd970..b58ba4ef474 100644
--- a/gcc/c-common.c
+++ b/gcc/c-common.c
@@ -220,6 +220,9 @@ int flag_short_double;
int flag_short_wchar;
+/* Nonzero means allow Microsoft extensions without warnings or errors. */
+int flag_ms_extensions;
+
/* Nonzero means warn about use of multicharacter literals. */
int warn_multichar = 1;
diff --git a/gcc/c-common.h b/gcc/c-common.h
index d0523a50051..b1fd9764a33 100644
--- a/gcc/c-common.h
+++ b/gcc/c-common.h
@@ -396,6 +396,9 @@ extern int flag_short_double;
extern int flag_short_wchar;
+/* Nonzero means allow Microsoft extensions without warnings or errors. */
+extern int flag_ms_extensions;
+
/* Nonzero means warn about use of multicharacter literals. */
extern int warn_multichar;
diff --git a/gcc/c-decl.c b/gcc/c-decl.c
index 075ac6d0bb0..96233e34230 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;
}
}
diff --git a/gcc/c-parse.in b/gcc/c-parse.in
index c5c499cf048..5dfecb8741f 100644
--- a/gcc/c-parse.in
+++ b/gcc/c-parse.in
@@ -298,17 +298,19 @@ static GTY(()) tree declspec_stack;
/* For __extension__, save/restore the warning flags which are
controlled by __extension__. */
-#define SAVE_WARN_FLAGS() \
+#define SAVE_EXT_FLAGS() \
size_int (pedantic \
| (warn_pointer_arith << 1) \
- | (warn_traditional << 2))
+ | (warn_traditional << 2) \
+ | (flag_iso << 3))
-#define RESTORE_WARN_FLAGS(tval) \
+#define RESTORE_EXT_FLAGS(tval) \
do { \
int val = tree_low_cst (tval, 0); \
pedantic = val & 1; \
warn_pointer_arith = (val >> 1) & 1; \
warn_traditional = (val >> 2) & 1; \
+ flag_iso = (val >> 3) & 1; \
} while (0)
ifobjc
@@ -394,7 +396,7 @@ end ifobjc
else
error ("argument of `asm' is not a constant string"); }
| extension extdef
- { RESTORE_WARN_FLAGS ($1); }
+ { RESTORE_EXT_FLAGS ($1); }
;
datadef:
@@ -517,7 +519,7 @@ unary_expr:
/* __extension__ turns off -pedantic for following primary. */
| extension cast_expr %prec UNARY
{ $$ = $2;
- RESTORE_WARN_FLAGS ($1); }
+ RESTORE_EXT_FLAGS ($1); }
| unop cast_expr %prec UNARY
{ $$ = build_unary_op ($1, $2, 0);
overflow_warning ($$); }
@@ -865,7 +867,7 @@ decl:
| declspecs ';'
{ shadow_tag ($1); }
| extension decl
- { RESTORE_WARN_FLAGS ($1); }
+ { RESTORE_EXT_FLAGS ($1); }
;
/* A list of declaration specifiers. These are:
@@ -1863,7 +1865,7 @@ component_decl:
{ $$ = NULL_TREE; }
| extension component_decl
{ $$ = $2;
- RESTORE_WARN_FLAGS ($1); }
+ RESTORE_EXT_FLAGS ($1); }
;
components:
@@ -2664,10 +2666,11 @@ identifiers_or_typenames:
extension:
EXTENSION
- { $$ = SAVE_WARN_FLAGS();
+ { $$ = SAVE_EXT_FLAGS();
pedantic = 0;
warn_pointer_arith = 0;
- warn_traditional = 0; }
+ warn_traditional = 0;
+ flag_iso = 0; }
;
ifobjc
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index b0479497809..707ee6f04e3 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,7 @@
+2002-06-16 Richard Henderson <rth@redhat.com>
+
+ * cp-tree.h, decl2.c (flag_ms_extensions): Move to c-common.
+
2002-06-15 Gabriel Dos Reis <gdr@codesourcery.com>
* cp-tree.h (compiler_error): Remove declaration.
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index f4b71ceb535..04f0e1bb5e1 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -3200,9 +3200,6 @@ typedef enum base_kind {
binfo. */
} base_kind;
-/* Nonzero means allow Microsoft extensions without a pedwarn. */
-extern int flag_ms_extensions;
-
/* Non-zero means warn in function declared in derived class has the
same name as a virtual in the base class, but fails to match the
type signature of any virtual function in the base class. */
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index 661ae3a9a9e..1188bb2acc8 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -299,10 +299,6 @@ int warn_deprecated = 1;
#endif
int dollars_in_ident = DOLLARS_IN_IDENTIFIERS;
-/* Nonzero means allow Microsoft extensions without a pedwarn. */
-
-int flag_ms_extensions;
-
/* C++ specific flags. */
/* Nonzero means we should attempt to elide constructors when possible. */
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 8549bfb5c6b..d81c4baae32 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -164,7 +164,7 @@ in the following sections.
@gccoptlist{
-ansi -std=@var{standard} -aux-info @var{filename} @gol
-fno-asm -fno-builtin -fno-builtin-@var{function} @gol
--fhosted -ffreestanding @gol
+-fhosted -ffreestanding -fms-extensions @gol
-trigraphs -traditional -traditional-cpp @gol
-fallow-single-precision -fcond-mismatch @gol
-fsigned-bitfields -fsigned-char @gol
@@ -1141,6 +1141,10 @@ This is equivalent to @option{-fno-hosted}.
@xref{Standards,,Language Standards Supported by GCC}, for details of
freestanding and hosted environments.
+@item -fms-extensions
+@opindex fms-extensions
+Accept some non-standard constructs used in Microsoft header files.
+
@item -trigraphs
@opindex trigraphs
Support ISO C trigraphs. The @option{-ansi} option (and @option{-std}
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index ffa1a3b15f4..df9ccd2c924 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,5 +1,16 @@
2002-06-16 Richard Henderson <rth@redhat.com>
+ * g++.dg/ext/anon-struct1.C: New.
+ * g++.dg/ext/anon-struct2.C: New.
+ * g++.dg/ext/anon-struct3.C: New.
+ * gcc.dg/anon-struct-1.c: New.
+ * gcc.dg/anon-struct-2.c: New.
+ * gcc.dg/anon-struct-3.c: New.
+ * gcc.dg/20011008-1.c: Adjust warning text.
+ * gcc.dg/20020527-1.c: Add -fms-extensions.
+
+2002-06-16 Richard Henderson <rth@redhat.com>
+
* gcc.dg/20020531-1.c: Add LL specifier to avoid warning.
2002-06-15 Hans-Peter Nilsson <hp@axis.com>
diff --git a/gcc/testsuite/g++.dg/ext/anon-struct1.C b/gcc/testsuite/g++.dg/ext/anon-struct1.C
new file mode 100644
index 00000000000..0a682db1ae2
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/anon-struct1.C
@@ -0,0 +1,50 @@
+/* { dg-options "-ansi -pedantic -pedantic-errors" } */
+/* In strict ISO C++ mode, we don't recognize the anonymous struct
+ extension or any Microsoft C extensions. */
+
+struct A { char a; };
+
+struct B {
+ struct A; /* forward decl of B::A. */
+ char b;
+};
+char testB[sizeof(B) == sizeof(A) ? 1 : -1];
+
+struct C {
+ struct D { char d; }; /* decl of C::D. */
+ char c;
+};
+char testC[sizeof(C) == sizeof(A) ? 1 : -1];
+char testD[sizeof(C::D) == sizeof(A) ? 1 : -1];
+
+/* GNU extension. */
+struct E {
+ struct { char z; }; /* { dg-error "prohibits anonymous structs" } */
+ char e;
+};
+
+typedef struct A typedef_A;
+struct F {
+ typedef_A; /* { dg-error "does not declare anything" } */
+ char f;
+};
+char testF[sizeof(struct F) == sizeof(struct A) ? 1 : -1];
+
+/* __extension__ enables GNU C mode for the duration of the declaration. */
+__extension__ struct G {
+ struct { char z; };
+ char g;
+};
+char testG[sizeof(G) == 2 * sizeof(A) ? 1 : -1];
+
+struct H {
+ __extension__ struct { char z; };
+ char h;
+};
+char testH[sizeof(H) == 2 * sizeof(A) ? 1 : -1];
+
+/* Make sure __extension__ gets turned back off. */
+struct I {
+ struct { char z; }; /* { dg-error "prohibits anonymous structs" } */
+ char i;
+};
diff --git a/gcc/testsuite/g++.dg/ext/anon-struct2.C b/gcc/testsuite/g++.dg/ext/anon-struct2.C
new file mode 100644
index 00000000000..0c629ed482f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/anon-struct2.C
@@ -0,0 +1,46 @@
+/* { dg-options "" } */
+/* In GNU C++ mode, we recognize the anonymous struct extension,
+ but not Microsoft C extensions. */
+
+struct A { char a; };
+
+struct B {
+ struct A; /* forward decl of B::A. */
+ char b;
+};
+char testB[sizeof(B) == sizeof(A) ? 1 : -1];
+
+struct C {
+ struct D { char d; }; /* decl of C::D. */
+ char c;
+};
+char testC[sizeof(C) == sizeof(A) ? 1 : -1];
+char testD[sizeof(C::D) == sizeof(A) ? 1 : -1];
+
+/* GNU extension. */
+struct E {
+ struct { char z; };
+ char e;
+};
+char testE[sizeof(E) == 2 * sizeof(A) ? 1 : -1];
+char testEz[sizeof( ((E *)0)->z )];
+
+typedef struct A typedef_A;
+struct F {
+ typedef_A; /* { dg-error "does not declare anything" } */
+ char f;
+};
+char testF[sizeof(F) == sizeof(A) ? 1 : -1];
+
+/* Test that __extension__ does the right thing coming _from_ GNU C mode. */
+__extension__ struct G {
+ struct { char z; };
+ char g;
+};
+char testG[sizeof(G) == 2 * sizeof(A) ? 1 : -1];
+
+struct H {
+ struct { char z; };
+ char h;
+};
+char testH[sizeof(H) == 2 * sizeof(A) ? 1 : -1];
diff --git a/gcc/testsuite/g++.dg/ext/anon-struct3.C b/gcc/testsuite/g++.dg/ext/anon-struct3.C
new file mode 100644
index 00000000000..1460d6c12f6
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/anon-struct3.C
@@ -0,0 +1,34 @@
+/* { dg-options "-fms-extensions" } */
+/* Verify that enabling Microsoft mode doesn't twist C++ as much as
+ their corresponding C extensions. Checked vs
+ Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8168 for 80x86
+ */
+
+struct A { char a; };
+
+struct B {
+ struct A; /* forward decl of B::A. */
+ char b;
+};
+char testB[sizeof(B) == sizeof(A) ? 1 : -1];
+
+struct C {
+ struct D { char d; }; /* decl of C::D. */
+ char c;
+};
+char testC[sizeof(C) == sizeof(A) ? 1 : -1];
+char testD[sizeof(C::D) == sizeof(A) ? 1 : -1];
+
+struct E {
+ struct { char z; };
+ char e;
+};
+char testE[sizeof(E) == 2 * sizeof(A) ? 1 : -1];
+char testEz[sizeof( ((E *)0)->z )];
+
+typedef struct A typedef_A;
+struct F {
+ typedef_A; /* { dg-error "does not declare anything" } */
+ char f;
+};
+char testF[sizeof(F) == sizeof(A) ? 1 : -1];
diff --git a/gcc/testsuite/gcc.dg/20011008-1.c b/gcc/testsuite/gcc.dg/20011008-1.c
index 5ac821cb2f0..e5c9e2cf0ee 100644
--- a/gcc/testsuite/gcc.dg/20011008-1.c
+++ b/gcc/testsuite/gcc.dg/20011008-1.c
@@ -1,7 +1,7 @@
/* { dg-do compile } */
/* { dg-options "-O0" } */
-struct { int; int q; } a; /* { dg-error "unnamed" } */
+struct { int; int q; } a; /* { dg-warning "does not declare anything" } */
struct { union {int x;}; int q; } b;
struct { struct {int x;}; int q; } c;
union { union {int x;}; int q; } d;
diff --git a/gcc/testsuite/gcc.dg/20020527-1.c b/gcc/testsuite/gcc.dg/20020527-1.c
index f480d7b7bb8..6f963ed9f78 100644
--- a/gcc/testsuite/gcc.dg/20020527-1.c
+++ b/gcc/testsuite/gcc.dg/20020527-1.c
@@ -2,7 +2,7 @@
Test whether an unnamed field with user defined type - struct or union is
accepted. */
/* { dg-do compile } */
-/* { dg-options "" } */
+/* { dg-options "-fms-extensions" } */
typedef struct {
unsigned short a;
diff --git a/gcc/testsuite/gcc.dg/anon-struct-1.c b/gcc/testsuite/gcc.dg/anon-struct-1.c
new file mode 100644
index 00000000000..587d59d7220
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/anon-struct-1.c
@@ -0,0 +1,56 @@
+/* { dg-options "-std=iso9899:1990" } */
+/* In strict ISO C mode, we don't recognize the anonymous struct/union
+ extension or any Microsoft extensions. */
+
+struct A { char a; };
+
+/* MS extension. */
+struct B {
+ struct A; /* { dg-warning "does not declare anything" } */
+ char b;
+};
+char testB[sizeof(struct B) == sizeof(struct A) ? 1 : -1];
+
+/* MS extension. */
+struct C {
+ struct D { char d; }; /* { dg-warning "does not declare anything" } */
+ char c;
+};
+char testC[sizeof(struct C) == sizeof(struct A) ? 1 : -1];
+char testD[sizeof(struct D) == sizeof(struct A) ? 1 : -1];
+
+/* GNU extension. */
+struct E {
+ struct { char z; }; /* { dg-warning "does not declare anything" } */
+ char e;
+};
+char testE[sizeof(struct E) == sizeof(struct A) ? 1 : -1];
+
+/* MS extension. */
+typedef struct A typedef_A;
+struct F {
+ typedef_A; /* { dg-warning "does not declare anything" } */
+ char f;
+};
+char testF[sizeof(struct F) == sizeof(struct A) ? 1 : -1];
+
+/* __extension__ enables GNU C mode for the duration of the declaration. */
+__extension__ struct G {
+ struct { char z; };
+ char g;
+};
+char testG[sizeof(struct G) == 2 * sizeof(struct A) ? 1 : -1];
+
+struct H {
+ __extension__ struct { char z; };
+ char h;
+};
+char testH[sizeof(struct H) == 2 * sizeof(struct A) ? 1 : -1];
+
+/* Make sure __extension__ gets turned back off. */
+struct I {
+ struct { char z; }; /* { dg-warning "does not declare anything" } */
+ char i;
+};
+char testI[sizeof(struct I) == sizeof(struct A) ? 1 : -1];
+
diff --git a/gcc/testsuite/gcc.dg/anon-struct-2.c b/gcc/testsuite/gcc.dg/anon-struct-2.c
new file mode 100644
index 00000000000..4bd2d0f337c
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/anon-struct-2.c
@@ -0,0 +1,48 @@
+/* { dg-options "-std=gnu89" } */
+/* In GNU C mode, we recognize the anonymous struct/union extension,
+ but not Microsoft extensions. */
+
+struct A { char a; };
+
+/* MS extension. */
+struct B {
+ struct A; /* { dg-warning "does not declare anything" } */
+ char b;
+};
+char testB[sizeof(struct B) == sizeof(struct A) ? 1 : -1];
+
+/* MS extension. */
+struct C {
+ struct D { char d; }; /* { dg-warning "does not declare anything" } */
+ char c;
+};
+char testC[sizeof(struct C) == sizeof(struct A) ? 1 : -1];
+char testD[sizeof(struct D) == sizeof(struct A) ? 1 : -1];
+
+/* GNU extension. */
+struct E {
+ struct { char z; };
+ char e;
+};
+char testE[sizeof(struct E) == 2 * sizeof(struct A) ? 1 : -1];
+
+/* MS extension. */
+typedef struct A typedef_A;
+struct F {
+ typedef_A; /* { dg-warning "does not declare anything" } */
+ char f;
+};
+char testF[sizeof(struct F) == sizeof(struct A) ? 1 : -1];
+
+/* Test that __extension__ does the right thing coming _from_ GNU C mode. */
+__extension__ struct G {
+ struct { char z; };
+ char g;
+};
+char testG[sizeof(struct G) == 2 * sizeof(struct A) ? 1 : -1];
+
+struct H {
+ struct { char z; };
+ char h;
+};
+char testH[sizeof(struct H) == 2 * sizeof(struct A) ? 1 : -1];
diff --git a/gcc/testsuite/gcc.dg/anon-struct-3.c b/gcc/testsuite/gcc.dg/anon-struct-3.c
new file mode 100644
index 00000000000..3ed6e672bd5
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/anon-struct-3.c
@@ -0,0 +1,32 @@
+/* { dg-options "-std=gnu89 -fms-extensions" } */
+/* Enabling Microsoft mode makes all of the tests equivalent. Checked vs
+ Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8168 for 80x86
+ */
+
+struct A { char a; };
+
+struct B {
+ struct A;
+ char b;
+};
+char testB[sizeof(struct B) == 2 * sizeof(struct A) ? 1 : -1];
+
+struct C {
+ struct D { char d; };
+ char c;
+};
+char testC[sizeof(struct C) == 2 * sizeof(struct A) ? 1 : -1];
+char testD[sizeof(struct D) == sizeof(struct A) ? 1 : -1];
+
+struct E {
+ struct { char z; };
+ char e;
+};
+char testE[sizeof(struct E) == 2 * sizeof(struct A) ? 1 : -1];
+
+typedef struct A typedef_A;
+struct F {
+ typedef_A;
+ char f;
+};
+char testF[sizeof(struct F) == 2 * sizeof(struct A) ? 1 : -1];