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