[cfe-commits] r129264 - in /cfe/trunk: lib/CodeGen/CGExprCXX.cpp test/CodeGenCXX/dynamic-cast-always-null.cpp
Anders Carlsson
andersca at mac.com
Sun Apr 10 18:45:29 PDT 2011
Author: andersca
Date: Sun Apr 10 20:45:29 2011
New Revision: 129264
URL: http://llvm.org/viewvc/llvm-project?rev=129264&view=rev
Log:
When we know that a dynamic_cast always returns null, we can make
CodeGenFunction::EmitDynamicCast always return null or throw a bad_cast
exception.
Added:
cfe/trunk/test/CodeGenCXX/dynamic-cast-always-null.cpp
Modified:
cfe/trunk/lib/CodeGen/CGExprCXX.cpp
Modified: cfe/trunk/lib/CodeGen/CGExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprCXX.cpp?rev=129264&r1=129263&r2=129264&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprCXX.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprCXX.cpp Sun Apr 10 20:45:29 2011
@@ -1416,6 +1416,18 @@
return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_bad_cast");
}
+static void EmitBadCastCall(CodeGenFunction &CGF) {
+ llvm::Value *F = getBadCastFn(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();
+}
+
static llvm::Value *
EmitDynamicCastCall(CodeGenFunction &CGF, llvm::Value *Value,
QualType SrcTy, QualType DestTy,
@@ -1484,25 +1496,35 @@
CGF.Builder.CreateCondBr(IsNull, BadCastBlock, CastEnd);
CGF.EmitBlock(BadCastBlock);
- llvm::Value *F = getBadCastFn(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();
+ EmitBadCastCall(CGF);
}
return Value;
}
+static llvm::Value *EmitDynamicCastToNull(CodeGenFunction &CGF,
+ QualType DestTy) {
+ const llvm::Type *DestLTy = CGF.ConvertType(DestTy);
+ if (DestTy->isPointerType())
+ return llvm::Constant::getNullValue(DestLTy);
+
+ /// C++ [expr.dynamic.cast]p9:
+ /// A failed cast to reference type throws std::bad_cast
+ EmitBadCastCall(CGF);
+
+ CGF.EmitBlock(CGF.createBasicBlock("dynamic_cast.end"));
+ return llvm::UndefValue::get(DestLTy);
+}
+
llvm::Value *CodeGenFunction::EmitDynamicCast(llvm::Value *Value,
const CXXDynamicCastExpr *DCE) {
- QualType SrcTy = DCE->getSubExpr()->getType();
QualType DestTy = DCE->getTypeAsWritten();
+ if (DCE->isAlwaysNull())
+ return EmitDynamicCastToNull(*this, DestTy);
+
+ QualType SrcTy = DCE->getSubExpr()->getType();
+
// C++ [expr.dynamic.cast]p4:
// If the value of v is a null pointer value in the pointer case, the result
// is the null pointer value of type T.
Added: cfe/trunk/test/CodeGenCXX/dynamic-cast-always-null.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/dynamic-cast-always-null.cpp?rev=129264&view=auto
==============================================================================
--- cfe/trunk/test/CodeGenCXX/dynamic-cast-always-null.cpp (added)
+++ cfe/trunk/test/CodeGenCXX/dynamic-cast-always-null.cpp Sun Apr 10 20:45:29 2011
@@ -0,0 +1,19 @@
+// RUN: %clang_cc1 -I%S %s -triple x86_64-apple-darwin10 -emit-llvm -fcxx-exceptions -fexceptions -std=c++0x -o - | FileCheck %s
+struct A { virtual ~A(); };
+struct B final : A { };
+struct C { virtual ~C(); };
+
+// CHECK: @_Z1fP1B
+C *f(B* b) {
+ // CHECK-NOT: call i8* @__dynamic_cast
+ // CHECK: ret %struct.C* null
+ return dynamic_cast<C*>(b);
+}
+
+// CHECK: @_Z1fR1B
+C &f(B& b) {
+ // CHECK-NOT: call i8* @__dynamic_cast
+ // CHECK: call void @__cxa_bad_cast() noreturn
+ // CHECK: ret %struct.C* undef
+ return dynamic_cast<C&>(b);
+}
More information about the cfe-commits
mailing list