]> granicus.if.org Git - clang/commitdiff
If there's an invoke destination, we should use invoke instead of call when calling...
authorAnders Carlsson <andersca@mac.com>
Mon, 11 Apr 2011 14:13:40 +0000 (14:13 +0000)
committerAnders Carlsson <andersca@mac.com>
Mon, 11 Apr 2011 14:13:40 +0000 (14:13 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@129273 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/CGExprCXX.cpp
test/CodeGenCXX/typeid.cpp [new file with mode: 0644]

index ef71e8907782d77106df420d4c11e659b1b8c764..4d5f8827de228bac9e648185a8c39a847e30a27a 100644 (file)
@@ -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 (file)
index 0000000..c299058
--- /dev/null
@@ -0,0 +1,18 @@
+// RUN: %clang_cc1 -I%S %s -triple x86_64-apple-darwin10 -emit-llvm -fcxx-exceptions -fexceptions -o - | FileCheck %s
+#include <typeinfo>
+
+// 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<A *>(0)).name();
+  } catch (...) {
+    // CHECK: call i8* @llvm.eh.exception
+  }
+
+  return 0;
+}