r328173 - Improve -Winfinite-recursion

Steven Wu via cfe-commits cfe-commits at lists.llvm.org
Fri Feb 8 10:24:34 PST 2019


Hi Robert

I ping'ed this commit on Phabricator with an example of false positive introduced by this patch. Can you take a look?

Thanks

Steven

> On Mar 21, 2018, at 8:16 PM, Robert Widmann via cfe-commits <cfe-commits at lists.llvm.org> wrote:
> 
> Author: codafi
> Date: Wed Mar 21 20:16:23 2018
> New Revision: 328173
> 
> URL: http://llvm.org/viewvc/llvm-project?rev=328173&view=rev
> Log:
> Improve -Winfinite-recursion
> 
> Summary: Rewrites -Winfinite-recursion to remove the state dictionary and explore paths in loops - especially infinite loops.  The new check now detects recursion in loop bodies dominated by a recursive call.
> 
> Reviewers: rsmith, rtrieu
> 
> Reviewed By: rtrieu
> 
> Subscribers: lebedev.ri, cfe-commits
> 
> Differential Revision: https://reviews.llvm.org/D43737
> 
> Modified:
>    cfe/trunk/lib/Sema/AnalysisBasedWarnings.cpp
>    cfe/trunk/test/SemaCXX/warn-infinite-recursion.cpp
> 
> Modified: cfe/trunk/lib/Sema/AnalysisBasedWarnings.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/AnalysisBasedWarnings.cpp?rev=328173&r1=328172&r2=328173&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Sema/AnalysisBasedWarnings.cpp (original)
> +++ cfe/trunk/lib/Sema/AnalysisBasedWarnings.cpp Wed Mar 21 20:16:23 2018
> @@ -200,60 +200,41 @@ static bool hasRecursiveCallInPath(const
>   return false;
> }
> 
> -// All blocks are in one of three states.  States are ordered so that blocks
> -// can only move to higher states.
> -enum RecursiveState {
> -  FoundNoPath,
> -  FoundPath,
> -  FoundPathWithNoRecursiveCall
> -};
> -
> -// Returns true if there exists a path to the exit block and every path
> -// to the exit block passes through a call to FD.
> +// Returns true if every path from the entry block passes through a call to FD.
> static bool checkForRecursiveFunctionCall(const FunctionDecl *FD, CFG *cfg) {
> +  llvm::SmallPtrSet<CFGBlock *, 16> Visited;
> +  llvm::SmallVector<CFGBlock *, 16> WorkList;
> +  // Keep track of whether we found at least one recursive path.
> +  bool foundRecursion = false;
> 
>   const unsigned ExitID = cfg->getExit().getBlockID();
> 
> -  // Mark all nodes as FoundNoPath, then set the status of the entry block.
> -  SmallVector<RecursiveState, 16> States(cfg->getNumBlockIDs(), FoundNoPath);
> -  States[cfg->getEntry().getBlockID()] = FoundPathWithNoRecursiveCall;
> -
> -  // Make the processing stack and seed it with the entry block.
> -  SmallVector<CFGBlock *, 16> Stack;
> -  Stack.push_back(&cfg->getEntry());
> -
> -  while (!Stack.empty()) {
> -    CFGBlock *CurBlock = Stack.back();
> -    Stack.pop_back();
> -
> -    unsigned ID = CurBlock->getBlockID();
> -    RecursiveState CurState = States[ID];
> -
> -    if (CurState == FoundPathWithNoRecursiveCall) {
> -      // Found a path to the exit node without a recursive call.
> -      if (ExitID == ID)
> -        return false;
> -
> -      // Only change state if the block has a recursive call.
> -      if (hasRecursiveCallInPath(FD, *CurBlock))
> -        CurState = FoundPath;
> -    }
> +  // Seed the work list with the entry block.
> +  WorkList.push_back(&cfg->getEntry());
> 
> -    // Loop over successor blocks and add them to the Stack if their state
> -    // changes.
> -    for (auto I = CurBlock->succ_begin(), E = CurBlock->succ_end(); I != E; ++I)
> -      if (*I) {
> -        unsigned next_ID = (*I)->getBlockID();
> -        if (States[next_ID] < CurState) {
> -          States[next_ID] = CurState;
> -          Stack.push_back(*I);
> +  while (!WorkList.empty()) {
> +    CFGBlock *Block = WorkList.pop_back_val();
> +
> +    for (auto I = Block->succ_begin(), E = Block->succ_end(); I != E; ++I) {
> +      if (CFGBlock *SuccBlock = *I) {
> +        if (!Visited.insert(SuccBlock).second)
> +          continue;
> +
> +        // Found a path to the exit node without a recursive call.
> +        if (ExitID == SuccBlock->getBlockID())
> +          return false;
> +
> +        // If the successor block contains a recursive call, end analysis there.
> +        if (hasRecursiveCallInPath(FD, *SuccBlock)) {
> +          foundRecursion = true;
> +          continue;
>         }
> +
> +        WorkList.push_back(SuccBlock);
>       }
> +    }
>   }
> -
> -  // Return true if the exit node is reachable, and only reachable through
> -  // a recursive call.
> -  return States[ExitID] == FoundPath;
> +  return foundRecursion;
> }
> 
> static void checkRecursiveFunction(Sema &S, const FunctionDecl *FD,
> @@ -269,10 +250,6 @@ static void checkRecursiveFunction(Sema
>   CFG *cfg = AC.getCFG();
>   if (!cfg) return;
> 
> -  // If the exit block is unreachable, skip processing the function.
> -  if (cfg->getExit().pred_empty())
> -    return;
> -
>   // Emit diagnostic if a recursive function call is detected for all paths.
>   if (checkForRecursiveFunctionCall(FD, cfg))
>     S.Diag(Body->getLocStart(), diag::warn_infinite_recursive_function);
> 
> Modified: cfe/trunk/test/SemaCXX/warn-infinite-recursion.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/warn-infinite-recursion.cpp?rev=328173&r1=328172&r2=328173&view=diff
> ==============================================================================
> --- cfe/trunk/test/SemaCXX/warn-infinite-recursion.cpp (original)
> +++ cfe/trunk/test/SemaCXX/warn-infinite-recursion.cpp Wed Mar 21 20:16:23 2018
> @@ -29,8 +29,7 @@ void f();
> void e() { f(); }
> void f() { e(); }
> 
> -// Don't warn on infinite loops
> -void g() {
> +void g() {  // expected-warning{{call itself}}
>   while (true)
>     g();
> 
> @@ -54,6 +53,19 @@ int j() {  // expected-warning{{call its
>   return 5 + j();
> }
> 
> +void k() {  // expected-warning{{call itself}}
> +  while(true) {
> +    k();
> +  }
> +}
> +
> +// Don't warn on infinite loops
> +void l() {
> +  while (true) {}
> +
> +  l();
> +}
> +
> class S {
>   static void a();
>   void b();
> 
> 
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits



More information about the cfe-commits mailing list