1*e8d8bef9SDimitry Andric //===- CalledOnceCheck.cpp - Check 'called once' parameters ---------------===// 2*e8d8bef9SDimitry Andric // 3*e8d8bef9SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*e8d8bef9SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*e8d8bef9SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*e8d8bef9SDimitry Andric // 7*e8d8bef9SDimitry Andric //===----------------------------------------------------------------------===// 8*e8d8bef9SDimitry Andric 9*e8d8bef9SDimitry Andric #include "clang/Analysis/Analyses/CalledOnceCheck.h" 10*e8d8bef9SDimitry Andric #include "clang/AST/Attr.h" 11*e8d8bef9SDimitry Andric #include "clang/AST/Decl.h" 12*e8d8bef9SDimitry Andric #include "clang/AST/DeclBase.h" 13*e8d8bef9SDimitry Andric #include "clang/AST/Expr.h" 14*e8d8bef9SDimitry Andric #include "clang/AST/ExprObjC.h" 15*e8d8bef9SDimitry Andric #include "clang/AST/OperationKinds.h" 16*e8d8bef9SDimitry Andric #include "clang/AST/ParentMap.h" 17*e8d8bef9SDimitry Andric #include "clang/AST/RecursiveASTVisitor.h" 18*e8d8bef9SDimitry Andric #include "clang/AST/Stmt.h" 19*e8d8bef9SDimitry Andric #include "clang/AST/StmtObjC.h" 20*e8d8bef9SDimitry Andric #include "clang/AST/StmtVisitor.h" 21*e8d8bef9SDimitry Andric #include "clang/AST/Type.h" 22*e8d8bef9SDimitry Andric #include "clang/Analysis/AnalysisDeclContext.h" 23*e8d8bef9SDimitry Andric #include "clang/Analysis/CFG.h" 24*e8d8bef9SDimitry Andric #include "clang/Analysis/FlowSensitive/DataflowWorklist.h" 25*e8d8bef9SDimitry Andric #include "clang/Basic/IdentifierTable.h" 26*e8d8bef9SDimitry Andric #include "clang/Basic/LLVM.h" 27*e8d8bef9SDimitry Andric #include "llvm/ADT/BitVector.h" 28*e8d8bef9SDimitry Andric #include "llvm/ADT/BitmaskEnum.h" 29*e8d8bef9SDimitry Andric #include "llvm/ADT/Optional.h" 30*e8d8bef9SDimitry Andric #include "llvm/ADT/PointerIntPair.h" 31*e8d8bef9SDimitry Andric #include "llvm/ADT/STLExtras.h" 32*e8d8bef9SDimitry Andric #include "llvm/ADT/Sequence.h" 33*e8d8bef9SDimitry Andric #include "llvm/ADT/SmallVector.h" 34*e8d8bef9SDimitry Andric #include "llvm/ADT/StringRef.h" 35*e8d8bef9SDimitry Andric #include "llvm/Support/Casting.h" 36*e8d8bef9SDimitry Andric #include "llvm/Support/Compiler.h" 37*e8d8bef9SDimitry Andric #include "llvm/Support/ErrorHandling.h" 38*e8d8bef9SDimitry Andric #include <memory> 39*e8d8bef9SDimitry Andric 40*e8d8bef9SDimitry Andric using namespace clang; 41*e8d8bef9SDimitry Andric 42*e8d8bef9SDimitry Andric namespace { 43*e8d8bef9SDimitry Andric static constexpr unsigned EXPECTED_MAX_NUMBER_OF_PARAMS = 2; 44*e8d8bef9SDimitry Andric template <class T> 45*e8d8bef9SDimitry Andric using ParamSizedVector = llvm::SmallVector<T, EXPECTED_MAX_NUMBER_OF_PARAMS>; 46*e8d8bef9SDimitry Andric static constexpr unsigned EXPECTED_NUMBER_OF_BASIC_BLOCKS = 8; 47*e8d8bef9SDimitry Andric template <class T> 48*e8d8bef9SDimitry Andric using CFGSizedVector = llvm::SmallVector<T, EXPECTED_NUMBER_OF_BASIC_BLOCKS>; 49*e8d8bef9SDimitry Andric constexpr llvm::StringLiteral CONVENTIONAL_NAMES[] = { 50*e8d8bef9SDimitry Andric "completionHandler", "completion", "withCompletionHandler"}; 51*e8d8bef9SDimitry Andric constexpr llvm::StringLiteral CONVENTIONAL_SUFFIXES[] = { 52*e8d8bef9SDimitry Andric "WithCompletionHandler", "WithCompletion"}; 53*e8d8bef9SDimitry Andric constexpr llvm::StringLiteral CONVENTIONAL_CONDITIONS[] = { 54*e8d8bef9SDimitry Andric "error", "cancel", "shouldCall", "done", "OK", "success"}; 55*e8d8bef9SDimitry Andric 56*e8d8bef9SDimitry Andric class ParameterStatus { 57*e8d8bef9SDimitry Andric public: 58*e8d8bef9SDimitry Andric // Status kind is basically the main part of parameter's status. 59*e8d8bef9SDimitry Andric // The kind represents our knowledge (so far) about a tracked parameter 60*e8d8bef9SDimitry Andric // in the context of this analysis. 61*e8d8bef9SDimitry Andric // 62*e8d8bef9SDimitry Andric // Since we want to report on missing and extraneous calls, we need to 63*e8d8bef9SDimitry Andric // track the fact whether paramater was called or not. This automatically 64*e8d8bef9SDimitry Andric // decides two kinds: `NotCalled` and `Called`. 65*e8d8bef9SDimitry Andric // 66*e8d8bef9SDimitry Andric // One of the erroneous situations is the case when parameter is called only 67*e8d8bef9SDimitry Andric // on some of the paths. We could've considered it `NotCalled`, but we want 68*e8d8bef9SDimitry Andric // to report double call warnings even if these two calls are not guaranteed 69*e8d8bef9SDimitry Andric // to happen in every execution. We also don't want to have it as `Called` 70*e8d8bef9SDimitry Andric // because not calling tracked parameter on all of the paths is an error 71*e8d8bef9SDimitry Andric // on its own. For these reasons, we need to have a separate kind, 72*e8d8bef9SDimitry Andric // `MaybeCalled`, and change `Called` to `DefinitelyCalled` to avoid 73*e8d8bef9SDimitry Andric // confusion. 74*e8d8bef9SDimitry Andric // 75*e8d8bef9SDimitry Andric // Two violations of calling parameter more than once and not calling it on 76*e8d8bef9SDimitry Andric // every path are not, however, mutually exclusive. In situations where both 77*e8d8bef9SDimitry Andric // violations take place, we prefer to report ONLY double call. It's always 78*e8d8bef9SDimitry Andric // harder to pinpoint a bug that has arisen when a user neglects to take the 79*e8d8bef9SDimitry Andric // right action (and therefore, no action is taken), than when a user takes 80*e8d8bef9SDimitry Andric // the wrong action. And, in order to remember that we already reported 81*e8d8bef9SDimitry Andric // a double call, we need another kind: `Reported`. 82*e8d8bef9SDimitry Andric // 83*e8d8bef9SDimitry Andric // Our analysis is intra-procedural and, while in the perfect world, 84*e8d8bef9SDimitry Andric // developers only use tracked parameters to call them, in the real world, 85*e8d8bef9SDimitry Andric // the picture might be different. Parameters can be stored in global 86*e8d8bef9SDimitry Andric // variables or leaked into other functions that we know nothing about. 87*e8d8bef9SDimitry Andric // We try to be lenient and trust users. Another kind `Escaped` reflects 88*e8d8bef9SDimitry Andric // such situations. We don't know if it gets called there or not, but we 89*e8d8bef9SDimitry Andric // should always think of `Escaped` as the best possible option. 90*e8d8bef9SDimitry Andric // 91*e8d8bef9SDimitry Andric // Some of the paths in the analyzed functions might end with a call 92*e8d8bef9SDimitry Andric // to noreturn functions. Such paths are not required to have parameter 93*e8d8bef9SDimitry Andric // calls and we want to track that. For the purposes of better diagnostics, 94*e8d8bef9SDimitry Andric // we don't want to reuse `Escaped` and, thus, have another kind `NoReturn`. 95*e8d8bef9SDimitry Andric // 96*e8d8bef9SDimitry Andric // Additionally, we have `NotVisited` kind that tells us nothing about 97*e8d8bef9SDimitry Andric // a tracked parameter, but is used for tracking analyzed (aka visited) 98*e8d8bef9SDimitry Andric // basic blocks. 99*e8d8bef9SDimitry Andric // 100*e8d8bef9SDimitry Andric // If we consider `|` to be a JOIN operation of two kinds coming from 101*e8d8bef9SDimitry Andric // two different paths, the following properties must hold: 102*e8d8bef9SDimitry Andric // 103*e8d8bef9SDimitry Andric // 1. for any Kind K: K | K == K 104*e8d8bef9SDimitry Andric // Joining two identical kinds should result in the same kind. 105*e8d8bef9SDimitry Andric // 106*e8d8bef9SDimitry Andric // 2. for any Kind K: Reported | K == Reported 107*e8d8bef9SDimitry Andric // Doesn't matter on which path it was reported, it still is. 108*e8d8bef9SDimitry Andric // 109*e8d8bef9SDimitry Andric // 3. for any Kind K: NoReturn | K == K 110*e8d8bef9SDimitry Andric // We can totally ignore noreturn paths during merges. 111*e8d8bef9SDimitry Andric // 112*e8d8bef9SDimitry Andric // 4. DefinitelyCalled | NotCalled == MaybeCalled 113*e8d8bef9SDimitry Andric // Called on one path, not called on another - that's simply 114*e8d8bef9SDimitry Andric // a definition for MaybeCalled. 115*e8d8bef9SDimitry Andric // 116*e8d8bef9SDimitry Andric // 5. for any Kind K in [DefinitelyCalled, NotCalled, MaybeCalled]: 117*e8d8bef9SDimitry Andric // Escaped | K == K 118*e8d8bef9SDimitry Andric // Escaped mirrors other statuses after joins. 119*e8d8bef9SDimitry Andric // Every situation, when we join any of the listed kinds K, 120*e8d8bef9SDimitry Andric // is a violation. For this reason, in order to assume the 121*e8d8bef9SDimitry Andric // best outcome for this escape, we consider it to be the 122*e8d8bef9SDimitry Andric // same as the other path. 123*e8d8bef9SDimitry Andric // 124*e8d8bef9SDimitry Andric // 6. for any Kind K in [DefinitelyCalled, NotCalled]: 125*e8d8bef9SDimitry Andric // MaybeCalled | K == MaybeCalled 126*e8d8bef9SDimitry Andric // MaybeCalled should basically stay after almost every join. 127*e8d8bef9SDimitry Andric enum Kind { 128*e8d8bef9SDimitry Andric // No-return paths should be absolutely transparent for the analysis. 129*e8d8bef9SDimitry Andric // 0x0 is the identity element for selected join operation (binary or). 130*e8d8bef9SDimitry Andric NoReturn = 0x0, /* 0000 */ 131*e8d8bef9SDimitry Andric // Escaped marks situations when marked parameter escaped into 132*e8d8bef9SDimitry Andric // another function (so we can assume that it was possibly called there). 133*e8d8bef9SDimitry Andric Escaped = 0x1, /* 0001 */ 134*e8d8bef9SDimitry Andric // Parameter was definitely called once at this point. 135*e8d8bef9SDimitry Andric DefinitelyCalled = 0x3, /* 0011 */ 136*e8d8bef9SDimitry Andric // Kinds less or equal to NON_ERROR_STATUS are not considered errors. 137*e8d8bef9SDimitry Andric NON_ERROR_STATUS = DefinitelyCalled, 138*e8d8bef9SDimitry Andric // Parameter was not yet called. 139*e8d8bef9SDimitry Andric NotCalled = 0x5, /* 0101 */ 140*e8d8bef9SDimitry Andric // Parameter was not called at least on one path leading to this point, 141*e8d8bef9SDimitry Andric // while there is also at least one path that it gets called. 142*e8d8bef9SDimitry Andric MaybeCalled = 0x7, /* 0111 */ 143*e8d8bef9SDimitry Andric // Parameter was not yet analyzed. 144*e8d8bef9SDimitry Andric NotVisited = 0x8, /* 1000 */ 145*e8d8bef9SDimitry Andric // We already reported a violation and stopped tracking calls for this 146*e8d8bef9SDimitry Andric // parameter. 147*e8d8bef9SDimitry Andric Reported = 0x15, /* 1111 */ 148*e8d8bef9SDimitry Andric LLVM_MARK_AS_BITMASK_ENUM(/* LargestValue = */ Reported) 149*e8d8bef9SDimitry Andric }; 150*e8d8bef9SDimitry Andric 151*e8d8bef9SDimitry Andric constexpr ParameterStatus() = default; 152*e8d8bef9SDimitry Andric /* implicit */ ParameterStatus(Kind K) : StatusKind(K) { 153*e8d8bef9SDimitry Andric assert(!seenAnyCalls(K) && "Can't initialize status without a call"); 154*e8d8bef9SDimitry Andric } 155*e8d8bef9SDimitry Andric ParameterStatus(Kind K, const Expr *Call) : StatusKind(K), Call(Call) { 156*e8d8bef9SDimitry Andric assert(seenAnyCalls(K) && "This kind is not supposed to have a call"); 157*e8d8bef9SDimitry Andric } 158*e8d8bef9SDimitry Andric 159*e8d8bef9SDimitry Andric const Expr &getCall() const { 160*e8d8bef9SDimitry Andric assert(seenAnyCalls(getKind()) && "ParameterStatus doesn't have a call"); 161*e8d8bef9SDimitry Andric return *Call; 162*e8d8bef9SDimitry Andric } 163*e8d8bef9SDimitry Andric static bool seenAnyCalls(Kind K) { 164*e8d8bef9SDimitry Andric return (K & DefinitelyCalled) == DefinitelyCalled && K != Reported; 165*e8d8bef9SDimitry Andric } 166*e8d8bef9SDimitry Andric bool seenAnyCalls() const { return seenAnyCalls(getKind()); } 167*e8d8bef9SDimitry Andric 168*e8d8bef9SDimitry Andric static bool isErrorStatus(Kind K) { return K > NON_ERROR_STATUS; } 169*e8d8bef9SDimitry Andric bool isErrorStatus() const { return isErrorStatus(getKind()); } 170*e8d8bef9SDimitry Andric 171*e8d8bef9SDimitry Andric Kind getKind() const { return StatusKind; } 172*e8d8bef9SDimitry Andric 173*e8d8bef9SDimitry Andric void join(const ParameterStatus &Other) { 174*e8d8bef9SDimitry Andric // If we have a pointer already, let's keep it. 175*e8d8bef9SDimitry Andric // For the purposes of the analysis, it doesn't really matter 176*e8d8bef9SDimitry Andric // which call we report. 177*e8d8bef9SDimitry Andric // 178*e8d8bef9SDimitry Andric // If we don't have a pointer, let's take whatever gets joined. 179*e8d8bef9SDimitry Andric if (!Call) { 180*e8d8bef9SDimitry Andric Call = Other.Call; 181*e8d8bef9SDimitry Andric } 182*e8d8bef9SDimitry Andric // Join kinds. 183*e8d8bef9SDimitry Andric StatusKind |= Other.getKind(); 184*e8d8bef9SDimitry Andric } 185*e8d8bef9SDimitry Andric 186*e8d8bef9SDimitry Andric bool operator==(const ParameterStatus &Other) const { 187*e8d8bef9SDimitry Andric // We compare only kinds, pointers on their own is only additional 188*e8d8bef9SDimitry Andric // information. 189*e8d8bef9SDimitry Andric return getKind() == Other.getKind(); 190*e8d8bef9SDimitry Andric } 191*e8d8bef9SDimitry Andric 192*e8d8bef9SDimitry Andric private: 193*e8d8bef9SDimitry Andric // It would've been a perfect place to use llvm::PointerIntPair, but 194*e8d8bef9SDimitry Andric // unfortunately NumLowBitsAvailable for clang::Expr had been reduced to 2. 195*e8d8bef9SDimitry Andric Kind StatusKind = NotVisited; 196*e8d8bef9SDimitry Andric const Expr *Call = nullptr; 197*e8d8bef9SDimitry Andric }; 198*e8d8bef9SDimitry Andric 199*e8d8bef9SDimitry Andric /// State aggregates statuses of all tracked parameters. 200*e8d8bef9SDimitry Andric class State { 201*e8d8bef9SDimitry Andric public: 202*e8d8bef9SDimitry Andric State(unsigned Size, ParameterStatus::Kind K = ParameterStatus::NotVisited) 203*e8d8bef9SDimitry Andric : ParamData(Size, K) {} 204*e8d8bef9SDimitry Andric 205*e8d8bef9SDimitry Andric /// Return status of a parameter with the given index. 206*e8d8bef9SDimitry Andric /// \{ 207*e8d8bef9SDimitry Andric ParameterStatus &getStatusFor(unsigned Index) { return ParamData[Index]; } 208*e8d8bef9SDimitry Andric const ParameterStatus &getStatusFor(unsigned Index) const { 209*e8d8bef9SDimitry Andric return ParamData[Index]; 210*e8d8bef9SDimitry Andric } 211*e8d8bef9SDimitry Andric /// \} 212*e8d8bef9SDimitry Andric 213*e8d8bef9SDimitry Andric /// Return true if parameter with the given index can be called. 214*e8d8bef9SDimitry Andric bool seenAnyCalls(unsigned Index) const { 215*e8d8bef9SDimitry Andric return getStatusFor(Index).seenAnyCalls(); 216*e8d8bef9SDimitry Andric } 217*e8d8bef9SDimitry Andric /// Return a reference that we consider a call. 218*e8d8bef9SDimitry Andric /// 219*e8d8bef9SDimitry Andric /// Should only be used for parameters that can be called. 220*e8d8bef9SDimitry Andric const Expr &getCallFor(unsigned Index) const { 221*e8d8bef9SDimitry Andric return getStatusFor(Index).getCall(); 222*e8d8bef9SDimitry Andric } 223*e8d8bef9SDimitry Andric /// Return status kind of parameter with the given index. 224*e8d8bef9SDimitry Andric ParameterStatus::Kind getKindFor(unsigned Index) const { 225*e8d8bef9SDimitry Andric return getStatusFor(Index).getKind(); 226*e8d8bef9SDimitry Andric } 227*e8d8bef9SDimitry Andric 228*e8d8bef9SDimitry Andric bool isVisited() const { 229*e8d8bef9SDimitry Andric return llvm::all_of(ParamData, [](const ParameterStatus &S) { 230*e8d8bef9SDimitry Andric return S.getKind() != ParameterStatus::NotVisited; 231*e8d8bef9SDimitry Andric }); 232*e8d8bef9SDimitry Andric } 233*e8d8bef9SDimitry Andric 234*e8d8bef9SDimitry Andric // Join other state into the current state. 235*e8d8bef9SDimitry Andric void join(const State &Other) { 236*e8d8bef9SDimitry Andric assert(ParamData.size() == Other.ParamData.size() && 237*e8d8bef9SDimitry Andric "Couldn't join statuses with different sizes"); 238*e8d8bef9SDimitry Andric for (auto Pair : llvm::zip(ParamData, Other.ParamData)) { 239*e8d8bef9SDimitry Andric std::get<0>(Pair).join(std::get<1>(Pair)); 240*e8d8bef9SDimitry Andric } 241*e8d8bef9SDimitry Andric } 242*e8d8bef9SDimitry Andric 243*e8d8bef9SDimitry Andric using iterator = ParamSizedVector<ParameterStatus>::iterator; 244*e8d8bef9SDimitry Andric using const_iterator = ParamSizedVector<ParameterStatus>::const_iterator; 245*e8d8bef9SDimitry Andric 246*e8d8bef9SDimitry Andric iterator begin() { return ParamData.begin(); } 247*e8d8bef9SDimitry Andric iterator end() { return ParamData.end(); } 248*e8d8bef9SDimitry Andric 249*e8d8bef9SDimitry Andric const_iterator begin() const { return ParamData.begin(); } 250*e8d8bef9SDimitry Andric const_iterator end() const { return ParamData.end(); } 251*e8d8bef9SDimitry Andric 252*e8d8bef9SDimitry Andric bool operator==(const State &Other) const { 253*e8d8bef9SDimitry Andric return ParamData == Other.ParamData; 254*e8d8bef9SDimitry Andric } 255*e8d8bef9SDimitry Andric 256*e8d8bef9SDimitry Andric private: 257*e8d8bef9SDimitry Andric ParamSizedVector<ParameterStatus> ParamData; 258*e8d8bef9SDimitry Andric }; 259*e8d8bef9SDimitry Andric 260*e8d8bef9SDimitry Andric /// A simple class that finds DeclRefExpr in the given expression. 261*e8d8bef9SDimitry Andric /// 262*e8d8bef9SDimitry Andric /// However, we don't want to find ANY nested DeclRefExpr skipping whatever 263*e8d8bef9SDimitry Andric /// expressions on our way. Only certain expressions considered "no-op" 264*e8d8bef9SDimitry Andric /// for our task are indeed skipped. 265*e8d8bef9SDimitry Andric class DeclRefFinder 266*e8d8bef9SDimitry Andric : public ConstStmtVisitor<DeclRefFinder, const DeclRefExpr *> { 267*e8d8bef9SDimitry Andric public: 268*e8d8bef9SDimitry Andric /// Find a DeclRefExpr in the given expression. 269*e8d8bef9SDimitry Andric /// 270*e8d8bef9SDimitry Andric /// In its most basic form (ShouldRetrieveFromComparisons == false), 271*e8d8bef9SDimitry Andric /// this function can be simply reduced to the following question: 272*e8d8bef9SDimitry Andric /// 273*e8d8bef9SDimitry Andric /// - If expression E is used as a function argument, could we say 274*e8d8bef9SDimitry Andric /// that DeclRefExpr nested in E is used as an argument? 275*e8d8bef9SDimitry Andric /// 276*e8d8bef9SDimitry Andric /// According to this rule, we can say that parens, casts and dereferencing 277*e8d8bef9SDimitry Andric /// (dereferencing only applied to function pointers, but this is our case) 278*e8d8bef9SDimitry Andric /// can be skipped. 279*e8d8bef9SDimitry Andric /// 280*e8d8bef9SDimitry Andric /// When we should look into comparisons the question changes to: 281*e8d8bef9SDimitry Andric /// 282*e8d8bef9SDimitry Andric /// - If expression E is used as a condition, could we say that 283*e8d8bef9SDimitry Andric /// DeclRefExpr is being checked? 284*e8d8bef9SDimitry Andric /// 285*e8d8bef9SDimitry Andric /// And even though, these are two different questions, they have quite a lot 286*e8d8bef9SDimitry Andric /// in common. Actually, we can say that whatever expression answers 287*e8d8bef9SDimitry Andric /// positively the first question also fits the second question as well. 288*e8d8bef9SDimitry Andric /// 289*e8d8bef9SDimitry Andric /// In addition, we skip binary operators == and !=, and unary opeartor !. 290*e8d8bef9SDimitry Andric static const DeclRefExpr *find(const Expr *E, 291*e8d8bef9SDimitry Andric bool ShouldRetrieveFromComparisons = false) { 292*e8d8bef9SDimitry Andric return DeclRefFinder(ShouldRetrieveFromComparisons).Visit(E); 293*e8d8bef9SDimitry Andric } 294*e8d8bef9SDimitry Andric 295*e8d8bef9SDimitry Andric const DeclRefExpr *VisitDeclRefExpr(const DeclRefExpr *DR) { return DR; } 296*e8d8bef9SDimitry Andric 297*e8d8bef9SDimitry Andric const DeclRefExpr *VisitUnaryOperator(const UnaryOperator *UO) { 298*e8d8bef9SDimitry Andric switch (UO->getOpcode()) { 299*e8d8bef9SDimitry Andric case UO_LNot: 300*e8d8bef9SDimitry Andric // We care about logical not only if we care about comparisons. 301*e8d8bef9SDimitry Andric if (!ShouldRetrieveFromComparisons) 302*e8d8bef9SDimitry Andric return nullptr; 303*e8d8bef9SDimitry Andric LLVM_FALLTHROUGH; 304*e8d8bef9SDimitry Andric // Function pointer/references can be dereferenced before a call. 305*e8d8bef9SDimitry Andric // That doesn't make it, however, any different from a regular call. 306*e8d8bef9SDimitry Andric // For this reason, dereference operation is a "no-op". 307*e8d8bef9SDimitry Andric case UO_Deref: 308*e8d8bef9SDimitry Andric return Visit(UO->getSubExpr()); 309*e8d8bef9SDimitry Andric default: 310*e8d8bef9SDimitry Andric return nullptr; 311*e8d8bef9SDimitry Andric } 312*e8d8bef9SDimitry Andric } 313*e8d8bef9SDimitry Andric 314*e8d8bef9SDimitry Andric const DeclRefExpr *VisitBinaryOperator(const BinaryOperator *BO) { 315*e8d8bef9SDimitry Andric if (!ShouldRetrieveFromComparisons) 316*e8d8bef9SDimitry Andric return nullptr; 317*e8d8bef9SDimitry Andric 318*e8d8bef9SDimitry Andric switch (BO->getOpcode()) { 319*e8d8bef9SDimitry Andric case BO_EQ: 320*e8d8bef9SDimitry Andric case BO_NE: { 321*e8d8bef9SDimitry Andric const DeclRefExpr *LHS = Visit(BO->getLHS()); 322*e8d8bef9SDimitry Andric return LHS ? LHS : Visit(BO->getRHS()); 323*e8d8bef9SDimitry Andric } 324*e8d8bef9SDimitry Andric default: 325*e8d8bef9SDimitry Andric return nullptr; 326*e8d8bef9SDimitry Andric } 327*e8d8bef9SDimitry Andric } 328*e8d8bef9SDimitry Andric 329*e8d8bef9SDimitry Andric const DeclRefExpr *VisitOpaqueValueExpr(const OpaqueValueExpr *OVE) { 330*e8d8bef9SDimitry Andric return Visit(OVE->getSourceExpr()); 331*e8d8bef9SDimitry Andric } 332*e8d8bef9SDimitry Andric 333*e8d8bef9SDimitry Andric const DeclRefExpr *VisitExpr(const Expr *E) { 334*e8d8bef9SDimitry Andric // It is a fallback method that gets called whenever the actual type 335*e8d8bef9SDimitry Andric // of the given expression is not covered. 336*e8d8bef9SDimitry Andric // 337*e8d8bef9SDimitry Andric // We first check if we have anything to skip. And then repeat the whole 338*e8d8bef9SDimitry Andric // procedure for a nested expression instead. 339*e8d8bef9SDimitry Andric const Expr *DeclutteredExpr = E->IgnoreParenCasts(); 340*e8d8bef9SDimitry Andric return E != DeclutteredExpr ? Visit(DeclutteredExpr) : nullptr; 341*e8d8bef9SDimitry Andric } 342*e8d8bef9SDimitry Andric 343*e8d8bef9SDimitry Andric private: 344*e8d8bef9SDimitry Andric DeclRefFinder(bool ShouldRetrieveFromComparisons) 345*e8d8bef9SDimitry Andric : ShouldRetrieveFromComparisons(ShouldRetrieveFromComparisons) {} 346*e8d8bef9SDimitry Andric 347*e8d8bef9SDimitry Andric bool ShouldRetrieveFromComparisons; 348*e8d8bef9SDimitry Andric }; 349*e8d8bef9SDimitry Andric 350*e8d8bef9SDimitry Andric const DeclRefExpr *findDeclRefExpr(const Expr *In, 351*e8d8bef9SDimitry Andric bool ShouldRetrieveFromComparisons = false) { 352*e8d8bef9SDimitry Andric return DeclRefFinder::find(In, ShouldRetrieveFromComparisons); 353*e8d8bef9SDimitry Andric } 354*e8d8bef9SDimitry Andric 355*e8d8bef9SDimitry Andric const ParmVarDecl * 356*e8d8bef9SDimitry Andric findReferencedParmVarDecl(const Expr *In, 357*e8d8bef9SDimitry Andric bool ShouldRetrieveFromComparisons = false) { 358*e8d8bef9SDimitry Andric if (const DeclRefExpr *DR = 359*e8d8bef9SDimitry Andric findDeclRefExpr(In, ShouldRetrieveFromComparisons)) { 360*e8d8bef9SDimitry Andric return dyn_cast<ParmVarDecl>(DR->getDecl()); 361*e8d8bef9SDimitry Andric } 362*e8d8bef9SDimitry Andric 363*e8d8bef9SDimitry Andric return nullptr; 364*e8d8bef9SDimitry Andric } 365*e8d8bef9SDimitry Andric 366*e8d8bef9SDimitry Andric /// Return conditions expression of a statement if it has one. 367*e8d8bef9SDimitry Andric const Expr *getCondition(const Stmt *S) { 368*e8d8bef9SDimitry Andric if (!S) { 369*e8d8bef9SDimitry Andric return nullptr; 370*e8d8bef9SDimitry Andric } 371*e8d8bef9SDimitry Andric 372*e8d8bef9SDimitry Andric if (const auto *If = dyn_cast<IfStmt>(S)) { 373*e8d8bef9SDimitry Andric return If->getCond(); 374*e8d8bef9SDimitry Andric } 375*e8d8bef9SDimitry Andric if (const auto *Ternary = dyn_cast<AbstractConditionalOperator>(S)) { 376*e8d8bef9SDimitry Andric return Ternary->getCond(); 377*e8d8bef9SDimitry Andric } 378*e8d8bef9SDimitry Andric 379*e8d8bef9SDimitry Andric return nullptr; 380*e8d8bef9SDimitry Andric } 381*e8d8bef9SDimitry Andric 382*e8d8bef9SDimitry Andric /// A small helper class that collects all named identifiers in the given 383*e8d8bef9SDimitry Andric /// expression. It traverses it recursively, so names from deeper levels 384*e8d8bef9SDimitry Andric /// of the AST will end up in the results. 385*e8d8bef9SDimitry Andric /// Results might have duplicate names, if this is a problem, convert to 386*e8d8bef9SDimitry Andric /// string sets afterwards. 387*e8d8bef9SDimitry Andric class NamesCollector : public RecursiveASTVisitor<NamesCollector> { 388*e8d8bef9SDimitry Andric public: 389*e8d8bef9SDimitry Andric static constexpr unsigned EXPECTED_NUMBER_OF_NAMES = 5; 390*e8d8bef9SDimitry Andric using NameCollection = 391*e8d8bef9SDimitry Andric llvm::SmallVector<llvm::StringRef, EXPECTED_NUMBER_OF_NAMES>; 392*e8d8bef9SDimitry Andric 393*e8d8bef9SDimitry Andric static NameCollection collect(const Expr *From) { 394*e8d8bef9SDimitry Andric NamesCollector Impl; 395*e8d8bef9SDimitry Andric Impl.TraverseStmt(const_cast<Expr *>(From)); 396*e8d8bef9SDimitry Andric return Impl.Result; 397*e8d8bef9SDimitry Andric } 398*e8d8bef9SDimitry Andric 399*e8d8bef9SDimitry Andric bool VisitDeclRefExpr(const DeclRefExpr *E) { 400*e8d8bef9SDimitry Andric Result.push_back(E->getDecl()->getName()); 401*e8d8bef9SDimitry Andric return true; 402*e8d8bef9SDimitry Andric } 403*e8d8bef9SDimitry Andric 404*e8d8bef9SDimitry Andric bool VisitObjCPropertyRefExpr(const ObjCPropertyRefExpr *E) { 405*e8d8bef9SDimitry Andric llvm::StringRef Name; 406*e8d8bef9SDimitry Andric 407*e8d8bef9SDimitry Andric if (E->isImplicitProperty()) { 408*e8d8bef9SDimitry Andric ObjCMethodDecl *PropertyMethodDecl = nullptr; 409*e8d8bef9SDimitry Andric if (E->isMessagingGetter()) { 410*e8d8bef9SDimitry Andric PropertyMethodDecl = E->getImplicitPropertyGetter(); 411*e8d8bef9SDimitry Andric } else { 412*e8d8bef9SDimitry Andric PropertyMethodDecl = E->getImplicitPropertySetter(); 413*e8d8bef9SDimitry Andric } 414*e8d8bef9SDimitry Andric assert(PropertyMethodDecl && 415*e8d8bef9SDimitry Andric "Implicit property must have associated declaration"); 416*e8d8bef9SDimitry Andric Name = PropertyMethodDecl->getSelector().getNameForSlot(0); 417*e8d8bef9SDimitry Andric } else { 418*e8d8bef9SDimitry Andric assert(E->isExplicitProperty()); 419*e8d8bef9SDimitry Andric Name = E->getExplicitProperty()->getName(); 420*e8d8bef9SDimitry Andric } 421*e8d8bef9SDimitry Andric 422*e8d8bef9SDimitry Andric Result.push_back(Name); 423*e8d8bef9SDimitry Andric return true; 424*e8d8bef9SDimitry Andric } 425*e8d8bef9SDimitry Andric 426*e8d8bef9SDimitry Andric private: 427*e8d8bef9SDimitry Andric NamesCollector() = default; 428*e8d8bef9SDimitry Andric NameCollection Result; 429*e8d8bef9SDimitry Andric }; 430*e8d8bef9SDimitry Andric 431*e8d8bef9SDimitry Andric /// Check whether the given expression mentions any of conventional names. 432*e8d8bef9SDimitry Andric bool mentionsAnyOfConventionalNames(const Expr *E) { 433*e8d8bef9SDimitry Andric NamesCollector::NameCollection MentionedNames = NamesCollector::collect(E); 434*e8d8bef9SDimitry Andric 435*e8d8bef9SDimitry Andric return llvm::any_of(MentionedNames, [](llvm::StringRef ConditionName) { 436*e8d8bef9SDimitry Andric return llvm::any_of( 437*e8d8bef9SDimitry Andric CONVENTIONAL_CONDITIONS, 438*e8d8bef9SDimitry Andric [ConditionName](const llvm::StringLiteral &Conventional) { 439*e8d8bef9SDimitry Andric return ConditionName.contains_lower(Conventional); 440*e8d8bef9SDimitry Andric }); 441*e8d8bef9SDimitry Andric }); 442*e8d8bef9SDimitry Andric } 443*e8d8bef9SDimitry Andric 444*e8d8bef9SDimitry Andric /// Clarification is a simple pair of a reason why parameter is not called 445*e8d8bef9SDimitry Andric /// on every path and a statement to blame. 446*e8d8bef9SDimitry Andric struct Clarification { 447*e8d8bef9SDimitry Andric NeverCalledReason Reason; 448*e8d8bef9SDimitry Andric const Stmt *Location; 449*e8d8bef9SDimitry Andric }; 450*e8d8bef9SDimitry Andric 451*e8d8bef9SDimitry Andric /// A helper class that can produce a clarification based on the given pair 452*e8d8bef9SDimitry Andric /// of basic blocks. 453*e8d8bef9SDimitry Andric class NotCalledClarifier 454*e8d8bef9SDimitry Andric : public ConstStmtVisitor<NotCalledClarifier, 455*e8d8bef9SDimitry Andric llvm::Optional<Clarification>> { 456*e8d8bef9SDimitry Andric public: 457*e8d8bef9SDimitry Andric /// The main entrypoint for the class, the function that tries to find the 458*e8d8bef9SDimitry Andric /// clarification of how to explain which sub-path starts with a CFG edge 459*e8d8bef9SDimitry Andric /// from Conditional to SuccWithoutCall. 460*e8d8bef9SDimitry Andric /// 461*e8d8bef9SDimitry Andric /// This means that this function has one precondition: 462*e8d8bef9SDimitry Andric /// SuccWithoutCall should be a successor block for Conditional. 463*e8d8bef9SDimitry Andric /// 464*e8d8bef9SDimitry Andric /// Because clarification is not needed for non-trivial pairs of blocks 465*e8d8bef9SDimitry Andric /// (i.e. SuccWithoutCall is not the only successor), it returns meaningful 466*e8d8bef9SDimitry Andric /// results only for such cases. For this very reason, the parent basic 467*e8d8bef9SDimitry Andric /// block, Conditional, is named that way, so it is clear what kind of 468*e8d8bef9SDimitry Andric /// block is expected. 469*e8d8bef9SDimitry Andric static llvm::Optional<Clarification> 470*e8d8bef9SDimitry Andric clarify(const CFGBlock *Conditional, const CFGBlock *SuccWithoutCall) { 471*e8d8bef9SDimitry Andric if (const Stmt *Terminator = Conditional->getTerminatorStmt()) { 472*e8d8bef9SDimitry Andric return NotCalledClarifier{Conditional, SuccWithoutCall}.Visit(Terminator); 473*e8d8bef9SDimitry Andric } 474*e8d8bef9SDimitry Andric return llvm::None; 475*e8d8bef9SDimitry Andric } 476*e8d8bef9SDimitry Andric 477*e8d8bef9SDimitry Andric llvm::Optional<Clarification> VisitIfStmt(const IfStmt *If) { 478*e8d8bef9SDimitry Andric return VisitBranchingBlock(If, NeverCalledReason::IfThen); 479*e8d8bef9SDimitry Andric } 480*e8d8bef9SDimitry Andric 481*e8d8bef9SDimitry Andric llvm::Optional<Clarification> 482*e8d8bef9SDimitry Andric VisitAbstractConditionalOperator(const AbstractConditionalOperator *Ternary) { 483*e8d8bef9SDimitry Andric return VisitBranchingBlock(Ternary, NeverCalledReason::IfThen); 484*e8d8bef9SDimitry Andric } 485*e8d8bef9SDimitry Andric 486*e8d8bef9SDimitry Andric llvm::Optional<Clarification> VisitSwitchStmt(const SwitchStmt *Switch) { 487*e8d8bef9SDimitry Andric const Stmt *CaseToBlame = SuccInQuestion->getLabel(); 488*e8d8bef9SDimitry Andric if (!CaseToBlame) { 489*e8d8bef9SDimitry Andric // If interesting basic block is not labeled, it means that this 490*e8d8bef9SDimitry Andric // basic block does not represent any of the cases. 491*e8d8bef9SDimitry Andric return Clarification{NeverCalledReason::SwitchSkipped, Switch}; 492*e8d8bef9SDimitry Andric } 493*e8d8bef9SDimitry Andric 494*e8d8bef9SDimitry Andric for (const SwitchCase *Case = Switch->getSwitchCaseList(); Case; 495*e8d8bef9SDimitry Andric Case = Case->getNextSwitchCase()) { 496*e8d8bef9SDimitry Andric if (Case == CaseToBlame) { 497*e8d8bef9SDimitry Andric return Clarification{NeverCalledReason::Switch, Case}; 498*e8d8bef9SDimitry Andric } 499*e8d8bef9SDimitry Andric } 500*e8d8bef9SDimitry Andric 501*e8d8bef9SDimitry Andric llvm_unreachable("Found unexpected switch structure"); 502*e8d8bef9SDimitry Andric } 503*e8d8bef9SDimitry Andric 504*e8d8bef9SDimitry Andric llvm::Optional<Clarification> VisitForStmt(const ForStmt *For) { 505*e8d8bef9SDimitry Andric return VisitBranchingBlock(For, NeverCalledReason::LoopEntered); 506*e8d8bef9SDimitry Andric } 507*e8d8bef9SDimitry Andric 508*e8d8bef9SDimitry Andric llvm::Optional<Clarification> VisitWhileStmt(const WhileStmt *While) { 509*e8d8bef9SDimitry Andric return VisitBranchingBlock(While, NeverCalledReason::LoopEntered); 510*e8d8bef9SDimitry Andric } 511*e8d8bef9SDimitry Andric 512*e8d8bef9SDimitry Andric llvm::Optional<Clarification> 513*e8d8bef9SDimitry Andric VisitBranchingBlock(const Stmt *Terminator, NeverCalledReason DefaultReason) { 514*e8d8bef9SDimitry Andric assert(Parent->succ_size() == 2 && 515*e8d8bef9SDimitry Andric "Branching block should have exactly two successors"); 516*e8d8bef9SDimitry Andric unsigned SuccessorIndex = getSuccessorIndex(Parent, SuccInQuestion); 517*e8d8bef9SDimitry Andric NeverCalledReason ActualReason = 518*e8d8bef9SDimitry Andric updateForSuccessor(DefaultReason, SuccessorIndex); 519*e8d8bef9SDimitry Andric return Clarification{ActualReason, Terminator}; 520*e8d8bef9SDimitry Andric } 521*e8d8bef9SDimitry Andric 522*e8d8bef9SDimitry Andric llvm::Optional<Clarification> VisitBinaryOperator(const BinaryOperator *) { 523*e8d8bef9SDimitry Andric // We don't want to report on short-curcuit logical operations. 524*e8d8bef9SDimitry Andric return llvm::None; 525*e8d8bef9SDimitry Andric } 526*e8d8bef9SDimitry Andric 527*e8d8bef9SDimitry Andric llvm::Optional<Clarification> VisitStmt(const Stmt *Terminator) { 528*e8d8bef9SDimitry Andric // If we got here, we didn't have a visit function for more derived 529*e8d8bef9SDimitry Andric // classes of statement that this terminator actually belongs to. 530*e8d8bef9SDimitry Andric // 531*e8d8bef9SDimitry Andric // This is not a good scenario and should not happen in practice, but 532*e8d8bef9SDimitry Andric // at least we'll warn the user. 533*e8d8bef9SDimitry Andric return Clarification{NeverCalledReason::FallbackReason, Terminator}; 534*e8d8bef9SDimitry Andric } 535*e8d8bef9SDimitry Andric 536*e8d8bef9SDimitry Andric static unsigned getSuccessorIndex(const CFGBlock *Parent, 537*e8d8bef9SDimitry Andric const CFGBlock *Child) { 538*e8d8bef9SDimitry Andric CFGBlock::const_succ_iterator It = llvm::find(Parent->succs(), Child); 539*e8d8bef9SDimitry Andric assert(It != Parent->succ_end() && 540*e8d8bef9SDimitry Andric "Given blocks should be in parent-child relationship"); 541*e8d8bef9SDimitry Andric return It - Parent->succ_begin(); 542*e8d8bef9SDimitry Andric } 543*e8d8bef9SDimitry Andric 544*e8d8bef9SDimitry Andric static NeverCalledReason 545*e8d8bef9SDimitry Andric updateForSuccessor(NeverCalledReason ReasonForTrueBranch, 546*e8d8bef9SDimitry Andric unsigned SuccessorIndex) { 547*e8d8bef9SDimitry Andric assert(SuccessorIndex <= 1); 548*e8d8bef9SDimitry Andric unsigned RawReason = 549*e8d8bef9SDimitry Andric static_cast<unsigned>(ReasonForTrueBranch) + SuccessorIndex; 550*e8d8bef9SDimitry Andric assert(RawReason <= 551*e8d8bef9SDimitry Andric static_cast<unsigned>(NeverCalledReason::LARGEST_VALUE)); 552*e8d8bef9SDimitry Andric return static_cast<NeverCalledReason>(RawReason); 553*e8d8bef9SDimitry Andric } 554*e8d8bef9SDimitry Andric 555*e8d8bef9SDimitry Andric private: 556*e8d8bef9SDimitry Andric NotCalledClarifier(const CFGBlock *Parent, const CFGBlock *SuccInQuestion) 557*e8d8bef9SDimitry Andric : Parent(Parent), SuccInQuestion(SuccInQuestion) {} 558*e8d8bef9SDimitry Andric 559*e8d8bef9SDimitry Andric const CFGBlock *Parent, *SuccInQuestion; 560*e8d8bef9SDimitry Andric }; 561*e8d8bef9SDimitry Andric 562*e8d8bef9SDimitry Andric class CalledOnceChecker : public ConstStmtVisitor<CalledOnceChecker> { 563*e8d8bef9SDimitry Andric public: 564*e8d8bef9SDimitry Andric static void check(AnalysisDeclContext &AC, CalledOnceCheckHandler &Handler, 565*e8d8bef9SDimitry Andric bool CheckConventionalParameters) { 566*e8d8bef9SDimitry Andric CalledOnceChecker(AC, Handler, CheckConventionalParameters).check(); 567*e8d8bef9SDimitry Andric } 568*e8d8bef9SDimitry Andric 569*e8d8bef9SDimitry Andric private: 570*e8d8bef9SDimitry Andric CalledOnceChecker(AnalysisDeclContext &AC, CalledOnceCheckHandler &Handler, 571*e8d8bef9SDimitry Andric bool CheckConventionalParameters) 572*e8d8bef9SDimitry Andric : FunctionCFG(*AC.getCFG()), AC(AC), Handler(Handler), 573*e8d8bef9SDimitry Andric CheckConventionalParameters(CheckConventionalParameters), 574*e8d8bef9SDimitry Andric CurrentState(0) { 575*e8d8bef9SDimitry Andric initDataStructures(); 576*e8d8bef9SDimitry Andric assert((size() == 0 || !States.empty()) && 577*e8d8bef9SDimitry Andric "Data structures are inconsistent"); 578*e8d8bef9SDimitry Andric } 579*e8d8bef9SDimitry Andric 580*e8d8bef9SDimitry Andric //===----------------------------------------------------------------------===// 581*e8d8bef9SDimitry Andric // Initializing functions 582*e8d8bef9SDimitry Andric //===----------------------------------------------------------------------===// 583*e8d8bef9SDimitry Andric 584*e8d8bef9SDimitry Andric void initDataStructures() { 585*e8d8bef9SDimitry Andric const Decl *AnalyzedDecl = AC.getDecl(); 586*e8d8bef9SDimitry Andric 587*e8d8bef9SDimitry Andric if (const auto *Function = dyn_cast<FunctionDecl>(AnalyzedDecl)) { 588*e8d8bef9SDimitry Andric findParamsToTrack(Function); 589*e8d8bef9SDimitry Andric } else if (const auto *Method = dyn_cast<ObjCMethodDecl>(AnalyzedDecl)) { 590*e8d8bef9SDimitry Andric findParamsToTrack(Method); 591*e8d8bef9SDimitry Andric } else if (const auto *Block = dyn_cast<BlockDecl>(AnalyzedDecl)) { 592*e8d8bef9SDimitry Andric findCapturesToTrack(Block); 593*e8d8bef9SDimitry Andric findParamsToTrack(Block); 594*e8d8bef9SDimitry Andric } 595*e8d8bef9SDimitry Andric 596*e8d8bef9SDimitry Andric // Have something to track, let's init states for every block from the CFG. 597*e8d8bef9SDimitry Andric if (size() != 0) { 598*e8d8bef9SDimitry Andric States = 599*e8d8bef9SDimitry Andric CFGSizedVector<State>(FunctionCFG.getNumBlockIDs(), State(size())); 600*e8d8bef9SDimitry Andric } 601*e8d8bef9SDimitry Andric } 602*e8d8bef9SDimitry Andric 603*e8d8bef9SDimitry Andric void findCapturesToTrack(const BlockDecl *Block) { 604*e8d8bef9SDimitry Andric for (const auto &Capture : Block->captures()) { 605*e8d8bef9SDimitry Andric if (const auto *P = dyn_cast<ParmVarDecl>(Capture.getVariable())) { 606*e8d8bef9SDimitry Andric // Parameter DeclContext is its owning function or method. 607*e8d8bef9SDimitry Andric const DeclContext *ParamContext = P->getDeclContext(); 608*e8d8bef9SDimitry Andric if (shouldBeCalledOnce(ParamContext, P)) { 609*e8d8bef9SDimitry Andric TrackedParams.push_back(P); 610*e8d8bef9SDimitry Andric } 611*e8d8bef9SDimitry Andric } 612*e8d8bef9SDimitry Andric } 613*e8d8bef9SDimitry Andric } 614*e8d8bef9SDimitry Andric 615*e8d8bef9SDimitry Andric template <class FunctionLikeDecl> 616*e8d8bef9SDimitry Andric void findParamsToTrack(const FunctionLikeDecl *Function) { 617*e8d8bef9SDimitry Andric for (unsigned Index : llvm::seq<unsigned>(0u, Function->param_size())) { 618*e8d8bef9SDimitry Andric if (shouldBeCalledOnce(Function, Index)) { 619*e8d8bef9SDimitry Andric TrackedParams.push_back(Function->getParamDecl(Index)); 620*e8d8bef9SDimitry Andric } 621*e8d8bef9SDimitry Andric } 622*e8d8bef9SDimitry Andric } 623*e8d8bef9SDimitry Andric 624*e8d8bef9SDimitry Andric //===----------------------------------------------------------------------===// 625*e8d8bef9SDimitry Andric // Main logic 'check' functions 626*e8d8bef9SDimitry Andric //===----------------------------------------------------------------------===// 627*e8d8bef9SDimitry Andric 628*e8d8bef9SDimitry Andric void check() { 629*e8d8bef9SDimitry Andric // Nothing to check here: we don't have marked parameters. 630*e8d8bef9SDimitry Andric if (size() == 0 || isPossiblyEmptyImpl()) 631*e8d8bef9SDimitry Andric return; 632*e8d8bef9SDimitry Andric 633*e8d8bef9SDimitry Andric assert( 634*e8d8bef9SDimitry Andric llvm::none_of(States, [](const State &S) { return S.isVisited(); }) && 635*e8d8bef9SDimitry Andric "None of the blocks should be 'visited' before the analysis"); 636*e8d8bef9SDimitry Andric 637*e8d8bef9SDimitry Andric // For our task, both backward and forward approaches suite well. 638*e8d8bef9SDimitry Andric // However, in order to report better diagnostics, we decided to go with 639*e8d8bef9SDimitry Andric // backward analysis. 640*e8d8bef9SDimitry Andric // 641*e8d8bef9SDimitry Andric // Let's consider the following CFG and how forward and backward analyses 642*e8d8bef9SDimitry Andric // will work for it. 643*e8d8bef9SDimitry Andric // 644*e8d8bef9SDimitry Andric // FORWARD: | BACKWARD: 645*e8d8bef9SDimitry Andric // #1 | #1 646*e8d8bef9SDimitry Andric // +---------+ | +-----------+ 647*e8d8bef9SDimitry Andric // | if | | |MaybeCalled| 648*e8d8bef9SDimitry Andric // +---------+ | +-----------+ 649*e8d8bef9SDimitry Andric // |NotCalled| | | if | 650*e8d8bef9SDimitry Andric // +---------+ | +-----------+ 651*e8d8bef9SDimitry Andric // / \ | / \ 652*e8d8bef9SDimitry Andric // #2 / \ #3 | #2 / \ #3 653*e8d8bef9SDimitry Andric // +----------------+ +---------+ | +----------------+ +---------+ 654*e8d8bef9SDimitry Andric // | foo() | | ... | | |DefinitelyCalled| |NotCalled| 655*e8d8bef9SDimitry Andric // +----------------+ +---------+ | +----------------+ +---------+ 656*e8d8bef9SDimitry Andric // |DefinitelyCalled| |NotCalled| | | foo() | | ... | 657*e8d8bef9SDimitry Andric // +----------------+ +---------+ | +----------------+ +---------+ 658*e8d8bef9SDimitry Andric // \ / | \ / 659*e8d8bef9SDimitry Andric // \ #4 / | \ #4 / 660*e8d8bef9SDimitry Andric // +-----------+ | +---------+ 661*e8d8bef9SDimitry Andric // | ... | | |NotCalled| 662*e8d8bef9SDimitry Andric // +-----------+ | +---------+ 663*e8d8bef9SDimitry Andric // |MaybeCalled| | | ... | 664*e8d8bef9SDimitry Andric // +-----------+ | +---------+ 665*e8d8bef9SDimitry Andric // 666*e8d8bef9SDimitry Andric // The most natural way to report lacking call in the block #3 would be to 667*e8d8bef9SDimitry Andric // message that the false branch of the if statement in the block #1 doesn't 668*e8d8bef9SDimitry Andric // have a call. And while with the forward approach we'll need to find a 669*e8d8bef9SDimitry Andric // least common ancestor or something like that to find the 'if' to blame, 670*e8d8bef9SDimitry Andric // backward analysis gives it to us out of the box. 671*e8d8bef9SDimitry Andric BackwardDataflowWorklist Worklist(FunctionCFG, AC); 672*e8d8bef9SDimitry Andric 673*e8d8bef9SDimitry Andric // Let's visit EXIT. 674*e8d8bef9SDimitry Andric const CFGBlock *Exit = &FunctionCFG.getExit(); 675*e8d8bef9SDimitry Andric assignState(Exit, State(size(), ParameterStatus::NotCalled)); 676*e8d8bef9SDimitry Andric Worklist.enqueuePredecessors(Exit); 677*e8d8bef9SDimitry Andric 678*e8d8bef9SDimitry Andric while (const CFGBlock *BB = Worklist.dequeue()) { 679*e8d8bef9SDimitry Andric assert(BB && "Worklist should filter out null blocks"); 680*e8d8bef9SDimitry Andric check(BB); 681*e8d8bef9SDimitry Andric assert(CurrentState.isVisited() && 682*e8d8bef9SDimitry Andric "After the check, basic block should be visited"); 683*e8d8bef9SDimitry Andric 684*e8d8bef9SDimitry Andric // Traverse successor basic blocks if the status of this block 685*e8d8bef9SDimitry Andric // has changed. 686*e8d8bef9SDimitry Andric if (assignState(BB, CurrentState)) { 687*e8d8bef9SDimitry Andric Worklist.enqueuePredecessors(BB); 688*e8d8bef9SDimitry Andric } 689*e8d8bef9SDimitry Andric } 690*e8d8bef9SDimitry Andric 691*e8d8bef9SDimitry Andric // Check that we have all tracked parameters at the last block. 692*e8d8bef9SDimitry Andric // As we are performing a backward version of the analysis, 693*e8d8bef9SDimitry Andric // it should be the ENTRY block. 694*e8d8bef9SDimitry Andric checkEntry(&FunctionCFG.getEntry()); 695*e8d8bef9SDimitry Andric } 696*e8d8bef9SDimitry Andric 697*e8d8bef9SDimitry Andric void check(const CFGBlock *BB) { 698*e8d8bef9SDimitry Andric // We start with a state 'inherited' from all the successors. 699*e8d8bef9SDimitry Andric CurrentState = joinSuccessors(BB); 700*e8d8bef9SDimitry Andric assert(CurrentState.isVisited() && 701*e8d8bef9SDimitry Andric "Shouldn't start with a 'not visited' state"); 702*e8d8bef9SDimitry Andric 703*e8d8bef9SDimitry Andric // This is the 'exit' situation, broken promises are probably OK 704*e8d8bef9SDimitry Andric // in such scenarios. 705*e8d8bef9SDimitry Andric if (BB->hasNoReturnElement()) { 706*e8d8bef9SDimitry Andric markNoReturn(); 707*e8d8bef9SDimitry Andric // This block still can have calls (even multiple calls) and 708*e8d8bef9SDimitry Andric // for this reason there is no early return here. 709*e8d8bef9SDimitry Andric } 710*e8d8bef9SDimitry Andric 711*e8d8bef9SDimitry Andric // We use a backward dataflow propagation and for this reason we 712*e8d8bef9SDimitry Andric // should traverse basic blocks bottom-up. 713*e8d8bef9SDimitry Andric for (const CFGElement &Element : llvm::reverse(*BB)) { 714*e8d8bef9SDimitry Andric if (Optional<CFGStmt> S = Element.getAs<CFGStmt>()) { 715*e8d8bef9SDimitry Andric check(S->getStmt()); 716*e8d8bef9SDimitry Andric } 717*e8d8bef9SDimitry Andric } 718*e8d8bef9SDimitry Andric } 719*e8d8bef9SDimitry Andric void check(const Stmt *S) { Visit(S); } 720*e8d8bef9SDimitry Andric 721*e8d8bef9SDimitry Andric void checkEntry(const CFGBlock *Entry) { 722*e8d8bef9SDimitry Andric // We finalize this algorithm with the ENTRY block because 723*e8d8bef9SDimitry Andric // we use a backward version of the analysis. This is where 724*e8d8bef9SDimitry Andric // we can judge that some of the tracked parameters are not called on 725*e8d8bef9SDimitry Andric // every path from ENTRY to EXIT. 726*e8d8bef9SDimitry Andric 727*e8d8bef9SDimitry Andric const State &EntryStatus = getState(Entry); 728*e8d8bef9SDimitry Andric llvm::BitVector NotCalledOnEveryPath(size(), false); 729*e8d8bef9SDimitry Andric llvm::BitVector NotUsedOnEveryPath(size(), false); 730*e8d8bef9SDimitry Andric 731*e8d8bef9SDimitry Andric // Check if there are no calls of the marked parameter at all 732*e8d8bef9SDimitry Andric for (const auto &IndexedStatus : llvm::enumerate(EntryStatus)) { 733*e8d8bef9SDimitry Andric const ParmVarDecl *Parameter = getParameter(IndexedStatus.index()); 734*e8d8bef9SDimitry Andric 735*e8d8bef9SDimitry Andric switch (IndexedStatus.value().getKind()) { 736*e8d8bef9SDimitry Andric case ParameterStatus::NotCalled: 737*e8d8bef9SDimitry Andric // If there were places where this parameter escapes (aka being used), 738*e8d8bef9SDimitry Andric // we can provide a more useful diagnostic by pointing at the exact 739*e8d8bef9SDimitry Andric // branches where it is not even mentioned. 740*e8d8bef9SDimitry Andric if (!hasEverEscaped(IndexedStatus.index())) { 741*e8d8bef9SDimitry Andric // This parameter is was not used at all, so we should report the 742*e8d8bef9SDimitry Andric // most generic version of the warning. 743*e8d8bef9SDimitry Andric if (isCaptured(Parameter)) { 744*e8d8bef9SDimitry Andric // We want to specify that it was captured by the block. 745*e8d8bef9SDimitry Andric Handler.handleCapturedNeverCalled(Parameter, AC.getDecl(), 746*e8d8bef9SDimitry Andric !isExplicitlyMarked(Parameter)); 747*e8d8bef9SDimitry Andric } else { 748*e8d8bef9SDimitry Andric Handler.handleNeverCalled(Parameter, 749*e8d8bef9SDimitry Andric !isExplicitlyMarked(Parameter)); 750*e8d8bef9SDimitry Andric } 751*e8d8bef9SDimitry Andric } else { 752*e8d8bef9SDimitry Andric // Mark it as 'interesting' to figure out which paths don't even 753*e8d8bef9SDimitry Andric // have escapes. 754*e8d8bef9SDimitry Andric NotUsedOnEveryPath[IndexedStatus.index()] = true; 755*e8d8bef9SDimitry Andric } 756*e8d8bef9SDimitry Andric 757*e8d8bef9SDimitry Andric break; 758*e8d8bef9SDimitry Andric case ParameterStatus::MaybeCalled: 759*e8d8bef9SDimitry Andric // If we have 'maybe called' at this point, we have an error 760*e8d8bef9SDimitry Andric // that there is at least one path where this parameter 761*e8d8bef9SDimitry Andric // is not called. 762*e8d8bef9SDimitry Andric // 763*e8d8bef9SDimitry Andric // However, reporting the warning with only that information can be 764*e8d8bef9SDimitry Andric // too vague for the users. For this reason, we mark such parameters 765*e8d8bef9SDimitry Andric // as "interesting" for further analysis. 766*e8d8bef9SDimitry Andric NotCalledOnEveryPath[IndexedStatus.index()] = true; 767*e8d8bef9SDimitry Andric break; 768*e8d8bef9SDimitry Andric default: 769*e8d8bef9SDimitry Andric break; 770*e8d8bef9SDimitry Andric } 771*e8d8bef9SDimitry Andric } 772*e8d8bef9SDimitry Andric 773*e8d8bef9SDimitry Andric // Early exit if we don't have parameters for extra analysis. 774*e8d8bef9SDimitry Andric if (NotCalledOnEveryPath.none() && NotUsedOnEveryPath.none()) 775*e8d8bef9SDimitry Andric return; 776*e8d8bef9SDimitry Andric 777*e8d8bef9SDimitry Andric // We are looking for a pair of blocks A, B so that the following is true: 778*e8d8bef9SDimitry Andric // * A is a predecessor of B 779*e8d8bef9SDimitry Andric // * B is marked as NotCalled 780*e8d8bef9SDimitry Andric // * A has at least one successor marked as either 781*e8d8bef9SDimitry Andric // Escaped or DefinitelyCalled 782*e8d8bef9SDimitry Andric // 783*e8d8bef9SDimitry Andric // In that situation, it is guaranteed that B is the first block of the path 784*e8d8bef9SDimitry Andric // where the user doesn't call or use parameter in question. 785*e8d8bef9SDimitry Andric // 786*e8d8bef9SDimitry Andric // For this reason, branch A -> B can be used for reporting. 787*e8d8bef9SDimitry Andric // 788*e8d8bef9SDimitry Andric // This part of the algorithm is guarded by a condition that the function 789*e8d8bef9SDimitry Andric // does indeed have a violation of contract. For this reason, we can 790*e8d8bef9SDimitry Andric // spend more time to find a good spot to place the warning. 791*e8d8bef9SDimitry Andric // 792*e8d8bef9SDimitry Andric // The following algorithm has the worst case complexity of O(V + E), 793*e8d8bef9SDimitry Andric // where V is the number of basic blocks in FunctionCFG, 794*e8d8bef9SDimitry Andric // E is the number of edges between blocks in FunctionCFG. 795*e8d8bef9SDimitry Andric for (const CFGBlock *BB : FunctionCFG) { 796*e8d8bef9SDimitry Andric if (!BB) 797*e8d8bef9SDimitry Andric continue; 798*e8d8bef9SDimitry Andric 799*e8d8bef9SDimitry Andric const State &BlockState = getState(BB); 800*e8d8bef9SDimitry Andric 801*e8d8bef9SDimitry Andric for (unsigned Index : llvm::seq(0u, size())) { 802*e8d8bef9SDimitry Andric // We don't want to use 'isLosingCall' here because we want to report 803*e8d8bef9SDimitry Andric // the following situation as well: 804*e8d8bef9SDimitry Andric // 805*e8d8bef9SDimitry Andric // MaybeCalled 806*e8d8bef9SDimitry Andric // | ... | 807*e8d8bef9SDimitry Andric // MaybeCalled NotCalled 808*e8d8bef9SDimitry Andric // 809*e8d8bef9SDimitry Andric // Even though successor is not 'DefinitelyCalled', it is still useful 810*e8d8bef9SDimitry Andric // to report it, it is still a path without a call. 811*e8d8bef9SDimitry Andric if (NotCalledOnEveryPath[Index] && 812*e8d8bef9SDimitry Andric BlockState.getKindFor(Index) == ParameterStatus::MaybeCalled) { 813*e8d8bef9SDimitry Andric 814*e8d8bef9SDimitry Andric findAndReportNotCalledBranches(BB, Index); 815*e8d8bef9SDimitry Andric } else if (NotUsedOnEveryPath[Index] && 816*e8d8bef9SDimitry Andric isLosingEscape(BlockState, BB, Index)) { 817*e8d8bef9SDimitry Andric 818*e8d8bef9SDimitry Andric findAndReportNotCalledBranches(BB, Index, /* IsEscape = */ true); 819*e8d8bef9SDimitry Andric } 820*e8d8bef9SDimitry Andric } 821*e8d8bef9SDimitry Andric } 822*e8d8bef9SDimitry Andric } 823*e8d8bef9SDimitry Andric 824*e8d8bef9SDimitry Andric /// Check potential call of a tracked parameter. 825*e8d8bef9SDimitry Andric void checkDirectCall(const CallExpr *Call) { 826*e8d8bef9SDimitry Andric if (auto Index = getIndexOfCallee(Call)) { 827*e8d8bef9SDimitry Andric processCallFor(*Index, Call); 828*e8d8bef9SDimitry Andric } 829*e8d8bef9SDimitry Andric } 830*e8d8bef9SDimitry Andric 831*e8d8bef9SDimitry Andric /// Check the call expression for being an indirect call of one of the tracked 832*e8d8bef9SDimitry Andric /// parameters. It is indirect in the sense that this particular call is not 833*e8d8bef9SDimitry Andric /// calling the parameter itself, but rather uses it as the argument. 834*e8d8bef9SDimitry Andric template <class CallLikeExpr> 835*e8d8bef9SDimitry Andric void checkIndirectCall(const CallLikeExpr *CallOrMessage) { 836*e8d8bef9SDimitry Andric // CallExpr::arguments does not interact nicely with llvm::enumerate. 837*e8d8bef9SDimitry Andric llvm::ArrayRef<const Expr *> Arguments = llvm::makeArrayRef( 838*e8d8bef9SDimitry Andric CallOrMessage->getArgs(), CallOrMessage->getNumArgs()); 839*e8d8bef9SDimitry Andric 840*e8d8bef9SDimitry Andric // Let's check if any of the call arguments is a point of interest. 841*e8d8bef9SDimitry Andric for (const auto &Argument : llvm::enumerate(Arguments)) { 842*e8d8bef9SDimitry Andric if (auto Index = getIndexOfExpression(Argument.value())) { 843*e8d8bef9SDimitry Andric ParameterStatus &CurrentParamStatus = CurrentState.getStatusFor(*Index); 844*e8d8bef9SDimitry Andric 845*e8d8bef9SDimitry Andric if (shouldBeCalledOnce(CallOrMessage, Argument.index())) { 846*e8d8bef9SDimitry Andric // If the corresponding parameter is marked as 'called_once' we should 847*e8d8bef9SDimitry Andric // consider it as a call. 848*e8d8bef9SDimitry Andric processCallFor(*Index, CallOrMessage); 849*e8d8bef9SDimitry Andric } else if (CurrentParamStatus.getKind() == ParameterStatus::NotCalled) { 850*e8d8bef9SDimitry Andric // Otherwise, we mark this parameter as escaped, which can be 851*e8d8bef9SDimitry Andric // interpreted both as called or not called depending on the context. 852*e8d8bef9SDimitry Andric CurrentParamStatus = ParameterStatus::Escaped; 853*e8d8bef9SDimitry Andric } 854*e8d8bef9SDimitry Andric // Otherwise, let's keep the state as it is. 855*e8d8bef9SDimitry Andric } 856*e8d8bef9SDimitry Andric } 857*e8d8bef9SDimitry Andric } 858*e8d8bef9SDimitry Andric 859*e8d8bef9SDimitry Andric /// Process call of the parameter with the given index 860*e8d8bef9SDimitry Andric void processCallFor(unsigned Index, const Expr *Call) { 861*e8d8bef9SDimitry Andric ParameterStatus &CurrentParamStatus = CurrentState.getStatusFor(Index); 862*e8d8bef9SDimitry Andric 863*e8d8bef9SDimitry Andric if (CurrentParamStatus.seenAnyCalls()) { 864*e8d8bef9SDimitry Andric 865*e8d8bef9SDimitry Andric // At this point, this parameter was called, so this is a second call. 866*e8d8bef9SDimitry Andric const ParmVarDecl *Parameter = getParameter(Index); 867*e8d8bef9SDimitry Andric Handler.handleDoubleCall( 868*e8d8bef9SDimitry Andric Parameter, &CurrentState.getCallFor(Index), Call, 869*e8d8bef9SDimitry Andric !isExplicitlyMarked(Parameter), 870*e8d8bef9SDimitry Andric // We are sure that the second call is definitely 871*e8d8bef9SDimitry Andric // going to happen if the status is 'DefinitelyCalled'. 872*e8d8bef9SDimitry Andric CurrentParamStatus.getKind() == ParameterStatus::DefinitelyCalled); 873*e8d8bef9SDimitry Andric 874*e8d8bef9SDimitry Andric // Mark this parameter as already reported on, so we don't repeat 875*e8d8bef9SDimitry Andric // warnings. 876*e8d8bef9SDimitry Andric CurrentParamStatus = ParameterStatus::Reported; 877*e8d8bef9SDimitry Andric 878*e8d8bef9SDimitry Andric } else if (CurrentParamStatus.getKind() != ParameterStatus::Reported) { 879*e8d8bef9SDimitry Andric // If we didn't report anything yet, let's mark this parameter 880*e8d8bef9SDimitry Andric // as called. 881*e8d8bef9SDimitry Andric ParameterStatus Called(ParameterStatus::DefinitelyCalled, Call); 882*e8d8bef9SDimitry Andric CurrentParamStatus = Called; 883*e8d8bef9SDimitry Andric } 884*e8d8bef9SDimitry Andric } 885*e8d8bef9SDimitry Andric 886*e8d8bef9SDimitry Andric void findAndReportNotCalledBranches(const CFGBlock *Parent, unsigned Index, 887*e8d8bef9SDimitry Andric bool IsEscape = false) { 888*e8d8bef9SDimitry Andric for (const CFGBlock *Succ : Parent->succs()) { 889*e8d8bef9SDimitry Andric if (!Succ) 890*e8d8bef9SDimitry Andric continue; 891*e8d8bef9SDimitry Andric 892*e8d8bef9SDimitry Andric if (getState(Succ).getKindFor(Index) == ParameterStatus::NotCalled) { 893*e8d8bef9SDimitry Andric assert(Parent->succ_size() >= 2 && 894*e8d8bef9SDimitry Andric "Block should have at least two successors at this point"); 895*e8d8bef9SDimitry Andric if (auto Clarification = NotCalledClarifier::clarify(Parent, Succ)) { 896*e8d8bef9SDimitry Andric const ParmVarDecl *Parameter = getParameter(Index); 897*e8d8bef9SDimitry Andric Handler.handleNeverCalled(Parameter, Clarification->Location, 898*e8d8bef9SDimitry Andric Clarification->Reason, !IsEscape, 899*e8d8bef9SDimitry Andric !isExplicitlyMarked(Parameter)); 900*e8d8bef9SDimitry Andric } 901*e8d8bef9SDimitry Andric } 902*e8d8bef9SDimitry Andric } 903*e8d8bef9SDimitry Andric } 904*e8d8bef9SDimitry Andric 905*e8d8bef9SDimitry Andric //===----------------------------------------------------------------------===// 906*e8d8bef9SDimitry Andric // Predicate functions to check parameters 907*e8d8bef9SDimitry Andric //===----------------------------------------------------------------------===// 908*e8d8bef9SDimitry Andric 909*e8d8bef9SDimitry Andric /// Return true if parameter is explicitly marked as 'called_once'. 910*e8d8bef9SDimitry Andric static bool isExplicitlyMarked(const ParmVarDecl *Parameter) { 911*e8d8bef9SDimitry Andric return Parameter->hasAttr<CalledOnceAttr>(); 912*e8d8bef9SDimitry Andric } 913*e8d8bef9SDimitry Andric 914*e8d8bef9SDimitry Andric /// Return true if the given name matches conventional pattens. 915*e8d8bef9SDimitry Andric static bool isConventional(llvm::StringRef Name) { 916*e8d8bef9SDimitry Andric return llvm::count(CONVENTIONAL_NAMES, Name) != 0; 917*e8d8bef9SDimitry Andric } 918*e8d8bef9SDimitry Andric 919*e8d8bef9SDimitry Andric /// Return true if the given name has conventional suffixes. 920*e8d8bef9SDimitry Andric static bool hasConventionalSuffix(llvm::StringRef Name) { 921*e8d8bef9SDimitry Andric return llvm::any_of(CONVENTIONAL_SUFFIXES, [Name](llvm::StringRef Suffix) { 922*e8d8bef9SDimitry Andric return Name.endswith(Suffix); 923*e8d8bef9SDimitry Andric }); 924*e8d8bef9SDimitry Andric } 925*e8d8bef9SDimitry Andric 926*e8d8bef9SDimitry Andric /// Return true if the given type can be used for conventional parameters. 927*e8d8bef9SDimitry Andric static bool isConventional(QualType Ty) { 928*e8d8bef9SDimitry Andric if (!Ty->isBlockPointerType()) { 929*e8d8bef9SDimitry Andric return false; 930*e8d8bef9SDimitry Andric } 931*e8d8bef9SDimitry Andric 932*e8d8bef9SDimitry Andric QualType BlockType = Ty->getAs<BlockPointerType>()->getPointeeType(); 933*e8d8bef9SDimitry Andric // Completion handlers should have a block type with void return type. 934*e8d8bef9SDimitry Andric return BlockType->getAs<FunctionType>()->getReturnType()->isVoidType(); 935*e8d8bef9SDimitry Andric } 936*e8d8bef9SDimitry Andric 937*e8d8bef9SDimitry Andric /// Return true if the only parameter of the function is conventional. 938*e8d8bef9SDimitry Andric static bool isOnlyParameterConventional(const FunctionDecl *Function) { 939*e8d8bef9SDimitry Andric IdentifierInfo *II = Function->getIdentifier(); 940*e8d8bef9SDimitry Andric return Function->getNumParams() == 1 && II && 941*e8d8bef9SDimitry Andric hasConventionalSuffix(II->getName()); 942*e8d8bef9SDimitry Andric } 943*e8d8bef9SDimitry Andric 944*e8d8bef9SDimitry Andric /// Return true/false if 'swift_async' attribute states that the given 945*e8d8bef9SDimitry Andric /// parameter is conventionally called once. 946*e8d8bef9SDimitry Andric /// Return llvm::None if the given declaration doesn't have 'swift_async' 947*e8d8bef9SDimitry Andric /// attribute. 948*e8d8bef9SDimitry Andric static llvm::Optional<bool> isConventionalSwiftAsync(const Decl *D, 949*e8d8bef9SDimitry Andric unsigned ParamIndex) { 950*e8d8bef9SDimitry Andric if (const SwiftAsyncAttr *A = D->getAttr<SwiftAsyncAttr>()) { 951*e8d8bef9SDimitry Andric if (A->getKind() == SwiftAsyncAttr::None) { 952*e8d8bef9SDimitry Andric return false; 953*e8d8bef9SDimitry Andric } 954*e8d8bef9SDimitry Andric 955*e8d8bef9SDimitry Andric return A->getCompletionHandlerIndex().getASTIndex() == ParamIndex; 956*e8d8bef9SDimitry Andric } 957*e8d8bef9SDimitry Andric return llvm::None; 958*e8d8bef9SDimitry Andric } 959*e8d8bef9SDimitry Andric 960*e8d8bef9SDimitry Andric /// Return true if the specified selector piece matches conventions. 961*e8d8bef9SDimitry Andric static bool isConventionalSelectorPiece(Selector MethodSelector, 962*e8d8bef9SDimitry Andric unsigned PieceIndex, 963*e8d8bef9SDimitry Andric QualType PieceType) { 964*e8d8bef9SDimitry Andric if (!isConventional(PieceType)) { 965*e8d8bef9SDimitry Andric return false; 966*e8d8bef9SDimitry Andric } 967*e8d8bef9SDimitry Andric 968*e8d8bef9SDimitry Andric if (MethodSelector.getNumArgs() == 1) { 969*e8d8bef9SDimitry Andric assert(PieceIndex == 0); 970*e8d8bef9SDimitry Andric return hasConventionalSuffix(MethodSelector.getNameForSlot(0)); 971*e8d8bef9SDimitry Andric } 972*e8d8bef9SDimitry Andric 973*e8d8bef9SDimitry Andric return isConventional(MethodSelector.getNameForSlot(PieceIndex)); 974*e8d8bef9SDimitry Andric } 975*e8d8bef9SDimitry Andric 976*e8d8bef9SDimitry Andric bool shouldBeCalledOnce(const ParmVarDecl *Parameter) const { 977*e8d8bef9SDimitry Andric return isExplicitlyMarked(Parameter) || 978*e8d8bef9SDimitry Andric (CheckConventionalParameters && 979*e8d8bef9SDimitry Andric isConventional(Parameter->getName()) && 980*e8d8bef9SDimitry Andric isConventional(Parameter->getType())); 981*e8d8bef9SDimitry Andric } 982*e8d8bef9SDimitry Andric 983*e8d8bef9SDimitry Andric bool shouldBeCalledOnce(const DeclContext *ParamContext, 984*e8d8bef9SDimitry Andric const ParmVarDecl *Param) { 985*e8d8bef9SDimitry Andric unsigned ParamIndex = Param->getFunctionScopeIndex(); 986*e8d8bef9SDimitry Andric if (const auto *Function = dyn_cast<FunctionDecl>(ParamContext)) { 987*e8d8bef9SDimitry Andric return shouldBeCalledOnce(Function, ParamIndex); 988*e8d8bef9SDimitry Andric } 989*e8d8bef9SDimitry Andric if (const auto *Method = dyn_cast<ObjCMethodDecl>(ParamContext)) { 990*e8d8bef9SDimitry Andric return shouldBeCalledOnce(Method, ParamIndex); 991*e8d8bef9SDimitry Andric } 992*e8d8bef9SDimitry Andric return shouldBeCalledOnce(Param); 993*e8d8bef9SDimitry Andric } 994*e8d8bef9SDimitry Andric 995*e8d8bef9SDimitry Andric bool shouldBeCalledOnce(const BlockDecl *Block, unsigned ParamIndex) const { 996*e8d8bef9SDimitry Andric return shouldBeCalledOnce(Block->getParamDecl(ParamIndex)); 997*e8d8bef9SDimitry Andric } 998*e8d8bef9SDimitry Andric 999*e8d8bef9SDimitry Andric bool shouldBeCalledOnce(const FunctionDecl *Function, 1000*e8d8bef9SDimitry Andric unsigned ParamIndex) const { 1001*e8d8bef9SDimitry Andric if (ParamIndex >= Function->getNumParams()) { 1002*e8d8bef9SDimitry Andric return false; 1003*e8d8bef9SDimitry Andric } 1004*e8d8bef9SDimitry Andric // 'swift_async' goes first and overrides anything else. 1005*e8d8bef9SDimitry Andric if (auto ConventionalAsync = 1006*e8d8bef9SDimitry Andric isConventionalSwiftAsync(Function, ParamIndex)) { 1007*e8d8bef9SDimitry Andric return ConventionalAsync.getValue(); 1008*e8d8bef9SDimitry Andric } 1009*e8d8bef9SDimitry Andric 1010*e8d8bef9SDimitry Andric return shouldBeCalledOnce(Function->getParamDecl(ParamIndex)) || 1011*e8d8bef9SDimitry Andric (CheckConventionalParameters && 1012*e8d8bef9SDimitry Andric isOnlyParameterConventional(Function)); 1013*e8d8bef9SDimitry Andric } 1014*e8d8bef9SDimitry Andric 1015*e8d8bef9SDimitry Andric bool shouldBeCalledOnce(const ObjCMethodDecl *Method, 1016*e8d8bef9SDimitry Andric unsigned ParamIndex) const { 1017*e8d8bef9SDimitry Andric Selector MethodSelector = Method->getSelector(); 1018*e8d8bef9SDimitry Andric if (ParamIndex >= MethodSelector.getNumArgs()) { 1019*e8d8bef9SDimitry Andric return false; 1020*e8d8bef9SDimitry Andric } 1021*e8d8bef9SDimitry Andric 1022*e8d8bef9SDimitry Andric // 'swift_async' goes first and overrides anything else. 1023*e8d8bef9SDimitry Andric if (auto ConventionalAsync = isConventionalSwiftAsync(Method, ParamIndex)) { 1024*e8d8bef9SDimitry Andric return ConventionalAsync.getValue(); 1025*e8d8bef9SDimitry Andric } 1026*e8d8bef9SDimitry Andric 1027*e8d8bef9SDimitry Andric const ParmVarDecl *Parameter = Method->getParamDecl(ParamIndex); 1028*e8d8bef9SDimitry Andric return shouldBeCalledOnce(Parameter) || 1029*e8d8bef9SDimitry Andric (CheckConventionalParameters && 1030*e8d8bef9SDimitry Andric isConventionalSelectorPiece(MethodSelector, ParamIndex, 1031*e8d8bef9SDimitry Andric Parameter->getType())); 1032*e8d8bef9SDimitry Andric } 1033*e8d8bef9SDimitry Andric 1034*e8d8bef9SDimitry Andric bool shouldBeCalledOnce(const CallExpr *Call, unsigned ParamIndex) const { 1035*e8d8bef9SDimitry Andric const FunctionDecl *Function = Call->getDirectCallee(); 1036*e8d8bef9SDimitry Andric return Function && shouldBeCalledOnce(Function, ParamIndex); 1037*e8d8bef9SDimitry Andric } 1038*e8d8bef9SDimitry Andric 1039*e8d8bef9SDimitry Andric bool shouldBeCalledOnce(const ObjCMessageExpr *Message, 1040*e8d8bef9SDimitry Andric unsigned ParamIndex) const { 1041*e8d8bef9SDimitry Andric const ObjCMethodDecl *Method = Message->getMethodDecl(); 1042*e8d8bef9SDimitry Andric return Method && ParamIndex < Method->param_size() && 1043*e8d8bef9SDimitry Andric shouldBeCalledOnce(Method, ParamIndex); 1044*e8d8bef9SDimitry Andric } 1045*e8d8bef9SDimitry Andric 1046*e8d8bef9SDimitry Andric //===----------------------------------------------------------------------===// 1047*e8d8bef9SDimitry Andric // Utility methods 1048*e8d8bef9SDimitry Andric //===----------------------------------------------------------------------===// 1049*e8d8bef9SDimitry Andric 1050*e8d8bef9SDimitry Andric bool isCaptured(const ParmVarDecl *Parameter) const { 1051*e8d8bef9SDimitry Andric if (const BlockDecl *Block = dyn_cast<BlockDecl>(AC.getDecl())) { 1052*e8d8bef9SDimitry Andric return Block->capturesVariable(Parameter); 1053*e8d8bef9SDimitry Andric } 1054*e8d8bef9SDimitry Andric return false; 1055*e8d8bef9SDimitry Andric } 1056*e8d8bef9SDimitry Andric 1057*e8d8bef9SDimitry Andric /// Return true if the analyzed function is actually a default implementation 1058*e8d8bef9SDimitry Andric /// of the method that has to be overriden. 1059*e8d8bef9SDimitry Andric /// 1060*e8d8bef9SDimitry Andric /// These functions can have tracked parameters, but wouldn't call them 1061*e8d8bef9SDimitry Andric /// because they are not designed to perform any meaningful actions. 1062*e8d8bef9SDimitry Andric /// 1063*e8d8bef9SDimitry Andric /// There are a couple of flavors of such default implementations: 1064*e8d8bef9SDimitry Andric /// 1. Empty methods or methods with a single return statement 1065*e8d8bef9SDimitry Andric /// 2. Methods that have one block with a call to no return function 1066*e8d8bef9SDimitry Andric /// 3. Methods with only assertion-like operations 1067*e8d8bef9SDimitry Andric bool isPossiblyEmptyImpl() const { 1068*e8d8bef9SDimitry Andric if (!isa<ObjCMethodDecl>(AC.getDecl())) { 1069*e8d8bef9SDimitry Andric // We care only about functions that are not supposed to be called. 1070*e8d8bef9SDimitry Andric // Only methods can be overriden. 1071*e8d8bef9SDimitry Andric return false; 1072*e8d8bef9SDimitry Andric } 1073*e8d8bef9SDimitry Andric 1074*e8d8bef9SDimitry Andric // Case #1 (without return statements) 1075*e8d8bef9SDimitry Andric if (FunctionCFG.size() == 2) { 1076*e8d8bef9SDimitry Andric // Method has only two blocks: ENTRY and EXIT. 1077*e8d8bef9SDimitry Andric // This is equivalent to empty function. 1078*e8d8bef9SDimitry Andric return true; 1079*e8d8bef9SDimitry Andric } 1080*e8d8bef9SDimitry Andric 1081*e8d8bef9SDimitry Andric // Case #2 1082*e8d8bef9SDimitry Andric if (FunctionCFG.size() == 3) { 1083*e8d8bef9SDimitry Andric const CFGBlock &Entry = FunctionCFG.getEntry(); 1084*e8d8bef9SDimitry Andric if (Entry.succ_empty()) { 1085*e8d8bef9SDimitry Andric return false; 1086*e8d8bef9SDimitry Andric } 1087*e8d8bef9SDimitry Andric 1088*e8d8bef9SDimitry Andric const CFGBlock *OnlyBlock = *Entry.succ_begin(); 1089*e8d8bef9SDimitry Andric // Method has only one block, let's see if it has a no-return 1090*e8d8bef9SDimitry Andric // element. 1091*e8d8bef9SDimitry Andric if (OnlyBlock && OnlyBlock->hasNoReturnElement()) { 1092*e8d8bef9SDimitry Andric return true; 1093*e8d8bef9SDimitry Andric } 1094*e8d8bef9SDimitry Andric // Fallthrough, CFGs with only one block can fall into #1 and #3 as well. 1095*e8d8bef9SDimitry Andric } 1096*e8d8bef9SDimitry Andric 1097*e8d8bef9SDimitry Andric // Cases #1 (return statements) and #3. 1098*e8d8bef9SDimitry Andric // 1099*e8d8bef9SDimitry Andric // It is hard to detect that something is an assertion or came 1100*e8d8bef9SDimitry Andric // from assertion. Here we use a simple heuristic: 1101*e8d8bef9SDimitry Andric // 1102*e8d8bef9SDimitry Andric // - If it came from a macro, it can be an assertion. 1103*e8d8bef9SDimitry Andric // 1104*e8d8bef9SDimitry Andric // Additionally, we can't assume a number of basic blocks or the CFG's 1105*e8d8bef9SDimitry Andric // structure because assertions might include loops and conditions. 1106*e8d8bef9SDimitry Andric return llvm::all_of(FunctionCFG, [](const CFGBlock *BB) { 1107*e8d8bef9SDimitry Andric if (!BB) { 1108*e8d8bef9SDimitry Andric // Unreachable blocks are totally fine. 1109*e8d8bef9SDimitry Andric return true; 1110*e8d8bef9SDimitry Andric } 1111*e8d8bef9SDimitry Andric 1112*e8d8bef9SDimitry Andric // Return statements can have sub-expressions that are represented as 1113*e8d8bef9SDimitry Andric // separate statements of a basic block. We should allow this. 1114*e8d8bef9SDimitry Andric // This parent map will be initialized with a parent tree for all 1115*e8d8bef9SDimitry Andric // subexpressions of the block's return statement (if it has one). 1116*e8d8bef9SDimitry Andric std::unique_ptr<ParentMap> ReturnChildren; 1117*e8d8bef9SDimitry Andric 1118*e8d8bef9SDimitry Andric return llvm::all_of( 1119*e8d8bef9SDimitry Andric llvm::reverse(*BB), // we should start with return statements, if we 1120*e8d8bef9SDimitry Andric // have any, i.e. from the bottom of the block 1121*e8d8bef9SDimitry Andric [&ReturnChildren](const CFGElement &Element) { 1122*e8d8bef9SDimitry Andric if (Optional<CFGStmt> S = Element.getAs<CFGStmt>()) { 1123*e8d8bef9SDimitry Andric const Stmt *SuspiciousStmt = S->getStmt(); 1124*e8d8bef9SDimitry Andric 1125*e8d8bef9SDimitry Andric if (isa<ReturnStmt>(SuspiciousStmt)) { 1126*e8d8bef9SDimitry Andric // Let's initialize this structure to test whether 1127*e8d8bef9SDimitry Andric // some further statement is a part of this return. 1128*e8d8bef9SDimitry Andric ReturnChildren = std::make_unique<ParentMap>( 1129*e8d8bef9SDimitry Andric const_cast<Stmt *>(SuspiciousStmt)); 1130*e8d8bef9SDimitry Andric // Return statements are allowed as part of #1. 1131*e8d8bef9SDimitry Andric return true; 1132*e8d8bef9SDimitry Andric } 1133*e8d8bef9SDimitry Andric 1134*e8d8bef9SDimitry Andric return SuspiciousStmt->getBeginLoc().isMacroID() || 1135*e8d8bef9SDimitry Andric (ReturnChildren && 1136*e8d8bef9SDimitry Andric ReturnChildren->hasParent(SuspiciousStmt)); 1137*e8d8bef9SDimitry Andric } 1138*e8d8bef9SDimitry Andric return true; 1139*e8d8bef9SDimitry Andric }); 1140*e8d8bef9SDimitry Andric }); 1141*e8d8bef9SDimitry Andric } 1142*e8d8bef9SDimitry Andric 1143*e8d8bef9SDimitry Andric /// Check if parameter with the given index has ever escaped. 1144*e8d8bef9SDimitry Andric bool hasEverEscaped(unsigned Index) const { 1145*e8d8bef9SDimitry Andric return llvm::any_of(States, [Index](const State &StateForOneBB) { 1146*e8d8bef9SDimitry Andric return StateForOneBB.getKindFor(Index) == ParameterStatus::Escaped; 1147*e8d8bef9SDimitry Andric }); 1148*e8d8bef9SDimitry Andric } 1149*e8d8bef9SDimitry Andric 1150*e8d8bef9SDimitry Andric /// Return status stored for the given basic block. 1151*e8d8bef9SDimitry Andric /// \{ 1152*e8d8bef9SDimitry Andric State &getState(const CFGBlock *BB) { 1153*e8d8bef9SDimitry Andric assert(BB); 1154*e8d8bef9SDimitry Andric return States[BB->getBlockID()]; 1155*e8d8bef9SDimitry Andric } 1156*e8d8bef9SDimitry Andric const State &getState(const CFGBlock *BB) const { 1157*e8d8bef9SDimitry Andric assert(BB); 1158*e8d8bef9SDimitry Andric return States[BB->getBlockID()]; 1159*e8d8bef9SDimitry Andric } 1160*e8d8bef9SDimitry Andric /// \} 1161*e8d8bef9SDimitry Andric 1162*e8d8bef9SDimitry Andric /// Assign status to the given basic block. 1163*e8d8bef9SDimitry Andric /// 1164*e8d8bef9SDimitry Andric /// Returns true when the stored status changed. 1165*e8d8bef9SDimitry Andric bool assignState(const CFGBlock *BB, const State &ToAssign) { 1166*e8d8bef9SDimitry Andric State &Current = getState(BB); 1167*e8d8bef9SDimitry Andric if (Current == ToAssign) { 1168*e8d8bef9SDimitry Andric return false; 1169*e8d8bef9SDimitry Andric } 1170*e8d8bef9SDimitry Andric 1171*e8d8bef9SDimitry Andric Current = ToAssign; 1172*e8d8bef9SDimitry Andric return true; 1173*e8d8bef9SDimitry Andric } 1174*e8d8bef9SDimitry Andric 1175*e8d8bef9SDimitry Andric /// Join all incoming statuses for the given basic block. 1176*e8d8bef9SDimitry Andric State joinSuccessors(const CFGBlock *BB) const { 1177*e8d8bef9SDimitry Andric auto Succs = 1178*e8d8bef9SDimitry Andric llvm::make_filter_range(BB->succs(), [this](const CFGBlock *Succ) { 1179*e8d8bef9SDimitry Andric return Succ && this->getState(Succ).isVisited(); 1180*e8d8bef9SDimitry Andric }); 1181*e8d8bef9SDimitry Andric // We came to this block from somewhere after all. 1182*e8d8bef9SDimitry Andric assert(!Succs.empty() && 1183*e8d8bef9SDimitry Andric "Basic block should have at least one visited successor"); 1184*e8d8bef9SDimitry Andric 1185*e8d8bef9SDimitry Andric State Result = getState(*Succs.begin()); 1186*e8d8bef9SDimitry Andric 1187*e8d8bef9SDimitry Andric for (const CFGBlock *Succ : llvm::drop_begin(Succs, 1)) { 1188*e8d8bef9SDimitry Andric Result.join(getState(Succ)); 1189*e8d8bef9SDimitry Andric } 1190*e8d8bef9SDimitry Andric 1191*e8d8bef9SDimitry Andric if (const Expr *Condition = getCondition(BB->getTerminatorStmt())) { 1192*e8d8bef9SDimitry Andric handleConditional(BB, Condition, Result); 1193*e8d8bef9SDimitry Andric } 1194*e8d8bef9SDimitry Andric 1195*e8d8bef9SDimitry Andric return Result; 1196*e8d8bef9SDimitry Andric } 1197*e8d8bef9SDimitry Andric 1198*e8d8bef9SDimitry Andric void handleConditional(const CFGBlock *BB, const Expr *Condition, 1199*e8d8bef9SDimitry Andric State &ToAlter) const { 1200*e8d8bef9SDimitry Andric handleParameterCheck(BB, Condition, ToAlter); 1201*e8d8bef9SDimitry Andric if (SuppressOnConventionalErrorPaths) { 1202*e8d8bef9SDimitry Andric handleConventionalCheck(BB, Condition, ToAlter); 1203*e8d8bef9SDimitry Andric } 1204*e8d8bef9SDimitry Andric } 1205*e8d8bef9SDimitry Andric 1206*e8d8bef9SDimitry Andric void handleParameterCheck(const CFGBlock *BB, const Expr *Condition, 1207*e8d8bef9SDimitry Andric State &ToAlter) const { 1208*e8d8bef9SDimitry Andric // In this function, we try to deal with the following pattern: 1209*e8d8bef9SDimitry Andric // 1210*e8d8bef9SDimitry Andric // if (parameter) 1211*e8d8bef9SDimitry Andric // parameter(...); 1212*e8d8bef9SDimitry Andric // 1213*e8d8bef9SDimitry Andric // It's not good to show a warning here because clearly 'parameter' 1214*e8d8bef9SDimitry Andric // couldn't and shouldn't be called on the 'else' path. 1215*e8d8bef9SDimitry Andric // 1216*e8d8bef9SDimitry Andric // Let's check if this if statement has a check involving one of 1217*e8d8bef9SDimitry Andric // the tracked parameters. 1218*e8d8bef9SDimitry Andric if (const ParmVarDecl *Parameter = findReferencedParmVarDecl( 1219*e8d8bef9SDimitry Andric Condition, 1220*e8d8bef9SDimitry Andric /* ShouldRetrieveFromComparisons = */ true)) { 1221*e8d8bef9SDimitry Andric if (const auto Index = getIndex(*Parameter)) { 1222*e8d8bef9SDimitry Andric ParameterStatus &CurrentStatus = ToAlter.getStatusFor(*Index); 1223*e8d8bef9SDimitry Andric 1224*e8d8bef9SDimitry Andric // We don't want to deep dive into semantics of the check and 1225*e8d8bef9SDimitry Andric // figure out if that check was for null or something else. 1226*e8d8bef9SDimitry Andric // We simply trust the user that they know what they are doing. 1227*e8d8bef9SDimitry Andric // 1228*e8d8bef9SDimitry Andric // For this reason, in the following loop we look for the 1229*e8d8bef9SDimitry Andric // best-looking option. 1230*e8d8bef9SDimitry Andric for (const CFGBlock *Succ : BB->succs()) { 1231*e8d8bef9SDimitry Andric if (!Succ) 1232*e8d8bef9SDimitry Andric continue; 1233*e8d8bef9SDimitry Andric 1234*e8d8bef9SDimitry Andric const ParameterStatus &StatusInSucc = 1235*e8d8bef9SDimitry Andric getState(Succ).getStatusFor(*Index); 1236*e8d8bef9SDimitry Andric 1237*e8d8bef9SDimitry Andric if (StatusInSucc.isErrorStatus()) { 1238*e8d8bef9SDimitry Andric continue; 1239*e8d8bef9SDimitry Andric } 1240*e8d8bef9SDimitry Andric 1241*e8d8bef9SDimitry Andric // Let's use this status instead. 1242*e8d8bef9SDimitry Andric CurrentStatus = StatusInSucc; 1243*e8d8bef9SDimitry Andric 1244*e8d8bef9SDimitry Andric if (StatusInSucc.getKind() == ParameterStatus::DefinitelyCalled) { 1245*e8d8bef9SDimitry Andric // This is the best option to have and we already found it. 1246*e8d8bef9SDimitry Andric break; 1247*e8d8bef9SDimitry Andric } 1248*e8d8bef9SDimitry Andric 1249*e8d8bef9SDimitry Andric // If we found 'Escaped' first, we still might find 'DefinitelyCalled' 1250*e8d8bef9SDimitry Andric // on the other branch. And we prefer the latter. 1251*e8d8bef9SDimitry Andric } 1252*e8d8bef9SDimitry Andric } 1253*e8d8bef9SDimitry Andric } 1254*e8d8bef9SDimitry Andric } 1255*e8d8bef9SDimitry Andric 1256*e8d8bef9SDimitry Andric void handleConventionalCheck(const CFGBlock *BB, const Expr *Condition, 1257*e8d8bef9SDimitry Andric State &ToAlter) const { 1258*e8d8bef9SDimitry Andric // Even when the analysis is technically correct, it is a widespread pattern 1259*e8d8bef9SDimitry Andric // not to call completion handlers in some scenarios. These usually have 1260*e8d8bef9SDimitry Andric // typical conditional names, such as 'error' or 'cancel'. 1261*e8d8bef9SDimitry Andric if (!mentionsAnyOfConventionalNames(Condition)) { 1262*e8d8bef9SDimitry Andric return; 1263*e8d8bef9SDimitry Andric } 1264*e8d8bef9SDimitry Andric 1265*e8d8bef9SDimitry Andric for (const auto &IndexedStatus : llvm::enumerate(ToAlter)) { 1266*e8d8bef9SDimitry Andric const ParmVarDecl *Parameter = getParameter(IndexedStatus.index()); 1267*e8d8bef9SDimitry Andric // Conventions do not apply to explicitly marked parameters. 1268*e8d8bef9SDimitry Andric if (isExplicitlyMarked(Parameter)) { 1269*e8d8bef9SDimitry Andric continue; 1270*e8d8bef9SDimitry Andric } 1271*e8d8bef9SDimitry Andric 1272*e8d8bef9SDimitry Andric ParameterStatus &CurrentStatus = IndexedStatus.value(); 1273*e8d8bef9SDimitry Andric // If we did find that on one of the branches the user uses the callback 1274*e8d8bef9SDimitry Andric // and doesn't on the other path, we believe that they know what they are 1275*e8d8bef9SDimitry Andric // doing and trust them. 1276*e8d8bef9SDimitry Andric // 1277*e8d8bef9SDimitry Andric // There are two possible scenarios for that: 1278*e8d8bef9SDimitry Andric // 1. Current status is 'MaybeCalled' and one of the branches is 1279*e8d8bef9SDimitry Andric // 'DefinitelyCalled' 1280*e8d8bef9SDimitry Andric // 2. Current status is 'NotCalled' and one of the branches is 'Escaped' 1281*e8d8bef9SDimitry Andric if (isLosingCall(ToAlter, BB, IndexedStatus.index()) || 1282*e8d8bef9SDimitry Andric isLosingEscape(ToAlter, BB, IndexedStatus.index())) { 1283*e8d8bef9SDimitry Andric CurrentStatus = ParameterStatus::Escaped; 1284*e8d8bef9SDimitry Andric } 1285*e8d8bef9SDimitry Andric } 1286*e8d8bef9SDimitry Andric } 1287*e8d8bef9SDimitry Andric 1288*e8d8bef9SDimitry Andric bool isLosingCall(const State &StateAfterJoin, const CFGBlock *JoinBlock, 1289*e8d8bef9SDimitry Andric unsigned ParameterIndex) const { 1290*e8d8bef9SDimitry Andric // Let's check if the block represents DefinitelyCalled -> MaybeCalled 1291*e8d8bef9SDimitry Andric // transition. 1292*e8d8bef9SDimitry Andric return isLosingJoin(StateAfterJoin, JoinBlock, ParameterIndex, 1293*e8d8bef9SDimitry Andric ParameterStatus::MaybeCalled, 1294*e8d8bef9SDimitry Andric ParameterStatus::DefinitelyCalled); 1295*e8d8bef9SDimitry Andric } 1296*e8d8bef9SDimitry Andric 1297*e8d8bef9SDimitry Andric bool isLosingEscape(const State &StateAfterJoin, const CFGBlock *JoinBlock, 1298*e8d8bef9SDimitry Andric unsigned ParameterIndex) const { 1299*e8d8bef9SDimitry Andric // Let's check if the block represents Escaped -> NotCalled transition. 1300*e8d8bef9SDimitry Andric return isLosingJoin(StateAfterJoin, JoinBlock, ParameterIndex, 1301*e8d8bef9SDimitry Andric ParameterStatus::NotCalled, ParameterStatus::Escaped); 1302*e8d8bef9SDimitry Andric } 1303*e8d8bef9SDimitry Andric 1304*e8d8bef9SDimitry Andric bool isLosingJoin(const State &StateAfterJoin, const CFGBlock *JoinBlock, 1305*e8d8bef9SDimitry Andric unsigned ParameterIndex, ParameterStatus::Kind AfterJoin, 1306*e8d8bef9SDimitry Andric ParameterStatus::Kind BeforeJoin) const { 1307*e8d8bef9SDimitry Andric assert(!ParameterStatus::isErrorStatus(BeforeJoin) && 1308*e8d8bef9SDimitry Andric ParameterStatus::isErrorStatus(AfterJoin) && 1309*e8d8bef9SDimitry Andric "It's not a losing join if statuses do not represent " 1310*e8d8bef9SDimitry Andric "correct-to-error transition"); 1311*e8d8bef9SDimitry Andric 1312*e8d8bef9SDimitry Andric const ParameterStatus &CurrentStatus = 1313*e8d8bef9SDimitry Andric StateAfterJoin.getStatusFor(ParameterIndex); 1314*e8d8bef9SDimitry Andric 1315*e8d8bef9SDimitry Andric return CurrentStatus.getKind() == AfterJoin && 1316*e8d8bef9SDimitry Andric anySuccessorHasStatus(JoinBlock, ParameterIndex, BeforeJoin); 1317*e8d8bef9SDimitry Andric } 1318*e8d8bef9SDimitry Andric 1319*e8d8bef9SDimitry Andric /// Return true if any of the successors of the given basic block has 1320*e8d8bef9SDimitry Andric /// a specified status for the given parameter. 1321*e8d8bef9SDimitry Andric bool anySuccessorHasStatus(const CFGBlock *Parent, unsigned ParameterIndex, 1322*e8d8bef9SDimitry Andric ParameterStatus::Kind ToFind) const { 1323*e8d8bef9SDimitry Andric return llvm::any_of( 1324*e8d8bef9SDimitry Andric Parent->succs(), [this, ParameterIndex, ToFind](const CFGBlock *Succ) { 1325*e8d8bef9SDimitry Andric return Succ && getState(Succ).getKindFor(ParameterIndex) == ToFind; 1326*e8d8bef9SDimitry Andric }); 1327*e8d8bef9SDimitry Andric } 1328*e8d8bef9SDimitry Andric 1329*e8d8bef9SDimitry Andric /// Check given expression that was discovered to escape. 1330*e8d8bef9SDimitry Andric void checkEscapee(const Expr *E) { 1331*e8d8bef9SDimitry Andric if (const ParmVarDecl *Parameter = findReferencedParmVarDecl(E)) { 1332*e8d8bef9SDimitry Andric checkEscapee(*Parameter); 1333*e8d8bef9SDimitry Andric } 1334*e8d8bef9SDimitry Andric } 1335*e8d8bef9SDimitry Andric 1336*e8d8bef9SDimitry Andric /// Check given parameter that was discovered to escape. 1337*e8d8bef9SDimitry Andric void checkEscapee(const ParmVarDecl &Parameter) { 1338*e8d8bef9SDimitry Andric if (auto Index = getIndex(Parameter)) { 1339*e8d8bef9SDimitry Andric ParameterStatus &CurrentParamStatus = CurrentState.getStatusFor(*Index); 1340*e8d8bef9SDimitry Andric 1341*e8d8bef9SDimitry Andric if (CurrentParamStatus.getKind() == ParameterStatus::NotCalled) { 1342*e8d8bef9SDimitry Andric CurrentParamStatus = ParameterStatus::Escaped; 1343*e8d8bef9SDimitry Andric } 1344*e8d8bef9SDimitry Andric } 1345*e8d8bef9SDimitry Andric } 1346*e8d8bef9SDimitry Andric 1347*e8d8bef9SDimitry Andric /// Mark all parameters in the current state as 'no-return'. 1348*e8d8bef9SDimitry Andric void markNoReturn() { 1349*e8d8bef9SDimitry Andric for (ParameterStatus &PS : CurrentState) { 1350*e8d8bef9SDimitry Andric PS = ParameterStatus::NoReturn; 1351*e8d8bef9SDimitry Andric } 1352*e8d8bef9SDimitry Andric } 1353*e8d8bef9SDimitry Andric 1354*e8d8bef9SDimitry Andric /// Check if the given assignment represents suppression and act on it. 1355*e8d8bef9SDimitry Andric void checkSuppression(const BinaryOperator *Assignment) { 1356*e8d8bef9SDimitry Andric // Suppression has the following form: 1357*e8d8bef9SDimitry Andric // parameter = 0; 1358*e8d8bef9SDimitry Andric // 0 can be of any form (NULL, nil, etc.) 1359*e8d8bef9SDimitry Andric if (auto Index = getIndexOfExpression(Assignment->getLHS())) { 1360*e8d8bef9SDimitry Andric 1361*e8d8bef9SDimitry Andric // We don't care what is written in the RHS, it could be whatever 1362*e8d8bef9SDimitry Andric // we can interpret as 0. 1363*e8d8bef9SDimitry Andric if (auto Constant = 1364*e8d8bef9SDimitry Andric Assignment->getRHS()->IgnoreParenCasts()->getIntegerConstantExpr( 1365*e8d8bef9SDimitry Andric AC.getASTContext())) { 1366*e8d8bef9SDimitry Andric 1367*e8d8bef9SDimitry Andric ParameterStatus &CurrentParamStatus = CurrentState.getStatusFor(*Index); 1368*e8d8bef9SDimitry Andric 1369*e8d8bef9SDimitry Andric if (0 == *Constant && CurrentParamStatus.seenAnyCalls()) { 1370*e8d8bef9SDimitry Andric // Even though this suppression mechanism is introduced to tackle 1371*e8d8bef9SDimitry Andric // false positives for multiple calls, the fact that the user has 1372*e8d8bef9SDimitry Andric // to use suppression can also tell us that we couldn't figure out 1373*e8d8bef9SDimitry Andric // how different paths cancel each other out. And if that is true, 1374*e8d8bef9SDimitry Andric // we will most certainly have false positives about parameters not 1375*e8d8bef9SDimitry Andric // being called on certain paths. 1376*e8d8bef9SDimitry Andric // 1377*e8d8bef9SDimitry Andric // For this reason, we abandon tracking this parameter altogether. 1378*e8d8bef9SDimitry Andric CurrentParamStatus = ParameterStatus::Reported; 1379*e8d8bef9SDimitry Andric } 1380*e8d8bef9SDimitry Andric } 1381*e8d8bef9SDimitry Andric } 1382*e8d8bef9SDimitry Andric } 1383*e8d8bef9SDimitry Andric 1384*e8d8bef9SDimitry Andric public: 1385*e8d8bef9SDimitry Andric //===----------------------------------------------------------------------===// 1386*e8d8bef9SDimitry Andric // Tree traversal methods 1387*e8d8bef9SDimitry Andric //===----------------------------------------------------------------------===// 1388*e8d8bef9SDimitry Andric 1389*e8d8bef9SDimitry Andric void VisitCallExpr(const CallExpr *Call) { 1390*e8d8bef9SDimitry Andric // This call might be a direct call, i.e. a parameter call... 1391*e8d8bef9SDimitry Andric checkDirectCall(Call); 1392*e8d8bef9SDimitry Andric // ... or an indirect call, i.e. when parameter is an argument. 1393*e8d8bef9SDimitry Andric checkIndirectCall(Call); 1394*e8d8bef9SDimitry Andric } 1395*e8d8bef9SDimitry Andric 1396*e8d8bef9SDimitry Andric void VisitObjCMessageExpr(const ObjCMessageExpr *Message) { 1397*e8d8bef9SDimitry Andric // The most common situation that we are defending against here is 1398*e8d8bef9SDimitry Andric // copying a tracked parameter. 1399*e8d8bef9SDimitry Andric if (const Expr *Receiver = Message->getInstanceReceiver()) { 1400*e8d8bef9SDimitry Andric checkEscapee(Receiver); 1401*e8d8bef9SDimitry Andric } 1402*e8d8bef9SDimitry Andric // Message expressions unlike calls, could not be direct. 1403*e8d8bef9SDimitry Andric checkIndirectCall(Message); 1404*e8d8bef9SDimitry Andric } 1405*e8d8bef9SDimitry Andric 1406*e8d8bef9SDimitry Andric void VisitBlockExpr(const BlockExpr *Block) { 1407*e8d8bef9SDimitry Andric for (const auto &Capture : Block->getBlockDecl()->captures()) { 1408*e8d8bef9SDimitry Andric // If a block captures a tracked parameter, it should be 1409*e8d8bef9SDimitry Andric // considered escaped. 1410*e8d8bef9SDimitry Andric // On one hand, blocks that do that should definitely call it on 1411*e8d8bef9SDimitry Andric // every path. However, it is not guaranteed that the block 1412*e8d8bef9SDimitry Andric // itself gets called whenever it gets created. 1413*e8d8bef9SDimitry Andric // 1414*e8d8bef9SDimitry Andric // Because we don't want to track blocks and whether they get called, 1415*e8d8bef9SDimitry Andric // we consider such parameters simply escaped. 1416*e8d8bef9SDimitry Andric if (const auto *Param = dyn_cast<ParmVarDecl>(Capture.getVariable())) { 1417*e8d8bef9SDimitry Andric checkEscapee(*Param); 1418*e8d8bef9SDimitry Andric } 1419*e8d8bef9SDimitry Andric } 1420*e8d8bef9SDimitry Andric } 1421*e8d8bef9SDimitry Andric 1422*e8d8bef9SDimitry Andric void VisitBinaryOperator(const BinaryOperator *Op) { 1423*e8d8bef9SDimitry Andric if (Op->getOpcode() == clang::BO_Assign) { 1424*e8d8bef9SDimitry Andric // Let's check if one of the tracked parameters is assigned into 1425*e8d8bef9SDimitry Andric // something, and if it is we don't want to track extra variables, so we 1426*e8d8bef9SDimitry Andric // consider it as an escapee. 1427*e8d8bef9SDimitry Andric checkEscapee(Op->getRHS()); 1428*e8d8bef9SDimitry Andric 1429*e8d8bef9SDimitry Andric // Let's check whether this assignment is a suppression. 1430*e8d8bef9SDimitry Andric checkSuppression(Op); 1431*e8d8bef9SDimitry Andric } 1432*e8d8bef9SDimitry Andric } 1433*e8d8bef9SDimitry Andric 1434*e8d8bef9SDimitry Andric void VisitDeclStmt(const DeclStmt *DS) { 1435*e8d8bef9SDimitry Andric // Variable initialization is not assignment and should be handled 1436*e8d8bef9SDimitry Andric // separately. 1437*e8d8bef9SDimitry Andric // 1438*e8d8bef9SDimitry Andric // Multiple declarations can be a part of declaration statement. 1439*e8d8bef9SDimitry Andric for (const auto *Declaration : DS->getDeclGroup()) { 1440*e8d8bef9SDimitry Andric if (const auto *Var = dyn_cast<VarDecl>(Declaration)) { 1441*e8d8bef9SDimitry Andric if (Var->getInit()) { 1442*e8d8bef9SDimitry Andric checkEscapee(Var->getInit()); 1443*e8d8bef9SDimitry Andric } 1444*e8d8bef9SDimitry Andric } 1445*e8d8bef9SDimitry Andric } 1446*e8d8bef9SDimitry Andric } 1447*e8d8bef9SDimitry Andric 1448*e8d8bef9SDimitry Andric void VisitCStyleCastExpr(const CStyleCastExpr *Cast) { 1449*e8d8bef9SDimitry Andric // We consider '(void)parameter' as a manual no-op escape. 1450*e8d8bef9SDimitry Andric // It should be used to explicitly tell the analysis that this parameter 1451*e8d8bef9SDimitry Andric // is intentionally not called on this path. 1452*e8d8bef9SDimitry Andric if (Cast->getType().getCanonicalType()->isVoidType()) { 1453*e8d8bef9SDimitry Andric checkEscapee(Cast->getSubExpr()); 1454*e8d8bef9SDimitry Andric } 1455*e8d8bef9SDimitry Andric } 1456*e8d8bef9SDimitry Andric 1457*e8d8bef9SDimitry Andric void VisitObjCAtThrowStmt(const ObjCAtThrowStmt *) { 1458*e8d8bef9SDimitry Andric // It is OK not to call marked parameters on exceptional paths. 1459*e8d8bef9SDimitry Andric markNoReturn(); 1460*e8d8bef9SDimitry Andric } 1461*e8d8bef9SDimitry Andric 1462*e8d8bef9SDimitry Andric private: 1463*e8d8bef9SDimitry Andric unsigned size() const { return TrackedParams.size(); } 1464*e8d8bef9SDimitry Andric 1465*e8d8bef9SDimitry Andric llvm::Optional<unsigned> getIndexOfCallee(const CallExpr *Call) const { 1466*e8d8bef9SDimitry Andric return getIndexOfExpression(Call->getCallee()); 1467*e8d8bef9SDimitry Andric } 1468*e8d8bef9SDimitry Andric 1469*e8d8bef9SDimitry Andric llvm::Optional<unsigned> getIndexOfExpression(const Expr *E) const { 1470*e8d8bef9SDimitry Andric if (const ParmVarDecl *Parameter = findReferencedParmVarDecl(E)) { 1471*e8d8bef9SDimitry Andric return getIndex(*Parameter); 1472*e8d8bef9SDimitry Andric } 1473*e8d8bef9SDimitry Andric 1474*e8d8bef9SDimitry Andric return llvm::None; 1475*e8d8bef9SDimitry Andric } 1476*e8d8bef9SDimitry Andric 1477*e8d8bef9SDimitry Andric llvm::Optional<unsigned> getIndex(const ParmVarDecl &Parameter) const { 1478*e8d8bef9SDimitry Andric // Expected number of parameters that we actually track is 1. 1479*e8d8bef9SDimitry Andric // 1480*e8d8bef9SDimitry Andric // Also, the maximum number of declared parameters could not be on a scale 1481*e8d8bef9SDimitry Andric // of hundreds of thousands. 1482*e8d8bef9SDimitry Andric // 1483*e8d8bef9SDimitry Andric // In this setting, linear search seems reasonable and even performs better 1484*e8d8bef9SDimitry Andric // than bisection. 1485*e8d8bef9SDimitry Andric ParamSizedVector<const ParmVarDecl *>::const_iterator It = 1486*e8d8bef9SDimitry Andric llvm::find(TrackedParams, &Parameter); 1487*e8d8bef9SDimitry Andric 1488*e8d8bef9SDimitry Andric if (It != TrackedParams.end()) { 1489*e8d8bef9SDimitry Andric return It - TrackedParams.begin(); 1490*e8d8bef9SDimitry Andric } 1491*e8d8bef9SDimitry Andric 1492*e8d8bef9SDimitry Andric return llvm::None; 1493*e8d8bef9SDimitry Andric } 1494*e8d8bef9SDimitry Andric 1495*e8d8bef9SDimitry Andric const ParmVarDecl *getParameter(unsigned Index) const { 1496*e8d8bef9SDimitry Andric assert(Index < TrackedParams.size()); 1497*e8d8bef9SDimitry Andric return TrackedParams[Index]; 1498*e8d8bef9SDimitry Andric } 1499*e8d8bef9SDimitry Andric 1500*e8d8bef9SDimitry Andric const CFG &FunctionCFG; 1501*e8d8bef9SDimitry Andric AnalysisDeclContext &AC; 1502*e8d8bef9SDimitry Andric CalledOnceCheckHandler &Handler; 1503*e8d8bef9SDimitry Andric bool CheckConventionalParameters; 1504*e8d8bef9SDimitry Andric // As of now, we turn this behavior off. So, we still are going to report 1505*e8d8bef9SDimitry Andric // missing calls on paths that look like it was intentional. 1506*e8d8bef9SDimitry Andric // Technically such reports are true positives, but they can make some users 1507*e8d8bef9SDimitry Andric // grumpy because of the sheer number of warnings. 1508*e8d8bef9SDimitry Andric // It can be turned back on if we decide that we want to have the other way 1509*e8d8bef9SDimitry Andric // around. 1510*e8d8bef9SDimitry Andric bool SuppressOnConventionalErrorPaths = false; 1511*e8d8bef9SDimitry Andric 1512*e8d8bef9SDimitry Andric State CurrentState; 1513*e8d8bef9SDimitry Andric ParamSizedVector<const ParmVarDecl *> TrackedParams; 1514*e8d8bef9SDimitry Andric CFGSizedVector<State> States; 1515*e8d8bef9SDimitry Andric }; 1516*e8d8bef9SDimitry Andric 1517*e8d8bef9SDimitry Andric } // end anonymous namespace 1518*e8d8bef9SDimitry Andric 1519*e8d8bef9SDimitry Andric namespace clang { 1520*e8d8bef9SDimitry Andric void checkCalledOnceParameters(AnalysisDeclContext &AC, 1521*e8d8bef9SDimitry Andric CalledOnceCheckHandler &Handler, 1522*e8d8bef9SDimitry Andric bool CheckConventionalParameters) { 1523*e8d8bef9SDimitry Andric CalledOnceChecker::check(AC, Handler, CheckConventionalParameters); 1524*e8d8bef9SDimitry Andric } 1525*e8d8bef9SDimitry Andric } // end namespace clang 1526