Index: docs/analyzer/developer-docs/DebugChecks.rst =================================================================== --- docs/analyzer/developer-docs/DebugChecks.rst +++ docs/analyzer/developer-docs/DebugChecks.rst @@ -285,3 +285,10 @@ statistics within the analyzer engine. Note the Stats checker (which produces at least one bug report per function) may actually change the values reported by -analyzer-stats. + +Output testing checkers +======================= + +- debug.ReportStmts reports a warning at **every** statement, making it a very + useful tool for testing thoroughly bug report construction and output + emission. Index: include/clang/StaticAnalyzer/Checkers/Checkers.td =================================================================== --- include/clang/StaticAnalyzer/Checkers/Checkers.td +++ include/clang/StaticAnalyzer/Checkers/Checkers.td @@ -1019,6 +1019,10 @@ HelpText<"View Exploded Graphs using GraphViz">, Documentation; +def ReportStmts : Checker<"ReportStmts">, + HelpText<"Emits a warning for every statement.">, + Documentation; + } // end "debug" Index: lib/StaticAnalyzer/Checkers/DebugCheckers.cpp =================================================================== --- lib/StaticAnalyzer/Checkers/DebugCheckers.cpp +++ lib/StaticAnalyzer/Checkers/DebugCheckers.cpp @@ -266,3 +266,34 @@ bool ento::shouldRegisterExplodedGraphViewer(const LangOptions &LO) { return true; } + +//===----------------------------------------------------------------------===// +// Emits a report for every Stmt that the analyzer visits. +//===----------------------------------------------------------------------===// + +namespace { + +class ReportStmts : public Checker> { + BuiltinBug BT_stmtLoc{this, "Statement"}; + +public: + void checkPreStmt(const Stmt *S, CheckerContext &C) const { + ExplodedNode *Node = C.generateNonFatalErrorNode(); + if (!Node) + return; + + auto Report = llvm::make_unique(BT_stmtLoc, "Statement", Node); + + C.emitReport(std::move(Report)); + } +}; + +} // end of anonymous namespace + +void ento::registerReportStmts(CheckerManager &mgr) { + mgr.registerChecker(); +} + +bool ento::shouldRegisterReportStmts(const LangOptions &LO) { + return true; +} Index: lib/StaticAnalyzer/Core/PathDiagnostic.cpp =================================================================== --- lib/StaticAnalyzer/Core/PathDiagnostic.cpp +++ lib/StaticAnalyzer/Core/PathDiagnostic.cpp @@ -571,6 +571,8 @@ } while (!L.isValid()); } + // FIXME: Ironically, this assert actually fails in some cases. + //assert(L.isValid()); return L; } @@ -671,7 +673,15 @@ PathDiagnosticLocation PathDiagnosticLocation::createMemberLoc(const MemberExpr *ME, const SourceManager &SM) { - return PathDiagnosticLocation(ME->getMemberLoc(), SM, SingleLocK); + + assert(ME->getMemberLoc().isValid() || ME->getBeginLoc().isValid()); + + // In some cases, getMemberLoc isn't valid -- in this case we'll return with + // some other related valid SourceLocation. + if (ME->getMemberLoc().isValid()) + return PathDiagnosticLocation(ME->getMemberLoc(), SM, SingleLocK); + + return PathDiagnosticLocation(ME->getBeginLoc(), SM, SingleLocK); } PathDiagnosticLocation Index: test/Analysis/diagnostics/invalid-srcloc-fix.cpp =================================================================== --- /dev/null +++ test/Analysis/diagnostics/invalid-srcloc-fix.cpp @@ -0,0 +1,12 @@ +// RUN: %clang_analyze_cc1 -verify %s \ +// RUN: -analyzer-output=plist -o %t.plist \ +// RUN: -analyzer-checker=core \ +// RUN: -analyzer-checker=debug.ReportStmts + +struct h { + operator int(); +}; + +int k() { + return h(); // expected-warning 3 {{Statement}} +} Index: test/Analysis/plist-html-macros.c =================================================================== --- test/Analysis/plist-html-macros.c +++ test/Analysis/plist-html-macros.c @@ -3,7 +3,10 @@ // RUN: rm -rf %t.dir // RUN: mkdir -p %t.dir -// RUN: %clang_analyze_cc1 -analyzer-checker=core -analyzer-output=plist-html -o %t.dir/index.plist %s +// +// RUN: %clang_analyze_cc1 -o %t.dir/index.plist %s \ +// RUN: -analyzer-checker=core -analyzer-output=plist-html +// // RUN: ls %t.dir | grep '\.html' | count 1 // RUN: grep '\.html' %t.dir/index.plist | count 1