summaryrefslogtreecommitdiffstats
path: root/clang
diff options
context:
space:
mode:
authorDuncan P. N. Exon Smith <dexonsmith@apple.com>2015-07-23 20:15:50 +0000
committerDuncan P. N. Exon Smith <dexonsmith@apple.com>2015-07-23 20:15:50 +0000
commitdccc30a7efe2e20b4263ca50171aaae55ef6b5a2 (patch)
tree54c3e03176fc63c1ce3722d4b7661102c34cb7a2 /clang
parentf0eafc78e08397c1ccb35acdd8105529369dce68 (diff)
downloadbcm5719-llvm-dccc30a7efe2e20b4263ca50171aaae55ef6b5a2.tar.gz
bcm5719-llvm-dccc30a7efe2e20b4263ca50171aaae55ef6b5a2.zip
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! llvm-svn: 243039
Diffstat (limited to 'clang')
-rw-r--r--clang/lib/Sema/AnalysisBasedWarnings.cpp40
1 files changed, 24 insertions, 16 deletions
diff --git a/clang/lib/Sema/AnalysisBasedWarnings.cpp b/clang/lib/Sema/AnalysisBasedWarnings.cpp
index 501b862cefb..59c25d235a6 100644
--- a/clang/lib/Sema/AnalysisBasedWarnings.cpp
+++ b/clang/lib/Sema/AnalysisBasedWarnings.cpp
@@ -207,27 +207,35 @@ static void checkForFunctionCall(Sema &S, const FunctionDecl *FD,
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;
+ while (!Stack.empty()) {
+ CFGBlock &CurBlock = *Stack.back().first;
+ RecursiveState CurState = Stack.back().second;
+ Stack.pop_back();
- States[ID] = State;
+ unsigned ID = CurBlock.getBlockID();
- if (State == FoundPathWithNoRecursiveCall) {
- // Found a path to the exit node without a recursive call.
- if (ExitID == ID)
- return;
+ // A block's state can only move to a higher state.
+ if (States[ID] >= CurState)
+ continue;
- if (hasRecursiveCallInPath(FD, Block))
- State = FoundPath;
- }
+ States[ID] = 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);
+ 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);
+ }
}
static void checkRecursiveFunction(Sema &S, const FunctionDecl *FD,
OpenPOWER on IntegriCloud