diff options
author | Mike Stump <mrs@apple.com> | 2009-11-15 16:52:53 +0000 |
---|---|---|
committer | Mike Stump <mrs@apple.com> | 2009-11-15 16:52:53 +0000 |
commit | f549e898a44fe91aca46fe34e9ba04a2f08318bf (patch) | |
tree | eac640e6f0b5836c560f32b873aa46a796f39a60 | |
parent | 50724302e24d44a27e3bc45e7185a710d6eb3c2d (diff) |
Finish off zero check for typeid(*p) so that it will do a __cxa_bad_typeid.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@88852 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/CodeGen/CGCXXExpr.cpp | 27 | ||||
-rw-r--r-- | test/CodeGenCXX/rtti.cpp | 14 |
2 files changed, 39 insertions, 2 deletions
diff --git a/lib/CodeGen/CGCXXExpr.cpp b/lib/CodeGen/CGCXXExpr.cpp index 565685c6d0..ccbb608553 100644 --- a/lib/CodeGen/CGCXXExpr.cpp +++ b/lib/CodeGen/CGCXXExpr.cpp @@ -357,8 +357,31 @@ llvm::Value * CodeGenFunction::EmitCXXTypeidExpr(const CXXTypeidExpr *E) { // FIXME: if subE is an lvalue do LValue Obj = EmitLValue(subE); llvm::Value *This = Obj.getAddress(); - // FIXME: need to do a 0 check here for *p on This - llvm::Value *V = Builder.CreateBitCast(This, LTy->getPointerTo()->getPointerTo()); + LTy = LTy->getPointerTo()->getPointerTo(); + llvm::Value *V = Builder.CreateBitCast(This, LTy); + // We need to do a zero check for *p, unless it has NonNullAttr. + // FIXME: PointerType->hasAttr<NonNullAttr>() + bool CanBeZero = false; + if (UnaryOperator *UO = dyn_cast<UnaryOperator>(subE)) + if (UO->getOpcode() == UnaryOperator::Deref) + CanBeZero = true; + if (CanBeZero) { + llvm::BasicBlock *NonZeroBlock = createBasicBlock(); + llvm::BasicBlock *ZeroBlock = createBasicBlock(); + + llvm::Value *Zero = llvm::Constant::getNullValue(LTy); + Builder.CreateCondBr(Builder.CreateICmpNE(V, Zero), + NonZeroBlock, ZeroBlock); + EmitBlock(ZeroBlock); + /// Call __cxa_bad_typeid + const llvm::Type *ResultType = llvm::Type::getVoidTy(VMContext); + const llvm::FunctionType *FTy; + FTy = llvm::FunctionType::get(ResultType, false); + llvm::Value *F = CGM.CreateRuntimeFunction(FTy, "__cxa_bad_typeid"); + Builder.CreateCall(F); + Builder.CreateUnreachable(); + EmitBlock(NonZeroBlock); + } V = Builder.CreateLoad(V, "vtable"); V = Builder.CreateConstInBoundsGEP1_64(V, -1ULL); V = Builder.CreateLoad(V); diff --git a/test/CodeGenCXX/rtti.cpp b/test/CodeGenCXX/rtti.cpp index f89396dd11..3e41c72b2c 100644 --- a/test/CodeGenCXX/rtti.cpp +++ b/test/CodeGenCXX/rtti.cpp @@ -102,6 +102,8 @@ void test2_2(test1_D *dp) { test2_1(); if (typeid(NP) == typeid(test1_D)) test2_1(); + if (typeid(*dp) == typeid(test1_D)) + test2_1(); } // CHECK-LL:define void @_Z7test2_2P7test1_D(%class.test1_B7* %dp) nounwind { @@ -113,3 +115,15 @@ void test2_2(test1_D *dp) { // CHECK-LL-NEXT: %call = call zeroext i1 @_ZNK3std9type_infoeqERKS0_(%"class.std::type_info"* %2, %"class.std::type_info"* bitcast (%1* @_ZTI7test1_D to %"class.std::type_info"*)) // CHECK-LL: %call2 = call zeroext i1 @_ZNK3std9type_infoeqERKS0_(%"class.std::type_info"* bitcast (%0* @_ZTI2NP to %"class.std::type_info"*), %"class.std::type_info"* bitcast (%1* @_ZTI7test1_D to %"class.std::type_info"*)) + +// CHECK-LL: %3 = bitcast %class.test1_B7* %tmp5 to %"class.std::type_info"*** +// CHECK-LL-NEXT: %4 = icmp ne %"class.std::type_info"*** %3, null +// CHECK-LL-NEXT: br i1 %4, label %6, label %5 +// CHECK-LL: ; <label>:5 +// CHECK-LL-NEXT: call void @__cxa_bad_typeid() +// CHECK-LL-NEXT: unreachable +// CHECK-LL: ; <label>:6 +// CHECK-LL-NEXT: %vtable6 = load %"class.std::type_info"*** %3 +// CHECK-LL-NEXT: %7 = getelementptr inbounds %"class.std::type_info"** %vtable6, i64 -1 +// CHECK-LL-NEXT: %8 = load %"class.std::type_info"** %7 +// CHECK-LL-NEXT: %call7 = call zeroext i1 @_ZNK3std9type_infoeqERKS0_(%"class.std::type_info"* %8, %"class.std::type_info"* bitcast (%1* @_ZTI7test1_D to %"class.std::type_info"*)) |