Introduce CGCXXABI::canCallMismatchedFunctionType

llvm-svn: 269089
This commit is contained in:
Derek Schuff 2016-05-10 17:44:55 +00:00
parent 09b2492387
commit 8179be4897
5 changed files with 24 additions and 11 deletions

View File

@ -106,6 +106,16 @@ public:
virtual bool hasMostDerivedReturn(GlobalDecl GD) const { return false; }
/// Returns true if the target allows calling a function through a pointer
/// with a different signature than the actual function (or equivalently,
/// bitcasting a function or function pointer to a different function type).
/// In principle in the most general case this could depend on the target, the
/// calling convention, and the actual types of the arguments and return
/// value. Here it just means whether the signature mismatch could *ever* be
/// allowed; in other words, does the target do strict checking of signatures
/// for all calls.
virtual bool canCallMismatchedFunctionType() const { return true; }
/// If the C++ ABI requires the given type be returned in a particular way,
/// this method sets RetAI and returns true.
virtual bool classifyReturnType(CGFunctionInfo &FI) const = 0;

View File

@ -88,11 +88,12 @@ static void EmitDeclDestroy(CodeGenFunction &CGF, const VarDecl &D,
// Special-case non-array C++ destructors, if they have the right signature.
// Under some ABIs, destructors return this instead of void, and cannot be
// passed directly to __cxa_atexit.
// passed directly to __cxa_atexit if the target does not allow this mismatch.
const CXXRecordDecl *Record = type->getAsCXXRecordDecl();
bool CanRegisterDestructor = Record &&
!CGM.getCXXABI().HasThisReturn(GlobalDecl(
Record->getDestructor(), Dtor_Complete));
bool CanRegisterDestructor =
Record && (!CGM.getCXXABI().HasThisReturn(
GlobalDecl(Record->getDestructor(), Dtor_Complete)) ||
CGM.getCXXABI().canCallMismatchedFunctionType());
// If __cxa_atexit is disabled via a flag, a different helper function is
// generated elsewhere which uses atexit instead, and it takes the destructor
// directly.

View File

@ -443,6 +443,7 @@ private:
(isa<CXXDestructorDecl>(GD.getDecl()) &&
GD.getDtorType() != Dtor_Deleting);
}
bool canCallMismatchedFunctionType() const override { return false; }
};
}

View File

@ -22,13 +22,8 @@ namespace test0 {
A global;
// CHECK-LABEL: define internal void @__cxx_global_var_init()
// CHECK: call [[A]]* @_ZN5test01AC1Ev([[A]]* @_ZN5test06globalE)
// CHECK-NEXT: call i32 @__cxa_atexit(void (i8*)* @__cxx_global_array_dtor, i8* null, i8* @__dso_handle) [[NOUNWIND:#[0-9]+]]
// CHECK-NEXT: call i32 @__cxa_atexit(void (i8*)* bitcast ([[A]]* ([[A]]*)* @_ZN5test01AD1Ev to void (i8*)*), i8* bitcast ([[A]]* @_ZN5test06globalE to i8*), i8* @__dso_handle) [[NOUNWIND:#[0-9]+]]
// CHECK-NEXT: ret void
// CHECK-LABEL: define internal void @__cxx_global_array_dtor(i8*)
// CHECK: call [[A]]* @_ZN5test01AD1Ev([[A]]* @_ZN5test06globalE)
// CHECK-NEXT: ret void
}
// CHECK: declare i32 @__cxa_atexit(void (i8*)*, i8*, i8*) [[NOUNWIND]]

View File

@ -1,6 +1,6 @@
// RUN: %clang_cc1 %s -triple=x86_64-pc-linux -emit-llvm -o - | FileCheck --check-prefix=X86 %s
// RUN: %clang_cc1 %s -triple=wasm32 -emit-llvm -o - | FileCheck --check-prefix=WASM %s
// RUN: %clang_cc1 %s -triple=armv7-apple-darwin9 -emit-llvm -o - | FileCheck --check-prefix=WASM %s
// RUN: %clang_cc1 %s -triple=armv7-apple-darwin9 -emit-llvm -o - | FileCheck --check-prefix=ARM %s
// Test that destructors are not passed directly to __cxa_atexit when their
// signatures do not match the type of its first argument.
@ -20,6 +20,12 @@ Foo global;
// X86-NEXT: entry:
// X86-NEXT: %0 = call i32 @__cxa_atexit(void (i8*)* bitcast (void (%class.Foo*)* @_ZN3FooD1Ev to void (i8*)*), i8* getelementptr inbounds (%class.Foo, %class.Foo* @global, i32 0, i32 0), i8* @__dso_handle)
// ARM destructors return this, but can be registered directly with __cxa_atexit
// because the calling conventions tolerate the mismatch.
// ARM: define internal void @__cxx_global_var_init()
// ARM-NEXT: entry:
// ARM-NEXT: %0 = call i32 @__cxa_atexit(void (i8*)* bitcast (%class.Foo* (%class.Foo*)* @_ZN3FooD1Ev to void (i8*)*), i8* getelementptr inbounds (%class.Foo, %class.Foo* @global, i32 0, i32 0), i8* @__dso_handle)
// Wasm destructors return this, and use a wrapper function, which is registered
// with __cxa_atexit.
// WASM: define internal void @__cxx_global_var_init()