diff --git a/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp b/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp --- a/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp +++ b/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp @@ -452,29 +452,8 @@ CallEventRef<> Call = BR.getStateManager().getCallEventManager().getCaller(SCtx, State); - // Optimistically suppress uninitialized value bugs that result - // from system headers having a chance to initialize the value - // but failing to do so. It's too unlikely a system header's fault. - // It's much more likely a situation in which the function has a failure - // mode that the user decided not to check. If we want to hunt such - // omitted checks, we should provide an explicit function-specific note - // describing the precondition under which the function isn't supposed to - // initialize its out-parameter, and additionally check that such - // precondition can actually be fulfilled on the current path. - if (Call->isInSystemHeader()) { - // We make an exception for system header functions that have no branches. - // Such functions unconditionally fail to initialize the variable. - // If they call other functions that have more paths within them, - // this suppression would still apply when we visit these inner functions. - // One common example of a standard function that doesn't ever initialize - // its out parameter is operator placement new; it's up to the follow-up - // constructor (if any) to initialize the memory. - if (!N->getStackFrame()->getCFG()->isLinear()) { - static int i = 0; - R.markInvalid(&i, nullptr); - } + if (Call->isInSystemHeader()) return nullptr; - } if (const auto *MC = dyn_cast(Call)) { // If we failed to construct a piece for self, we still want to check @@ -492,6 +471,70 @@ return maybeEmitNoteForParameters(R, *Call, N); } +//===----------------------------------------------------------------------===// +// Implementation of SuppressSystemHeaderWarningVistor. +//===----------------------------------------------------------------------===// + +// This visitor suppresses warnings coming from inlined system +// headers functions when we exit the call that have no branches. +// This is a very primitive visitor. It flat-out suppresses every report that +// have a node that matches all the conditions above. +// It should be used carefully! +// +// A good example for the usage of this visitor is when we want to suppress +// warnings when a system header function does not initialize their arguments. +// It's too unlikely a system header's fault. +// It's much more likely a situation in which the function has a failure +// mode that the user decided not to check. If we want to hunt such +// omitted checks, we should provide an explicit function-specific note +// describing the precondition under which the function isn't supposed to +// initialize its out-parameter, and additionally check that such +// precondition can actually be fulfilled on the current path. +// +// System header functions that have no branches unconditionally fail to +// initialize the variable. +// If they call other functions that have more paths within them, +// this suppression would still apply when we visit these inner functions. +// One common example of a standard function that doesn't ever initialize +// its out parameter is operator placement new; it's up to the follow-up +// constructor (if any) to initialize the memory +namespace { +class SuppressSystemHeaderWarningVisitor : public BugReporterVisitor { +public: + virtual PathDiagnosticPieceRef VisitNode(const ExplodedNode *, + BugReporterContext &, + PathSensitiveBugReport &) override; + void Profile(llvm::FoldingSetNodeID &ID) const override { + static int Tag = 0; + ID.AddPointer(&Tag); + } +}; +} // namespace + +PathDiagnosticPieceRef +SuppressSystemHeaderWarningVisitor::VisitNode(const ExplodedNode *Succ, + BugReporterContext &BRC, + PathSensitiveBugReport &BR) { + const LocationContext *Ctx = Succ->getLocationContext(); + const StackFrameContext *SCtx = Ctx->getStackFrame(); + ProgramStateRef State = Succ->getState(); + auto CallExitLoc = Succ->getLocationAs(); + + if (!CallExitLoc) + return nullptr; + + CallEventRef<> Call = + BRC.getStateManager().getCallEventManager().getCaller(SCtx, State); + + if (Call->isInSystemHeader()) { + if (!Succ->getStackFrame()->getCFG()->isLinear()) { + static int i = 0; + BR.markInvalid(&i, nullptr); + } + } + return nullptr; +} + //===----------------------------------------------------------------------===// // Implementation of NoStoreFuncVisitor. //===----------------------------------------------------------------------===// @@ -2350,7 +2393,7 @@ // Mark both the variable region and its contents as interesting. SVal V = LVState->getRawSVal(loc::MemRegionVal(R)); Report.addVisitor(cast(R), Opts.Kind); - + Report.addVisitor(); // When we got here, we do have something to track, and we will // interrupt. Result.FoundSomethingToTrack = true;