[analyzer][RetainCount] Tie diagnostics to osx.cocoa.RetainCount rather then RetainCountBase, for the most part

Similarly to other patches of mine, I'm trying to uniformize the checker
interface so that dependency checkers don't emit diagnostics. The checker that
made me most anxious so far was definitely RetainCount, because it is definitely
impacted by backward compatibility concerns, and implements a checker hierarchy
that is a lot different to other examples of similar size. Also, I don't have
authority, nor expertise regarding ObjC related code, so I welcome any
objection/discussion!

Differential Revision: https://reviews.llvm.org/D78099
This commit is contained in:
Kirstóf Umann 2020-04-13 20:51:27 +02:00
parent 9eacda51fa
commit 5192783bb2
15 changed files with 591 additions and 564 deletions

View File

@ -12,12 +12,12 @@
//===----------------------------------------------------------------------===//
#include "RetainCountChecker.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
using namespace clang;
using namespace ento;
using namespace retaincountchecker;
using llvm::StrInStrNoCase;
REGISTER_MAP_WITH_PROGRAMSTATE(RefBindings, SymbolRef, RefVal)
@ -701,7 +701,7 @@ void RetainCountChecker::checkSummary(const RetainSummary &Summ,
for (ProgramStateRef St : Out) {
if (DeallocSent) {
C.addTransition(St, C.getPredecessor(), &DeallocSentTag);
C.addTransition(St, C.getPredecessor(), &getDeallocSentTag());
} else {
C.addTransition(St);
}
@ -844,13 +844,13 @@ RetainCountChecker::errorKindToBugKind(RefVal::Kind ErrorKind,
SymbolRef Sym) const {
switch (ErrorKind) {
case RefVal::ErrorUseAfterRelease:
return useAfterRelease;
return *UseAfterRelease;
case RefVal::ErrorReleaseNotOwned:
return releaseNotOwned;
return *ReleaseNotOwned;
case RefVal::ErrorDeallocNotOwned:
if (Sym->getType()->getPointeeCXXRecordDecl())
return freeNotOwned;
return deallocNotOwned;
return *FreeNotOwned;
return *DeallocNotOwned;
default:
llvm_unreachable("Unhandled error.");
}
@ -946,7 +946,7 @@ bool RetainCountChecker::evalCall(const CallEvent &Call,
// Assume that output is zero on the other branch.
NullOutputState = NullOutputState->BindExpr(
CE, LCtx, C.getSValBuilder().makeNull(), /*Invalidate=*/false);
C.addTransition(NullOutputState, &CastFailTag);
C.addTransition(NullOutputState, &getCastFailTag());
// And on the original branch assume that both input and
// output are non-zero.
@ -1095,7 +1095,7 @@ ExplodedNode * RetainCountChecker::checkReturnWithRetEffect(const ReturnStmt *S,
if (N) {
const LangOptions &LOpts = C.getASTContext().getLangOpts();
auto R =
std::make_unique<RefLeakReport>(leakAtReturn, LOpts, N, Sym, C);
std::make_unique<RefLeakReport>(*LeakAtReturn, LOpts, N, Sym, C);
C.emitReport(std::move(R));
}
return N;
@ -1120,7 +1120,7 @@ ExplodedNode * RetainCountChecker::checkReturnWithRetEffect(const ReturnStmt *S,
ExplodedNode *N = C.addTransition(state, Pred, &ReturnNotOwnedTag);
if (N) {
auto R = std::make_unique<RefCountReport>(
returnNotOwnedForOwned, C.getASTContext().getLangOpts(), N, Sym);
*ReturnNotOwnedForOwned, C.getASTContext().getLangOpts(), N, Sym);
C.emitReport(std::move(R));
}
return N;
@ -1273,8 +1273,8 @@ RetainCountChecker::handleAutoreleaseCounts(ProgramStateRef state,
os << "has a +" << V.getCount() << " retain count";
const LangOptions &LOpts = Ctx.getASTContext().getLangOpts();
auto R = std::make_unique<RefCountReport>(overAutorelease, LOpts, N, Sym,
os.str());
auto R = std::make_unique<RefCountReport>(*OverAutorelease, LOpts, N, Sym,
os.str());
Ctx.emitReport(std::move(R));
}
@ -1320,7 +1320,7 @@ RetainCountChecker::processLeaks(ProgramStateRef state,
if (N) {
for (SymbolRef L : Leaked) {
const RefCountBug &BT = Pred ? leakWithinFunction : leakAtReturn;
const RefCountBug &BT = Pred ? *LeakWithinFunction : *LeakAtReturn;
Ctx.emitReport(std::make_unique<RefLeakReport>(BT, LOpts, N, L, Ctx));
}
}
@ -1473,19 +1473,39 @@ void RetainCountChecker::printState(raw_ostream &Out, ProgramStateRef State,
// Checker registration.
//===----------------------------------------------------------------------===//
std::unique_ptr<CheckerProgramPointTag> RetainCountChecker::DeallocSentTag;
std::unique_ptr<CheckerProgramPointTag> RetainCountChecker::CastFailTag;
void ento::registerRetainCountBase(CheckerManager &Mgr) {
Mgr.registerChecker<RetainCountChecker>();
auto *Chk = Mgr.registerChecker<RetainCountChecker>();
Chk->DeallocSentTag =
std::make_unique<CheckerProgramPointTag>(Chk, "DeallocSent");
Chk->CastFailTag =
std::make_unique<CheckerProgramPointTag>(Chk, "DynamicCastFail");
}
bool ento::shouldRegisterRetainCountBase(const CheckerManager &mgr) {
return true;
}
void ento::registerRetainCountChecker(CheckerManager &Mgr) {
auto *Chk = Mgr.getChecker<RetainCountChecker>();
Chk->TrackObjCAndCFObjects = true;
Chk->TrackNSCFStartParam = Mgr.getAnalyzerOptions().getCheckerBooleanOption(
Mgr.getCurrentCheckerName(), "TrackNSCFStartParam");
#define INIT_BUGTYPE(KIND) \
Chk->KIND = std::make_unique<RefCountBug>(Mgr.getCurrentCheckerName(), \
RefCountBug::KIND);
// TODO: Ideally, we should have a checker for each of these bug types.
INIT_BUGTYPE(UseAfterRelease)
INIT_BUGTYPE(ReleaseNotOwned)
INIT_BUGTYPE(DeallocNotOwned)
INIT_BUGTYPE(FreeNotOwned)
INIT_BUGTYPE(OverAutorelease)
INIT_BUGTYPE(ReturnNotOwnedForOwned)
INIT_BUGTYPE(LeakWithinFunction)
INIT_BUGTYPE(LeakAtReturn)
#undef INIT_BUGTYPE
}
bool ento::shouldRegisterRetainCountChecker(const CheckerManager &mgr) {
@ -1495,6 +1515,29 @@ bool ento::shouldRegisterRetainCountChecker(const CheckerManager &mgr) {
void ento::registerOSObjectRetainCountChecker(CheckerManager &Mgr) {
auto *Chk = Mgr.getChecker<RetainCountChecker>();
Chk->TrackOSObjects = true;
// FIXME: We want bug reports to always have the same checker name associated
// with them, yet here, if RetainCountChecker is disabled but
// OSObjectRetainCountChecker is enabled, the checker names will be different.
// This hack will make it so that the checker name depends on which checker is
// enabled rather than on the registration order.
// For the most part, we want **non-hidden checkers** to be associated with
// diagnostics, and **hidden checker options** with the fine-tuning of
// modeling. Following this logic, OSObjectRetainCountChecker should be the
// latter, but we can't just remove it for backward compatibility reasons.
#define LAZY_INIT_BUGTYPE(KIND) \
if (!Chk->KIND) \
Chk->KIND = std::make_unique<RefCountBug>(Mgr.getCurrentCheckerName(), \
RefCountBug::KIND);
LAZY_INIT_BUGTYPE(UseAfterRelease)
LAZY_INIT_BUGTYPE(ReleaseNotOwned)
LAZY_INIT_BUGTYPE(DeallocNotOwned)
LAZY_INIT_BUGTYPE(FreeNotOwned)
LAZY_INIT_BUGTYPE(OverAutorelease)
LAZY_INIT_BUGTYPE(ReturnNotOwnedForOwned)
LAZY_INIT_BUGTYPE(LeakWithinFunction)
LAZY_INIT_BUGTYPE(LeakAtReturn)
#undef LAZY_INIT_BUGTYPE
}
bool ento::shouldRegisterOSObjectRetainCountChecker(const CheckerManager &mgr) {

View File

@ -251,20 +251,20 @@ class RetainCountChecker
eval::Assume,
eval::Call > {
RefCountBug useAfterRelease{this, RefCountBug::UseAfterRelease};
RefCountBug releaseNotOwned{this, RefCountBug::ReleaseNotOwned};
RefCountBug deallocNotOwned{this, RefCountBug::DeallocNotOwned};
RefCountBug freeNotOwned{this, RefCountBug::FreeNotOwned};
RefCountBug overAutorelease{this, RefCountBug::OverAutorelease};
RefCountBug returnNotOwnedForOwned{this, RefCountBug::ReturnNotOwnedForOwned};
RefCountBug leakWithinFunction{this, RefCountBug::LeakWithinFunction};
RefCountBug leakAtReturn{this, RefCountBug::LeakAtReturn};
CheckerProgramPointTag DeallocSentTag{this, "DeallocSent"};
CheckerProgramPointTag CastFailTag{this, "DynamicCastFail"};
public:
std::unique_ptr<RefCountBug> UseAfterRelease;
std::unique_ptr<RefCountBug> ReleaseNotOwned;
std::unique_ptr<RefCountBug> DeallocNotOwned;
std::unique_ptr<RefCountBug> FreeNotOwned;
std::unique_ptr<RefCountBug> OverAutorelease;
std::unique_ptr<RefCountBug> ReturnNotOwnedForOwned;
std::unique_ptr<RefCountBug> LeakWithinFunction;
std::unique_ptr<RefCountBug> LeakAtReturn;
mutable std::unique_ptr<RetainSummaryManager> Summaries;
public:
static std::unique_ptr<CheckerProgramPointTag> DeallocSentTag;
static std::unique_ptr<CheckerProgramPointTag> CastFailTag;
/// Track Objective-C and CoreFoundation objects.
bool TrackObjCAndCFObjects = false;
@ -360,13 +360,11 @@ public:
CheckerContext &Ctx,
ExplodedNode *Pred = nullptr) const;
const CheckerProgramPointTag &getDeallocSentTag() const {
return DeallocSentTag;
static const CheckerProgramPointTag &getDeallocSentTag() {
return *DeallocSentTag;
}
const CheckerProgramPointTag &getCastFailTag() const {
return CastFailTag;
}
static const CheckerProgramPointTag &getCastFailTag() { return *CastFailTag; }
private:
/// Perform the necessary checks and state adjustments at the end of the

View File

@ -18,7 +18,7 @@ using namespace clang;
using namespace ento;
using namespace retaincountchecker;
StringRef RefCountBug::bugTypeToName(RefCountBug::RefCountBugType BT) {
StringRef RefCountBug::bugTypeToName(RefCountBug::RefCountBugKind BT) {
switch (BT) {
case UseAfterRelease:
return "Use-after-release";
@ -37,7 +37,7 @@ StringRef RefCountBug::bugTypeToName(RefCountBug::RefCountBugType BT) {
case LeakAtReturn:
return "Leak of returned object";
}
llvm_unreachable("Unknown RefCountBugType");
llvm_unreachable("Unknown RefCountBugKind");
}
StringRef RefCountBug::getDescription() const {
@ -60,13 +60,14 @@ StringRef RefCountBug::getDescription() const {
case LeakAtReturn:
return "";
}
llvm_unreachable("Unknown RefCountBugType");
llvm_unreachable("Unknown RefCountBugKind");
}
RefCountBug::RefCountBug(const CheckerBase *Checker, RefCountBugType BT)
RefCountBug::RefCountBug(CheckerNameRef Checker, RefCountBugKind BT)
: BugType(Checker, bugTypeToName(BT), categories::MemoryRefCount,
/*SuppressOnSink=*/BT == LeakWithinFunction || BT == LeakAtReturn),
BT(BT), Checker(Checker) {}
/*SuppressOnSink=*/BT == LeakWithinFunction ||
BT == LeakAtReturn),
BT(BT) {}
static bool isNumericLiteralExpression(const Expr *E) {
// FIXME: This set of cases was copied from SemaExprObjC.
@ -453,8 +454,6 @@ RefCountReportVisitor::VisitNode(const ExplodedNode *N, BugReporterContext &BRC,
PathSensitiveBugReport &BR) {
const auto &BT = static_cast<const RefCountBug&>(BR.getBugType());
const auto *Checker =
static_cast<const RetainCountChecker *>(BT.getChecker());
bool IsFreeUnowned = BT.getBugType() == RefCountBug::FreeNotOwned ||
BT.getBugType() == RefCountBug::DeallocNotOwned;
@ -545,11 +544,11 @@ RefCountReportVisitor::VisitNode(const ExplodedNode *N, BugReporterContext &BRC,
const ProgramPointTag *Tag = N->getLocation().getTag();
if (Tag == &Checker->getCastFailTag()) {
if (Tag == &RetainCountChecker::getCastFailTag()) {
os << "Assuming dynamic cast returns null due to type mismatch";
}
if (Tag == &Checker->getDeallocSentTag()) {
if (Tag == &RetainCountChecker::getDeallocSentTag()) {
// We only have summaries attached to nodes after evaluating CallExpr and
// ObjCMessageExprs.
const Stmt *S = N->getLocation().castAs<StmtPoint>().getStmt();

View File

@ -26,7 +26,7 @@ namespace retaincountchecker {
class RefCountBug : public BugType {
public:
enum RefCountBugType {
enum RefCountBugKind {
UseAfterRelease,
ReleaseNotOwned,
DeallocNotOwned,
@ -36,21 +36,14 @@ public:
LeakWithinFunction,
LeakAtReturn,
};
RefCountBug(const CheckerBase *checker, RefCountBugType BT);
RefCountBug(CheckerNameRef Checker, RefCountBugKind BT);
StringRef getDescription() const;
RefCountBugType getBugType() const {
return BT;
}
const CheckerBase *getChecker() const {
return Checker;
}
RefCountBugKind getBugType() const { return BT; }
private:
RefCountBugType BT;
const CheckerBase *Checker;
static StringRef bugTypeToName(RefCountBugType BT);
RefCountBugKind BT;
static StringRef bugTypeToName(RefCountBugKind BT);
};
class RefCountReport : public PathSensitiveBugReport {

View File

@ -2119,9 +2119,9 @@
<key>description</key><string>Potential leak of an object stored into &apos;value&apos;</string>
<key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
<key>type</key><string>Leak</string>
<key>check_name</key><string>osx.cocoa.RetainCountBase</string>
<key>check_name</key><string>osx.cocoa.RetainCount</string>
<!-- This hash is experimental and going to change! -->
<key>issue_hash_content_of_line_in_context</key><string>b2b15a95787e594ff79f02c600e9d357</string>
<key>issue_hash_content_of_line_in_context</key><string>29a10ca4af622b6146ca082e49d919d6</string>
<key>issue_context_kind</key><string>function</string>
<key>issue_context</key><string>rdar8331641</string>
<key>issue_hash_function_offset</key><string>2</string>
@ -11612,9 +11612,9 @@
<key>description</key><string>Potential leak of an object stored into &apos;foo&apos;</string>
<key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
<key>type</key><string>Leak</string>
<key>check_name</key><string>osx.cocoa.RetainCountBase</string>
<key>check_name</key><string>osx.cocoa.RetainCount</string>
<!-- This hash is experimental and going to change! -->
<key>issue_hash_content_of_line_in_context</key><string>ef342aeb2f2719117ddd4ef1b72f5ba7</string>
<key>issue_hash_content_of_line_in_context</key><string>f533db5cbb9c20d171f9f92105789dc4</string>
<key>issue_context_kind</key><string>Objective-C method</string>
<key>issue_context</key><string>test2</string>
<key>issue_hash_function_offset</key><string>2</string>
@ -21954,9 +21954,9 @@
<key>description</key><string>Potential leak of an object stored into &apos;foo&apos;</string>
<key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
<key>type</key><string>Leak</string>
<key>check_name</key><string>osx.cocoa.RetainCountBase</string>
<key>check_name</key><string>osx.cocoa.RetainCount</string>
<!-- This hash is experimental and going to change! -->
<key>issue_hash_content_of_line_in_context</key><string>f81f51dd154d0a11cab412a1cd1cd095</string>
<key>issue_hash_content_of_line_in_context</key><string>5616a7601faa1a8c2ac56fa1b595b172</string>
<key>issue_context_kind</key><string>function</string>
<key>issue_context</key><string>longLines</string>
<key>issue_hash_function_offset</key><string>1</string>

View File

@ -312,9 +312,9 @@
<key>description</key><string>Potential leak of an object stored into &apos;date&apos;</string>
<key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
<key>type</key><string>Leak</string>
<key>check_name</key><string>osx.cocoa.RetainCountBase</string>
<key>check_name</key><string>osx.cocoa.RetainCount</string>
<!-- This hash is experimental and going to change! -->
<key>issue_hash_content_of_line_in_context</key><string>7bd4a6e187407677b2d9e717576818bf</string>
<key>issue_hash_content_of_line_in_context</key><string>61d185b2522d15fb327f6784e0217adf</string>
<key>issue_context_kind</key><string>function</string>
<key>issue_context</key><string>test_cf_leak</string>
<key>issue_hash_function_offset</key><string>2</string>
@ -843,9 +843,9 @@
<key>description</key><string>Potential leak of an object stored into &apos;obj5&apos;</string>
<key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
<key>type</key><string>Leak</string>
<key>check_name</key><string>osx.cocoa.RetainCountBase</string>
<key>check_name</key><string>osx.cocoa.RetainCount</string>
<!-- This hash is experimental and going to change! -->
<key>issue_hash_content_of_line_in_context</key><string>0aed4f65cb3dba7331f9319fd1ceb003</string>
<key>issue_hash_content_of_line_in_context</key><string>5baa7d5f38420d0a035aa61607675f3e</string>
<key>issue_context_kind</key><string>function</string>
<key>issue_context</key><string>from_cf</string>
<key>issue_hash_function_offset</key><string>7</string>
@ -989,9 +989,9 @@
<key>description</key><string>Potential leak of an object stored into &apos;obj6&apos;</string>
<key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
<key>type</key><string>Leak</string>
<key>check_name</key><string>osx.cocoa.RetainCountBase</string>
<key>check_name</key><string>osx.cocoa.RetainCount</string>
<!-- This hash is experimental and going to change! -->
<key>issue_hash_content_of_line_in_context</key><string>0851961d40a4c8331ebe713f4a3e05f4</string>
<key>issue_hash_content_of_line_in_context</key><string>4665e04694fd55e7c4ed7a67860b3b74</string>
<key>issue_context_kind</key><string>function</string>
<key>issue_context</key><string>from_cf</string>
<key>issue_hash_function_offset</key><string>8</string>
@ -1423,9 +1423,9 @@
<key>description</key><string>Potential leak of an object stored into &apos;date&apos;</string>
<key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
<key>type</key><string>Leak</string>
<key>check_name</key><string>osx.cocoa.RetainCountBase</string>
<key>check_name</key><string>osx.cocoa.RetainCount</string>
<!-- This hash is experimental and going to change! -->
<key>issue_hash_content_of_line_in_context</key><string>00045bff3b7c26fe7cb80a71f512575c</string>
<key>issue_hash_content_of_line_in_context</key><string>798e65f80df0526369f9bb240e3d91fd</string>
<key>issue_context_kind</key><string>function</string>
<key>issue_context</key><string>test_objc_unretainedObject</string>
<key>issue_hash_function_offset</key><string>2</string>
@ -1734,9 +1734,9 @@
<key>description</key><string>Potential leak of an object of type &apos;CFStringRef&apos;</string>
<key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
<key>type</key><string>Leak</string>
<key>check_name</key><string>osx.cocoa.RetainCountBase</string>
<key>check_name</key><string>osx.cocoa.RetainCount</string>
<!-- This hash is experimental and going to change! -->
<key>issue_hash_content_of_line_in_context</key><string>9f258122568ea8763047e98db8a52647</string>
<key>issue_hash_content_of_line_in_context</key><string>e1fbcc142b678b3c2c43737ee35b64d9</string>
<key>issue_context_kind</key><string>function</string>
<key>issue_context</key><string>test_objc_arrays</string>
<key>issue_hash_function_offset</key><string>24</string>
@ -1928,9 +1928,9 @@
<key>description</key><string>Potential leak of an object stored into &apos;o&apos;</string>
<key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
<key>type</key><string>Leak</string>
<key>check_name</key><string>osx.cocoa.RetainCountBase</string>
<key>check_name</key><string>osx.cocoa.RetainCount</string>
<!-- This hash is experimental and going to change! -->
<key>issue_hash_content_of_line_in_context</key><string>8187b0ba5cadd42594120fe05d871502</string>
<key>issue_hash_content_of_line_in_context</key><string>e300a279615a384d2b310329651d3978</string>
<key>issue_context_kind</key><string>function</string>
<key>issue_context</key><string>rdar11059275_positive</string>
<key>issue_hash_function_offset</key><string>1</string>

View File

@ -1329,9 +1329,9 @@
<key>description</key><string>Potential leak of an object of type &apos;NSNumber *&apos;</string>
<key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
<key>type</key><string>Leak</string>
<key>check_name</key><string>osx.cocoa.RetainCountBase</string>
<key>check_name</key><string>osx.cocoa.RetainCount</string>
<!-- This hash is experimental and going to change! -->
<key>issue_hash_content_of_line_in_context</key><string>c204ce6cce660a7714c801bdf9183431</string>
<key>issue_hash_content_of_line_in_context</key><string>500e2bbda41c8086771ad98b6bcfdc50</string>
<key>location</key>
<dict>
<key>line</key><integer>53</integer>

View File

@ -1485,9 +1485,9 @@
<key>description</key><string>Potential leak of an object stored into &apos;value&apos;</string>
<key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
<key>type</key><string>Leak</string>
<key>check_name</key><string>osx.cocoa.RetainCountBase</string>
<key>check_name</key><string>osx.cocoa.RetainCount</string>
<!-- This hash is experimental and going to change! -->
<key>issue_hash_content_of_line_in_context</key><string>b2b15a95787e594ff79f02c600e9d357</string>
<key>issue_hash_content_of_line_in_context</key><string>29a10ca4af622b6146ca082e49d919d6</string>
<key>issue_context_kind</key><string>function</string>
<key>issue_context</key><string>rdar8331641</string>
<key>issue_hash_function_offset</key><string>2</string>

View File

@ -2372,9 +2372,9 @@
<key>description</key><string>Potential leak of an object stored into &apos;foo&apos;</string>
<key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
<key>type</key><string>Leak</string>
<key>check_name</key><string>osx.cocoa.RetainCountBase</string>
<key>check_name</key><string>osx.cocoa.RetainCount</string>
<!-- This hash is experimental and going to change! -->
<key>issue_hash_content_of_line_in_context</key><string>ef342aeb2f2719117ddd4ef1b72f5ba7</string>
<key>issue_hash_content_of_line_in_context</key><string>f533db5cbb9c20d171f9f92105789dc4</string>
<key>issue_context_kind</key><string>Objective-C method</string>
<key>issue_context</key><string>test2</string>
<key>issue_hash_function_offset</key><string>2</string>

View File

@ -104,9 +104,9 @@
<key>description</key><string>Potential leak of an object stored into &apos;leaked&apos;</string>
<key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
<key>type</key><string>Leak</string>
<key>check_name</key><string>osx.cocoa.RetainCountBase</string>
<key>check_name</key><string>osx.cocoa.RetainCount</string>
<!-- This hash is experimental and going to change! -->
<key>issue_hash_content_of_line_in_context</key><string>fc2476fe550128eebe2a0a8fa4299a59</string>
<key>issue_hash_content_of_line_in_context</key><string>d21e9660cc6434ef84a51f39ffcdce86</string>
<key>issue_context_kind</key><string>function</string>
<key>issue_context</key><string>creationViaAlloc</string>
<key>issue_hash_function_offset</key><string>1</string>
@ -225,9 +225,9 @@
<key>description</key><string>Potential leak of an object stored into &apos;leaked&apos;</string>
<key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
<key>type</key><string>Leak</string>
<key>check_name</key><string>osx.cocoa.RetainCountBase</string>
<key>check_name</key><string>osx.cocoa.RetainCount</string>
<!-- This hash is experimental and going to change! -->
<key>issue_hash_content_of_line_in_context</key><string>31ad4a19f94c8994ebf7e887ed4ab840</string>
<key>issue_hash_content_of_line_in_context</key><string>f8ec2601a04113e567aa1d09c9902c91</string>
<key>issue_context_kind</key><string>function</string>
<key>issue_context</key><string>creationViaCFCreate</string>
<key>issue_hash_function_offset</key><string>1</string>
@ -571,9 +571,9 @@
<key>description</key><string>Potential leak of an object stored into &apos;leaked&apos;</string>
<key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
<key>type</key><string>Leak</string>
<key>check_name</key><string>osx.cocoa.RetainCountBase</string>
<key>check_name</key><string>osx.cocoa.RetainCount</string>
<!-- This hash is experimental and going to change! -->
<key>issue_hash_content_of_line_in_context</key><string>1b654ea7bbef1493beda9e0a667dd859</string>
<key>issue_hash_content_of_line_in_context</key><string>dd26a8ad9a7a057feaa636974b43ccb0</string>
<key>issue_context_kind</key><string>function</string>
<key>issue_context</key><string>acquisitionViaMethod</string>
<key>issue_hash_function_offset</key><string>1</string>
@ -770,9 +770,9 @@
<key>description</key><string>Potential leak of an object stored into &apos;leaked&apos;</string>
<key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
<key>type</key><string>Leak</string>
<key>check_name</key><string>osx.cocoa.RetainCountBase</string>
<key>check_name</key><string>osx.cocoa.RetainCount</string>
<!-- This hash is experimental and going to change! -->
<key>issue_hash_content_of_line_in_context</key><string>3fc42b0b859923347e789ad601d29b2a</string>
<key>issue_hash_content_of_line_in_context</key><string>2f2de5d7fe728958585598b619069e5a</string>
<key>issue_context_kind</key><string>function</string>
<key>issue_context</key><string>acquisitionViaProperty</string>
<key>issue_hash_function_offset</key><string>1</string>
@ -967,9 +967,9 @@
<key>description</key><string>Potential leak of an object stored into &apos;leaked&apos;</string>
<key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
<key>type</key><string>Leak</string>
<key>check_name</key><string>osx.cocoa.RetainCountBase</string>
<key>check_name</key><string>osx.cocoa.RetainCount</string>
<!-- This hash is experimental and going to change! -->
<key>issue_hash_content_of_line_in_context</key><string>0b4d42c9cc01d55bc281c067f1cc1c3d</string>
<key>issue_hash_content_of_line_in_context</key><string>1c02b65e83dad1b22270ff5a71de3118</string>
<key>issue_context_kind</key><string>function</string>
<key>issue_context</key><string>acquisitionViaCFFunction</string>
<key>issue_hash_function_offset</key><string>1</string>
@ -1164,9 +1164,9 @@
<key>description</key><string>Reference-counted object is used after it is released</string>
<key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
<key>type</key><string>Use-after-release</string>
<key>check_name</key><string>osx.cocoa.RetainCountBase</string>
<key>check_name</key><string>osx.cocoa.RetainCount</string>
<!-- This hash is experimental and going to change! -->
<key>issue_hash_content_of_line_in_context</key><string>baa3d5ecb7824a6997e0734ad148ec55</string>
<key>issue_hash_content_of_line_in_context</key><string>03c23f0f82d7f2fd880a22e0d9cf14b9</string>
<key>issue_context_kind</key><string>function</string>
<key>issue_context</key><string>explicitDealloc</string>
<key>issue_hash_function_offset</key><string>3</string>
@ -1361,9 +1361,9 @@
<key>description</key><string>Reference-counted object is used after it is released</string>
<key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
<key>type</key><string>Use-after-release</string>
<key>check_name</key><string>osx.cocoa.RetainCountBase</string>
<key>check_name</key><string>osx.cocoa.RetainCount</string>
<!-- This hash is experimental and going to change! -->
<key>issue_hash_content_of_line_in_context</key><string>ce73a05e0a1055b4b451f5015edbd6ec</string>
<key>issue_hash_content_of_line_in_context</key><string>6f1b3f0c6c7f79f1af9b313273a01e92</string>
<key>issue_context_kind</key><string>function</string>
<key>issue_context</key><string>implicitDealloc</string>
<key>issue_hash_function_offset</key><string>3</string>
@ -1633,9 +1633,9 @@
<key>description</key><string>Object autoreleased too many times</string>
<key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
<key>type</key><string>Object autoreleased too many times</string>
<key>check_name</key><string>osx.cocoa.RetainCountBase</string>
<key>check_name</key><string>osx.cocoa.RetainCount</string>
<!-- This hash is experimental and going to change! -->
<key>issue_hash_content_of_line_in_context</key><string>b8cbd4dae812cd8d8faaf3b48dad2021</string>
<key>issue_hash_content_of_line_in_context</key><string>cb5e4205a8f925230a70715914a2e3d2</string>
<key>issue_context_kind</key><string>function</string>
<key>issue_context</key><string>overAutorelease</string>
<key>issue_hash_function_offset</key><string>4</string>
@ -1831,9 +1831,9 @@
<key>description</key><string>Object autoreleased too many times</string>
<key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
<key>type</key><string>Object autoreleased too many times</string>
<key>check_name</key><string>osx.cocoa.RetainCountBase</string>
<key>check_name</key><string>osx.cocoa.RetainCount</string>
<!-- This hash is experimental and going to change! -->
<key>issue_hash_content_of_line_in_context</key><string>ee96f7e22e32b24d677efa45b2395915</string>
<key>issue_hash_content_of_line_in_context</key><string>1edd178e5ad76c79ce9812f519e8f467</string>
<key>issue_context_kind</key><string>function</string>
<key>issue_context</key><string>autoreleaseUnowned</string>
<key>issue_hash_function_offset</key><string>3</string>
@ -1953,9 +1953,9 @@
<key>description</key><string>Potential leak of an object stored into &apos;leaked&apos;</string>
<key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
<key>type</key><string>Leak</string>
<key>check_name</key><string>osx.cocoa.RetainCountBase</string>
<key>check_name</key><string>osx.cocoa.RetainCount</string>
<!-- This hash is experimental and going to change! -->
<key>issue_hash_content_of_line_in_context</key><string>12887d3520c4c9fd03995feeb69967ec</string>
<key>issue_hash_content_of_line_in_context</key><string>3f08690fae9687c29bb23b7a7cb7995b</string>
<key>issue_context_kind</key><string>function</string>
<key>issue_context</key><string>makeCollectableIgnored</string>
<key>issue_hash_function_offset</key><string>1</string>
@ -2076,9 +2076,9 @@
<key>description</key><string>Object with a +0 retain count returned to caller where a +1 (owning) retain count is expected</string>
<key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
<key>type</key><string>Method should return an owned object</string>
<key>check_name</key><string>osx.cocoa.RetainCountBase</string>
<key>check_name</key><string>osx.cocoa.RetainCount</string>
<!-- This hash is experimental and going to change! -->
<key>issue_hash_content_of_line_in_context</key><string>d715154641c7b248d401df12c1ce0808</string>
<key>issue_hash_content_of_line_in_context</key><string>4b621ab5f8f2ef9240699119f4d874cb</string>
<key>issue_context_kind</key><string>function</string>
<key>issue_context</key><string>CFCopyRuleViolation</string>
<key>issue_hash_function_offset</key><string>2</string>
@ -2197,9 +2197,9 @@
<key>description</key><string>Potential leak of an object stored into &apos;object&apos;</string>
<key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
<key>type</key><string>Leak of returned object</string>
<key>check_name</key><string>osx.cocoa.RetainCountBase</string>
<key>check_name</key><string>osx.cocoa.RetainCount</string>
<!-- This hash is experimental and going to change! -->
<key>issue_hash_content_of_line_in_context</key><string>58d56f1d5982f5923ab07900852ea30c</string>
<key>issue_hash_content_of_line_in_context</key><string>5248d2310322982d02e5f3d564249b4f</string>
<key>issue_context_kind</key><string>function</string>
<key>issue_context</key><string>CFGetRuleViolation</string>
<key>issue_hash_function_offset</key><string>1</string>
@ -2318,9 +2318,9 @@
<key>description</key><string>Object with a +0 retain count returned to caller where a +1 (owning) retain count is expected</string>
<key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
<key>type</key><string>Method should return an owned object</string>
<key>check_name</key><string>osx.cocoa.RetainCountBase</string>
<key>check_name</key><string>osx.cocoa.RetainCount</string>
<!-- This hash is experimental and going to change! -->
<key>issue_hash_content_of_line_in_context</key><string>cc20c23c14b2363ca453c24ede3bc38d</string>
<key>issue_hash_content_of_line_in_context</key><string>4f23ad2725fb68134cec8b8354cd295c</string>
<key>issue_context_kind</key><string>Objective-C method</string>
<key>issue_context</key><string>copyViolation</string>
<key>issue_hash_function_offset</key><string>2</string>
@ -2439,9 +2439,9 @@
<key>description</key><string>Object with a +0 retain count returned to caller where a +1 (owning) retain count is expected</string>
<key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
<key>type</key><string>Method should return an owned object</string>
<key>check_name</key><string>osx.cocoa.RetainCountBase</string>
<key>check_name</key><string>osx.cocoa.RetainCount</string>
<!-- This hash is experimental and going to change! -->
<key>issue_hash_content_of_line_in_context</key><string>4eefa164042de89f947573c1df2fce03</string>
<key>issue_hash_content_of_line_in_context</key><string>da1dab126ed46b144040160ae8628460</string>
<key>issue_context_kind</key><string>Objective-C method</string>
<key>issue_context</key><string>copyViolationIndexedSubscript</string>
<key>issue_hash_function_offset</key><string>2</string>
@ -2560,9 +2560,9 @@
<key>description</key><string>Object with a +0 retain count returned to caller where a +1 (owning) retain count is expected</string>
<key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
<key>type</key><string>Method should return an owned object</string>
<key>check_name</key><string>osx.cocoa.RetainCountBase</string>
<key>check_name</key><string>osx.cocoa.RetainCount</string>
<!-- This hash is experimental and going to change! -->
<key>issue_hash_content_of_line_in_context</key><string>e8ad4d8a073872a91d2b0225319cd521</string>
<key>issue_hash_content_of_line_in_context</key><string>52877f9471b1ecdaf213b39016b84e52</string>
<key>issue_context_kind</key><string>Objective-C method</string>
<key>issue_context</key><string>copyViolationKeyedSubscript</string>
<key>issue_hash_function_offset</key><string>2</string>
@ -2681,9 +2681,9 @@
<key>description</key><string>Potential leak of an object stored into &apos;result&apos;</string>
<key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
<key>type</key><string>Leak of returned object</string>
<key>check_name</key><string>osx.cocoa.RetainCountBase</string>
<key>check_name</key><string>osx.cocoa.RetainCount</string>
<!-- This hash is experimental and going to change! -->
<key>issue_hash_content_of_line_in_context</key><string>f858bd7c1720b43bd464bbec97a1cb6b</string>
<key>issue_hash_content_of_line_in_context</key><string>cf8c65a18ad9982cb9848a266cd9c61b</string>
<key>issue_context_kind</key><string>Objective-C method</string>
<key>issue_context</key><string>getViolation</string>
<key>issue_hash_function_offset</key><string>1</string>
@ -2877,9 +2877,9 @@
<key>description</key><string>Object with a +0 retain count returned to caller where a +1 (owning) retain count is expected</string>
<key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
<key>type</key><string>Method should return an owned object</string>
<key>check_name</key><string>osx.cocoa.RetainCountBase</string>
<key>check_name</key><string>osx.cocoa.RetainCount</string>
<!-- This hash is experimental and going to change! -->
<key>issue_hash_content_of_line_in_context</key><string>4da16a9c4c9d9587418f276359c5f098</string>
<key>issue_hash_content_of_line_in_context</key><string>e7b798151545b45a994592df0d27d250</string>
<key>issue_context_kind</key><string>Objective-C method</string>
<key>issue_context</key><string>copyAutorelease</string>
<key>issue_hash_function_offset</key><string>3</string>
@ -2999,9 +2999,9 @@
<key>description</key><string>Incorrect decrement of the reference count of an object that is not owned at this point by the caller</string>
<key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
<key>type</key><string>Bad release</string>
<key>check_name</key><string>osx.cocoa.RetainCountBase</string>
<key>check_name</key><string>osx.cocoa.RetainCount</string>
<!-- This hash is experimental and going to change! -->
<key>issue_hash_content_of_line_in_context</key><string>18ba6f4fe59b182bee196c1a976e3aa2</string>
<key>issue_hash_content_of_line_in_context</key><string>4e0c810e2b301aca3f636ad7e3d6b0b8</string>
<key>issue_context_kind</key><string>function</string>
<key>issue_context</key><string>testNumericLiteral</string>
<key>issue_hash_function_offset</key><string>2</string>
@ -3120,9 +3120,9 @@
<key>description</key><string>Incorrect decrement of the reference count of an object that is not owned at this point by the caller</string>
<key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
<key>type</key><string>Bad release</string>
<key>check_name</key><string>osx.cocoa.RetainCountBase</string>
<key>check_name</key><string>osx.cocoa.RetainCount</string>
<!-- This hash is experimental and going to change! -->
<key>issue_hash_content_of_line_in_context</key><string>ac4375d1ab6887c27055ee00b20a212e</string>
<key>issue_hash_content_of_line_in_context</key><string>1d054002016aa4360aaf23a4c4d8fbb7</string>
<key>issue_context_kind</key><string>function</string>
<key>issue_context</key><string>testBoxedInt</string>
<key>issue_hash_function_offset</key><string>2</string>
@ -3241,9 +3241,9 @@
<key>description</key><string>Incorrect decrement of the reference count of an object that is not owned at this point by the caller</string>
<key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
<key>type</key><string>Bad release</string>
<key>check_name</key><string>osx.cocoa.RetainCountBase</string>
<key>check_name</key><string>osx.cocoa.RetainCount</string>
<!-- This hash is experimental and going to change! -->
<key>issue_hash_content_of_line_in_context</key><string>cd2f260edad8ce1826b21acc49cba277</string>
<key>issue_hash_content_of_line_in_context</key><string>67ca92144b05322ee4569aea88d08595</string>
<key>issue_context_kind</key><string>function</string>
<key>issue_context</key><string>testBoxedString</string>
<key>issue_hash_function_offset</key><string>2</string>
@ -3362,9 +3362,9 @@
<key>description</key><string>Incorrect decrement of the reference count of an object that is not owned at this point by the caller</string>
<key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
<key>type</key><string>Bad release</string>
<key>check_name</key><string>osx.cocoa.RetainCountBase</string>
<key>check_name</key><string>osx.cocoa.RetainCount</string>
<!-- This hash is experimental and going to change! -->
<key>issue_hash_content_of_line_in_context</key><string>e60765ef00b3af982aacd5471a2cdb21</string>
<key>issue_hash_content_of_line_in_context</key><string>32fcec71872b8f62d8d7b1b05284b0fe</string>
<key>issue_context_kind</key><string>function</string>
<key>issue_context</key><string>testArray</string>
<key>issue_hash_function_offset</key><string>2</string>
@ -3483,9 +3483,9 @@
<key>description</key><string>Incorrect decrement of the reference count of an object that is not owned at this point by the caller</string>
<key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
<key>type</key><string>Bad release</string>
<key>check_name</key><string>osx.cocoa.RetainCountBase</string>
<key>check_name</key><string>osx.cocoa.RetainCount</string>
<!-- This hash is experimental and going to change! -->
<key>issue_hash_content_of_line_in_context</key><string>42da4f0388822b235ed56427f2e1ac1b</string>
<key>issue_hash_content_of_line_in_context</key><string>d9584825bb1e62066879949e3ade8570</string>
<key>issue_context_kind</key><string>function</string>
<key>issue_context</key><string>testDictionary</string>
<key>issue_hash_function_offset</key><string>2</string>
@ -3841,9 +3841,9 @@
<key>description</key><string>Potential leak of an object of type &apos;MyObj *&apos;</string>
<key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
<key>type</key><string>Leak</string>
<key>check_name</key><string>osx.cocoa.RetainCountBase</string>
<key>check_name</key><string>osx.cocoa.RetainCount</string>
<!-- This hash is experimental and going to change! -->
<key>issue_hash_content_of_line_in_context</key><string>b5589615cea2321192e477d2011edf09</string>
<key>issue_hash_content_of_line_in_context</key><string>eef2aef4b58abf21fcfa4bbf69e19c02</string>
<key>issue_context_kind</key><string>Objective-C method</string>
<key>issue_context</key><string>test</string>
<key>issue_hash_function_offset</key><string>2</string>
@ -4240,9 +4240,9 @@
<key>description</key><string>Potential leak of an object stored into &apos;y&apos;</string>
<key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
<key>type</key><string>Leak</string>
<key>check_name</key><string>osx.cocoa.RetainCountBase</string>
<key>check_name</key><string>osx.cocoa.RetainCount</string>
<!-- This hash is experimental and going to change! -->
<key>issue_hash_content_of_line_in_context</key><string>b319657460942b0e8deafb79876d5479</string>
<key>issue_hash_content_of_line_in_context</key><string>8c27524f691296551f9e52856b824326</string>
<key>issue_context_kind</key><string>Objective-C method</string>
<key>issue_context</key><string>test</string>
<key>issue_hash_function_offset</key><string>8</string>
@ -4518,9 +4518,9 @@
<key>description</key><string>Object autoreleased too many times</string>
<key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
<key>type</key><string>Object autoreleased too many times</string>
<key>check_name</key><string>osx.cocoa.RetainCountBase</string>
<key>check_name</key><string>osx.cocoa.RetainCount</string>
<!-- This hash is experimental and going to change! -->
<key>issue_hash_content_of_line_in_context</key><string>8e06af66dd0b414c095c951ac1f2cc68</string>
<key>issue_hash_content_of_line_in_context</key><string>4fc36e73ba317d307dc9cc4b3d62fd0a</string>
<key>issue_context_kind</key><string>function</string>
<key>issue_context</key><string>CFOverAutorelease</string>
<key>issue_hash_function_offset</key><string>4</string>
@ -4716,9 +4716,9 @@
<key>description</key><string>Object autoreleased too many times</string>
<key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
<key>type</key><string>Object autoreleased too many times</string>
<key>check_name</key><string>osx.cocoa.RetainCountBase</string>
<key>check_name</key><string>osx.cocoa.RetainCount</string>
<!-- This hash is experimental and going to change! -->
<key>issue_hash_content_of_line_in_context</key><string>06eeb988e43f885cb575eba46e7ccf8f</string>
<key>issue_hash_content_of_line_in_context</key><string>08e6a3931d34cda45c09dfda76976e17</string>
<key>issue_context_kind</key><string>function</string>
<key>issue_context</key><string>CFAutoreleaseUnowned</string>
<key>issue_hash_function_offset</key><string>3</string>
@ -4988,9 +4988,9 @@
<key>description</key><string>Object autoreleased too many times</string>
<key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
<key>type</key><string>Object autoreleased too many times</string>
<key>check_name</key><string>osx.cocoa.RetainCountBase</string>
<key>check_name</key><string>osx.cocoa.RetainCount</string>
<!-- This hash is experimental and going to change! -->
<key>issue_hash_content_of_line_in_context</key><string>e1b335bbbaad2a9c427e681a6fac6562</string>
<key>issue_hash_content_of_line_in_context</key><string>d9bb23a5435fe15df9d7ffdc27a8a072</string>
<key>issue_context_kind</key><string>function</string>
<key>issue_context</key><string>CFAutoreleaseUnownedMixed</string>
<key>issue_hash_function_offset</key><string>4</string>

View File

@ -125,7 +125,7 @@ bool write_into_out_param_on_success(OS_RETURNS_RETAINED OSObject **obj);
void use_out_param_leak() {
OSObject *obj;
// FIXME: This shouldn't be tied to a modeling checker.
write_into_out_param_on_success(&obj); // expected-warning{{Potential leak of an object stored into 'obj' [osx.cocoa.RetainCountBase]}}
write_into_out_param_on_success(&obj); // expected-warning{{Potential leak of an object stored into 'obj' [osx.cocoa.RetainCount]}}
}
typedef struct dispatch_queue_s *dispatch_queue_t;

View File

@ -1965,9 +1965,9 @@
<key>description</key><string>Object autoreleased too many times</string>
<key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
<key>type</key><string>Object autoreleased too many times</string>
<key>check_name</key><string>osx.cocoa.RetainCountBase</string>
<key>check_name</key><string>osx.cocoa.RetainCount</string>
<!-- This hash is experimental and going to change! -->
<key>issue_hash_content_of_line_in_context</key><string>b6a556c71184371a9567489c8477c2f7</string>
<key>issue_hash_content_of_line_in_context</key><string>a3c91a7a52619d81ebe032dcc49ebb93</string>
<key>issue_context_kind</key><string>function</string>
<key>issue_context</key><string>testAutoreleaseTakesEffectInDispatch</string>
<key>issue_hash_function_offset</key><string>11</string>

View File

@ -1,8 +1,8 @@
// RUN: %clang_analyze_cc1 -std=c++14 -DNO_CF_OBJECT -verify %s \
// RUN: %clang_analyze_cc1 -std=c++14 -verify=no-retain-count %s \
// RUN: -analyzer-checker=core,osx \
// RUN: -analyzer-disable-checker osx.cocoa.RetainCount
//
// RUN: %clang_analyze_cc1 -std=c++14 -DNO_OS_OBJECT -verify %s \
// RUN: %clang_analyze_cc1 -std=c++14 -verify=no-os-object %s \
// RUN: -analyzer-checker=core,osx \
// RUN: -analyzer-disable-checker osx.OSObjectRetainCount
@ -20,17 +20,11 @@ using size_t = decltype(sizeof(int));
void cf_overrelease() {
CFTypeRef cf = CFCreate();
CFRelease(cf);
CFRelease(cf);
#ifndef NO_CF_OBJECT
// expected-warning@-2{{Reference-counted object is used after it is released}}
#endif
CFRelease(cf); // no-os-object-warning{{Reference-counted object is used after it is released}}
}
void osobject_overrelease() {
OSObject *o = new OSObject;
o->release();
o->release();
#ifndef NO_OS_OBJECT
// expected-warning@-2{{Reference-counted object is used after it is released}}
#endif
o->release(); // no-retain-count-warning{{Reference-counted object is used after it is released}}
}