Index: clang/include/clang/Analysis/PathDiagnostic.h =================================================================== --- clang/include/clang/Analysis/PathDiagnostic.h +++ clang/include/clang/Analysis/PathDiagnostic.h @@ -58,6 +58,47 @@ class PathDiagnostic; +/// These options tweak the behavior of path diangostic consumers. +/// Most of these options are currently supported by very few consumers. +struct PathDiagnosticConsumerOptions { + /// Whether to include additional information about macro expansions + /// with the diagnostics, because otherwise they can be hard to obtain + /// without re-compiling the program under analysis. + bool ShouldDisplayMacroExpansions; + + /// Run-line of the tool that produced the diagnostic. + /// It can be included with the diagnostic for debugging purposes. + std::string ToolInvocation; + + /// Whether to include LLVM statistics of the process in the diagnostic. + /// Useful for profiling the tool on large real-world codebases. + bool ShouldSerializeStats; + + /// If the consumer intends to produce multiple output files, should it + /// use randomly generated file names for these files (with the tiny risk of + /// having random collisions) or deterministic human-readable file names + /// (with a larger risk of deterministic collisions or invalid characters + /// in the file name). We should not really give this choice to the users + /// because deterministic mode is always superior when done right, but + /// for some consumers this mode is experimental and needs to be + /// off by default. + bool ShouldWriteStableReportFilename; + + /// Whether the consumer should display warnings as hard errors. + /// Useful for breaking your build when issues are found. + bool ShouldDisplayWarningsAsErrors; + + /// Whether the consumer should display fixits as notes of "remark" severity. + /// Useful for testing fixits themselves. + bool ShouldEmitFixItHintsAsRemarks; + + /// Whether the consumer should display path pieces. If off, only warnings + /// and normal notes are displayed. Useful when another consumer is already + /// displaying path notes, and you only want this consumer to notify the user + /// that the warning was emitted. Also useful for testing. + bool ShouldDisplayPathNotes; +}; + class PathDiagnosticConsumer { public: class PDFileEntry : public llvm::FoldingSetNode { Index: clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h =================================================================== --- clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h +++ clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h @@ -14,6 +14,7 @@ #ifndef LLVM_CLANG_STATICANALYZER_CORE_ANALYZEROPTIONS_H #define LLVM_CLANG_STATICANALYZER_CORE_ANALYZEROPTIONS_H +#include "clang/Analysis/PathDiagnostic.h" #include "clang/Basic/LLVM.h" #include "llvm/ADT/IntrusiveRefCntPtr.h" #include "llvm/ADT/Optional.h" @@ -281,7 +282,7 @@ unsigned NoRetryExhausted : 1; /// Emit analyzer warnings as errors. - unsigned AnalyzerWerror : 1; + bool AnalyzerWerror : 1; /// The inlining stack depth limit. // Cap the stack depth at 4 calls (5 stack frames, base + 4 calls). @@ -418,6 +419,16 @@ /// /// \sa CXXMemberInliningMode bool mayInlineCXXMemberFunction(CXXInlineableMemberKind K) const; + + ento::PathDiagnosticConsumerOptions getDiagOpts() const { + return {ShouldDisplayMacroExpansions, + FullCompilerInvocation, + ShouldSerializeStats, + ShouldWriteStableReportFilename, + AnalyzerWerror, + ShouldEmitFixItHintsAsRemarks, + /*ShouldDisplayPathNotes=*/true}; + } }; using AnalyzerOptionsRef = IntrusiveRefCntPtr; Index: clang/include/clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h =================================================================== --- clang/include/clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h +++ clang/include/clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h @@ -30,8 +30,9 @@ typedef std::vector PathDiagnosticConsumers; #define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATEFN) \ - void CREATEFN(AnalyzerOptions &AnalyzerOpts, PathDiagnosticConsumers &C, \ - const std::string &Prefix, const Preprocessor &PP, \ + void CREATEFN(PathDiagnosticConsumerOptions &&Diagopts, \ + PathDiagnosticConsumers &C, const std::string &Prefix, \ + const Preprocessor &PP, \ const cross_tu::CrossTranslationUnitContext &CTU); #include "clang/StaticAnalyzer/Core/Analyses.def" Index: clang/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp =================================================================== --- clang/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp +++ clang/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp @@ -23,7 +23,6 @@ #include "clang/Lex/Token.h" #include "clang/Rewrite/Core/HTMLRewrite.h" #include "clang/Rewrite/Core/Rewriter.h" -#include "clang/StaticAnalyzer/Core/AnalyzerOptions.h" #include "clang/StaticAnalyzer/Core/IssueHash.h" #include "clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h" #include "llvm/ADT/ArrayRef.h" @@ -58,19 +57,19 @@ namespace { class HTMLDiagnostics : public PathDiagnosticConsumer { + PathDiagnosticConsumerOptions DiagOpts; std::string Directory; bool createdDir = false; bool noDir = false; const Preprocessor &PP; - AnalyzerOptions &AnalyzerOpts; const bool SupportsCrossFileDiagnostics; public: - HTMLDiagnostics(AnalyzerOptions &AnalyzerOpts, + HTMLDiagnostics(PathDiagnosticConsumerOptions &&DiagOpts, const std::string& prefix, const Preprocessor &pp, bool supportsMultipleFiles) - : Directory(prefix), PP(pp), AnalyzerOpts(AnalyzerOpts), + : DiagOpts(std::move(DiagOpts)), Directory(prefix), PP(pp), SupportsCrossFileDiagnostics(supportsMultipleFiles) {} ~HTMLDiagnostics() override { FlushDiagnostics(nullptr); } @@ -135,17 +134,17 @@ } // namespace void ento::createHTMLDiagnosticConsumer( - AnalyzerOptions &AnalyzerOpts, PathDiagnosticConsumers &C, + PathDiagnosticConsumerOptions &&DiagOpts, PathDiagnosticConsumers &C, const std::string &prefix, const Preprocessor &PP, const cross_tu::CrossTranslationUnitContext &) { - C.push_back(new HTMLDiagnostics(AnalyzerOpts, prefix, PP, true)); + C.push_back(new HTMLDiagnostics(std::move(DiagOpts), prefix, PP, true)); } void ento::createHTMLSingleFileDiagnosticConsumer( - AnalyzerOptions &AnalyzerOpts, PathDiagnosticConsumers &C, + PathDiagnosticConsumerOptions &&DiagOpts, PathDiagnosticConsumers &C, const std::string &prefix, const Preprocessor &PP, const cross_tu::CrossTranslationUnitContext &) { - C.push_back(new HTMLDiagnostics(AnalyzerOpts, prefix, PP, false)); + C.push_back(new HTMLDiagnostics(std::move(DiagOpts), prefix, PP, false)); } //===----------------------------------------------------------------------===// @@ -218,7 +217,7 @@ int FD; SmallString<128> Model, ResultPath; - if (!AnalyzerOpts.ShouldWriteStableReportFilename) { + if (!DiagOpts.ShouldWriteStableReportFilename) { llvm::sys::path::append(Model, Directory, "report-%%%%%%.html"); if (std::error_code EC = llvm::sys::fs::make_absolute(Model)) { @@ -508,7 +507,7 @@
clang -cc1 )<<<"; - os << html::EscapeText(AnalyzerOpts.FullCompilerInvocation); + os << html::EscapeText(DiagOpts.ToolInvocation); os << R"<<<(