1//=== RetainSummaryManager.h - Summaries for reference counting ---*- C++ -*--//
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// This file defines summaries implementation for retain counting, which
10// implements a reference count checker for Core Foundation and Cocoa
11// on (Mac OS X).
12//
13//===----------------------------------------------------------------------===//
14
15#ifndef LLVM_CLANG_ANALYSIS_RETAINSUMMARYMANAGER_H
16#define LLVM_CLANG_ANALYSIS_RETAINSUMMARYMANAGER_H
17
18#include "llvm/ADT/DenseMap.h"
19#include "llvm/ADT/FoldingSet.h"
20#include "llvm/ADT/ImmutableMap.h"
21#include "clang/AST/Attr.h"
22#include "clang/AST/DeclCXX.h"
23#include "clang/AST/DeclObjC.h"
24#include "clang/AST/ParentMap.h"
25#include "clang/Analysis/AnyCall.h"
26#include "clang/Analysis/SelectorExtras.h"
27#include "llvm/ADT/STLExtras.h"
28#include <optional>
29
30using namespace clang;
31
32namespace clang {
33namespace ento {
34
35/// Determines the object kind of a tracked object.
36enum class ObjKind {
37 /// Indicates that the tracked object is a CF object.
38 CF,
39
40 /// Indicates that the tracked object is an Objective-C object.
41 ObjC,
42
43 /// Indicates that the tracked object could be a CF or Objective-C object.
44 AnyObj,
45
46 /// Indicates that the tracked object is a generalized object.
47 Generalized,
48
49 /// Indicates that the tracking object is a descendant of a
50 /// referenced-counted OSObject, used in the Darwin kernel.
51 OS
52};
53
54enum ArgEffectKind {
55 /// There is no effect.
56 DoNothing,
57
58 /// The argument is treated as if an -autorelease message had been sent to
59 /// the referenced object.
60 Autorelease,
61
62 /// The argument is treated as if the referenced object was deallocated.
63 Dealloc,
64
65 /// The argument has its reference count decreased by 1.
66 DecRef,
67
68 /// The argument has its reference count decreased by 1 to model
69 /// a transferred bridge cast under ARC.
70 DecRefBridgedTransferred,
71
72 /// The argument has its reference count increased by 1.
73 IncRef,
74
75 /// The argument is a pointer to a retain-counted object; on exit, the new
76 /// value of the pointer is a +0 value.
77 UnretainedOutParameter,
78
79 /// The argument is a pointer to a retain-counted object; on exit, the new
80 /// value of the pointer is a +1 value.
81 RetainedOutParameter,
82
83 /// The argument is a pointer to a retain-counted object; on exit, the new
84 /// value of the pointer is a +1 value iff the return code is zero.
85 RetainedOutParameterOnZero,
86
87 /// The argument is a pointer to a retain-counted object; on exit, the new
88 /// value of the pointer is a +1 value iff the return code is non-zero.
89 RetainedOutParameterOnNonZero,
90
91 /// The argument is treated as potentially escaping, meaning that
92 /// even when its reference count hits 0 it should be treated as still
93 /// possibly being alive as someone else *may* be holding onto the object.
94 MayEscape,
95
96 /// All typestate tracking of the object ceases. This is usually employed
97 /// when the effect of the call is completely unknown.
98 StopTracking,
99
100 /// All typestate tracking of the object ceases. Unlike StopTracking,
101 /// this is also enforced when the method body is inlined.
102 ///
103 /// In some cases, we obtain a better summary for this checker
104 /// by looking at the call site than by inlining the function.
105 /// Signifies that we should stop tracking the symbol even if
106 /// the function is inlined.
107 StopTrackingHard,
108
109 /// Performs the combined functionality of DecRef and StopTrackingHard.
110 ///
111 /// The models the effect that the called function decrements the reference
112 /// count of the argument and all typestate tracking on that argument
113 /// should cease.
114 DecRefAndStopTrackingHard,
115};
116
117/// An ArgEffect summarizes the retain count behavior on an argument or receiver
118/// to a function or method.
119class ArgEffect {
120 ArgEffectKind K;
121 ObjKind O;
122public:
123 explicit ArgEffect(ArgEffectKind K = DoNothing, ObjKind O = ObjKind::AnyObj)
124 : K(K), O(O) {}
125
126 ArgEffectKind getKind() const { return K; }
127 ObjKind getObjKind() const { return O; }
128
129 ArgEffect withKind(ArgEffectKind NewK) {
130 return ArgEffect(NewK, O);
131 }
132
133 bool operator==(const ArgEffect &Other) const {
134 return K == Other.K && O == Other.O;
135 }
136};
137
138/// RetEffect summarizes a call's retain/release behavior with respect
139/// to its return value.
140class RetEffect {
141public:
142 enum Kind {
143 /// Indicates that no retain count information is tracked for
144 /// the return value.
145 NoRet,
146
147 /// Indicates that the returned value is an owned (+1) symbol.
148 OwnedSymbol,
149
150 /// Indicates that the returned value is an object with retain count
151 /// semantics but that it is not owned (+0). This is the default
152 /// for getters, etc.
153 NotOwnedSymbol,
154
155 /// Indicates that the return value is an owned object when the
156 /// receiver is also a tracked object.
157 OwnedWhenTrackedReceiver,
158
159 // Treat this function as returning a non-tracked symbol even if
160 // the function has been inlined. This is used where the call
161 // site summary is more precise than the summary indirectly produced
162 // by inlining the function
163 NoRetHard
164 };
165
166private:
167 Kind K;
168 ObjKind O;
169
170 RetEffect(Kind k, ObjKind o = ObjKind::AnyObj) : K(k), O(o) {}
171
172public:
173 Kind getKind() const { return K; }
174
175 ObjKind getObjKind() const { return O; }
176
177 bool isOwned() const {
178 return K == OwnedSymbol || K == OwnedWhenTrackedReceiver;
179 }
180
181 bool notOwned() const {
182 return K == NotOwnedSymbol;
183 }
184
185 bool operator==(const RetEffect &Other) const {
186 return K == Other.K && O == Other.O;
187 }
188
189 static RetEffect MakeOwnedWhenTrackedReceiver() {
190 return RetEffect(OwnedWhenTrackedReceiver, ObjKind::ObjC);
191 }
192
193 static RetEffect MakeOwned(ObjKind o) {
194 return RetEffect(OwnedSymbol, o);
195 }
196 static RetEffect MakeNotOwned(ObjKind o) {
197 return RetEffect(NotOwnedSymbol, o);
198 }
199 static RetEffect MakeNoRet() {
200 return RetEffect(NoRet);
201 }
202 static RetEffect MakeNoRetHard() {
203 return RetEffect(NoRetHard);
204 }
205};
206
207/// A key identifying a summary.
208class ObjCSummaryKey {
209 IdentifierInfo* II;
210 Selector S;
211public:
212 ObjCSummaryKey(IdentifierInfo* ii, Selector s)
213 : II(ii), S(s) {}
214
215 ObjCSummaryKey(const ObjCInterfaceDecl *d, Selector s)
216 : II(d ? d->getIdentifier() : nullptr), S(s) {}
217
218 ObjCSummaryKey(Selector s)
219 : II(nullptr), S(s) {}
220
221 IdentifierInfo *getIdentifier() const { return II; }
222 Selector getSelector() const { return S; }
223};
224
225} // end namespace ento
226} // end namespace clang
227
228using namespace ento;
229
230namespace llvm {
231
232//===----------------------------------------------------------------------===//
233// Adapters for FoldingSet.
234//===----------------------------------------------------------------------===//
235template <> struct FoldingSetTrait<ArgEffect> {
236static inline void Profile(const ArgEffect X, FoldingSetNodeID &ID) {
237 ID.AddInteger(I: (unsigned) X.getKind());
238 ID.AddInteger(I: (unsigned) X.getObjKind());
239}
240};
241template <> struct FoldingSetTrait<RetEffect> {
242 static inline void Profile(const RetEffect &X, FoldingSetNodeID &ID) {
243 ID.AddInteger(I: (unsigned) X.getKind());
244 ID.AddInteger(I: (unsigned) X.getObjKind());
245}
246};
247
248template <> struct DenseMapInfo<ObjCSummaryKey> {
249 static inline ObjCSummaryKey getEmptyKey() {
250 return ObjCSummaryKey(DenseMapInfo<IdentifierInfo*>::getEmptyKey(),
251 DenseMapInfo<Selector>::getEmptyKey());
252 }
253
254 static inline ObjCSummaryKey getTombstoneKey() {
255 return ObjCSummaryKey(DenseMapInfo<IdentifierInfo*>::getTombstoneKey(),
256 DenseMapInfo<Selector>::getTombstoneKey());
257 }
258
259 static unsigned getHashValue(const ObjCSummaryKey &V) {
260 typedef std::pair<IdentifierInfo*, Selector> PairTy;
261 return DenseMapInfo<PairTy>::getHashValue(PairVal: PairTy(V.getIdentifier(),
262 V.getSelector()));
263 }
264
265 static bool isEqual(const ObjCSummaryKey& LHS, const ObjCSummaryKey& RHS) {
266 return LHS.getIdentifier() == RHS.getIdentifier() &&
267 LHS.getSelector() == RHS.getSelector();
268 }
269
270};
271
272} // end llvm namespace
273
274
275namespace clang {
276namespace ento {
277
278/// ArgEffects summarizes the effects of a function/method call on all of
279/// its arguments.
280typedef llvm::ImmutableMap<unsigned, ArgEffect> ArgEffects;
281
282/// Summary for a function with respect to ownership changes.
283class RetainSummary {
284 /// Args - a map of (index, ArgEffect) pairs, where index
285 /// specifies the argument (starting from 0). This can be sparsely
286 /// populated; arguments with no entry in Args use 'DefaultArgEffect'.
287 ArgEffects Args;
288
289 /// DefaultArgEffect - The default ArgEffect to apply to arguments that
290 /// do not have an entry in Args.
291 ArgEffect DefaultArgEffect;
292
293 /// Receiver - If this summary applies to an Objective-C message expression,
294 /// this is the effect applied to the state of the receiver.
295 ArgEffect Receiver;
296
297 /// Effect on "this" pointer - applicable only to C++ method calls.
298 ArgEffect This;
299
300 /// Ret - The effect on the return value. Used to indicate if the
301 /// function/method call returns a new tracked symbol.
302 RetEffect Ret;
303
304public:
305 RetainSummary(ArgEffects A,
306 RetEffect R,
307 ArgEffect defaultEff,
308 ArgEffect ReceiverEff,
309 ArgEffect ThisEff)
310 : Args(A), DefaultArgEffect(defaultEff), Receiver(ReceiverEff),
311 This(ThisEff), Ret(R) {}
312
313 /// getArg - Return the argument effect on the argument specified by
314 /// idx (starting from 0).
315 ArgEffect getArg(unsigned idx) const {
316 if (const ArgEffect *AE = Args.lookup(K: idx))
317 return *AE;
318
319 return DefaultArgEffect;
320 }
321
322 void addArg(ArgEffects::Factory &af, unsigned idx, ArgEffect e) {
323 Args = af.add(Old: Args, K: idx, D: e);
324 }
325
326 /// setDefaultArgEffect - Set the default argument effect.
327 void setDefaultArgEffect(ArgEffect E) {
328 DefaultArgEffect = E;
329 }
330
331 /// getRetEffect - Returns the effect on the return value of the call.
332 RetEffect getRetEffect() const { return Ret; }
333
334 /// setRetEffect - Set the effect of the return value of the call.
335 void setRetEffect(RetEffect E) { Ret = E; }
336
337
338 /// Sets the effect on the receiver of the message.
339 void setReceiverEffect(ArgEffect e) { Receiver = e; }
340
341 /// getReceiverEffect - Returns the effect on the receiver of the call.
342 /// This is only meaningful if the summary applies to an ObjCMessageExpr*.
343 ArgEffect getReceiverEffect() const { return Receiver; }
344
345 /// \return the effect on the "this" receiver of the method call.
346 /// This is only meaningful if the summary applies to CXXMethodDecl*.
347 ArgEffect getThisEffect() const { return This; }
348
349 ArgEffect getDefaultEffect() const { return DefaultArgEffect; }
350
351 /// Set the effect of the method on "this".
352 void setThisEffect(ArgEffect e) { This = e; }
353
354 bool isNoop() const {
355 return Ret == RetEffect::MakeNoRet() && Receiver.getKind() == DoNothing
356 && DefaultArgEffect.getKind() == MayEscape && This.getKind() == DoNothing
357 && Args.isEmpty();
358 }
359
360 /// Test if two retain summaries are identical. Note that merely equivalent
361 /// summaries are not necessarily identical (for example, if an explicit
362 /// argument effect matches the default effect).
363 bool operator==(const RetainSummary &Other) const {
364 return Args == Other.Args && DefaultArgEffect == Other.DefaultArgEffect &&
365 Receiver == Other.Receiver && This == Other.This && Ret == Other.Ret;
366 }
367
368 /// Profile this summary for inclusion in a FoldingSet.
369 void Profile(llvm::FoldingSetNodeID& ID) const {
370 ID.Add(x: Args);
371 ID.Add(x: DefaultArgEffect);
372 ID.Add(x: Receiver);
373 ID.Add(x: This);
374 ID.Add(x: Ret);
375 }
376
377 /// A retain summary is simple if it has no ArgEffects other than the default.
378 bool isSimple() const {
379 return Args.isEmpty();
380 }
381
382 ArgEffects getArgEffects() const { return Args; }
383
384private:
385 ArgEffect getDefaultArgEffect() const { return DefaultArgEffect; }
386
387 friend class RetainSummaryManager;
388};
389
390class ObjCSummaryCache {
391 typedef llvm::DenseMap<ObjCSummaryKey, const RetainSummary *> MapTy;
392 MapTy M;
393public:
394 ObjCSummaryCache() {}
395
396 const RetainSummary * find(const ObjCInterfaceDecl *D, Selector S) {
397 // Do a lookup with the (D,S) pair. If we find a match return
398 // the iterator.
399 ObjCSummaryKey K(D, S);
400 MapTy::iterator I = M.find(Val: K);
401
402 if (I != M.end())
403 return I->second;
404 if (!D)
405 return nullptr;
406
407 // Walk the super chain. If we find a hit with a parent, we'll end
408 // up returning that summary. We actually allow that key (null,S), as
409 // we cache summaries for the null ObjCInterfaceDecl* to allow us to
410 // generate initial summaries without having to worry about NSObject
411 // being declared.
412 // FIXME: We may change this at some point.
413 for (ObjCInterfaceDecl *C=D->getSuperClass() ;; C=C->getSuperClass()) {
414 if ((I = M.find(Val: ObjCSummaryKey(C, S))) != M.end())
415 break;
416
417 if (!C)
418 return nullptr;
419 }
420
421 // Cache the summary with original key to make the next lookup faster
422 // and return the iterator.
423 const RetainSummary *Summ = I->second;
424 M[K] = Summ;
425 return Summ;
426 }
427
428 const RetainSummary *find(IdentifierInfo* II, Selector S) {
429 // FIXME: Class method lookup. Right now we don't have a good way
430 // of going between IdentifierInfo* and the class hierarchy.
431 MapTy::iterator I = M.find(Val: ObjCSummaryKey(II, S));
432
433 if (I == M.end())
434 I = M.find(Val: ObjCSummaryKey(S));
435
436 return I == M.end() ? nullptr : I->second;
437 }
438
439 const RetainSummary *& operator[](ObjCSummaryKey K) {
440 return M[K];
441 }
442
443 const RetainSummary *& operator[](Selector S) {
444 return M[ ObjCSummaryKey(S) ];
445 }
446};
447
448class RetainSummaryTemplate;
449
450class RetainSummaryManager {
451 typedef llvm::DenseMap<const FunctionDecl*, const RetainSummary *>
452 FuncSummariesTy;
453
454 typedef ObjCSummaryCache ObjCMethodSummariesTy;
455
456 typedef llvm::FoldingSetNodeWrapper<RetainSummary> CachedSummaryNode;
457
458 /// Ctx - The ASTContext object for the analyzed ASTs.
459 ASTContext &Ctx;
460
461 /// Records whether or not the analyzed code runs in ARC mode.
462 const bool ARCEnabled;
463
464 /// Track Objective-C and CoreFoundation objects.
465 const bool TrackObjCAndCFObjects;
466
467 /// Track sublcasses of OSObject.
468 const bool TrackOSObjects;
469
470 /// FuncSummaries - A map from FunctionDecls to summaries.
471 FuncSummariesTy FuncSummaries;
472
473 /// ObjCClassMethodSummaries - A map from selectors (for instance methods)
474 /// to summaries.
475 ObjCMethodSummariesTy ObjCClassMethodSummaries;
476
477 /// ObjCMethodSummaries - A map from selectors to summaries.
478 ObjCMethodSummariesTy ObjCMethodSummaries;
479
480 /// BPAlloc - A BumpPtrAllocator used for allocating summaries, ArgEffects,
481 /// and all other data used by the checker.
482 llvm::BumpPtrAllocator BPAlloc;
483
484 /// AF - A factory for ArgEffects objects.
485 ArgEffects::Factory AF;
486
487 /// ObjCAllocRetE - Default return effect for methods returning Objective-C
488 /// objects.
489 RetEffect ObjCAllocRetE;
490
491 /// ObjCInitRetE - Default return effect for init methods returning
492 /// Objective-C objects.
493 RetEffect ObjCInitRetE;
494
495 /// SimpleSummaries - Used for uniquing summaries that don't have special
496 /// effects.
497 llvm::FoldingSet<CachedSummaryNode> SimpleSummaries;
498
499 /// Create an OS object at +1.
500 const RetainSummary *getOSSummaryCreateRule(const FunctionDecl *FD);
501
502 /// Get an OS object at +0.
503 const RetainSummary *getOSSummaryGetRule(const FunctionDecl *FD);
504
505 /// Increment the reference count on OS object.
506 const RetainSummary *getOSSummaryRetainRule(const FunctionDecl *FD);
507
508 /// Decrement the reference count on OS object.
509 const RetainSummary *getOSSummaryReleaseRule(const FunctionDecl *FD);
510
511 /// Free the OS object.
512 const RetainSummary *getOSSummaryFreeRule(const FunctionDecl *FD);
513
514 const RetainSummary *getUnarySummary(const FunctionType* FT,
515 ArgEffectKind AE);
516
517 const RetainSummary *getCFSummaryCreateRule(const FunctionDecl *FD);
518 const RetainSummary *getCFSummaryGetRule(const FunctionDecl *FD);
519 const RetainSummary *getCFCreateGetRuleSummary(const FunctionDecl *FD);
520
521 const RetainSummary *getPersistentSummary(const RetainSummary &OldSumm);
522
523 const RetainSummary *
524 getPersistentSummary(RetEffect RetEff, ArgEffects ScratchArgs,
525 ArgEffect ReceiverEff = ArgEffect(DoNothing),
526 ArgEffect DefaultEff = ArgEffect(MayEscape),
527 ArgEffect ThisEff = ArgEffect(DoNothing)) {
528 RetainSummary Summ(ScratchArgs, RetEff, DefaultEff, ReceiverEff, ThisEff);
529 return getPersistentSummary(OldSumm: Summ);
530 }
531
532 const RetainSummary *getDoNothingSummary() {
533 return getPersistentSummary(RetEff: RetEffect::MakeNoRet(),
534 ScratchArgs: ArgEffects(AF.getEmptyMap()),
535 ReceiverEff: ArgEffect(DoNothing), DefaultEff: ArgEffect(DoNothing));
536 }
537
538 const RetainSummary *getDefaultSummary() {
539 return getPersistentSummary(RetEff: RetEffect::MakeNoRet(),
540 ScratchArgs: ArgEffects(AF.getEmptyMap()),
541 ReceiverEff: ArgEffect(DoNothing), DefaultEff: ArgEffect(MayEscape));
542 }
543
544 const RetainSummary *getPersistentStopSummary() {
545 return getPersistentSummary(
546 RetEff: RetEffect::MakeNoRet(), ScratchArgs: ArgEffects(AF.getEmptyMap()),
547 ReceiverEff: ArgEffect(StopTracking), DefaultEff: ArgEffect(StopTracking));
548 }
549
550 void InitializeClassMethodSummaries();
551 void InitializeMethodSummaries();
552
553 void addNSObjectClsMethSummary(Selector S, const RetainSummary *Summ) {
554 ObjCClassMethodSummaries[S] = Summ;
555 }
556
557 void addNSObjectMethSummary(Selector S, const RetainSummary *Summ) {
558 ObjCMethodSummaries[S] = Summ;
559 }
560
561 void addClassMethSummary(const char* Cls, const char* name,
562 const RetainSummary *Summ, bool isNullary = true) {
563 IdentifierInfo* ClsII = &Ctx.Idents.get(Name: Cls);
564 Selector S = isNullary ? GetNullarySelector(name, Ctx)
565 : GetUnarySelector(name, Ctx);
566 ObjCClassMethodSummaries[ObjCSummaryKey(ClsII, S)] = Summ;
567 }
568
569 void addInstMethSummary(const char* Cls, const char* nullaryName,
570 const RetainSummary *Summ) {
571 IdentifierInfo* ClsII = &Ctx.Idents.get(Name: Cls);
572 Selector S = GetNullarySelector(name: nullaryName, Ctx);
573 ObjCMethodSummaries[ObjCSummaryKey(ClsII, S)] = Summ;
574 }
575
576 template <typename... Keywords>
577 void addMethodSummary(IdentifierInfo *ClsII, ObjCMethodSummariesTy &Summaries,
578 const RetainSummary *Summ, Keywords *... Kws) {
579 Selector S = getKeywordSelector(Ctx, Kws...);
580 Summaries[ObjCSummaryKey(ClsII, S)] = Summ;
581 }
582
583 template <typename... Keywords>
584 void addInstMethSummary(const char *Cls, const RetainSummary *Summ,
585 Keywords *... Kws) {
586 addMethodSummary(&Ctx.Idents.get(Name: Cls), ObjCMethodSummaries, Summ, Kws...);
587 }
588
589 template <typename... Keywords>
590 void addClsMethSummary(const char *Cls, const RetainSummary *Summ,
591 Keywords *... Kws) {
592 addMethodSummary(&Ctx.Idents.get(Name: Cls), ObjCClassMethodSummaries, Summ,
593 Kws...);
594 }
595
596 template <typename... Keywords>
597 void addClsMethSummary(IdentifierInfo *II, const RetainSummary *Summ,
598 Keywords *... Kws) {
599 addMethodSummary(II, ObjCClassMethodSummaries, Summ, Kws...);
600 }
601
602 const RetainSummary * generateSummary(const FunctionDecl *FD,
603 bool &AllowAnnotations);
604
605 /// Return a summary for OSObject, or nullptr if not found.
606 const RetainSummary *getSummaryForOSObject(const FunctionDecl *FD,
607 StringRef FName, QualType RetTy);
608
609 /// Return a summary for Objective-C or CF object, or nullptr if not found.
610 const RetainSummary *getSummaryForObjCOrCFObject(
611 const FunctionDecl *FD,
612 StringRef FName,
613 QualType RetTy,
614 const FunctionType *FT,
615 bool &AllowAnnotations);
616
617 /// Apply the annotation of @c pd in function @c FD
618 /// to the resulting summary stored in out-parameter @c Template.
619 /// \return whether an annotation was applied.
620 bool applyParamAnnotationEffect(const ParmVarDecl *pd, unsigned parm_idx,
621 const NamedDecl *FD,
622 RetainSummaryTemplate &Template);
623
624public:
625 RetainSummaryManager(ASTContext &ctx, bool trackObjCAndCFObjects,
626 bool trackOSObjects)
627 : Ctx(ctx), ARCEnabled((bool)Ctx.getLangOpts().ObjCAutoRefCount),
628 TrackObjCAndCFObjects(trackObjCAndCFObjects),
629 TrackOSObjects(trackOSObjects), AF(BPAlloc),
630 ObjCAllocRetE(ARCEnabled ? RetEffect::MakeNotOwned(o: ObjKind::ObjC)
631 : RetEffect::MakeOwned(o: ObjKind::ObjC)),
632 ObjCInitRetE(ARCEnabled ? RetEffect::MakeNotOwned(o: ObjKind::ObjC)
633 : RetEffect::MakeOwnedWhenTrackedReceiver()) {
634 InitializeClassMethodSummaries();
635 InitializeMethodSummaries();
636 }
637
638 enum class BehaviorSummary {
639 // Function does not return.
640 NoOp,
641
642 // Function returns the first argument.
643 Identity,
644
645 // Function returns "this" argument.
646 IdentityThis,
647
648 // Function either returns zero, or the input parameter.
649 IdentityOrZero
650 };
651
652 std::optional<BehaviorSummary>
653 canEval(const CallExpr *CE, const FunctionDecl *FD,
654 bool &hasTrustedImplementationAnnotation);
655
656 /// \return Whether the type corresponds to a known smart pointer
657 /// implementation (that is, everything about it is inlineable).
658 static bool isKnownSmartPointer(QualType QT);
659
660 bool isTrustedReferenceCountImplementation(const Decl *FD);
661
662 const RetainSummary *getSummary(AnyCall C,
663 bool HasNonZeroCallbackArg=false,
664 bool IsReceiverUnconsumedSelf=false,
665 QualType ReceiverType={});
666
667 RetEffect getObjAllocRetEffect() const { return ObjCAllocRetE; }
668
669private:
670
671 /// getMethodSummary - This version of getMethodSummary is used to query
672 /// the summary for the current method being analyzed.
673 const RetainSummary *getMethodSummary(const ObjCMethodDecl *MD);
674
675 const RetainSummary *getFunctionSummary(const FunctionDecl *FD);
676
677 const RetainSummary *getMethodSummary(Selector S, const ObjCInterfaceDecl *ID,
678 const ObjCMethodDecl *MD,
679 QualType RetTy,
680 ObjCMethodSummariesTy &CachedSummaries);
681
682 const RetainSummary *
683 getInstanceMethodSummary(const ObjCMessageExpr *ME, QualType ReceiverType);
684
685 const RetainSummary *getClassMethodSummary(const ObjCMessageExpr *ME);
686
687 const RetainSummary *getStandardMethodSummary(const ObjCMethodDecl *MD,
688 Selector S, QualType RetTy);
689
690 /// Determine if there is a special return effect for this function or method.
691 std::optional<RetEffect> getRetEffectFromAnnotations(QualType RetTy,
692 const Decl *D);
693
694 void updateSummaryFromAnnotations(const RetainSummary *&Summ,
695 const ObjCMethodDecl *MD);
696
697 void updateSummaryFromAnnotations(const RetainSummary *&Summ,
698 const FunctionDecl *FD);
699
700 const RetainSummary *updateSummaryForNonZeroCallbackArg(const RetainSummary *S,
701 AnyCall &C);
702
703 /// Special case '[super init];' and '[self init];'
704 ///
705 /// Even though calling '[super init]' without assigning the result to self
706 /// and checking if the parent returns 'nil' is a bad pattern, it is common.
707 /// Additionally, our Self Init checker already warns about it. To avoid
708 /// overwhelming the user with messages from both checkers, we model the case
709 /// of '[super init]' in cases when it is not consumed by another expression
710 /// as if the call preserves the value of 'self'; essentially, assuming it can
711 /// never fail and return 'nil'.
712 /// Note, we don't want to just stop tracking the value since we want the
713 /// RetainCount checker to report leaks and use-after-free if SelfInit checker
714 /// is turned off.
715 void updateSummaryForReceiverUnconsumedSelf(const RetainSummary *&S);
716
717 /// Set argument types for arguments which are not doing anything.
718 void updateSummaryForArgumentTypes(const AnyCall &C, const RetainSummary *&RS);
719
720 /// Determine whether a declaration @c D of correspondent type (return
721 /// type for functions/methods) @c QT has any of the given attributes,
722 /// provided they pass necessary validation checks AND tracking the given
723 /// attribute is enabled.
724 /// Returns the object kind corresponding to the present attribute, or
725 /// std::nullopt, if none of the specified attributes are present.
726 /// Crashes if passed an attribute which is not explicitly handled.
727 template <class T>
728 std::optional<ObjKind> hasAnyEnabledAttrOf(const Decl *D, QualType QT);
729
730 template <class T1, class T2, class... Others>
731 std::optional<ObjKind> hasAnyEnabledAttrOf(const Decl *D, QualType QT);
732
733 friend class RetainSummaryTemplate;
734};
735
736
737// Used to avoid allocating long-term (BPAlloc'd) memory for default retain
738// summaries. If a function or method looks like it has a default summary, but
739// it has annotations, the annotations are added to the stack-based template
740// and then copied into managed memory.
741class RetainSummaryTemplate {
742 RetainSummaryManager &Manager;
743 const RetainSummary *&RealSummary;
744 RetainSummary ScratchSummary;
745 bool Accessed;
746public:
747 RetainSummaryTemplate(const RetainSummary *&real, RetainSummaryManager &mgr)
748 : Manager(mgr), RealSummary(real), ScratchSummary(*real), Accessed(false) {}
749
750 ~RetainSummaryTemplate() {
751 if (Accessed)
752 RealSummary = Manager.getPersistentSummary(OldSumm: ScratchSummary);
753 }
754
755 RetainSummary &operator*() {
756 Accessed = true;
757 return ScratchSummary;
758 }
759
760 RetainSummary *operator->() {
761 Accessed = true;
762 return &ScratchSummary;
763 }
764};
765
766} // end namespace ento
767} // end namespace clang
768
769#endif
770

source code of clang/include/clang/Analysis/RetainSummaryManager.h