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:
John McCall 2012-08-25 02:00:03 +00:00
Родитель 2612e9f1d0
Коммит fb60914137
2 изменённых файлов: 77 добавлений и 2 удалений

Просмотреть файл

@ -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"