Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:36:26

0001 //=== RetainSummaryManager.h - Summaries for reference counting ---*- C++ -*--//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 //
0009 //  This file defines summaries implementation for retain counting, which
0010 //  implements a reference count checker for Core Foundation and Cocoa
0011 //  on (Mac OS X).
0012 //
0013 //===----------------------------------------------------------------------===//
0014 
0015 #ifndef LLVM_CLANG_ANALYSIS_RETAINSUMMARYMANAGER_H
0016 #define LLVM_CLANG_ANALYSIS_RETAINSUMMARYMANAGER_H
0017 
0018 #include "llvm/ADT/DenseMap.h"
0019 #include "llvm/ADT/FoldingSet.h"
0020 #include "llvm/ADT/ImmutableMap.h"
0021 #include "clang/AST/Attr.h"
0022 #include "clang/AST/DeclCXX.h"
0023 #include "clang/AST/DeclObjC.h"
0024 #include "clang/AST/ParentMap.h"
0025 #include "clang/Analysis/AnyCall.h"
0026 #include "clang/Analysis/SelectorExtras.h"
0027 #include "llvm/ADT/STLExtras.h"
0028 #include <optional>
0029 
0030 using namespace clang;
0031 
0032 namespace clang {
0033 namespace ento {
0034 
0035 /// Determines the object kind of a tracked object.
0036 enum class ObjKind {
0037   /// Indicates that the tracked object is a CF object.
0038   CF,
0039 
0040   /// Indicates that the tracked object is an Objective-C object.
0041   ObjC,
0042 
0043   /// Indicates that the tracked object could be a CF or Objective-C object.
0044   AnyObj,
0045 
0046   /// Indicates that the tracked object is a generalized object.
0047   Generalized,
0048 
0049   /// Indicates that the tracking object is a descendant of a
0050   /// referenced-counted OSObject, used in the Darwin kernel.
0051   OS
0052 };
0053 
0054 enum ArgEffectKind {
0055   /// There is no effect.
0056   DoNothing,
0057 
0058   /// The argument is treated as if an -autorelease message had been sent to
0059   /// the referenced object.
0060   Autorelease,
0061 
0062   /// The argument is treated as if the referenced object was deallocated.
0063   Dealloc,
0064 
0065   /// The argument has its reference count decreased by 1.
0066   DecRef,
0067 
0068   /// The argument has its reference count decreased by 1 to model
0069   /// a transferred bridge cast under ARC.
0070   DecRefBridgedTransferred,
0071 
0072   /// The argument has its reference count increased by 1.
0073   IncRef,
0074 
0075   /// The argument is a pointer to a retain-counted object; on exit, the new
0076   /// value of the pointer is a +0 value.
0077   UnretainedOutParameter,
0078 
0079   /// The argument is a pointer to a retain-counted object; on exit, the new
0080   /// value of the pointer is a +1 value.
0081   RetainedOutParameter,
0082 
0083   /// The argument is a pointer to a retain-counted object; on exit, the new
0084   /// value of the pointer is a +1 value iff the return code is zero.
0085   RetainedOutParameterOnZero,
0086 
0087   /// The argument is a pointer to a retain-counted object; on exit, the new
0088   /// value of the pointer is a +1 value iff the return code is non-zero.
0089   RetainedOutParameterOnNonZero,
0090 
0091   /// The argument is treated as potentially escaping, meaning that
0092   /// even when its reference count hits 0 it should be treated as still
0093   /// possibly being alive as someone else *may* be holding onto the object.
0094   MayEscape,
0095 
0096   /// All typestate tracking of the object ceases.  This is usually employed
0097   /// when the effect of the call is completely unknown.
0098   StopTracking,
0099 
0100   /// All typestate tracking of the object ceases.  Unlike StopTracking,
0101   /// this is also enforced when the method body is inlined.
0102   ///
0103   /// In some cases, we obtain a better summary for this checker
0104   /// by looking at the call site than by inlining the function.
0105   /// Signifies that we should stop tracking the symbol even if
0106   /// the function is inlined.
0107   StopTrackingHard,
0108 
0109   /// Performs the combined functionality of DecRef and StopTrackingHard.
0110   ///
0111   /// The models the effect that the called function decrements the reference
0112   /// count of the argument and all typestate tracking on that argument
0113   /// should cease.
0114   DecRefAndStopTrackingHard,
0115 };
0116 
0117 /// An ArgEffect summarizes the retain count behavior on an argument or receiver
0118 /// to a function or method.
0119 class ArgEffect {
0120   ArgEffectKind K;
0121   ObjKind O;
0122 public:
0123   explicit ArgEffect(ArgEffectKind K = DoNothing, ObjKind O = ObjKind::AnyObj)
0124       : K(K), O(O) {}
0125 
0126   ArgEffectKind getKind() const { return K; }
0127   ObjKind getObjKind() const { return O; }
0128 
0129   ArgEffect withKind(ArgEffectKind NewK) {
0130     return ArgEffect(NewK, O);
0131   }
0132 
0133   bool operator==(const ArgEffect &Other) const {
0134     return K == Other.K && O == Other.O;
0135   }
0136 };
0137 
0138 /// RetEffect summarizes a call's retain/release behavior with respect
0139 /// to its return value.
0140 class RetEffect {
0141 public:
0142   enum Kind {
0143     /// Indicates that no retain count information is tracked for
0144     /// the return value.
0145     NoRet,
0146 
0147     /// Indicates that the returned value is an owned (+1) symbol.
0148     OwnedSymbol,
0149 
0150     /// Indicates that the returned value is an object with retain count
0151     /// semantics but that it is not owned (+0).  This is the default
0152     /// for getters, etc.
0153     NotOwnedSymbol,
0154 
0155     /// Indicates that the return value is an owned object when the
0156     /// receiver is also a tracked object.
0157     OwnedWhenTrackedReceiver,
0158 
0159     // Treat this function as returning a non-tracked symbol even if
0160     // the function has been inlined. This is used where the call
0161     // site summary is more precise than the summary indirectly produced
0162     // by inlining the function
0163     NoRetHard
0164   };
0165 
0166 private:
0167   Kind K;
0168   ObjKind O;
0169 
0170   RetEffect(Kind k, ObjKind o = ObjKind::AnyObj) : K(k), O(o) {}
0171 
0172 public:
0173   Kind getKind() const { return K; }
0174 
0175   ObjKind getObjKind() const { return O; }
0176 
0177   bool isOwned() const {
0178     return K == OwnedSymbol || K == OwnedWhenTrackedReceiver;
0179   }
0180 
0181   bool notOwned() const {
0182     return K == NotOwnedSymbol;
0183   }
0184 
0185   bool operator==(const RetEffect &Other) const {
0186     return K == Other.K && O == Other.O;
0187   }
0188 
0189   static RetEffect MakeOwnedWhenTrackedReceiver() {
0190     return RetEffect(OwnedWhenTrackedReceiver, ObjKind::ObjC);
0191   }
0192 
0193   static RetEffect MakeOwned(ObjKind o) {
0194     return RetEffect(OwnedSymbol, o);
0195   }
0196   static RetEffect MakeNotOwned(ObjKind o) {
0197     return RetEffect(NotOwnedSymbol, o);
0198   }
0199   static RetEffect MakeNoRet() {
0200     return RetEffect(NoRet);
0201   }
0202   static RetEffect MakeNoRetHard() {
0203     return RetEffect(NoRetHard);
0204   }
0205 };
0206 
0207 /// A key identifying a summary.
0208 class ObjCSummaryKey {
0209   IdentifierInfo* II;
0210   Selector S;
0211 public:
0212   ObjCSummaryKey(IdentifierInfo* ii, Selector s)
0213     : II(ii), S(s) {}
0214 
0215   ObjCSummaryKey(const ObjCInterfaceDecl *d, Selector s)
0216     : II(d ? d->getIdentifier() : nullptr), S(s) {}
0217 
0218   ObjCSummaryKey(Selector s)
0219     : II(nullptr), S(s) {}
0220 
0221   IdentifierInfo *getIdentifier() const { return II; }
0222   Selector getSelector() const { return S; }
0223 };
0224 
0225 } // end namespace ento
0226 } // end namespace clang
0227 
0228 using namespace ento;
0229 
0230 namespace llvm {
0231 
0232 //===----------------------------------------------------------------------===//
0233 // Adapters for FoldingSet.
0234 //===----------------------------------------------------------------------===//
0235 template <> struct FoldingSetTrait<ArgEffect> {
0236 static inline void Profile(const ArgEffect X, FoldingSetNodeID &ID) {
0237   ID.AddInteger((unsigned) X.getKind());
0238   ID.AddInteger((unsigned) X.getObjKind());
0239 }
0240 };
0241 template <> struct FoldingSetTrait<RetEffect> {
0242   static inline void Profile(const RetEffect &X, FoldingSetNodeID &ID) {
0243     ID.AddInteger((unsigned) X.getKind());
0244     ID.AddInteger((unsigned) X.getObjKind());
0245 }
0246 };
0247 
0248 template <> struct DenseMapInfo<ObjCSummaryKey> {
0249   static inline ObjCSummaryKey getEmptyKey() {
0250     return ObjCSummaryKey(DenseMapInfo<IdentifierInfo*>::getEmptyKey(),
0251                           DenseMapInfo<Selector>::getEmptyKey());
0252   }
0253 
0254   static inline ObjCSummaryKey getTombstoneKey() {
0255     return ObjCSummaryKey(DenseMapInfo<IdentifierInfo*>::getTombstoneKey(),
0256                           DenseMapInfo<Selector>::getTombstoneKey());
0257   }
0258 
0259   static unsigned getHashValue(const ObjCSummaryKey &V) {
0260     typedef std::pair<IdentifierInfo*, Selector> PairTy;
0261     return DenseMapInfo<PairTy>::getHashValue(PairTy(V.getIdentifier(),
0262                                                      V.getSelector()));
0263   }
0264 
0265   static bool isEqual(const ObjCSummaryKey& LHS, const ObjCSummaryKey& RHS) {
0266     return LHS.getIdentifier() == RHS.getIdentifier() &&
0267            LHS.getSelector() == RHS.getSelector();
0268   }
0269 
0270 };
0271 
0272 } // end llvm namespace
0273 
0274 
0275 namespace clang {
0276 namespace ento {
0277 
0278 /// ArgEffects summarizes the effects of a function/method call on all of
0279 /// its arguments.
0280 typedef llvm::ImmutableMap<unsigned, ArgEffect> ArgEffects;
0281 
0282 /// Summary for a function with respect to ownership changes.
0283 class RetainSummary {
0284   /// Args - a map of (index, ArgEffect) pairs, where index
0285   ///  specifies the argument (starting from 0).  This can be sparsely
0286   ///  populated; arguments with no entry in Args use 'DefaultArgEffect'.
0287   ArgEffects Args;
0288 
0289   /// DefaultArgEffect - The default ArgEffect to apply to arguments that
0290   ///  do not have an entry in Args.
0291   ArgEffect DefaultArgEffect;
0292 
0293   /// Receiver - If this summary applies to an Objective-C message expression,
0294   ///  this is the effect applied to the state of the receiver.
0295   ArgEffect Receiver;
0296 
0297   /// Effect on "this" pointer - applicable only to C++ method calls.
0298   ArgEffect This;
0299 
0300   /// Ret - The effect on the return value.  Used to indicate if the
0301   ///  function/method call returns a new tracked symbol.
0302   RetEffect Ret;
0303 
0304 public:
0305   RetainSummary(ArgEffects A,
0306                 RetEffect R,
0307                 ArgEffect defaultEff,
0308                 ArgEffect ReceiverEff,
0309                 ArgEffect ThisEff)
0310     : Args(A), DefaultArgEffect(defaultEff), Receiver(ReceiverEff),
0311       This(ThisEff), Ret(R) {}
0312 
0313   /// getArg - Return the argument effect on the argument specified by
0314   ///  idx (starting from 0).
0315   ArgEffect getArg(unsigned idx) const {
0316     if (const ArgEffect *AE = Args.lookup(idx))
0317       return *AE;
0318 
0319     return DefaultArgEffect;
0320   }
0321 
0322   void addArg(ArgEffects::Factory &af, unsigned idx, ArgEffect e) {
0323     Args = af.add(Args, idx, e);
0324   }
0325 
0326   /// setDefaultArgEffect - Set the default argument effect.
0327   void setDefaultArgEffect(ArgEffect E) {
0328     DefaultArgEffect = E;
0329   }
0330 
0331   /// getRetEffect - Returns the effect on the return value of the call.
0332   RetEffect getRetEffect() const { return Ret; }
0333 
0334   /// setRetEffect - Set the effect of the return value of the call.
0335   void setRetEffect(RetEffect E) { Ret = E; }
0336 
0337 
0338   /// Sets the effect on the receiver of the message.
0339   void setReceiverEffect(ArgEffect e) { Receiver = e; }
0340 
0341   /// getReceiverEffect - Returns the effect on the receiver of the call.
0342   ///  This is only meaningful if the summary applies to an ObjCMessageExpr*.
0343   ArgEffect getReceiverEffect() const { return Receiver; }
0344 
0345   /// \return the effect on the "this" receiver of the method call.
0346   /// This is only meaningful if the summary applies to CXXMethodDecl*.
0347   ArgEffect getThisEffect() const { return This; }
0348 
0349   ArgEffect getDefaultEffect() const { return DefaultArgEffect; }
0350 
0351   /// Set the effect of the method on "this".
0352   void setThisEffect(ArgEffect e) { This = e; }
0353 
0354   bool isNoop() const {
0355     return Ret == RetEffect::MakeNoRet() && Receiver.getKind() == DoNothing
0356       && DefaultArgEffect.getKind() == MayEscape && This.getKind() == DoNothing
0357       && Args.isEmpty();
0358   }
0359 
0360   /// Test if two retain summaries are identical. Note that merely equivalent
0361   /// summaries are not necessarily identical (for example, if an explicit
0362   /// argument effect matches the default effect).
0363   bool operator==(const RetainSummary &Other) const {
0364     return Args == Other.Args && DefaultArgEffect == Other.DefaultArgEffect &&
0365            Receiver == Other.Receiver && This == Other.This && Ret == Other.Ret;
0366   }
0367 
0368   /// Profile this summary for inclusion in a FoldingSet.
0369   void Profile(llvm::FoldingSetNodeID& ID) const {
0370     ID.Add(Args);
0371     ID.Add(DefaultArgEffect);
0372     ID.Add(Receiver);
0373     ID.Add(This);
0374     ID.Add(Ret);
0375   }
0376 
0377   /// A retain summary is simple if it has no ArgEffects other than the default.
0378   bool isSimple() const {
0379     return Args.isEmpty();
0380   }
0381 
0382   ArgEffects getArgEffects() const { return Args; }
0383 
0384 private:
0385   ArgEffect getDefaultArgEffect() const { return DefaultArgEffect; }
0386 
0387   friend class RetainSummaryManager;
0388 };
0389 
0390 class ObjCSummaryCache {
0391   typedef llvm::DenseMap<ObjCSummaryKey, const RetainSummary *> MapTy;
0392   MapTy M;
0393 public:
0394   ObjCSummaryCache() {}
0395 
0396   const RetainSummary * find(const ObjCInterfaceDecl *D, Selector S) {
0397     // Do a lookup with the (D,S) pair.  If we find a match return
0398     // the iterator.
0399     ObjCSummaryKey K(D, S);
0400     MapTy::iterator I = M.find(K);
0401 
0402     if (I != M.end())
0403       return I->second;
0404     if (!D)
0405       return nullptr;
0406 
0407     // Walk the super chain.  If we find a hit with a parent, we'll end
0408     // up returning that summary.  We actually allow that key (null,S), as
0409     // we cache summaries for the null ObjCInterfaceDecl* to allow us to
0410     // generate initial summaries without having to worry about NSObject
0411     // being declared.
0412     // FIXME: We may change this at some point.
0413     for (ObjCInterfaceDecl *C=D->getSuperClass() ;; C=C->getSuperClass()) {
0414       if ((I = M.find(ObjCSummaryKey(C, S))) != M.end())
0415         break;
0416 
0417       if (!C)
0418         return nullptr;
0419     }
0420 
0421     // Cache the summary with original key to make the next lookup faster
0422     // and return the iterator.
0423     const RetainSummary *Summ = I->second;
0424     M[K] = Summ;
0425     return Summ;
0426   }
0427 
0428   const RetainSummary *find(IdentifierInfo* II, Selector S) {
0429     // FIXME: Class method lookup.  Right now we don't have a good way
0430     // of going between IdentifierInfo* and the class hierarchy.
0431     MapTy::iterator I = M.find(ObjCSummaryKey(II, S));
0432 
0433     if (I == M.end())
0434       I = M.find(ObjCSummaryKey(S));
0435 
0436     return I == M.end() ? nullptr : I->second;
0437   }
0438 
0439   const RetainSummary *& operator[](ObjCSummaryKey K) {
0440     return M[K];
0441   }
0442 
0443   const RetainSummary *& operator[](Selector S) {
0444     return M[ ObjCSummaryKey(S) ];
0445   }
0446 };
0447 
0448 class RetainSummaryTemplate;
0449 
0450 class RetainSummaryManager {
0451   typedef llvm::DenseMap<const FunctionDecl*, const RetainSummary *>
0452           FuncSummariesTy;
0453 
0454   typedef ObjCSummaryCache ObjCMethodSummariesTy;
0455 
0456   typedef llvm::FoldingSetNodeWrapper<RetainSummary> CachedSummaryNode;
0457 
0458   /// Ctx - The ASTContext object for the analyzed ASTs.
0459   ASTContext &Ctx;
0460 
0461   /// Records whether or not the analyzed code runs in ARC mode.
0462   const bool ARCEnabled;
0463 
0464   /// Track Objective-C and CoreFoundation objects.
0465   const bool TrackObjCAndCFObjects;
0466 
0467   /// Track sublcasses of OSObject.
0468   const bool TrackOSObjects;
0469 
0470   /// FuncSummaries - A map from FunctionDecls to summaries.
0471   FuncSummariesTy FuncSummaries;
0472 
0473   /// ObjCClassMethodSummaries - A map from selectors (for instance methods)
0474   ///  to summaries.
0475   ObjCMethodSummariesTy ObjCClassMethodSummaries;
0476 
0477   /// ObjCMethodSummaries - A map from selectors to summaries.
0478   ObjCMethodSummariesTy ObjCMethodSummaries;
0479 
0480   /// BPAlloc - A BumpPtrAllocator used for allocating summaries, ArgEffects,
0481   ///  and all other data used by the checker.
0482   llvm::BumpPtrAllocator BPAlloc;
0483 
0484   /// AF - A factory for ArgEffects objects.
0485   ArgEffects::Factory AF;
0486 
0487   /// ObjCAllocRetE - Default return effect for methods returning Objective-C
0488   ///  objects.
0489   RetEffect ObjCAllocRetE;
0490 
0491   /// ObjCInitRetE - Default return effect for init methods returning
0492   ///   Objective-C objects.
0493   RetEffect ObjCInitRetE;
0494 
0495   /// SimpleSummaries - Used for uniquing summaries that don't have special
0496   /// effects.
0497   llvm::FoldingSet<CachedSummaryNode> SimpleSummaries;
0498 
0499   /// Create an OS object at +1.
0500   const RetainSummary *getOSSummaryCreateRule(const FunctionDecl *FD);
0501 
0502   /// Get an OS object at +0.
0503   const RetainSummary *getOSSummaryGetRule(const FunctionDecl *FD);
0504 
0505   /// Increment the reference count on OS object.
0506   const RetainSummary *getOSSummaryRetainRule(const FunctionDecl *FD);
0507 
0508   /// Decrement the reference count on OS object.
0509   const RetainSummary *getOSSummaryReleaseRule(const FunctionDecl *FD);
0510 
0511   /// Free the OS object.
0512   const RetainSummary *getOSSummaryFreeRule(const FunctionDecl *FD);
0513 
0514   const RetainSummary *getUnarySummary(const FunctionType* FT,
0515                                        ArgEffectKind AE);
0516 
0517   const RetainSummary *getCFSummaryCreateRule(const FunctionDecl *FD);
0518   const RetainSummary *getCFSummaryGetRule(const FunctionDecl *FD);
0519   const RetainSummary *getCFCreateGetRuleSummary(const FunctionDecl *FD);
0520 
0521   const RetainSummary *getPersistentSummary(const RetainSummary &OldSumm);
0522 
0523   const RetainSummary *
0524   getPersistentSummary(RetEffect RetEff, ArgEffects ScratchArgs,
0525                        ArgEffect ReceiverEff = ArgEffect(DoNothing),
0526                        ArgEffect DefaultEff = ArgEffect(MayEscape),
0527                        ArgEffect ThisEff = ArgEffect(DoNothing)) {
0528     RetainSummary Summ(ScratchArgs, RetEff, DefaultEff, ReceiverEff, ThisEff);
0529     return getPersistentSummary(Summ);
0530   }
0531 
0532   const RetainSummary *getDoNothingSummary() {
0533     return getPersistentSummary(RetEffect::MakeNoRet(),
0534                                 ArgEffects(AF.getEmptyMap()),
0535                                 ArgEffect(DoNothing), ArgEffect(DoNothing));
0536   }
0537 
0538   const RetainSummary *getDefaultSummary() {
0539     return getPersistentSummary(RetEffect::MakeNoRet(),
0540                                 ArgEffects(AF.getEmptyMap()),
0541                                 ArgEffect(DoNothing), ArgEffect(MayEscape));
0542   }
0543 
0544   const RetainSummary *getPersistentStopSummary() {
0545     return getPersistentSummary(
0546         RetEffect::MakeNoRet(), ArgEffects(AF.getEmptyMap()),
0547         ArgEffect(StopTracking), ArgEffect(StopTracking));
0548   }
0549 
0550   void InitializeClassMethodSummaries();
0551   void InitializeMethodSummaries();
0552 
0553   void addNSObjectClsMethSummary(Selector S, const RetainSummary *Summ) {
0554     ObjCClassMethodSummaries[S] = Summ;
0555   }
0556 
0557   void addNSObjectMethSummary(Selector S, const RetainSummary *Summ) {
0558     ObjCMethodSummaries[S] = Summ;
0559   }
0560 
0561   void addClassMethSummary(const char* Cls, const char* name,
0562                            const RetainSummary *Summ, bool isNullary = true) {
0563     IdentifierInfo* ClsII = &Ctx.Idents.get(Cls);
0564     Selector S = isNullary ? GetNullarySelector(name, Ctx)
0565                            : GetUnarySelector(name, Ctx);
0566     ObjCClassMethodSummaries[ObjCSummaryKey(ClsII, S)]  = Summ;
0567   }
0568 
0569   void addInstMethSummary(const char* Cls, const char* nullaryName,
0570                           const RetainSummary *Summ) {
0571     IdentifierInfo* ClsII = &Ctx.Idents.get(Cls);
0572     Selector S = GetNullarySelector(nullaryName, Ctx);
0573     ObjCMethodSummaries[ObjCSummaryKey(ClsII, S)]  = Summ;
0574   }
0575 
0576   template <typename... Keywords>
0577   void addMethodSummary(IdentifierInfo *ClsII, ObjCMethodSummariesTy &Summaries,
0578                         const RetainSummary *Summ, Keywords *... Kws) {
0579     Selector S = getKeywordSelector(Ctx, Kws...);
0580     Summaries[ObjCSummaryKey(ClsII, S)] = Summ;
0581   }
0582 
0583   template <typename... Keywords>
0584   void addInstMethSummary(const char *Cls, const RetainSummary *Summ,
0585                           Keywords *... Kws) {
0586     addMethodSummary(&Ctx.Idents.get(Cls), ObjCMethodSummaries, Summ, Kws...);
0587   }
0588 
0589   template <typename... Keywords>
0590   void addClsMethSummary(const char *Cls, const RetainSummary *Summ,
0591                          Keywords *... Kws) {
0592     addMethodSummary(&Ctx.Idents.get(Cls), ObjCClassMethodSummaries, Summ,
0593                      Kws...);
0594   }
0595 
0596   template <typename... Keywords>
0597   void addClsMethSummary(IdentifierInfo *II, const RetainSummary *Summ,
0598                          Keywords *... Kws) {
0599     addMethodSummary(II, ObjCClassMethodSummaries, Summ, Kws...);
0600   }
0601 
0602   const RetainSummary * generateSummary(const FunctionDecl *FD,
0603                                         bool &AllowAnnotations);
0604 
0605   /// Return a summary for OSObject, or nullptr if not found.
0606   const RetainSummary *getSummaryForOSObject(const FunctionDecl *FD,
0607                                              StringRef FName, QualType RetTy);
0608 
0609   /// Return a summary for Objective-C or CF object, or nullptr if not found.
0610   const RetainSummary *getSummaryForObjCOrCFObject(
0611     const FunctionDecl *FD,
0612     StringRef FName,
0613     QualType RetTy,
0614     const FunctionType *FT,
0615     bool &AllowAnnotations);
0616 
0617   /// Apply the annotation of @c pd in function @c FD
0618   /// to the resulting summary stored in out-parameter @c Template.
0619   /// \return whether an annotation was applied.
0620   bool applyParamAnnotationEffect(const ParmVarDecl *pd, unsigned parm_idx,
0621                                   const NamedDecl *FD,
0622                                   RetainSummaryTemplate &Template);
0623 
0624 public:
0625   RetainSummaryManager(ASTContext &ctx, bool trackObjCAndCFObjects,
0626                        bool trackOSObjects)
0627       : Ctx(ctx), ARCEnabled((bool)Ctx.getLangOpts().ObjCAutoRefCount),
0628         TrackObjCAndCFObjects(trackObjCAndCFObjects),
0629         TrackOSObjects(trackOSObjects), AF(BPAlloc),
0630         ObjCAllocRetE(ARCEnabled ? RetEffect::MakeNotOwned(ObjKind::ObjC)
0631                                  : RetEffect::MakeOwned(ObjKind::ObjC)),
0632         ObjCInitRetE(ARCEnabled ? RetEffect::MakeNotOwned(ObjKind::ObjC)
0633                                 : RetEffect::MakeOwnedWhenTrackedReceiver()) {
0634     InitializeClassMethodSummaries();
0635     InitializeMethodSummaries();
0636   }
0637 
0638   enum class BehaviorSummary {
0639     // Function does not return.
0640     NoOp,
0641 
0642     // Function returns the first argument.
0643     Identity,
0644 
0645     // Function returns "this" argument.
0646     IdentityThis,
0647 
0648     // Function either returns zero, or the input parameter.
0649     IdentityOrZero
0650   };
0651 
0652   std::optional<BehaviorSummary>
0653   canEval(const CallExpr *CE, const FunctionDecl *FD,
0654           bool &hasTrustedImplementationAnnotation);
0655 
0656   /// \return Whether the type corresponds to a known smart pointer
0657   /// implementation (that is, everything about it is inlineable).
0658   static bool isKnownSmartPointer(QualType QT);
0659 
0660   bool isTrustedReferenceCountImplementation(const Decl *FD);
0661 
0662   const RetainSummary *getSummary(AnyCall C,
0663                                   bool HasNonZeroCallbackArg=false,
0664                                   bool IsReceiverUnconsumedSelf=false,
0665                                   QualType ReceiverType={});
0666 
0667   RetEffect getObjAllocRetEffect() const { return ObjCAllocRetE; }
0668 
0669 private:
0670 
0671   /// getMethodSummary - This version of getMethodSummary is used to query
0672   ///  the summary for the current method being analyzed.
0673   const RetainSummary *getMethodSummary(const ObjCMethodDecl *MD);
0674 
0675   const RetainSummary *getFunctionSummary(const FunctionDecl *FD);
0676 
0677   const RetainSummary *getMethodSummary(Selector S, const ObjCInterfaceDecl *ID,
0678                                         const ObjCMethodDecl *MD,
0679                                         QualType RetTy,
0680                                         ObjCMethodSummariesTy &CachedSummaries);
0681 
0682   const RetainSummary *
0683   getInstanceMethodSummary(const ObjCMessageExpr *ME, QualType ReceiverType);
0684 
0685   const RetainSummary *getClassMethodSummary(const ObjCMessageExpr *ME);
0686 
0687   const RetainSummary *getStandardMethodSummary(const ObjCMethodDecl *MD,
0688                                                 Selector S, QualType RetTy);
0689 
0690   /// Determine if there is a special return effect for this function or method.
0691   std::optional<RetEffect> getRetEffectFromAnnotations(QualType RetTy,
0692                                                        const Decl *D);
0693 
0694   void updateSummaryFromAnnotations(const RetainSummary *&Summ,
0695                                     const ObjCMethodDecl *MD);
0696 
0697   void updateSummaryFromAnnotations(const RetainSummary *&Summ,
0698                                     const FunctionDecl *FD);
0699 
0700   const RetainSummary *updateSummaryForNonZeroCallbackArg(const RetainSummary *S,
0701                                                           AnyCall &C);
0702 
0703   /// Special case '[super init];' and '[self init];'
0704   ///
0705   /// Even though calling '[super init]' without assigning the result to self
0706   /// and checking if the parent returns 'nil' is a bad pattern, it is common.
0707   /// Additionally, our Self Init checker already warns about it. To avoid
0708   /// overwhelming the user with messages from both checkers, we model the case
0709   /// of '[super init]' in cases when it is not consumed by another expression
0710   /// as if the call preserves the value of 'self'; essentially, assuming it can
0711   /// never fail and return 'nil'.
0712   /// Note, we don't want to just stop tracking the value since we want the
0713   /// RetainCount checker to report leaks and use-after-free if SelfInit checker
0714   /// is turned off.
0715   void updateSummaryForReceiverUnconsumedSelf(const RetainSummary *&S);
0716 
0717   /// Set argument types for arguments which are not doing anything.
0718   void updateSummaryForArgumentTypes(const AnyCall &C, const RetainSummary *&RS);
0719 
0720   /// Determine whether a declaration @c D of correspondent type (return
0721   /// type for functions/methods) @c QT has any of the given attributes,
0722   /// provided they pass necessary validation checks AND tracking the given
0723   /// attribute is enabled.
0724   /// Returns the object kind corresponding to the present attribute, or
0725   /// std::nullopt, if none of the specified attributes are present.
0726   /// Crashes if passed an attribute which is not explicitly handled.
0727   template <class T>
0728   std::optional<ObjKind> hasAnyEnabledAttrOf(const Decl *D, QualType QT);
0729 
0730   template <class T1, class T2, class... Others>
0731   std::optional<ObjKind> hasAnyEnabledAttrOf(const Decl *D, QualType QT);
0732 
0733   friend class RetainSummaryTemplate;
0734 };
0735 
0736 
0737 // Used to avoid allocating long-term (BPAlloc'd) memory for default retain
0738 // summaries. If a function or method looks like it has a default summary, but
0739 // it has annotations, the annotations are added to the stack-based template
0740 // and then copied into managed memory.
0741 class RetainSummaryTemplate {
0742   RetainSummaryManager &Manager;
0743   const RetainSummary *&RealSummary;
0744   RetainSummary ScratchSummary;
0745   bool Accessed;
0746 public:
0747   RetainSummaryTemplate(const RetainSummary *&real, RetainSummaryManager &mgr)
0748     : Manager(mgr), RealSummary(real), ScratchSummary(*real), Accessed(false) {}
0749 
0750   ~RetainSummaryTemplate() {
0751     if (Accessed)
0752       RealSummary = Manager.getPersistentSummary(ScratchSummary);
0753   }
0754 
0755   RetainSummary &operator*() {
0756     Accessed = true;
0757     return ScratchSummary;
0758   }
0759 
0760   RetainSummary *operator->() {
0761     Accessed = true;
0762     return &ScratchSummary;
0763   }
0764 };
0765 
0766 } // end namespace ento
0767 } // end namespace clang
0768 
0769 #endif