Add support for Microsoft's __thiscall, from Steven Watanabe!
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@104026 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/clang/AST/Attr.h b/include/clang/AST/Attr.h
index 1974493..6bdb4a2 100644
--- a/include/clang/AST/Attr.h
+++ b/include/clang/AST/Attr.h
@@ -86,6 +86,7 @@
Section,
Sentinel,
StdCall,
+ ThisCall,
TransparentUnion,
Unavailable,
Unused,
@@ -457,6 +458,7 @@
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 c2cddb9..f14b652 100644
--- a/include/clang/AST/Type.h
+++ b/include/clang/AST/Type.h
@@ -396,7 +396,8 @@
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 @@
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 @@
// 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 52e83f4..c50b31d 100644
--- a/include/clang/Basic/TokenKinds.def
+++ b/include/clang/Basic/TokenKinds.def
@@ -336,6 +336,7 @@
KEYWORD(__cdecl , KEYALL)
KEYWORD(__stdcall , KEYALL)
KEYWORD(__fastcall , KEYALL)
+KEYWORD(__thiscall , KEYALL)
KEYWORD(__forceinline , KEYALL)
// Altivec Extension.
@@ -372,6 +373,7 @@
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 12512f3..68d6f22 100644
--- a/include/clang/Parse/AttributeList.h
+++ b/include/clang/Parse/AttributeList.h
@@ -102,6 +102,7 @@
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 423aa06..0345226 100644
--- a/lib/AST/AttrImpl.cpp
+++ b/lib/AST/AttrImpl.cpp
@@ -100,6 +100,7 @@
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 ebaad9a..5d27ba4 100644
--- a/lib/AST/Type.cpp
+++ b/lib/AST/Type.cpp
@@ -919,6 +919,7 @@
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 ad5b91a..35a7e09 100644
--- a/lib/AST/TypePrinter.cpp
+++ b/lib/AST/TypePrinter.cpp
@@ -295,6 +295,9 @@
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 92d15d9..0d6a70c 100644
--- a/lib/CodeGen/CGCall.cpp
+++ b/lib/CodeGen/CGCall.cpp
@@ -38,6 +38,7 @@
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 @@
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 49010bf..1e8bd2f 100644
--- a/lib/Frontend/PCHReaderDecl.cpp
+++ b/lib/Frontend/PCHReaderDecl.cpp
@@ -763,6 +763,7 @@
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 bae2a09..5340628 100644
--- a/lib/Parse/AttributeList.cpp
+++ b/lib/Parse/AttributeList.cpp
@@ -119,5 +119,10 @@
.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 28d9dd0..929b20c 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -277,8 +277,8 @@
// 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 @@
case tok::kw___cdecl:
case tok::kw___stdcall:
case tok::kw___fastcall:
+ case tok::kw___thiscall:
DS.AddAttributes(ParseMicrosoftTypeAttributes());
continue;
@@ -1622,6 +1623,7 @@
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 @@
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 @@
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 @@
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 @@
}
// 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 a6c6d3f..5e64e61 100644
--- a/lib/Parse/ParseTentative.cpp
+++ b/lib/Parse/ParseTentative.cpp
@@ -753,6 +753,7 @@
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 8d51639..6b8afed 100644
--- a/lib/Sema/SemaDeclAttr.cpp
+++ b/lib/Sema/SemaDeclAttr.cpp
@@ -1654,6 +1654,8 @@
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 @@
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 59c699d..5ca632b 100644
--- a/lib/Sema/SemaType.cpp
+++ b/lib/Sema/SemaType.cpp
@@ -1825,6 +1825,7 @@
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 @@
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 46fe326..6f3b003 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
}