<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Wed, Jul 22, 2015 at 1:34 PM, Vedant Kumar <span dir="ltr"><<a href="mailto:vsk@apple.com" target="_blank">vsk@apple.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div><div>Large CFGs cause clang::Sema::checkForFunctionCall() to stack overflow.<br></div></div></blockquote><div>Is the code that produces the large CFG available? It may be useful to test that other users of the CFG can cope with processing the code. </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div><div>
<br>
I have a patch which breaks the recursion in checkForFunctionCall() by manually<br>
managing the call stack. This fixes the problem. The check-clang target reports<br>
no regressions.<br>
<br>
I don't have commit rights, so I'd appreciate someone taking a look at the<br>
patch and getting it into trunk :).<br>
<br>
thanks!<br>
vedant<br>
<br>
================================================================================<br>
<br>
diff --git a/lib/Sema/AnalysisBasedWarnings.cpp b/lib/Sema/AnalysisBasedWarnings.cpp<br>
index f2ff48a..dc6dda0 100644<br>
--- a/lib/Sema/AnalysisBasedWarnings.cpp<br>
+++ b/lib/Sema/AnalysisBasedWarnings.cpp<br>
@@ -52,6 +52,8 @@<br>
#include <deque><br>
#include <iterator><br>
#include <vector><br>
+#include <functional><br>
+#include <utility><br>
<br>
using namespace clang;<br>
<br>
@@ -175,59 +177,69 @@ static void checkForFunctionCall(Sema &S, const FunctionDecl *FD,<br>
CFGBlock &Block, unsigned ExitID,<br>
llvm::SmallVectorImpl<RecursiveState> &States,<br>
RecursiveState State) {<br>
- unsigned ID = Block.getBlockID();<br>
+ std::vector<std::pair<std::reference_wrapper<CFGBlock>, RecursiveState>><br>
+ Stack;<br>
+ Stack.emplace_back(std::make_pair(std::ref(Block), State));<br>
<br>
- // A block's state can only move to a higher state.<br>
- if (States[ID] >= State)<br>
- return;<br>
+ while (!Stack.empty()) {<br>
+ CFGBlock &CurBlock = Stack.back().first.get();<br>
+ RecursiveState CurState = Stack.back().second;<br>
+ Stack.pop_back();<br>
<br>
- States[ID] = State;<br>
+ unsigned ID = CurBlock.getBlockID();<br>
<br>
- // Found a path to the exit node without a recursive call.<br>
- if (ID == ExitID && State == FoundPathWithNoRecursiveCall)<br>
- return;<br>
+ // A block's state can only move to a higher state.<br>
+ if (States[ID] >= CurState)<br>
+ continue;<br>
<br>
- if (State == FoundPathWithNoRecursiveCall) {<br>
- // If the current state is FoundPathWithNoRecursiveCall, the successors<br>
- // will be either FoundPathWithNoRecursiveCall or FoundPath. To determine<br>
- // which, process all the Stmt's in this block to find any recursive calls.<br>
- for (const auto &B : Block) {<br>
- if (B.getKind() != CFGElement::Statement)<br>
- continue;<br>
+ States[ID] = CurState;<br>
+<br>
+ // Found a path to the exit node without a recursive call.<br>
+ if (ID == ExitID && CurState == FoundPathWithNoRecursiveCall)<br>
+ continue;<br>
+<br>
+ if (CurState == FoundPathWithNoRecursiveCall) {<br>
+ // If the current state is FoundPathWithNoRecursiveCall, the successors<br>
+ // will be either FoundPathWithNoRecursiveCall or FoundPath. To determine<br>
+ // which, process all the Stmt's in this block to find any recursive<br>
+ // calls.<br>
+ for (const auto &B : CurBlock) {<br>
+ if (B.getKind() != CFGElement::Statement)<br>
+ continue;<br>
<br>
- const CallExpr *CE = dyn_cast<CallExpr>(B.getAs<CFGStmt>()->getStmt());<br>
- if (CE && CE->getCalleeDecl() &&<br>
- CE->getCalleeDecl()->getCanonicalDecl() == FD) {<br>
-<br>
- // Skip function calls which are qualified with a templated class.<br>
- if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(<br>
- CE->getCallee()->IgnoreParenImpCasts())) {<br>
- if (NestedNameSpecifier *NNS = DRE->getQualifier()) {<br>
- if (NNS->getKind() == NestedNameSpecifier::TypeSpec &&<br>
- isa<TemplateSpecializationType>(NNS->getAsType())) {<br>
- continue;<br>
+ const CallExpr *CE = dyn_cast<CallExpr>(B.getAs<CFGStmt>()->getStmt());<br>
+ if (CE && CE->getCalleeDecl() &&<br>
+ CE->getCalleeDecl()->getCanonicalDecl() == FD) {<br>
+<br>
+ // Skip function calls which are qualified with a templated class.<br>
+ if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(<br>
+ CE->getCallee()->IgnoreParenImpCasts())) {<br>
+ if (NestedNameSpecifier *NNS = DRE->getQualifier()) {<br>
+ if (NNS->getKind() == NestedNameSpecifier::TypeSpec &&<br>
+ isa<TemplateSpecializationType>(NNS->getAsType())) {<br>
+ continue;<br>
+ }<br>
}<br>
}<br>
- }<br>
<br>
- if (const CXXMemberCallExpr *MCE = dyn_cast<CXXMemberCallExpr>(CE)) {<br>
- if (isa<CXXThisExpr>(MCE->getImplicitObjectArgument()) ||<br>
- !MCE->getMethodDecl()->isVirtual()) {<br>
- State = FoundPath;<br>
+ if (const CXXMemberCallExpr *MCE = dyn_cast<CXXMemberCallExpr>(CE)) {<br>
+ if (isa<CXXThisExpr>(MCE->getImplicitObjectArgument()) ||<br>
+ !MCE->getMethodDecl()->isVirtual()) {<br>
+ CurState = FoundPath;<br>
+ break;<br>
+ }<br>
+ } else {<br>
+ CurState = FoundPath;<br>
break;<br>
}<br>
- } else {<br>
- State = FoundPath;<br>
- break;<br>
}<br>
}<br>
}<br>
- }<br>
<br>
- for (CFGBlock::succ_iterator I = Block.succ_begin(), E = Block.succ_end();<br>
- I != E; ++I)<br>
- if (*I)<br>
- checkForFunctionCall(S, FD, **I, ExitID, States, State);<br>
+ for (auto I = CurBlock.succ_rbegin(), E = CurBlock.succ_rend(); I != E; ++I)<br>
+ if (*I)<br>
+ Stack.emplace_back(std::make_pair(std::ref(**I), CurState));<br>
+ }<br>
}<br>
<br>
static void checkRecursiveFunction(Sema &S, const FunctionDecl *FD,<br>
_______________________________________________<br>
</div></div>cfe-commits mailing list<br>
<a href="mailto:cfe-commits@cs.uiuc.edu" target="_blank">cfe-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits" rel="noreferrer" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits</a><br>
</blockquote></div><br></div></div>