[cfe-commits] r162215 - in /cfe/trunk: include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h lib/StaticAnalyzer/Checkers/OSAtomicChecker.cpp lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp lib/StaticAnalyzer/Core/ExprEngine.cpp lib/StaticAnalyzer/Core/ExprEngineC.cpp lib/StaticAnalyzer/Core/ExprEngineObjC.cpp

Jordan Rose jordan_rose at apple.com
Mon Aug 20 11:43:42 PDT 2012


Author: jrose
Date: Mon Aug 20 13:43:42 2012
New Revision: 162215

URL: http://llvm.org/viewvc/llvm-project?rev=162215&view=rev
Log:
[analyzer] Replace boolean IsSink parameters with 'generateSink' methods.

Generating a sink is significantly different behavior from generating a
normal node, and a simple boolean parameter can be rather opaque. Per
offline discussion with Anna, adding new generation methods is the
clearest way to communicate intent.

No functionality change.

Modified:
    cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h
    cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h
    cfe/trunk/lib/StaticAnalyzer/Checkers/OSAtomicChecker.cpp
    cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp
    cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp
    cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineC.cpp
    cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp

Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h?rev=162215&r1=162214&r2=162215&view=diff
==============================================================================
--- cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h (original)
+++ cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h Mon Aug 20 13:43:42 2012
@@ -144,20 +144,15 @@
   /// \brief Generates a new transition in the program state graph
   /// (ExplodedGraph). Uses the default CheckerContext predecessor node.
   ///
-  /// @param State The state of the generated node.
+  /// @param State The state of the generated node. If not specified, the state
+  ///        will not be changed, but the new node will have the checker's tag.
   /// @param Tag The tag is used to uniquely identify the creation site. If no
   ///        tag is specified, a default tag, unique to the given checker,
   ///        will be used. Tags are used to prevent states generated at
   ///        different sites from caching out.
-  ExplodedNode *addTransition(ProgramStateRef State,
+  ExplodedNode *addTransition(ProgramStateRef State = 0,
                               const ProgramPointTag *Tag = 0) {
-    return addTransitionImpl(State, false, 0, Tag);
-  }
-
-  /// \brief Generates a default transition (containing checker tag but no
-  /// checker state changes).
-  ExplodedNode *addTransition() {
-    return addTransition(getState());
+    return addTransitionImpl(State ? State : getState(), false, 0, Tag);
   }
 
   /// \brief Generates a new transition with the given predecessor.
@@ -170,16 +165,17 @@
   /// @param IsSink Mark the new node as sink, which will stop exploration of
   ///               the given path.
   ExplodedNode *addTransition(ProgramStateRef State,
-                             ExplodedNode *Pred,
-                             const ProgramPointTag *Tag = 0,
-                             bool IsSink = false) {
-    return addTransitionImpl(State, IsSink, Pred, Tag);
+                              ExplodedNode *Pred,
+                              const ProgramPointTag *Tag = 0) {
+    return addTransitionImpl(State, false, Pred, Tag);
   }
 
-  /// \brief Generate a sink node. Generating sink stops exploration of the
+  /// \brief Generate a sink node. Generating a sink stops exploration of the
   /// given path.
-  ExplodedNode *generateSink(ProgramStateRef state = 0) {
-    return addTransitionImpl(state ? state : getState(), true);
+  ExplodedNode *generateSink(ProgramStateRef State = 0,
+                             ExplodedNode *Pred = 0,
+                             const ProgramPointTag *Tag = 0) {
+    return addTransitionImpl(State ? State : getState(), true, Pred, Tag);
   }
 
   /// \brief Emit the diagnostics report.
@@ -226,9 +222,15 @@
       return Pred;
 
     Changed = true;
-    ExplodedNode *node = NB.generateNode(Tag ? Location.withTag(Tag) : Location,
-                                        State,
-                                        P ? P : Pred, MarkAsSink);
+    const ProgramPoint &LocalLoc = (Tag ? Location.withTag(Tag) : Location);
+    if (!P)
+      P = Pred;
+
+    ExplodedNode *node;
+    if (MarkAsSink)
+      node = NB.generateSink(LocalLoc, State, P);
+    else
+      node = NB.generateNode(LocalLoc, State, P);
     return node;
   }
 };

Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h?rev=162215&r1=162214&r2=162215&view=diff
==============================================================================
--- cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h (original)
+++ cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h Mon Aug 20 13:43:42 2012
@@ -265,14 +265,21 @@
   virtual ~NodeBuilder() {}
 
   /// \brief Generates a node in the ExplodedGraph.
+  ExplodedNode *generateNode(const ProgramPoint &PP,
+                             ProgramStateRef State,
+                             ExplodedNode *Pred) {
+    return generateNodeImpl(PP, State, Pred, false);
+  }
+
+  /// \brief Generates a sink in the ExplodedGraph.
   ///
   /// When a node is marked as sink, the exploration from the node is stopped -
-  /// the node becomes the last node on the path.
-  ExplodedNode *generateNode(const ProgramPoint &PP,
+  /// the node becomes the last node on the path and certain kinds of bugs are
+  /// suppressed.
+  ExplodedNode *generateSink(const ProgramPoint &PP,
                              ProgramStateRef State,
-                             ExplodedNode *Pred,
-                             bool MarkAsSink = false) {
-    return generateNodeImpl(PP, State, Pred, MarkAsSink);
+                             ExplodedNode *Pred) {
+    return generateNodeImpl(PP, State, Pred, true);
   }
 
   const ExplodedNodeSet &getResults() {
@@ -317,13 +324,18 @@
   NodeBuilderWithSinks(ExplodedNode *Pred, ExplodedNodeSet &DstSet,
                        const NodeBuilderContext &Ctx, ProgramPoint &L)
     : NodeBuilder(Pred, DstSet, Ctx), Location(L) {}
+
   ExplodedNode *generateNode(ProgramStateRef State,
                              ExplodedNode *Pred,
-                             const ProgramPointTag *Tag = 0,
-                             bool MarkAsSink = false) {
-    ProgramPoint LocalLoc = (Tag ? Location.withTag(Tag): Location);
+                             const ProgramPointTag *Tag = 0) {
+    const ProgramPoint &LocalLoc = (Tag ? Location.withTag(Tag) : Location);
+    return NodeBuilder::generateNode(LocalLoc, State, Pred);
+  }
 
-    ExplodedNode *N = generateNodeImpl(LocalLoc, State, Pred, MarkAsSink);
+  ExplodedNode *generateSink(ProgramStateRef State, ExplodedNode *Pred,
+                             const ProgramPointTag *Tag = 0) {
+    const ProgramPoint &LocalLoc = (Tag ? Location.withTag(Tag) : Location);
+    ExplodedNode *N = NodeBuilder::generateSink(LocalLoc, State, Pred);
     if (N && N->isSink())
       sinksGenerated.push_back(N);
     return N;
@@ -336,7 +348,7 @@
 
 /// \class StmtNodeBuilder
 /// \brief This builder class is useful for generating nodes that resulted from
-/// visiting a statement. The main difference from it's parent NodeBuilder is
+/// visiting a statement. The main difference from its parent NodeBuilder is
 /// that it creates a statement specific ProgramPoint.
 class StmtNodeBuilder: public NodeBuilder {
   NodeBuilder *EnclosingBldr;
@@ -363,22 +375,27 @@
 
   virtual ~StmtNodeBuilder();
 
+  using NodeBuilder::generateNode;
+  using NodeBuilder::generateSink;
+
   ExplodedNode *generateNode(const Stmt *S,
                              ExplodedNode *Pred,
                              ProgramStateRef St,
-                             bool MarkAsSink = false,
                              const ProgramPointTag *tag = 0,
                              ProgramPoint::Kind K = ProgramPoint::PostStmtKind){
     const ProgramPoint &L = ProgramPoint::getProgramPoint(S, K,
                                   Pred->getLocationContext(), tag);
-    return generateNodeImpl(L, St, Pred, MarkAsSink);
+    return NodeBuilder::generateNode(L, St, Pred);
   }
 
-  ExplodedNode *generateNode(const ProgramPoint &PP,
+  ExplodedNode *generateSink(const Stmt *S,
                              ExplodedNode *Pred,
-                             ProgramStateRef State,
-                             bool MarkAsSink = false) {
-    return generateNodeImpl(PP, State, Pred, MarkAsSink);
+                             ProgramStateRef St,
+                             const ProgramPointTag *tag = 0,
+                             ProgramPoint::Kind K = ProgramPoint::PostStmtKind){
+    const ProgramPoint &L = ProgramPoint::getProgramPoint(S, K,
+                                  Pred->getLocationContext(), tag);
+    return NodeBuilder::generateSink(L, St, Pred);
   }
 };
 

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/OSAtomicChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/OSAtomicChecker.cpp?rev=162215&r1=162214&r2=162215&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/OSAtomicChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/OSAtomicChecker.cpp Mon Aug 20 13:43:42 2012
@@ -192,8 +192,7 @@
         QualType T = CE->getType();
         if (!T->isVoidType())
           Res = Eng.getSValBuilder().makeTruthVal(true, T);
-        B.generateNode(CE, predNew, stateNew->BindExpr(CE, LCtx, Res),
-                       false, this);
+        B.generateNode(CE, predNew, stateNew->BindExpr(CE, LCtx, Res), this);
       }
     }
 
@@ -205,8 +204,7 @@
       if (!T->isVoidType())
         Res = Eng.getSValBuilder().makeTruthVal(false, CE->getType());
       StmtNodeBuilder B(N, Dst, Eng.getBuilderContext());    
-      B.generateNode(CE, N, stateNotEqual->BindExpr(CE, LCtx, Res),
-                     false, this);
+      B.generateNode(CE, N, stateNotEqual->BindExpr(CE, LCtx, Res), this);
     }
   }
 

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp?rev=162215&r1=162214&r2=162215&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp Mon Aug 20 13:43:42 2012
@@ -3432,7 +3432,7 @@
   V = V ^ RefVal::ErrorOverAutorelease;
   state = setRefBinding(state, Sym, V);
 
-  ExplodedNode *N = Ctx.addTransition(state, Pred, Tag, /*IsSink=*/true);
+  ExplodedNode *N = Ctx.generateSink(state, Pred, Tag);
   if (N) {
     SmallString<128> sbuf;
     llvm::raw_svector_ostream os(sbuf);

Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp?rev=162215&r1=162214&r2=162215&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp Mon Aug 20 13:43:42 2012
@@ -277,7 +277,7 @@
     // up. Since no symbols are dead, we can optimize and not clean out
     // the constraint manager.
     StmtNodeBuilder Bldr(Pred, Out, *currentBuilderContext);
-    Bldr.generateNode(DiagnosticStmt, Pred, CleanedState, false, &cleanupTag,K);
+    Bldr.generateNode(DiagnosticStmt, Pred, CleanedState, &cleanupTag, K);
 
   } else {
     // Call checkers with the non-cleaned state so that they could query the
@@ -309,8 +309,7 @@
       // generate a transition to that state.
       ProgramStateRef CleanedCheckerSt =
         StateMgr.getPersistentStateWithGDM(CleanedState, CheckerState);
-      Bldr.generateNode(DiagnosticStmt, *I, CleanedCheckerSt, false,
-                        &cleanupTag, K);
+      Bldr.generateNode(DiagnosticStmt, *I, CleanedCheckerSt, &cleanupTag, K);
     }
   }
 }
@@ -525,8 +524,7 @@
     case Stmt::SEHExceptStmtClass:
     case Stmt::LambdaExprClass:
     case Stmt::SEHFinallyStmtClass: {
-      const ExplodedNode *node = Bldr.generateNode(S, Pred, Pred->getState(),
-                                                   /* sink */ true);
+      const ExplodedNode *node = Bldr.generateSink(S, Pred, Pred->getState());
       Engine.addAbortedBlock(node, currentBuilderContext->getBlock());
       break;
     }
@@ -885,7 +883,7 @@
     case Stmt::CXXThrowExprClass:
       // FIXME: This is not complete.  We basically treat @throw as
       // an abort.
-      Bldr.generateNode(S, Pred, Pred->getState(), /*IsSink=*/true);
+      Bldr.generateSink(S, Pred, Pred->getState());
       break;
 
     case Stmt::ReturnStmtClass:
@@ -1033,7 +1031,7 @@
   if (nodeBuilder.getContext().getCurrentBlockCount() >= AMgr.getMaxVisit()) {
     static SimpleProgramPointTag tag("ExprEngine : Block count exceeded");
     const ExplodedNode *Sink =
-                   nodeBuilder.generateNode(pred->getState(), pred, &tag, true);
+                   nodeBuilder.generateSink(pred->getState(), pred, &tag);
 
     // Check if we stopped at the top level function or not.
     // Root node should have the location context of the top most function.
@@ -1417,7 +1415,7 @@
         V = UnknownVal();
     }
 
-    Bldr.generateNode(Ex, Pred, state->BindExpr(Ex, LCtx, V), false, 0,
+    Bldr.generateNode(Ex, Pred, state->BindExpr(Ex, LCtx, V), 0,
                       ProgramPoint::PostLValueKind);
     return;
   }
@@ -1429,19 +1427,18 @@
   }
   if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
     SVal V = svalBuilder.getFunctionPointer(FD);
-    Bldr.generateNode(Ex, Pred, state->BindExpr(Ex, LCtx, V), false, 0,
+    Bldr.generateNode(Ex, Pred, state->BindExpr(Ex, LCtx, V), 0,
                       ProgramPoint::PostLValueKind);
     return;
   }
   if (isa<FieldDecl>(D)) {
-    // FIXME: Compute lvalue of fields.
-    Bldr.generateNode(Ex, Pred, state->BindExpr(Ex, LCtx, UnknownVal()),
-		      false, 0, ProgramPoint::PostLValueKind);
+    // FIXME: Compute lvalue of field pointers-to-member.
+    Bldr.generateNode(Ex, Pred, state->BindExpr(Ex, LCtx, UnknownVal()), 0,
+		      ProgramPoint::PostLValueKind);
     return;
   }
 
-  assert (false &&
-          "ValueDecl support for this ValueDecl not implemented.");
+  llvm_unreachable("Support for this Decl not implemented.");
 }
 
 /// VisitArraySubscriptExpr - Transfer function for array accesses
@@ -1466,8 +1463,8 @@
                               state->getSVal(Idx, LCtx),
                               state->getSVal(Base, LCtx));
     assert(A->isGLValue());
-    Bldr.generateNode(A, *it, state->BindExpr(A, LCtx, V),
-                      false, 0, ProgramPoint::PostLValueKind);
+    Bldr.generateNode(A, *it, state->BindExpr(A, LCtx, V), 0, 
+                      ProgramPoint::PostLValueKind);
   }
 }
 
@@ -1530,7 +1527,7 @@
         L = UnknownVal();
     }
 
-    Bldr.generateNode(M, Pred, state->BindExpr(M, LCtx, L), false, 0,
+    Bldr.generateNode(M, Pred, state->BindExpr(M, LCtx, L), 0,
                       ProgramPoint::PostLValueKind);
   } else {
     Bldr.takeNodes(Pred);
@@ -1574,7 +1571,7 @@
       LocReg = LocRegVal->getRegion();
 
     const ProgramPoint L = PostStore(StoreE, LC, LocReg, 0);
-    Bldr.generateNode(L, PredI, state, false);
+    Bldr.generateNode(L, state, PredI);
   }
 
   Dst.insert(TmpDst);
@@ -1679,8 +1676,7 @@
       // This is important.  We must nuke the old binding.
       Bldr.generateNode(NodeEx, *NI,
                         state->BindExpr(BoundEx, LCtx, UnknownVal()),
-                        false, tag,
-                        ProgramPoint::PostLoadKind);
+                        tag, ProgramPoint::PostLoadKind);
     }
     else {
       if (LoadTy.isNull())
@@ -1688,7 +1684,7 @@
       SVal V = state->getSVal(cast<Loc>(location), LoadTy);
       Bldr.generateNode(NodeEx, *NI,
                         state->bindExprAndLocation(BoundEx, LCtx, location, V),
-                        false, tag, ProgramPoint::PostLoadKind);
+                        tag, ProgramPoint::PostLoadKind);
     }
   }
 }
@@ -1720,9 +1716,8 @@
     // instead "int *p" is noted as
     // "Variable 'p' initialized to a null pointer value"
     
-    // FIXME: why is 'tag' not used instead of etag?
-    static SimpleProgramPointTag etag("ExprEngine: Location");
-    Bldr.generateNode(NodeEx, Pred, state, false, &etag);
+    static SimpleProgramPointTag tag("ExprEngine: Location");
+    Bldr.generateNode(NodeEx, Pred, state, &tag);
   }
   ExplodedNodeSet Tmp;
   getCheckerManager().runCheckersForLocation(Tmp, Src, location, isLoad,
@@ -1763,14 +1758,14 @@
       if (ProgramStateRef StateTrue = state->assume(*SEV, true)) {
         SVal Val = svalBuilder.makeIntVal(1U, Ex->getType());        
         StateTrue = StateTrue->BindExpr(Ex, Pred->getLocationContext(), Val);
-        Bldr.generateNode(Ex, Pred, StateTrue, false, tags.first);
+        Bldr.generateNode(Ex, Pred, StateTrue, tags.first);
       }
 
       // Next, assume that the condition is false.
       if (ProgramStateRef StateFalse = state->assume(*SEV, false)) {
         SVal Val = svalBuilder.makeIntVal(0U, Ex->getType());
         StateFalse = StateFalse->BindExpr(Ex, Pred->getLocationContext(), Val);
-        Bldr.generateNode(Ex, Pred, StateFalse, false, tags.second);
+        Bldr.generateNode(Ex, Pred, StateFalse, tags.second);
       }
     }
   }

Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineC.cpp?rev=162215&r1=162214&r2=162215&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineC.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineC.cpp Mon Aug 20 13:43:42 2012
@@ -211,8 +211,7 @@
   StmtNodeBuilder Bldr(Pred, Tmp, *currentBuilderContext);
   Bldr.generateNode(BE, Pred,
                     State->BindExpr(BE, Pred->getLocationContext(), V),
-                    false, 0,
-                    ProgramPoint::PostLValueKind);
+                    0, ProgramPoint::PostLValueKind);
   
   // FIXME: Move all post/pre visits to ::Visit().
   getCheckerManager().runCheckersForPostStmt(Dst, Tmp, BE, *this);
@@ -347,7 +346,7 @@
           if (T->isReferenceType()) {
             // A bad_cast exception is thrown if input value is a reference.
             // Currently, we model this, by generating a sink.
-            Bldr.generateNode(CastE, Pred, state, true);
+            Bldr.generateSink(CastE, Pred, state);
             continue;
           } else {
             // If the cast fails on a pointer, bind to 0.

Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp?rev=162215&r1=162214&r2=162215&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp Mon Aug 20 13:43:42 2012
@@ -187,7 +187,7 @@
         if (Msg->getSelector() == RaiseSel) {
           // If we raise an exception, for now treat it as a sink.
           // Eventually we will want to handle exceptions properly.
-          Bldr.generateNode(currentStmt, Pred, State, true);
+          Bldr.generateSink(currentStmt, Pred, State);
           continue;
         }
         
@@ -237,7 +237,7 @@
           if (RaisesException) {
             // If we raise an exception, for now treat it as a sink.
             // Eventually we will want to handle exceptions properly.
-            Bldr.generateNode(currentStmt, Pred, Pred->getState(), true);
+            Bldr.generateSink(currentStmt, Pred, Pred->getState());
             continue;
           }
 





More information about the cfe-commits mailing list