[cfe-commits] r123374 - in /cfe/trunk: include/clang/StaticAnalyzer/PathSensitive/MemRegion.h lib/StaticAnalyzer/Checkers/ExprEngine.cpp lib/StaticAnalyzer/RegionStore.cpp test/Analysis/base-init.cpp

Zhongxing Xu xuzhongxing at gmail.com
Thu Jan 13 04:30:12 PST 2011


Author: zhongxingxu
Date: Thu Jan 13 06:30:12 2011
New Revision: 123374

URL: http://llvm.org/viewvc/llvm-project?rev=123374&view=rev
Log:
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.

Added:
    cfe/trunk/test/Analysis/base-init.cpp
Modified:
    cfe/trunk/include/clang/StaticAnalyzer/PathSensitive/MemRegion.h
    cfe/trunk/lib/StaticAnalyzer/Checkers/ExprEngine.cpp
    cfe/trunk/lib/StaticAnalyzer/RegionStore.cpp

Modified: cfe/trunk/include/clang/StaticAnalyzer/PathSensitive/MemRegion.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/PathSensitive/MemRegion.h?rev=123374&r1=123373&r2=123374&view=diff
==============================================================================
--- cfe/trunk/include/clang/StaticAnalyzer/PathSensitive/MemRegion.h (original)
+++ cfe/trunk/include/clang/StaticAnalyzer/PathSensitive/MemRegion.h Thu Jan 13 06:30:12 2011
@@ -872,6 +872,8 @@
                             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 @@
   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,

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/ExprEngine.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/ExprEngine.cpp?rev=123374&r1=123373&r2=123374&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/ExprEngine.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/ExprEngine.cpp Thu Jan 13 06:30:12 2011
@@ -643,36 +643,52 @@
   // 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,

Modified: cfe/trunk/lib/StaticAnalyzer/RegionStore.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/RegionStore.cpp?rev=123374&r1=123373&r2=123374&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/RegionStore.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/RegionStore.cpp Thu Jan 13 06:30:12 2011
@@ -822,7 +822,8 @@
     return derived;
 
   const MemRegion *baseReg = 
-    MRMgr.getCXXBaseObjectRegion(baseDecl, derivedRegVal->getRegion());
+    MRMgr.getCXXBaseObjectRegion(baseDecl, derivedRegVal->getRegion()); 
+
   return loc::MemRegionVal(baseReg);
 }
 //===----------------------------------------------------------------------===//
@@ -1105,6 +1106,17 @@
       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::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 @@
   // 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;

Added: cfe/trunk/test/Analysis/base-init.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/base-init.cpp?rev=123374&view=auto
==============================================================================
--- cfe/trunk/test/Analysis/base-init.cpp (added)
+++ cfe/trunk/test/Analysis/base-init.cpp Thu Jan 13 06:30:12 2011
@@ -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
+  }
+}





More information about the cfe-commits mailing list