Index: clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp =================================================================== --- clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp +++ clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp @@ -1601,9 +1601,6 @@ AnalyzerOptions &Options = N->getState()->getAnalysisManager().options; if (!Options.ShouldSuppressInlinedDefensiveChecks) IsSatisfied = true; - - assert(N->getState()->isNull(V).isConstrainedTrue() && - "The visitor only tracks the cases where V is constrained to 0"); } void SuppressInlineDefensiveChecksVisitor::Profile( @@ -1634,13 +1631,12 @@ // Check if in the previous state it was feasible for this value // to *not* be null. - if (!Pred->getState()->isNull(V).isConstrainedTrue()) { + if (!Pred->getState()->isNull(V).isConstrainedTrue() && + Succ->getState()->isNull(V).isConstrainedTrue()) { IsSatisfied = true; - assert(Succ->getState()->isNull(V).isConstrainedTrue()); - // Check if this is inlined defensive checks. - const LocationContext *CurLC =Succ->getLocationContext(); + const LocationContext *CurLC = Succ->getLocationContext(); const LocationContext *ReportLC = BR.getErrorNode()->getLocationContext(); if (CurLC != ReportLC && !CurLC->isParentOf(ReportLC)) { BR.markInvalid("Suppress IDC", CurLC); @@ -2007,11 +2003,16 @@ // Add visitor, which will suppress inline defensive checks. if (auto DV = V.getAs()) - if (!DV->isZeroConstant() && LVState->isNull(*DV).isConstrainedTrue() && - EnableNullFPSuppression) + if (!DV->isZeroConstant() && EnableNullFPSuppression) { + // Note that LVNode may be too late; the lvalue may have been computed + // before the inlined call was evaluated. InputNode may as well be + // too late, because the symbol is already dead; this, however, + // is fine because we can still find the node in which it + // collapsed to null previously. report.addVisitor( - std::make_unique(*DV, - LVNode)); + std::make_unique( + *DV, InputNode)); + } if (auto KV = V.getAs()) report.addVisitor(std::make_unique( Index: clang/test/Analysis/NSContainers.m =================================================================== --- clang/test/Analysis/NSContainers.m +++ clang/test/Analysis/NSContainers.m @@ -2,6 +2,8 @@ void clang_analyzer_eval(int); +#define nil ((id)0) + typedef unsigned long NSUInteger; typedef signed char BOOL; typedef struct _NSZone NSZone; @@ -310,3 +312,14 @@ // here either. [subviews addObject:view]; // no-warning } + +NSString *getStringFromString(NSString *string) { + if (!string) + return nil; + return @"New String"; +} +void testInlinedDefensiveCheck(NSMutableDictionary *dict, id obj) { + // The check in getStringFromString() is not a good indication + // that 'obj' can be nil in this context. + dict[obj] = getStringFromString(obj); // no-warning +}