[Analyser] Remove unnecessary recursive visits for ExprWithCleanups and
MaterializeTemporaryExpr.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@152730 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/StaticAnalyzer/Core/AggExprVisitor.cpp b/lib/StaticAnalyzer/Core/AggExprVisitor.cpp
index 0936d61..53441f0 100644
--- a/lib/StaticAnalyzer/Core/AggExprVisitor.cpp
+++ b/lib/StaticAnalyzer/Core/AggExprVisitor.cpp
@@ -50,6 +50,8 @@
   case CK_NoOp:
   case CK_ConstructorConversion:
   case CK_UserDefinedConversion:
+    // FIXME: The CFG is fully linearised, so a recursive visit is probably not
+    // needed anymore.
     Visit(E->getSubExpr());
     break;
   }
@@ -60,6 +62,8 @@
 }
 
 void AggExprVisitor::VisitCXXMemberCallExpr(CXXMemberCallExpr *E) {
+  // FIXME: The CFG is fully linearised, so a recursive visit is probably not
+  // needed anymore.
   Eng.Visit(E, Pred, DstSet);
 }
 
diff --git a/lib/StaticAnalyzer/Core/ExprEngine.cpp b/lib/StaticAnalyzer/Core/ExprEngine.cpp
index 3d1d6ea..fa52bee 100644
--- a/lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ b/lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -363,29 +363,22 @@
   SVal thisVal = Pred->getState()->getSVal(thisReg);
 
   if (BMI->isAnyMemberInitializer()) {
-    ExplodedNodeSet AfterEval;
-
     // Evaluate the initializer.
-    Visit(BMI->getInit(), Pred, AfterEval);
 
-    StmtNodeBuilder Bldr(AfterEval, Dst, *currentBuilderContext);
-    for (ExplodedNodeSet::iterator I = AfterEval.begin(),
-                                   E = AfterEval.end(); I != E; ++I){
-      ExplodedNode *P = *I;
-      ProgramStateRef state = P->getState();
+    StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext);
+    ProgramStateRef state = Pred->getState();
 
-      const FieldDecl *FD = BMI->getAnyMember();
+    const FieldDecl *FD = BMI->getAnyMember();
 
-      SVal FieldLoc = state->getLValue(FD, thisVal);
-      SVal InitVal = state->getSVal(BMI->getInit(), Pred->getLocationContext());
-      state = state->bindLoc(FieldLoc, InitVal);
+    SVal FieldLoc = state->getLValue(FD, thisVal);
+    SVal InitVal = state->getSVal(BMI->getInit(), Pred->getLocationContext());
+    state = state->bindLoc(FieldLoc, InitVal);
 
-      // Use a custom node building process.
-      PostInitializer PP(BMI, stackFrame);
-      // Builder automatically add the generated node to the deferred set,
-      // which are processed in the builder's dtor.
-      Bldr.generateNode(PP, P, state);
-    }
+    // Use a custom node building process.
+    PostInitializer PP(BMI, stackFrame);
+    // Builder automatically add the generated node to the deferred set,
+    // which are processed in the builder's dtor.
+    Bldr.generateNode(PP, Pred, state);
   } else {
     assert(BMI->isBaseInitializer());
 
@@ -574,9 +567,7 @@
     }
       
     case Stmt::ExprWithCleanupsClass:
-      Bldr.takeNodes(Pred);
-      Visit(cast<ExprWithCleanups>(S)->getSubExpr(), Pred, Dst);
-      Bldr.addNodes(Dst);
+      // Handled due to fully linearised CFG.
       break;
 
     // Cases not handled yet; but will handle some day.
@@ -835,10 +826,10 @@
       Bldr.takeNodes(Pred);
       const MaterializeTemporaryExpr *Materialize
                                             = cast<MaterializeTemporaryExpr>(S);
-      if (!Materialize->getType()->isRecordType())
-        CreateCXXTemporaryObject(Materialize, Pred, Dst);
+      if (Materialize->getType()->isRecordType())
+        Dst.Add(Pred);
       else
-        Visit(Materialize->GetTemporaryExpr(), Pred, Dst);
+        CreateCXXTemporaryObject(Materialize, Pred, Dst);
       Bldr.addNodes(Dst);
       break;
     }
diff --git a/test/Analysis/nullptr.cpp b/test/Analysis/nullptr.cpp
index 3f2bac1..c0fed87 100644
--- a/test/Analysis/nullptr.cpp
+++ b/test/Analysis/nullptr.cpp
@@ -59,3 +59,25 @@
       :"0"(*b) // expected-warning{{Dereference of null pointer}}
       );
 }
+
+int exprWithCleanups() {
+  struct S {
+    S(int a):a(a){}
+    ~S() {}
+
+    int a;
+  };
+
+  int *x = 0;
+  return S(*x).a; // expected-warning{{Dereference of null pointer}}
+}
+
+int materializeTempExpr() {
+  int *n = 0;
+  struct S {
+    int a;
+    S(int i): a(i) {}
+  };
+  const S &s = S(*n); // expected-warning{{Dereference of null pointer}}
+  return s.a;
+}