aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFrancois Pichet <pichet2000@gmail.com>2010-09-08 11:32:25 +0000
committerFrancois Pichet <pichet2000@gmail.com>2010-09-08 11:32:25 +0000
commit538e0d0292cab16198a4fce5c388ff06adc74d0c (patch)
tree89e9318108ae96be16acddd090a30d2be38a1312
parent36281c6fd792a254ade72caf825bad7b7c63b0e0 (diff)
Allow type definitions inside anonymous struct/union in Microsoft mode.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@113354 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang/Basic/DiagnosticGroups.td3
-rw-r--r--include/clang/Basic/DiagnosticSemaKinds.td3
-rw-r--r--lib/Sema/SemaDecl.cpp24
-rw-r--r--test/SemaCXX/MicrosoftExtensions.cpp44
4 files changed, 68 insertions, 6 deletions
diff --git a/include/clang/Basic/DiagnosticGroups.td b/include/clang/Basic/DiagnosticGroups.td
index dade38e4e3..fa7c5cfc91 100644
--- a/include/clang/Basic/DiagnosticGroups.td
+++ b/include/clang/Basic/DiagnosticGroups.td
@@ -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">;
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index 7ec98a69f3..438d0fc1f8 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -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<
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 2b42fb60fb..dbc758f1f2 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -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;
+ }
}
}
}
diff --git a/test/SemaCXX/MicrosoftExtensions.cpp b/test/SemaCXX/MicrosoftExtensions.cpp
index fb3107f44e..93650a53f4 100644
--- a/test/SemaCXX/MicrosoftExtensions.cpp
+++ b/test/SemaCXX/MicrosoftExtensions.cpp
@@ -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();