From c72c57c9e9b69944e3e009cd5e209634839581d3 Mon Sep 17 00:00:00 2001 From: dim Date: Mon, 8 Apr 2013 18:45:10 +0000 Subject: Vendor import of clang trunk r178860: http://llvm.org/svn/llvm-project/cfe/trunk@178860 --- lib/StaticAnalyzer/Core/Store.cpp | 66 ++++++++++++++++++++++++++++----------- 1 file changed, 48 insertions(+), 18 deletions(-) (limited to 'lib/StaticAnalyzer/Core/Store.cpp') 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(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(&Derived); +SVal StoreManager::evalDerivedToBase(SVal Derived, QualType BaseType, + bool IsVirtual) { + Optional DerivedRegVal = + Derived.getAs(); 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(&Base); + Optional BaseRegVal = Base.getAs(); 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(Base); + Loc BaseL = Base.castAs(); const MemRegion* BaseR = 0; switch (BaseL.getSubKind()) { case loc::MemRegionKind: - BaseR = cast(BaseL).getRegion(); + BaseR = BaseL.castAs().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(Base)) + if (Base.isUnknownOrUndef() || Base.getAs()) return Base; - const MemRegion* BaseRegion = cast(Base).getRegion(); + const MemRegion* BaseRegion = Base.castAs().getRegion(); // Pointer of any type can be cast and used as array base. const ElementRegion *ElemR = dyn_cast(BaseRegion); // Convert the offset to the appropriate size and signedness. - Offset = cast(svalBuilder.convertToArrayIndex(Offset)); + Offset = svalBuilder.convertToArrayIndex(Offset).castAs(); if (!ElemR) { // @@ -417,15 +446,16 @@ SVal StoreManager::getLValueElement(QualType elementType, NonLoc Offset, SVal BaseIdx = ElemR->getIndex(); - if (!isa(BaseIdx)) + if (!BaseIdx.getAs()) return UnknownVal(); - const llvm::APSInt& BaseIdxI = cast(BaseIdx).getValue(); + const llvm::APSInt &BaseIdxI = + BaseIdx.castAs().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(Offset)) { + if (!Offset.getAs()) { if (isa(BaseRegion->StripCasts())) return UnknownVal(); @@ -434,7 +464,7 @@ SVal StoreManager::getLValueElement(QualType elementType, NonLoc Offset, Ctx)); } - const llvm::APSInt& OffI = cast(Offset).getValue(); + const llvm::APSInt& OffI = Offset.castAs().getValue(); assert(BaseIdxI.isSigned()); // Compute the new index. -- cgit v1.1