diff options
author | dim <dim@FreeBSD.org> | 2013-04-08 18:45:10 +0000 |
---|---|---|
committer | dim <dim@FreeBSD.org> | 2013-04-08 18:45:10 +0000 |
commit | c72c57c9e9b69944e3e009cd5e209634839581d3 (patch) | |
tree | 4fc2f184c499d106f29a386c452b49e5197bf63d /lib/StaticAnalyzer/Core/Store.cpp | |
parent | 5b20025c30d23d521e12c1f33ec8fa6b821952cd (diff) | |
download | FreeBSD-src-c72c57c9e9b69944e3e009cd5e209634839581d3.zip FreeBSD-src-c72c57c9e9b69944e3e009cd5e209634839581d3.tar.gz |
Vendor import of clang trunk r178860:
http://llvm.org/svn/llvm-project/cfe/trunk@178860
Diffstat (limited to 'lib/StaticAnalyzer/Core/Store.cpp')
-rw-r--r-- | lib/StaticAnalyzer/Core/Store.cpp | 66 |
1 files changed, 48 insertions, 18 deletions
diff --git a/lib/StaticAnalyzer/Core/Store.cpp b/lib/StaticAnalyzer/Core/Store.cpp index 939ae54..a0c24fe 100644 --- a/lib/StaticAnalyzer/Core/Store.cpp +++ b/lib/StaticAnalyzer/Core/Store.cpp @@ -12,11 +12,11 @@ //===----------------------------------------------------------------------===// #include "clang/StaticAnalyzer/Core/PathSensitive/Store.h" -#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h" -#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h" -#include "clang/AST/CharUnits.h" #include "clang/AST/CXXInheritance.h" +#include "clang/AST/CharUnits.h" #include "clang/AST/DeclObjC.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h" using namespace clang; using namespace ento; @@ -223,13 +223,38 @@ const MemRegion *StoreManager::castRegion(const MemRegion *R, QualType CastToTy) llvm_unreachable("unreachable"); } +static bool regionMatchesCXXRecordType(SVal V, QualType Ty) { + const MemRegion *MR = V.getAsRegion(); + if (!MR) + return true; + + const TypedValueRegion *TVR = dyn_cast<TypedValueRegion>(MR); + if (!TVR) + return true; + + const CXXRecordDecl *RD = TVR->getValueType()->getAsCXXRecordDecl(); + if (!RD) + return true; + + const CXXRecordDecl *Expected = Ty->getPointeeCXXRecordDecl(); + if (!Expected) + Expected = Ty->getAsCXXRecordDecl(); + + return Expected->getCanonicalDecl() == RD->getCanonicalDecl(); +} + SVal StoreManager::evalDerivedToBase(SVal Derived, const CastExpr *Cast) { + // Sanity check to avoid doing the wrong thing in the face of + // reinterpret_cast. + if (!regionMatchesCXXRecordType(Derived, Cast->getSubExpr()->getType())) + return UnknownVal(); + // Walk through the cast path to create nested CXXBaseRegions. SVal Result = Derived; for (CastExpr::path_const_iterator I = Cast->path_begin(), E = Cast->path_end(); I != E; ++I) { - Result = evalDerivedToBase(Result, (*I)->getType()); + Result = evalDerivedToBase(Result, (*I)->getType(), (*I)->isVirtual()); } return Result; } @@ -239,13 +264,16 @@ SVal StoreManager::evalDerivedToBase(SVal Derived, const CXXBasePath &Path) { SVal Result = Derived; for (CXXBasePath::const_iterator I = Path.begin(), E = Path.end(); I != E; ++I) { - Result = evalDerivedToBase(Result, I->Base->getType()); + Result = evalDerivedToBase(Result, I->Base->getType(), + I->Base->isVirtual()); } return Result; } -SVal StoreManager::evalDerivedToBase(SVal Derived, QualType BaseType) { - loc::MemRegionVal *DerivedRegVal = dyn_cast<loc::MemRegionVal>(&Derived); +SVal StoreManager::evalDerivedToBase(SVal Derived, QualType BaseType, + bool IsVirtual) { + Optional<loc::MemRegionVal> DerivedRegVal = + Derived.getAs<loc::MemRegionVal>(); if (!DerivedRegVal) return Derived; @@ -255,7 +283,8 @@ SVal StoreManager::evalDerivedToBase(SVal Derived, QualType BaseType) { assert(BaseDecl && "not a C++ object?"); const MemRegion *BaseReg = - MRMgr.getCXXBaseObjectRegion(BaseDecl, DerivedRegVal->getRegion()); + MRMgr.getCXXBaseObjectRegion(BaseDecl, DerivedRegVal->getRegion(), + IsVirtual); return loc::MemRegionVal(BaseReg); } @@ -264,7 +293,7 @@ SVal StoreManager::evalDynamicCast(SVal Base, QualType DerivedType, bool &Failed) { Failed = false; - loc::MemRegionVal *BaseRegVal = dyn_cast<loc::MemRegionVal>(&Base); + Optional<loc::MemRegionVal> BaseRegVal = Base.getAs<loc::MemRegionVal>(); if (!BaseRegVal) return UnknownVal(); const MemRegion *BaseRegion = BaseRegVal->stripCasts(/*StripBases=*/false); @@ -348,12 +377,12 @@ SVal StoreManager::getLValueFieldOrIvar(const Decl *D, SVal Base) { if (Base.isUnknownOrUndef()) return Base; - Loc BaseL = cast<Loc>(Base); + Loc BaseL = Base.castAs<Loc>(); const MemRegion* BaseR = 0; switch (BaseL.getSubKind()) { case loc::MemRegionKind: - BaseR = cast<loc::MemRegionVal>(BaseL).getRegion(); + BaseR = BaseL.castAs<loc::MemRegionVal>().getRegion(); break; case loc::GotoLabelKind: @@ -390,16 +419,16 @@ SVal StoreManager::getLValueElement(QualType elementType, NonLoc Offset, // FIXME: For absolute pointer addresses, we just return that value back as // well, although in reality we should return the offset added to that // value. - if (Base.isUnknownOrUndef() || isa<loc::ConcreteInt>(Base)) + if (Base.isUnknownOrUndef() || Base.getAs<loc::ConcreteInt>()) return Base; - const MemRegion* BaseRegion = cast<loc::MemRegionVal>(Base).getRegion(); + const MemRegion* BaseRegion = Base.castAs<loc::MemRegionVal>().getRegion(); // Pointer of any type can be cast and used as array base. const ElementRegion *ElemR = dyn_cast<ElementRegion>(BaseRegion); // Convert the offset to the appropriate size and signedness. - Offset = cast<NonLoc>(svalBuilder.convertToArrayIndex(Offset)); + Offset = svalBuilder.convertToArrayIndex(Offset).castAs<NonLoc>(); if (!ElemR) { // @@ -417,15 +446,16 @@ SVal StoreManager::getLValueElement(QualType elementType, NonLoc Offset, SVal BaseIdx = ElemR->getIndex(); - if (!isa<nonloc::ConcreteInt>(BaseIdx)) + if (!BaseIdx.getAs<nonloc::ConcreteInt>()) return UnknownVal(); - const llvm::APSInt& BaseIdxI = cast<nonloc::ConcreteInt>(BaseIdx).getValue(); + const llvm::APSInt &BaseIdxI = + BaseIdx.castAs<nonloc::ConcreteInt>().getValue(); // Only allow non-integer offsets if the base region has no offset itself. // FIXME: This is a somewhat arbitrary restriction. We should be using // SValBuilder here to add the two offsets without checking their types. - if (!isa<nonloc::ConcreteInt>(Offset)) { + if (!Offset.getAs<nonloc::ConcreteInt>()) { if (isa<ElementRegion>(BaseRegion->StripCasts())) return UnknownVal(); @@ -434,7 +464,7 @@ SVal StoreManager::getLValueElement(QualType elementType, NonLoc Offset, Ctx)); } - const llvm::APSInt& OffI = cast<nonloc::ConcreteInt>(Offset).getValue(); + const llvm::APSInt& OffI = Offset.castAs<nonloc::ConcreteInt>().getValue(); assert(BaseIdxI.isSigned()); // Compute the new index. |