[cfe-commits] r166728 - in /cfe/trunk: include/clang/StaticAnalyzer/Core/BugReporter/ lib/StaticAnalyzer/Core/ test/Analysis/ test/Analysis/diagnostics/ test/Analysis/inlining/
Jordan Rose
jordan_rose at apple.com
Thu Oct 25 15:59:19 PDT 2012
On Oct 25, 2012, at 15:07 , Ted Kremenek <kremenek at apple.com> wrote:
> Author: kremenek
> Date: Thu Oct 25 17:07:10 2012
> New Revision: 166728
>
> URL: http://llvm.org/viewvc/llvm-project?rev=166728&view=rev
> Log:
> TrackConstraintBRVisitor and ConditionBRVisitor can emit similar
> path notes for cases where a value may be assumed to be null, etc.
> Instead of having redundant diagnostics, do a pass over the generated
> PathDiagnostic pieces and remove notes from TrackConstraintBRVisitor
> that are already covered by ConditionBRVisitor, whose notes tend
> to be better.
>
> Fixes <rdar://problem/12252783>
>
> Modified:
> cfe/trunk/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h
> cfe/trunk/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h
> cfe/trunk/lib/StaticAnalyzer/Core/BugReporter.cpp
> cfe/trunk/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
> cfe/trunk/test/Analysis/conditional-operator-path-notes.c
> cfe/trunk/test/Analysis/diagnostics/deref-track-symbolic-region.cpp
> cfe/trunk/test/Analysis/inline-plist.c
> cfe/trunk/test/Analysis/inlining/path-notes.c
> cfe/trunk/test/Analysis/method-call-path-notes.cpp
> cfe/trunk/test/Analysis/null-deref-path-notes.m
> cfe/trunk/test/Analysis/plist-output-alternate.m
> cfe/trunk/test/Analysis/plist-output.m
> cfe/trunk/test/Analysis/retain-release-path-notes.m
>
> Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h?rev=166728&r1=166727&r2=166728&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h (original)
> +++ cfe/trunk/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h Thu Oct 25 17:07:10 2012
> @@ -141,6 +141,10 @@
>
> void Profile(llvm::FoldingSetNodeID &ID) const;
>
> + /// Return the tag associated with this visitor. This tag will be used
> + /// to make all PathDiagnosticPieces created by this visitor.
> + static const char *getTag();
> +
> PathDiagnosticPiece *VisitNode(const ExplodedNode *N,
> const ExplodedNode *PrevN,
> BugReporterContext &BRC,
> @@ -170,6 +174,9 @@
> ID.AddPointer(&x);
> }
>
> + /// Return the tag associated with this visitor. This tag will be used
> + /// to make all PathDiagnosticPieces created by this visitor.
> + static const char *getTag();
>
> virtual PathDiagnosticPiece *VisitNode(const ExplodedNode *N,
> const ExplodedNode *Prev,
>
> Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h?rev=166728&r1=166727&r2=166728&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h (original)
> +++ cfe/trunk/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h Thu Oct 25 17:07:10 2012
> @@ -320,6 +320,13 @@
> const std::string str;
> const Kind kind;
> const DisplayHint Hint;
> +
> + /// A constant string that can be used to tag the PathDiagnosticPiece,
> + /// typically with the identification of the creator. The actual pointer
> + /// value is meant to be an identifier; the string itself is useful for
> + /// debugging.
> + StringRef Tag;
> +
> std::vector<SourceRange> ranges;
>
> PathDiagnosticPiece() LLVM_DELETED_FUNCTION;
> @@ -336,6 +343,16 @@
>
> llvm::StringRef getString() const { return str; }
>
> + /// Tag this PathDiagnosticPiece with the given C-string.
> + void setTag(const char *tag) { Tag = tag; }
> +
> + /// Return the opaque tag (if any) on the PathDiagnosticPiece.
> + const void *getTag() const { return Tag.data(); }
> +
> + /// Return the string representation of the tag. This is useful
> + /// for debugging.
> + StringRef getTagStr() const { return Tag; }
> +
> /// getDisplayHint - Return a hint indicating where the diagnostic should
> /// be displayed by the PathDiagnosticConsumer.
> DisplayHint getDisplayHint() const { return Hint; }
>
> Modified: cfe/trunk/lib/StaticAnalyzer/Core/BugReporter.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/BugReporter.cpp?rev=166728&r1=166727&r2=166728&view=diff
> ==============================================================================
> --- cfe/trunk/lib/StaticAnalyzer/Core/BugReporter.cpp (original)
> +++ cfe/trunk/lib/StaticAnalyzer/Core/BugReporter.cpp Thu Oct 25 17:07:10 2012
> @@ -118,6 +118,68 @@
> // Diagnostic cleanup.
> //===----------------------------------------------------------------------===//
>
> +static PathDiagnosticEventPiece *
> +eventsDescribeSameCondition(PathDiagnosticEventPiece *X,
> + PathDiagnosticEventPiece *Y) {
> + // Prefer diagnostics that come from ConditionBRVisitor over
> + // those that came from TrackConstraintBRVisitor.
> + const void *tagPreferred = ConditionBRVisitor::getTag();
> + const void *tagLesser = TrackConstraintBRVisitor::getTag();
> +
> + if (X->getLocation() != Y->getLocation())
> + return 0;
> +
> + if (X->getTag() == tagPreferred && Y->getTag() == tagLesser)
> + return X;
> +
> + if (Y->getTag() == tagPreferred && X->getTag() == tagLesser)
> + return Y;
> +
> + return 0;
> +}
> +
> +static void RemoveRedundantMsgs(PathPieces &path) {
New LLVM coding conventions would have this be lowerCamelCase.
> + unsigned N = path.size();
> + if (N < 2)
> + return;
> + for (unsigned i = 0; i < N; ++i) {
I would appreciate a comment reminding maintainers NOT to switch this to an iterator-based loop, since not only is PathPieces modified during the loop, but the path never actually "reaches the end" (since things get pushed on the back).
> + IntrusiveRefCntPtr<PathDiagnosticPiece> piece(path.front());
> + path.pop_front();
> +
> + switch (piece->getKind()) {
> + case clang::ento::PathDiagnosticPiece::Call:
> + RemoveRedundantMsgs(cast<PathDiagnosticCallPiece>(piece)->path);
> + break;
> + case clang::ento::PathDiagnosticPiece::Macro:
> + RemoveRedundantMsgs(cast<PathDiagnosticMacroPiece>(piece)->subPieces);
> + break;
> + case clang::ento::PathDiagnosticPiece::ControlFlow:
> + break;
> + case clang::ento::PathDiagnosticPiece::Event: {
> + if (i == N-1)
> + break;
> +
> + if (PathDiagnosticEventPiece *nextEvent =
> + dyn_cast<PathDiagnosticEventPiece>(path.front().getPtr())) {
> + PathDiagnosticEventPiece *event =
> + cast<PathDiagnosticEventPiece>(piece);
> + // Check to see if we should keep one of the two pieces. If we
> + // come up with a preference, record which piece to keep, and consume
> + // another piece from the path.
> + if (PathDiagnosticEventPiece *pieceToKeep =
> + eventsDescribeSameCondition(event, nextEvent)) {
> + piece = pieceToKeep;
> + path.pop_front();
> + ++i;
> + }
> + }
> + break;
> + }
> + }
> + path.push_back(piece);
> + }
> +}
> +
> /// Recursively scan through a path and prune out calls and macros pieces
> /// that aren't needed. Return true if afterwards the path contains
> /// "interesting stuff" which means it should be pruned from the parent path.
> @@ -2016,10 +2078,16 @@
> } while(finalReportConfigToken != originalReportConfigToken);
>
> // Finally, prune the diagnostic path of uninteresting stuff.
> - if (!PD.path.empty() && R->shouldPrunePath()) {
> - bool hasSomethingInteresting = RemoveUneededCalls(PD.getMutablePieces(), R);
> - assert(hasSomethingInteresting);
> - (void) hasSomethingInteresting;
> + if (!PD.path.empty()) {
> + // Remove messages that are basically the same.
> + RemoveRedundantMsgs(PD.getMutablePieces());
> +
> + if (R->shouldPrunePath()) {
> + bool hasSomethingInteresting = RemoveUneededCalls(PD.getMutablePieces(),
> + R);
> + assert(hasSomethingInteresting);
> + (void) hasSomethingInteresting;
> + }
It's probably cheaper to do this in the other order.
> }
>
> return true;
More information about the cfe-commits
mailing list