return getSValBuilder().getSymbolManager();
}
+ bool isObjCGCEnabled() {
+ return Eng.isObjCGCEnabled();
+ }
+
ExplodedNode *generateNode(bool autoTransition = true) {
assert(statement && "Only transitions with statements currently supported");
ExplodedNode *N = generateNodeImpl(statement, getState(), false,
// Obj-C Selectors.
Selector* NSExceptionInstanceRaiseSelectors;
Selector RaiseSel;
+
+ /// Whether or not GC is enabled in this analysis.
+ bool ObjCGCEnabled;
/// The BugReporter associated with this engine. It is important that
/// this object be placed at the very end of member variables so that its
/// destructor is called before the rest of the ExprEngine is destroyed.
GRBugReporter BR;
-
- llvm::OwningPtr<TransferFuncs> TF;
public:
- ExprEngine(AnalysisManager &mgr, TransferFuncs *tf);
+ ExprEngine(AnalysisManager &mgr, bool gcEnabled);
~ExprEngine();
SValBuilder &getSValBuilder() { return svalBuilder; }
- TransferFuncs& getTF() { return *TF; }
-
BugReporter& getBugReporter() { return BR; }
StmtNodeBuilder &getBuilder() { assert(Builder); return *Builder; }
- // FIXME: Remove once TransferFuncs is no longer referenced.
- void setTransferFunction(TransferFuncs* tf);
+ bool isObjCGCEnabled() { return ObjCGCEnabled; }
/// ViewGraph - Visualize the ExplodedGraph created by executing the
/// simulation.
HelpText<"Check usage of NSError** parameters">,
DescFile<"NSErrorChecker.cpp">;
+def RetainCountChecker : Checker<"RetainCount">,
+ HelpText<"Check for leaks and improper reference count management">,
+ DescFile<"RetainCountChecker.cpp">;
+
} // end "cocoa"
let ParentPackage = CocoaExperimental in {
mutable SummaryLogTy SummaryLog;
mutable bool ShouldResetSummaryLog;
- LangOptions::GCMode GCMode;
-
public:
- RetainReleaseChecker()
- : ShouldResetSummaryLog(false), GCMode(LangOptions::HybridGC) {}
+ RetainReleaseChecker() : ShouldResetSummaryLog(false) {}
virtual ~RetainReleaseChecker() {
DeleteContainerSeconds(DeadSymbolTags);
ShouldResetSummaryLog = !SummaryLog.empty();
}
- void setGCMode(LangOptions::GCMode newGC) {
- // FIXME: This is definitely not const behavior; its intended use is to
- // set the GC mode for the entire coming code body. This setting will
- // most likely live somewhere else in the future.
- assert(newGC != LangOptions::HybridGC && "Analysis requires GC on or off.");
- GCMode = newGC;
- }
-
- bool isGCEnabled() const {
- switch (GCMode) {
- case LangOptions::HybridGC:
- llvm_unreachable("GC mode not set yet!");
- case LangOptions::NonGC:
- return false;
- case LangOptions::GCOnly:
- return true;
- }
-
- llvm_unreachable("Invalid/unknown GC mode.");
- }
-
- bool isARCorGCEnabled(ASTContext &Ctx) const {
- return isGCEnabled() || Ctx.getLangOptions().ObjCAutoRefCount;
- }
-
- CFRefBug *getLeakWithinFunctionBug(ASTContext &Ctx) const {
- if (isGCEnabled()) {
+ CFRefBug *getLeakWithinFunctionBug(const LangOptions &LOpts,
+ bool GCEnabled) const {
+ if (GCEnabled) {
if (!leakWithinFunctionGC)
leakWithinFunctionGC.reset(new LeakWithinFunction("Leak of object when "
"using garbage "
"collection"));
- return &*leakWithinFunctionGC;
+ return leakWithinFunctionGC.get();
} else {
if (!leakWithinFunction) {
- if (Ctx.getLangOptions().getGCMode() == LangOptions::HybridGC) {
+ if (LOpts.getGCMode() == LangOptions::HybridGC) {
leakWithinFunction.reset(new LeakWithinFunction("Leak of object when "
"not using garbage "
"collection (GC) in "
leakWithinFunction.reset(new LeakWithinFunction("Leak"));
}
}
- return &*leakWithinFunction;
+ return leakWithinFunction.get();
}
}
- CFRefBug *getLeakAtReturnBug(ASTContext &Ctx) const {
- if (isGCEnabled()) {
+ CFRefBug *getLeakAtReturnBug(const LangOptions &LOpts, bool GCEnabled) const {
+ if (GCEnabled) {
if (!leakAtReturnGC)
leakAtReturnGC.reset(new LeakAtReturn("Leak of returned object when "
"using garbage collection"));
- return &*leakAtReturnGC;
+ return leakAtReturnGC.get();
} else {
if (!leakAtReturn) {
- if (Ctx.getLangOptions().getGCMode() == LangOptions::HybridGC) {
+ if (LOpts.getGCMode() == LangOptions::HybridGC) {
leakAtReturn.reset(new LeakAtReturn("Leak of returned object when "
"not using garbage collection "
"(GC) in dual GC/non-GC code"));
leakAtReturn.reset(new LeakAtReturn("Leak of returned object"));
}
}
- return &*leakAtReturn;
+ return leakAtReturn.get();
}
}
- RetainSummaryManager &getSummaryManager(ASTContext &Ctx) const {
- if (isGCEnabled()) {
- if (!SummariesGC) {
- bool ARCEnabled = (bool)Ctx.getLangOptions().ObjCAutoRefCount;
+ RetainSummaryManager &getSummaryManager(ASTContext &Ctx,
+ bool GCEnabled) const {
+ // FIXME: We don't support ARC being turned on and off during one analysis.
+ // (nor, for that matter, do we support changing ASTContexts)
+ bool ARCEnabled = (bool)Ctx.getLangOptions().ObjCAutoRefCount;
+ if (GCEnabled) {
+ if (!SummariesGC)
SummariesGC.reset(new RetainSummaryManager(Ctx, true, ARCEnabled));
- }
+ else
+ assert(SummariesGC->isARCEnabled() == ARCEnabled);
return *SummariesGC;
} else {
- if (!Summaries) {
- bool ARCEnabled = (bool)Ctx.getLangOptions().ObjCAutoRefCount;
+ if (!Summaries)
Summaries.reset(new RetainSummaryManager(Ctx, false, ARCEnabled));
- }
+ else
+ assert(Summaries->isARCEnabled() == ARCEnabled);
return *Summaries;
}
}
+ RetainSummaryManager &getSummaryManager(CheckerContext &C) const {
+ return getSummaryManager(C.getASTContext(), C.isObjCGCEnabled());
+ }
+
void printState(raw_ostream &Out, const ProgramState *State,
const char *NL, const char *Sep) const;
void checkEndPath(EndOfFunctionNodeBuilder &Builder, ExprEngine &Eng) const;
const ProgramState *updateSymbol(const ProgramState *state, SymbolRef sym,
- RefVal V, ArgEffect E,
- RefVal::Kind &hasErr) const;
+ RefVal V, ArgEffect E, RefVal::Kind &hasErr,
+ CheckerContext &C) const;
void processNonLeakError(const ProgramState *St, SourceRange ErrorRange,
RefVal::Kind ErrorKind, SymbolRef Sym,
return;
RefVal::Kind hasErr = (RefVal::Kind) 0;
- state = updateSymbol(state, Sym, *T, AE, hasErr);
+ state = updateSymbol(state, Sym, *T, AE, hasErr, C);
if (hasErr) {
// FIXME: If we get an error during a bridge cast, should we report it?
const Expr *Callee = CE->getCallee();
SVal L = state->getSVal(Callee);
- RetainSummaryManager &Summaries = getSummaryManager(C.getASTContext());
+ RetainSummaryManager &Summaries = getSummaryManager(C);
RetainSummary *Summ = 0;
// FIXME: Better support for blocks. For now we stop tracking anything
if (!Ctor)
return;
- RetainSummaryManager &Summaries = getSummaryManager(C.getASTContext());
+ RetainSummaryManager &Summaries = getSummaryManager(C);
RetainSummary *Summ = Summaries.getSummary(Ctor);
// If we didn't get a summary, this constructor doesn't affect retain counts.
const ProgramState *state = C.getState();
ExplodedNode *Pred = C.getPredecessor();
- RetainSummaryManager &Summaries = getSummaryManager(C.getASTContext());
+ RetainSummaryManager &Summaries = getSummaryManager(C);
RetainSummary *Summ;
if (Msg.isInstanceMessage()) {
if (SymbolRef Sym = V.getAsLocSymbol()) {
if (RefBindings::data_type *T = state->get<RefBindings>(Sym)) {
- state = updateSymbol(state, Sym, *T, Summ.getArg(idx), hasErr);
+ state = updateSymbol(state, Sym, *T, Summ.getArg(idx), hasErr, C);
if (hasErr) {
ErrorRange = CallOrMsg.getArgSourceRange(idx);
ErrorSym = Sym;
if (SymbolRef Sym = Receiver.getAsLocSymbol()) {
if (const RefVal *T = state->get<RefBindings>(Sym)) {
ReceiverIsTracked = true;
- state = updateSymbol(state, Sym, *T, Summ.getReceiverEffect(), hasErr);
+ state = updateSymbol(state, Sym, *T, Summ.getReceiverEffect(),
+ hasErr, C);
if (hasErr) {
ErrorRange = CallOrMsg.getReceiverSourceRange();
ErrorSym = Sym;
if (RE.getKind() == RetEffect::OwnedWhenTrackedReceiver) {
if (ReceiverIsTracked)
- RE = getSummaryManager(C.getASTContext()).getObjAllocRetEffect();
+ RE = getSummaryManager(C).getObjAllocRetEffect();
else
RE = RetEffect::MakeNoRet();
}
const ProgramState *
RetainReleaseChecker::updateSymbol(const ProgramState *state, SymbolRef sym,
- RefVal V, ArgEffect E,
- RefVal::Kind &hasErr) const {
+ RefVal V, ArgEffect E, RefVal::Kind &hasErr,
+ CheckerContext &C) const {
// In GC mode [... release] and [... retain] do nothing.
- ASTContext &Ctx = state->getStateManager().getContext();
+ bool IgnoreRetainMsg = C.isObjCGCEnabled();
+ if (!IgnoreRetainMsg)
+ IgnoreRetainMsg = (bool)C.getASTContext().getLangOptions().ObjCAutoRefCount;
+
switch (E) {
default: break;
- case IncRefMsg: E = isARCorGCEnabled(Ctx) ? DoNothing : IncRef; break;
- case DecRefMsg: E = isARCorGCEnabled(Ctx) ? DoNothing : DecRef; break;
- case MakeCollectable: E = isGCEnabled() ? DecRef : DoNothing; break;
- case NewAutoreleasePool: E = isGCEnabled() ? DoNothing :
- NewAutoreleasePool; break;
+ case IncRefMsg: E = IgnoreRetainMsg ? DoNothing : IncRef; break;
+ case DecRefMsg: E = IgnoreRetainMsg ? DoNothing : DecRef; break;
+ case MakeCollectable: E = C.isObjCGCEnabled() ? DecRef : DoNothing; break;
+ case NewAutoreleasePool: E = C.isObjCGCEnabled() ? DoNothing :
+ NewAutoreleasePool; break;
}
// Handle all use-after-releases.
- if (!isGCEnabled() && V.getKind() == RefVal::Released) {
+ if (!C.isObjCGCEnabled() && V.getKind() == RefVal::Released) {
V = V ^ RefVal::ErrorUseAfterRelease;
hasErr = V.getKind();
return state->set<RefBindings>(sym, V);
case Dealloc:
// Any use of -dealloc in GC is *bad*.
- if (isGCEnabled()) {
+ if (C.isObjCGCEnabled()) {
V = V ^ RefVal::ErrorDeallocGC;
hasErr = V.getKind();
break;
break;
case NewAutoreleasePool:
- assert(!isGCEnabled());
+ assert(!C.isObjCGCEnabled());
return state->add<AutoreleaseStack>(sym);
case MayEscape:
return state;
case Autorelease:
- if (isGCEnabled())
+ if (C.isObjCGCEnabled())
return state;
// Update the autorelease counts.
break;
case RefVal::Released:
// Non-GC cases are handled above.
- assert(isGCEnabled());
+ assert(C.isObjCGCEnabled());
V = (V ^ RefVal::Owned) + 1;
break;
}
case RefVal::Released:
// Non-GC cases are handled above.
- assert(isGCEnabled());
+ assert(C.isObjCGCEnabled());
V = V ^ RefVal::ErrorUseAfterRelease;
hasErr = V.getKind();
break;
assert(BT);
CFRefReport *report = new CFRefReport(*BT, C.getASTContext().getLangOptions(),
- isGCEnabled(), SummaryLog, N, Sym);
+ C.isObjCGCEnabled(), SummaryLog,
+ N, Sym);
report->addRange(ErrorRange);
C.EmitReport(report);
}
X = *T;
// Consult the summary of the enclosing method.
- RetainSummaryManager &Summaries = getSummaryManager(C.getASTContext());
+ RetainSummaryManager &Summaries = getSummaryManager(C);
const Decl *CD = &Pred->getCodeDecl();
if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(CD)) {
if (X.isReturnedOwned() && X.getCount() == 0) {
if (RE.getKind() != RetEffect::NoRet) {
bool hasError = false;
- if (isGCEnabled() && RE.getObjKind() == RetEffect::ObjC) {
+ if (C.isObjCGCEnabled() && RE.getObjKind() == RetEffect::ObjC) {
// Things are more complicated with garbage collection. If the
// returned object is suppose to be an Objective-C object, we have
// a leak (as the caller expects a GC'ed object) because no
ExplodedNode *N = Builder.generateNode(S, state, Pred,
&ReturnOwnLeakTag);
if (N) {
- ASTContext &Ctx = C.getASTContext();
+ const LangOptions &LOpts = C.getASTContext().getLangOptions();
+ bool GCEnabled = C.isObjCGCEnabled();
CFRefReport *report =
- new CFRefLeakReport(*getLeakAtReturnBug(Ctx), Ctx.getLangOptions(),
- isGCEnabled(), SummaryLog, N, Sym,
- C.getEngine());
+ new CFRefLeakReport(*getLeakAtReturnBug(LOpts, GCEnabled),
+ LOpts, GCEnabled, SummaryLog,
+ N, Sym, C.getEngine());
C.EmitReport(report);
}
}
CFRefReport *report =
new CFRefReport(*returnNotOwnedForOwned,
- C.getASTContext().getLangOptions(), isGCEnabled(),
- SummaryLog, N, Sym);
+ C.getASTContext().getLangOptions(),
+ C.isObjCGCEnabled(), SummaryLog, N, Sym);
C.EmitReport(report);
}
}
if (!ACnt)
return std::make_pair(Pred, state);
- assert(!isGCEnabled() && "Autorelease counts in GC mode?");
+ assert(!Eng.isObjCGCEnabled() && "Autorelease counts in GC mode?");
unsigned Cnt = V.getCount();
// FIXME: Handle sending 'autorelease' to already released object.
for (SmallVectorImpl<SymbolRef>::iterator
I = Leaked.begin(), E = Leaked.end(); I != E; ++I) {
- ASTContext &Ctx = Eng.getContext();
- CFRefBug *BT = Pred ? getLeakWithinFunctionBug(Ctx)
- : getLeakAtReturnBug(Ctx);
+ const LangOptions &LOpts = Eng.getContext().getLangOptions();
+ bool GCEnabled = Eng.isObjCGCEnabled();
+ CFRefBug *BT = Pred ? getLeakWithinFunctionBug(LOpts, GCEnabled)
+ : getLeakAtReturnBug(LOpts, GCEnabled);
assert(BT && "BugType not initialized.");
- const LangOptions &LOpts = Ctx.getLangOptions();
- CFRefLeakReport *report = new CFRefLeakReport(*BT, LOpts, isGCEnabled(),
+ CFRefLeakReport *report = new CFRefLeakReport(*BT, LOpts, GCEnabled,
SummaryLog, N, *I, Eng);
Eng.getBugReporter().EmitReport(report);
}
RetainReleaseChecker *checker =
Eng.getCheckerManager().registerChecker<RetainReleaseChecker>();
assert(checker);
- checker->setGCMode(GCEnabled ? LangOptions::GCOnly : LangOptions::NonGC);
+ //checker->setGCMode(GCEnabled ? LangOptions::GCOnly : LangOptions::NonGC);
}
TransferFuncs* ento::MakeCFRefCountTF(ASTContext &Ctx, bool GCEnabled,
const LangOptions& lopts) {
return new CFRefCount(Ctx, GCEnabled, lopts);
}
+
+
+// FIXME: This will be unnecessary once RetainReleaseChecker is moved to
+// the Checkers library (...and renamed to RetainCountChecker).
+namespace clang {
+namespace ento {
+ void registerRetainCountChecker(CheckerManager &Mgr);
+}
+}
+
+void ento::registerRetainCountChecker(CheckerManager &Mgr) {
+ Mgr.registerChecker<RetainReleaseChecker>();
+}
+
// Engine construction and deletion.
//===----------------------------------------------------------------------===//
-ExprEngine::ExprEngine(AnalysisManager &mgr, TransferFuncs *tf)
+ExprEngine::ExprEngine(AnalysisManager &mgr, bool gcEnabled)
: AMgr(mgr),
Engine(*this),
G(Engine.getGraph()),
EntryNode(NULL), currentStmt(NULL),
NSExceptionII(NULL), NSExceptionInstanceRaiseSelectors(NULL),
RaiseSel(GetNullarySelector("raise", getContext())),
- BR(mgr, *this), TF(tf) {
-
- // FIXME: Eventually remove the TF object entirely.
- TF->RegisterChecks(*this);
+ BR(mgr, *this), ObjCGCEnabled(gcEnabled) {
if (mgr.shouldEagerlyTrimExplodedGraph()) {
// Enable eager node reclaimation when constructing the ExplodedGraph.
FindBlocks(DC, WL);
}
-static void ActionObjCMemChecker(AnalysisConsumer &C, AnalysisManager& mgr,
- Decl *D);
+static void RunPathSensitiveChecks(AnalysisConsumer &C, AnalysisManager &mgr,
+ Decl *D);
void AnalysisConsumer::HandleCode(Decl *D) {
if ((*WI)->hasBody()) {
checkerMgr->runCheckersOnASTBody(*WI, *Mgr, BR);
if (checkerMgr->hasPathSensitiveCheckers())
- ActionObjCMemChecker(*this, *Mgr, *WI);
+ RunPathSensitiveChecks(*this, *Mgr, *WI);
}
}
// Path-sensitive checking.
//===----------------------------------------------------------------------===//
-static void ActionExprEngine(AnalysisConsumer &C, AnalysisManager& mgr,
- Decl *D,
- TransferFuncs* tf) {
-
- llvm::OwningPtr<TransferFuncs> TF(tf);
-
+static void ActionExprEngine(AnalysisConsumer &C, AnalysisManager &mgr,
+ Decl *D, bool ObjCGCEnabled) {
// Construct the analysis engine. We first query for the LiveVariables
// information to see if the CFG is valid.
// FIXME: Inter-procedural analysis will need to handle invalid CFGs.
if (!mgr.getLiveVariables(D))
return;
- ExprEngine Eng(mgr, TF.take());
+ ExprEngine Eng(mgr, ObjCGCEnabled);
// Set the graph auditor.
llvm::OwningPtr<ExplodedNode::Auditor> Auditor;
Eng.getBugReporter().FlushReports();
}
-static void ActionObjCMemCheckerAux(AnalysisConsumer &C, AnalysisManager& mgr,
- Decl *D, bool GCEnabled) {
-
- TransferFuncs* TF = MakeCFRefCountTF(mgr.getASTContext(),
- GCEnabled,
- mgr.getLangOptions());
-
- ActionExprEngine(C, mgr, D, TF);
-}
-
-static void ActionObjCMemChecker(AnalysisConsumer &C, AnalysisManager& mgr,
- Decl *D) {
-
- switch (mgr.getLangOptions().getGCMode()) {
- default:
- assert (false && "Invalid GC mode.");
- case LangOptions::NonGC:
- ActionObjCMemCheckerAux(C, mgr, D, false);
- break;
-
- case LangOptions::GCOnly:
- ActionObjCMemCheckerAux(C, mgr, D, true);
- break;
-
- case LangOptions::HybridGC:
- ActionObjCMemCheckerAux(C, mgr, D, false);
- ActionObjCMemCheckerAux(C, mgr, D, true);
- break;
- }
+static void RunPathSensitiveChecks(AnalysisConsumer &C, AnalysisManager &mgr,
+ Decl *D) {
+
+ switch (mgr.getLangOptions().getGCMode()) {
+ default:
+ llvm_unreachable("Invalid GC mode.");
+ case LangOptions::NonGC:
+ ActionExprEngine(C, mgr, D, false);
+ break;
+
+ case LangOptions::GCOnly:
+ ActionExprEngine(C, mgr, D, true);
+ break;
+
+ case LangOptions::HybridGC:
+ ActionExprEngine(C, mgr, D, false);
+ ActionExprEngine(C, mgr, D, true);
+ break;
+ }
}
//===----------------------------------------------------------------------===//
-// RUN: %clang_cc1 -analyze -analyzer-checker=core -analyzer-store=region -analyzer-constraints=basic -verify -fobjc-gc %s -Wno-implicit-function-declaration
-// RUN: %clang_cc1 -analyze -analyzer-checker=core -analyzer-store=region -analyzer-constraints=range -verify -fobjc-gc %s -Wno-implicit-function-declaration
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,osx.cocoa.RetainCount -analyzer-store=region -analyzer-constraints=basic -verify -fobjc-gc %s -Wno-implicit-function-declaration
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,osx.cocoa.RetainCount -analyzer-store=region -analyzer-constraints=range -verify -fobjc-gc %s -Wno-implicit-function-declaration
//===----------------------------------------------------------------------===//
// The following code is reduced using delta-debugging from
-// RUN: %clang_cc1 -analyze -analyzer-checker=core,osx.coreFoundation.CFNumber -analyzer-store=region -analyzer-constraints=basic -verify -triple x86_64-apple-darwin9 %s
-// RUN: %clang_cc1 -analyze -analyzer-checker=core,osx.coreFoundation.CFNumber -analyzer-store=region -analyzer-constraints=range -verify -triple x86_64-apple-darwin9 %s
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,osx.coreFoundation.CFNumber,osx.cocoa.RetainCount -analyzer-store=region -analyzer-constraints=basic -verify -triple x86_64-apple-darwin9 %s
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,osx.coreFoundation.CFNumber,osx.cocoa.RetainCount -analyzer-store=region -analyzer-constraints=range -verify -triple x86_64-apple-darwin9 %s
typedef signed long CFIndex;
typedef const struct __CFAllocator * CFAllocatorRef;
-// RUN: %clang_cc1 -analyze -analyzer-checker=core,experimental.core -verify %s -analyzer-constraints=basic -analyzer-store=region
-// RUN: %clang_cc1 -analyze -analyzer-checker=core,experimental.core -verify %s -analyzer-constraints=range -analyzer-store=region
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,osx.cocoa.RetainCount,experimental.core -verify %s -analyzer-constraints=basic -analyzer-store=region
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,osx.cocoa.RetainCount,experimental.core -verify %s -analyzer-constraints=range -analyzer-store=region
typedef struct objc_selector *SEL;
typedef signed char BOOL;
-// RUN: %clang_cc1 -analyze -analyzer-checker=core -analyzer-store=region -analyzer-constraints=basic -verify %s
-// RUN: %clang_cc1 -analyze -analyzer-checker=core -analyzer-store=region -analyzer-constraints=range -verify %s
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,osx.cocoa.RetainCount -analyzer-store=region -analyzer-constraints=basic -verify %s
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,osx.cocoa.RetainCount -analyzer-store=region -analyzer-constraints=range -verify %s
typedef struct CGColorSpace *CGColorSpaceRef;
extern CGColorSpaceRef CGColorSpaceCreateDeviceRGB(void);
-// RUN: %clang_cc1 -analyze -analyzer-checker=core,experimental.core -analyzer-store=region -analyzer-constraints=basic -verify %s
-// RUN: %clang_cc1 -analyze -analyzer-checker=core,experimental.core -analyzer-store=region -analyzer-constraints=range -verify %s
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,osx.cocoa.RetainCount,experimental.core -analyzer-store=region -analyzer-constraints=basic -verify %s
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,osx.cocoa.RetainCount,experimental.core -analyzer-store=region -analyzer-constraints=range -verify %s
// BEGIN delta-debugging reduced header stuff
-// RUN: %clang_cc1 -triple i386-apple-darwin10 -analyze -analyzer-checker=core,osx.cocoa.NilArg,osx.AtomicCAS,experimental.core -analyzer-store=region -analyzer-constraints=basic -verify %s
-// RUN: %clang_cc1 -triple i386-apple-darwin10 -analyze -analyzer-checker=core,osx.cocoa.NilArg,osx.AtomicCAS,experimental.core -analyzer-store=region -analyzer-constraints=range -verify %s
-// RUN: %clang_cc1 -DTEST_64 -triple x86_64-apple-darwin10 -analyze -analyzer-checker=core,osx.cocoa.NilArg,osx.AtomicCAS,experimental.core -analyzer-store=region -analyzer-constraints=basic -verify %s
-// RUN: %clang_cc1 -DTEST_64 -triple x86_64-apple-darwin10 -analyze -analyzer-checker=core,osx.cocoa.NilArg,osx.AtomicCAS,experimental.core -analyzer-store=region -analyzer-constraints=range -verify %s
+// RUN: %clang_cc1 -triple i386-apple-darwin10 -analyze -analyzer-checker=core,osx.cocoa.NilArg,osx.cocoa.RetainCount,osx.AtomicCAS,experimental.core -analyzer-store=region -analyzer-constraints=basic -verify %s
+// RUN: %clang_cc1 -triple i386-apple-darwin10 -analyze -analyzer-checker=core,osx.cocoa.NilArg,osx.cocoa.RetainCount,osx.AtomicCAS,experimental.core -analyzer-store=region -analyzer-constraints=range -verify %s
+// RUN: %clang_cc1 -DTEST_64 -triple x86_64-apple-darwin10 -analyze -analyzer-checker=core,osx.cocoa.NilArg,osx.cocoa.RetainCount,osx.AtomicCAS,experimental.core -analyzer-store=region -analyzer-constraints=basic -verify %s
+// RUN: %clang_cc1 -DTEST_64 -triple x86_64-apple-darwin10 -analyze -analyzer-checker=core,osx.cocoa.NilArg,osx.cocoa.RetainCount,osx.AtomicCAS,experimental.core -analyzer-store=region -analyzer-constraints=range -verify %s
//===----------------------------------------------------------------------===//
-// RUN: %clang_cc1 -analyze -analyzer-checker=core,experimental.core -analyzer-checker=deadcode.DeadStores -analyzer-store=region -analyzer-constraints=basic -verify %s
-// RUN: %clang_cc1 -analyze -analyzer-checker=core,experimental.core -analyzer-checker=deadcode.DeadStores -analyzer-store=region -analyzer-constraints=range -verify %s
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,osx.cocoa.RetainCount,experimental.core,deadcode.DeadStores -analyzer-store=region -analyzer-constraints=basic -verify %s
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,osx.cocoa.RetainCount,experimental.core,deadcode.DeadStores -analyzer-store=region -analyzer-constraints=range -verify %s
// These declarations were reduced using Delta-Debugging from Foundation.h
// on Mac OS X. The test cases are below.
-// RUN: %clang_cc1 -analyze -analyzer-checker=core,experimental.core -analyzer-constraints=range -analyzer-store=region -fobjc-gc -verify %s
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,osx.cocoa.RetainCount,experimental.core -analyzer-constraints=range -analyzer-store=region -fobjc-gc -verify %s
typedef const void * CFTypeRef;
typedef const struct __CFString * CFStringRef;
-// RUN: %clang_cc1 -analyze -analyzer-checker=core,experimental.core -analyzer-store=region -analyzer-constraints=basic -verify %s
-// RUN: %clang_cc1 -analyze -analyzer-checker=core,experimental.core -analyzer-store=region -analyzer-constraints=range -verify %s
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,osx.cocoa.RetainCount,experimental.core -analyzer-store=region -analyzer-constraints=basic -verify %s
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,osx.cocoa.RetainCount,experimental.core -analyzer-store=region -analyzer-constraints=range -verify %s
typedef unsigned char Boolean;
typedef signed long CFIndex;
-// RUN: %clang_cc1 -analyze -analyzer-checker=experimental.core -analyzer-checker=deadcode.DeadStores -verify %s
+// RUN: %clang_cc1 -analyze -analyzer-checker=experimental.core -analyzer-checker=deadcode.DeadStores,osx.cocoa.RetainCount -verify %s
typedef signed char BOOL;
typedef unsigned int NSUInteger;
-// RUN: %clang_cc1 -analyze -analyzer-checker=core -analyzer-store=region -verify %s
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,osx.cocoa.RetainCount -analyzer-store=region -verify %s
//===----------------------------------------------------------------------===//
-// RUN: %clang_cc1 -analyze -analyzer-store=region -analyzer-constraints=range -fblocks -analyzer-opt-analyze-nested-blocks -analyzer-checker=deadcode.IdempotentOperations -verify %s
+// RUN: %clang_cc1 -analyze -analyzer-store=region -analyzer-constraints=range -fblocks -analyzer-opt-analyze-nested-blocks -analyzer-checker=deadcode.IdempotentOperations,osx.cocoa.RetainCount -verify %s
typedef signed char BOOL;
typedef unsigned long NSUInteger;
-// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -analyze -analyzer-checker=core -analyzer-checker=deadcode -analyzer-store=region -verify -fblocks -analyzer-opt-analyze-nested-blocks -fobjc-nonfragile-abi -fobjc-arc %s
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -analyze -analyzer-checker=core,osx.cocoa.RetainCount,deadcode -analyzer-store=region -verify -fblocks -analyzer-opt-analyze-nested-blocks -fobjc-nonfragile-abi -fobjc-arc %s
typedef signed char BOOL;
typedef struct _NSZone NSZone;
-// RUN: %clang_cc1 -analyze -analyzer-checker=core,experimental.core -analyzer-store=region -analyzer-constraints=range -fblocks -analyzer-output=plist -o - %s | FileCheck %s
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,osx.cocoa.RetainCount,experimental.core -analyzer-store=region -analyzer-constraints=range -fblocks -analyzer-output=plist -o - %s | FileCheck %s
void test_null_init(void) {
int *p = 0;
-// RUN: %clang_cc1 -analyze -analyzer-checker=core,experimental.core -pedantic -analyzer-store=region -verify %s
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,osx.cocoa.RetainCount,experimental.core -pedantic -analyzer-store=region -verify %s
// BEGIN delta-debugging reduced header stuff
-// RUN: %clang_cc1 -analyze -analyzer-checker=core -analyzer-store=region -verify %s
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,osx.cocoa.RetainCount -analyzer-store=region -verify %s
typedef signed char BOOL;
typedef unsigned int NSUInteger;
-// RUN: %clang_cc1 -analyze -analyzer-checker=core,experimental.core -analyzer-constraints=basic -analyzer-store=region -verify %s
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,osx.cocoa.RetainCount,experimental.core -analyzer-constraints=basic -analyzer-store=region -verify %s
//
// This test case mainly checks that the retain/release checker doesn't crash
// on this file.
-// RUN: %clang_cc1 -analyze -analyzer-checker=core,experimental.core -analyzer-store=region -verify %s
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,osx.cocoa.RetainCount,experimental.core -analyzer-store=region -verify %s
typedef const struct __CFString * CFStringRef;
typedef const struct __CFAllocator * CFAllocatorRef;
-// RUN: %clang_cc1 -analyze -analyzer-checker=core,osx.cocoa.NSAutoreleasePool -analyzer-store=region -fobjc-gc-only -fblocks -verify %s
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,osx.cocoa.RetainCount,osx.cocoa.NSAutoreleasePool -analyzer-store=region -fobjc-gc-only -fblocks -verify %s
//===----------------------------------------------------------------------===//
// Header stuff.
-// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -analyze -analyzer-checker=core,osx.coreFoundation.CFRetainRelease,osx.cocoa.ClassRelease -analyzer-store=region -analyzer-output=text -fobjc-gc-only -verify %s
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -analyze -analyzer-checker=core,osx.coreFoundation.CFRetainRelease,osx.cocoa.ClassRelease,osx.cocoa.RetainCount -analyzer-store=region -analyzer-output=text -fobjc-gc-only -verify %s
/***
This file is for testing the path-sensitive notes for retain/release errors.
-// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -analyze -analyzer-checker=core,osx.coreFoundation.CFRetainRelease,osx.cocoa.ClassRelease -analyzer-store=region -analyzer-output=text -verify %s
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -analyze -analyzer-checker=core,osx.coreFoundation.CFRetainRelease,osx.cocoa.ClassRelease,osx.cocoa.RetainCount -analyzer-store=region -analyzer-output=text -verify %s
/***
This file is for testing the path-sensitive notes for retain/release errors.
-// RUN: %clang_cc1 -analyze -analyzer-checker=core -analyzer-store=region -analyzer-max-loop 6 -verify %s
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,osx.cocoa.RetainCount -analyzer-store=region -analyzer-max-loop 6 -verify %s
//===----------------------------------------------------------------------===//
// The following code is reduced using delta-debugging from
-// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -analyze -analyzer-checker=core,osx.coreFoundation.CFRetainRelease,osx.cocoa.ClassRelease -analyzer-store=region -fblocks -verify %s
-// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -analyze -analyzer-checker=core,osx.coreFoundation.CFRetainRelease,osx.cocoa.ClassRelease -analyzer-store=region -fblocks -verify -x objective-c++ %s
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -analyze -analyzer-checker=core,osx.coreFoundation.CFRetainRelease,osx.cocoa.ClassRelease,osx.cocoa.RetainCount -analyzer-store=region -fblocks -verify %s
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -analyze -analyzer-checker=core,osx.coreFoundation.CFRetainRelease,osx.cocoa.ClassRelease,osx.cocoa.RetainCount -analyzer-store=region -fblocks -verify -x objective-c++ %s
#if __has_feature(attribute_ns_returns_retained)
#define NS_RETURNS_RETAINED __attribute__((ns_returns_retained))
-// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -analyze -analyzer-checker=core,osx.coreFoundation.CFRetainRelease,osx.cocoa.ClassRelease -analyzer-store=region -fblocks -verify %s
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -analyze -analyzer-checker=core,osx.coreFoundation.CFRetainRelease,osx.cocoa.ClassRelease,osx.cocoa.RetainCount -analyzer-store=region -fblocks -verify %s
#if __has_feature(attribute_ns_returns_retained)
#define NS_RETURNS_RETAINED __attribute__((ns_returns_retained))