Index: lib/Sema/AnalysisBasedWarnings.cpp =================================================================== --- lib/Sema/AnalysisBasedWarnings.cpp +++ lib/Sema/AnalysisBasedWarnings.cpp @@ -200,60 +200,43 @@ 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. static bool checkForRecursiveFunctionCall(const FunctionDecl *FD, CFG *cfg) { + llvm::SmallPtrSet Visited; + llvm::SmallVector WorkList; + // Keep track of whether we found at least one recursive path. + bool foundRecursion = false; const unsigned ExitID = cfg->getExit().getBlockID(); + auto analyzeSuccessor = [&](CFGBlock *CurBlock) -> bool { + if (!Visited.insert(CurBlock).second) + return false; + + // If the successor block contains a recursive call, end analysis there. + if (!hasRecursiveCallInPath(FD, *CurBlock)) { + WorkList.push_back(CurBlock); + return false; + } + return true; + }; - // Mark all nodes as FoundNoPath, then set the status of the entry block. - SmallVector States(cfg->getNumBlockIDs(), FoundNoPath); - States[cfg->getEntry().getBlockID()] = FoundPathWithNoRecursiveCall; - - // Make the processing stack and seed it with the entry block. - SmallVector Stack; - Stack.push_back(&cfg->getEntry()); - - while (!Stack.empty()) { - CFGBlock *CurBlock = Stack.back(); - Stack.pop_back(); + // Seed the work list with the entry block. + foundRecursion |= analyzeSuccessor(&cfg->getEntry()); + while (!WorkList.empty()) { + CFGBlock *CurBlock = WorkList.pop_back_val(); 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; - } + // Found a path to the exit node without a recursive call. + if (ExitID == ID) + return false; - // 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); - } - } + if (*I) + foundRecursion |= analyzeSuccessor(*I); } - - // 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, Index: test/SemaCXX/warn-infinite-recursion.cpp =================================================================== --- test/SemaCXX/warn-infinite-recursion.cpp +++ test/SemaCXX/warn-infinite-recursion.cpp @@ -29,8 +29,7 @@ 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,13 @@ return 5 + j(); } +// Don't warn on infinite loops +void k() { + while (true) {} + + k(); +} + class S { static void a(); void b();