forked from OSchip/llvm-project
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:
parent
ad000d8f16
commit
0d87e0c65b
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue