From: Ted Kremenek Date: Wed, 8 May 2013 01:15:24 +0000 (+0000) Subject: [analyzer; alternate edges] insert an extra edge for 'for' statements to conditions. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=aecda966174516c0ac7c05ceb40e88fc99bcf27c;p=clang [analyzer; alternate edges] insert an extra edge for 'for' statements to conditions. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@181385 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/StaticAnalyzer/Core/BugReporter.cpp b/lib/StaticAnalyzer/Core/BugReporter.cpp index ccfc5f7386..41ea0a4e88 100644 --- a/lib/StaticAnalyzer/Core/BugReporter.cpp +++ b/lib/StaticAnalyzer/Core/BugReporter.cpp @@ -1983,6 +1983,89 @@ static bool optimizeEdges(PathPieces &path, SourceManager &SM, return hasChanges; } +static void adjustLoopEdges(PathPieces &pieces, LocationContextMap &LCM, + SourceManager &SM) { + // Retrieve the parent map for this path. + const LocationContext *LC = LCM[&pieces]; + ParentMap &PM = LC->getParentMap(); + PathPieces::iterator Prev = pieces.end(); + for (PathPieces::iterator I = pieces.begin(), E = pieces.end(); I != E; + Prev = I, ++I) { + // Adjust edges in subpaths. + if (PathDiagnosticCallPiece *Call = dyn_cast(*I)) { + adjustLoopEdges(Call->path, LCM, SM); + continue; + } + + PathDiagnosticControlFlowPiece *PieceI = + dyn_cast(*I); + + if (!PieceI) + continue; + + // We are looking at two edges. Is the second one incident + // on an expression (or subexpression) of a loop condition. + const Stmt *Dst = getLocStmt(PieceI->getEndLocation()); + const Stmt *Src = getLocStmt(PieceI->getStartLocation()); + + if (!Dst || !Src) + continue; + + const ForStmt *FS = 0; + const Stmt *S = Dst; + while (const Stmt *Parent = PM.getParentIgnoreParens(S)) { + FS = dyn_cast(Parent); + if (FS) { + if (FS->getCond()->IgnoreParens() != S) + FS = 0; + break; + } + S = Parent; + } + + // If 'FS' is non-null we have found a match where we have an edge + // incident on the condition of a for statement. + if (!FS) + continue; + + // If the current source of the edge is the 'for', then there is nothing + // left to be done. + if (Src == FS) + continue; + + // Now look at the previous edge. We want to know if this was in the same + // "level" as the for statement. + const Stmt *SrcParent = PM.getParentIgnoreParens(Src); + const Stmt *FSParent = PM.getParentIgnoreParens(FS); + if (SrcParent && SrcParent == FSParent) { + PathDiagnosticLocation L(FS, SM, LC); + bool needsEdge = true; + + if (Prev != E) { + if (PathDiagnosticControlFlowPiece *P = + dyn_cast(*Prev)) { + const Stmt *PrevSrc = getLocStmt(P->getStartLocation()); + if (PrevSrc) { + const Stmt *PrevSrcParent = PM.getParentIgnoreParens(PrevSrc); + if (PrevSrcParent == FSParent) { + P->setEndLocation(L); + needsEdge = false; + } + } + } + } + + if (needsEdge) { + PathDiagnosticControlFlowPiece *P = + new PathDiagnosticControlFlowPiece(PieceI->getStartLocation(), L); + pieces.insert(I, P); + } + + PieceI->setStartLocation(L); + } + } +} + //===----------------------------------------------------------------------===// // Methods for BugType and subclasses. //===----------------------------------------------------------------------===// @@ -2668,9 +2751,17 @@ bool GRBugReporter::generatePathDiagnostic(PathDiagnostic& PD, adjustCallLocations(PD.getMutablePieces()); if (ActiveScheme == PathDiagnosticConsumer::AlternateExtensive) { + SourceManager &SM = getSourceManager(); + + // Reduce the number of edges from a very conservative set + // to an aesthetically pleasing subset that conveys the + // necessary information. OptimizedCallsSet OCS; - while (optimizeEdges(PD.getMutablePieces(), getSourceManager(), - OCS, LCM)) {} + while (optimizeEdges(PD.getMutablePieces(), SM, OCS, LCM)) {} + + // Adjust edges into loop conditions to make them more uniform + // and aesthetically pleasing. + adjustLoopEdges(PD.getMutablePieces(), LCM, SM); } }