From 538e0d0292cab16198a4fce5c388ff06adc74d0c Mon Sep 17 00:00:00 2001 From: Francois Pichet Date: Wed, 8 Sep 2010 11:32:25 +0000 Subject: [PATCH] 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 --- include/clang/Basic/DiagnosticGroups.td | 3 ++ include/clang/Basic/DiagnosticSemaKinds.td | 3 ++ lib/Sema/SemaDecl.cpp | 24 +++++++++--- test/SemaCXX/MicrosoftExtensions.cpp | 44 +++++++++++++++++++++- 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; 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(*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(*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(*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(); -- 2.40.0