summaryrefslogtreecommitdiffstats
path: root/lib/StaticAnalyzer/Core/Store.cpp
diff options
context:
space:
mode:
authordim <dim@FreeBSD.org>2013-04-08 18:45:10 +0000
committerdim <dim@FreeBSD.org>2013-04-08 18:45:10 +0000
commitc72c57c9e9b69944e3e009cd5e209634839581d3 (patch)
tree4fc2f184c499d106f29a386c452b49e5197bf63d /lib/StaticAnalyzer/Core/Store.cpp
parent5b20025c30d23d521e12c1f33ec8fa6b821952cd (diff)
downloadFreeBSD-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.cpp66
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.
OpenPOWER on IntegriCloud