From 17a38e2636a8b1ce473fc6504c4b16cb09db29f4 Mon Sep 17 00:00:00 2001 From: Jordy Rose Date: Fri, 2 Sep 2011 05:55:19 +0000 Subject: [PATCH] [analyzer] Move the knowledge of whether or not GC is enabled for the current analysis from CFRefCount to ExprEngine. Remove TransferFuncs from ExprEngine and AnalysisConsumer. Demote RetainReleaseChecker to a regular checker, and give it the name osx.cocoa.RetainCount (class name change coming shortly). Update tests accordingly. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@138998 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../Core/PathSensitive/CheckerContext.h | 4 + .../Core/PathSensitive/ExprEngine.h | 12 +- lib/StaticAnalyzer/Checkers/Checkers.td | 4 + lib/StaticAnalyzer/Core/CFRefCount.cpp | 173 +++++++++--------- lib/StaticAnalyzer/Core/ExprEngine.cpp | 7 +- .../Frontend/AnalysisConsumer.cpp | 62 +++---- test/Analysis/CFDateGC.m | 4 +- test/Analysis/CFNumber.c | 4 +- .../CFRetainRelease_NSAssertionHandler.m | 4 +- test/Analysis/CGColorSpace.c | 4 +- test/Analysis/NSPanel.m | 4 +- test/Analysis/NSString.m | 8 +- test/Analysis/NSWindow.m | 4 +- test/Analysis/PR2599.m | 2 +- test/Analysis/cfref_PR2519.c | 4 +- test/Analysis/dead-stores.m | 2 +- test/Analysis/delegates.m | 2 +- test/Analysis/idempotent-operations.m | 2 +- test/Analysis/objc-arc.m | 2 +- test/Analysis/plist-output-alternate.m | 2 +- test/Analysis/pr_2542_rdar_6793404.m | 2 +- test/Analysis/properties.m | 2 +- test/Analysis/rdar-6562655.m | 2 +- test/Analysis/refcnt_naming.m | 2 +- test/Analysis/retain-release-gc-only.m | 2 +- test/Analysis/retain-release-path-notes-gc.m | 2 +- test/Analysis/retain-release-path-notes.m | 2 +- test/Analysis/retain-release-region-store.m | 2 +- test/Analysis/retain-release.m | 4 +- test/Analysis/retain-release.mm | 2 +- 30 files changed, 161 insertions(+), 171 deletions(-) diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h b/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h index 968b742400..cdd72880a4 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h @@ -103,6 +103,10 @@ public: 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, diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h index 2c0a935a02..503700dc37 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h @@ -74,16 +74,17 @@ class ExprEngine : public SubEngine { // 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 TF; public: - ExprEngine(AnalysisManager &mgr, TransferFuncs *tf); + ExprEngine(AnalysisManager &mgr, bool gcEnabled); ~ExprEngine(); @@ -111,14 +112,11 @@ public: 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. diff --git a/lib/StaticAnalyzer/Checkers/Checkers.td b/lib/StaticAnalyzer/Checkers/Checkers.td index 5c21519444..d53e0b887e 100644 --- a/lib/StaticAnalyzer/Checkers/Checkers.td +++ b/lib/StaticAnalyzer/Checkers/Checkers.td @@ -311,6 +311,10 @@ def NSErrorChecker : Checker<"NSError">, 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 { diff --git a/lib/StaticAnalyzer/Core/CFRefCount.cpp b/lib/StaticAnalyzer/Core/CFRefCount.cpp index a38c450148..7a1c73f03d 100644 --- a/lib/StaticAnalyzer/Core/CFRefCount.cpp +++ b/lib/StaticAnalyzer/Core/CFRefCount.cpp @@ -2357,11 +2357,8 @@ class RetainReleaseChecker mutable SummaryLogTy SummaryLog; mutable bool ShouldResetSummaryLog; - LangOptions::GCMode GCMode; - public: - RetainReleaseChecker() - : ShouldResetSummaryLog(false), GCMode(LangOptions::HybridGC) {} + RetainReleaseChecker() : ShouldResetSummaryLog(false) {} virtual ~RetainReleaseChecker() { DeleteContainerSeconds(DeadSymbolTags); @@ -2403,41 +2400,17 @@ public: 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 " @@ -2447,19 +2420,19 @@ public: 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")); @@ -2467,26 +2440,34 @@ public: 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; @@ -2524,8 +2505,8 @@ public: 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, @@ -2730,7 +2711,7 @@ void RetainReleaseChecker::checkPostStmt(const CastExpr *CE, 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? @@ -2748,7 +2729,7 @@ void RetainReleaseChecker::checkPostStmt(const CallExpr *CE, 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 @@ -2776,7 +2757,7 @@ void RetainReleaseChecker::checkPostStmt(const CXXConstructExpr *CE, 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. @@ -2792,7 +2773,7 @@ void RetainReleaseChecker::checkPostObjCMessage(const ObjCMessage &Msg, const ProgramState *state = C.getState(); ExplodedNode *Pred = C.getPredecessor(); - RetainSummaryManager &Summaries = getSummaryManager(C.getASTContext()); + RetainSummaryManager &Summaries = getSummaryManager(C); RetainSummary *Summ; if (Msg.isInstanceMessage()) { @@ -2824,7 +2805,7 @@ void RetainReleaseChecker::checkSummary(const RetainSummary &Summ, if (SymbolRef Sym = V.getAsLocSymbol()) { if (RefBindings::data_type *T = state->get(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; @@ -2842,7 +2823,8 @@ void RetainReleaseChecker::checkSummary(const RetainSummary &Summ, if (SymbolRef Sym = Receiver.getAsLocSymbol()) { if (const RefVal *T = state->get(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; @@ -2862,7 +2844,7 @@ void RetainReleaseChecker::checkSummary(const RetainSummary &Summ, if (RE.getKind() == RetEffect::OwnedWhenTrackedReceiver) { if (ReceiverIsTracked) - RE = getSummaryManager(C.getASTContext()).getObjAllocRetEffect(); + RE = getSummaryManager(C).getObjAllocRetEffect(); else RE = RetEffect::MakeNoRet(); } @@ -2940,21 +2922,24 @@ void RetainReleaseChecker::checkSummary(const RetainSummary &Summ, 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(sym, V); @@ -2969,7 +2954,7 @@ RetainReleaseChecker::updateSymbol(const ProgramState *state, SymbolRef sym, case Dealloc: // Any use of -dealloc in GC is *bad*. - if (isGCEnabled()) { + if (C.isObjCGCEnabled()) { V = V ^ RefVal::ErrorDeallocGC; hasErr = V.getKind(); break; @@ -2992,7 +2977,7 @@ RetainReleaseChecker::updateSymbol(const ProgramState *state, SymbolRef sym, break; case NewAutoreleasePool: - assert(!isGCEnabled()); + assert(!C.isObjCGCEnabled()); return state->add(sym); case MayEscape: @@ -3007,7 +2992,7 @@ RetainReleaseChecker::updateSymbol(const ProgramState *state, SymbolRef sym, return state; case Autorelease: - if (isGCEnabled()) + if (C.isObjCGCEnabled()) return state; // Update the autorelease counts. @@ -3029,7 +3014,7 @@ RetainReleaseChecker::updateSymbol(const ProgramState *state, SymbolRef sym, break; case RefVal::Released: // Non-GC cases are handled above. - assert(isGCEnabled()); + assert(C.isObjCGCEnabled()); V = (V ^ RefVal::Owned) + 1; break; } @@ -3065,7 +3050,7 @@ RetainReleaseChecker::updateSymbol(const ProgramState *state, SymbolRef sym, case RefVal::Released: // Non-GC cases are handled above. - assert(isGCEnabled()); + assert(C.isObjCGCEnabled()); V = V ^ RefVal::ErrorUseAfterRelease; hasErr = V.getKind(); break; @@ -3113,7 +3098,8 @@ void RetainReleaseChecker::processNonLeakError(const ProgramState *St, 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); } @@ -3271,7 +3257,7 @@ void RetainReleaseChecker::checkPreStmt(const ReturnStmt *S, 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(CD)) { @@ -3301,7 +3287,7 @@ void RetainReleaseChecker::checkReturnWithRetEffect(const ReturnStmt *S, 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 @@ -3327,11 +3313,12 @@ void RetainReleaseChecker::checkReturnWithRetEffect(const ReturnStmt *S, 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); } } @@ -3353,8 +3340,8 @@ void RetainReleaseChecker::checkReturnWithRetEffect(const ReturnStmt *S, CFRefReport *report = new CFRefReport(*returnNotOwnedForOwned, - C.getASTContext().getLangOptions(), isGCEnabled(), - SummaryLog, N, Sym); + C.getASTContext().getLangOptions(), + C.isObjCGCEnabled(), SummaryLog, N, Sym); C.EmitReport(report); } } @@ -3377,7 +3364,7 @@ RetainReleaseChecker::handleAutoreleaseCounts(const ProgramState *state, 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. @@ -3465,13 +3452,13 @@ RetainReleaseChecker::processLeaks(const ProgramState *state, for (SmallVectorImpl::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); } @@ -3638,10 +3625,24 @@ void CFRefCount::RegisterChecks(ExprEngine& Eng) { RetainReleaseChecker *checker = Eng.getCheckerManager().registerChecker(); 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(); +} + diff --git a/lib/StaticAnalyzer/Core/ExprEngine.cpp b/lib/StaticAnalyzer/Core/ExprEngine.cpp index 9dd2884578..8b03ae223a 100644 --- a/lib/StaticAnalyzer/Core/ExprEngine.cpp +++ b/lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -50,7 +50,7 @@ static inline Selector GetNullarySelector(const char* name, ASTContext &Ctx) { // Engine construction and deletion. //===----------------------------------------------------------------------===// -ExprEngine::ExprEngine(AnalysisManager &mgr, TransferFuncs *tf) +ExprEngine::ExprEngine(AnalysisManager &mgr, bool gcEnabled) : AMgr(mgr), Engine(*this), G(Engine.getGraph()), @@ -63,10 +63,7 @@ ExprEngine::ExprEngine(AnalysisManager &mgr, TransferFuncs *tf) 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. diff --git a/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp b/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp index 4b5a8824ec..7f553412a8 100644 --- a/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp +++ b/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp @@ -262,8 +262,8 @@ static void FindBlocks(DeclContext *D, SmallVectorImpl &WL) { 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) { @@ -295,7 +295,7 @@ void AnalysisConsumer::HandleCode(Decl *D) { if ((*WI)->hasBody()) { checkerMgr->runCheckersOnASTBody(*WI, *Mgr, BR); if (checkerMgr->hasPathSensitiveCheckers()) - ActionObjCMemChecker(*this, *Mgr, *WI); + RunPathSensitiveChecks(*this, *Mgr, *WI); } } @@ -303,18 +303,14 @@ void AnalysisConsumer::HandleCode(Decl *D) { // Path-sensitive checking. //===----------------------------------------------------------------------===// -static void ActionExprEngine(AnalysisConsumer &C, AnalysisManager& mgr, - Decl *D, - TransferFuncs* tf) { - - llvm::OwningPtr 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 Auditor; @@ -338,35 +334,25 @@ static void ActionExprEngine(AnalysisConsumer &C, AnalysisManager& mgr, Eng.getBugReporter().FlushReports(); } -static void ActionObjCMemCheckerAux(AnalysisConsumer &C, AnalysisManager& mgr, - Decl *D, bool GCEnabled) { +static void RunPathSensitiveChecks(AnalysisConsumer &C, AnalysisManager &mgr, + Decl *D) { - 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; - } + 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; + } } //===----------------------------------------------------------------------===// diff --git a/test/Analysis/CFDateGC.m b/test/Analysis/CFDateGC.m index 770a0e0276..69b99f052b 100644 --- a/test/Analysis/CFDateGC.m +++ b/test/Analysis/CFDateGC.m @@ -1,5 +1,5 @@ -// 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 diff --git a/test/Analysis/CFNumber.c b/test/Analysis/CFNumber.c index 76c6bc6eb9..fbbe4d15f4 100644 --- a/test/Analysis/CFNumber.c +++ b/test/Analysis/CFNumber.c @@ -1,5 +1,5 @@ -// 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; diff --git a/test/Analysis/CFRetainRelease_NSAssertionHandler.m b/test/Analysis/CFRetainRelease_NSAssertionHandler.m index 35461dd0db..e0c9be1c1e 100644 --- a/test/Analysis/CFRetainRelease_NSAssertionHandler.m +++ b/test/Analysis/CFRetainRelease_NSAssertionHandler.m @@ -1,5 +1,5 @@ -// 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; diff --git a/test/Analysis/CGColorSpace.c b/test/Analysis/CGColorSpace.c index 4c6a03bf97..1bd20fa1cf 100644 --- a/test/Analysis/CGColorSpace.c +++ b/test/Analysis/CGColorSpace.c @@ -1,5 +1,5 @@ -// 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); diff --git a/test/Analysis/NSPanel.m b/test/Analysis/NSPanel.m index d8058c0471..ac72571645 100644 --- a/test/Analysis/NSPanel.m +++ b/test/Analysis/NSPanel.m @@ -1,5 +1,5 @@ -// 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 diff --git a/test/Analysis/NSString.m b/test/Analysis/NSString.m index c715f1bae9..48450daa01 100644 --- a/test/Analysis/NSString.m +++ b/test/Analysis/NSString.m @@ -1,7 +1,7 @@ -// 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 //===----------------------------------------------------------------------===// diff --git a/test/Analysis/NSWindow.m b/test/Analysis/NSWindow.m index 66fb002773..495f8e19d8 100644 --- a/test/Analysis/NSWindow.m +++ b/test/Analysis/NSWindow.m @@ -1,5 +1,5 @@ -// 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. diff --git a/test/Analysis/PR2599.m b/test/Analysis/PR2599.m index 90c88ac11c..5436063738 100644 --- a/test/Analysis/PR2599.m +++ b/test/Analysis/PR2599.m @@ -1,4 +1,4 @@ -// 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; diff --git a/test/Analysis/cfref_PR2519.c b/test/Analysis/cfref_PR2519.c index dc760d97b2..5292109869 100644 --- a/test/Analysis/cfref_PR2519.c +++ b/test/Analysis/cfref_PR2519.c @@ -1,5 +1,5 @@ -// 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; diff --git a/test/Analysis/dead-stores.m b/test/Analysis/dead-stores.m index 51b5858a62..4ed71c4e8b 100644 --- a/test/Analysis/dead-stores.m +++ b/test/Analysis/dead-stores.m @@ -1,4 +1,4 @@ -// 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; diff --git a/test/Analysis/delegates.m b/test/Analysis/delegates.m index d15a9aeaf9..8f42b83b0e 100644 --- a/test/Analysis/delegates.m +++ b/test/Analysis/delegates.m @@ -1,4 +1,4 @@ -// 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 //===----------------------------------------------------------------------===// diff --git a/test/Analysis/idempotent-operations.m b/test/Analysis/idempotent-operations.m index 8f534940c9..b4765082d8 100644 --- a/test/Analysis/idempotent-operations.m +++ b/test/Analysis/idempotent-operations.m @@ -1,4 +1,4 @@ -// 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; diff --git a/test/Analysis/objc-arc.m b/test/Analysis/objc-arc.m index 8e18877f29..507deadaef 100644 --- a/test/Analysis/objc-arc.m +++ b/test/Analysis/objc-arc.m @@ -1,4 +1,4 @@ -// 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; diff --git a/test/Analysis/plist-output-alternate.m b/test/Analysis/plist-output-alternate.m index 8343d47618..67135fac36 100644 --- a/test/Analysis/plist-output-alternate.m +++ b/test/Analysis/plist-output-alternate.m @@ -1,4 +1,4 @@ -// 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; diff --git a/test/Analysis/pr_2542_rdar_6793404.m b/test/Analysis/pr_2542_rdar_6793404.m index 69068615ca..d5125a649d 100644 --- a/test/Analysis/pr_2542_rdar_6793404.m +++ b/test/Analysis/pr_2542_rdar_6793404.m @@ -1,4 +1,4 @@ -// 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 diff --git a/test/Analysis/properties.m b/test/Analysis/properties.m index ad9db1ad68..6d04a4ab4e 100644 --- a/test/Analysis/properties.m +++ b/test/Analysis/properties.m @@ -1,4 +1,4 @@ -// 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; diff --git a/test/Analysis/rdar-6562655.m b/test/Analysis/rdar-6562655.m index 62626882aa..3a592730a8 100644 --- a/test/Analysis/rdar-6562655.m +++ b/test/Analysis/rdar-6562655.m @@ -1,4 +1,4 @@ -// 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. diff --git a/test/Analysis/refcnt_naming.m b/test/Analysis/refcnt_naming.m index da29b1876f..aff713be49 100644 --- a/test/Analysis/refcnt_naming.m +++ b/test/Analysis/refcnt_naming.m @@ -1,4 +1,4 @@ -// 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; diff --git a/test/Analysis/retain-release-gc-only.m b/test/Analysis/retain-release-gc-only.m index b43b5238f7..4e1b8466c3 100644 --- a/test/Analysis/retain-release-gc-only.m +++ b/test/Analysis/retain-release-gc-only.m @@ -1,4 +1,4 @@ -// 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. diff --git a/test/Analysis/retain-release-path-notes-gc.m b/test/Analysis/retain-release-path-notes-gc.m index a489745af2..19e6d7b8b3 100644 --- a/test/Analysis/retain-release-path-notes-gc.m +++ b/test/Analysis/retain-release-path-notes-gc.m @@ -1,4 +1,4 @@ -// 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. diff --git a/test/Analysis/retain-release-path-notes.m b/test/Analysis/retain-release-path-notes.m index 3c9e54bb8a..e34942a896 100644 --- a/test/Analysis/retain-release-path-notes.m +++ b/test/Analysis/retain-release-path-notes.m @@ -1,4 +1,4 @@ -// 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. diff --git a/test/Analysis/retain-release-region-store.m b/test/Analysis/retain-release-region-store.m index ac2362a4a7..89950ce7cd 100644 --- a/test/Analysis/retain-release-region-store.m +++ b/test/Analysis/retain-release-region-store.m @@ -1,4 +1,4 @@ -// 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 diff --git a/test/Analysis/retain-release.m b/test/Analysis/retain-release.m index e2ff5c9759..1e50e1ed59 100644 --- a/test/Analysis/retain-release.m +++ b/test/Analysis/retain-release.m @@ -1,5 +1,5 @@ -// 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)) diff --git a/test/Analysis/retain-release.mm b/test/Analysis/retain-release.mm index bdc3dc0396..7c6f9e3c4a 100644 --- a/test/Analysis/retain-release.mm +++ b/test/Analysis/retain-release.mm @@ -1,4 +1,4 @@ -// 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))