зеркало из https://github.com/microsoft/clang-1.git
Fix the CC-matching logic for instance methods in the MS ABI.
Patch by Timur Iskhodzhanov! git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@162639 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
2612e9f1d0
Коммит
fb60914137
|
@ -1920,6 +1920,19 @@ static bool canRedefineFunction(const FunctionDecl *FD,
|
|||
FD->getStorageClass() == SC_Extern);
|
||||
}
|
||||
|
||||
/// Is the given calling convention the ABI default for the given
|
||||
/// declaration?
|
||||
static bool isABIDefaultCC(Sema &S, CallingConv CC, FunctionDecl *D) {
|
||||
CallingConv ABIDefaultCC;
|
||||
if (isa<CXXMethodDecl>(D) && cast<CXXMethodDecl>(D)->isInstance()) {
|
||||
ABIDefaultCC = S.Context.getDefaultCXXMethodCallConv(D->isVariadic());
|
||||
} else {
|
||||
// Free C function or a static method.
|
||||
ABIDefaultCC = (S.Context.getLangOpts().MRTD ? CC_X86StdCall : CC_C);
|
||||
}
|
||||
return ABIDefaultCC == CC;
|
||||
}
|
||||
|
||||
/// MergeFunctionDecl - We just parsed a function 'New' from
|
||||
/// declarator D which has the same name and scope as a previous
|
||||
/// declaration 'Old'. Figure out how to resolve this situation,
|
||||
|
@ -1988,6 +2001,9 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, Scope *S) {
|
|||
// later declared or defined without one, the second decl assumes the
|
||||
// calling convention of the first.
|
||||
//
|
||||
// It's OK if a function is first declared without a calling convention,
|
||||
// but is later declared or defined with the default calling convention.
|
||||
//
|
||||
// For the new decl, we have to look at the NON-canonical type to tell the
|
||||
// difference between a function that really doesn't have a calling
|
||||
// convention and one that is declared cdecl. That's because in
|
||||
|
@ -2001,10 +2017,22 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, Scope *S) {
|
|||
FunctionType::ExtInfo OldTypeInfo = OldType->getExtInfo();
|
||||
FunctionType::ExtInfo NewTypeInfo = NewType->getExtInfo();
|
||||
bool RequiresAdjustment = false;
|
||||
if (OldTypeInfo.getCC() != CC_Default &&
|
||||
NewTypeInfo.getCC() == CC_Default) {
|
||||
if (OldTypeInfo.getCC() == NewTypeInfo.getCC()) {
|
||||
// Fast path: nothing to do.
|
||||
|
||||
// Inherit the CC from the previous declaration if it was specified
|
||||
// there but not here.
|
||||
} else if (NewTypeInfo.getCC() == CC_Default) {
|
||||
NewTypeInfo = NewTypeInfo.withCallingConv(OldTypeInfo.getCC());
|
||||
RequiresAdjustment = true;
|
||||
|
||||
// Don't complain about mismatches when the default CC is
|
||||
// effectively the same as the explict one.
|
||||
} else if (OldTypeInfo.getCC() == CC_Default &&
|
||||
isABIDefaultCC(*this, NewTypeInfo.getCC(), New)) {
|
||||
NewTypeInfo = NewTypeInfo.withCallingConv(OldTypeInfo.getCC());
|
||||
RequiresAdjustment = true;
|
||||
|
||||
} else if (!Context.isSameCallConv(OldTypeInfo.getCC(),
|
||||
NewTypeInfo.getCC())) {
|
||||
// Calling conventions really aren't compatible, so complain.
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
// RUN: %clang_cc1 -emit-llvm %s -o - | FileCheck -check-prefix GCABI %s
|
||||
// RUN: %clang_cc1 -emit-llvm %s -o - -DMS_ABI -cxx-abi microsoft -triple=i386-pc-win32 | FileCheck -check-prefix MSABI %s
|
||||
|
||||
#ifdef MS_ABI
|
||||
# define METHOD_CC __thiscall
|
||||
#else
|
||||
# define METHOD_CC __attribute__ ((cdecl))
|
||||
#endif
|
||||
|
||||
// Test that it's OK to have multiple function declarations with the default CC
|
||||
// both mentioned explicitly and implied.
|
||||
void foo();
|
||||
void __cdecl foo();
|
||||
void __cdecl foo() {}
|
||||
// GCABI: define void @_Z3foov()
|
||||
// MSABI: define void @"\01?foo@@YAXXZ"
|
||||
|
||||
void __cdecl bar();
|
||||
void bar();
|
||||
void bar() {}
|
||||
// GCABI: define void @_Z3barv()
|
||||
// MSABI: define void @"\01?bar@@YAXXZ"
|
||||
|
||||
// Test that it's OK to mark either the method declaration or method definition
|
||||
// with a default CC explicitly.
|
||||
class A {
|
||||
public:
|
||||
void baz();
|
||||
void METHOD_CC qux();
|
||||
|
||||
void static_baz();
|
||||
void __cdecl static_qux();
|
||||
};
|
||||
|
||||
void METHOD_CC A::baz() {}
|
||||
// GCABI: define void @_ZN1A3bazEv
|
||||
// MSABI: define x86_thiscallcc void @"\01?baz@A@@QAEXXZ"
|
||||
void A::qux() {}
|
||||
// GCABI: define void @_ZN1A3quxEv
|
||||
// MSABI: define x86_thiscallcc void @"\01?qux@A@@QAEXXZ"
|
||||
|
||||
void __cdecl static_baz() {}
|
||||
// GCABI: define void @_Z10static_bazv
|
||||
// MSABI: define void @"\01?static_baz@@YAXXZ"
|
||||
void static_qux() {}
|
||||
// GCABI: define void @_Z10static_quxv
|
||||
// MSABI: define void @"\01?static_qux@@YAXXZ"
|
Загрузка…
Ссылка в новой задаче