From 7d99bc37e77157523e3bfbc6c077842b74e6690f Mon Sep 17 00:00:00 2001 From: Anders Carlsson Date: Sun, 10 Apr 2011 20:33:22 +0000 Subject: [PATCH] As a first step towards fixing PR9641, add a CK_DynamicToNull cast kind which represents a dynamic cast where we know that the result is always null. For example: struct A { virtual ~A(); }; struct B final : A { }; struct C { }; bool f(B* b) { return dynamic_cast(b); } git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@129256 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/AST/Expr.h | 1 + include/clang/AST/OperationKinds.h | 4 ++++ lib/AST/Expr.cpp | 2 ++ lib/AST/ExprConstant.cpp | 2 ++ lib/CodeGen/CGExpr.cpp | 3 ++- lib/CodeGen/CGExprAgg.cpp | 5 ++++- lib/CodeGen/CGExprConstant.cpp | 1 + lib/CodeGen/CGExprScalar.cpp | 3 ++- lib/Sema/SemaCXXCast.cpp | 8 ++++++++ lib/StaticAnalyzer/Core/ExprEngine.cpp | 1 + 10 files changed, 27 insertions(+), 3 deletions(-) diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h index 110c4a7323..4ef29642d1 100644 --- a/include/clang/AST/Expr.h +++ b/include/clang/AST/Expr.h @@ -2183,6 +2183,7 @@ private: // These should not have an inheritance path. case CK_BitCast: case CK_Dynamic: + case CK_DynamicToNull: case CK_ToUnion: case CK_ArrayToPointerDecay: case CK_FunctionToPointerDecay: diff --git a/include/clang/AST/OperationKinds.h b/include/clang/AST/OperationKinds.h index ab9d97dbb7..6e16d2196a 100644 --- a/include/clang/AST/OperationKinds.h +++ b/include/clang/AST/OperationKinds.h @@ -82,6 +82,10 @@ enum CastKind { /// CK_Dynamic - A C++ dynamic_cast. CK_Dynamic, + /// CK_DynamicToNull - A C++ dynamic_cast that can be proven to + /// always yield a null result. + CK_DynamicToNull, + /// CK_ToUnion - The GCC cast-to-union extension. /// int -> union { int x; float y; } /// float -> union { int x; float y; } diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index 28f42124f9..227d6569dd 100644 --- a/lib/AST/Expr.cpp +++ b/lib/AST/Expr.cpp @@ -987,6 +987,8 @@ const char *CastExpr::getCastKindName() const { return "UncheckedDerivedToBase"; case CK_Dynamic: return "Dynamic"; + case CK_DynamicToNull: + return "DynamicToNull"; case CK_ToUnion: return "ToUnion"; case CK_ArrayToPointerDecay: diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp index e0f9958298..aa8d91a6d6 100644 --- a/lib/AST/ExprConstant.cpp +++ b/lib/AST/ExprConstant.cpp @@ -1768,6 +1768,7 @@ bool IntExprEvaluator::VisitCastExpr(CastExpr *E) { case CK_DerivedToBase: case CK_UncheckedDerivedToBase: case CK_Dynamic: + case CK_DynamicToNull: case CK_ToUnion: case CK_ArrayToPointerDecay: case CK_FunctionToPointerDecay: @@ -2315,6 +2316,7 @@ bool ComplexExprEvaluator::VisitCastExpr(CastExpr *E) { case CK_DerivedToBase: case CK_UncheckedDerivedToBase: case CK_Dynamic: + case CK_DynamicToNull: case CK_ToUnion: case CK_ArrayToPointerDecay: case CK_FunctionToPointerDecay: diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp index a35f81ca20..ad51316a1f 100644 --- a/lib/CodeGen/CGExpr.cpp +++ b/lib/CodeGen/CGExpr.cpp @@ -1867,7 +1867,8 @@ LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) { return MakeAddrLValue(V, E->getType()); } - case CK_Dynamic: { + case CK_Dynamic: + case CK_DynamicToNull: { LValue LV = EmitLValue(E->getSubExpr()); llvm::Value *V = LV.getAddress(); const CXXDynamicCastExpr *DCE = cast(E); diff --git a/lib/CodeGen/CGExprAgg.cpp b/lib/CodeGen/CGExprAgg.cpp index 75e3a7879d..5e1ac3cbac 100644 --- a/lib/CodeGen/CGExprAgg.cpp +++ b/lib/CodeGen/CGExprAgg.cpp @@ -255,7 +255,10 @@ void AggExprEmitter::VisitCastExpr(CastExpr *E) { } switch (E->getCastKind()) { - case CK_Dynamic: { + case CK_Dynamic: + case CK_DynamicToNull: { + + // FIXME: Actually handle DynamicToNull here. assert(isa(E) && "CK_Dynamic without a dynamic_cast?"); LValue LV = CGF.EmitCheckedLValue(E->getSubExpr()); // FIXME: Do we also need to handle property references here? diff --git a/lib/CodeGen/CGExprConstant.cpp b/lib/CodeGen/CGExprConstant.cpp index 822a999b96..578a37f0fc 100644 --- a/lib/CodeGen/CGExprConstant.cpp +++ b/lib/CodeGen/CGExprConstant.cpp @@ -552,6 +552,7 @@ public: case CK_GetObjCProperty: case CK_ToVoid: case CK_Dynamic: + case CK_DynamicToNull: case CK_ResolveUnknownAnyType: return 0; diff --git a/lib/CodeGen/CGExprScalar.cpp b/lib/CodeGen/CGExprScalar.cpp index 65aa46fff0..322b6e0c49 100644 --- a/lib/CodeGen/CGExprScalar.cpp +++ b/lib/CodeGen/CGExprScalar.cpp @@ -1053,7 +1053,8 @@ Value *ScalarExprEmitter::EmitCastExpr(CastExpr *CE) { CE->path_begin(), CE->path_end(), ShouldNullCheckClassCastValue(CE)); } - case CK_Dynamic: { + case CK_Dynamic: + case CK_DynamicToNull: { Value *V = Visit(const_cast(E)); const CXXDynamicCastExpr *DCE = cast(CE); return CGF.EmitDynamicCast(V, DCE); diff --git a/lib/Sema/SemaCXXCast.cpp b/lib/Sema/SemaCXXCast.cpp index 31a772a5d8..52a13ef5b2 100644 --- a/lib/Sema/SemaCXXCast.cpp +++ b/lib/Sema/SemaCXXCast.cpp @@ -522,6 +522,14 @@ CheckDynamicCast(Sema &Self, ExprResult &SrcExpr, QualType DestType, return; } + // If the source class is marked 'final', and the destination class does not + // derive from the source class, then we know that the result is always null. + if (SrcRecord->getDecl()->hasAttr() && + !Self.IsDerivedFrom(DestPointee, SrcPointee)) { + Kind = CK_DynamicToNull; + return; + } + // C++ 5.2.7p5 // Upcasts are resolved statically. if (DestRecord && Self.IsDerivedFrom(SrcPointee, DestPointee)) { diff --git a/lib/StaticAnalyzer/Core/ExprEngine.cpp b/lib/StaticAnalyzer/Core/ExprEngine.cpp index 0a7f1e93af..6a7637097b 100644 --- a/lib/StaticAnalyzer/Core/ExprEngine.cpp +++ b/lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -2178,6 +2178,7 @@ void ExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex, // Various C++ casts that are not handled yet. case CK_ResolveUnknownAnyType: case CK_Dynamic: + case CK_DynamicToNull: case CK_ToUnion: case CK_BaseToDerived: case CK_NullToMemberPointer: -- 2.40.0