]> granicus.if.org Git - clang/commitdiff
Introduce CGCXXABI::canCallMismatchedFunctionType
authorDerek Schuff <dschuff@google.com>
Tue, 10 May 2016 17:44:55 +0000 (17:44 +0000)
committerDerek Schuff <dschuff@google.com>
Tue, 10 May 2016 17:44:55 +0000 (17:44 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@269089 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/CGCXXABI.h
lib/CodeGen/CGDeclCXX.cpp
lib/CodeGen/ItaniumCXXABI.cpp
test/CodeGenCXX/runtimecc.cpp
test/CodeGenCXX/static-destructor.cpp

index 3f240b1802b8adb90f121e8547fce83df46f9b31..8c0f6c2efd51a19322683b69d8c75697e36e7f46 100644 (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;
index 46d92ec46c4fdc96c1fca85f2bd0e999c84cb041..89d142e44b49e5ba4d53f7a4efdd58f6213c9992 100644 (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.
index 52e519f304418e98766b767f002b18aad428ce01..4da7b9498f608ba2bd48f102b2f5f83b6e0f2f0a 100644 (file)
@@ -443,6 +443,7 @@ private:
            (isa<CXXDestructorDecl>(GD.getDecl()) &&
             GD.getDtorType() != Dtor_Deleting);
   }
+  bool canCallMismatchedFunctionType() const override { return false; }
 };
 }
 
index 1aac5ffa716596c3617896b116f9a86c0de9fdb0..ad6dc85c360d689bf055c1eee01bcd13bac15712 100644 (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]]
index 1b6ca305563cfe043b4ef9f3a616fcb1d3eb8cea..24e31d3d863312501998c26673d0f90d087bd6e5 100644 (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()