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.

llvm-svn: 123374
This commit is contained in:
Zhongxing Xu 2011-01-13 12:30:12 +00:00
parent ad000d8f16
commit 0d87e0c65b
4 changed files with 79 additions and 12 deletions

View File

@ -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,

View File

@ -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,

View File

@ -823,6 +823,7 @@ SVal RegionStoreManager::evalDerivedToBase(SVal derived, QualType baseType) {
const MemRegion *baseReg =
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

View File

@ -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
}
}