CodaFi updated this revision to Diff 135827.
https://reviews.llvm.org/D43737
Files:
lib/Sema/AnalysisBasedWarnings.cpp
test/SemaCXX/warn-infinite-recursion.cpp
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();
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<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();
+ 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<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();
+ // 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,
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits