diff options
author | Anders Carlsson <andersca@mac.com> | 2011-04-11 01:43:55 +0000 |
---|---|---|
committer | Anders Carlsson <andersca@mac.com> | 2011-04-11 01:43:55 +0000 |
commit | 267c0c930e29234d291a6a1e4896b76489529548 (patch) | |
tree | 7d0ccd319424cbca2596c805ad67628486a8586b /clang/lib/AST/ExprCXX.cpp | |
parent | 882d790f724750c1c8911894687537fc5f7b5e95 (diff) | |
download | bcm5719-llvm-267c0c930e29234d291a6a1e4896b76489529548.tar.gz bcm5719-llvm-267c0c930e29234d291a6a1e4896b76489529548.zip |
Add CXXDynamicCastExpr::isAlwaysNull() which will be replacing the cast kind I added.
llvm-svn: 129263
Diffstat (limited to 'clang/lib/AST/ExprCXX.cpp')
-rw-r--r-- | clang/lib/AST/ExprCXX.cpp | 30 |
1 files changed, 30 insertions, 0 deletions
diff --git a/clang/lib/AST/ExprCXX.cpp b/clang/lib/AST/ExprCXX.cpp index 526c484677b..692c2c37607 100644 --- a/clang/lib/AST/ExprCXX.cpp +++ b/clang/lib/AST/ExprCXX.cpp @@ -482,6 +482,36 @@ CXXDynamicCastExpr *CXXDynamicCastExpr::CreateEmpty(ASTContext &C, return new (Buffer) CXXDynamicCastExpr(EmptyShell(), PathSize); } +/// isAlwaysNull - Return whether the result of the dynamic_cast is proven +/// to always be null. For example: +/// +/// struct A { }; +/// struct B final : A { }; +/// struct C { }; +/// +/// C *f(B* b) { return dynamic_cast<C*>(b); } +bool CXXDynamicCastExpr::isAlwaysNull() const +{ + QualType SrcType = getSubExpr()->getType(); + QualType DestType = getType(); + + if (const PointerType *SrcPTy = SrcType->getAs<PointerType>()) { + SrcType = SrcPTy->getPointeeType(); + DestType = DestType->castAs<PointerType>()->getPointeeType(); + } + + const CXXRecordDecl *SrcRD = + cast<CXXRecordDecl>(SrcType->castAs<RecordType>()->getDecl()); + + if (!SrcRD->hasAttr<FinalAttr>()) + return false; + + const CXXRecordDecl *DestRD = + cast<CXXRecordDecl>(DestType->castAs<RecordType>()->getDecl()); + + return !DestRD->isDerivedFrom(SrcRD); +} + CXXReinterpretCastExpr * CXXReinterpretCastExpr::Create(ASTContext &C, QualType T, ExprValueKind VK, CastKind K, Expr *Op, |