diff options
Diffstat (limited to 'clang/lib/StaticAnalyzer/Checkers')
3 files changed, 41 insertions, 14 deletions
diff --git a/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.cpp index 30d4dd1bd8a..2b39ad6fa65 100644 --- a/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.cpp @@ -418,13 +418,18 @@ void RetainCountChecker::processSummaryOfInlined(const RetainSummary &Summ, } // Consult the summary for the return value. + SymbolRef Sym = CallOrMsg.getReturnValue().getAsSymbol(); RetEffect RE = Summ.getRetEffect(); - if (RE.getKind() == RetEffect::NoRetHard) { - SymbolRef Sym = CallOrMsg.getReturnValue().getAsSymbol(); - if (Sym) - state = removeRefBinding(state, Sym); + if (const auto *MCall = dyn_cast<CXXMemberCall>(&CallOrMsg)) { + if (Optional<RefVal> updatedRefVal = + refValFromRetEffect(RE, MCall->getResultType())) { + state = setRefBinding(state, Sym, *updatedRefVal); + } } + if (RE.getKind() == RetEffect::NoRetHard && Sym) + state = removeRefBinding(state, Sym); + C.addTransition(state); } @@ -490,11 +495,10 @@ void RetainCountChecker::checkSummary(const RetainSummary &Summ, } } - // Evaluate the effect on the message receiver. + // Evaluate the effect on the message receiver / `this` argument. bool ReceiverIsTracked = false; if (!hasErr) { - const ObjCMethodCall *MsgInvocation = dyn_cast<ObjCMethodCall>(&CallOrMsg); - if (MsgInvocation) { + if (const auto *MsgInvocation = dyn_cast<ObjCMethodCall>(&CallOrMsg)) { if (SymbolRef Sym = MsgInvocation->getReceiverSVal().getAsLocSymbol()) { if (const RefVal *T = getRefBinding(state, Sym)) { ReceiverIsTracked = true; @@ -506,6 +510,17 @@ void RetainCountChecker::checkSummary(const RetainSummary &Summ, } } } + } else if (const auto *MCall = dyn_cast<CXXMemberCall>(&CallOrMsg)) { + if (SymbolRef Sym = MCall->getCXXThisVal().getAsLocSymbol()) { + if (const RefVal *T = getRefBinding(state, Sym)) { + state = updateSymbol(state, Sym, *T, Summ.getThisEffect(), + hasErr, C); + if (hasErr) { + ErrorRange = MCall->getOriginExpr()->getSourceRange(); + ErrorSym = Sym; + } + } + } } } diff --git a/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.h b/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.h index 6bd5379e5f4..8683b23dd96 100644 --- a/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.h +++ b/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.h @@ -98,7 +98,7 @@ private: /// The kind of object being tracked (CF or ObjC), if known. /// /// See the RetEffect::ObjKind enum for possible values. - unsigned RawObjectKind : 2; + unsigned RawObjectKind : 3; /// True if the current state and/or retain count may turn out to not be the /// best possible approximation of the reference counting state. @@ -268,6 +268,8 @@ class RetainCountChecker mutable std::unique_ptr<RetainSummaryManager> Summaries; mutable SummaryLogTy SummaryLog; + + AnalyzerOptions &Options; mutable bool ShouldResetSummaryLog; /// Optional setting to indicate if leak reports should include @@ -275,12 +277,17 @@ class RetainCountChecker mutable bool IncludeAllocationLine; public: - RetainCountChecker(AnalyzerOptions &AO) - : ShouldResetSummaryLog(false), - IncludeAllocationLine(shouldIncludeAllocationSiteInLeakDiagnostics(AO)) {} + RetainCountChecker(AnalyzerOptions &Options) + : Options(Options), ShouldResetSummaryLog(false), + IncludeAllocationLine( + shouldIncludeAllocationSiteInLeakDiagnostics(Options)) {} ~RetainCountChecker() override { DeleteContainerSeconds(DeadSymbolTags); } + bool shouldCheckOSObjectRetainCount() const { + return Options.getBooleanOption("CheckOSObject", false, this); + } + void checkEndAnalysis(ExplodedGraph &G, BugReporter &BR, ExprEngine &Eng) const { // FIXME: This is a hack to make sure the summary log gets cleared between @@ -333,10 +340,12 @@ public: // 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.getLangOpts().ObjCAutoRefCount; - if (!Summaries) - Summaries.reset(new RetainSummaryManager(Ctx, ARCEnabled)); - else + if (!Summaries) { + Summaries.reset(new RetainSummaryManager( + Ctx, ARCEnabled, shouldCheckOSObjectRetainCount())); + } else { assert(Summaries->isARCEnabled() == ARCEnabled); + } return *Summaries; } diff --git a/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountDiagnostics.cpp b/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountDiagnostics.cpp index ef03470f908..2d41c4526fb 100644 --- a/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountDiagnostics.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountDiagnostics.cpp @@ -120,6 +120,9 @@ CFRefReportVisitor::VisitNode(const ExplodedNode *N, const ExplodedNode *PrevN, if (CurrV.getObjKind() == RetEffect::CF) { os << " returns a Core Foundation object of type " << Sym->getType().getAsString() << " with a "; + } else if (CurrV.getObjKind() == RetEffect::OS) { + os << " returns an OSObject of type " + << Sym->getType().getAsString() << " with a "; } else if (CurrV.getObjKind() == RetEffect::Generalized) { os << " returns an object of type " << Sym->getType().getAsString() << " with a "; |