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