aboutsummaryrefslogtreecommitdiff
path: root/lib/StaticAnalyzer/Core/BugReporter.cpp
diff options
context:
space:
mode:
authorJordan Rose <jordan_rose@apple.com>2012-12-07 19:56:29 +0000
committerJordan Rose <jordan_rose@apple.com>2012-12-07 19:56:29 +0000
commitafa7cae15b117c4b75794c6c32424953d94b4359 (patch)
tree4c4dc8bb7e558f468cf98285eeff9ff72d6497e2 /lib/StaticAnalyzer/Core/BugReporter.cpp
parent18f860ee6cc43c8fc80834073b097eb5c02b22cf (diff)
[analyzer] Fix r168019 to work with unpruned paths as well.
This is the case where the analyzer tries to print out source locations for code within a synthesized function body, which of course does not have a valid source location. The previous fix attempted to do this during diagnostic path pruning, but some diagnostics have pruning disabled, and so any diagnostic with a path that goes through a synthesized body will either hit an assertion or emit invalid output. <rdar://problem/12657843> (again) git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@169631 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/StaticAnalyzer/Core/BugReporter.cpp')
-rw-r--r--lib/StaticAnalyzer/Core/BugReporter.cpp68
1 files changed, 44 insertions, 24 deletions
diff --git a/lib/StaticAnalyzer/Core/BugReporter.cpp b/lib/StaticAnalyzer/Core/BugReporter.cpp
index bc5e7ddc64..d5e5f05c48 100644
--- a/lib/StaticAnalyzer/Core/BugReporter.cpp
+++ b/lib/StaticAnalyzer/Core/BugReporter.cpp
@@ -191,9 +191,8 @@ static void removeRedundantMsgs(PathPieces &path) {
/// 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.
-bool BugReporter::RemoveUneededCalls(PathPieces &pieces, BugReport *R,
- PathDiagnosticLocation *LastCallLocation) {
+/// "interesting stuff" which means it shouldn't be pruned from the parent path.
+bool BugReporter::RemoveUnneededCalls(PathPieces &pieces, BugReport *R) {
bool containsSomethingInteresting = false;
const unsigned N = pieces.size();
@@ -203,7 +202,9 @@ bool BugReporter::RemoveUneededCalls(PathPieces &pieces, BugReport *R,
IntrusiveRefCntPtr<PathDiagnosticPiece> piece(pieces.front());
pieces.pop_front();
- // Throw away pieces with invalid locations.
+ // Throw away pieces with invalid locations. Note that we can't throw away
+ // calls just yet because they might have something interesting inside them.
+ // If so, their locations will be adjusted as necessary later.
if (piece->getKind() != PathDiagnosticPiece::Call &&
piece->getLocation().asLocation().isInvalid())
continue;
@@ -218,23 +219,7 @@ bool BugReporter::RemoveUneededCalls(PathPieces &pieces, BugReport *R,
break;
}
- if (LastCallLocation) {
- if (!call->callEnter.asLocation().isValid())
- call->callEnter = *LastCallLocation;
- if (!call->callReturn.asLocation().isValid())
- call->callReturn = *LastCallLocation;
- }
-
- // Recursively clean out the subclass. Keep this call around if
- // it contains any informative diagnostics.
- PathDiagnosticLocation *ThisCallLocation;
- if (call->callEnterWithin.asLocation().isValid())
- ThisCallLocation = &call->callEnterWithin;
- else
- ThisCallLocation = &call->callEnter;
-
- assert(ThisCallLocation && "Outermost call has an invalid location");
- if (!RemoveUneededCalls(call->path, R, ThisCallLocation))
+ if (!RemoveUnneededCalls(call->path, R))
continue;
containsSomethingInteresting = true;
@@ -242,7 +227,7 @@ bool BugReporter::RemoveUneededCalls(PathPieces &pieces, BugReport *R,
}
case PathDiagnosticPiece::Macro: {
PathDiagnosticMacroPiece *macro = cast<PathDiagnosticMacroPiece>(piece);
- if (!RemoveUneededCalls(macro->subPieces, R))
+ if (!RemoveUnneededCalls(macro->subPieces, R))
continue;
containsSomethingInteresting = true;
break;
@@ -265,6 +250,39 @@ bool BugReporter::RemoveUneededCalls(PathPieces &pieces, BugReport *R,
return containsSomethingInteresting;
}
+/// Recursively scan through a path and make sure that all call pieces have
+/// valid locations. Note that all other pieces with invalid locations should
+/// have already been pruned out.
+static void adjustCallLocations(PathPieces &Pieces,
+ PathDiagnosticLocation *LastCallLocation = 0) {
+ for (PathPieces::iterator I = Pieces.begin(), E = Pieces.end(); I != E; ++I) {
+ PathDiagnosticCallPiece *Call = dyn_cast<PathDiagnosticCallPiece>(*I);
+
+ if (!Call) {
+ assert((*I)->getLocation().asLocation().isValid());
+ continue;
+ }
+
+ if (LastCallLocation) {
+ if (!Call->callEnter.asLocation().isValid())
+ Call->callEnter = *LastCallLocation;
+ if (!Call->callReturn.asLocation().isValid())
+ Call->callReturn = *LastCallLocation;
+ }
+
+ // Recursively clean out the subclass. Keep this call around if
+ // it contains any informative diagnostics.
+ PathDiagnosticLocation *ThisCallLocation;
+ if (Call->callEnterWithin.asLocation().isValid())
+ ThisCallLocation = &Call->callEnterWithin;
+ else
+ ThisCallLocation = &Call->callEnter;
+
+ assert(ThisCallLocation && "Outermost call has an invalid location");
+ adjustCallLocations(Call->path, ThisCallLocation);
+ }
+}
+
//===----------------------------------------------------------------------===//
// PathDiagnosticBuilder and its associated routines and helper objects.
//===----------------------------------------------------------------------===//
@@ -2102,11 +2120,13 @@ bool GRBugReporter::generatePathDiagnostic(PathDiagnostic& PD,
removeRedundantMsgs(PD.getMutablePieces());
if (R->shouldPrunePath()) {
- bool hasSomethingInteresting = RemoveUneededCalls(PD.getMutablePieces(),
- R);
+ bool hasSomethingInteresting = RemoveUnneededCalls(PD.getMutablePieces(),
+ R);
assert(hasSomethingInteresting);
(void) hasSomethingInteresting;
}
+
+ adjustCallLocations(PD.getMutablePieces());
}
return true;