123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778 |
- #pragma once
- #ifdef __GNUC__
- #pragma GCC diagnostic push
- #pragma GCC diagnostic ignored "-Wunused-parameter"
- #endif
- //=== RetainSummaryManager.h - Summaries for reference counting ---*- C++ -*--//
- //
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
- // See https://llvm.org/LICENSE.txt for license information.
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
- //
- //===----------------------------------------------------------------------===//
- //
- // This file defines summaries implementation for retain counting, which
- // implements a reference count checker for Core Foundation and Cocoa
- // on (Mac OS X).
- //
- //===----------------------------------------------------------------------===//
- #ifndef LLVM_CLANG_ANALYSIS_RETAINSUMMARYMANAGER_H
- #define LLVM_CLANG_ANALYSIS_RETAINSUMMARYMANAGER_H
- #include "llvm/ADT/DenseMap.h"
- #include "llvm/ADT/FoldingSet.h"
- #include "llvm/ADT/ImmutableMap.h"
- #include "clang/AST/Attr.h"
- #include "clang/AST/DeclCXX.h"
- #include "clang/AST/DeclObjC.h"
- #include "clang/AST/ParentMap.h"
- #include "clang/Analysis/AnyCall.h"
- #include "clang/Analysis/SelectorExtras.h"
- #include "llvm/ADT/STLExtras.h"
- using namespace clang;
- namespace clang {
- namespace ento {
- /// Determines the object kind of a tracked object.
- enum class ObjKind {
- /// Indicates that the tracked object is a CF object.
- CF,
- /// Indicates that the tracked object is an Objective-C object.
- ObjC,
- /// Indicates that the tracked object could be a CF or Objective-C object.
- AnyObj,
- /// Indicates that the tracked object is a generalized object.
- Generalized,
- /// Indicates that the tracking object is a descendant of a
- /// referenced-counted OSObject, used in the Darwin kernel.
- OS
- };
- enum ArgEffectKind {
- /// There is no effect.
- DoNothing,
- /// The argument is treated as if an -autorelease message had been sent to
- /// the referenced object.
- Autorelease,
- /// The argument is treated as if the referenced object was deallocated.
- Dealloc,
- /// The argument has its reference count decreased by 1.
- DecRef,
- /// The argument has its reference count decreased by 1 to model
- /// a transferred bridge cast under ARC.
- DecRefBridgedTransferred,
- /// The argument has its reference count increased by 1.
- IncRef,
- /// The argument is a pointer to a retain-counted object; on exit, the new
- /// value of the pointer is a +0 value.
- UnretainedOutParameter,
- /// The argument is a pointer to a retain-counted object; on exit, the new
- /// value of the pointer is a +1 value.
- RetainedOutParameter,
- /// The argument is a pointer to a retain-counted object; on exit, the new
- /// value of the pointer is a +1 value iff the return code is zero.
- RetainedOutParameterOnZero,
- /// The argument is a pointer to a retain-counted object; on exit, the new
- /// value of the pointer is a +1 value iff the return code is non-zero.
- RetainedOutParameterOnNonZero,
- /// The argument is treated as potentially escaping, meaning that
- /// even when its reference count hits 0 it should be treated as still
- /// possibly being alive as someone else *may* be holding onto the object.
- MayEscape,
- /// All typestate tracking of the object ceases. This is usually employed
- /// when the effect of the call is completely unknown.
- StopTracking,
- /// All typestate tracking of the object ceases. Unlike StopTracking,
- /// this is also enforced when the method body is inlined.
- ///
- /// In some cases, we obtain a better summary for this checker
- /// by looking at the call site than by inlining the function.
- /// Signifies that we should stop tracking the symbol even if
- /// the function is inlined.
- StopTrackingHard,
- /// Performs the combined functionality of DecRef and StopTrackingHard.
- ///
- /// The models the effect that the called function decrements the reference
- /// count of the argument and all typestate tracking on that argument
- /// should cease.
- DecRefAndStopTrackingHard,
- };
- /// An ArgEffect summarizes the retain count behavior on an argument or receiver
- /// to a function or method.
- class ArgEffect {
- ArgEffectKind K;
- ObjKind O;
- public:
- explicit ArgEffect(ArgEffectKind K = DoNothing, ObjKind O = ObjKind::AnyObj)
- : K(K), O(O) {}
- ArgEffectKind getKind() const { return K; }
- ObjKind getObjKind() const { return O; }
- ArgEffect withKind(ArgEffectKind NewK) {
- return ArgEffect(NewK, O);
- }
- bool operator==(const ArgEffect &Other) const {
- return K == Other.K && O == Other.O;
- }
- };
- /// RetEffect summarizes a call's retain/release behavior with respect
- /// to its return value.
- class RetEffect {
- public:
- enum Kind {
- /// Indicates that no retain count information is tracked for
- /// the return value.
- NoRet,
- /// Indicates that the returned value is an owned (+1) symbol.
- OwnedSymbol,
- /// Indicates that the returned value is an object with retain count
- /// semantics but that it is not owned (+0). This is the default
- /// for getters, etc.
- NotOwnedSymbol,
- /// Indicates that the return value is an owned object when the
- /// receiver is also a tracked object.
- OwnedWhenTrackedReceiver,
- // Treat this function as returning a non-tracked symbol even if
- // the function has been inlined. This is used where the call
- // site summary is more precise than the summary indirectly produced
- // by inlining the function
- NoRetHard
- };
- private:
- Kind K;
- ObjKind O;
- RetEffect(Kind k, ObjKind o = ObjKind::AnyObj) : K(k), O(o) {}
- public:
- Kind getKind() const { return K; }
- ObjKind getObjKind() const { return O; }
- bool isOwned() const {
- return K == OwnedSymbol || K == OwnedWhenTrackedReceiver;
- }
- bool notOwned() const {
- return K == NotOwnedSymbol;
- }
- bool operator==(const RetEffect &Other) const {
- return K == Other.K && O == Other.O;
- }
- static RetEffect MakeOwnedWhenTrackedReceiver() {
- return RetEffect(OwnedWhenTrackedReceiver, ObjKind::ObjC);
- }
- static RetEffect MakeOwned(ObjKind o) {
- return RetEffect(OwnedSymbol, o);
- }
- static RetEffect MakeNotOwned(ObjKind o) {
- return RetEffect(NotOwnedSymbol, o);
- }
- static RetEffect MakeNoRet() {
- return RetEffect(NoRet);
- }
- static RetEffect MakeNoRetHard() {
- return RetEffect(NoRetHard);
- }
- };
- /// A key identifying a summary.
- class ObjCSummaryKey {
- IdentifierInfo* II;
- Selector S;
- public:
- ObjCSummaryKey(IdentifierInfo* ii, Selector s)
- : II(ii), S(s) {}
- ObjCSummaryKey(const ObjCInterfaceDecl *d, Selector s)
- : II(d ? d->getIdentifier() : nullptr), S(s) {}
- ObjCSummaryKey(Selector s)
- : II(nullptr), S(s) {}
- IdentifierInfo *getIdentifier() const { return II; }
- Selector getSelector() const { return S; }
- };
- } // end namespace ento
- } // end namespace clang
- using namespace ento;
- namespace llvm {
- //===----------------------------------------------------------------------===//
- // Adapters for FoldingSet.
- //===----------------------------------------------------------------------===//
- template <> struct FoldingSetTrait<ArgEffect> {
- static inline void Profile(const ArgEffect X, FoldingSetNodeID &ID) {
- ID.AddInteger((unsigned) X.getKind());
- ID.AddInteger((unsigned) X.getObjKind());
- }
- };
- template <> struct FoldingSetTrait<RetEffect> {
- static inline void Profile(const RetEffect &X, FoldingSetNodeID &ID) {
- ID.AddInteger((unsigned) X.getKind());
- ID.AddInteger((unsigned) X.getObjKind());
- }
- };
- template <> struct DenseMapInfo<ObjCSummaryKey> {
- static inline ObjCSummaryKey getEmptyKey() {
- return ObjCSummaryKey(DenseMapInfo<IdentifierInfo*>::getEmptyKey(),
- DenseMapInfo<Selector>::getEmptyKey());
- }
- static inline ObjCSummaryKey getTombstoneKey() {
- return ObjCSummaryKey(DenseMapInfo<IdentifierInfo*>::getTombstoneKey(),
- DenseMapInfo<Selector>::getTombstoneKey());
- }
- static unsigned getHashValue(const ObjCSummaryKey &V) {
- typedef std::pair<IdentifierInfo*, Selector> PairTy;
- return DenseMapInfo<PairTy>::getHashValue(PairTy(V.getIdentifier(),
- V.getSelector()));
- }
- static bool isEqual(const ObjCSummaryKey& LHS, const ObjCSummaryKey& RHS) {
- return LHS.getIdentifier() == RHS.getIdentifier() &&
- LHS.getSelector() == RHS.getSelector();
- }
- };
- } // end llvm namespace
- namespace clang {
- namespace ento {
- /// ArgEffects summarizes the effects of a function/method call on all of
- /// its arguments.
- typedef llvm::ImmutableMap<unsigned, ArgEffect> ArgEffects;
- /// Summary for a function with respect to ownership changes.
- class RetainSummary {
- /// Args - a map of (index, ArgEffect) pairs, where index
- /// specifies the argument (starting from 0). This can be sparsely
- /// populated; arguments with no entry in Args use 'DefaultArgEffect'.
- ArgEffects Args;
- /// DefaultArgEffect - The default ArgEffect to apply to arguments that
- /// do not have an entry in Args.
- ArgEffect DefaultArgEffect;
- /// Receiver - If this summary applies to an Objective-C message expression,
- /// this is the effect applied to the state of the receiver.
- ArgEffect Receiver;
- /// Effect on "this" pointer - applicable only to C++ method calls.
- ArgEffect This;
- /// Ret - The effect on the return value. Used to indicate if the
- /// function/method call returns a new tracked symbol.
- RetEffect Ret;
- public:
- RetainSummary(ArgEffects A,
- RetEffect R,
- ArgEffect defaultEff,
- ArgEffect ReceiverEff,
- ArgEffect ThisEff)
- : Args(A), DefaultArgEffect(defaultEff), Receiver(ReceiverEff),
- This(ThisEff), Ret(R) {}
- /// getArg - Return the argument effect on the argument specified by
- /// idx (starting from 0).
- ArgEffect getArg(unsigned idx) const {
- if (const ArgEffect *AE = Args.lookup(idx))
- return *AE;
- return DefaultArgEffect;
- }
- void addArg(ArgEffects::Factory &af, unsigned idx, ArgEffect e) {
- Args = af.add(Args, idx, e);
- }
- /// setDefaultArgEffect - Set the default argument effect.
- void setDefaultArgEffect(ArgEffect E) {
- DefaultArgEffect = E;
- }
- /// getRetEffect - Returns the effect on the return value of the call.
- RetEffect getRetEffect() const { return Ret; }
- /// setRetEffect - Set the effect of the return value of the call.
- void setRetEffect(RetEffect E) { Ret = E; }
- /// Sets the effect on the receiver of the message.
- void setReceiverEffect(ArgEffect e) { Receiver = e; }
- /// getReceiverEffect - Returns the effect on the receiver of the call.
- /// This is only meaningful if the summary applies to an ObjCMessageExpr*.
- ArgEffect getReceiverEffect() const { return Receiver; }
- /// \return the effect on the "this" receiver of the method call.
- /// This is only meaningful if the summary applies to CXXMethodDecl*.
- ArgEffect getThisEffect() const { return This; }
- ArgEffect getDefaultEffect() const { return DefaultArgEffect; }
- /// Set the effect of the method on "this".
- void setThisEffect(ArgEffect e) { This = e; }
- bool isNoop() const {
- return Ret == RetEffect::MakeNoRet() && Receiver.getKind() == DoNothing
- && DefaultArgEffect.getKind() == MayEscape && This.getKind() == DoNothing
- && Args.isEmpty();
- }
- /// Test if two retain summaries are identical. Note that merely equivalent
- /// summaries are not necessarily identical (for example, if an explicit
- /// argument effect matches the default effect).
- bool operator==(const RetainSummary &Other) const {
- return Args == Other.Args && DefaultArgEffect == Other.DefaultArgEffect &&
- Receiver == Other.Receiver && This == Other.This && Ret == Other.Ret;
- }
- /// Profile this summary for inclusion in a FoldingSet.
- void Profile(llvm::FoldingSetNodeID& ID) const {
- ID.Add(Args);
- ID.Add(DefaultArgEffect);
- ID.Add(Receiver);
- ID.Add(This);
- ID.Add(Ret);
- }
- /// A retain summary is simple if it has no ArgEffects other than the default.
- bool isSimple() const {
- return Args.isEmpty();
- }
- ArgEffects getArgEffects() const { return Args; }
- private:
- ArgEffect getDefaultArgEffect() const { return DefaultArgEffect; }
- friend class RetainSummaryManager;
- };
- class ObjCSummaryCache {
- typedef llvm::DenseMap<ObjCSummaryKey, const RetainSummary *> MapTy;
- MapTy M;
- public:
- ObjCSummaryCache() {}
- const RetainSummary * find(const ObjCInterfaceDecl *D, Selector S) {
- // Do a lookup with the (D,S) pair. If we find a match return
- // the iterator.
- ObjCSummaryKey K(D, S);
- MapTy::iterator I = M.find(K);
- if (I != M.end())
- return I->second;
- if (!D)
- return nullptr;
- // Walk the super chain. If we find a hit with a parent, we'll end
- // up returning that summary. We actually allow that key (null,S), as
- // we cache summaries for the null ObjCInterfaceDecl* to allow us to
- // generate initial summaries without having to worry about NSObject
- // being declared.
- // FIXME: We may change this at some point.
- for (ObjCInterfaceDecl *C=D->getSuperClass() ;; C=C->getSuperClass()) {
- if ((I = M.find(ObjCSummaryKey(C, S))) != M.end())
- break;
- if (!C)
- return nullptr;
- }
- // Cache the summary with original key to make the next lookup faster
- // and return the iterator.
- const RetainSummary *Summ = I->second;
- M[K] = Summ;
- return Summ;
- }
- const RetainSummary *find(IdentifierInfo* II, Selector S) {
- // FIXME: Class method lookup. Right now we don't have a good way
- // of going between IdentifierInfo* and the class hierarchy.
- MapTy::iterator I = M.find(ObjCSummaryKey(II, S));
- if (I == M.end())
- I = M.find(ObjCSummaryKey(S));
- return I == M.end() ? nullptr : I->second;
- }
- const RetainSummary *& operator[](ObjCSummaryKey K) {
- return M[K];
- }
- const RetainSummary *& operator[](Selector S) {
- return M[ ObjCSummaryKey(S) ];
- }
- };
- class RetainSummaryTemplate;
- class RetainSummaryManager {
- typedef llvm::DenseMap<const FunctionDecl*, const RetainSummary *>
- FuncSummariesTy;
- typedef ObjCSummaryCache ObjCMethodSummariesTy;
- typedef llvm::FoldingSetNodeWrapper<RetainSummary> CachedSummaryNode;
- /// Ctx - The ASTContext object for the analyzed ASTs.
- ASTContext &Ctx;
- /// Records whether or not the analyzed code runs in ARC mode.
- const bool ARCEnabled;
- /// Track Objective-C and CoreFoundation objects.
- const bool TrackObjCAndCFObjects;
- /// Track sublcasses of OSObject.
- const bool TrackOSObjects;
- /// FuncSummaries - A map from FunctionDecls to summaries.
- FuncSummariesTy FuncSummaries;
- /// ObjCClassMethodSummaries - A map from selectors (for instance methods)
- /// to summaries.
- ObjCMethodSummariesTy ObjCClassMethodSummaries;
- /// ObjCMethodSummaries - A map from selectors to summaries.
- ObjCMethodSummariesTy ObjCMethodSummaries;
- /// BPAlloc - A BumpPtrAllocator used for allocating summaries, ArgEffects,
- /// and all other data used by the checker.
- llvm::BumpPtrAllocator BPAlloc;
- /// AF - A factory for ArgEffects objects.
- ArgEffects::Factory AF;
- /// ObjCAllocRetE - Default return effect for methods returning Objective-C
- /// objects.
- RetEffect ObjCAllocRetE;
- /// ObjCInitRetE - Default return effect for init methods returning
- /// Objective-C objects.
- RetEffect ObjCInitRetE;
- /// SimpleSummaries - Used for uniquing summaries that don't have special
- /// effects.
- llvm::FoldingSet<CachedSummaryNode> SimpleSummaries;
- /// Create an OS object at +1.
- const RetainSummary *getOSSummaryCreateRule(const FunctionDecl *FD);
- /// Get an OS object at +0.
- const RetainSummary *getOSSummaryGetRule(const FunctionDecl *FD);
- /// Increment the reference count on OS object.
- const RetainSummary *getOSSummaryRetainRule(const FunctionDecl *FD);
- /// Decrement the reference count on OS object.
- const RetainSummary *getOSSummaryReleaseRule(const FunctionDecl *FD);
- /// Free the OS object.
- const RetainSummary *getOSSummaryFreeRule(const FunctionDecl *FD);
- const RetainSummary *getUnarySummary(const FunctionType* FT,
- ArgEffectKind AE);
- const RetainSummary *getCFSummaryCreateRule(const FunctionDecl *FD);
- const RetainSummary *getCFSummaryGetRule(const FunctionDecl *FD);
- const RetainSummary *getCFCreateGetRuleSummary(const FunctionDecl *FD);
- const RetainSummary *getPersistentSummary(const RetainSummary &OldSumm);
- const RetainSummary *
- getPersistentSummary(RetEffect RetEff, ArgEffects ScratchArgs,
- ArgEffect ReceiverEff = ArgEffect(DoNothing),
- ArgEffect DefaultEff = ArgEffect(MayEscape),
- ArgEffect ThisEff = ArgEffect(DoNothing)) {
- RetainSummary Summ(ScratchArgs, RetEff, DefaultEff, ReceiverEff, ThisEff);
- return getPersistentSummary(Summ);
- }
- const RetainSummary *getDoNothingSummary() {
- return getPersistentSummary(RetEffect::MakeNoRet(),
- ArgEffects(AF.getEmptyMap()),
- ArgEffect(DoNothing), ArgEffect(DoNothing));
- }
- const RetainSummary *getDefaultSummary() {
- return getPersistentSummary(RetEffect::MakeNoRet(),
- ArgEffects(AF.getEmptyMap()),
- ArgEffect(DoNothing), ArgEffect(MayEscape));
- }
- const RetainSummary *getPersistentStopSummary() {
- return getPersistentSummary(
- RetEffect::MakeNoRet(), ArgEffects(AF.getEmptyMap()),
- ArgEffect(StopTracking), ArgEffect(StopTracking));
- }
- void InitializeClassMethodSummaries();
- void InitializeMethodSummaries();
- void addNSObjectClsMethSummary(Selector S, const RetainSummary *Summ) {
- ObjCClassMethodSummaries[S] = Summ;
- }
- void addNSObjectMethSummary(Selector S, const RetainSummary *Summ) {
- ObjCMethodSummaries[S] = Summ;
- }
- void addClassMethSummary(const char* Cls, const char* name,
- const RetainSummary *Summ, bool isNullary = true) {
- IdentifierInfo* ClsII = &Ctx.Idents.get(Cls);
- Selector S = isNullary ? GetNullarySelector(name, Ctx)
- : GetUnarySelector(name, Ctx);
- ObjCClassMethodSummaries[ObjCSummaryKey(ClsII, S)] = Summ;
- }
- void addInstMethSummary(const char* Cls, const char* nullaryName,
- const RetainSummary *Summ) {
- IdentifierInfo* ClsII = &Ctx.Idents.get(Cls);
- Selector S = GetNullarySelector(nullaryName, Ctx);
- ObjCMethodSummaries[ObjCSummaryKey(ClsII, S)] = Summ;
- }
- template <typename... Keywords>
- void addMethodSummary(IdentifierInfo *ClsII, ObjCMethodSummariesTy &Summaries,
- const RetainSummary *Summ, Keywords *... Kws) {
- Selector S = getKeywordSelector(Ctx, Kws...);
- Summaries[ObjCSummaryKey(ClsII, S)] = Summ;
- }
- template <typename... Keywords>
- void addInstMethSummary(const char *Cls, const RetainSummary *Summ,
- Keywords *... Kws) {
- addMethodSummary(&Ctx.Idents.get(Cls), ObjCMethodSummaries, Summ, Kws...);
- }
- template <typename... Keywords>
- void addClsMethSummary(const char *Cls, const RetainSummary *Summ,
- Keywords *... Kws) {
- addMethodSummary(&Ctx.Idents.get(Cls), ObjCClassMethodSummaries, Summ,
- Kws...);
- }
- template <typename... Keywords>
- void addClsMethSummary(IdentifierInfo *II, const RetainSummary *Summ,
- Keywords *... Kws) {
- addMethodSummary(II, ObjCClassMethodSummaries, Summ, Kws...);
- }
- const RetainSummary * generateSummary(const FunctionDecl *FD,
- bool &AllowAnnotations);
- /// Return a summary for OSObject, or nullptr if not found.
- const RetainSummary *getSummaryForOSObject(const FunctionDecl *FD,
- StringRef FName, QualType RetTy);
- /// Return a summary for Objective-C or CF object, or nullptr if not found.
- const RetainSummary *getSummaryForObjCOrCFObject(
- const FunctionDecl *FD,
- StringRef FName,
- QualType RetTy,
- const FunctionType *FT,
- bool &AllowAnnotations);
- /// Apply the annotation of @c pd in function @c FD
- /// to the resulting summary stored in out-parameter @c Template.
- /// \return whether an annotation was applied.
- bool applyParamAnnotationEffect(const ParmVarDecl *pd, unsigned parm_idx,
- const NamedDecl *FD,
- RetainSummaryTemplate &Template);
- public:
- RetainSummaryManager(ASTContext &ctx, bool trackObjCAndCFObjects,
- bool trackOSObjects)
- : Ctx(ctx), ARCEnabled((bool)Ctx.getLangOpts().ObjCAutoRefCount),
- TrackObjCAndCFObjects(trackObjCAndCFObjects),
- TrackOSObjects(trackOSObjects), AF(BPAlloc),
- ObjCAllocRetE(ARCEnabled ? RetEffect::MakeNotOwned(ObjKind::ObjC)
- : RetEffect::MakeOwned(ObjKind::ObjC)),
- ObjCInitRetE(ARCEnabled ? RetEffect::MakeNotOwned(ObjKind::ObjC)
- : RetEffect::MakeOwnedWhenTrackedReceiver()) {
- InitializeClassMethodSummaries();
- InitializeMethodSummaries();
- }
- enum class BehaviorSummary {
- // Function does not return.
- NoOp,
- // Function returns the first argument.
- Identity,
- // Function returns "this" argument.
- IdentityThis,
- // Function either returns zero, or the input parameter.
- IdentityOrZero
- };
- Optional<BehaviorSummary> canEval(const CallExpr *CE, const FunctionDecl *FD,
- bool &hasTrustedImplementationAnnotation);
- /// \return Whether the type corresponds to a known smart pointer
- /// implementation (that is, everything about it is inlineable).
- static bool isKnownSmartPointer(QualType QT);
- bool isTrustedReferenceCountImplementation(const Decl *FD);
- const RetainSummary *getSummary(AnyCall C,
- bool HasNonZeroCallbackArg=false,
- bool IsReceiverUnconsumedSelf=false,
- QualType ReceiverType={});
- RetEffect getObjAllocRetEffect() const { return ObjCAllocRetE; }
- private:
- /// getMethodSummary - This version of getMethodSummary is used to query
- /// the summary for the current method being analyzed.
- const RetainSummary *getMethodSummary(const ObjCMethodDecl *MD);
- const RetainSummary *getFunctionSummary(const FunctionDecl *FD);
- const RetainSummary *getMethodSummary(Selector S, const ObjCInterfaceDecl *ID,
- const ObjCMethodDecl *MD,
- QualType RetTy,
- ObjCMethodSummariesTy &CachedSummaries);
- const RetainSummary *
- getInstanceMethodSummary(const ObjCMessageExpr *ME, QualType ReceiverType);
- const RetainSummary *getClassMethodSummary(const ObjCMessageExpr *ME);
- const RetainSummary *getStandardMethodSummary(const ObjCMethodDecl *MD,
- Selector S, QualType RetTy);
- /// Determine if there is a special return effect for this function or method.
- Optional<RetEffect> getRetEffectFromAnnotations(QualType RetTy,
- const Decl *D);
- void updateSummaryFromAnnotations(const RetainSummary *&Summ,
- const ObjCMethodDecl *MD);
- void updateSummaryFromAnnotations(const RetainSummary *&Summ,
- const FunctionDecl *FD);
- const RetainSummary *updateSummaryForNonZeroCallbackArg(const RetainSummary *S,
- AnyCall &C);
- /// Special case '[super init];' and '[self init];'
- ///
- /// Even though calling '[super init]' without assigning the result to self
- /// and checking if the parent returns 'nil' is a bad pattern, it is common.
- /// Additionally, our Self Init checker already warns about it. To avoid
- /// overwhelming the user with messages from both checkers, we model the case
- /// of '[super init]' in cases when it is not consumed by another expression
- /// as if the call preserves the value of 'self'; essentially, assuming it can
- /// never fail and return 'nil'.
- /// Note, we don't want to just stop tracking the value since we want the
- /// RetainCount checker to report leaks and use-after-free if SelfInit checker
- /// is turned off.
- void updateSummaryForReceiverUnconsumedSelf(const RetainSummary *&S);
- /// Set argument types for arguments which are not doing anything.
- void updateSummaryForArgumentTypes(const AnyCall &C, const RetainSummary *&RS);
- /// Determine whether a declaration @c D of correspondent type (return
- /// type for functions/methods) @c QT has any of the given attributes,
- /// provided they pass necessary validation checks AND tracking the given
- /// attribute is enabled.
- /// Returns the object kind corresponding to the present attribute, or None,
- /// if none of the specified attributes are present.
- /// Crashes if passed an attribute which is not explicitly handled.
- template <class T>
- Optional<ObjKind> hasAnyEnabledAttrOf(const Decl *D, QualType QT);
- template <class T1, class T2, class... Others>
- Optional<ObjKind> hasAnyEnabledAttrOf(const Decl *D, QualType QT);
- friend class RetainSummaryTemplate;
- };
- // Used to avoid allocating long-term (BPAlloc'd) memory for default retain
- // summaries. If a function or method looks like it has a default summary, but
- // it has annotations, the annotations are added to the stack-based template
- // and then copied into managed memory.
- class RetainSummaryTemplate {
- RetainSummaryManager &Manager;
- const RetainSummary *&RealSummary;
- RetainSummary ScratchSummary;
- bool Accessed;
- public:
- RetainSummaryTemplate(const RetainSummary *&real, RetainSummaryManager &mgr)
- : Manager(mgr), RealSummary(real), ScratchSummary(*real), Accessed(false) {}
- ~RetainSummaryTemplate() {
- if (Accessed)
- RealSummary = Manager.getPersistentSummary(ScratchSummary);
- }
- RetainSummary &operator*() {
- Accessed = true;
- return ScratchSummary;
- }
- RetainSummary *operator->() {
- Accessed = true;
- return &ScratchSummary;
- }
- };
- } // end namespace ento
- } // end namespace clang
- #endif
- #ifdef __GNUC__
- #pragma GCC diagnostic pop
- #endif
|