diff options
| author | George Karpenkov <ekarpenkov@apple.com> | 2019-01-29 19:29:59 +0000 |
|---|---|---|
| committer | George Karpenkov <ekarpenkov@apple.com> | 2019-01-29 19:29:59 +0000 |
| commit | d37ff4e888729c807fc4b9e8d2cac0846c5dcf73 (patch) | |
| tree | e3dcac2b9b1f7f0f971474fa94ae95fb9685b424 /clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountDiagnostics.cpp | |
| parent | b0fc58b57c577841ede11f534768f5acf675175c (diff) | |
| download | bcm5719-llvm-d37ff4e888729c807fc4b9e8d2cac0846c5dcf73.tar.gz bcm5719-llvm-d37ff4e888729c807fc4b9e8d2cac0846c5dcf73.zip | |
[analyzer] [RetainCountChecker] Track input parameters to the top-level function
Track them for ISL/OS objects by default, and for NS/CF under a flag.
rdar://47536377
Differential Revision: https://reviews.llvm.org/D57356
llvm-svn: 352534
Diffstat (limited to 'clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountDiagnostics.cpp')
| -rw-r--r-- | clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountDiagnostics.cpp | 54 |
1 files changed, 49 insertions, 5 deletions
diff --git a/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountDiagnostics.cpp b/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountDiagnostics.cpp index dcb5ca85558..8e13ee35f3c 100644 --- a/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountDiagnostics.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountDiagnostics.cpp @@ -418,6 +418,38 @@ annotateConsumedSummaryMismatch(const ExplodedNode *N, return std::make_shared<PathDiagnosticEventPiece>(L, os.str()); } +/// Annotate the parameter at the analysis entry point. +static std::shared_ptr<PathDiagnosticEventPiece> +annotateStartParameter(const ExplodedNode *N, SymbolRef Sym, + const SourceManager &SM) { + auto PP = N->getLocationAs<BlockEdge>(); + if (!PP) + return nullptr; + + const CFGBlock *Src = PP->getSrc(); + const RefVal *CurrT = getRefBinding(N->getState(), Sym); + + if (&Src->getParent()->getEntry() != Src || !CurrT || + getRefBinding(N->getFirstPred()->getState(), Sym)) + return nullptr; + + const auto *VR = cast<VarRegion>(cast<SymbolRegionValue>(Sym)->getRegion()); + const auto *PVD = cast<ParmVarDecl>(VR->getDecl()); + PathDiagnosticLocation L = PathDiagnosticLocation(PVD, SM); + + std::string s; + llvm::raw_string_ostream os(s); + os << "Parameter '" << PVD->getNameAsString() + << "' starts at +"; + if (CurrT->getCount() == 1) { + os << "1, as it is marked as consuming"; + } else { + assert(CurrT->getCount() == 0); + os << "0"; + } + return std::make_shared<PathDiagnosticEventPiece>(L, os.str()); +} + std::shared_ptr<PathDiagnosticPiece> RefCountReportVisitor::VisitNode(const ExplodedNode *N, BugReporterContext &BRC, BugReport &BR) { @@ -435,6 +467,9 @@ RefCountReportVisitor::VisitNode(const ExplodedNode *N, if (auto PD = annotateConsumedSummaryMismatch(N, *CE, SM, CEMgr)) return PD; + if (auto PD = annotateStartParameter(N, Sym, SM)) + return PD; + // FIXME: We will eventually need to handle non-statement-based events // (__attribute__((cleanup))). if (!N->getLocation().getAs<StmtPoint>()) @@ -673,7 +708,7 @@ static AllocationInfo GetAllocationSite(ProgramStateManager &StateMgr, if (AllocationNodeInCurrentOrParentContext && AllocationNodeInCurrentOrParentContext->getLocationContext() != - LeakContext) + LeakContext) FirstBinding = nullptr; return AllocationInfo(AllocationNodeInCurrentOrParentContext, @@ -757,10 +792,19 @@ RefLeakReportVisitor::getEndPath(BugReporterContext &BRC, } } else { const FunctionDecl *FD = cast<FunctionDecl>(D); - os << "whose name ('" << *FD - << "') does not contain 'Copy' or 'Create'. This violates the naming" - " convention rules given in the Memory Management Guide for Core" - " Foundation"; + ObjKind K = RV->getObjKind(); + if (K == ObjKind::ObjC || K == ObjKind::CF) { + os << "whose name ('" << *FD + << "') does not contain 'Copy' or 'Create'. This violates the " + "naming" + " convention rules given in the Memory Management Guide for " + "Core" + " Foundation"; + } else if (RV->getObjKind() == ObjKind::OS) { + std::string FuncName = FD->getNameAsString(); + os << "whose name ('" << FuncName + << "') starts with '" << StringRef(FuncName).substr(0, 3) << "'"; + } } } } else { |

