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