diff options
-rw-r--r-- | clang/lib/StaticAnalyzer/Checkers/AllocationDiagnostics.cpp | 24 | ||||
-rw-r--r-- | clang/lib/StaticAnalyzer/Checkers/AllocationDiagnostics.h | 31 | ||||
-rw-r--r-- | clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt | 1 | ||||
-rw-r--r-- | clang/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp | 35 | ||||
-rw-r--r-- | clang/test/Analysis/analyzer-config.c | 3 | ||||
-rw-r--r-- | clang/test/Analysis/analyzer-config.cpp | 3 |
6 files changed, 85 insertions, 12 deletions
diff --git a/clang/lib/StaticAnalyzer/Checkers/AllocationDiagnostics.cpp b/clang/lib/StaticAnalyzer/Checkers/AllocationDiagnostics.cpp new file mode 100644 index 00000000000..3dec8a58c92 --- /dev/null +++ b/clang/lib/StaticAnalyzer/Checkers/AllocationDiagnostics.cpp @@ -0,0 +1,24 @@ +//=- AllocationDiagnostics.cpp - Config options for allocation diags *- C++ -*-// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Declares the configuration functions for leaks/allocation diagnostics. +// +//===-------------------------- + +#include "AllocationDiagnostics.h" + +namespace clang { +namespace ento { + +bool shouldIncludeAllocationSiteInLeakDiagnostics(AnalyzerOptions &AOpts) { + return AOpts.getBooleanOption("leak-diagnostics-reference-allocation", + false); +} + +}} diff --git a/clang/lib/StaticAnalyzer/Checkers/AllocationDiagnostics.h b/clang/lib/StaticAnalyzer/Checkers/AllocationDiagnostics.h new file mode 100644 index 00000000000..2b314a3b749 --- /dev/null +++ b/clang/lib/StaticAnalyzer/Checkers/AllocationDiagnostics.h @@ -0,0 +1,31 @@ +//=--- AllocationDiagnostics.h - Config options for allocation diags *- C++ -*-// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Declares the configuration functions for leaks/allocation diagnostics. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_SA_LIB_CHECKERS_ALLOC_DIAGS_H +#define LLVM_CLANG_SA_LIB_CHECKERS_ALLOC_DIAGS_H + +#include "clang/StaticAnalyzer/Core/AnalyzerOptions.h" + +namespace clang { namespace ento { + +/// \brief Returns true if leak diagnostics should directly reference +/// the allocatin site (where possible). +/// +/// The default is false. +/// +bool shouldIncludeAllocationSiteInLeakDiagnostics(AnalyzerOptions &AOpts); + +}} + +#endif + diff --git a/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt b/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt index a20394d8934..7da68251063 100644 --- a/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt +++ b/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt @@ -4,6 +4,7 @@ clang_tablegen(Checkers.inc -gen-clang-sa-checkers TARGET ClangSACheckers) add_clang_library(clangStaticAnalyzerCheckers + AllocationDiagnostics.cpp AnalyzerStatsChecker.cpp ArrayBoundChecker.cpp ArrayBoundCheckerV2.cpp diff --git a/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp index 156e1f9c3ff..4c630190837 100644 --- a/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp @@ -37,6 +37,8 @@ #include "llvm/ADT/StringExtras.h" #include <cstdarg> +#include "AllocationDiagnostics.h" + using namespace clang; using namespace ento; using llvm::StrInStrNoCase; @@ -1773,11 +1775,11 @@ namespace { class CFRefLeakReport : public CFRefReport { const MemRegion* AllocBinding; - public: CFRefLeakReport(CFRefBug &D, const LangOptions &LOpts, bool GCEnabled, const SummaryLogTy &Log, ExplodedNode *n, SymbolRef sym, - CheckerContext &Ctx); + CheckerContext &Ctx, + bool IncludeAllocationLine); PathDiagnosticLocation getLocation(const SourceManager &SM) const { assert(Location.isValid()); @@ -2323,8 +2325,9 @@ CFRefLeakReportVisitor::getEndPath(BugReporterContext &BRC, CFRefLeakReport::CFRefLeakReport(CFRefBug &D, const LangOptions &LOpts, bool GCEnabled, const SummaryLogTy &Log, ExplodedNode *n, SymbolRef sym, - CheckerContext &Ctx) -: CFRefReport(D, LOpts, GCEnabled, Log, n, sym, false) { + CheckerContext &Ctx, + bool IncludeAllocationLine) + : CFRefReport(D, LOpts, GCEnabled, Log, n, sym, false) { // Most bug reports are cached at the location where they occurred. // With leaks, we want to unique them by the location where they were @@ -2365,9 +2368,13 @@ CFRefLeakReport::CFRefLeakReport(CFRefBug &D, const LangOptions &LOpts, os << "(when using garbage collection) "; os << "of an object"; - // FIXME: AllocBinding doesn't get populated for RegionStore yet. - if (AllocBinding) + if (AllocBinding) { os << " stored into '" << AllocBinding->getString() << '\''; + if (IncludeAllocationLine) { + FullSourceLoc SL(AllocStmt->getLocStart(), Ctx.getSourceManager()); + os << " (allocated on line " << SL.getSpellingLineNumber() << ")"; + } + } addVisitor(new CFRefLeakReportVisitor(sym, GCEnabled, Log)); } @@ -2408,8 +2415,14 @@ class RetainCountChecker mutable SummaryLogTy SummaryLog; mutable bool ShouldResetSummaryLog; + /// Optional setting to indicate if leak reports should include + /// the allocation line. + mutable bool IncludeAllocationLine; + public: - RetainCountChecker() : ShouldResetSummaryLog(false) {} + RetainCountChecker(AnalyzerOptions &AO) + : ShouldResetSummaryLog(false), + IncludeAllocationLine(shouldIncludeAllocationSiteInLeakDiagnostics(AO)) {} virtual ~RetainCountChecker() { DeleteContainerSeconds(DeadSymbolTags); @@ -3354,7 +3367,8 @@ void RetainCountChecker::checkReturnWithRetEffect(const ReturnStmt *S, CFRefReport *report = new CFRefLeakReport(*getLeakAtReturnBug(LOpts, GCEnabled), LOpts, GCEnabled, SummaryLog, - N, Sym, C); + N, Sym, C, IncludeAllocationLine); + C.emitReport(report); } } @@ -3594,7 +3608,8 @@ RetainCountChecker::processLeaks(ProgramStateRef state, assert(BT && "BugType not initialized."); CFRefLeakReport *report = new CFRefLeakReport(*BT, LOpts, GCEnabled, - SummaryLog, N, *I, Ctx); + SummaryLog, N, *I, Ctx, + IncludeAllocationLine); Ctx.emitReport(report); } } @@ -3716,6 +3731,6 @@ void RetainCountChecker::printState(raw_ostream &Out, ProgramStateRef State, //===----------------------------------------------------------------------===// void ento::registerRetainCountChecker(CheckerManager &Mgr) { - Mgr.registerChecker<RetainCountChecker>(); + Mgr.registerChecker<RetainCountChecker>(Mgr.getAnalyzerOptions()); } diff --git a/clang/test/Analysis/analyzer-config.c b/clang/test/Analysis/analyzer-config.c index 96b948352b3..2a3d645ffdf 100644 --- a/clang/test/Analysis/analyzer-config.c +++ b/clang/test/Analysis/analyzer-config.c @@ -11,10 +11,11 @@ void foo() { bar(); } // CHECK-NEXT: graph-trim-interval = 1000 // CHECK-NEXT: ipa = dynamic-bifurcate // CHECK-NEXT: ipa-always-inline-size = 3 +// CHECK-NEXT: leak-diagnostics-reference-allocation = false // CHECK-NEXT: max-inlinable-size = 50 // CHECK-NEXT: max-nodes = 150000 // CHECK-NEXT: max-times-inline-large = 32 // CHECK-NEXT: mode = deep // CHECK-NEXT: [stats] -// CHECK-NEXT: num-entries = 10 +// CHECK-NEXT: num-entries = 11 diff --git a/clang/test/Analysis/analyzer-config.cpp b/clang/test/Analysis/analyzer-config.cpp index 1224204f8c7..1ba59184d80 100644 --- a/clang/test/Analysis/analyzer-config.cpp +++ b/clang/test/Analysis/analyzer-config.cpp @@ -21,9 +21,10 @@ public: // CHECK-NEXT: graph-trim-interval = 1000 // CHECK-NEXT: ipa = dynamic-bifurcate // CHECK-NEXT: ipa-always-inline-size = 3 +// CHECK-NEXT: leak-diagnostics-reference-allocation = false // CHECK-NEXT: max-inlinable-size = 50 // CHECK-NEXT: max-nodes = 150000 // CHECK-NEXT: max-times-inline-large = 32 // CHECK-NEXT: mode = deep // CHECK-NEXT: [stats] -// CHECK-NEXT: num-entries = 14 +// CHECK-NEXT: num-entries = 15 |