While building a cute new algorithm, would it be a good idea to move the loop events into visitors instead of mixing them with the main traversal and edge logic?
Jordan On May 3, 2013, at 11:25 , Ted Kremenek <[email protected]> wrote: > Author: kremenek > Date: Fri May 3 13:25:33 2013 > New Revision: 181040 > > URL: http://llvm.org/viewvc/llvm-project?rev=181040&view=rev > Log: > [analyzer] Start hacking up alternate control-flow edge generation. WIP. > Not guaranteed to do anything useful yet. > > Modified: > cfe/trunk/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h > cfe/trunk/lib/StaticAnalyzer/Core/BugReporter.cpp > > 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=181040&r1=181039&r2=181040&view=diff > ============================================================================== > --- cfe/trunk/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h > (original) > +++ cfe/trunk/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h > Fri May 3 13:25:33 2013 > @@ -94,7 +94,7 @@ public: > > void HandlePathDiagnostic(PathDiagnostic *D); > > - enum PathGenerationScheme { None, Minimal, Extensive }; > + enum PathGenerationScheme { None, Minimal, Extensive, AlternateExtensive }; > virtual PathGenerationScheme getGenerationScheme() const { return Minimal; } > virtual bool supportsLogicalOpControlFlow() const { return false; } > virtual bool supportsAllBlockEdges() const { return false; } > > Modified: cfe/trunk/lib/StaticAnalyzer/Core/BugReporter.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/BugReporter.cpp?rev=181040&r1=181039&r2=181040&view=diff > ============================================================================== > --- cfe/trunk/lib/StaticAnalyzer/Core/BugReporter.cpp (original) > +++ cfe/trunk/lib/StaticAnalyzer/Core/BugReporter.cpp Fri May 3 13:25:33 2013 > @@ -1530,6 +1530,212 @@ static bool GenerateExtensivePathDiagnos > return PDB.getBugReport()->isValid(); > } > > +/// \brief Adds a sanitized control-flow diagnostic edge to a path. > +static void addEdgeToPath(PathPieces &path, > + PathDiagnosticLocation &PrevLoc, > + PathDiagnosticLocation NewLoc, > + const LocationContext *LC) { > + if (NewLoc.asLocation().isMacroID()) > + return; > + > + if (!PrevLoc.isValid()) { > + PrevLoc = NewLoc; > + return; > + } > + > + const PathDiagnosticLocation &PrevLocClean = cleanUpLocation(PrevLoc, LC); > + if (PrevLocClean.asLocation().isInvalid()) { > + PrevLoc = NewLoc; > + return; > + } > + > + const PathDiagnosticLocation &NewLocClean = cleanUpLocation(NewLoc, LC); > + if (NewLocClean.asLocation() == PrevLocClean.asLocation()) > + return; > + > + // FIXME: ignore intra-macro edges for now. > + if (NewLocClean.asLocation().getExpansionLoc() == > + PrevLocClean.asLocation().getExpansionLoc()) > + return; > + > + path.push_front(new PathDiagnosticControlFlowPiece(NewLocClean, > + PrevLocClean)); > + PrevLoc = NewLoc; > +} > + > +static bool > +GenerateAlternateExtensivePathDiagnostic(PathDiagnostic& PD, > + PathDiagnosticBuilder &PDB, > + const ExplodedNode *N, > + LocationContextMap &LCM, > + ArrayRef<BugReporterVisitor *> > visitors) { > + > + BugReport *report = PDB.getBugReport(); > + const SourceManager& SM = PDB.getSourceManager(); > + StackDiagVector CallStack; > + InterestingExprs IE; > + > + // Record the last location for a given visited stack frame. > + llvm::DenseMap<const StackFrameContext *, PathDiagnosticLocation> > + PrevLocMap; > + > + const ExplodedNode *NextNode = N->getFirstPred(); > + while (NextNode) { > + N = NextNode; > + NextNode = N->getFirstPred(); > + ProgramPoint P = N->getLocation(); > + const LocationContext *LC = N->getLocationContext(); > + PathDiagnosticLocation &PrevLoc = PrevLocMap[LC->getCurrentStackFrame()]; > + > + do { > + if (Optional<PostStmt> PS = P.getAs<PostStmt>()) { > + // For expressions, make sure we propagate the > + // interesting symbols correctly. > + if (const Expr *Ex = PS->getStmtAs<Expr>()) > + reversePropagateIntererstingSymbols(*PDB.getBugReport(), IE, > + N->getState().getPtr(), Ex, > + N->getLocationContext()); > + break; > + } > + > + // Have we encountered an exit from a function call? > + if (Optional<CallExitEnd> CE = P.getAs<CallExitEnd>()) { > + const Stmt *S = CE->getCalleeContext()->getCallSite(); > + // Propagate the interesting symbols accordingly. > + if (const Expr *Ex = dyn_cast_or_null<Expr>(S)) { > + reversePropagateIntererstingSymbols(*PDB.getBugReport(), IE, > + N->getState().getPtr(), Ex, > + N->getLocationContext()); > + } > + > + // We are descending into a call (backwards). Construct > + // a new call piece to contain the path pieces for that call. > + PathDiagnosticCallPiece *C = > + PathDiagnosticCallPiece::construct(N, *CE, SM); > + > + // Record the location context for this call piece. > + LCM[C] = CE->getCalleeContext(); > + > + // Add the edge to the return site. > + addEdgeToPath(PD.getActivePath(), PrevLoc, C->callReturn, LC); > + > + // Make the contents of the call the active path for now. > + PD.pushActivePath(&C->path); > + CallStack.push_back(StackDiagPair(C, N)); > + break; > + } > + > + // Have we encountered an entrance to a call? It may be > + // the case that we have not encountered a matching > + // call exit before this point. This means that the path > + // terminated within the call itself. > + if (Optional<CallEnter> CE = P.getAs<CallEnter>()) { > + // Add an edge to the start of the function. > + const Decl *D = CE->getCalleeContext()->getDecl(); > + addEdgeToPath(PD.getActivePath(), PrevLoc, > + PathDiagnosticLocation::createBegin(D, SM), LC); > + > + // Did we visit an entire call? > + bool VisitedEntireCall = PD.isWithinCall(); > + PD.popActivePath(); > + > + PathDiagnosticCallPiece *C; > + if (VisitedEntireCall) { > + C = cast<PathDiagnosticCallPiece>(PD.getActivePath().front()); > + } else { > + const Decl *Caller = CE->getLocationContext()->getDecl(); > + C = PathDiagnosticCallPiece::construct(PD.getActivePath(), Caller); > + LCM[C] = CE->getCalleeContext(); > + } > + C->setCallee(*CE, SM); > + > + if (!CallStack.empty()) { > + assert(CallStack.back().first == C); > + CallStack.pop_back(); > + } > + break; > + } > + > + // Block edges. > + if (Optional<BlockEdge> BE = P.getAs<BlockEdge>()) { > + // Does this represent entering a call? If so, look at propagating > + // interesting symbols across call boundaries. > + if (NextNode) { > + const LocationContext *CallerCtx = NextNode->getLocationContext(); > + const LocationContext *CalleeCtx = PDB.LC; > + if (CallerCtx != CalleeCtx) { > + reversePropagateInterestingSymbols(*PDB.getBugReport(), IE, > + N->getState().getPtr(), > + CalleeCtx, CallerCtx); > + } > + } > + > + // Are we jumping to the head of a loop? Add a special diagnostic. > + if (const Stmt *Loop = BE->getSrc()->getLoopTarget()) { > + PathDiagnosticLocation L(Loop, SM, PDB.LC); > + const CompoundStmt *CS = NULL; > + > + if (const ForStmt *FS = dyn_cast<ForStmt>(Loop)) > + CS = dyn_cast<CompoundStmt>(FS->getBody()); > + else if (const WhileStmt *WS = dyn_cast<WhileStmt>(Loop)) > + CS = dyn_cast<CompoundStmt>(WS->getBody()); > + > + PathDiagnosticEventPiece *p = > + new PathDiagnosticEventPiece(L, "Looping back to the head " > + "of the loop"); > + p->setPrunable(true); > + > + addEdgeToPath(PD.getActivePath(), PrevLoc, p->getLocation(), LC); > + > + if (CS) { > + addEdgeToPath(PD.getActivePath(), PrevLoc, > + PathDiagnosticLocation::createEndBrace(CS, SM), > LC); > + } > + } > + > + const CFGBlock *BSrc = BE->getSrc(); > + ParentMap &PM = PDB.getParentMap(); > + > + if (const Stmt *Term = BSrc->getTerminator()) { > + // Are we jumping past the loop body without ever executing the > + // loop (because the condition was false)? > + if (isLoopJumpPastBody(Term, &*BE) && > + !isInLoopBody(PM, > + getStmtBeforeCond(PM, > + BSrc->getTerminatorCondition(), > + N), > + Term)) > + { > + PathDiagnosticLocation L(Term, SM, PDB.LC); > + PathDiagnosticEventPiece *PE = > + new PathDiagnosticEventPiece(L, "Loop body executed 0 times"); > + PE->setPrunable(true); > + addEdgeToPath(PD.getActivePath(), PrevLoc, > + PE->getLocation(), LC); > + } > + } > + break; > + } > + } while (0); > + > + if (!NextNode) > + continue; > + > + // Add pieces from custom visitors. > + BugReport *R = PDB.getBugReport(); > + for (ArrayRef<BugReporterVisitor *>::iterator I = visitors.begin(), > + E = visitors.end(); > + I != E; ++I) { > + if (PathDiagnosticPiece *p = (*I)->VisitNode(N, NextNode, PDB, *R)) { > + addEdgeToPath(PD.getActivePath(), PrevLoc, p->getLocation(), LC); > + updateStackPiecesWithMessage(p, CallStack); > + } > + } > + } > + > + return report->isValid(); > +} > + > //===----------------------------------------------------------------------===// > // Methods for BugType and subclasses. > //===----------------------------------------------------------------------===// > @@ -2108,6 +2314,13 @@ bool GRBugReporter::generatePathDiagnost > typedef PathDiagnosticConsumer::PathGenerationScheme PathGenerationScheme; > PathGenerationScheme ActiveScheme = PC.getGenerationScheme(); > > + if (ActiveScheme == PathDiagnosticConsumer::Extensive) { > + AnalyzerOptions &options = getEngine().getAnalysisManager().options; > + if (options.getBooleanOption("path-diagnostics-alternate", false)) { > + ActiveScheme = PathDiagnosticConsumer::AlternateExtensive; > + } > + } > + > TrimmedGraph TrimG(&getGraph(), errorNodes); > ReportGraph ErrorGraph; > > @@ -2169,6 +2382,9 @@ bool GRBugReporter::generatePathDiagnost > LCM.clear(); > > switch (ActiveScheme) { > + case PathDiagnosticConsumer::AlternateExtensive: > + GenerateAlternateExtensivePathDiagnostic(PD, PDB, N, LCM, visitors); > + break; > case PathDiagnosticConsumer::Extensive: > GenerateExtensivePathDiagnostic(PD, PDB, N, LCM, visitors); > break; > > > _______________________________________________ > cfe-commits mailing list > [email protected] > http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
_______________________________________________ cfe-commits mailing list [email protected] http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
