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
diff --git a/clang/lib/StaticAnalyzer/Checkers/ExprEngine.cpp b/clang/lib/StaticAnalyzer/Checkers/ExprEngine.cpp
index 1577cbe..874e7a3 100644
--- a/clang/lib/StaticAnalyzer/Checkers/ExprEngine.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/ExprEngine.cpp
@@ -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,
diff --git a/clang/lib/StaticAnalyzer/RegionStore.cpp b/clang/lib/StaticAnalyzer/RegionStore.cpp
index e47a77e..58cec30 100644
--- a/clang/lib/StaticAnalyzer/RegionStore.cpp
+++ b/clang/lib/StaticAnalyzer/RegionStore.cpp
@@ -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;