diff options
author | Jordan Rose <jordan_rose@apple.com> | 2012-12-07 19:56:29 +0000 |
---|---|---|
committer | Jordan Rose <jordan_rose@apple.com> | 2012-12-07 19:56:29 +0000 |
commit | afa7cae15b117c4b75794c6c32424953d94b4359 (patch) | |
tree | 4c4dc8bb7e558f468cf98285eeff9ff72d6497e2 /lib/StaticAnalyzer/Core/BugReporter.cpp | |
parent | 18f860ee6cc43c8fc80834073b097eb5c02b22cf (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.cpp | 68 |
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; |