diff options
-rw-r--r-- | include/clang/AST/Attr.h | 2 | ||||
-rw-r--r-- | include/clang/AST/Type.h | 7 | ||||
-rw-r--r-- | include/clang/Basic/TokenKinds.def | 2 | ||||
-rw-r--r-- | include/clang/Parse/AttributeList.h | 1 | ||||
-rw-r--r-- | lib/AST/AttrImpl.cpp | 1 | ||||
-rw-r--r-- | lib/AST/Type.cpp | 1 | ||||
-rw-r--r-- | lib/AST/TypePrinter.cpp | 3 | ||||
-rw-r--r-- | lib/CodeGen/CGCall.cpp | 4 | ||||
-rw-r--r-- | lib/Frontend/PCHReaderDecl.cpp | 1 | ||||
-rw-r--r-- | lib/Parse/AttributeList.cpp | 5 | ||||
-rw-r--r-- | lib/Parse/ParseDecl.cpp | 13 | ||||
-rw-r--r-- | lib/Parse/ParseTentative.cpp | 1 | ||||
-rw-r--r-- | lib/Sema/SemaDeclAttr.cpp | 3 | ||||
-rw-r--r-- | lib/Sema/SemaType.cpp | 2 | ||||
-rw-r--r-- | test/CodeGen/stdcall-fastcall.c | 37 |
15 files changed, 63 insertions, 20 deletions
diff --git a/include/clang/AST/Attr.h b/include/clang/AST/Attr.h index 1974493176..6bdb4a2fb6 100644 --- a/include/clang/AST/Attr.h +++ b/include/clang/AST/Attr.h @@ -86,6 +86,7 @@ public: Section, Sentinel, StdCall, + ThisCall, TransparentUnion, Unavailable, Unused, @@ -457,6 +458,7 @@ public: DEF_SIMPLE_ATTR(FastCall); DEF_SIMPLE_ATTR(StdCall); +DEF_SIMPLE_ATTR(ThisCall); DEF_SIMPLE_ATTR(CDecl); DEF_SIMPLE_ATTR(TransparentUnion); DEF_SIMPLE_ATTR(ObjCNSObject); diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h index c2cddb95f7..f14b652372 100644 --- a/include/clang/AST/Type.h +++ b/include/clang/AST/Type.h @@ -396,7 +396,8 @@ enum CallingConv { CC_Default, CC_C, // __attribute__((cdecl)) CC_X86StdCall, // __attribute__((stdcall)) - CC_X86FastCall // __attribute__((fastcall)) + CC_X86FastCall, // __attribute__((fastcall)) + CC_X86ThisCall // __attribute__((thiscall)) }; @@ -1763,7 +1764,7 @@ class FunctionType : public Type { unsigned RegParm : 3; /// CallConv - The calling convention used by the function. - unsigned CallConv : 2; + unsigned CallConv : 3; // The type returned by the function. QualType ResultType; @@ -1831,7 +1832,7 @@ class FunctionType : public Type { // The value passed to __attribute__((regparm(x))) unsigned RegParm; // The calling convention as specified via - // __attribute__((cdecl|stdcall||fastcall)) + // __attribute__((cdecl|stdcall|fastcall|thiscall)) CallingConv CC; }; diff --git a/include/clang/Basic/TokenKinds.def b/include/clang/Basic/TokenKinds.def index 52e83f4045..c50b31d374 100644 --- a/include/clang/Basic/TokenKinds.def +++ b/include/clang/Basic/TokenKinds.def @@ -336,6 +336,7 @@ KEYWORD(__declspec , KEYALL) KEYWORD(__cdecl , KEYALL) KEYWORD(__stdcall , KEYALL) KEYWORD(__fastcall , KEYALL) +KEYWORD(__thiscall , KEYALL) KEYWORD(__forceinline , KEYALL) // Altivec Extension. @@ -372,6 +373,7 @@ ALIAS("_asm" , asm , KEYMS) ALIAS("_cdecl" , __cdecl , KEYMS) ALIAS("_fastcall" , __fastcall , KEYMS) ALIAS("_stdcall" , __stdcall , KEYMS) +ALIAS("_thiscall" , __thiscall , KEYMS) //===----------------------------------------------------------------------===// // Objective-C @-preceeded keywords. diff --git a/include/clang/Parse/AttributeList.h b/include/clang/Parse/AttributeList.h index 12512f33c7..68d6f22c9b 100644 --- a/include/clang/Parse/AttributeList.h +++ b/include/clang/Parse/AttributeList.h @@ -102,6 +102,7 @@ public: AT_section, AT_sentinel, AT_stdcall, + AT_thiscall, AT_transparent_union, AT_unavailable, AT_unused, diff --git a/lib/AST/AttrImpl.cpp b/lib/AST/AttrImpl.cpp index 423aa065e5..0345226787 100644 --- a/lib/AST/AttrImpl.cpp +++ b/lib/AST/AttrImpl.cpp @@ -100,6 +100,7 @@ DEF_SIMPLE_ATTR_CLONE(Override) DEF_SIMPLE_ATTR_CLONE(Packed) DEF_SIMPLE_ATTR_CLONE(Pure) DEF_SIMPLE_ATTR_CLONE(StdCall) +DEF_SIMPLE_ATTR_CLONE(ThisCall) DEF_SIMPLE_ATTR_CLONE(TransparentUnion) DEF_SIMPLE_ATTR_CLONE(Unavailable) DEF_SIMPLE_ATTR_CLONE(Unused) diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index ebaad9a0a8..5d27ba469c 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -919,6 +919,7 @@ llvm::StringRef FunctionType::getNameForCallConv(CallingConv CC) { case CC_C: return "cdecl"; case CC_X86StdCall: return "stdcall"; case CC_X86FastCall: return "fastcall"; + case CC_X86ThisCall: return "thiscall"; } } diff --git a/lib/AST/TypePrinter.cpp b/lib/AST/TypePrinter.cpp index ad5b91aac5..35a7e09699 100644 --- a/lib/AST/TypePrinter.cpp +++ b/lib/AST/TypePrinter.cpp @@ -295,6 +295,9 @@ void TypePrinter::PrintFunctionProto(const FunctionProtoType *T, case CC_X86FastCall: S += " __attribute__((fastcall))"; break; + case CC_X86ThisCall: + S += " __attribute__((thiscall))"; + break; } if (Info.getNoReturn()) S += " __attribute__((noreturn))"; diff --git a/lib/CodeGen/CGCall.cpp b/lib/CodeGen/CGCall.cpp index 92d15d9d8c..0d6a70c64d 100644 --- a/lib/CodeGen/CGCall.cpp +++ b/lib/CodeGen/CGCall.cpp @@ -38,6 +38,7 @@ static unsigned ClangCallConvToLLVMCallConv(CallingConv CC) { default: return llvm::CallingConv::C; case CC_X86StdCall: return llvm::CallingConv::X86_StdCall; case CC_X86FastCall: return llvm::CallingConv::X86_FastCall; + case CC_X86ThisCall: return llvm::CallingConv::X86_ThisCall; } } @@ -97,6 +98,9 @@ static CallingConv getCallingConventionForDecl(const Decl *D) { if (D->hasAttr<FastCallAttr>()) return CC_X86FastCall; + if (D->hasAttr<ThisCallAttr>()) + return CC_X86ThisCall; + return CC_C; } diff --git a/lib/Frontend/PCHReaderDecl.cpp b/lib/Frontend/PCHReaderDecl.cpp index 49010bf0d6..1e8bd2fe55 100644 --- a/lib/Frontend/PCHReaderDecl.cpp +++ b/lib/Frontend/PCHReaderDecl.cpp @@ -763,6 +763,7 @@ Attr *PCHReader::ReadAttributes() { UNSIGNED_ATTR(Regparm); STRING_ATTR(Section); SIMPLE_ATTR(StdCall); + SIMPLE_ATTR(ThisCall); SIMPLE_ATTR(TransparentUnion); SIMPLE_ATTR(Unavailable); SIMPLE_ATTR(Unused); diff --git a/lib/Parse/AttributeList.cpp b/lib/Parse/AttributeList.cpp index bae2a09a98..53406280bb 100644 --- a/lib/Parse/AttributeList.cpp +++ b/lib/Parse/AttributeList.cpp @@ -119,5 +119,10 @@ AttributeList::Kind AttributeList::getKind(const IdentifierInfo *Name) { .Case("cf_returns_retained", AT_cf_returns_retained) .Case("reqd_work_group_size", AT_reqd_wg_size) .Case("no_instrument_function", AT_no_instrument_function) + .Case("thiscall", AT_thiscall) + .Case("__cdecl", AT_cdecl) + .Case("__stdcall", AT_stdcall) + .Case("__fastcall", AT_fastcall) + .Case("__thiscall", AT_thiscall) .Default(UnknownAttribute); } diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index 28d9dd021c..929b20cc3d 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -277,8 +277,8 @@ AttributeList* Parser::ParseMicrosoftTypeAttributes(AttributeList *CurrAttr) { // Treat these like attributes // FIXME: Allow Sema to distinguish between these and real attributes! while (Tok.is(tok::kw___fastcall) || Tok.is(tok::kw___stdcall) || - Tok.is(tok::kw___cdecl) || Tok.is(tok::kw___ptr64) || - Tok.is(tok::kw___w64)) { + Tok.is(tok::kw___thiscall) || Tok.is(tok::kw___cdecl) || + Tok.is(tok::kw___ptr64) || Tok.is(tok::kw___w64)) { IdentifierInfo *AttrName = Tok.getIdentifierInfo(); SourceLocation AttrNameLoc = ConsumeToken(); if (Tok.is(tok::kw___ptr64) || Tok.is(tok::kw___w64)) @@ -1143,6 +1143,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, case tok::kw___cdecl: case tok::kw___stdcall: case tok::kw___fastcall: + case tok::kw___thiscall: DS.AddAttributes(ParseMicrosoftTypeAttributes()); continue; @@ -1622,6 +1623,7 @@ bool Parser::ParseOptionalTypeSpecifier(DeclSpec &DS, bool& isInvalid, case tok::kw___cdecl: case tok::kw___stdcall: case tok::kw___fastcall: + case tok::kw___thiscall: DS.AddAttributes(ParseMicrosoftTypeAttributes()); return true; @@ -2198,6 +2200,7 @@ bool Parser::isTypeSpecifierQualifier() { case tok::kw___cdecl: case tok::kw___stdcall: case tok::kw___fastcall: + case tok::kw___thiscall: case tok::kw___w64: case tok::kw___ptr64: return true; @@ -2304,6 +2307,7 @@ bool Parser::isDeclarationSpecifier() { case tok::kw___cdecl: case tok::kw___stdcall: case tok::kw___fastcall: + case tok::kw___thiscall: case tok::kw___w64: case tok::kw___ptr64: case tok::kw___forceinline: @@ -2401,6 +2405,7 @@ void Parser::ParseTypeQualifierListOpt(DeclSpec &DS, bool GNUAttributesAllowed, case tok::kw___cdecl: case tok::kw___stdcall: case tok::kw___fastcall: + case tok::kw___thiscall: if (GNUAttributesAllowed) { DS.AddAttributes(ParseMicrosoftTypeAttributes()); continue; @@ -2785,8 +2790,8 @@ void Parser::ParseParenDeclarator(Declarator &D) { } // Eat any Microsoft extensions. if (Tok.is(tok::kw___cdecl) || Tok.is(tok::kw___stdcall) || - Tok.is(tok::kw___fastcall) || Tok.is(tok::kw___w64) || - Tok.is(tok::kw___ptr64)) { + Tok.is(tok::kw___thiscall) || Tok.is(tok::kw___fastcall) || + Tok.is(tok::kw___w64) || Tok.is(tok::kw___ptr64)) { AttrList.reset(ParseMicrosoftTypeAttributes(AttrList.take())); } diff --git a/lib/Parse/ParseTentative.cpp b/lib/Parse/ParseTentative.cpp index a6c6d3f945..5e64e6162b 100644 --- a/lib/Parse/ParseTentative.cpp +++ b/lib/Parse/ParseTentative.cpp @@ -753,6 +753,7 @@ Parser::TPResult Parser::isCXXDeclarationSpecifier() { case tok::kw___cdecl: case tok::kw___stdcall: case tok::kw___fastcall: + case tok::kw___thiscall: case tok::kw___w64: case tok::kw___ptr64: case tok::kw___forceinline: diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index 8d51639d22..6b8afed6f6 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/lib/Sema/SemaDeclAttr.cpp @@ -1654,6 +1654,8 @@ static void HandleCallConvAttr(Decl *d, const AttributeList &Attr, Sema &S) { case AttributeList::AT_stdcall: d->addAttr(::new (S.Context) StdCallAttr()); return; + case AttributeList::AT_thiscall: + d->addAttr(::new (S.Context) ThisCallAttr()); case AttributeList::AT_cdecl: d->addAttr(::new (S.Context) CDeclAttr()); return; @@ -1950,6 +1952,7 @@ static void ProcessDeclAttribute(Scope *scope, Decl *D, case AttributeList::AT_stdcall: case AttributeList::AT_cdecl: case AttributeList::AT_fastcall: + case AttributeList::AT_thiscall: HandleCallConvAttr(D, Attr, S); break; default: diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index 59c699d498..5ca632b8b3 100644 --- a/lib/Sema/SemaType.cpp +++ b/lib/Sema/SemaType.cpp @@ -1825,6 +1825,7 @@ bool ProcessFnAttr(Sema &S, QualType &Type, const AttributeList &Attr) { case AttributeList::AT_cdecl: CC = CC_C; break; case AttributeList::AT_fastcall: CC = CC_X86FastCall; break; case AttributeList::AT_stdcall: CC = CC_X86StdCall; break; + case AttributeList::AT_thiscall: CC = CC_X86ThisCall; break; default: llvm_unreachable("unexpected attribute kind"); return false; } @@ -1949,6 +1950,7 @@ void ProcessTypeAttributeList(Sema &S, QualType &Result, case AttributeList::AT_cdecl: case AttributeList::AT_fastcall: case AttributeList::AT_stdcall: + case AttributeList::AT_thiscall: case AttributeList::AT_regparm: // Don't process these on the DeclSpec. if (IsDeclSpec || diff --git a/test/CodeGen/stdcall-fastcall.c b/test/CodeGen/stdcall-fastcall.c index 46fe326fad..6f3b003287 100644 --- a/test/CodeGen/stdcall-fastcall.c +++ b/test/CodeGen/stdcall-fastcall.c @@ -2,38 +2,49 @@ void __attribute__((fastcall)) f1(void); void __attribute__((stdcall)) f2(void); -void __attribute__((fastcall)) f3(void) { -// CHECK: define x86_fastcallcc void @f3() +void __attribute__((thiscall)) f3(void); +void __attribute__((fastcall)) f4(void) { +// CHECK: define x86_fastcallcc void @f4() f1(); // CHECK: call x86_fastcallcc void @f1() } -void __attribute__((stdcall)) f4(void) { -// CHECK: define x86_stdcallcc void @f4() +void __attribute__((stdcall)) f5(void) { +// CHECK: define x86_stdcallcc void @f5() f2(); // CHECK: call x86_stdcallcc void @f2() } +void __attribute__((thiscall)) f6(void) { +// CHECK: define x86_thiscallcc void @f6() + f3(); +// CHECK: call x86_thiscallcc void @f3() +} // PR5280 void (__attribute__((fastcall)) *pf1)(void) = f1; void (__attribute__((stdcall)) *pf2)(void) = f2; -void (__attribute__((fastcall)) *pf3)(void) = f3; -void (__attribute__((stdcall)) *pf4)(void) = f4; +void (__attribute__((thiscall)) *pf3)(void) = f3; +void (__attribute__((fastcall)) *pf4)(void) = f4; +void (__attribute__((stdcall)) *pf5)(void) = f5; +void (__attribute__((thiscall)) *pf6)(void) = f6; int main(void) { - f3(); f4(); - // CHECK: call x86_fastcallcc void @f3() - // CHECK: call x86_stdcallcc void @f4() - pf1(); pf2(); pf3(); pf4(); + f4(); f5(); f6(); + // CHECK: call x86_fastcallcc void @f4() + // CHECK: call x86_stdcallcc void @f5() + // CHECK: call x86_thiscallcc void @f6() + pf1(); pf2(); pf3(); pf4(); pf5(); pf6(); // CHECK: call x86_fastcallcc void %{{.*}}() // CHECK: call x86_stdcallcc void %{{.*}}() + // CHECK: call x86_thiscallcc void %{{.*}}() // CHECK: call x86_fastcallcc void %{{.*}}() // CHECK: call x86_stdcallcc void %{{.*}}() + // CHECK: call x86_thiscallcc void %{{.*}}() return 0; } // PR7117 -void __attribute((stdcall)) f5(foo) int foo; {} -void f6(void) { - f5(0); +void __attribute((stdcall)) f7(foo) int foo; {} +void f8(void) { + f7(0); // CHECK: call x86_stdcallcc void (...)* bitcast } |