r243039 - Sema: Avoid a stack overflow on large CFGs

Duncan P. N. Exon Smith dexonsmith at apple.com
Thu Jul 23 13:15:50 PDT 2015


Author: dexonsmith
Date: Thu Jul 23 15:15:50 2015
New Revision: 243039

URL: http://llvm.org/viewvc/llvm-project?rev=243039&view=rev
Log:
Sema: Avoid a stack overflow on large CFGs

Large CFGs cause `checkForFunctionCall()` to overflow its stack.  Break
the recursion by manually managing the call stack instead.

Patch by Vedant Kumar!

Modified:
    cfe/trunk/lib/Sema/AnalysisBasedWarnings.cpp

Modified: cfe/trunk/lib/Sema/AnalysisBasedWarnings.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/AnalysisBasedWarnings.cpp?rev=243039&r1=243038&r2=243039&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/AnalysisBasedWarnings.cpp (original)
+++ cfe/trunk/lib/Sema/AnalysisBasedWarnings.cpp Thu Jul 23 15:15:50 2015
@@ -207,27 +207,35 @@ static void checkForFunctionCall(Sema &S
                                  CFGBlock &Block, unsigned ExitID,
                                  llvm::SmallVectorImpl<RecursiveState> &States,
                                  RecursiveState State) {
-  unsigned ID = Block.getBlockID();
+  SmallVector<std::pair<CFGBlock *, RecursiveState>, 16> Stack;
+  Stack.emplace_back(&Block, State);
 
-  // A block's state can only move to a higher state.
-  if (States[ID] >= State)
-    return;
-
-  States[ID] = State;
-
-  if (State == FoundPathWithNoRecursiveCall) {
-    // Found a path to the exit node without a recursive call.
-    if (ExitID == ID)
-      return;
-
-    if (hasRecursiveCallInPath(FD, Block))
-      State = FoundPath;
+  while (!Stack.empty()) {
+    CFGBlock &CurBlock = *Stack.back().first;
+    RecursiveState CurState = Stack.back().second;
+    Stack.pop_back();
+
+    unsigned ID = CurBlock.getBlockID();
+
+    // A block's state can only move to a higher state.
+    if (States[ID] >= CurState)
+      continue;
+
+    States[ID] = CurState;
+
+    if (CurState == FoundPathWithNoRecursiveCall) {
+      // Found a path to the exit node without a recursive call.
+      if (ExitID == ID)
+        continue;
+
+      if (hasRecursiveCallInPath(FD, CurBlock))
+        CurState = FoundPath;
+    }
+
+    for (auto I = CurBlock.succ_begin(), E = CurBlock.succ_end(); I != E; ++I)
+      if (*I)
+        Stack.emplace_back(*I, CurState);
   }
-
-  for (CFGBlock::succ_iterator I = Block.succ_begin(), E = Block.succ_end();
-       I != E; ++I)
-    if (*I)
-      checkForFunctionCall(S, FD, **I, ExitID, States, State);
 }
 
 static void checkRecursiveFunction(Sema &S, const FunctionDecl *FD,





More information about the cfe-commits mailing list