Skip to content

Commit

Permalink
[analyzer] Move out tracking retain count for OSObjects into a separa…
Browse files Browse the repository at this point in the history
…te checker

Allow enabling and disabling tracking of ObjC/CF objects
separately from tracking of OS objects.

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

llvm-svn: 348638
  • Loading branch information
George Karpenkov committed Dec 7, 2018
1 parent 936a9c9 commit 27db330
Show file tree
Hide file tree
Showing 7 changed files with 225 additions and 88 deletions.
3 changes: 3 additions & 0 deletions clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
Expand Up @@ -520,6 +520,9 @@ def MacOSKeychainAPIChecker : Checker<"SecKeychainAPI">,
def ObjCPropertyChecker : Checker<"ObjCProperty">,
HelpText<"Check for proper uses of Objective-C properties">;

def OSObjectRetainCountChecker : Checker<"OSObjectRetainCount">,
HelpText<"Check for leaks and improper reference count management for OSObject">;

} // end "osx"

let ParentPackage = Cocoa in {
Expand Down
47 changes: 44 additions & 3 deletions clang/include/clang/StaticAnalyzer/Core/RetainSummaryManager.h
Expand Up @@ -469,6 +469,8 @@ class ObjCSummaryCache {
}
};

class RetainSummaryTemplate;

class RetainSummaryManager {
typedef llvm::DenseMap<const FunctionDecl*, const RetainSummary *>
FuncSummariesTy;
Expand All @@ -483,7 +485,10 @@ class RetainSummaryManager {
/// Records whether or not the analyzed code runs in ARC mode.
const bool ARCEnabled;

/// Track sublcasses of OSObject
/// Track Objective-C and CoreFoundation objects.
const bool TrackObjCAndCFObjects;

/// Track sublcasses of OSObject.
const bool TrackOSObjects;

/// FuncSummaries - A map from FunctionDecls to summaries.
Expand Down Expand Up @@ -626,13 +631,36 @@ class RetainSummaryManager {
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 {@code pd} in function {@code FD}
/// to the resulting summary stored in out-parameter {@code Template}.
/// \return whether an annotation was applied.
bool applyFunctionParamAnnotationEffect(const ParmVarDecl *pd,
unsigned parm_idx,
const FunctionDecl *FD,
ArgEffects::Factory &AF,
RetainSummaryTemplate &Template);

public:
RetainSummaryManager(ASTContext &ctx,
bool usesARC,
bool trackOSObject)
bool trackObjCAndCFObjects,
bool trackOSObjects)
: Ctx(ctx),
ARCEnabled(usesARC),
TrackOSObjects(trackOSObject),
TrackObjCAndCFObjects(trackObjCAndCFObjects),
TrackOSObjects(trackOSObjects),
AF(BPAlloc), ScratchArgs(AF.getEmptyMap()),
ObjCAllocRetE(usesARC ? RetEffect::MakeNotOwned(RetEffect::ObjC)
: RetEffect::MakeOwned(RetEffect::ObjC)),
Expand Down Expand Up @@ -709,16 +737,29 @@ class RetainSummaryManager {
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; }

/// \return True if the declaration has an attribute {@code T},
/// AND we are tracking that attribute. False otherwise.
template <class T>
bool hasEnabledAttr(const Decl *D) {
return isAttrEnabled<T>() && D->hasAttr<T>();
}

/// Check whether we are tracking properties specified by the attributes.
template <class T>
bool isAttrEnabled();

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
Expand Down
Expand Up @@ -1504,9 +1504,10 @@ void RetainCountChecker::printState(raw_ostream &Out, ProgramStateRef State,

void ento::registerRetainCountChecker(CheckerManager &Mgr) {
auto *Chk = Mgr.registerChecker<RetainCountChecker>();
Chk->TrackObjCAndCFObjects = true;
}

AnalyzerOptions &Options = Mgr.getAnalyzerOptions();

Chk->ShouldCheckOSObjectRetainCount = Options.getCheckerBooleanOption(
"CheckOSObject", true, Chk);
void ento::registerOSObjectRetainCountChecker(CheckerManager &Mgr) {
auto *Chk = Mgr.registerChecker<RetainCountChecker>();
Chk->TrackOSObjects = true;
}
Expand Up @@ -92,7 +92,7 @@ class RefVal {
/// See the RefVal::Kind enum for possible values.
unsigned RawKind : 5;

/// The kind of object being tracked (CF or ObjC), if known.
/// The kind of object being tracked (CF or ObjC or OSObject), if known.
///
/// See the RetEffect::ObjKind enum for possible values.
unsigned RawObjectKind : 3;
Expand Down Expand Up @@ -268,10 +268,12 @@ class RetainCountChecker
mutable bool ShouldResetSummaryLog;

public:
/// Optional setting to indicate if leak reports should include
/// the allocation line.
bool IncludeAllocationLine;
bool ShouldCheckOSObjectRetainCount;

/// Track Objective-C and CoreFoundation objects.
bool TrackObjCAndCFObjects = false;

/// Track sublcasses of OSObject.
bool TrackOSObjects = false;

RetainCountChecker() : ShouldResetSummaryLog(false) {}

Expand All @@ -290,7 +292,7 @@ class RetainCountChecker
bool ARCEnabled = (bool)Ctx.getLangOpts().ObjCAutoRefCount;
if (!Summaries) {
Summaries.reset(new RetainSummaryManager(
Ctx, ARCEnabled, ShouldCheckOSObjectRetainCount));
Ctx, ARCEnabled, TrackObjCAndCFObjects, TrackOSObjects));
} else {
assert(Summaries->isARCEnabled() == ARCEnabled);
}
Expand Down

0 comments on commit 27db330

Please sign in to comment.