[analyzer] [NFC] Split up RetainSummaryManager from RetainCountChecker

ARCMigrator is using code from RetainCountChecker, which is a layering
violation (and it also does it badly, by using a different header, and
then relying on implementation being present in a header file).

This change splits up RetainSummaryManager into a separate library in
lib/Analysis, which can be used independently of a checker.

Differential Revision: https://reviews.llvm.org/D50934

llvm-svn: 340114
This commit is contained in:
George Karpenkov 2018-08-18 01:45:50 +00:00
parent 5b4f8e10b5
commit 0ac54fad53
14 changed files with 270 additions and 335 deletions

View File

@ -1,231 +0,0 @@
//==-- ObjCRetainCount.h - Retain count summaries for Cocoa -------*- 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 the core data structures for retain count "summaries"
// for Objective-C and Core Foundation APIs. These summaries are used
// by the static analyzer to summarize the retain/release effects of
// function and method calls. This drives a path-sensitive typestate
// analysis in the static analyzer, but can also potentially be used by
// other clients.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_STATICANALYZER_CHECKERS_OBJCRETAINCOUNT_H
#define LLVM_CLANG_STATICANALYZER_CHECKERS_OBJCRETAINCOUNT_H
#include "clang/Basic/LLVM.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/SmallVector.h"
namespace clang {
class FunctionDecl;
class ObjCMethodDecl;
namespace ento { namespace objc_retain {
/// An ArgEffect summarizes the retain count behavior on an argument or receiver
/// to a function or method.
enum ArgEffect {
/// 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 an -dealloc message had been sent to
/// the referenced object.
Dealloc,
/// The argument has its reference count decreased by 1. This is as
/// if CFRelease has been called on the argument.
DecRef,
/// The argument has its reference count decreased by 1. This is as
/// if a -release message has been sent to the argument. This differs
/// in behavior from DecRef when GC is enabled.
DecRefMsg,
/// 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. This is as
/// if a -retain message has been sent to the argument. This differs
/// in behavior from IncRef when GC is enabled.
IncRefMsg,
/// The argument has its reference count increased by 1. This is as
/// if CFRetain has been called on the argument.
IncRef,
/// Used to mark an argument as collectible in GC mode, currently a noop.
MakeCollectable,
/// The argument is a pointer to a retain-counted object; on exit, the new
/// value of the pointer is a +0 value or NULL.
UnretainedOutParameter,
/// The argument is a pointer to a retain-counted object; on exit, the new
/// value of the pointer is a +1 value or NULL.
RetainedOutParameter,
/// 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,
/// Performs the combined functionality of DecRefMsg 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.
DecRefMsgAndStopTrackingHard
};
/// 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 object is not owned and controlled by the
/// Garbage collector.
GCNotOwnedSymbol,
/// 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 presise than the summary indirectly produced
// by inlining the function
NoRetHard
};
/// Determines the object kind of a tracked object.
enum ObjKind {
/// Indicates that the tracked object is a CF object. This is
/// important between GC and non-GC code.
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
};
private:
Kind K;
ObjKind O;
RetEffect(Kind k, ObjKind o = 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, ObjC);
}
static RetEffect MakeOwned(ObjKind o) {
return RetEffect(OwnedSymbol, o);
}
static RetEffect MakeNotOwned(ObjKind o) {
return RetEffect(NotOwnedSymbol, o);
}
static RetEffect MakeGCNotOwned() {
return RetEffect(GCNotOwnedSymbol, ObjC);
}
static RetEffect MakeNoRet() {
return RetEffect(NoRet);
}
static RetEffect MakeNoRetHard() {
return RetEffect(NoRetHard);
}
};
/// Encapsulates the retain count semantics on the arguments, return value,
/// and receiver (if any) of a function/method call.
///
/// Note that construction of these objects is not highly efficient. That
/// is okay for clients where creating these objects isn't really a bottleneck.
/// The purpose of the API is to provide something simple. The actual
/// static analyzer checker that implements retain/release typestate
/// tracking uses something more efficient.
class CallEffects {
llvm::SmallVector<ArgEffect, 10> Args;
RetEffect Ret;
ArgEffect Receiver;
CallEffects(const RetEffect &R) : Ret(R) {}
public:
/// Returns the argument effects for a call.
ArrayRef<ArgEffect> getArgs() const { return Args; }
/// Returns the effects on the receiver.
ArgEffect getReceiver() const { return Receiver; }
/// Returns the effect on the return value.
RetEffect getReturnValue() const { return Ret; }
/// Return the CallEfect for a given Objective-C method.
static CallEffects getEffect(const ObjCMethodDecl *MD);
/// Return the CallEfect for a given C/C++ function.
static CallEffects getEffect(const FunctionDecl *FD);
};
}}}
#endif

View File

@ -1,4 +1,4 @@
//=== RetainCountSummaries.h - Checks for leaks and other issues -*- C++ -*--//
//=== RetainSummaryManager.h - Summaries for reference counting ---*- C++ -*--//
//
// The LLVM Compiler Infrastructure
//
@ -7,25 +7,22 @@
//
//===----------------------------------------------------------------------===//
//
// 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).
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_LIB_STATICANALYZER_CHECKERS_RETAINCOUNTCHECKER_SUMMARY_H
#define LLVM_CLANG_LIB_STATICANALYZER_CHECKERS_RETAINCOUNTCHECKER_SUMMARY_H
#ifndef LLVM_CLANG_LIB_ANALYSIS_RETAINSUMMARYMANAGER
#define LLVM_CLANG_LIB_ANALYSIS_RETAINSUMMARYMANAGER
#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/Checkers/SelectorExtras.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
#include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
@ -44,11 +41,206 @@
using namespace clang;
using namespace ento;
using namespace objc_retain;
namespace clang {
namespace ento {
namespace retaincountchecker {
/// An ArgEffect summarizes the retain count behavior on an argument or receiver
/// to a function or method.
enum ArgEffect {
/// 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 an -dealloc message had been sent to
/// the referenced object.
Dealloc,
/// The argument has its reference count decreased by 1. This is as
/// if CFRelease has been called on the argument.
DecRef,
/// The argument has its reference count decreased by 1. This is as
/// if a -release message has been sent to the argument. This differs
/// in behavior from DecRef when GC is enabled.
DecRefMsg,
/// 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. This is as
/// if a -retain message has been sent to the argument. This differs
/// in behavior from IncRef when GC is enabled.
IncRefMsg,
/// The argument has its reference count increased by 1. This is as
/// if CFRetain has been called on the argument.
IncRef,
/// The argument acts as if has been passed to CFMakeCollectable, which
/// transfers the object to the Garbage Collector under GC.
MakeCollectable,
/// The argument is a pointer to a retain-counted object; on exit, the new
/// value of the pointer is a +0 value or NULL.
UnretainedOutParameter,
/// The argument is a pointer to a retain-counted object; on exit, the new
/// value of the pointer is a +1 value or NULL.
RetainedOutParameter,
/// 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,
/// Performs the combined functionality of DecRefMsg 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.
DecRefMsgAndStopTrackingHard
};
/// 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 object is not owned and controlled by the
/// Garbage collector.
GCNotOwnedSymbol,
/// 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 presise than the summary indirectly produced
// by inlining the function
NoRetHard
};
/// Determines the object kind of a tracked object.
enum ObjKind {
/// Indicates that the tracked object is a CF object. This is
/// important between GC and non-GC code.
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
};
private:
Kind K;
ObjKind O;
RetEffect(Kind k, ObjKind o = 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, ObjC);
}
static RetEffect MakeOwned(ObjKind o) {
return RetEffect(OwnedSymbol, o);
}
static RetEffect MakeNotOwned(ObjKind o) {
return RetEffect(NotOwnedSymbol, o);
}
static RetEffect MakeGCNotOwned() {
return RetEffect(GCNotOwnedSymbol, ObjC);
}
static RetEffect MakeNoRet() {
return RetEffect(NoRet);
}
static RetEffect MakeNoRetHard() {
return RetEffect(NoRetHard);
}
};
/// Encapsulates the retain count semantics on the arguments, return value,
/// and receiver (if any) of a function/method call.
///
/// Note that construction of these objects is not highly efficient. That
/// is okay for clients where creating these objects isn't really a bottleneck.
/// The purpose of the API is to provide something simple. The actual
/// static analyzer checker that implements retain/release typestate
/// tracking uses something more efficient.
class CallEffects {
llvm::SmallVector<ArgEffect, 10> Args;
RetEffect Ret;
ArgEffect Receiver;
CallEffects(const RetEffect &R) : Ret(R) {}
public:
/// Returns the argument effects for a call.
ArrayRef<ArgEffect> getArgs() const { return Args; }
/// Returns the effects on the receiver.
ArgEffect getReceiver() const { return Receiver; }
/// Returns the effect on the return value.
RetEffect getReturnValue() const { return Ret; }
/// Return the CallEfect for a given Objective-C method.
static CallEffects getEffect(const ObjCMethodDecl *MD);
/// Return the CallEfect for a given C/C++ function.
static CallEffects getEffect(const FunctionDecl *FD);
};
/// A key identifying a summary.
class ObjCSummaryKey {
@ -68,12 +260,10 @@ public:
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) {
@ -116,7 +306,6 @@ template <> struct DenseMapInfo<ObjCSummaryKey> {
namespace clang {
namespace ento {
namespace retaincountchecker {
/// ArgEffects summarizes the effects of a function/method call on all of
/// its arguments.
@ -199,12 +388,12 @@ public:
return Args.isEmpty();
}
private:
ArgEffects getArgEffects() const { return Args; }
private:
ArgEffect getDefaultArgEffect() const { return DefaultArgEffect; }
friend class RetainSummaryManager;
friend class RetainCountChecker;
};
class ObjCSummaryCache {
@ -399,6 +588,9 @@ class RetainSummaryManager {
addMethodSummary(II, ObjCClassMethodSummaries, Summ, Kws...);
}
const RetainSummary * generateSummary(const FunctionDecl *FD,
bool &AllowAnnotations);
public:
RetainSummaryManager(ASTContext &ctx, bool usesARC)
: Ctx(ctx),
@ -419,7 +611,7 @@ public:
bool isTrustedReferenceCountImplementation(const FunctionDecl *FD);
const RetainSummary *getSummary(const CallEvent &Call,
ProgramStateRef State = nullptr);
QualType ReceiverType=QualType());
const RetainSummary *getFunctionSummary(const FunctionDecl *FD);
@ -428,8 +620,9 @@ public:
QualType RetTy,
ObjCMethodSummariesTy &CachedSummaries);
const RetainSummary *getInstanceMethodSummary(const ObjCMethodCall &M,
ProgramStateRef State);
const RetainSummary *
getInstanceMethodSummary(const ObjCMethodCall &M,
QualType ReceiverType);
const RetainSummary *getClassMethodSummary(const ObjCMethodCall &M) {
assert(!M.isInstanceMessage());
@ -475,10 +668,6 @@ public:
RetEffect getObjAllocRetEffect() const { return ObjCAllocRetE; }
private:
const RetainSummary * generateSummary(const FunctionDecl *FD,
bool &AllowAnnotations);
friend class RetainSummaryTemplate;
};
@ -511,7 +700,6 @@ public:
}
};
} // end namespace retaincountchecker
} // end namespace ento
} // end namespace clang

View File

@ -33,13 +33,6 @@ static inline void lazyInitKeywordSelector(Selector &Sel, ASTContext &Ctx,
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

View File

@ -34,5 +34,4 @@ add_clang_library(clangARCMigrate
clangRewrite
clangSema
clangSerialization
clangStaticAnalyzerCheckers
)

View File

@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
#include "Transforms.h"
#include "clang/Analysis/ObjCRetainCount.h"
#include "clang/Analysis/RetainSummaryManager.h"
#include "clang/ARCMigrate/ARCMT.h"
#include "clang/ARCMigrate/ARCMTActions.h"
#include "clang/AST/ASTConsumer.h"
@ -35,8 +35,8 @@
#include "llvm/Support/YAMLParser.h"
using namespace clang;
using namespace ento;
using namespace arcmt;
using namespace ento::objc_retain;
namespace {

View File

@ -24,6 +24,7 @@ add_clang_library(clangAnalysis
ProgramPoint.cpp
PseudoConstantAnalysis.cpp
ReachableCode.cpp
RetainSummaryManager.cpp
ScanfFormatString.cpp
ThreadSafety.cpp
ThreadSafetyCommon.cpp

View File

@ -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/Analysis/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;
}

View File

@ -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/StaticAnalyzer/Checkers/SelectorExtras.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"

View File

@ -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

View File

@ -13,8 +13,8 @@
//===----------------------------------------------------------------------===//
#include "ClangSACheckers.h"
#include "SelectorExtras.h"
#include "clang/AST/Attr.h"
#include "clang/StaticAnalyzer/Checkers/SelectorExtras.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"

View File

@ -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);
@ -1387,45 +1398,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.
//===----------------------------------------------------------------------===//

View File

@ -17,17 +17,16 @@
#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"
#include "clang/AST/ParentMap.h"
#include "clang/Analysis/DomainSpecific/CocoaConventions.h"
#include "clang/Analysis/RetainSummaryManager.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/SourceManager.h"
#include "clang/StaticAnalyzer/Checkers/SelectorExtras.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
#include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
@ -46,7 +45,6 @@
#include <cstdarg>
#include <utility>
using namespace objc_retain;
using llvm::StrInStrNoCase;
namespace clang {

View File

@ -15,7 +15,7 @@
#ifndef LLVM_CLANG_LIB_STATICANALYZER_CHECKERS_RETAINCOUNTCHECKER_DIAGNOSTICS_H
#define LLVM_CLANG_LIB_STATICANALYZER_CHECKERS_RETAINCOUNTCHECKER_DIAGNOSTICS_H
#include "RetainCountSummaries.h"
#include "clang/Analysis/RetainSummaryManager.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h"
#include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h"

View File

@ -20,7 +20,7 @@
//===----------------------------------------------------------------------===//
#include "ClangSACheckers.h"
#include "SelectorExtras.h"
#include "clang/StaticAnalyzer/Checkers/SelectorExtras.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"