aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZhongxing Xu <xuzhongxing@gmail.com>2011-01-13 12:30:12 +0000
committerZhongxing Xu <xuzhongxing@gmail.com>2011-01-13 12:30:12 +0000
commitd074441e027471a914cbb909a7aad1d43224950f (patch)
tree00b080ed9a0662effebaaa7d09294534403900cf
parentbda1efd0daf6fca9f515c6ce38d1ed71a3cca5b7 (diff)
Support inlining base initializers. We still haven't got it completely right,
since the bindings are purged after they are set up. Need to investigate RemoveDeadBindings algorithm. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@123374 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang/StaticAnalyzer/PathSensitive/MemRegion.h10
-rw-r--r--lib/StaticAnalyzer/Checkers/ExprEngine.cpp34
-rw-r--r--lib/StaticAnalyzer/RegionStore.cpp17
-rw-r--r--test/Analysis/base-init.cpp30
4 files changed, 79 insertions, 12 deletions
diff --git a/include/clang/StaticAnalyzer/PathSensitive/MemRegion.h b/include/clang/StaticAnalyzer/PathSensitive/MemRegion.h
index 6ba3dc68fc..6e5790456c 100644
--- a/include/clang/StaticAnalyzer/PathSensitive/MemRegion.h
+++ b/include/clang/StaticAnalyzer/PathSensitive/MemRegion.h
@@ -872,6 +872,8 @@ class CXXBaseObjectRegion : public TypedRegion {
const CXXRecordDecl *decl, const MemRegion *sReg);
public:
+ const CXXRecordDecl *getDecl() const { return decl; }
+
QualType getValueType() const;
void dumpToStream(llvm::raw_ostream& os) const;
@@ -1012,6 +1014,14 @@ public:
const CXXBaseObjectRegion *getCXXBaseObjectRegion(const CXXRecordDecl *decl,
const MemRegion *superRegion);
+ /// Create a CXXBaseObjectRegion with the same CXXRecordDecl but a different
+ /// super region.
+ const CXXBaseObjectRegion *
+ getCXXBaseObjectRegionWithSuper(const CXXBaseObjectRegion *baseReg,
+ const MemRegion *superRegion) {
+ return getCXXBaseObjectRegion(baseReg->getDecl(), superRegion);
+ }
+
const FunctionTextRegion *getFunctionTextRegion(const FunctionDecl *FD);
const BlockTextRegion *getBlockTextRegion(const BlockDecl *BD,
CanQualType locTy,
diff --git a/lib/StaticAnalyzer/Checkers/ExprEngine.cpp b/lib/StaticAnalyzer/Checkers/ExprEngine.cpp
index 1577cbee31..874e7a3064 100644
--- a/lib/StaticAnalyzer/Checkers/ExprEngine.cpp
+++ b/lib/StaticAnalyzer/Checkers/ExprEngine.cpp
@@ -643,36 +643,52 @@ void ExprEngine::ProcessInitializer(const CFGInitializer Init,
// We don't set EntryNode and currentStmt. And we don't clean up state.
const CXXCtorInitializer *BMI = Init.getInitializer();
- ExplodedNode *Pred = builder.getPredecessor();
- const LocationContext *LC = Pred->getLocationContext();
+ ExplodedNode *pred = builder.getPredecessor();
+
+ const StackFrameContext *stackFrame = cast<StackFrameContext>(pred->getLocationContext());
+ const CXXConstructorDecl *decl = cast<CXXConstructorDecl>(stackFrame->getDecl());
+ const CXXThisRegion *thisReg = getCXXThisRegion(decl, stackFrame);
+
+ SVal thisVal = pred->getState()->getSVal(thisReg);
if (BMI->isAnyMemberInitializer()) {
ExplodedNodeSet Dst;
// Evaluate the initializer.
- Visit(BMI->getInit(), Pred, Dst);
+ Visit(BMI->getInit(), pred, Dst);
for (ExplodedNodeSet::iterator I = Dst.begin(), E = Dst.end(); I != E; ++I){
ExplodedNode *Pred = *I;
const GRState *state = Pred->getState();
const FieldDecl *FD = BMI->getAnyMember();
- const RecordDecl *RD = FD->getParent();
- const CXXThisRegion *ThisR = getCXXThisRegion(cast<CXXRecordDecl>(RD),
- cast<StackFrameContext>(LC));
- SVal ThisV = state->getSVal(ThisR);
- SVal FieldLoc = state->getLValue(FD, ThisV);
+ SVal FieldLoc = state->getLValue(FD, thisVal);
SVal InitVal = state->getSVal(BMI->getInit());
state = state->bindLoc(FieldLoc, InitVal);
// Use a custom node building process.
- PostInitializer PP(BMI, LC);
+ PostInitializer PP(BMI, stackFrame);
// Builder automatically add the generated node to the deferred set,
// which are processed in the builder's dtor.
builder.generateNode(PP, state, Pred);
}
+ return;
}
+
+ assert(BMI->isBaseInitializer());
+
+ // Get the base class declaration.
+ const CXXConstructExpr *ctorExpr = cast<CXXConstructExpr>(BMI->getInit());
+
+ // Create the base object region.
+ SVal baseVal =
+ getStoreManager().evalDerivedToBase(thisVal, ctorExpr->getType());
+ const MemRegion *baseReg = baseVal.getAsRegion();
+ assert(baseReg);
+ Builder = &builder;
+ ExplodedNodeSet dst;
+ VisitCXXConstructExpr(ctorExpr, baseReg, pred, dst);
}
void ExprEngine::ProcessImplicitDtor(const CFGImplicitDtor D,
diff --git a/lib/StaticAnalyzer/RegionStore.cpp b/lib/StaticAnalyzer/RegionStore.cpp
index e47a77e6fc..58cec30313 100644
--- a/lib/StaticAnalyzer/RegionStore.cpp
+++ b/lib/StaticAnalyzer/RegionStore.cpp
@@ -822,7 +822,8 @@ SVal RegionStoreManager::evalDerivedToBase(SVal derived, QualType baseType) {
return derived;
const MemRegion *baseReg =
- MRMgr.getCXXBaseObjectRegion(baseDecl, derivedRegVal->getRegion());
+ MRMgr.getCXXBaseObjectRegion(baseDecl, derivedRegVal->getRegion());
+
return loc::MemRegionVal(baseReg);
}
//===----------------------------------------------------------------------===//
@@ -1105,6 +1106,17 @@ RegionStoreManager::GetLazyBinding(RegionBindings B, const MemRegion *R) {
return std::make_pair(X.first,
MRMgr.getFieldRegionWithSuper(FR, X.second));
}
+ // C++ base object region is another kind of region that we should blast
+ // through to look for lazy compound value. It is like a field region.
+ else if (const CXXBaseObjectRegion *baseReg =
+ dyn_cast<CXXBaseObjectRegion>(R)) {
+ const std::pair<Store, const MemRegion *> &X =
+ GetLazyBinding(B, baseReg->getSuperRegion());
+
+ if (X.second)
+ return std::make_pair(X.first,
+ MRMgr.getCXXBaseObjectRegionWithSuper(baseReg, X.second));
+ }
// The NULL MemRegion indicates an non-existent lazy binding. A NULL Store is
// possible for a valid lazy binding.
return std::make_pair((Store) 0, (const MemRegion *) 0);
@@ -1572,7 +1584,6 @@ Store RegionStoreManager::BindStruct(Store store, const TypedRegion* R,
Store RegionStoreManager::KillStruct(Store store, const TypedRegion* R,
SVal DefaultVal) {
-
BindingKey key = BindingKey::Make(R, BindingKey::Default);
// The BindingKey may be "invalid" if we cannot handle the region binding
@@ -1582,7 +1593,7 @@ Store RegionStoreManager::KillStruct(Store store, const TypedRegion* R,
// the case of nested symbolic indices, we need to march up the region
// hierarchy untile we reach a region whose binding we can reason about.
const SubRegion *subReg = R;
-
+
while (!key.isValid()) {
if (const SubRegion *tmp = dyn_cast<SubRegion>(subReg->getSuperRegion())) {
subReg = tmp;
diff --git a/test/Analysis/base-init.cpp b/test/Analysis/base-init.cpp
new file mode 100644
index 0000000000..e82f443ced
--- /dev/null
+++ b/test/Analysis/base-init.cpp
@@ -0,0 +1,30 @@
+// RUN: %clang_cc1 -analyze -analyzer-check-objc-mem -analyzer-store region -analyzer-inline-call -cfg-add-initializers -verify -analyzer-no-purge-dead %s
+
+class A {
+ int x;
+public:
+ A();
+ int getx() const {
+ return x;
+ }
+};
+
+A::A() : x(0) {
+}
+
+class B : public A {
+ int y;
+public:
+ B();
+};
+
+B::B() {
+}
+
+void f() {
+ B b;
+ if (b.getx() != 0) {
+ int *p = 0;
+ *p = 0; // no-warning
+ }
+}