From 3c02b7312f417e6a400c8aaba97b167e36c6e410 Mon Sep 17 00:00:00 2001 From: Vedant Kumar Date: Fri, 11 Sep 2015 15:40:05 +0000 Subject: [PATCH] [CodeGen] Teach SimplifyPersonality about the updated LandingPadInst 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 | 66 ++++++++++++++----------- test/CodeGenObjCXX/exception-cxx.mm | 13 +++++ test/CodeGenObjCXX/personality-abuse.mm | 19 +++++++ 3 files changed, 70 insertions(+), 28 deletions(-) create mode 100644 test/CodeGenObjCXX/exception-cxx.mm create mode 100644 test/CodeGenObjCXX/personality-abuse.mm diff --git a/lib/CodeGen/CGException.cpp b/lib/CodeGen/CGException.cpp index 255cb841c8..858b83da36 100644 --- a/lib/CodeGen/CGException.cpp +++ b/lib/CodeGen/CGException.cpp @@ -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(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(Val); + for (llvm::User::op_iterator + II = CVal->op_begin(), IE = CVal->op_end(); II != IE; ++II) { + if (llvm::GlobalVariable *GV = + cast((*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(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(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(Val); - for (llvm::User::op_iterator - II = CVal->op_begin(), IE = CVal->op_end(); II != IE; ++II) { - if (llvm::GlobalVariable *GV = - cast((*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(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 index 0000000000..76a5a08458 --- /dev/null +++ b/test/CodeGenObjCXX/exception-cxx.mm @@ -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 index 0000000000..55e0e2c832 --- /dev/null +++ b/test/CodeGenObjCXX/personality-abuse.mm @@ -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*) -- 2.40.0