r247859 - [analyzer] Add generateErrorNode() APIs to CheckerContext.

Devin Coughlin via cfe-commits cfe-commits at lists.llvm.org
Wed Sep 16 15:03:07 PDT 2015


Author: dcoughlin
Date: Wed Sep 16 17:03:05 2015
New Revision: 247859

URL: http://llvm.org/viewvc/llvm-project?rev=247859&view=rev
Log:
[analyzer] Add generateErrorNode() APIs to CheckerContext.

The analyzer trims unnecessary nodes from the exploded graph before reporting
path diagnostics. However, in some cases it can trim all nodes (including the
error node), leading to an assertion failure (see
https://llvm.org/bugs/show_bug.cgi?id=24184).

This commit addresses the issue by adding two new APIs to CheckerContext to
explicitly create error nodes. Unless the client provides a custom tag, these
APIs tag the node with the checker's tag -- preventing it from being trimmed.
The generateErrorNode() method creates a sink error node, while
generateNonFatalErrorNode() creates an error node for a path that should
continue being explored.

The intent is that one of these two methods should be used whenever a checker
creates an error node.

This commit updates the checkers to use these APIs. These APIs
(unlike addTransition() and generateSink()) do not take an explicit Pred node.
This is because there are not any error nodes in the checkers that were created
with an explicit different than the default (the CheckerContext's Pred node).

It also changes generateSink() to require state and pred nodes (previously
these were optional) to reduce confusion.

Additionally, there were several cases where checkers did check whether a
generated node could be null; we now explicitly check for null in these places.

This commit also includes a test case written by Ying Yi as part of
http://reviews.llvm.org/D12163 (that patch originally addressed this issue but
was reverted because it introduced false positive regressions).

Differential Revision: http://reviews.llvm.org/D12780

Added:
    cfe/trunk/test/Analysis/PR24184.cpp
Modified:
    cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h
    cfe/trunk/lib/StaticAnalyzer/Checkers/ArrayBoundChecker.cpp
    cfe/trunk/lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp
    cfe/trunk/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp
    cfe/trunk/lib/StaticAnalyzer/Checkers/BoolAssignmentChecker.cpp
    cfe/trunk/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
    cfe/trunk/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp
    cfe/trunk/lib/StaticAnalyzer/Checkers/CastSizeChecker.cpp
    cfe/trunk/lib/StaticAnalyzer/Checkers/CastToStructChecker.cpp
    cfe/trunk/lib/StaticAnalyzer/Checkers/ChrootChecker.cpp
    cfe/trunk/lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp
    cfe/trunk/lib/StaticAnalyzer/Checkers/DivZeroChecker.cpp
    cfe/trunk/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp
    cfe/trunk/lib/StaticAnalyzer/Checkers/FixedAddressChecker.cpp
    cfe/trunk/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
    cfe/trunk/lib/StaticAnalyzer/Checkers/MacOSKeychainAPIChecker.cpp
    cfe/trunk/lib/StaticAnalyzer/Checkers/MacOSXAPIChecker.cpp
    cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
    cfe/trunk/lib/StaticAnalyzer/Checkers/NSAutoreleasePoolChecker.cpp
    cfe/trunk/lib/StaticAnalyzer/Checkers/NoReturnFunctionChecker.cpp
    cfe/trunk/lib/StaticAnalyzer/Checkers/NonNullParamChecker.cpp
    cfe/trunk/lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp
    cfe/trunk/lib/StaticAnalyzer/Checkers/ObjCAtSyncChecker.cpp
    cfe/trunk/lib/StaticAnalyzer/Checkers/ObjCContainersChecker.cpp
    cfe/trunk/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp
    cfe/trunk/lib/StaticAnalyzer/Checkers/PointerArithChecker.cpp
    cfe/trunk/lib/StaticAnalyzer/Checkers/PointerSubChecker.cpp
    cfe/trunk/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp
    cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp
    cfe/trunk/lib/StaticAnalyzer/Checkers/ReturnPointerRangeChecker.cpp
    cfe/trunk/lib/StaticAnalyzer/Checkers/ReturnUndefChecker.cpp
    cfe/trunk/lib/StaticAnalyzer/Checkers/SimpleStreamChecker.cpp
    cfe/trunk/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp
    cfe/trunk/lib/StaticAnalyzer/Checkers/StreamChecker.cpp
    cfe/trunk/lib/StaticAnalyzer/Checkers/TaintTesterChecker.cpp
    cfe/trunk/lib/StaticAnalyzer/Checkers/TestAfterDivZeroChecker.cpp
    cfe/trunk/lib/StaticAnalyzer/Checkers/UndefBranchChecker.cpp
    cfe/trunk/lib/StaticAnalyzer/Checkers/UndefCapturedBlockVarChecker.cpp
    cfe/trunk/lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp
    cfe/trunk/lib/StaticAnalyzer/Checkers/UndefinedArraySubscriptChecker.cpp
    cfe/trunk/lib/StaticAnalyzer/Checkers/UndefinedAssignmentChecker.cpp
    cfe/trunk/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp
    cfe/trunk/lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp
    cfe/trunk/lib/StaticAnalyzer/Core/BugReporter.cpp
    cfe/trunk/test/Analysis/malloc.c

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=247859&r1=247858&r2=247859&view=diff
==============================================================================
--- cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h (original)
+++ cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h Wed Sep 16 17:03:05 2015
@@ -224,13 +224,39 @@ public:
   }
 
   /// \brief Generate a sink node. Generating a sink stops exploration of the
-  /// given path.
-  ExplodedNode *generateSink(ProgramStateRef State = nullptr,
-                             ExplodedNode *Pred = nullptr,
+  /// given path. To create a sink node for the purpose of reporting an error,
+  /// checkers should use generateErrorNode() instead.
+  ExplodedNode *generateSink(ProgramStateRef State, ExplodedNode *Pred,
                              const ProgramPointTag *Tag = nullptr) {
     return addTransitionImpl(State ? State : getState(), true, Pred, Tag);
   }
 
+  /// \brief Generate a transition to a node that will be used to report
+  /// an error. This node will be a sink. That is, it will stop exploration of
+  /// the given path.
+  ///
+  /// @param State The state of the generated node.
+  /// @param Tag The tag to uniquely identify the creation site. If null,
+  ///        the default tag for the checker will be used.
+  ExplodedNode *generateErrorNode(ProgramStateRef State = nullptr,
+                                  const ProgramPointTag *Tag = nullptr) {
+    return generateSink(State, Pred,
+                       (Tag ? Tag : Location.getTag()));
+  }
+
+  /// \brief Generate a transition to a node that will be used to report
+  /// an error. This node will not be a sink. That is, exploration will
+  /// continue along this path.
+  ///
+  /// @param State The state of the generated node.
+  /// @param Tag The tag to uniquely identify the creation site. If null,
+  ///        the default tag for the checker will be used.
+  ExplodedNode *
+  generateNonFatalErrorNode(ProgramStateRef State = nullptr,
+                            const ProgramPointTag *Tag = nullptr) {
+    return addTransition(State, (Tag ? Tag : Location.getTag()));
+  }
+
   /// \brief Emit the diagnostics report.
   void emitReport(std::unique_ptr<BugReport> R) {
     Changed = true;
@@ -287,6 +313,18 @@ private:
                                  bool MarkAsSink,
                                  ExplodedNode *P = nullptr,
                                  const ProgramPointTag *Tag = nullptr) {
+    // The analyzer may stop exploring if it sees a state it has previously
+    // visited ("cache out"). The early return here is a defensive check to
+    // prevent accidental caching out by checker API clients. Unless there is a
+    // tag or the the client checker has requested that the generated node be
+    // marked as a sink, we assume that a client requesting a transition to a
+    // state that is the same as the predecessor state has made a mistake. We
+    // return the predecessor rather than cache out.
+    //
+    // TODO: We could potentially change the return to an assertion to alert
+    // clients to their mistake, but several checkers (including
+    // DereferenceChecker, CallAndMessageChecker, and DynamicTypePropagation)
+    // rely upon the defensive behavior and would need to be updated.
     if (!State || (State == Pred->getState() && !Tag && !MarkAsSink))
       return Pred;
 

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/ArrayBoundChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/ArrayBoundChecker.cpp?rev=247859&r1=247858&r2=247859&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/ArrayBoundChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/ArrayBoundChecker.cpp Wed Sep 16 17:03:05 2015
@@ -62,7 +62,7 @@ void ArrayBoundChecker::checkLocation(SV
   ProgramStateRef StInBound = state->assumeInBound(Idx, NumElements, true);
   ProgramStateRef StOutBound = state->assumeInBound(Idx, NumElements, false);
   if (StOutBound && !StInBound) {
-    ExplodedNode *N = C.generateSink(StOutBound);
+    ExplodedNode *N = C.generateErrorNode(StOutBound);
     if (!N)
       return;
 

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp?rev=247859&r1=247858&r2=247859&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp Wed Sep 16 17:03:05 2015
@@ -182,7 +182,7 @@ void ArrayBoundCheckerV2::reportOOB(Chec
                                     ProgramStateRef errorState,
                                     OOB_Kind kind) const {
 
-  ExplodedNode *errorNode = checkerContext.generateSink(errorState);
+  ExplodedNode *errorNode = checkerContext.generateErrorNode(errorState);
   if (!errorNode)
     return;
 

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp?rev=247859&r1=247858&r2=247859&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp Wed Sep 16 17:03:05 2015
@@ -140,7 +140,7 @@ void NilArgChecker::warnIfNilExpr(const
   ProgramStateRef State = C.getState();
   if (State->isNull(C.getSVal(E)).isConstrainedTrue()) {
 
-    if (ExplodedNode *N = C.generateSink()) {
+    if (ExplodedNode *N = C.generateErrorNode()) {
       generateBugReport(N, Msg, E->getSourceRange(), E, C);
     }
 
@@ -157,7 +157,7 @@ void NilArgChecker::warnIfNilArg(Checker
   if (!State->isNull(msg.getArgSVal(Arg)).isConstrainedTrue())
       return;
 
-  if (ExplodedNode *N = C.generateSink()) {
+  if (ExplodedNode *N = C.generateErrorNode()) {
     SmallString<128> sbuf;
     llvm::raw_svector_ostream os(sbuf);
 
@@ -489,14 +489,15 @@ void CFNumberCreateChecker::checkPreStmt
   if (SourceSize == TargetSize)
     return;
 
-  // Generate an error.  Only generate a sink if 'SourceSize < TargetSize';
-  // otherwise generate a regular node.
+  // Generate an error.  Only generate a sink error node
+  // if 'SourceSize < TargetSize'; otherwise generate a non-fatal error node.
   //
   // FIXME: We can actually create an abstract "CFNumber" object that has
   //  the bits initialized to the provided values.
   //
-  if (ExplodedNode *N = SourceSize < TargetSize ? C.generateSink()
-                                                : C.addTransition()) {
+  ExplodedNode *N = SourceSize < TargetSize ? C.generateErrorNode()
+                                            : C.generateNonFatalErrorNode();
+  if (N) {
     SmallString<128> sbuf;
     llvm::raw_svector_ostream os(sbuf);
 
@@ -589,7 +590,7 @@ void CFRetainReleaseChecker::checkPreStm
   std::tie(stateTrue, stateFalse) = state->assume(ArgIsNull);
 
   if (stateTrue && !stateFalse) {
-    ExplodedNode *N = C.generateSink(stateTrue);
+    ExplodedNode *N = C.generateErrorNode(stateTrue);
     if (!N)
       return;
 
@@ -656,7 +657,7 @@ void ClassReleaseChecker::checkPreObjCMe
   if (!(S == releaseS || S == retainS || S == autoreleaseS || S == drainS))
     return;
 
-  if (ExplodedNode *N = C.addTransition()) {
+  if (ExplodedNode *N = C.generateNonFatalErrorNode()) {
     SmallString<200> buf;
     llvm::raw_svector_ostream os(buf);
 
@@ -800,7 +801,7 @@ void VariadicMethodTypeChecker::checkPre
 
     // Generate only one error node to use for all bug reports.
     if (!errorNode.hasValue())
-      errorNode = C.addTransition();
+      errorNode = C.generateNonFatalErrorNode();
 
     if (!errorNode.getValue())
       continue;
@@ -1025,7 +1026,7 @@ void ObjCLoopChecker::checkPostStmt(cons
   }
 
   if (!State)
-    C.generateSink();
+    C.generateSink(C.getState(), C.getPredecessor());
   else if (State != C.getState())
     C.addTransition(State);
 }

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/BoolAssignmentChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/BoolAssignmentChecker.cpp?rev=247859&r1=247858&r2=247859&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/BoolAssignmentChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/BoolAssignmentChecker.cpp Wed Sep 16 17:03:05 2015
@@ -32,7 +32,7 @@ namespace {
 
 void BoolAssignmentChecker::emitReport(ProgramStateRef state,
                                        CheckerContext &C) const {
-  if (ExplodedNode *N = C.addTransition(state)) {
+  if (ExplodedNode *N = C.generateNonFatalErrorNode(state)) {
     if (!BT)
       BT.reset(new BuiltinBug(this, "Assignment of a non-Boolean value"));
     C.emitReport(llvm::make_unique<BugReport>(*BT, BT->getDescription(), N));

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/CStringChecker.cpp?rev=247859&r1=247858&r2=247859&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/CStringChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/CStringChecker.cpp Wed Sep 16 17:03:05 2015
@@ -229,7 +229,7 @@ ProgramStateRef CStringChecker::checkNon
     if (!Filter.CheckCStringNullArg)
       return nullptr;
 
-    ExplodedNode *N = C.generateSink(stateNull);
+    ExplodedNode *N = C.generateErrorNode(stateNull);
     if (!N)
       return nullptr;
 
@@ -292,7 +292,7 @@ ProgramStateRef CStringChecker::CheckLoc
   ProgramStateRef StInBound = state->assumeInBound(Idx, Size, true);
   ProgramStateRef StOutBound = state->assumeInBound(Idx, Size, false);
   if (StOutBound && !StInBound) {
-    ExplodedNode *N = C.generateSink(StOutBound);
+    ExplodedNode *N = C.generateErrorNode(StOutBound);
     if (!N)
       return nullptr;
 
@@ -525,7 +525,7 @@ ProgramStateRef CStringChecker::CheckOve
 
 void CStringChecker::emitOverlapBug(CheckerContext &C, ProgramStateRef state,
                                   const Stmt *First, const Stmt *Second) const {
-  ExplodedNode *N = C.generateSink(state);
+  ExplodedNode *N = C.generateErrorNode(state);
   if (!N)
     return;
 
@@ -585,7 +585,7 @@ ProgramStateRef CStringChecker::checkAdd
 
     if (stateOverflow && !stateOkay) {
       // We have an overflow. Emit a bug report.
-      ExplodedNode *N = C.generateSink(stateOverflow);
+      ExplodedNode *N = C.generateErrorNode(stateOverflow);
       if (!N)
         return nullptr;
 
@@ -706,7 +706,7 @@ SVal CStringChecker::getCStringLength(Ch
       if (!Filter.CheckCStringNotNullTerm)
         return UndefinedVal();
 
-      if (ExplodedNode *N = C.addTransition(state)) {
+      if (ExplodedNode *N = C.generateNonFatalErrorNode(state)) {
         if (!BT_NotCString)
           BT_NotCString.reset(new BuiltinBug(
               Filter.CheckNameCStringNotNullTerm, categories::UnixAPI,
@@ -766,7 +766,7 @@ SVal CStringChecker::getCStringLength(Ch
     if (!Filter.CheckCStringNotNullTerm)
       return UndefinedVal();
 
-    if (ExplodedNode *N = C.addTransition(state)) {
+    if (ExplodedNode *N = C.generateNonFatalErrorNode(state)) {
       if (!BT_NotCString)
         BT_NotCString.reset(new BuiltinBug(
             Filter.CheckNameCStringNotNullTerm, categories::UnixAPI,

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp?rev=247859&r1=247858&r2=247859&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp Wed Sep 16 17:03:05 2015
@@ -97,7 +97,7 @@ private:
 
 void CallAndMessageChecker::emitBadCall(BugType *BT, CheckerContext &C,
                                         const Expr *BadE) {
-  ExplodedNode *N = C.generateSink();
+  ExplodedNode *N = C.generateErrorNode();
   if (!N)
     return;
 
@@ -169,7 +169,7 @@ bool CallAndMessageChecker::uninitRefOrP
     const ProgramStateRef State = C.getState();
     const SVal PSV = State->getSVal(SValMemRegion);
     if (PSV.isUndef()) {
-      if (ExplodedNode *N = C.generateSink()) {
+      if (ExplodedNode *N = C.generateErrorNode()) {
         LazyInit_BT(BD, BT);
         auto R = llvm::make_unique<BugReport>(*BT, Message, N);
         R->addRange(ArgRange);
@@ -200,7 +200,7 @@ bool CallAndMessageChecker::PreVisitProc
     return true;
 
   if (V.isUndef()) {
-    if (ExplodedNode *N = C.generateSink()) {
+    if (ExplodedNode *N = C.generateErrorNode()) {
       LazyInit_BT(BD, BT);
 
       // Generate a report for this bug.
@@ -265,7 +265,7 @@ bool CallAndMessageChecker::PreVisitProc
                              D->getStore());
 
     if (F.Find(D->getRegion())) {
-      if (ExplodedNode *N = C.generateSink()) {
+      if (ExplodedNode *N = C.generateErrorNode()) {
         LazyInit_BT(BD, BT);
         SmallString<512> Str;
         llvm::raw_svector_ostream os(Str);
@@ -338,7 +338,7 @@ void CallAndMessageChecker::checkPreStmt
   SVal Arg = C.getSVal(DE->getArgument());
   if (Arg.isUndef()) {
     StringRef Desc;
-    ExplodedNode *N = C.generateSink();
+    ExplodedNode *N = C.generateErrorNode();
     if (!N)
       return;
     if (!BT_cxx_delete_undef)
@@ -395,7 +395,7 @@ void CallAndMessageChecker::checkPreCall
     // the function.
     unsigned Params = FD->getNumParams();
     if (Call.getNumArgs() < Params) {
-      ExplodedNode *N = C.generateSink();
+      ExplodedNode *N = C.generateErrorNode();
       if (!N)
         return;
 
@@ -443,7 +443,7 @@ void CallAndMessageChecker::checkPreObjC
                                                 CheckerContext &C) const {
   SVal recVal = msg.getReceiverSVal();
   if (recVal.isUndef()) {
-    if (ExplodedNode *N = C.generateSink()) {
+    if (ExplodedNode *N = C.generateErrorNode()) {
       BugType *BT = nullptr;
       switch (msg.getMessageKind()) {
       case OCM_Message:
@@ -559,7 +559,7 @@ void CallAndMessageChecker::HandleNilRec
             Ctx.LongDoubleTy == CanRetTy ||
             Ctx.LongLongTy == CanRetTy ||
             Ctx.UnsignedLongLongTy == CanRetTy)))) {
-      if (ExplodedNode *N = C.generateSink(state, nullptr, &Tag))
+      if (ExplodedNode *N = C.generateErrorNode(state, &Tag))
         emitNilReceiverBug(C, Msg, N);
       return;
     }

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/CastSizeChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/CastSizeChecker.cpp?rev=247859&r1=247858&r2=247859&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/CastSizeChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/CastSizeChecker.cpp Wed Sep 16 17:03:05 2015
@@ -131,7 +131,7 @@ void CastSizeChecker::checkPreStmt(const
   if (evenFlexibleArraySize(Ctx, regionSize, typeSize, ToPointeeTy))
     return;
 
-  if (ExplodedNode *errorNode = C.generateSink()) {
+  if (ExplodedNode *errorNode = C.generateErrorNode()) {
     if (!BT)
       BT.reset(new BuiltinBug(this, "Cast region with wrong size.",
                                     "Cast a region whose size is not a multiple"

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/CastToStructChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/CastToStructChecker.cpp?rev=247859&r1=247858&r2=247859&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/CastToStructChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/CastToStructChecker.cpp Wed Sep 16 17:03:05 2015
@@ -56,7 +56,7 @@ void CastToStructChecker::checkPreStmt(c
 
   // Now the cast-to-type is struct pointer, the original type is not void*.
   if (!OrigPointeeTy->isRecordType()) {
-    if (ExplodedNode *N = C.addTransition()) {
+    if (ExplodedNode *N = C.generateNonFatalErrorNode()) {
       if (!BT)
         BT.reset(
             new BuiltinBug(this, "Cast from non-struct type to struct type",

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/ChrootChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/ChrootChecker.cpp?rev=247859&r1=247858&r2=247859&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/ChrootChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/ChrootChecker.cpp Wed Sep 16 17:03:05 2015
@@ -140,7 +140,7 @@ void ChrootChecker::checkPreStmt(const C
   void *const* k = C.getState()->FindGDM(ChrootChecker::getTag());
   if (k)
     if (isRootChanged((intptr_t) *k))
-      if (ExplodedNode *N = C.addTransition()) {
+      if (ExplodedNode *N = C.generateNonFatalErrorNode()) {
         if (!BT_BreakJail)
           BT_BreakJail.reset(new BuiltinBug(
               this, "Break out of jail", "No call of chdir(\"/\") immediately "

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp?rev=247859&r1=247858&r2=247859&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp Wed Sep 16 17:03:05 2015
@@ -91,7 +91,7 @@ DereferenceChecker::AddDerefSource(raw_o
 void DereferenceChecker::reportBug(ProgramStateRef State, const Stmt *S,
                                    CheckerContext &C, bool IsBind) const {
   // Generate an error node.
-  ExplodedNode *N = C.generateSink(State);
+  ExplodedNode *N = C.generateErrorNode(State);
   if (!N)
     return;
 
@@ -184,7 +184,7 @@ void DereferenceChecker::checkLocation(S
                                        CheckerContext &C) const {
   // Check for dereference of an undefined value.
   if (l.isUndef()) {
-    if (ExplodedNode *N = C.generateSink()) {
+    if (ExplodedNode *N = C.generateErrorNode()) {
       if (!BT_undef)
         BT_undef.reset(
             new BuiltinBug(this, "Dereference of undefined pointer value"));
@@ -219,7 +219,7 @@ void DereferenceChecker::checkLocation(S
     // Otherwise, we have the case where the location could either be
     // null or not-null.  Record the error node as an "implicit" null
     // dereference.
-    if (ExplodedNode *N = C.generateSink(nullState)) {
+    if (ExplodedNode *N = C.generateSink(nullState, C.getPredecessor())) {
       ImplicitNullDerefEvent event = {l, isLoad, N, &C.getBugReporter(),
                                       /*IsDirectDereference=*/false};
       dispatchEvent(event);
@@ -257,7 +257,7 @@ void DereferenceChecker::checkBind(SVal
 
     // At this point the value could be either null or non-null.
     // Record this as an "implicit" null dereference.
-    if (ExplodedNode *N = C.generateSink(StNull)) {
+    if (ExplodedNode *N = C.generateSink(StNull, C.getPredecessor())) {
       ImplicitNullDerefEvent event = {V, /*isLoad=*/true, N,
                                       &C.getBugReporter(),
                                       /*IsDirectDereference=*/false};

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/DivZeroChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/DivZeroChecker.cpp?rev=247859&r1=247858&r2=247859&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/DivZeroChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/DivZeroChecker.cpp Wed Sep 16 17:03:05 2015
@@ -35,7 +35,7 @@ public:
 void DivZeroChecker::reportBug(const char *Msg,
                                ProgramStateRef StateZero,
                                CheckerContext &C) const {
-  if (ExplodedNode *N = C.generateSink(StateZero)) {
+  if (ExplodedNode *N = C.generateErrorNode(StateZero)) {
     if (!BT)
       BT.reset(new BuiltinBug(this, "Division by zero"));
 

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp?rev=247859&r1=247858&r2=247859&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp Wed Sep 16 17:03:05 2015
@@ -86,8 +86,7 @@ static const char *getArgumentValueStrin
 
 void ExprInspectionChecker::analyzerEval(const CallExpr *CE,
                                          CheckerContext &C) const {
-  ExplodedNode *N = C.getPredecessor();
-  const LocationContext *LC = N->getLocationContext();
+  const LocationContext *LC = C.getPredecessor()->getLocationContext();
 
   // A specific instantiation of an inlined function may have more constrained
   // values than can generally be assumed. Skip the check.
@@ -97,24 +96,28 @@ void ExprInspectionChecker::analyzerEval
   if (!BT)
     BT.reset(new BugType(this, "Checking analyzer assumptions", "debug"));
 
+  ExplodedNode *N = C.generateNonFatalErrorNode();
+  if (!N)
+    return;
   C.emitReport(
       llvm::make_unique<BugReport>(*BT, getArgumentValueString(CE, C), N));
 }
 
 void ExprInspectionChecker::analyzerWarnIfReached(const CallExpr *CE,
                                                   CheckerContext &C) const {
-  ExplodedNode *N = C.getPredecessor();
 
   if (!BT)
     BT.reset(new BugType(this, "Checking analyzer assumptions", "debug"));
 
+  ExplodedNode *N = C.generateNonFatalErrorNode();
+  if (!N)
+    return;
   C.emitReport(llvm::make_unique<BugReport>(*BT, "REACHABLE", N));
 }
 
 void ExprInspectionChecker::analyzerCheckInlined(const CallExpr *CE,
                                                  CheckerContext &C) const {
-  ExplodedNode *N = C.getPredecessor();
-  const LocationContext *LC = N->getLocationContext();
+  const LocationContext *LC = C.getPredecessor()->getLocationContext();
 
   // An inlined function could conceivably also be analyzed as a top-level
   // function. We ignore this case and only emit a message (TRUE or FALSE)
@@ -127,6 +130,9 @@ void ExprInspectionChecker::analyzerChec
   if (!BT)
     BT.reset(new BugType(this, "Checking analyzer assumptions", "debug"));
 
+  ExplodedNode *N = C.generateNonFatalErrorNode();
+  if (!N)
+    return;
   C.emitReport(
       llvm::make_unique<BugReport>(*BT, getArgumentValueString(CE, C), N));
 }

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/FixedAddressChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/FixedAddressChecker.cpp?rev=247859&r1=247858&r2=247859&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/FixedAddressChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/FixedAddressChecker.cpp Wed Sep 16 17:03:05 2015
@@ -50,7 +50,7 @@ void FixedAddressChecker::checkPreStmt(c
   if (!RV.isConstant() || RV.isZeroConstant())
     return;
 
-  if (ExplodedNode *N = C.addTransition()) {
+  if (ExplodedNode *N = C.generateNonFatalErrorNode()) {
     if (!BT)
       BT.reset(
           new BuiltinBug(this, "Use fixed address",

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp?rev=247859&r1=247858&r2=247859&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp Wed Sep 16 17:03:05 2015
@@ -640,7 +640,7 @@ bool GenericTaintChecker::generateReport
     return false;
 
   // Generate diagnostic.
-  if (ExplodedNode *N = C.addTransition()) {
+  if (ExplodedNode *N = C.generateNonFatalErrorNode()) {
     initBugType();
     auto report = llvm::make_unique<BugReport>(*BT, Msg, N);
     report->addRange(E->getSourceRange());

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/MacOSKeychainAPIChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/MacOSKeychainAPIChecker.cpp?rev=247859&r1=247858&r2=247859&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/MacOSKeychainAPIChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/MacOSKeychainAPIChecker.cpp Wed Sep 16 17:03:05 2015
@@ -255,7 +255,7 @@ void MacOSKeychainAPIChecker::
                                     CheckerContext &C) const {
   ProgramStateRef State = C.getState();
   State = State->remove<AllocatedData>(AP.first);
-  ExplodedNode *N = C.addTransition(State);
+  ExplodedNode *N = C.generateNonFatalErrorNode(State);
 
   if (!N)
     return;
@@ -301,7 +301,7 @@ void MacOSKeychainAPIChecker::checkPreSt
           // Remove the value from the state. The new symbol will be added for
           // tracking when the second allocator is processed in checkPostStmt().
           State = State->remove<AllocatedData>(V);
-          ExplodedNode *N = C.addTransition(State);
+          ExplodedNode *N = C.generateNonFatalErrorNode(State);
           if (!N)
             return;
           initBugType();
@@ -364,7 +364,7 @@ void MacOSKeychainAPIChecker::checkPreSt
     if (isEnclosingFunctionParam(ArgExpr))
       return;
 
-    ExplodedNode *N = C.addTransition(State);
+    ExplodedNode *N = C.generateNonFatalErrorNode(State);
     if (!N)
       return;
     initBugType();
@@ -430,7 +430,7 @@ void MacOSKeychainAPIChecker::checkPreSt
   // report a bad call to free.
   if (State->assume(ArgSVal.castAs<DefinedSVal>(), false) &&
       !definitelyDidnotReturnError(AS->Region, State, C.getSValBuilder())) {
-    ExplodedNode *N = C.addTransition(State);
+    ExplodedNode *N = C.generateNonFatalErrorNode(State);
     if (!N)
       return;
     initBugType();
@@ -584,7 +584,9 @@ void MacOSKeychainAPIChecker::checkDeadS
   }
 
   static CheckerProgramPointTag Tag(this, "DeadSymbolsLeak");
-  ExplodedNode *N = C.addTransition(C.getState(), C.getPredecessor(), &Tag);
+  ExplodedNode *N = C.generateNonFatalErrorNode(C.getState(), &Tag);
+  if (!N)
+    return;
 
   // Generate the error reports.
   for (const auto P : Errors)

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/MacOSXAPIChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/MacOSXAPIChecker.cpp?rev=247859&r1=247858&r2=247859&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/MacOSXAPIChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/MacOSXAPIChecker.cpp Wed Sep 16 17:03:05 2015
@@ -62,7 +62,7 @@ void MacOSXAPIChecker::CheckDispatchOnce
   if (!R || !isa<StackSpaceRegion>(R->getMemorySpace()))
     return;
 
-  ExplodedNode *N = C.generateSink(state);
+  ExplodedNode *N = C.generateErrorNode(state);
   if (!N)
     return;
 

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp?rev=247859&r1=247858&r2=247859&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp Wed Sep 16 17:03:05 2015
@@ -1592,7 +1592,7 @@ void MallocChecker::ReportBadFree(Checke
   if (!CheckKind.hasValue())
     return;
 
-  if (ExplodedNode *N = C.generateSink()) {
+  if (ExplodedNode *N = C.generateErrorNode()) {
     if (!BT_BadFree[*CheckKind])
       BT_BadFree[*CheckKind].reset(
           new BugType(CheckNames[*CheckKind], "Bad free", "Memory Error"));
@@ -1637,7 +1637,7 @@ void MallocChecker::ReportFreeAlloca(Che
   else
     return;
 
-  if (ExplodedNode *N = C.generateSink()) {
+  if (ExplodedNode *N = C.generateErrorNode()) {
     if (!BT_FreeAlloca[*CheckKind])
       BT_FreeAlloca[*CheckKind].reset(
           new BugType(CheckNames[*CheckKind], "Free alloca()", "Memory Error"));
@@ -1661,7 +1661,7 @@ void MallocChecker::ReportMismatchedDeal
   if (!ChecksEnabled[CK_MismatchedDeallocatorChecker])
     return;
 
-  if (ExplodedNode *N = C.generateSink()) {
+  if (ExplodedNode *N = C.generateErrorNode()) {
     if (!BT_MismatchedDealloc)
       BT_MismatchedDealloc.reset(
           new BugType(CheckNames[CK_MismatchedDeallocatorChecker],
@@ -1720,7 +1720,7 @@ void MallocChecker::ReportOffsetFree(Che
   if (!CheckKind.hasValue())
     return;
 
-  ExplodedNode *N = C.generateSink();
+  ExplodedNode *N = C.generateErrorNode();
   if (!N)
     return;
 
@@ -1774,7 +1774,7 @@ void MallocChecker::ReportUseAfterFree(C
   if (!CheckKind.hasValue())
     return;
 
-  if (ExplodedNode *N = C.generateSink()) {
+  if (ExplodedNode *N = C.generateErrorNode()) {
     if (!BT_UseFree[*CheckKind])
       BT_UseFree[*CheckKind].reset(new BugType(
           CheckNames[*CheckKind], "Use-after-free", "Memory Error"));
@@ -1801,7 +1801,7 @@ void MallocChecker::ReportDoubleFree(Che
   if (!CheckKind.hasValue())
     return;
 
-  if (ExplodedNode *N = C.generateSink()) {
+  if (ExplodedNode *N = C.generateErrorNode()) {
     if (!BT_DoubleFree[*CheckKind])
       BT_DoubleFree[*CheckKind].reset(
           new BugType(CheckNames[*CheckKind], "Double free", "Memory Error"));
@@ -1829,7 +1829,7 @@ void MallocChecker::ReportDoubleDelete(C
   if (!CheckKind.hasValue())
     return;
 
-  if (ExplodedNode *N = C.generateSink()) {
+  if (ExplodedNode *N = C.generateErrorNode()) {
     if (!BT_DoubleDelete)
       BT_DoubleDelete.reset(new BugType(CheckNames[CK_NewDeleteChecker],
                                         "Double delete", "Memory Error"));
@@ -1856,7 +1856,7 @@ void MallocChecker::ReportUseZeroAllocat
   if (!CheckKind.hasValue())
     return;
 
-  if (ExplodedNode *N = C.generateSink()) {
+  if (ExplodedNode *N = C.generateErrorNode()) {
     if (!BT_UseZerroAllocated[*CheckKind])
       BT_UseZerroAllocated[*CheckKind].reset(new BugType(
           CheckNames[*CheckKind], "Use of zero allocated", "Memory Error"));
@@ -2150,10 +2150,12 @@ void MallocChecker::checkDeadSymbols(Sym
   ExplodedNode *N = C.getPredecessor();
   if (!Errors.empty()) {
     static CheckerProgramPointTag Tag("MallocChecker", "DeadSymbolsLeak");
-    N = C.addTransition(C.getState(), C.getPredecessor(), &Tag);
-    for (SmallVectorImpl<SymbolRef>::iterator
+    N = C.generateNonFatalErrorNode(C.getState(), &Tag);
+    if (N) {
+      for (SmallVectorImpl<SymbolRef>::iterator
            I = Errors.begin(), E = Errors.end(); I != E; ++I) {
-      reportLeak(*I, N, C);
+        reportLeak(*I, N, C);
+      }
     }
   }
 

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/NSAutoreleasePoolChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/NSAutoreleasePoolChecker.cpp?rev=247859&r1=247858&r2=247859&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/NSAutoreleasePoolChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/NSAutoreleasePoolChecker.cpp Wed Sep 16 17:03:05 2015
@@ -62,7 +62,7 @@ void NSAutoreleasePoolChecker::checkPreO
     BT.reset(new BugType(this, "Use -drain instead of -release",
                          "API Upgrade (Apple)"));
 
-  ExplodedNode *N = C.addTransition();
+  ExplodedNode *N = C.generateNonFatalErrorNode();
   if (!N) {
     assert(0);
     return;

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/NoReturnFunctionChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/NoReturnFunctionChecker.cpp?rev=247859&r1=247858&r2=247859&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/NoReturnFunctionChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/NoReturnFunctionChecker.cpp Wed Sep 16 17:03:05 2015
@@ -81,7 +81,7 @@ void NoReturnFunctionChecker::checkPostC
   }
 
   if (BuildSinks)
-    C.generateSink();
+    C.generateSink(C.getState(), C.getPredecessor());
 }
 
 void NoReturnFunctionChecker::checkPostObjCMessage(const ObjCMethodCall &Msg,
@@ -90,7 +90,7 @@ void NoReturnFunctionChecker::checkPostO
   if (const ObjCMethodDecl *MD = Msg.getDecl()) {
     MD = MD->getCanonicalDecl();
     if (MD->hasAttr<AnalyzerNoReturnAttr>()) {
-      C.generateSink();
+      C.generateSink(C.getState(), C.getPredecessor());
       return;
     }
   }
@@ -136,7 +136,7 @@ void NoReturnFunctionChecker::checkPostO
   }
 
   // If we got here, it's one of the messages we care about.
-  C.generateSink();
+  C.generateSink(C.getState(), C.getPredecessor());
 }
 
 void ento::registerNoReturnFunctionChecker(CheckerManager &mgr) {

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/NonNullParamChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/NonNullParamChecker.cpp?rev=247859&r1=247858&r2=247859&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/NonNullParamChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/NonNullParamChecker.cpp Wed Sep 16 17:03:05 2015
@@ -143,7 +143,7 @@ void NonNullParamChecker::checkPreCall(c
       if (!stateNotNull) {
         // Generate an error node.  Check for a null node in case
         // we cache out.
-        if (ExplodedNode *errorNode = C.generateSink(stateNull)) {
+        if (ExplodedNode *errorNode = C.generateErrorNode(stateNull)) {
 
           std::unique_ptr<BugReport> R;
           if (haveAttrNonNull)
@@ -161,7 +161,7 @@ void NonNullParamChecker::checkPreCall(c
         // Always return.  Either we cached out or we just emitted an error.
         return;
       }
-      if (ExplodedNode *N = C.generateSink(stateNull)) {
+      if (ExplodedNode *N = C.generateSink(stateNull, C.getPredecessor())) {
         ImplicitNullDerefEvent event = {
             V, false, N, &C.getBugReporter(),
             /*IsDirectDereference=*/haveRefTypeParam};

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp?rev=247859&r1=247858&r2=247859&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp Wed Sep 16 17:03:05 2015
@@ -499,7 +499,9 @@ void NullabilityChecker::checkPreStmt(co
       Nullness == NullConstraint::IsNull &&
       StaticNullability == Nullability::Nonnull) {
     static CheckerProgramPointTag Tag(this, "NullReturnedFromNonnull");
-    ExplodedNode *N = C.generateSink(State, C.getPredecessor(), &Tag);
+    ExplodedNode *N = C.generateErrorNode(State, &Tag);
+    if (!N)
+      return;
     reportBugIfPreconditionHolds(ErrorKind::NilReturnedToNonnull, N, nullptr, C,
                                  RetExpr);
     return;
@@ -569,7 +571,9 @@ void NullabilityChecker::checkPreCall(co
     if (Filter.CheckNullPassedToNonnull && Nullness == NullConstraint::IsNull &&
         ArgStaticNullability != Nullability::Nonnull &&
         ParamNullability == Nullability::Nonnull) {
-      ExplodedNode *N = C.generateSink(State);
+      ExplodedNode *N = C.generateErrorNode(State);
+      if (!N)
+        return;
       reportBugIfPreconditionHolds(ErrorKind::NilPassedToNonnull, N, nullptr, C,
                                    ArgExpr);
       return;
@@ -891,7 +895,9 @@ void NullabilityChecker::checkBind(SVal
       ValNullability != Nullability::Nonnull &&
       LocNullability == Nullability::Nonnull) {
     static CheckerProgramPointTag Tag(this, "NullPassedToNonnull");
-    ExplodedNode *N = C.generateSink(State, C.getPredecessor(), &Tag);
+    ExplodedNode *N = C.generateErrorNode(State, &Tag);
+    if (!N)
+      return;
     reportBugIfPreconditionHolds(ErrorKind::NilAssignedToNonnull, N, nullptr, C,
                                  S);
     return;

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/ObjCAtSyncChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/ObjCAtSyncChecker.cpp?rev=247859&r1=247858&r2=247859&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/ObjCAtSyncChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/ObjCAtSyncChecker.cpp Wed Sep 16 17:03:05 2015
@@ -43,7 +43,7 @@ void ObjCAtSyncChecker::checkPreStmt(con
 
   // Uninitialized value used for the mutex?
   if (V.getAs<UndefinedVal>()) {
-    if (ExplodedNode *N = C.generateSink()) {
+    if (ExplodedNode *N = C.generateErrorNode()) {
       if (!BT_undef)
         BT_undef.reset(new BuiltinBug(this, "Uninitialized value used as mutex "
                                             "for @synchronized"));
@@ -66,7 +66,7 @@ void ObjCAtSyncChecker::checkPreStmt(con
     if (!notNullState) {
       // Generate an error node.  This isn't a sink since
       // a null mutex just means no synchronization occurs.
-      if (ExplodedNode *N = C.addTransition(nullState)) {
+      if (ExplodedNode *N = C.generateNonFatalErrorNode(nullState)) {
         if (!BT_null)
           BT_null.reset(new BuiltinBug(
               this, "Nil value used as mutex for @synchronized() "

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/ObjCContainersChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/ObjCContainersChecker.cpp?rev=247859&r1=247858&r2=247859&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/ObjCContainersChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/ObjCContainersChecker.cpp Wed Sep 16 17:03:05 2015
@@ -139,7 +139,7 @@ void ObjCContainersChecker::checkPreStmt
     ProgramStateRef StInBound = State->assumeInBound(Idx, *Size, true, T);
     ProgramStateRef StOutBound = State->assumeInBound(Idx, *Size, false, T);
     if (StOutBound && !StInBound) {
-      ExplodedNode *N = C.generateSink(StOutBound);
+      ExplodedNode *N = C.generateErrorNode(StOutBound);
       if (!N)
         return;
       initBugType();

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp?rev=247859&r1=247858&r2=247859&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp Wed Sep 16 17:03:05 2015
@@ -153,7 +153,7 @@ void ObjCSelfInitChecker::checkForInvali
     return;
 
   // Generate an error node.
-  ExplodedNode *N = C.generateSink();
+  ExplodedNode *N = C.generateErrorNode();
   if (!N)
     return;
 

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/PointerArithChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/PointerArithChecker.cpp?rev=247859&r1=247858&r2=247859&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/PointerArithChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/PointerArithChecker.cpp Wed Sep 16 17:03:05 2015
@@ -51,7 +51,7 @@ void PointerArithChecker::checkPreStmt(c
   if (isa<VarRegion>(LR) || isa<CodeTextRegion>(LR) ||
       isa<CompoundLiteralRegion>(LR)) {
 
-    if (ExplodedNode *N = C.addTransition()) {
+    if (ExplodedNode *N = C.generateNonFatalErrorNode()) {
       if (!BT)
         BT.reset(
             new BuiltinBug(this, "Dangerous pointer arithmetic",

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/PointerSubChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/PointerSubChecker.cpp?rev=247859&r1=247858&r2=247859&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/PointerSubChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/PointerSubChecker.cpp Wed Sep 16 17:03:05 2015
@@ -60,7 +60,7 @@ void PointerSubChecker::checkPreStmt(con
   if (isa<SymbolicRegion>(BaseLR) || isa<SymbolicRegion>(BaseRR))
     return;
 
-  if (ExplodedNode *N = C.addTransition()) {
+  if (ExplodedNode *N = C.generateNonFatalErrorNode()) {
     if (!BT)
       BT.reset(
           new BuiltinBug(this, "Pointer subtraction",

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp?rev=247859&r1=247858&r2=247859&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp Wed Sep 16 17:03:05 2015
@@ -142,7 +142,7 @@ void PthreadLockChecker::AcquireLock(Che
       if (!BT_doublelock)
         BT_doublelock.reset(new BugType(this, "Double locking",
                                         "Lock checker"));
-      ExplodedNode *N = C.generateSink();
+      ExplodedNode *N = C.generateErrorNode();
       if (!N)
         return;
       auto report = llvm::make_unique<BugReport>(
@@ -204,7 +204,7 @@ void PthreadLockChecker::ReleaseLock(Che
       if (!BT_doubleunlock)
         BT_doubleunlock.reset(new BugType(this, "Double unlocking",
                                           "Lock checker"));
-      ExplodedNode *N = C.generateSink();
+      ExplodedNode *N = C.generateErrorNode();
       if (!N)
         return;
       auto Report = llvm::make_unique<BugReport>(
@@ -227,7 +227,7 @@ void PthreadLockChecker::ReleaseLock(Che
     if (firstLockR != lockR) {
       if (!BT_lor)
         BT_lor.reset(new BugType(this, "Lock order reversal", "Lock checker"));
-      ExplodedNode *N = C.generateSink();
+      ExplodedNode *N = C.generateErrorNode();
       if (!N)
         return;
       auto report = llvm::make_unique<BugReport>(
@@ -272,7 +272,7 @@ void PthreadLockChecker::DestroyLock(Che
   if (!BT_destroylock)
     BT_destroylock.reset(new BugType(this, "Destroy invalid lock",
                                      "Lock checker"));
-  ExplodedNode *N = C.generateSink();
+  ExplodedNode *N = C.generateErrorNode();
   if (!N)
     return;
   auto Report = llvm::make_unique<BugReport>(*BT_destroylock, Message, N);
@@ -307,7 +307,7 @@ void PthreadLockChecker::InitLock(Checke
   if (!BT_initlock)
     BT_initlock.reset(new BugType(this, "Init invalid lock",
                                   "Lock checker"));
-  ExplodedNode *N = C.generateSink();
+  ExplodedNode *N = C.generateErrorNode();
   if (!N)
     return;
   auto Report = llvm::make_unique<BugReport>(*BT_initlock, Message, N);
@@ -320,7 +320,7 @@ void PthreadLockChecker::reportUseDestro
   if (!BT_destroylock)
     BT_destroylock.reset(new BugType(this, "Use destroyed lock",
                                      "Lock checker"));
-  ExplodedNode *N = C.generateSink();
+  ExplodedNode *N = C.generateErrorNode();
   if (!N)
     return;
   auto Report = llvm::make_unique<BugReport>(

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp?rev=247859&r1=247858&r2=247859&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp Wed Sep 16 17:03:05 2015
@@ -3306,7 +3306,7 @@ void RetainCountChecker::processNonLeakE
     if (RV->getIvarAccessHistory() != RefVal::IvarAccessHistory::None)
       return;
 
-  ExplodedNode *N = C.generateSink(St);
+  ExplodedNode *N = C.generateErrorNode(St);
   if (!N)
     return;
 

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/ReturnPointerRangeChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/ReturnPointerRangeChecker.cpp?rev=247859&r1=247858&r2=247859&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/ReturnPointerRangeChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/ReturnPointerRangeChecker.cpp Wed Sep 16 17:03:05 2015
@@ -62,7 +62,7 @@ void ReturnPointerRangeChecker::checkPre
   ProgramStateRef StInBound = state->assumeInBound(Idx, NumElements, true);
   ProgramStateRef StOutBound = state->assumeInBound(Idx, NumElements, false);
   if (StOutBound && !StInBound) {
-    ExplodedNode *N = C.generateSink(StOutBound);
+    ExplodedNode *N = C.generateErrorNode(StOutBound);
 
     if (!N)
       return;

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/ReturnUndefChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/ReturnUndefChecker.cpp?rev=247859&r1=247858&r2=247859&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/ReturnUndefChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/ReturnUndefChecker.cpp Wed Sep 16 17:03:05 2015
@@ -80,7 +80,7 @@ void ReturnUndefChecker::checkPreStmt(co
 
 static void emitBug(CheckerContext &C, BuiltinBug &BT, const Expr *RetE,
                     const Expr *TrackingE = nullptr) {
-  ExplodedNode *N = C.generateSink();
+  ExplodedNode *N = C.generateErrorNode();
   if (!N)
     return;
 

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/SimpleStreamChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/SimpleStreamChecker.cpp?rev=247859&r1=247858&r2=247859&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/SimpleStreamChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/SimpleStreamChecker.cpp Wed Sep 16 17:03:05 2015
@@ -200,7 +200,9 @@ void SimpleStreamChecker::checkDeadSymbo
       State = State->remove<StreamMap>(Sym);
   }
 
-  ExplodedNode *N = C.addTransition(State);
+  ExplodedNode *N = C.generateNonFatalErrorNode(State);
+  if (!N)
+    return;
   reportLeaks(LeakedStreams, C, N);
 }
 
@@ -208,7 +210,7 @@ void SimpleStreamChecker::reportDoubleCl
                                             const CallEvent &Call,
                                             CheckerContext &C) const {
   // We reached a bug, stop exploring the path here by generating a sink.
-  ExplodedNode *ErrNode = C.generateSink();
+  ExplodedNode *ErrNode = C.generateErrorNode();
   // If we've already reached this node on another path, return.
   if (!ErrNode)
     return;

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp?rev=247859&r1=247858&r2=247859&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp Wed Sep 16 17:03:05 2015
@@ -94,7 +94,7 @@ SourceRange StackAddrEscapeChecker::genN
 
 void StackAddrEscapeChecker::EmitStackError(CheckerContext &C, const MemRegion *R,
                                           const Expr *RetE) const {
-  ExplodedNode *N = C.generateSink();
+  ExplodedNode *N = C.generateErrorNode();
 
   if (!N)
     return;
@@ -211,7 +211,7 @@ void StackAddrEscapeChecker::checkEndFun
     return;
 
   // Generate an error node.
-  ExplodedNode *N = Ctx.addTransition(state);
+  ExplodedNode *N = Ctx.generateNonFatalErrorNode(state);
   if (!N)
     return;
 

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/StreamChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/StreamChecker.cpp?rev=247859&r1=247858&r2=247859&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/StreamChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/StreamChecker.cpp Wed Sep 16 17:03:05 2015
@@ -271,7 +271,7 @@ void StreamChecker::Fseek(CheckerContext
   if (x >= 0 && x <= 2)
     return;
 
-  if (ExplodedNode *N = C.addTransition(state)) {
+  if (ExplodedNode *N = C.generateNonFatalErrorNode(state)) {
     if (!BT_illegalwhence)
       BT_illegalwhence.reset(
           new BuiltinBug(this, "Illegal whence argument",
@@ -349,7 +349,7 @@ ProgramStateRef StreamChecker::CheckNull
   std::tie(stateNotNull, stateNull) = CM.assumeDual(state, *DV);
 
   if (!stateNotNull && stateNull) {
-    if (ExplodedNode *N = C.generateSink(stateNull)) {
+    if (ExplodedNode *N = C.generateErrorNode(stateNull)) {
       if (!BT_nullfp)
         BT_nullfp.reset(new BuiltinBug(this, "NULL stream pointer",
                                        "Stream pointer might be NULL."));
@@ -378,7 +378,7 @@ ProgramStateRef StreamChecker::CheckDoub
   // Check: Double close a File Descriptor could cause undefined behaviour.
   // Conforming to man-pages
   if (SS->isClosed()) {
-    ExplodedNode *N = C.generateSink();
+    ExplodedNode *N = C.generateErrorNode();
     if (N) {
       if (!BT_doubleclose)
         BT_doubleclose.reset(new BuiltinBug(
@@ -406,7 +406,7 @@ void StreamChecker::checkDeadSymbols(Sym
       continue;
 
     if (SS->isOpened()) {
-      ExplodedNode *N = C.generateSink();
+      ExplodedNode *N = C.generateErrorNode();
       if (N) {
         if (!BT_ResourceLeak)
           BT_ResourceLeak.reset(new BuiltinBug(

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/TaintTesterChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/TaintTesterChecker.cpp?rev=247859&r1=247858&r2=247859&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/TaintTesterChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/TaintTesterChecker.cpp Wed Sep 16 17:03:05 2015
@@ -48,7 +48,7 @@ void TaintTesterChecker::checkPostStmt(c
     return;
 
   if (State->isTainted(E, C.getLocationContext())) {
-    if (ExplodedNode *N = C.addTransition()) {
+    if (ExplodedNode *N = C.generateNonFatalErrorNode()) {
       initBugType();
       auto report = llvm::make_unique<BugReport>(*BT, "tainted",N);
       report->addRange(E->getSourceRange());

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/TestAfterDivZeroChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/TestAfterDivZeroChecker.cpp?rev=247859&r1=247858&r2=247859&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/TestAfterDivZeroChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/TestAfterDivZeroChecker.cpp Wed Sep 16 17:03:05 2015
@@ -167,7 +167,7 @@ bool TestAfterDivZeroChecker::hasDivZero
 }
 
 void TestAfterDivZeroChecker::reportBug(SVal Val, CheckerContext &C) const {
-  if (ExplodedNode *N = C.generateSink(C.getState())) {
+  if (ExplodedNode *N = C.generateErrorNode(C.getState())) {
     if (!DivZeroBug)
       DivZeroBug.reset(new BuiltinBug(this, "Division by zero"));
 

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/UndefBranchChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/UndefBranchChecker.cpp?rev=247859&r1=247858&r2=247859&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/UndefBranchChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/UndefBranchChecker.cpp Wed Sep 16 17:03:05 2015
@@ -62,7 +62,7 @@ void UndefBranchChecker::checkBranchCond
   if (X.isUndef()) {
     // Generate a sink node, which implicitly marks both outgoing branches as
     // infeasible.
-    ExplodedNode *N = Ctx.generateSink();
+    ExplodedNode *N = Ctx.generateErrorNode();
     if (N) {
       if (!BT)
         BT.reset(new BuiltinBug(

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/UndefCapturedBlockVarChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/UndefCapturedBlockVarChecker.cpp?rev=247859&r1=247858&r2=247859&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/UndefCapturedBlockVarChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/UndefCapturedBlockVarChecker.cpp Wed Sep 16 17:03:05 2015
@@ -74,7 +74,7 @@ UndefCapturedBlockVarChecker::checkPostS
     // Get the VarRegion associated with VD in the local stack frame.
     if (Optional<UndefinedVal> V =
           state->getSVal(I.getOriginalRegion()).getAs<UndefinedVal>()) {
-      if (ExplodedNode *N = C.generateSink()) {
+      if (ExplodedNode *N = C.generateErrorNode()) {
         if (!BT)
           BT.reset(
               new BuiltinBug(this, "uninitialized variable captured by block"));

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp?rev=247859&r1=247858&r2=247859&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp Wed Sep 16 17:03:05 2015
@@ -50,7 +50,7 @@ void UndefResultChecker::checkPostStmt(c
         return;
 
     // Generate an error node.
-    ExplodedNode *N = C.generateSink();
+    ExplodedNode *N = C.generateErrorNode();
     if (!N)
       return;
 

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/UndefinedArraySubscriptChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/UndefinedArraySubscriptChecker.cpp?rev=247859&r1=247858&r2=247859&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/UndefinedArraySubscriptChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/UndefinedArraySubscriptChecker.cpp Wed Sep 16 17:03:05 2015
@@ -46,7 +46,7 @@ UndefinedArraySubscriptChecker::checkPre
     if (Ctor->isDefaulted())
       return;
 
-  ExplodedNode *N = C.generateSink();
+  ExplodedNode *N = C.generateErrorNode();
   if (!N)
     return;
   if (!BT)

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/UndefinedAssignmentChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/UndefinedAssignmentChecker.cpp?rev=247859&r1=247858&r2=247859&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/UndefinedAssignmentChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/UndefinedAssignmentChecker.cpp Wed Sep 16 17:03:05 2015
@@ -46,7 +46,7 @@ void UndefinedAssignmentChecker::checkBi
     if (C.getCalleeName(EnclosingFunctionDecl) == "swap")
       return;
 
-  ExplodedNode *N = C.generateSink();
+  ExplodedNode *N = C.generateErrorNode();
 
   if (!N)
     return;

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp?rev=247859&r1=247858&r2=247859&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp Wed Sep 16 17:03:05 2015
@@ -77,7 +77,7 @@ void UnixAPIChecker::ReportOpenBug(Check
                                    ProgramStateRef State,
                                    const char *Msg,
                                    SourceRange SR) const {
-  ExplodedNode *N = C.generateSink(State);
+  ExplodedNode *N = C.generateErrorNode(State);
   if (!N)
     return;
 
@@ -182,7 +182,7 @@ void UnixAPIChecker::CheckPthreadOnce(Ch
   if (!R || !isa<StackSpaceRegion>(R->getMemorySpace()))
     return;
 
-  ExplodedNode *N = C.generateSink(state);
+  ExplodedNode *N = C.generateErrorNode(state);
   if (!N)
     return;
 
@@ -231,7 +231,7 @@ bool UnixAPIChecker::ReportZeroByteAlloc
                                               ProgramStateRef falseState,
                                               const Expr *arg,
                                               const char *fn_name) const {
-  ExplodedNode *N = C.generateSink(falseState);
+  ExplodedNode *N = C.generateErrorNode(falseState);
   if (!N)
     return false;
 

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp?rev=247859&r1=247858&r2=247859&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp Wed Sep 16 17:03:05 2015
@@ -46,7 +46,7 @@ void VLASizeChecker::reportBug(VLASize_K
                                ProgramStateRef State,
                                CheckerContext &C) const {
   // Generate an error node.
-  ExplodedNode *N = C.generateSink(State);
+  ExplodedNode *N = C.generateErrorNode(State);
   if (!N)
     return;
 

Modified: cfe/trunk/lib/StaticAnalyzer/Core/BugReporter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/BugReporter.cpp?rev=247859&r1=247858&r2=247859&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/BugReporter.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/BugReporter.cpp Wed Sep 16 17:03:05 2015
@@ -3224,6 +3224,11 @@ void BugReporter::Register(BugType *BT)
 
 void BugReporter::emitReport(std::unique_ptr<BugReport> R) {
   if (const ExplodedNode *E = R->getErrorNode()) {
+    // An error node must either be a sink or have a tag, otherwise
+    // it could get reclaimed before the path diagnostic is created.
+    assert((E->isSink() || E->getLocation().getTag()) &&
+            "Error node must either be a sink or have a tag");
+
     const AnalysisDeclContext *DeclCtx =
         E->getLocationContext()->getAnalysisDeclContext();
     // The source of autosynthesized body can be handcrafted AST or a model

Added: cfe/trunk/test/Analysis/PR24184.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/PR24184.cpp?rev=247859&view=auto
==============================================================================
--- cfe/trunk/test/Analysis/PR24184.cpp (added)
+++ cfe/trunk/test/Analysis/PR24184.cpp Wed Sep 16 17:03:05 2015
@@ -0,0 +1,97 @@
+// RUN: %clang_cc1 -w -analyze -analyzer-eagerly-assume -fcxx-exceptions -analyzer-checker=core -analyzer-checker=alpha.core.PointerArithm,alpha.core.CastToStruct -analyzer-max-loop 64 -verify %s
+// RUN: %clang_cc1 -w -analyze -analyzer-checker=core -analyzer-checker=cplusplus -fcxx-exceptions -analyzer-checker alpha.core.PointerArithm,alpha.core.CastToStruct -analyzer-max-loop 63 -verify %s
+
+// These tests used to hit an assertion in the bug report. Test case from http://llvm.org/PR24184.
+typedef struct {
+  int cbData;
+  unsigned pbData;
+} CRYPT_DATA_BLOB;
+
+typedef enum { DT_NONCE_FIXED } DATA_TYPE;
+int a;
+typedef int *vcreate_t(int *, DATA_TYPE, int, int);
+void fn1(unsigned, unsigned) {
+  char b = 0;
+  for (; 1; a++, &b + a * 0) // expected-warning{{Pointer arithmetic done on non-array variables means reliance on memory layout, which is dangerous}}
+    ;
+}
+
+vcreate_t fn2;
+struct A {
+  CRYPT_DATA_BLOB value;
+  int m_fn1() {
+    int c;
+    value.pbData == 0;
+    fn1(0, 0);
+  }
+};
+struct B {
+  A IkeHashAlg;
+  A IkeGType;
+  A NoncePhase1_r;
+};
+class C {
+  int m_fn2(B *);
+  void m_fn3(B *, int, int, int);
+};
+int C::m_fn2(B *p1) {
+  int *d;
+  int e = p1->IkeHashAlg.m_fn1();
+  unsigned f = p1->IkeGType.m_fn1(), h;
+  int g;
+  d = fn2(0, DT_NONCE_FIXED, (char)0, p1->NoncePhase1_r.value.cbData);
+  h = 0 | 0;
+  m_fn3(p1, 0, 0, 0);
+}
+
+// case 2:
+typedef struct {
+  int cbData;
+  unsigned char *pbData;
+} CRYPT_DATA_BLOB_1;
+typedef unsigned uint32_t;
+void fn1_1(void *p1, const void *p2) { p1 != p2; }
+
+void fn2_1(uint32_t *p1, unsigned char *p2, uint32_t p3) {
+  unsigned i = 0;
+  for (0; i < p3; i++)
+    fn1_1(p1 + i, p2 + i * 0);    // expected-warning{{Pointer arithmetic done on non-array variables means reliance on memory layout, which is dangerous}}
+}
+
+struct A_1 {
+  CRYPT_DATA_BLOB_1 value;
+  uint32_t m_fn1() {
+    uint32_t a;
+    if (value.pbData)
+      fn2_1(&a, value.pbData, value.cbData);
+    return 0;
+  }
+};
+struct {
+  A_1 HashAlgId;
+} *b;
+void fn3() {
+  uint32_t c, d;
+  d = b->HashAlgId.m_fn1();
+  d << 0 | 0 | 0;
+  c = 0;
+  0 | 1 << 0 | 0 && b;
+}
+
+// case 3:
+struct ST {
+  char c;
+};
+char *p;
+int foo1(ST);
+int foo2() {
+  ST *p1 = (ST *)(p);      // expected-warning{{Casting a non-structure type to a structure type and accessing a field can lead to memory access errors or data corruption}}
+  while (p1->c & 0x0F || p1->c & 0x07)
+    p1 = p1 + foo1(*p1);
+}
+
+int foo3(int *node) {
+  int i = foo2();
+  if (i)
+    return foo2();
+}

Modified: cfe/trunk/test/Analysis/malloc.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/malloc.c?rev=247859&r1=247858&r2=247859&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/malloc.c (original)
+++ cfe/trunk/test/Analysis/malloc.c Wed Sep 16 17:03:05 2015
@@ -1386,7 +1386,9 @@ char* reallocButNoMalloc(struct HasPtr *
   int *s;
   char *b = realloc(a->p, size);
   char *m = realloc(a->p, size); // expected-warning {{Attempt to free released memory}}
-  return a->p;
+  // We don't expect a use-after-free for a->P here because the warning above
+  // is a sink.
+  return a->p; // no-warning
 }
 
 // We should not warn in this case since the caller will presumably free a->p in all cases.




More information about the cfe-commits mailing list