[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