]> granicus.if.org Git - clang/commitdiff
[CodeGen] Teach SimplifyPersonality about the updated LandingPadInst
authorVedant Kumar <vsk@apple.com>
Fri, 11 Sep 2015 15:40:05 +0000 (15:40 +0000)
committerVedant Kumar <vsk@apple.com>
Fri, 11 Sep 2015 15:40:05 +0000 (15:40 +0000)
When uses of personality functions were moved from LandingPadInst to
Function, we forgot to update SimplifyPersonality(). This patch corrects
that.

Note: SimplifyPersonality() is an optimization which replaces
personality functions with the default C++ personality when possible.
Without this update, some ObjC++ projects fail to link against C++
libraries (seeing as the exception ABI had effectively changed).

rdar://problem/22155434

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@247421 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/CGException.cpp
test/CodeGenObjCXX/exception-cxx.mm [new file with mode: 0644]
test/CodeGenObjCXX/personality-abuse.mm [new file with mode: 0644]

index 255cb841c861488da0b06cf125c21b7c0d590b68..858b83da36ecdd3a50de163a80a7e30151ad04ee 100644 (file)
@@ -229,6 +229,36 @@ static llvm::Constant *getOpaquePersonalityFn(CodeGenModule &CGM,
   return llvm::ConstantExpr::getBitCast(Fn, CGM.Int8PtrTy);
 }
 
+/// Check whether a landingpad instruction only uses C++ features.
+static bool LandingPadHasOnlyCXXUses(llvm::LandingPadInst *LPI) {
+  for (unsigned I = 0, E = LPI->getNumClauses(); I != E; ++I) {
+    // Look for something that would've been returned by the ObjC
+    // runtime's GetEHType() method.
+    llvm::Value *Val = LPI->getClause(I)->stripPointerCasts();
+    if (LPI->isCatch(I)) {
+      // Check if the catch value has the ObjC prefix.
+      if (llvm::GlobalVariable *GV = dyn_cast<llvm::GlobalVariable>(Val))
+        // ObjC EH selector entries are always global variables with
+        // names starting like this.
+        if (GV->getName().startswith("OBJC_EHTYPE"))
+          return false;
+    } else {
+      // Check if any of the filter values have the ObjC prefix.
+      llvm::Constant *CVal = cast<llvm::Constant>(Val);
+      for (llvm::User::op_iterator
+              II = CVal->op_begin(), IE = CVal->op_end(); II != IE; ++II) {
+        if (llvm::GlobalVariable *GV =
+            cast<llvm::GlobalVariable>((*II)->stripPointerCasts()))
+          // ObjC EH selector entries are always global variables with
+          // names starting like this.
+          if (GV->getName().startswith("OBJC_EHTYPE"))
+            return false;
+      }
+    }
+  }
+  return true;
+}
+
 /// Check whether a personality function could reasonably be swapped
 /// for a C++ personality function.
 static bool PersonalityHasOnlyCXXUses(llvm::Constant *Fn) {
@@ -241,34 +271,14 @@ static bool PersonalityHasOnlyCXXUses(llvm::Constant *Fn) {
       continue;
     }
 
-    // Otherwise, it has to be a landingpad instruction.
-    llvm::LandingPadInst *LPI = dyn_cast<llvm::LandingPadInst>(U);
-    if (!LPI) return false;
-
-    for (unsigned I = 0, E = LPI->getNumClauses(); I != E; ++I) {
-      // Look for something that would've been returned by the ObjC
-      // runtime's GetEHType() method.
-      llvm::Value *Val = LPI->getClause(I)->stripPointerCasts();
-      if (LPI->isCatch(I)) {
-        // Check if the catch value has the ObjC prefix.
-        if (llvm::GlobalVariable *GV = dyn_cast<llvm::GlobalVariable>(Val))
-          // ObjC EH selector entries are always global variables with
-          // names starting like this.
-          if (GV->getName().startswith("OBJC_EHTYPE"))
-            return false;
-      } else {
-        // Check if any of the filter values have the ObjC prefix.
-        llvm::Constant *CVal = cast<llvm::Constant>(Val);
-        for (llvm::User::op_iterator
-               II = CVal->op_begin(), IE = CVal->op_end(); II != IE; ++II) {
-          if (llvm::GlobalVariable *GV =
-              cast<llvm::GlobalVariable>((*II)->stripPointerCasts()))
-            // ObjC EH selector entries are always global variables with
-            // names starting like this.
-            if (GV->getName().startswith("OBJC_EHTYPE"))
-              return false;
-        }
-      }
+    // Otherwise it must be a function.
+    llvm::Function *F = dyn_cast<llvm::Function>(U);
+    if (!F) return false;
+
+    for (auto BB = F->begin(), E = F->end(); BB != E; ++BB) {
+      if (BB->isLandingPad())
+        if (!LandingPadHasOnlyCXXUses(BB->getLandingPadInst()))
+          return false;
     }
   }
 
diff --git a/test/CodeGenObjCXX/exception-cxx.mm b/test/CodeGenObjCXX/exception-cxx.mm
new file mode 100644 (file)
index 0000000..76a5a08
--- /dev/null
@@ -0,0 +1,13 @@
+// RUN: %clang_cc1 -x objective-c++ -triple x86_64-apple-darwin10 -emit-llvm -fcxx-exceptions -fexceptions -fobjc-exceptions -o - %s | FileCheck %s
+
+// rdar://problem/22155434
+namespace test0 {
+  void foo() {
+    try {
+      throw 0;
+    } catch (...) {
+      return;
+    }
+  }
+// CHECK: define void @_ZN5test03fooEv() #0 personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*)
+}
diff --git a/test/CodeGenObjCXX/personality-abuse.mm b/test/CodeGenObjCXX/personality-abuse.mm
new file mode 100644 (file)
index 0000000..55e0e2c
--- /dev/null
@@ -0,0 +1,19 @@
+// RUN: %clang_cc1 -x objective-c++ -triple x86_64-apple-darwin10 -emit-llvm -fcxx-exceptions -fexceptions -fobjc-exceptions -o - %s | FileCheck %s
+
+extern "C" {
+  int __objc_personality_v0();
+}
+
+void *abuse_personality_func() {
+  return (void *)&__objc_personality_v0;
+}
+
+void foo() {
+  try {
+    throw 0;
+  } catch (...) {
+    return;
+  }
+}
+
+// CHECK: define void @_Z3foov() #1 personality i8* bitcast (i32 ()* @__objc_personality_v0 to i8*)