diff options
author | George Karpenkov <ekarpenkov@apple.com> | 2018-08-21 03:09:02 +0000 |
---|---|---|
committer | George Karpenkov <ekarpenkov@apple.com> | 2018-08-21 03:09:02 +0000 |
commit | 3025b837ed076a70786893c4a96a4389c53c487e (patch) | |
tree | c1a491b871058f9efcb526967506b194aa7fcc93 /lib | |
parent | 43e71a0b50e85ee4b755ca43e554099dba14decc (diff) | |
download | clang-3025b837ed076a70786893c4a96a4389c53c487e.tar.gz |
[analyzer] [NFC] Split up RetainSummaryManager from RetainCountChecker - try #2
Turns out it can't be removed from the analyzer since it relies on CallEvent.
Moving to staticAnalyzer/core
Differential Revision: https://reviews.llvm.org/D51023
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@340247 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r-- | lib/ARCMigrate/ObjCMT.cpp | 4 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp | 2 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Checkers/CMakeLists.txt | 4 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Checkers/NoReturnFunctionChecker.cpp | 2 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.cpp | 54 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.h | 6 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountDiagnostics.h | 2 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountSummaries.h | 518 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Checkers/SelectorExtras.h | 46 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Checkers/TrustNonnullChecker.cpp | 2 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/CMakeLists.txt | 1 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/RetainSummaryManager.cpp (renamed from lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountSummaries.cpp) | 58 |
12 files changed, 59 insertions, 640 deletions
diff --git a/lib/ARCMigrate/ObjCMT.cpp b/lib/ARCMigrate/ObjCMT.cpp index 7353c8c479..d202411429 100644 --- a/lib/ARCMigrate/ObjCMT.cpp +++ b/lib/ARCMigrate/ObjCMT.cpp @@ -8,7 +8,6 @@ //===----------------------------------------------------------------------===// #include "Transforms.h" -#include "clang/Analysis/ObjCRetainCount.h" #include "clang/ARCMigrate/ARCMT.h" #include "clang/ARCMigrate/ARCMTActions.h" #include "clang/AST/ASTConsumer.h" @@ -28,6 +27,7 @@ #include "clang/Lex/PPConditionalDirectiveRecord.h" #include "clang/Lex/Preprocessor.h" #include "clang/Rewrite/Core/Rewriter.h" +#include "clang/StaticAnalyzer/Core/RetainSummaryManager.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringSet.h" #include "llvm/Support/Path.h" @@ -36,7 +36,7 @@ using namespace clang; using namespace arcmt; -using namespace ento::objc_retain; +using namespace ento; namespace { diff --git a/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp b/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp index cff0f0a29b..70ce41ac89 100644 --- a/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp +++ b/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp @@ -14,13 +14,13 @@ //===----------------------------------------------------------------------===// #include "ClangSACheckers.h" -#include "SelectorExtras.h" #include "clang/AST/ASTContext.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/Expr.h" #include "clang/AST/ExprObjC.h" #include "clang/AST/StmtObjC.h" #include "clang/Analysis/DomainSpecific/CocoaConventions.h" +#include "clang/Analysis/SelectorExtras.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" #include "clang/StaticAnalyzer/Core/Checker.h" #include "clang/StaticAnalyzer/Core/CheckerManager.h" diff --git a/lib/StaticAnalyzer/Checkers/CMakeLists.txt b/lib/StaticAnalyzer/Checkers/CMakeLists.txt index 0b2aab94da..306813b880 100644 --- a/lib/StaticAnalyzer/Checkers/CMakeLists.txt +++ b/lib/StaticAnalyzer/Checkers/CMakeLists.txt @@ -77,7 +77,6 @@ add_clang_library(clangStaticAnalyzerCheckers PointerSubChecker.cpp PthreadLockChecker.cpp RetainCountChecker/RetainCountChecker.cpp - RetainCountChecker/RetainCountSummaries.cpp RetainCountChecker/RetainCountDiagnostics.cpp ReturnPointerRangeChecker.cpp ReturnUndefChecker.cpp @@ -104,9 +103,6 @@ add_clang_library(clangStaticAnalyzerCheckers ValistChecker.cpp VirtualCallChecker.cpp - DEPENDS - ClangSACheckers - LINK_LIBS clangAST clangASTMatchers diff --git a/lib/StaticAnalyzer/Checkers/NoReturnFunctionChecker.cpp b/lib/StaticAnalyzer/Checkers/NoReturnFunctionChecker.cpp index 8a5c769b6b..44674eb4d7 100644 --- a/lib/StaticAnalyzer/Checkers/NoReturnFunctionChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/NoReturnFunctionChecker.cpp @@ -13,8 +13,8 @@ //===----------------------------------------------------------------------===// #include "ClangSACheckers.h" -#include "SelectorExtras.h" #include "clang/AST/Attr.h" +#include "clang/Analysis/SelectorExtras.h" #include "clang/StaticAnalyzer/Core/Checker.h" #include "clang/StaticAnalyzer/Core/CheckerManager.h" #include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h" diff --git a/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.cpp b/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.cpp index a8957e1704..9d6c8314d8 100644 --- a/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.cpp @@ -16,7 +16,6 @@ using namespace clang; using namespace ento; -using namespace objc_retain; using namespace retaincountchecker; using llvm::StrInStrNoCase; @@ -331,7 +330,19 @@ void RetainCountChecker::checkPostStmt(const ObjCIvarRefExpr *IRE, void RetainCountChecker::checkPostCall(const CallEvent &Call, CheckerContext &C) const { RetainSummaryManager &Summaries = getSummaryManager(C); - const RetainSummary *Summ = Summaries.getSummary(Call, C.getState()); + + // Leave null if no receiver. + QualType ReceiverType; + if (const auto *MC = dyn_cast<ObjCMethodCall>(&Call)) { + if (MC->isInstanceMessage()) { + SVal ReceiverV = MC->getReceiverSVal(); + if (SymbolRef Sym = ReceiverV.getAsLocSymbol()) + if (const RefVal *T = getRefBinding(C.getState(), Sym)) + ReceiverType = T->getType(); + } + } + + const RetainSummary *Summ = Summaries.getSummary(Call, ReceiverType); if (C.wasInlined) { processSummaryOfInlined(*Summ, Call, C); @@ -1388,45 +1399,6 @@ void RetainCountChecker::printState(raw_ostream &Out, ProgramStateRef State, } //===----------------------------------------------------------------------===// -// Implementation of the CallEffects API. -//===----------------------------------------------------------------------===// - -namespace clang { -namespace ento { -namespace objc_retain { - -// This is a bit gross, but it allows us to populate CallEffects without -// creating a bunch of accessors. This kind is very localized, so the -// damage of this macro is limited. -#define createCallEffect(D, KIND)\ - ASTContext &Ctx = D->getASTContext();\ - LangOptions L = Ctx.getLangOpts();\ - RetainSummaryManager M(Ctx, L.ObjCAutoRefCount);\ - const RetainSummary *S = M.get ## KIND ## Summary(D);\ - CallEffects CE(S->getRetEffect());\ - CE.Receiver = S->getReceiverEffect();\ - unsigned N = D->param_size();\ - for (unsigned i = 0; i < N; ++i) {\ - CE.Args.push_back(S->getArg(i));\ - } - -CallEffects CallEffects::getEffect(const ObjCMethodDecl *MD) { - createCallEffect(MD, Method); - return CE; -} - -CallEffects CallEffects::getEffect(const FunctionDecl *FD) { - createCallEffect(FD, Function); - return CE; -} - -#undef createCallEffect - -} // end namespace objc_retain -} // end namespace ento -} // end namespace clang - -//===----------------------------------------------------------------------===// // Checker registration. //===----------------------------------------------------------------------===// diff --git a/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.h b/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.h index 9946591c4d..15172a9deb 100644 --- a/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.h +++ b/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.h @@ -17,10 +17,7 @@ #include "../ClangSACheckers.h" #include "../AllocationDiagnostics.h" -#include "../SelectorExtras.h" -#include "RetainCountSummaries.h" #include "RetainCountDiagnostics.h" -#include "clang/Analysis/ObjCRetainCount.h" #include "clang/AST/Attr.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclObjC.h" @@ -28,6 +25,7 @@ #include "clang/Analysis/DomainSpecific/CocoaConventions.h" #include "clang/Basic/LangOptions.h" #include "clang/Basic/SourceManager.h" +#include "clang/Analysis/SelectorExtras.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" #include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h" #include "clang/StaticAnalyzer/Core/Checker.h" @@ -36,6 +34,7 @@ #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h" #include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h" +#include "clang/StaticAnalyzer/Core/RetainSummaryManager.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/ImmutableList.h" @@ -46,7 +45,6 @@ #include <cstdarg> #include <utility> -using namespace objc_retain; using llvm::StrInStrNoCase; namespace clang { diff --git a/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountDiagnostics.h b/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountDiagnostics.h index cbdfe3a916..83c2be8298 100644 --- a/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountDiagnostics.h +++ b/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountDiagnostics.h @@ -15,10 +15,10 @@ #ifndef LLVM_CLANG_LIB_STATICANALYZER_CHECKERS_RETAINCOUNTCHECKER_DIAGNOSTICS_H #define LLVM_CLANG_LIB_STATICANALYZER_CHECKERS_RETAINCOUNTCHECKER_DIAGNOSTICS_H -#include "RetainCountSummaries.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h" #include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h" +#include "clang/StaticAnalyzer/Core/RetainSummaryManager.h" namespace clang { namespace ento { diff --git a/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountSummaries.h b/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountSummaries.h deleted file mode 100644 index dd56a44858..0000000000 --- a/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountSummaries.h +++ /dev/null @@ -1,518 +0,0 @@ -//=== RetainCountSummaries.h - Checks for leaks and other issues -*- C++ -*--// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines summaries implementation for RetainCountChecker, which -// implements a reference count checker for Core Foundation and Cocoa -// on (Mac OS X). -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_LIB_STATICANALYZER_CHECKERS_RETAINCOUNTCHECKER_SUMMARY_H -#define LLVM_CLANG_LIB_STATICANALYZER_CHECKERS_RETAINCOUNTCHECKER_SUMMARY_H - -#include "../ClangSACheckers.h" -#include "../AllocationDiagnostics.h" -#include "../SelectorExtras.h" -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/FoldingSet.h" -#include "clang/Analysis/ObjCRetainCount.h" -#include "clang/AST/Attr.h" -#include "clang/AST/DeclCXX.h" -#include "clang/AST/DeclObjC.h" -#include "clang/AST/ParentMap.h" -#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" -#include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h" -#include "clang/StaticAnalyzer/Core/Checker.h" -#include "clang/StaticAnalyzer/Core/CheckerManager.h" -#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h" -#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" -#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h" -#include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h" -#include "llvm/ADT/ImmutableList.h" -#include "llvm/ADT/ImmutableMap.h" -#include "llvm/ADT/STLExtras.h" - -//===----------------------------------------------------------------------===// -// Adapters for FoldingSet. -//===----------------------------------------------------------------------===// - -using namespace clang; -using namespace ento; -using namespace objc_retain; - -namespace clang { -namespace ento { -namespace retaincountchecker { - -/// 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 retaincountchecker -} // end namespace ento -} // end namespace clang - -namespace llvm { -using namespace retaincountchecker; - -template <> struct FoldingSetTrait<ArgEffect> { -static inline void Profile(const ArgEffect X, FoldingSetNodeID &ID) { - ID.AddInteger((unsigned) X); -} -}; -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 { -namespace retaincountchecker { - -/// 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; - - /// 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) - : Args(A), DefaultArgEffect(defaultEff), Receiver(ReceiverEff), 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; } - - /// 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 && 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(Ret); - } - - /// A retain summary is simple if it has no ArgEffects other than the default. - bool isSimple() const { - return Args.isEmpty(); - } - -private: - ArgEffects getArgEffects() const { return Args; } - ArgEffect getDefaultArgEffect() const { return DefaultArgEffect; } - - friend class RetainSummaryManager; - friend class RetainCountChecker; -}; - -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 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; - - /// 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; - - /// ScratchArgs - A holding buffer for construct ArgEffects. - ArgEffects ScratchArgs; - - /// 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; - - /// getArgEffects - Returns a persistent ArgEffects object based on the - /// data in ScratchArgs. - ArgEffects getArgEffects(); - - enum UnaryFuncKind { cfretain, cfrelease, cfautorelease, cfmakecollectable }; - - const RetainSummary *getUnarySummary(const FunctionType* FT, - UnaryFuncKind func); - - 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, - ArgEffect ReceiverEff = DoNothing, - ArgEffect DefaultEff = MayEscape) { - RetainSummary Summ(getArgEffects(), RetEff, DefaultEff, ReceiverEff); - return getPersistentSummary(Summ); - } - - const RetainSummary *getDoNothingSummary() { - return getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, DoNothing); - } - - const RetainSummary *getDefaultSummary() { - return getPersistentSummary(RetEffect::MakeNoRet(), - DoNothing, MayEscape); - } - - const RetainSummary *getPersistentStopSummary() { - return getPersistentSummary(RetEffect::MakeNoRet(), - StopTracking, 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...); - } - -public: - RetainSummaryManager(ASTContext &ctx, bool usesARC) - : Ctx(ctx), - ARCEnabled(usesARC), - AF(BPAlloc), ScratchArgs(AF.getEmptyMap()), - ObjCAllocRetE(usesARC ? RetEffect::MakeNotOwned(RetEffect::ObjC) - : RetEffect::MakeOwned(RetEffect::ObjC)), - ObjCInitRetE(usesARC ? RetEffect::MakeNotOwned(RetEffect::ObjC) - : RetEffect::MakeOwnedWhenTrackedReceiver()) { - InitializeClassMethodSummaries(); - InitializeMethodSummaries(); - } - - bool canEval(const CallExpr *CE, - const FunctionDecl *FD, - bool &hasTrustedImplementationAnnotation); - - bool isTrustedReferenceCountImplementation(const FunctionDecl *FD); - - const RetainSummary *getSummary(const CallEvent &Call, - ProgramStateRef State = nullptr); - - 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 ObjCMethodCall &M, - ProgramStateRef State); - - const RetainSummary *getClassMethodSummary(const ObjCMethodCall &M) { - assert(!M.isInstanceMessage()); - const ObjCInterfaceDecl *Class = M.getReceiverInterface(); - - return getMethodSummary(M.getSelector(), Class, M.getDecl(), - M.getResultType(), ObjCClassMethodSummaries); - } - - /// getMethodSummary - This version of getMethodSummary is used to query - /// the summary for the current method being analyzed. - const RetainSummary *getMethodSummary(const ObjCMethodDecl *MD) { - const ObjCInterfaceDecl *ID = MD->getClassInterface(); - Selector S = MD->getSelector(); - QualType ResultTy = MD->getReturnType(); - - ObjCMethodSummariesTy *CachedSummaries; - if (MD->isInstanceMethod()) - CachedSummaries = &ObjCMethodSummaries; - else - CachedSummaries = &ObjCClassMethodSummaries; - - return getMethodSummary(S, ID, MD, ResultTy, *CachedSummaries); - } - - 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); - - void updateSummaryForCall(const RetainSummary *&Summ, - const CallEvent &Call); - - bool isARCEnabled() const { return ARCEnabled; } - - RetEffect getObjAllocRetEffect() const { return ObjCAllocRetE; } - -private: - const RetainSummary * generateSummary(const FunctionDecl *FD, - bool &AllowAnnotations); - - 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 retaincountchecker -} // end namespace ento -} // end namespace clang - -#endif diff --git a/lib/StaticAnalyzer/Checkers/SelectorExtras.h b/lib/StaticAnalyzer/Checkers/SelectorExtras.h deleted file mode 100644 index b11d070c62..0000000000 --- a/lib/StaticAnalyzer/Checkers/SelectorExtras.h +++ /dev/null @@ -1,46 +0,0 @@ -//=== SelectorExtras.h - Helpers for checkers using selectors -----*- C++ -*-=// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_LIB_STATICANALYZER_CHECKERS_SELECTOREXTRAS_H -#define LLVM_CLANG_LIB_STATICANALYZER_CHECKERS_SELECTOREXTRAS_H - -#include "clang/AST/ASTContext.h" - -namespace clang { -namespace ento { - -template <typename... IdentifierInfos> -static inline Selector getKeywordSelector(ASTContext &Ctx, - IdentifierInfos *... IIs) { - static_assert(sizeof...(IdentifierInfos), - "keyword selectors must have at least one argument"); - SmallVector<IdentifierInfo *, 10> II({&Ctx.Idents.get(IIs)...}); - - return Ctx.Selectors.getSelector(II.size(), &II[0]); -} - -template <typename... IdentifierInfos> -static inline void lazyInitKeywordSelector(Selector &Sel, ASTContext &Ctx, - IdentifierInfos *... IIs) { - if (!Sel.isNull()) - return; - Sel = getKeywordSelector(Ctx, IIs...); -} - -static inline void lazyInitNullarySelector(Selector &Sel, ASTContext &Ctx, - const char *Name) { - if (!Sel.isNull()) - return; - Sel = GetNullarySelector(Name, Ctx); -} - -} // end namespace ento -} // end namespace clang - -#endif diff --git a/lib/StaticAnalyzer/Checkers/TrustNonnullChecker.cpp b/lib/StaticAnalyzer/Checkers/TrustNonnullChecker.cpp index f42c78a769..eed1efd10e 100644 --- a/lib/StaticAnalyzer/Checkers/TrustNonnullChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/TrustNonnullChecker.cpp @@ -20,7 +20,7 @@ //===----------------------------------------------------------------------===// #include "ClangSACheckers.h" -#include "SelectorExtras.h" +#include "clang/Analysis/SelectorExtras.h" #include "clang/StaticAnalyzer/Core/Checker.h" #include "clang/StaticAnalyzer/Core/CheckerManager.h" #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" diff --git a/lib/StaticAnalyzer/Core/CMakeLists.txt b/lib/StaticAnalyzer/Core/CMakeLists.txt index de994b598e..86f2abf8b2 100644 --- a/lib/StaticAnalyzer/Core/CMakeLists.txt +++ b/lib/StaticAnalyzer/Core/CMakeLists.txt @@ -44,6 +44,7 @@ add_clang_library(clangStaticAnalyzerCore RangeConstraintManager.cpp RangedConstraintManager.cpp RegionStore.cpp + RetainSummaryManager.cpp SValBuilder.cpp SVals.cpp SimpleConstraintManager.cpp diff --git a/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountSummaries.cpp b/lib/StaticAnalyzer/Core/RetainSummaryManager.cpp index 18813741f2..a2e716f56f 100644 --- a/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountSummaries.cpp +++ b/lib/StaticAnalyzer/Core/RetainSummaryManager.cpp @@ -1,4 +1,4 @@ -//== RetainCountSummaries.cpp - Checks for leaks and other issues -*- C++ -*--// +//== RetainSummaryManager.cpp - Summaries for reference counting --*- C++ -*--// // // The LLVM Compiler Infrastructure // @@ -7,25 +7,21 @@ // //===----------------------------------------------------------------------===// // -// This file defines summaries implementation for RetainCountChecker, which +// This file defines summaries implementation for retain counting, which // implements a reference count checker for Core Foundation and Cocoa // on (Mac OS X). // //===----------------------------------------------------------------------===// -#include "RetainCountSummaries.h" -#include "RetainCountChecker.h" - +#include "clang/StaticAnalyzer/Core/RetainSummaryManager.h" #include "clang/Analysis/DomainSpecific/CocoaConventions.h" #include "clang/AST/Attr.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/ParentMap.h" -using namespace objc_retain; using namespace clang; using namespace ento; -using namespace retaincountchecker; ArgEffects RetainSummaryManager::getArgEffects() { ArgEffects AE = ScratchArgs; @@ -408,7 +404,7 @@ void RetainSummaryManager::updateSummaryForCall(const RetainSummary *&S, const RetainSummary * RetainSummaryManager::getSummary(const CallEvent &Call, - ProgramStateRef State) { + QualType ReceiverType) { const RetainSummary *Summ; switch (Call.getKind()) { case CE_Function: @@ -425,7 +421,7 @@ RetainSummaryManager::getSummary(const CallEvent &Call, case CE_ObjCMessage: { const ObjCMethodCall &Msg = cast<ObjCMethodCall>(Call); if (Msg.isInstanceMessage()) - Summ = getInstanceMethodSummary(Msg, State); + Summ = getInstanceMethodSummary(Msg, ReceiverType); else Summ = getClassMethodSummary(Msg); break; @@ -739,22 +735,15 @@ RetainSummaryManager::getStandardMethodSummary(const ObjCMethodDecl *MD, return getPersistentSummary(ResultEff, ReceiverEff, MayEscape); } -const RetainSummary * -RetainSummaryManager::getInstanceMethodSummary(const ObjCMethodCall &Msg, - ProgramStateRef State) { +const RetainSummary *RetainSummaryManager::getInstanceMethodSummary( + const ObjCMethodCall &Msg, QualType ReceiverType) { const ObjCInterfaceDecl *ReceiverClass = nullptr; // We do better tracking of the type of the object than the core ExprEngine. // See if we have its type in our private state. - // FIXME: Eventually replace the use of state->get<RefBindings> with - // a generic API for reasoning about the Objective-C types of symbolic - // objects. - SVal ReceiverV = Msg.getReceiverSVal(); - if (SymbolRef Sym = ReceiverV.getAsLocSymbol()) - if (const RefVal *T = getRefBinding(State, Sym)) - if (const ObjCObjectPointerType *PT = - T->getType()->getAs<ObjCObjectPointerType>()) - ReceiverClass = PT->getInterfaceDecl(); + if (!ReceiverType.isNull()) + if (const auto *PT = ReceiverType->getAs<ObjCObjectPointerType>()) + ReceiverClass = PT->getInterfaceDecl(); // If we don't know what kind of object this is, fall back to its static type. if (!ReceiverClass) @@ -884,3 +873,30 @@ void RetainSummaryManager::InitializeMethodSummaries() { "format", "colorSpace"); addInstMethSummary("CIContext", CFAllocSumm, "createCGLayerWithSize", "info"); } + +CallEffects CallEffects::getEffect(const ObjCMethodDecl *MD) { + ASTContext &Ctx = MD->getASTContext(); + LangOptions L = Ctx.getLangOpts(); + RetainSummaryManager M(Ctx, L.ObjCAutoRefCount); + const RetainSummary *S = M.getMethodSummary(MD); + CallEffects CE(S->getRetEffect()); + CE.Receiver = S->getReceiverEffect(); + unsigned N = MD->param_size(); + for (unsigned i = 0; i < N; ++i) { + CE.Args.push_back(S->getArg(i)); + } + return CE; +} + +CallEffects CallEffects::getEffect(const FunctionDecl *FD) { + ASTContext &Ctx = FD->getASTContext(); + LangOptions L = Ctx.getLangOpts(); + RetainSummaryManager M(Ctx, L.ObjCAutoRefCount); + const RetainSummary *S = M.getFunctionSummary(FD); + CallEffects CE(S->getRetEffect()); + unsigned N = FD->param_size(); + for (unsigned i = 0; i < N; ++i) { + CE.Args.push_back(S->getArg(i)); + } + return CE; +} |