forked from OSchip/llvm-project
Introduce CGCXXABI::canCallMismatchedFunctionType
llvm-svn: 269089
This commit is contained in:
parent
09b2492387
commit
8179be4897
|
@ -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;
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -443,6 +443,7 @@ private:
|
|||
(isa<CXXDestructorDecl>(GD.getDecl()) &&
|
||||
GD.getDtorType() != Dtor_Deleting);
|
||||
}
|
||||
bool canCallMismatchedFunctionType() const override { return false; }
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -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]]
|
||||
|
|
|
@ -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()
|
||||
|
|
Loading…
Reference in New Issue