diff options
| author | Zhongxing Xu <xuzhongxing@gmail.com> | 2011-01-13 12:30:12 +0000 | 
|---|---|---|
| committer | Zhongxing Xu <xuzhongxing@gmail.com> | 2011-01-13 12:30:12 +0000 | 
| commit | 0d87e0c65b9a1c35c7dd3d6bc3c247da079ec0af (patch) | |
| tree | 7d8b2ce315473dd7c4f5881662c9c63bfb20f94a | |
| parent | ad000d8f16b5ca8ff2460dd60d657bfa55425855 (diff) | |
| download | bcm5719-llvm-0d87e0c65b9a1c35c7dd3d6bc3c247da079ec0af.tar.gz bcm5719-llvm-0d87e0c65b9a1c35c7dd3d6bc3c247da079ec0af.zip | |
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
| -rw-r--r-- | clang/include/clang/StaticAnalyzer/PathSensitive/MemRegion.h | 10 | ||||
| -rw-r--r-- | clang/lib/StaticAnalyzer/Checkers/ExprEngine.cpp | 34 | ||||
| -rw-r--r-- | clang/lib/StaticAnalyzer/RegionStore.cpp | 17 | ||||
| -rw-r--r-- | clang/test/Analysis/base-init.cpp | 30 | 
4 files changed, 79 insertions, 12 deletions
| diff --git a/clang/include/clang/StaticAnalyzer/PathSensitive/MemRegion.h b/clang/include/clang/StaticAnalyzer/PathSensitive/MemRegion.h index 6ba3dc68fcf..6e5790456c1 100644 --- a/clang/include/clang/StaticAnalyzer/PathSensitive/MemRegion.h +++ b/clang/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/clang/lib/StaticAnalyzer/Checkers/ExprEngine.cpp b/clang/lib/StaticAnalyzer/Checkers/ExprEngine.cpp index 1577cbee315..874e7a30642 100644 --- a/clang/lib/StaticAnalyzer/Checkers/ExprEngine.cpp +++ b/clang/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/clang/lib/StaticAnalyzer/RegionStore.cpp b/clang/lib/StaticAnalyzer/RegionStore.cpp index e47a77e6fc8..58cec303132 100644 --- a/clang/lib/StaticAnalyzer/RegionStore.cpp +++ b/clang/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/clang/test/Analysis/base-init.cpp b/clang/test/Analysis/base-init.cpp new file mode 100644 index 00000000000..e82f443ced9 --- /dev/null +++ b/clang/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 +  } +} | 

