Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Blame | Last modification | View Log | Download | RSS feed

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