summaryrefslogtreecommitdiffstats
path: root/clang/lib/StaticAnalyzer/Checkers
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/StaticAnalyzer/Checkers')
-rw-r--r--clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.cpp29
-rw-r--r--clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.h23
-rw-r--r--clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountDiagnostics.cpp3
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 ";
OpenPOWER on IntegriCloud