From: John McCall Date: Tue, 22 May 2012 21:28:12 +0000 (+0000) Subject: Recognize the MS inheritance attributes and turn them into attributes X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=c052dbb2d8fe0e23e90d81236aab0f864f712b45;p=clang 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. Patch by João Matos! git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@157288 91177308-0d34-0410-b5e6-96231b3b80d8 --- 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; +}