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 
30 using namespace clang;
31 
32 namespace clang {
33 namespace ento {
34 
35 /// Determines the object kind of a tracked object.
36 enum 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 
54 enum 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.
119 class ArgEffect {
120   ArgEffectKind K;
121   ObjKind O;
122 public:
123   explicit ArgEffect(ArgEffectKind K = DoNothing, ObjKind O = ObjKind::AnyObj)
K(K)124       : K(K), O(O) {}
125 
getKind()126   ArgEffectKind getKind() const { return K; }
getObjKind()127   ObjKind getObjKind() const { return O; }
128 
withKind(ArgEffectKind NewK)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.
140 class RetEffect {
141 public:
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 
166 private:
167   Kind K;
168   ObjKind O;
169 
K(k)170   RetEffect(Kind k, ObjKind o = ObjKind::AnyObj) : K(k), O(o) {}
171 
172 public:
getKind()173   Kind getKind() const { return K; }
174 
getObjKind()175   ObjKind getObjKind() const { return O; }
176 
isOwned()177   bool isOwned() const {
178     return K == OwnedSymbol || K == OwnedWhenTrackedReceiver;
179   }
180 
notOwned()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 
MakeOwnedWhenTrackedReceiver()189   static RetEffect MakeOwnedWhenTrackedReceiver() {
190     return RetEffect(OwnedWhenTrackedReceiver, ObjKind::ObjC);
191   }
192 
MakeOwned(ObjKind o)193   static RetEffect MakeOwned(ObjKind o) {
194     return RetEffect(OwnedSymbol, o);
195   }
MakeNotOwned(ObjKind o)196   static RetEffect MakeNotOwned(ObjKind o) {
197     return RetEffect(NotOwnedSymbol, o);
198   }
MakeNoRet()199   static RetEffect MakeNoRet() {
200     return RetEffect(NoRet);
201   }
MakeNoRetHard()202   static RetEffect MakeNoRetHard() {
203     return RetEffect(NoRetHard);
204   }
205 };
206 
207 /// A key identifying a summary.
208 class ObjCSummaryKey {
209   IdentifierInfo* II;
210   Selector S;
211 public:
ObjCSummaryKey(IdentifierInfo * ii,Selector s)212   ObjCSummaryKey(IdentifierInfo* ii, Selector s)
213     : II(ii), S(s) {}
214 
ObjCSummaryKey(const ObjCInterfaceDecl * d,Selector s)215   ObjCSummaryKey(const ObjCInterfaceDecl *d, Selector s)
216     : II(d ? d->getIdentifier() : nullptr), S(s) {}
217 
ObjCSummaryKey(Selector s)218   ObjCSummaryKey(Selector s)
219     : II(nullptr), S(s) {}
220 
getIdentifier()221   IdentifierInfo *getIdentifier() const { return II; }
getSelector()222   Selector getSelector() const { return S; }
223 };
224 
225 } // end namespace ento
226 } // end namespace clang
227 
228 using namespace ento;
229 
230 namespace llvm {
231 
232 //===----------------------------------------------------------------------===//
233 // Adapters for FoldingSet.
234 //===----------------------------------------------------------------------===//
235 template <> struct FoldingSetTrait<ArgEffect> {
236 static inline void Profile(const ArgEffect X, FoldingSetNodeID &ID) {
237   ID.AddInteger((unsigned) X.getKind());
238   ID.AddInteger((unsigned) X.getObjKind());
239 }
240 };
241 template <> struct FoldingSetTrait<RetEffect> {
242   static inline void Profile(const RetEffect &X, FoldingSetNodeID &ID) {
243     ID.AddInteger((unsigned) X.getKind());
244     ID.AddInteger((unsigned) X.getObjKind());
245 }
246 };
247 
248 template <> 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(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 
275 namespace clang {
276 namespace ento {
277 
278 /// ArgEffects summarizes the effects of a function/method call on all of
279 /// its arguments.
280 typedef llvm::ImmutableMap<unsigned, ArgEffect> ArgEffects;
281 
282 /// Summary for a function with respect to ownership changes.
283 class 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 
304 public:
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(idx))
317       return *AE;
318 
319     return DefaultArgEffect;
320   }
321 
322   void addArg(ArgEffects::Factory &af, unsigned idx, ArgEffect e) {
323     Args = af.add(Args, idx, 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(Args);
371     ID.Add(DefaultArgEffect);
372     ID.Add(Receiver);
373     ID.Add(This);
374     ID.Add(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 
384 private:
385   ArgEffect getDefaultArgEffect() const { return DefaultArgEffect; }
386 
387   friend class RetainSummaryManager;
388 };
389 
390 class ObjCSummaryCache {
391   typedef llvm::DenseMap<ObjCSummaryKey, const RetainSummary *> MapTy;
392   MapTy M;
393 public:
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(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(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(ObjCSummaryKey(II, S));
432 
433     if (I == M.end())
434       I = M.find(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 
448 class RetainSummaryTemplate;
449 
450 class 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(Summ);
530   }
531 
532   const RetainSummary *getDoNothingSummary() {
533     return getPersistentSummary(RetEffect::MakeNoRet(),
534                                 ArgEffects(AF.getEmptyMap()),
535                                 ArgEffect(DoNothing), ArgEffect(DoNothing));
536   }
537 
538   const RetainSummary *getDefaultSummary() {
539     return getPersistentSummary(RetEffect::MakeNoRet(),
540                                 ArgEffects(AF.getEmptyMap()),
541                                 ArgEffect(DoNothing), ArgEffect(MayEscape));
542   }
543 
544   const RetainSummary *getPersistentStopSummary() {
545     return getPersistentSummary(
546         RetEffect::MakeNoRet(), ArgEffects(AF.getEmptyMap()),
547         ArgEffect(StopTracking), 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(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(Cls);
572     Selector S = GetNullarySelector(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(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(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 
624 public:
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(ObjKind::ObjC)
631                                  : RetEffect::MakeOwned(ObjKind::ObjC)),
632         ObjCInitRetE(ARCEnabled ? RetEffect::MakeNotOwned(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 
669 private:
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.
741 class RetainSummaryTemplate {
742   RetainSummaryManager &Manager;
743   const RetainSummary *&RealSummary;
744   RetainSummary ScratchSummary;
745   bool Accessed;
746 public:
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(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