Allow type definitions inside anonymous struct/union in Microsoft mode.

llvm-svn: 113354
This commit is contained in:
Francois Pichet 2010-09-08 11:32:25 +00:00
parent 2907d2e419
commit 4ad4b58639
4 changed files with 68 additions and 6 deletions

View File

@ -227,3 +227,6 @@ def NonGCC : DiagGroup<"non-gcc",
// A warning group for warnings about GCC extensions.
def GNU : DiagGroup<"gnu", [GNUDesignator, VLA]>;
// A warning group for warnings about Microsoft extensions.
def Microsoft : DiagGroup<"microsoft">;

View File

@ -2850,6 +2850,9 @@ def err_anonymous_struct_member_redecl : Error<
"member of anonymous struct redeclares %0">;
def err_anonymous_record_with_type : Error<
"types cannot be declared in an anonymous %select{struct|union}0">;
def ext_anonymous_record_with_type : Extension<
"types declared in an anonymous %select{struct|union}0 are a Microsoft extension">,
InGroup<Microsoft>;
def err_anonymous_record_with_function : Error<
"functions cannot be declared in an anonymous %select{struct|union}0">;
def err_anonymous_record_with_static : Error<

View File

@ -1898,10 +1898,16 @@ Decl *Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS,
} else if (RecordDecl *MemRecord = dyn_cast<RecordDecl>(*Mem)) {
if (!MemRecord->isAnonymousStructOrUnion() &&
MemRecord->getDeclName()) {
// This is a nested type declaration.
Diag(MemRecord->getLocation(), diag::err_anonymous_record_with_type)
<< (int)Record->isUnion();
Invalid = true;
// Visual C++ allows type definition in anonymous struct or union.
if (getLangOptions().Microsoft)
Diag(MemRecord->getLocation(), diag::ext_anonymous_record_with_type)
<< (int)Record->isUnion();
else {
// This is a nested type declaration.
Diag(MemRecord->getLocation(), diag::err_anonymous_record_with_type)
<< (int)Record->isUnion();
Invalid = true;
}
}
} else if (isa<AccessSpecDecl>(*Mem)) {
// Any access specifier is fine.
@ -1915,9 +1921,17 @@ Decl *Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS,
DK = diag::err_anonymous_record_with_function;
else if (isa<VarDecl>(*Mem))
DK = diag::err_anonymous_record_with_static;
Diag((*Mem)->getLocation(), DK)
// Visual C++ allows type definition in anonymous struct or union.
if (getLangOptions().Microsoft &&
DK == diag::err_anonymous_record_with_type)
Diag((*Mem)->getLocation(), diag::ext_anonymous_record_with_type)
<< (int)Record->isUnion();
else {
Diag((*Mem)->getLocation(), DK)
<< (int)Record->isUnion();
Invalid = true;
}
}
}
}

View File

@ -1,4 +1,4 @@
// RUN: %clang_cc1 %s -fsyntax-only -verify -fms-extensions -fexceptions
// RUN: %clang_cc1 %s -fsyntax-only -Wmicrosoft -verify -fms-extensions -fexceptions
// ::type_info is predeclared with forward class declartion
@ -30,6 +30,48 @@ struct Derived : Base {
virtual void f3();
};
// MSVC allows type definition in anonymous union and struct
struct A
{
union
{
int a;
struct B // expected-warning {{types declared in an anonymous union are a Microsoft extension}}
{
int c;
} d;
union C // expected-warning {{types declared in an anonymous union are a Microsoft extension}}
{
int e;
int ee;
} f;
typedef int D; // expected-warning {{types declared in an anonymous union are a Microsoft extension}}
struct F; // expected-warning {{types declared in an anonymous union are a Microsoft extension}}
};
struct
{
int a2;
struct B2 // expected-warning {{types declared in an anonymous struct are a Microsoft extension}}
{
int c2;
} d2;
union C2 // expected-warning {{types declared in an anonymous struct are a Microsoft extension}}
{
int e2;
int ee2;
} f2;
typedef int D2; // expected-warning {{types declared in an anonymous struct are a Microsoft extension}}
struct F2; // expected-warning {{types declared in an anonymous struct are a Microsoft extension}}
};
};
// __stdcall handling
struct M {
int __stdcall addP();