r181040 - [analyzer] Start hacking up alternate control-flow edge generation. WIP. Not guaranteed to do anything useful yet.
Jordan Rose
jordan_rose at apple.com
Fri May 3 13:38:53 PDT 2013
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 <kremenek at apple.com> 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
> cfe-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20130503/70540835/attachment.html>
More information about the cfe-commits
mailing list