Lines Matching +full:ps +full:- +full:seq +full:- +full:loop
1 //===- CalledOnceCheck.cpp - Check 'called once' parameters ---------------===//
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
102 // Our analysis is intra-procedural and, while in the perfect world,
132 // Called on one path, not called on another - that's simply
147 // No-return paths should be absolutely transparent for the analysis.
282 /// expressions on our way. Only certain expressions considered "no-op"
292 /// - If expression E is used as a function argument, could we say
301 /// - If expression E is used as a condition, could we say that
317 switch (UO->getOpcode()) { in VisitUnaryOperator()
325 // For this reason, dereference operation is a "no-op". in VisitUnaryOperator()
327 return Visit(UO->getSubExpr()); in VisitUnaryOperator()
337 switch (BO->getOpcode()) { in VisitBinaryOperator()
340 const DeclRefExpr *LHS = Visit(BO->getLHS()); in VisitBinaryOperator()
341 return LHS ? LHS : Visit(BO->getRHS()); in VisitBinaryOperator()
349 return Visit(OVE->getSourceExpr()); in VisitOpaqueValueExpr()
358 switch (CE->getBuiltinCallee()) { in VisitCallExpr()
361 assert(CE->getNumArgs() >= 2); in VisitCallExpr()
363 const DeclRefExpr *Candidate = Visit(CE->getArg(0)); in VisitCallExpr()
364 return Candidate != nullptr ? Candidate : Visit(CE->getArg(1)); in VisitCallExpr()
368 return Visit(CE->getArg(0)); in VisitCallExpr()
381 const Expr *DeclutteredExpr = E->IgnoreParenCasts(); in VisitExpr()
402 return dyn_cast<ParmVarDecl>(DR->getDecl()); in findReferencedParmVarDecl()
415 return If->getCond(); in getCondition()
418 return Ternary->getCond(); in getCondition()
442 Result.push_back(E->getDecl()->getName()); in VisitDeclRefExpr()
449 if (E->isImplicitProperty()) { in VisitObjCPropertyRefExpr()
451 if (E->isMessagingGetter()) { in VisitObjCPropertyRefExpr()
452 PropertyMethodDecl = E->getImplicitPropertyGetter(); in VisitObjCPropertyRefExpr()
454 PropertyMethodDecl = E->getImplicitPropertySetter(); in VisitObjCPropertyRefExpr()
458 Name = PropertyMethodDecl->getSelector().getNameForSlot(0); in VisitObjCPropertyRefExpr()
460 assert(E->isExplicitProperty()); in VisitObjCPropertyRefExpr()
461 Name = E->getExplicitProperty()->getName(); in VisitObjCPropertyRefExpr()
500 /// clarification of how to explain which sub-path starts with a CFG edge
506 /// Because clarification is not needed for non-trivial pairs of blocks
513 if (const Stmt *Terminator = Conditional->getTerminatorStmt()) { in clarify()
529 const Stmt *CaseToBlame = SuccInQuestion->getLabel(); in VisitSwitchStmt()
536 for (const SwitchCase *Case = Switch->getSwitchCaseList(); Case; in VisitSwitchStmt()
537 Case = Case->getNextSwitchCase()) { in VisitSwitchStmt()
556 assert(Parent->succ_size() == 2 && in VisitBranchingBlock()
565 // We don't want to report on short-curcuit logical operations. in VisitBinaryOperator()
580 CFGBlock::const_succ_iterator It = llvm::find(Parent->succs(), Child); in getSuccessorIndex()
581 assert(It != Parent->succ_end() && in getSuccessorIndex()
582 "Given blocks should be in parent-child relationship"); in getSuccessorIndex()
583 return It - Parent->succ_begin(); in getSuccessorIndex()
622 //===----------------------------------------------------------------------===//
624 //===----------------------------------------------------------------------===//
646 for (const auto &Capture : Block->captures()) { in findCapturesToTrack()
649 const DeclContext *ParamContext = P->getDeclContext(); in findCapturesToTrack()
659 for (unsigned Index : llvm::seq<unsigned>(0u, Function->param_size())) { in findParamsToTrack()
661 TrackedParams.push_back(Function->getParamDecl(Index)); in findParamsToTrack()
666 //===----------------------------------------------------------------------===//
668 //===----------------------------------------------------------------------===//
688 // +---------+ | +-----------+ in check()
690 // +---------+ | +-----------+ in check()
692 // +---------+ | +-----------+ in check()
695 // +----------------+ +---------+ | +----------------+ +---------+ in check()
697 // +----------------+ +---------+ | +----------------+ +---------+ in check()
699 // +----------------+ +---------+ | +----------------+ +---------+ in check()
702 // +-----------+ | +---------+ in check()
704 // +-----------+ | +---------+ in check()
706 // +-----------+ | +---------+ in check()
747 if (BB->hasNoReturnElement()) { in check()
754 // should traverse basic blocks bottom-up. in check()
757 check(S->getStmt()); in check()
832 // For this reason, branch A -> B can be used for reporting. in checkEntry()
847 for (unsigned Index : llvm::seq(0u, size())) { in checkEntry()
884 llvm::ArrayRef(CallOrMessage->getArgs(), CallOrMessage->getNumArgs()); in checkIndirectCall()
943 for (const CFGBlock *Succ : Parent->succs()) { in findAndReportNotCalledBranches()
948 assert(Parent->succ_size() >= 2 && in findAndReportNotCalledBranches()
953 Parameter, AC.getDecl(), Clarification->Location, in findAndReportNotCalledBranches()
954 Clarification->Reason, !IsEscape, !isExplicitlyMarked(Parameter)); in findAndReportNotCalledBranches()
960 //===----------------------------------------------------------------------===//
962 //===----------------------------------------------------------------------===//
966 return Parameter->hasAttr<CalledOnceAttr>(); in isExplicitlyMarked()
983 if (!Ty->isBlockPointerType()) { in isConventional()
987 QualType BlockType = Ty->castAs<BlockPointerType>()->getPointeeType(); in isConventional()
989 return BlockType->castAs<FunctionType>()->getReturnType()->isVoidType(); in isConventional()
994 IdentifierInfo *II = Function->getIdentifier(); in isOnlyParameterConventional()
995 return Function->getNumParams() == 1 && II && in isOnlyParameterConventional()
996 hasConventionalSuffix(II->getName()); in isOnlyParameterConventional()
1005 if (const SwiftAsyncAttr *A = D->getAttr<SwiftAsyncAttr>()) { in isConventionalSwiftAsync()
1006 if (A->getKind() == SwiftAsyncAttr::None) { in isConventionalSwiftAsync()
1010 return A->getCompletionHandlerIndex().getASTIndex() == ParamIndex; in isConventionalSwiftAsync()
1040 (isConventional(Parameter->getName()) || in shouldBeCalledOnce()
1041 hasConventionalSuffix(Parameter->getName())) && in shouldBeCalledOnce()
1042 isConventional(Parameter->getType())); in shouldBeCalledOnce()
1047 unsigned ParamIndex = Param->getFunctionScopeIndex(); in shouldBeCalledOnce()
1058 return shouldBeCalledOnce(Block->getParamDecl(ParamIndex)); in shouldBeCalledOnce()
1063 if (ParamIndex >= Function->getNumParams()) { in shouldBeCalledOnce()
1072 return shouldBeCalledOnce(Function->getParamDecl(ParamIndex)) || in shouldBeCalledOnce()
1079 Selector MethodSelector = Method->getSelector(); in shouldBeCalledOnce()
1089 const ParmVarDecl *Parameter = Method->getParamDecl(ParamIndex); in shouldBeCalledOnce()
1093 Parameter->getType())); in shouldBeCalledOnce()
1097 const FunctionDecl *Function = Call->getDirectCallee(); in shouldBeCalledOnce()
1103 const ObjCMethodDecl *Method = Message->getMethodDecl(); in shouldBeCalledOnce()
1104 return Method && ParamIndex < Method->param_size() && in shouldBeCalledOnce()
1108 //===----------------------------------------------------------------------===//
1110 //===----------------------------------------------------------------------===//
1114 return Block->capturesVariable(Parameter); in isCaptured()
1132 // Skip no-op (for our case) operations. in getBlockGuaraneedCallSite()
1140 if (Call->getCallee() == Prev) in getBlockGuaraneedCallSite()
1162 llvm::ArrayRef(CallOrMessage->getArgs(), CallOrMessage->getNumArgs()); in shouldBlockArgumentBeCalledOnce()
1175 const FunctionDecl *Function = Call->getDirectCallee(); in shouldBlockArgumentBeCalledOnce()
1182 // At the moment, we don't have any Obj-C methods we want to specifically in shouldBlockArgumentBeCalledOnce()
1199 Function->getName() && in shouldBlockArgumentBeCalledOnce()
1213 /// 3. Methods with only assertion-like operations
1236 // Method has only one block, let's see if it has a no-return in isPossiblyEmptyImpl()
1238 if (OnlyBlock && OnlyBlock->hasNoReturnElement()) { in isPossiblyEmptyImpl()
1249 // - If it came from a macro, it can be an assertion. in isPossiblyEmptyImpl()
1259 // Return statements can have sub-expressions that are represented as in isPossiblyEmptyImpl()
1270 const Stmt *SuspiciousStmt = S->getStmt(); in isPossiblyEmptyImpl()
1281 return SuspiciousStmt->getBeginLoc().isMacroID() || in isPossiblyEmptyImpl()
1283 ReturnChildren->hasParent(SuspiciousStmt)); in isPossiblyEmptyImpl()
1301 return States[BB->getBlockID()]; in getState()
1305 return States[BB->getBlockID()]; in getState()
1325 llvm::make_filter_range(BB->succs(), [this](const CFGBlock *Succ) { in joinSuccessors()
1326 return Succ && this->getState(Succ).isVisited(); in joinSuccessors()
1338 if (const Expr *Condition = getCondition(BB->getTerminatorStmt())) { in joinSuccessors()
1375 // For this reason, in the following loop we look for the in handleParameterCheck()
1376 // best-looking option. in handleParameterCheck()
1377 for (const CFGBlock *Succ : BB->succs()) { in handleParameterCheck()
1437 // Let's check if the block represents DefinitelyCalled -> MaybeCalled in isLosingCall()
1446 // Let's check if the block represents Escaped -> NotCalled transition. in isLosingEscape()
1457 "correct-to-error transition"); in isLosingJoin()
1471 Parent->succs(), [this, ParameterIndex, ToFind](const CFGBlock *Succ) { in anySuccessorHasStatus()
1490 /// Mark all parameters in the current state as 'no-return'.
1492 for (ParameterStatus &PS : CurrentState) { in markNoReturn()
1493 PS = ParameterStatus::NoReturn; in markNoReturn()
1502 if (auto Index = getIndexOfExpression(Assignment->getLHS())) { in checkSuppression()
1507 Assignment->getRHS()->IgnoreParenCasts()->getIntegerConstantExpr( in checkSuppression()
1528 //===----------------------------------------------------------------------===//
1530 //===----------------------------------------------------------------------===//
1542 if (const Expr *Receiver = Message->getInstanceReceiver()) { in VisitObjCMessageExpr()
1557 // for completion handlers and can be too heavyweight for a compile-time in VisitBlockExpr()
1569 Handler.handleBlockThatIsGuaranteedToBeCalledOnce(Block->getBlockDecl()); in VisitBlockExpr()
1571 Handler.handleBlockWithNoGuarantees(Block->getBlockDecl()); in VisitBlockExpr()
1574 for (const auto &Capture : Block->getBlockDecl()->captures()) { in VisitBlockExpr()
1593 if (Op->getOpcode() == clang::BO_Assign) { in VisitBinaryOperator()
1597 checkEscapee(Op->getRHS()); in VisitBinaryOperator()
1609 for (const auto *Declaration : DS->getDeclGroup()) { in VisitDeclStmt()
1611 if (Var->getInit()) { in VisitDeclStmt()
1612 checkEscapee(Var->getInit()); in VisitDeclStmt()
1615 if (Var->hasAttr<CleanupAttr>()) { in VisitDeclStmt()
1623 // We consider '(void)parameter' as a manual no-op escape. in VisitCStyleCastExpr()
1626 if (Cast->getType().getCanonicalType()->isVoidType()) { in VisitCStyleCastExpr()
1627 checkEscapee(Cast->getSubExpr()); in VisitCStyleCastExpr()
1640 return getIndexOfExpression(Call->getCallee()); in getIndexOfCallee()
1663 return It - TrackedParams.begin(); in getIndex()