summaryrefslogtreecommitdiffstats
path: root/clang/lib/Sema/AnalysisBasedWarnings.cpp
diff options
context:
space:
mode:
authorRobert Widmann <devteam.codafi@gmail.com>2018-03-22 03:16:23 +0000
committerRobert Widmann <devteam.codafi@gmail.com>2018-03-22 03:16:23 +0000
commit97608445b12e93b95111031492d8a46a97f33db3 (patch)
tree1d1d877fe07547259e43c3cf1a9677dc6ad2894b /clang/lib/Sema/AnalysisBasedWarnings.cpp
parent2a0373a2db804c2b290c4b8bd94d575f79f13036 (diff)
downloadbcm5719-llvm-97608445b12e93b95111031492d8a46a97f33db3.tar.gz
bcm5719-llvm-97608445b12e93b95111031492d8a46a97f33db3.zip
Improve -Winfinite-recursion
Summary: Rewrites -Winfinite-recursion to remove the state dictionary and explore paths in loops - especially infinite loops. The new check now detects recursion in loop bodies dominated by a recursive call. Reviewers: rsmith, rtrieu Reviewed By: rtrieu Subscribers: lebedev.ri, cfe-commits Differential Revision: https://reviews.llvm.org/D43737 llvm-svn: 328173
Diffstat (limited to 'clang/lib/Sema/AnalysisBasedWarnings.cpp')
-rw-r--r--clang/lib/Sema/AnalysisBasedWarnings.cpp71
1 files changed, 24 insertions, 47 deletions
diff --git a/clang/lib/Sema/AnalysisBasedWarnings.cpp b/clang/lib/Sema/AnalysisBasedWarnings.cpp
index 87f73f75751..4a8540ae582 100644
--- a/clang/lib/Sema/AnalysisBasedWarnings.cpp
+++ b/clang/lib/Sema/AnalysisBasedWarnings.cpp
@@ -200,60 +200,41 @@ static bool hasRecursiveCallInPath(const FunctionDecl *FD, CFGBlock &Block) {
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.
+// Returns true if every path from the entry 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();
- // 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.
+ WorkList.push_back(&cfg->getEntry());
- unsigned ID = CurBlock->getBlockID();
- RecursiveState CurState = States[ID];
+ while (!WorkList.empty()) {
+ CFGBlock *Block = WorkList.pop_back_val();
- if (CurState == FoundPathWithNoRecursiveCall) {
- // Found a path to the exit node without a recursive call.
- if (ExitID == ID)
- return false;
+ for (auto I = Block->succ_begin(), E = Block->succ_end(); I != E; ++I) {
+ if (CFGBlock *SuccBlock = *I) {
+ if (!Visited.insert(SuccBlock).second)
+ continue;
- // 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 == SuccBlock->getBlockID())
+ 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 the successor block contains a recursive call, end analysis there.
+ if (hasRecursiveCallInPath(FD, *SuccBlock)) {
+ foundRecursion = true;
+ continue;
}
+
+ WorkList.push_back(SuccBlock);
}
+ }
}
-
- // 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,
@@ -269,10 +250,6 @@ static void checkRecursiveFunction(Sema &S, const FunctionDecl *FD,
CFG *cfg = AC.getCFG();
if (!cfg) return;
- // If the exit block is unreachable, skip processing the function.
- if (cfg->getExit().pred_empty())
- return;
-
// Emit diagnostic if a recursive function call is detected for all paths.
if (checkForRecursiveFunctionCall(FD, cfg))
S.Diag(Body->getLocStart(), diag::warn_infinite_recursive_function);
OpenPOWER on IntegriCloud