From 4bdbc0cb1e29ac870b7e7985cf4a1b5c34176e8c Mon Sep 17 00:00:00 2001 From: Anders Carlsson Date: Mon, 11 Apr 2011 14:13:40 +0000 Subject: [PATCH] If there's an invoke destination, we should use invoke instead of call when calling the __cxa_bad_typeid function. Fixes PR7400. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@129273 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGExprCXX.cpp | 32 +++++++++++++++++++++++++------- test/CodeGenCXX/typeid.cpp | 18 ++++++++++++++++++ 2 files changed, 43 insertions(+), 7 deletions(-) create mode 100644 test/CodeGenCXX/typeid.cpp diff --git a/lib/CodeGen/CGExprCXX.cpp b/lib/CodeGen/CGExprCXX.cpp index ef71e89077..4d5f8827de 100644 --- a/lib/CodeGen/CGExprCXX.cpp +++ b/lib/CodeGen/CGExprCXX.cpp @@ -1338,6 +1338,28 @@ void CodeGenFunction::EmitCXXDeleteExpr(const CXXDeleteExpr *E) { EmitBlock(DeleteEnd); } +static llvm::Constant *getBadTypeidFn(CodeGenFunction &CGF) { + // void __cxa_bad_typeid(); + + const llvm::Type *VoidTy = llvm::Type::getVoidTy(CGF.getLLVMContext()); + const llvm::FunctionType *FTy = + llvm::FunctionType::get(VoidTy, false); + + return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_bad_typeid"); +} + +static void EmitBadTypeidCall(CodeGenFunction &CGF) { + llvm::Value *F = getBadTypeidFn(CGF); + if (llvm::BasicBlock *InvokeDest = CGF.getInvokeDest()) { + llvm::BasicBlock *Cont = CGF.createBasicBlock("invoke.cont"); + CGF.Builder.CreateInvoke(F, Cont, InvokeDest)->setDoesNotReturn(); + CGF.EmitBlock(Cont); + } else + CGF.Builder.CreateCall(F)->setDoesNotReturn(); + + CGF.Builder.CreateUnreachable(); +} + llvm::Value *CodeGenFunction::EmitCXXTypeidExpr(const CXXTypeidExpr *E) { QualType Ty = E->getType(); const llvm::Type *LTy = ConvertType(Ty)->getPointerTo(); @@ -1372,13 +1394,9 @@ llvm::Value *CodeGenFunction::EmitCXXTypeidExpr(const CXXTypeidExpr *E) { Builder.CreateCondBr(Builder.CreateICmpNE(This, Zero), NonZeroBlock, ZeroBlock); EmitBlock(ZeroBlock); - /// Call __cxa_bad_typeid - const llvm::Type *ResultType = llvm::Type::getVoidTy(getLLVMContext()); - const llvm::FunctionType *FTy; - FTy = llvm::FunctionType::get(ResultType, false); - llvm::Value *F = CGM.CreateRuntimeFunction(FTy, "__cxa_bad_typeid"); - Builder.CreateCall(F)->setDoesNotReturn(); - Builder.CreateUnreachable(); + + EmitBadTypeidCall(*this); + EmitBlock(NonZeroBlock); } llvm::Value *V = GetVTablePtr(This, LTy->getPointerTo()); diff --git a/test/CodeGenCXX/typeid.cpp b/test/CodeGenCXX/typeid.cpp new file mode 100644 index 0000000000..c2990586b5 --- /dev/null +++ b/test/CodeGenCXX/typeid.cpp @@ -0,0 +1,18 @@ +// RUN: %clang_cc1 -I%S %s -triple x86_64-apple-darwin10 -emit-llvm -fcxx-exceptions -fexceptions -o - | FileCheck %s +#include + +// PR7400 +struct A { virtual void f(); }; + +// CHECK: define i8* @_Z1fv +const char *f() { + try { + // CHECK: br i1 + // CHECK: invoke void @__cxa_bad_typeid() noreturn + return typeid(*static_cast(0)).name(); + } catch (...) { + // CHECK: call i8* @llvm.eh.exception + } + + return 0; +} -- 2.40.0