1 //=== RetainSummaryManager.h - Summaries for reference counting ---*- C++ -*--//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file defines summaries implementation for retain counting, which
11 // implements a reference count checker for Core Foundation and Cocoa
14 //===----------------------------------------------------------------------===//
16 #ifndef LLVM_CLANG_ANALYZER_CORE_RETAINSUMMARYMANAGER
17 #define LLVM_CLANG_ANALYZER_CORE_RETAINSUMMARYMANAGER
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"
29 //===----------------------------------------------------------------------===//
30 // Adapters for FoldingSet.
31 //===----------------------------------------------------------------------===//
33 using namespace clang;
39 /// Determines the object kind of a tracked object.
41 /// Indicates that the tracked object is a CF object.
44 /// Indicates that the tracked object is an Objective-C object.
47 /// Indicates that the tracked object could be a CF or Objective-C object.
50 /// Indicates that the tracked object is a generalized object.
53 /// Indicates that the tracking object is a descendant of a
54 /// referenced-counted OSObject, used in the Darwin kernel.
59 /// There is no effect.
62 /// The argument is treated as if an -autorelease message had been sent to
63 /// the referenced object.
66 /// The argument is treated as if the referenced object was deallocated.
69 /// The argument has its reference count decreased by 1.
72 /// The argument has its reference count decreased by 1 to model
73 /// a transferred bridge cast under ARC.
74 DecRefBridgedTransferred,
76 /// The argument has its reference count increased by 1.
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,
83 /// The argument is a pointer to a retain-counted object; on exit, the new
84 /// value of the pointer is a +1 value.
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,
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,
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.
100 /// All typestate tracking of the object ceases. This is usually employed
101 /// when the effect of the call is completely unknown.
104 /// All typestate tracking of the object ceases. Unlike StopTracking,
105 /// this is also enforced when the method body is inlined.
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.
113 /// Performs the combined functionality of DecRef and StopTrackingHard.
115 /// The models the effect that the called function decrements the reference
116 /// count of the argument and all typestate tracking on that argument
118 DecRefAndStopTrackingHard,
121 /// An ArgEffect summarizes the retain count behavior on an argument or receiver
122 /// to a function or method.
127 explicit ArgEffect(ArgEffectKind K = DoNothing, ObjKind O = ObjKind::AnyObj)
130 ArgEffectKind getKind() const { return K; }
131 ObjKind getObjKind() const { return O; }
133 ArgEffect withKind(ArgEffectKind NewK) {
134 return ArgEffect(NewK, O);
137 bool operator==(const ArgEffect &Other) const {
138 return K == Other.K && O == Other.O;
142 /// RetEffect summarizes a call's retain/release behavior with respect
143 /// to its return value.
147 /// Indicates that no retain count information is tracked for
148 /// the return value.
151 /// Indicates that the returned value is an owned (+1) symbol.
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.
159 /// Indicates that the return value is an owned object when the
160 /// receiver is also a tracked object.
161 OwnedWhenTrackedReceiver,
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
174 RetEffect(Kind k, ObjKind o = ObjKind::AnyObj) : K(k), O(o) {}
177 Kind getKind() const { return K; }
179 ObjKind getObjKind() const { return O; }
181 bool isOwned() const {
182 return K == OwnedSymbol || K == OwnedWhenTrackedReceiver;
185 bool notOwned() const {
186 return K == NotOwnedSymbol;
189 bool operator==(const RetEffect &Other) const {
190 return K == Other.K && O == Other.O;
193 static RetEffect MakeOwnedWhenTrackedReceiver() {
194 return RetEffect(OwnedWhenTrackedReceiver, ObjKind::ObjC);
197 static RetEffect MakeOwned(ObjKind o) {
198 return RetEffect(OwnedSymbol, o);
200 static RetEffect MakeNotOwned(ObjKind o) {
201 return RetEffect(NotOwnedSymbol, o);
203 static RetEffect MakeNoRet() {
204 return RetEffect(NoRet);
206 static RetEffect MakeNoRetHard() {
207 return RetEffect(NoRetHard);
211 /// Encapsulates the retain count semantics on the arguments, return value,
212 /// and receiver (if any) of a function/method call.
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.
220 llvm::SmallVector<ArgEffect, 10> Args;
224 CallEffects(const RetEffect &R,
225 ArgEffect Receiver = ArgEffect(DoNothing, ObjKind::AnyObj))
226 : Ret(R), Receiver(Receiver) {}
229 /// Returns the argument effects for a call.
230 ArrayRef<ArgEffect> getArgs() const { return Args; }
232 /// Returns the effects on the receiver.
233 ArgEffect getReceiver() const { return Receiver; }
235 /// Returns the effect on the return value.
236 RetEffect getReturnValue() const { return Ret; }
238 /// Return the CallEfect for a given Objective-C method.
239 static CallEffects getEffect(const ObjCMethodDecl *MD);
241 /// Return the CallEfect for a given C/C++ function.
242 static CallEffects getEffect(const FunctionDecl *FD);
245 /// A key identifying a summary.
246 class ObjCSummaryKey {
250 ObjCSummaryKey(IdentifierInfo* ii, Selector s)
253 ObjCSummaryKey(const ObjCInterfaceDecl *d, Selector s)
254 : II(d ? d->getIdentifier() : nullptr), S(s) {}
256 ObjCSummaryKey(Selector s)
257 : II(nullptr), S(s) {}
259 IdentifierInfo *getIdentifier() const { return II; }
260 Selector getSelector() const { return S; }
263 } // end namespace ento
264 } // end namespace clang
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());
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());
282 template <> struct DenseMapInfo<ObjCSummaryKey> {
283 static inline ObjCSummaryKey getEmptyKey() {
284 return ObjCSummaryKey(DenseMapInfo<IdentifierInfo*>::getEmptyKey(),
285 DenseMapInfo<Selector>::getEmptyKey());
288 static inline ObjCSummaryKey getTombstoneKey() {
289 return ObjCSummaryKey(DenseMapInfo<IdentifierInfo*>::getTombstoneKey(),
290 DenseMapInfo<Selector>::getTombstoneKey());
293 static unsigned getHashValue(const ObjCSummaryKey &V) {
294 typedef std::pair<IdentifierInfo*, Selector> PairTy;
295 return DenseMapInfo<PairTy>::getHashValue(PairTy(V.getIdentifier(),
299 static bool isEqual(const ObjCSummaryKey& LHS, const ObjCSummaryKey& RHS) {
300 return LHS.getIdentifier() == RHS.getIdentifier() &&
301 LHS.getSelector() == RHS.getSelector();
306 } // end llvm namespace
312 /// ArgEffects summarizes the effects of a function/method call on all of
314 typedef llvm::ImmutableMap<unsigned, ArgEffect> ArgEffects;
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'.
323 /// DefaultArgEffect - The default ArgEffect to apply to arguments that
324 /// do not have an entry in Args.
325 ArgEffect DefaultArgEffect;
327 /// Receiver - If this summary applies to an Objective-C message expression,
328 /// this is the effect applied to the state of the receiver.
331 /// Effect on "this" pointer - applicable only to C++ method calls.
334 /// Ret - The effect on the return value. Used to indicate if the
335 /// function/method call returns a new tracked symbol.
339 RetainSummary(ArgEffects A,
341 ArgEffect defaultEff,
342 ArgEffect ReceiverEff,
344 : Args(A), DefaultArgEffect(defaultEff), Receiver(ReceiverEff),
345 This(ThisEff), Ret(R) {}
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))
353 return DefaultArgEffect;
356 void addArg(ArgEffects::Factory &af, unsigned idx, ArgEffect e) {
357 Args = af.add(Args, idx, e);
360 /// setDefaultArgEffect - Set the default argument effect.
361 void setDefaultArgEffect(ArgEffect E) {
362 DefaultArgEffect = E;
365 /// getRetEffect - Returns the effect on the return value of the call.
366 RetEffect getRetEffect() const { return Ret; }
368 /// setRetEffect - Set the effect of the return value of the call.
369 void setRetEffect(RetEffect E) { Ret = E; }
372 /// Sets the effect on the receiver of the message.
373 void setReceiverEffect(ArgEffect e) { Receiver = e; }
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; }
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; }
383 /// Set the effect of the method on "this".
384 void setThisEffect(ArgEffect e) { This = e; }
386 bool isNoop() const {
387 return Ret == RetEffect::MakeNoRet() && Receiver.getKind() == DoNothing
388 && DefaultArgEffect.getKind() == MayEscape && This.getKind() == DoNothing
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;
400 /// Profile this summary for inclusion in a FoldingSet.
401 void Profile(llvm::FoldingSetNodeID& ID) const {
403 ID.Add(DefaultArgEffect);
409 /// A retain summary is simple if it has no ArgEffects other than the default.
410 bool isSimple() const {
411 return Args.isEmpty();
414 ArgEffects getArgEffects() const { return Args; }
417 ArgEffect getDefaultArgEffect() const { return DefaultArgEffect; }
419 friend class RetainSummaryManager;
422 class ObjCSummaryCache {
423 typedef llvm::DenseMap<ObjCSummaryKey, const RetainSummary *> MapTy;
426 ObjCSummaryCache() {}
428 const RetainSummary * find(const ObjCInterfaceDecl *D, Selector S) {
429 // Do a lookup with the (D,S) pair. If we find a match return
431 ObjCSummaryKey K(D, S);
432 MapTy::iterator I = M.find(K);
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
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())
453 // Cache the summary with original key to make the next lookup faster
454 // and return the iterator.
455 const RetainSummary *Summ = I->second;
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));
466 I = M.find(ObjCSummaryKey(S));
468 return I == M.end() ? nullptr : I->second;
471 const RetainSummary *& operator[](ObjCSummaryKey K) {
475 const RetainSummary *& operator[](Selector S) {
476 return M[ ObjCSummaryKey(S) ];
480 class RetainSummaryTemplate;
482 class RetainSummaryManager {
483 typedef llvm::DenseMap<const FunctionDecl*, const RetainSummary *>
486 typedef ObjCSummaryCache ObjCMethodSummariesTy;
488 typedef llvm::FoldingSetNodeWrapper<RetainSummary> CachedSummaryNode;
490 /// Ctx - The ASTContext object for the analyzed ASTs.
493 /// Records whether or not the analyzed code runs in ARC mode.
494 const bool ARCEnabled;
496 /// Track Objective-C and CoreFoundation objects.
497 const bool TrackObjCAndCFObjects;
499 /// Track sublcasses of OSObject.
500 const bool TrackOSObjects;
502 /// FuncSummaries - A map from FunctionDecls to summaries.
503 FuncSummariesTy FuncSummaries;
505 /// ObjCClassMethodSummaries - A map from selectors (for instance methods)
507 ObjCMethodSummariesTy ObjCClassMethodSummaries;
509 /// ObjCMethodSummaries - A map from selectors to summaries.
510 ObjCMethodSummariesTy ObjCMethodSummaries;
512 /// BPAlloc - A BumpPtrAllocator used for allocating summaries, ArgEffects,
513 /// and all other data used by the checker.
514 llvm::BumpPtrAllocator BPAlloc;
516 /// AF - A factory for ArgEffects objects.
517 ArgEffects::Factory AF;
519 /// ObjCAllocRetE - Default return effect for methods returning Objective-C
521 RetEffect ObjCAllocRetE;
523 /// ObjCInitRetE - Default return effect for init methods returning
524 /// Objective-C objects.
525 RetEffect ObjCInitRetE;
527 /// SimpleSummaries - Used for uniquing summaries that don't have special
529 llvm::FoldingSet<CachedSummaryNode> SimpleSummaries;
531 /// Create an OS object at +1.
532 const RetainSummary *getOSSummaryCreateRule(const FunctionDecl *FD);
534 /// Get an OS object at +0.
535 const RetainSummary *getOSSummaryGetRule(const FunctionDecl *FD);
537 /// Increment the reference count on OS object.
538 const RetainSummary *getOSSummaryRetainRule(const FunctionDecl *FD);
540 /// Decrement the reference count on OS object.
541 const RetainSummary *getOSSummaryReleaseRule(const FunctionDecl *FD);
543 /// Free the OS object.
544 const RetainSummary *getOSSummaryFreeRule(const FunctionDecl *FD);
546 const RetainSummary *getUnarySummary(const FunctionType* FT,
549 const RetainSummary *getCFSummaryCreateRule(const FunctionDecl *FD);
550 const RetainSummary *getCFSummaryGetRule(const FunctionDecl *FD);
551 const RetainSummary *getCFCreateGetRuleSummary(const FunctionDecl *FD);
553 const RetainSummary *getPersistentSummary(const RetainSummary &OldSumm);
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);
564 const RetainSummary *getDoNothingSummary() {
565 return getPersistentSummary(RetEffect::MakeNoRet(),
566 ArgEffects(AF.getEmptyMap()),
567 ArgEffect(DoNothing), ArgEffect(DoNothing));
570 const RetainSummary *getDefaultSummary() {
571 return getPersistentSummary(RetEffect::MakeNoRet(),
572 ArgEffects(AF.getEmptyMap()),
573 ArgEffect(DoNothing), ArgEffect(MayEscape));
576 const RetainSummary *getPersistentStopSummary() {
577 return getPersistentSummary(
578 RetEffect::MakeNoRet(), ArgEffects(AF.getEmptyMap()),
579 ArgEffect(StopTracking), ArgEffect(StopTracking));
582 void InitializeClassMethodSummaries();
583 void InitializeMethodSummaries();
585 void addNSObjectClsMethSummary(Selector S, const RetainSummary *Summ) {
586 ObjCClassMethodSummaries[S] = Summ;
589 void addNSObjectMethSummary(Selector S, const RetainSummary *Summ) {
590 ObjCMethodSummaries[S] = Summ;
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;
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;
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;
615 template <typename... Keywords>
616 void addInstMethSummary(const char *Cls, const RetainSummary *Summ,
618 addMethodSummary(&Ctx.Idents.get(Cls), ObjCMethodSummaries, Summ, Kws...);
621 template <typename... Keywords>
622 void addClsMethSummary(const char *Cls, const RetainSummary *Summ,
624 addMethodSummary(&Ctx.Idents.get(Cls), ObjCClassMethodSummaries, Summ,
628 template <typename... Keywords>
629 void addClsMethSummary(IdentifierInfo *II, const RetainSummary *Summ,
631 addMethodSummary(II, ObjCClassMethodSummaries, Summ, Kws...);
634 const RetainSummary * generateSummary(const FunctionDecl *FD,
635 bool &AllowAnnotations);
637 /// Return a summary for OSObject, or nullptr if not found.
638 const RetainSummary *getSummaryForOSObject(const FunctionDecl *FD,
639 StringRef FName, QualType RetTy);
641 /// Return a summary for Objective-C or CF object, or nullptr if not found.
642 const RetainSummary *getSummaryForObjCOrCFObject(
643 const FunctionDecl *FD,
646 const FunctionType *FT,
647 bool &AllowAnnotations);
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,
654 RetainSummaryTemplate &Template);
657 RetainSummaryManager(ASTContext &ctx,
659 bool trackObjCAndCFObjects,
663 TrackObjCAndCFObjects(trackObjCAndCFObjects),
664 TrackOSObjects(trackOSObjects),
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();
674 enum class BehaviorSummary {
675 // Function does not return.
678 // Function returns the first argument.
681 // Function either returns zero, or the input parameter.
685 Optional<BehaviorSummary> canEval(const CallExpr *CE, const FunctionDecl *FD,
686 bool &hasTrustedImplementationAnnotation);
688 bool isTrustedReferenceCountImplementation(const FunctionDecl *FD);
690 const RetainSummary *getSummary(const CallEvent &Call,
691 QualType ReceiverType=QualType());
693 const RetainSummary *getFunctionSummary(const FunctionDecl *FD);
695 const RetainSummary *getMethodSummary(Selector S, const ObjCInterfaceDecl *ID,
696 const ObjCMethodDecl *MD,
698 ObjCMethodSummariesTy &CachedSummaries);
700 const RetainSummary *
701 getInstanceMethodSummary(const ObjCMethodCall &M,
702 QualType ReceiverType);
704 const RetainSummary *getClassMethodSummary(const ObjCMethodCall &M) {
705 assert(!M.isInstanceMessage());
706 const ObjCInterfaceDecl *Class = M.getReceiverInterface();
708 return getMethodSummary(M.getSelector(), Class, M.getDecl(),
709 M.getResultType(), ObjCClassMethodSummaries);
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();
719 ObjCMethodSummariesTy *CachedSummaries;
720 if (MD->isInstanceMethod())
721 CachedSummaries = &ObjCMethodSummaries;
723 CachedSummaries = &ObjCClassMethodSummaries;
725 return getMethodSummary(S, ID, MD, ResultTy, *CachedSummaries);
728 const RetainSummary *getStandardMethodSummary(const ObjCMethodDecl *MD,
729 Selector S, QualType RetTy);
731 /// Determine if there is a special return effect for this function or method.
732 Optional<RetEffect> getRetEffectFromAnnotations(QualType RetTy,
735 void updateSummaryFromAnnotations(const RetainSummary *&Summ,
736 const ObjCMethodDecl *MD);
738 void updateSummaryFromAnnotations(const RetainSummary *&Summ,
739 const FunctionDecl *FD);
742 void updateSummaryForCall(const RetainSummary *&Summ,
743 const CallEvent &Call);
745 bool isARCEnabled() const { return ARCEnabled; }
747 RetEffect getObjAllocRetEffect() const { return ObjCAllocRetE; }
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.
757 Optional<ObjKind> hasAnyEnabledAttrOf(const Decl *D, QualType QT);
759 template <class T1, class T2, class... Others>
760 Optional<ObjKind> hasAnyEnabledAttrOf(const Decl *D, QualType QT);
762 friend class RetainSummaryTemplate;
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;
776 RetainSummaryTemplate(const RetainSummary *&real, RetainSummaryManager &mgr)
777 : Manager(mgr), RealSummary(real), ScratchSummary(*real), Accessed(false) {}
779 ~RetainSummaryTemplate() {
781 RealSummary = Manager.getPersistentSummary(ScratchSummary);
784 RetainSummary &operator*() {
786 return ScratchSummary;
789 RetainSummary *operator->() {
791 return &ScratchSummary;
795 } // end namespace ento
796 } // end namespace clang