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