From ef22647e6cb77ef2346ae564c05c85e5ce978ca7 Mon Sep 17 00:00:00 2001 From: "Duncan P. N. Exon Smith" Date: Thu, 23 Jul 2015 20:11:47 +0000 Subject: [PATCH] Sema: Split out helper from checkForFunctionCall(), NFC Split out `hasRecursiveCallInPath()` from `checkForFunctionCall()` to flatten nesting and clarify the code. This also simplifies a follow-up patch that refactors the other logic in `checkForFunctionCall()`. Patch by Vedant Kumar! git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@243038 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/AnalysisBasedWarnings.cpp | 74 +++++++++++++++--------------- 1 file changed, 37 insertions(+), 37 deletions(-) diff --git a/lib/Sema/AnalysisBasedWarnings.cpp b/lib/Sema/AnalysisBasedWarnings.cpp index f2ff48ad69..501b862cef 100644 --- a/lib/Sema/AnalysisBasedWarnings.cpp +++ b/lib/Sema/AnalysisBasedWarnings.cpp @@ -171,6 +171,38 @@ enum RecursiveState { FoundPathWithNoRecursiveCall }; +static bool hasRecursiveCallInPath(const FunctionDecl *FD, CFGBlock &Block) { + // Since the current state is FoundPathWithNoRecursiveCall, the successors + // will be either FoundPathWithNoRecursiveCall or FoundPath. To determine + // which, process all the Stmt's in this block to find any recursive calls. + for (const auto &B : Block) { + if (B.getKind() != CFGElement::Statement) + continue; + + const CallExpr *CE = dyn_cast(B.getAs()->getStmt()); + if (!CE || !CE->getCalleeDecl() || + CE->getCalleeDecl()->getCanonicalDecl() != FD) + continue; + + // Skip function calls which are qualified with a templated class. + if (const DeclRefExpr *DRE = + dyn_cast(CE->getCallee()->IgnoreParenImpCasts())) { + if (NestedNameSpecifier *NNS = DRE->getQualifier()) { + if (NNS->getKind() == NestedNameSpecifier::TypeSpec && + isa(NNS->getAsType())) { + continue; + } + } + } + + const CXXMemberCallExpr *MCE = dyn_cast(CE); + if (!MCE || isa(MCE->getImplicitObjectArgument()) || + !MCE->getMethodDecl()->isVirtual()) + return true; + } + return false; +} + static void checkForFunctionCall(Sema &S, const FunctionDecl *FD, CFGBlock &Block, unsigned ExitID, llvm::SmallVectorImpl &States, @@ -183,45 +215,13 @@ static void checkForFunctionCall(Sema &S, const FunctionDecl *FD, States[ID] = State; - // Found a path to the exit node without a recursive call. - if (ID == ExitID && State == FoundPathWithNoRecursiveCall) - return; - if (State == FoundPathWithNoRecursiveCall) { - // If the current state is FoundPathWithNoRecursiveCall, the successors - // will be either FoundPathWithNoRecursiveCall or FoundPath. To determine - // which, process all the Stmt's in this block to find any recursive calls. - for (const auto &B : Block) { - if (B.getKind() != CFGElement::Statement) - continue; - - const CallExpr *CE = dyn_cast(B.getAs()->getStmt()); - if (CE && CE->getCalleeDecl() && - CE->getCalleeDecl()->getCanonicalDecl() == FD) { - - // Skip function calls which are qualified with a templated class. - if (const DeclRefExpr *DRE = dyn_cast( - CE->getCallee()->IgnoreParenImpCasts())) { - if (NestedNameSpecifier *NNS = DRE->getQualifier()) { - if (NNS->getKind() == NestedNameSpecifier::TypeSpec && - isa(NNS->getAsType())) { - continue; - } - } - } + // Found a path to the exit node without a recursive call. + if (ExitID == ID) + return; - if (const CXXMemberCallExpr *MCE = dyn_cast(CE)) { - if (isa(MCE->getImplicitObjectArgument()) || - !MCE->getMethodDecl()->isVirtual()) { - State = FoundPath; - break; - } - } else { - State = FoundPath; - break; - } - } - } + if (hasRecursiveCallInPath(FD, Block)) + State = FoundPath; } for (CFGBlock::succ_iterator I = Block.succ_begin(), E = Block.succ_end(); -- 2.50.1