aboutsummaryrefslogtreecommitdiff
path: root/lib/CodeGen/CGExprCXX.cpp
diff options
context:
space:
mode:
authorAnders Carlsson <andersca@mac.com>2011-04-11 01:45:29 +0000
committerAnders Carlsson <andersca@mac.com>2011-04-11 01:45:29 +0000
commit3ddcdd5d6c88902d24baa9e6bb240a3da88e68d4 (patch)
treecf1439a3f611b669f6b1de0f17726715fb99b3de /lib/CodeGen/CGExprCXX.cpp
parent0fee330f5754ca4b248e5bb7363e834668aff06d (diff)
When we know that a dynamic_cast always returns null, we can make
CodeGenFunction::EmitDynamicCast always return null or throw a bad_cast exception. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@129264 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/CGExprCXX.cpp')
-rw-r--r--lib/CodeGen/CGExprCXX.cpp42
1 files changed, 32 insertions, 10 deletions
diff --git a/lib/CodeGen/CGExprCXX.cpp b/lib/CodeGen/CGExprCXX.cpp
index ff7b7112ca..a3d3f439b6 100644
--- a/lib/CodeGen/CGExprCXX.cpp
+++ b/lib/CodeGen/CGExprCXX.cpp
@@ -1416,6 +1416,18 @@ static llvm::Constant *getBadCastFn(CodeGenFunction &CGF) {
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 @@ EmitDynamicCastCall(CodeGenFunction &CGF, llvm::Value *Value,
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.