From c052dbb2d8fe0e23e90d81236aab0f864f712b45 Mon Sep 17 00:00:00 2001 From: John McCall Date: Tue, 22 May 2012 21:28:12 +0000 Subject: [PATCH] Recognize the MS inheritance attributes and turn them into attributes on the RecordDecl. Persist the MS portability type attributes and ignore them in Sema rather than the parser. MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Patch by João Matos! git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@157288 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/Attr.td | 50 ++++++++++++++++------ include/clang/Basic/DiagnosticSemaKinds.td | 3 +- include/clang/Basic/TokenKinds.def | 3 ++ include/clang/Parse/Parser.h | 1 + lib/Parse/ParseDecl.cpp | 4 -- lib/Parse/ParseDeclCXX.cpp | 17 ++++++++ lib/Sema/SemaDeclAttr.cpp | 48 ++++++++++++++++++++- lib/Sema/SemaType.cpp | 7 +++ test/Parser/MicrosoftExtensions.c | 4 +- test/Parser/MicrosoftExtensions.cpp | 6 +++ 10 files changed, 123 insertions(+), 20 deletions(-) diff --git a/include/clang/Basic/Attr.td b/include/clang/Basic/Attr.td index f4370113fd..72e0c69bf3 100644 --- a/include/clang/Basic/Attr.td +++ b/include/clang/Basic/Attr.td @@ -308,14 +308,6 @@ def Destructor : InheritableAttr { let Args = [IntArgument<"Priority">]; } -def DLLExport : InheritableAttr { - let Spellings = ["dllexport"]; -} - -def DLLImport : InheritableAttr { - let Spellings = ["dllimport"]; -} - def ExtVectorType : Attr { let Spellings = ["ext_vector_type"]; let Args = [ExprArgument<"NumElements">]; @@ -336,10 +328,6 @@ def Final : InheritableAttr { let SemaHandler = 0; } -def MsStruct : InheritableAttr { - let Spellings = ["__ms_struct__"]; -} - def Format : InheritableAttr { let Spellings = ["format"]; let Args = [StringArgument<"Type">, IntArgument<"FormatIdx">, @@ -816,3 +804,41 @@ def SharedLocksRequired : InheritableAttr { let LateParsed = 1; let TemplateDependent = 1; } + +// Microsoft-related attributes + +def MsStruct : InheritableAttr { + let Spellings = ["__ms_struct__"]; +} + +def DLLExport : InheritableAttr { + let Spellings = ["dllexport"]; +} + +def DLLImport : InheritableAttr { + let Spellings = ["dllimport"]; +} + +def Win64 : InheritableAttr { + let Spellings = ["__w64"]; +} + +def Ptr32 : InheritableAttr { + let Spellings = ["__ptr32"]; +} + +def Ptr64 : InheritableAttr { + let Spellings = ["__ptr64"]; +} + +def SingleInheritance : InheritableAttr { + let Spellings = ["__single_inheritance"]; +} + +def MultipleInheritance : InheritableAttr { + let Spellings = ["__multiple_inheritance"]; +} + +def VirtualInheritance : InheritableAttr { + let Spellings = ["__virtual_inheritance"]; +} \ No newline at end of file diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index d2292af468..fba50ece83 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -1630,7 +1630,8 @@ def warn_attribute_wrong_decl_type : Warning< "variables and functions|functions and methods|parameters|" "functions, methods and blocks|functions, methods, and parameters|" "classes|variables|methods|variables, functions and labels|" - "fields and global variables|structs}1">; + "fields and global variables|structs|" + "variables, functions and tag types}1">; def err_attribute_wrong_decl_type : Error< "%0 attribute only applies to %select{functions|unions|" "variables and functions|functions and methods|parameters|" diff --git a/include/clang/Basic/TokenKinds.def b/include/clang/Basic/TokenKinds.def index 9ea2c18693..7c800df7fb 100644 --- a/include/clang/Basic/TokenKinds.def +++ b/include/clang/Basic/TokenKinds.def @@ -496,6 +496,9 @@ KEYWORD(__leave , KEYMS | KEYBORLAND) KEYWORD(__int64 , KEYMS) KEYWORD(__if_exists , KEYMS) KEYWORD(__if_not_exists , KEYMS) +KEYWORD(__single_inheritance , KEYMS) +KEYWORD(__multiple_inheritance , KEYMS) +KEYWORD(__virtual_inheritance , KEYMS) ALIAS("__int8" , char , KEYMS) ALIAS("__int16" , short , KEYMS) ALIAS("__int32" , int , KEYMS) diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h index 814b45afc7..f3143766cb 100644 --- a/include/clang/Parse/Parser.h +++ b/include/clang/Parse/Parser.h @@ -1859,6 +1859,7 @@ private: SourceLocation *endLoc = 0); void ParseMicrosoftDeclSpec(ParsedAttributes &attrs); void ParseMicrosoftTypeAttributes(ParsedAttributes &attrs); + void ParseMicrosoftInheritanceClassAttributes(ParsedAttributes &attrs); void ParseBorlandTypeAttributes(ParsedAttributes &attrs); void ParseOpenCLAttributes(ParsedAttributes &attrs); void ParseOpenCLQualifiers(DeclSpec &DS); diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index c3ffd9e135..ac6378035c 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -343,10 +343,6 @@ void Parser::ParseMicrosoftTypeAttributes(ParsedAttributes &attrs) { Tok.is(tok::kw___unaligned)) { IdentifierInfo *AttrName = Tok.getIdentifierInfo(); SourceLocation AttrNameLoc = ConsumeToken(); - if (Tok.is(tok::kw___ptr64) || Tok.is(tok::kw___w64) || - Tok.is(tok::kw___ptr32)) - // FIXME: Support these properly! - continue; attrs.addNew(AttrName, AttrNameLoc, 0, AttrNameLoc, 0, SourceLocation(), 0, 0, true); } diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp index 0b5c39680d..c75e138f61 100644 --- a/lib/Parse/ParseDeclCXX.cpp +++ b/lib/Parse/ParseDeclCXX.cpp @@ -900,6 +900,17 @@ Parser::TypeResult Parser::ParseBaseTypeSpecifier(SourceLocation &BaseLoc, return Actions.ActOnTypeName(getCurScope(), DeclaratorInfo); } +void Parser::ParseMicrosoftInheritanceClassAttributes(ParsedAttributes &attrs) { + while (Tok.is(tok::kw___single_inheritance) || + Tok.is(tok::kw___multiple_inheritance) || + Tok.is(tok::kw___virtual_inheritance)) { + IdentifierInfo *AttrName = Tok.getIdentifierInfo(); + SourceLocation AttrNameLoc = ConsumeToken(); + attrs.addNew(AttrName, AttrNameLoc, 0, AttrNameLoc, 0, + SourceLocation(), 0, 0, false); + } +} + /// ParseClassSpecifier - Parse a C++ class-specifier [C++ class] or /// elaborated-type-specifier [C++ dcl.type.elab]; we can't tell which /// until we reach the start of a definition or see a token that @@ -985,6 +996,12 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, while (Tok.is(tok::kw___declspec)) ParseMicrosoftDeclSpec(attrs); + // Parse inheritance specifiers. + if (Tok.is(tok::kw___single_inheritance) || + Tok.is(tok::kw___multiple_inheritance) || + Tok.is(tok::kw___virtual_inheritance)) + ParseMicrosoftInheritanceClassAttributes(attrs); + // If C++0x attributes exist here, parse them. // FIXME: Are we consistent with the ordering of parsing of different // styles of attributes? diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index 6d0e30c77c..ff25645707 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/lib/Sema/SemaDeclAttr.cpp @@ -3773,6 +3773,38 @@ static void handleUuidAttr(Sema &S, Decl *D, const AttributeList &Attr) { S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "uuid"; } +static void handleInheritanceAttr(Sema &S, Decl *D, const AttributeList &Attr) { + if (S.LangOpts.MicrosoftExt) { + AttributeList::Kind Kind = Attr.getKind(); + if (Kind == AttributeList::AT_single_inheritance) + D->addAttr( + ::new (S.Context) SingleInheritanceAttr(Attr.getRange(), S.Context)); + else if (Kind == AttributeList::AT_multiple_inheritance) + D->addAttr( + ::new (S.Context) MultipleInheritanceAttr(Attr.getRange(), S.Context)); + else if (Kind == AttributeList::AT_virtual_inheritance) + D->addAttr( + ::new (S.Context) VirtualInheritanceAttr(Attr.getRange(), S.Context)); + } else + S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName(); +} + +static void handlePortabilityAttr(Sema &S, Decl *D, const AttributeList &Attr) { + if (S.LangOpts.MicrosoftExt) { + AttributeList::Kind Kind = Attr.getKind(); + if (Kind == AttributeList::AT_ptr32) + D->addAttr( + ::new (S.Context) Ptr32Attr(Attr.getRange(), S.Context)); + else if (Kind == AttributeList::AT_ptr64) + D->addAttr( + ::new (S.Context) Ptr64Attr(Attr.getRange(), S.Context)); + else if (Kind == AttributeList::AT_w64) + D->addAttr( + ::new (S.Context) Win64Attr(Attr.getRange(), S.Context)); + } else + S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName(); +} + //===----------------------------------------------------------------------===// // Top Level Sema Entry Points //===----------------------------------------------------------------------===// @@ -3889,7 +3921,6 @@ static void ProcessInheritableDeclAttr(Sema &S, Scope *scope, Decl *D, handleInitPriorityAttr(S, D, Attr); break; case AttributeList::AT_packed: handlePackedAttr (S, D, Attr); break; - case AttributeList::AT_ms_struct: handleMsStructAttr (S, D, Attr); break; case AttributeList::AT_section: handleSectionAttr (S, D, Attr); break; case AttributeList::AT_unavailable: handleAttrWithMessage(S, D, Attr, "unavailable"); @@ -3949,9 +3980,24 @@ static void ProcessInheritableDeclAttr(Sema &S, Scope *scope, Decl *D, case AttributeList::AT_opencl_kernel_function: handleOpenCLKernelAttr(S, D, Attr); break; + + // Microsoft attributes: + case AttributeList::AT_ms_struct: + handleMsStructAttr(S, D, Attr); + break; case AttributeList::AT_uuid: handleUuidAttr(S, D, Attr); break; + case AttributeList::AT_single_inheritance: + case AttributeList::AT_multiple_inheritance: + case AttributeList::AT_virtual_inheritance: + handleInheritanceAttr(S, D, Attr); + break; + case AttributeList::AT_w64: + case AttributeList::AT_ptr32: + case AttributeList::AT_ptr64: + handlePortabilityAttr(S, D, Attr); + break; // Thread safety attributes: case AttributeList::AT_guarded_var: diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index 13a72a5338..f795660d08 100644 --- a/lib/Sema/SemaType.cpp +++ b/lib/Sema/SemaType.cpp @@ -4028,6 +4028,13 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type, attr.setUsedAsTypeAttr(); break; + case AttributeList::AT_w64: + case AttributeList::AT_ptr32: + case AttributeList::AT_ptr64: + // FIXME: don't ignore these + attr.setUsedAsTypeAttr(); + break; + case AttributeList::AT_ns_returns_retained: if (!state.getSema().getLangOpts().ObjCAutoRefCount) break; diff --git a/test/Parser/MicrosoftExtensions.c b/test/Parser/MicrosoftExtensions.c index 6b00534d1d..c20bdb6b14 100644 --- a/test/Parser/MicrosoftExtensions.c +++ b/test/Parser/MicrosoftExtensions.c @@ -11,11 +11,11 @@ typedef __w64 unsigned long ULONG_PTR, *PULONG_PTR; void * __ptr64 PtrToPtr64(const void *p) { - return((void * __ptr64) (unsigned __int64) (ULONG_PTR)p ); // expected-warning {{unknown attribute '__ptr64' ignored}} + return((void * __ptr64) (unsigned __int64) (ULONG_PTR)p ); } void * __ptr32 PtrToPtr32(const void *p) { - return((void * __ptr32) (unsigned __int32) (ULONG_PTR)p ); // expected-warning {{unknown attribute '__ptr32' ignored}} + return((void * __ptr32) (unsigned __int32) (ULONG_PTR)p ); } void __forceinline InterlockedBitTestAndSet (long *Base, long Bit) diff --git a/test/Parser/MicrosoftExtensions.cpp b/test/Parser/MicrosoftExtensions.cpp index 94047884d6..6219e29f59 100644 --- a/test/Parser/MicrosoftExtensions.cpp +++ b/test/Parser/MicrosoftExtensions.cpp @@ -317,3 +317,9 @@ namespace access_protected_PTM { &A::f; } } + +namespace Inheritance { + class __single_inheritance A; + class __multiple_inheritance B; + class __virtual_inheritance C; +} -- 2.50.1