forked from OSchip/llvm-project
Revert "Revert "[analyzer] NFC: Separate PathDiagnosticConsumer options from AnalyzerOptions.""
This reverts commit 10f1ca99b4
.
(cherry picked from commit c599fc738a70e482976c6cc0ea31bef561641279)
This commit is contained in:
parent
fa5cb4b936
commit
499bce3aba
|
@ -58,6 +58,47 @@ namespace ento {
|
||||||
|
|
||||||
class PathDiagnostic;
|
class PathDiagnostic;
|
||||||
|
|
||||||
|
/// These options tweak the behavior of path diangostic consumers.
|
||||||
|
/// Most of these options are currently supported by very few consumers.
|
||||||
|
struct PathDiagnosticConsumerOptions {
|
||||||
|
/// 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 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;
|
||||||
|
|
||||||
|
/// 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 treat consumed diagnostics as hard errors.
|
||||||
|
/// Useful for breaking your build when issues are found.
|
||||||
|
bool ShouldDisplayWarningsAsErrors;
|
||||||
|
|
||||||
|
/// Whether the consumer should attempt to rewrite the source file
|
||||||
|
/// with fix-it hints attached to the diagnostics it consumes.
|
||||||
|
bool ShouldApplyFixIts;
|
||||||
|
|
||||||
|
/// Whether the consumer should present the name of the entity that emitted
|
||||||
|
/// the diagnostic (eg., a checker) so that the user knew how to disable it.
|
||||||
|
bool ShouldDisplayDiagnosticName;
|
||||||
|
|
||||||
|
PathDiagnosticConsumerOptions() = delete;
|
||||||
|
};
|
||||||
|
|
||||||
class PathDiagnosticConsumer {
|
class PathDiagnosticConsumer {
|
||||||
public:
|
public:
|
||||||
class PDFileEntry : public llvm::FoldingSetNode {
|
class PDFileEntry : public llvm::FoldingSetNode {
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
#ifndef LLVM_CLANG_STATICANALYZER_CORE_ANALYZEROPTIONS_H
|
#ifndef LLVM_CLANG_STATICANALYZER_CORE_ANALYZEROPTIONS_H
|
||||||
#define LLVM_CLANG_STATICANALYZER_CORE_ANALYZEROPTIONS_H
|
#define LLVM_CLANG_STATICANALYZER_CORE_ANALYZEROPTIONS_H
|
||||||
|
|
||||||
|
#include "clang/Analysis/PathDiagnostic.h"
|
||||||
#include "clang/Basic/LLVM.h"
|
#include "clang/Basic/LLVM.h"
|
||||||
#include "llvm/ADT/IntrusiveRefCntPtr.h"
|
#include "llvm/ADT/IntrusiveRefCntPtr.h"
|
||||||
#include "llvm/ADT/Optional.h"
|
#include "llvm/ADT/Optional.h"
|
||||||
|
@ -255,7 +256,7 @@ public:
|
||||||
unsigned NoRetryExhausted : 1;
|
unsigned NoRetryExhausted : 1;
|
||||||
|
|
||||||
/// Emit analyzer warnings as errors.
|
/// Emit analyzer warnings as errors.
|
||||||
unsigned AnalyzerWerror : 1;
|
bool AnalyzerWerror : 1;
|
||||||
|
|
||||||
/// The inlining stack depth limit.
|
/// The inlining stack depth limit.
|
||||||
// Cap the stack depth at 4 calls (5 stack frames, base + 4 calls).
|
// Cap the stack depth at 4 calls (5 stack frames, base + 4 calls).
|
||||||
|
@ -390,6 +391,16 @@ public:
|
||||||
///
|
///
|
||||||
/// \sa CXXMemberInliningMode
|
/// \sa CXXMemberInliningMode
|
||||||
bool mayInlineCXXMemberFunction(CXXInlineableMemberKind K) const;
|
bool mayInlineCXXMemberFunction(CXXInlineableMemberKind K) const;
|
||||||
|
|
||||||
|
ento::PathDiagnosticConsumerOptions getDiagOpts() const {
|
||||||
|
return {FullCompilerInvocation,
|
||||||
|
ShouldDisplayMacroExpansions,
|
||||||
|
ShouldSerializeStats,
|
||||||
|
ShouldWriteStableReportFilename,
|
||||||
|
AnalyzerWerror,
|
||||||
|
ShouldApplyFixIts,
|
||||||
|
ShouldDisplayCheckerNameForText};
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
using AnalyzerOptionsRef = IntrusiveRefCntPtr<AnalyzerOptions>;
|
using AnalyzerOptionsRef = IntrusiveRefCntPtr<AnalyzerOptions>;
|
||||||
|
|
|
@ -13,6 +13,8 @@
|
||||||
#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHDIAGNOSTICCONSUMERS_H
|
#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHDIAGNOSTICCONSUMERS_H
|
||||||
#define LLVM_CLANG_STATICANALYZER_CORE_PATHDIAGNOSTICCONSUMERS_H
|
#define LLVM_CLANG_STATICANALYZER_CORE_PATHDIAGNOSTICCONSUMERS_H
|
||||||
|
|
||||||
|
#include "clang/Analysis/PathDiagnostic.h"
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
@ -30,8 +32,9 @@ class PathDiagnosticConsumer;
|
||||||
typedef std::vector<PathDiagnosticConsumer*> PathDiagnosticConsumers;
|
typedef std::vector<PathDiagnosticConsumer*> PathDiagnosticConsumers;
|
||||||
|
|
||||||
#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATEFN) \
|
#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATEFN) \
|
||||||
void CREATEFN(AnalyzerOptions &AnalyzerOpts, PathDiagnosticConsumers &C, \
|
void CREATEFN(PathDiagnosticConsumerOptions Diagopts, \
|
||||||
const std::string &Prefix, const Preprocessor &PP, \
|
PathDiagnosticConsumers &C, const std::string &Prefix, \
|
||||||
|
const Preprocessor &PP, \
|
||||||
const cross_tu::CrossTranslationUnitContext &CTU);
|
const cross_tu::CrossTranslationUnitContext &CTU);
|
||||||
#include "clang/StaticAnalyzer/Core/Analyses.def"
|
#include "clang/StaticAnalyzer/Core/Analyses.def"
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,6 @@
|
||||||
#include "clang/Lex/Token.h"
|
#include "clang/Lex/Token.h"
|
||||||
#include "clang/Rewrite/Core/HTMLRewrite.h"
|
#include "clang/Rewrite/Core/HTMLRewrite.h"
|
||||||
#include "clang/Rewrite/Core/Rewriter.h"
|
#include "clang/Rewrite/Core/Rewriter.h"
|
||||||
#include "clang/StaticAnalyzer/Core/AnalyzerOptions.h"
|
|
||||||
#include "clang/StaticAnalyzer/Core/IssueHash.h"
|
#include "clang/StaticAnalyzer/Core/IssueHash.h"
|
||||||
#include "clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h"
|
#include "clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h"
|
||||||
#include "llvm/ADT/ArrayRef.h"
|
#include "llvm/ADT/ArrayRef.h"
|
||||||
|
@ -58,17 +57,18 @@ using namespace ento;
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
class HTMLDiagnostics : public PathDiagnosticConsumer {
|
class HTMLDiagnostics : public PathDiagnosticConsumer {
|
||||||
|
PathDiagnosticConsumerOptions DiagOpts;
|
||||||
std::string Directory;
|
std::string Directory;
|
||||||
bool createdDir = false;
|
bool createdDir = false;
|
||||||
bool noDir = false;
|
bool noDir = false;
|
||||||
const Preprocessor &PP;
|
const Preprocessor &PP;
|
||||||
AnalyzerOptions &AnalyzerOpts;
|
|
||||||
const bool SupportsCrossFileDiagnostics;
|
const bool SupportsCrossFileDiagnostics;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
HTMLDiagnostics(AnalyzerOptions &AnalyzerOpts, const std::string &OutputDir,
|
HTMLDiagnostics(PathDiagnosticConsumerOptions DiagOpts,
|
||||||
const Preprocessor &pp, bool supportsMultipleFiles)
|
const std::string &OutputDir, const Preprocessor &pp,
|
||||||
: Directory(OutputDir), PP(pp), AnalyzerOpts(AnalyzerOpts),
|
bool supportsMultipleFiles)
|
||||||
|
: DiagOpts(std::move(DiagOpts)), Directory(OutputDir), PP(pp),
|
||||||
SupportsCrossFileDiagnostics(supportsMultipleFiles) {}
|
SupportsCrossFileDiagnostics(supportsMultipleFiles) {}
|
||||||
|
|
||||||
~HTMLDiagnostics() override { FlushDiagnostics(nullptr); }
|
~HTMLDiagnostics() override { FlushDiagnostics(nullptr); }
|
||||||
|
@ -133,7 +133,7 @@ private:
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
void ento::createHTMLDiagnosticConsumer(
|
void ento::createHTMLDiagnosticConsumer(
|
||||||
AnalyzerOptions &AnalyzerOpts, PathDiagnosticConsumers &C,
|
PathDiagnosticConsumerOptions DiagOpts, PathDiagnosticConsumers &C,
|
||||||
const std::string &OutputDir, const Preprocessor &PP,
|
const std::string &OutputDir, const Preprocessor &PP,
|
||||||
const cross_tu::CrossTranslationUnitContext &CTU) {
|
const cross_tu::CrossTranslationUnitContext &CTU) {
|
||||||
|
|
||||||
|
@ -142,37 +142,38 @@ void ento::createHTMLDiagnosticConsumer(
|
||||||
// output mode. This doesn't make much sense, we should have the minimal text
|
// output mode. This doesn't make much sense, we should have the minimal text
|
||||||
// as our default. In the case of backward compatibility concerns, this could
|
// as our default. In the case of backward compatibility concerns, this could
|
||||||
// be preserved with -analyzer-config-compatibility-mode=true.
|
// be preserved with -analyzer-config-compatibility-mode=true.
|
||||||
createTextMinimalPathDiagnosticConsumer(AnalyzerOpts, C, OutputDir, PP, CTU);
|
createTextMinimalPathDiagnosticConsumer(DiagOpts, C, OutputDir, PP, CTU);
|
||||||
|
|
||||||
// TODO: Emit an error here.
|
// TODO: Emit an error here.
|
||||||
if (OutputDir.empty())
|
if (OutputDir.empty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
C.push_back(new HTMLDiagnostics(AnalyzerOpts, OutputDir, PP, true));
|
C.push_back(new HTMLDiagnostics(std::move(DiagOpts), OutputDir, PP, true));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ento::createHTMLSingleFileDiagnosticConsumer(
|
void ento::createHTMLSingleFileDiagnosticConsumer(
|
||||||
AnalyzerOptions &AnalyzerOpts, PathDiagnosticConsumers &C,
|
PathDiagnosticConsumerOptions DiagOpts, PathDiagnosticConsumers &C,
|
||||||
const std::string &OutputDir, const Preprocessor &PP,
|
const std::string &OutputDir, const Preprocessor &PP,
|
||||||
const cross_tu::CrossTranslationUnitContext &CTU) {
|
const cross_tu::CrossTranslationUnitContext &CTU) {
|
||||||
|
createTextMinimalPathDiagnosticConsumer(DiagOpts, C, OutputDir, PP, CTU);
|
||||||
|
|
||||||
// TODO: Emit an error here.
|
// TODO: Emit an error here.
|
||||||
if (OutputDir.empty())
|
if (OutputDir.empty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
C.push_back(new HTMLDiagnostics(AnalyzerOpts, OutputDir, PP, false));
|
C.push_back(new HTMLDiagnostics(std::move(DiagOpts), OutputDir, PP, false));
|
||||||
createTextMinimalPathDiagnosticConsumer(AnalyzerOpts, C, OutputDir, PP, CTU);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ento::createPlistHTMLDiagnosticConsumer(
|
void ento::createPlistHTMLDiagnosticConsumer(
|
||||||
AnalyzerOptions &AnalyzerOpts, PathDiagnosticConsumers &C,
|
PathDiagnosticConsumerOptions DiagOpts, PathDiagnosticConsumers &C,
|
||||||
const std::string &prefix, const Preprocessor &PP,
|
const std::string &prefix, const Preprocessor &PP,
|
||||||
const cross_tu::CrossTranslationUnitContext &CTU) {
|
const cross_tu::CrossTranslationUnitContext &CTU) {
|
||||||
createHTMLDiagnosticConsumer(
|
createHTMLDiagnosticConsumer(
|
||||||
AnalyzerOpts, C, std::string(llvm::sys::path::parent_path(prefix)), PP,
|
DiagOpts, C, std::string(llvm::sys::path::parent_path(prefix)), PP,
|
||||||
CTU);
|
CTU);
|
||||||
createPlistMultiFileDiagnosticConsumer(AnalyzerOpts, C, prefix, PP, CTU);
|
createPlistMultiFileDiagnosticConsumer(DiagOpts, C, prefix, PP, CTU);
|
||||||
createTextMinimalPathDiagnosticConsumer(AnalyzerOpts, C, prefix, PP, CTU);
|
createTextMinimalPathDiagnosticConsumer(std::move(DiagOpts), C, prefix, PP,
|
||||||
|
CTU);
|
||||||
}
|
}
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
@ -245,7 +246,7 @@ void HTMLDiagnostics::ReportDiag(const PathDiagnostic& D,
|
||||||
int FD;
|
int FD;
|
||||||
SmallString<128> Model, ResultPath;
|
SmallString<128> Model, ResultPath;
|
||||||
|
|
||||||
if (!AnalyzerOpts.ShouldWriteStableReportFilename) {
|
if (!DiagOpts.ShouldWriteStableReportFilename) {
|
||||||
llvm::sys::path::append(Model, Directory, "report-%%%%%%.html");
|
llvm::sys::path::append(Model, Directory, "report-%%%%%%.html");
|
||||||
if (std::error_code EC =
|
if (std::error_code EC =
|
||||||
llvm::sys::fs::make_absolute(Model)) {
|
llvm::sys::fs::make_absolute(Model)) {
|
||||||
|
@ -535,7 +536,7 @@ void HTMLDiagnostics::FinalizeHTML(const PathDiagnostic& D, Rewriter &R,
|
||||||
<input type="checkbox" class="spoilerhider" id="showinvocation" />
|
<input type="checkbox" class="spoilerhider" id="showinvocation" />
|
||||||
<label for="showinvocation" >Show analyzer invocation</label>
|
<label for="showinvocation" >Show analyzer invocation</label>
|
||||||
<div class="spoiler">clang -cc1 )<<<";
|
<div class="spoiler">clang -cc1 )<<<";
|
||||||
os << html::EscapeText(AnalyzerOpts.FullCompilerInvocation);
|
os << html::EscapeText(DiagOpts.ToolInvocation);
|
||||||
os << R"<<<(
|
os << R"<<<(
|
||||||
</div>
|
</div>
|
||||||
<div id='tooltiphint' hidden="true">
|
<div id='tooltiphint' hidden="true">
|
||||||
|
|
|
@ -20,7 +20,6 @@
|
||||||
#include "clang/Lex/Preprocessor.h"
|
#include "clang/Lex/Preprocessor.h"
|
||||||
#include "clang/Lex/TokenConcatenation.h"
|
#include "clang/Lex/TokenConcatenation.h"
|
||||||
#include "clang/Rewrite/Core/HTMLRewrite.h"
|
#include "clang/Rewrite/Core/HTMLRewrite.h"
|
||||||
#include "clang/StaticAnalyzer/Core/AnalyzerOptions.h"
|
|
||||||
#include "clang/StaticAnalyzer/Core/IssueHash.h"
|
#include "clang/StaticAnalyzer/Core/IssueHash.h"
|
||||||
#include "clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h"
|
#include "clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h"
|
||||||
#include "llvm/ADT/SmallPtrSet.h"
|
#include "llvm/ADT/SmallPtrSet.h"
|
||||||
|
@ -40,13 +39,17 @@ using namespace markup;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
class PlistDiagnostics : public PathDiagnosticConsumer {
|
class PlistDiagnostics : public PathDiagnosticConsumer {
|
||||||
|
PathDiagnosticConsumerOptions DiagOpts;
|
||||||
const std::string OutputFile;
|
const std::string OutputFile;
|
||||||
const Preprocessor &PP;
|
const Preprocessor &PP;
|
||||||
const cross_tu::CrossTranslationUnitContext &CTU;
|
const cross_tu::CrossTranslationUnitContext &CTU;
|
||||||
AnalyzerOptions &AnOpts;
|
|
||||||
const bool SupportsCrossFileDiagnostics;
|
const bool SupportsCrossFileDiagnostics;
|
||||||
|
|
||||||
|
void printBugPath(llvm::raw_ostream &o, const FIDMap &FM,
|
||||||
|
const PathPieces &Path);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
PlistDiagnostics(AnalyzerOptions &AnalyzerOpts,
|
PlistDiagnostics(PathDiagnosticConsumerOptions DiagOpts,
|
||||||
const std::string &OutputFile, const Preprocessor &PP,
|
const std::string &OutputFile, const Preprocessor &PP,
|
||||||
const cross_tu::CrossTranslationUnitContext &CTU,
|
const cross_tu::CrossTranslationUnitContext &CTU,
|
||||||
bool supportsMultipleFiles);
|
bool supportsMultipleFiles);
|
||||||
|
@ -75,23 +78,19 @@ namespace {
|
||||||
/// A helper class for emitting a single report.
|
/// A helper class for emitting a single report.
|
||||||
class PlistPrinter {
|
class PlistPrinter {
|
||||||
const FIDMap& FM;
|
const FIDMap& FM;
|
||||||
AnalyzerOptions &AnOpts;
|
|
||||||
const Preprocessor &PP;
|
const Preprocessor &PP;
|
||||||
const cross_tu::CrossTranslationUnitContext &CTU;
|
const cross_tu::CrossTranslationUnitContext &CTU;
|
||||||
llvm::SmallVector<const PathDiagnosticMacroPiece *, 0> MacroPieces;
|
llvm::SmallVector<const PathDiagnosticMacroPiece *, 0> MacroPieces;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
PlistPrinter(const FIDMap& FM, AnalyzerOptions &AnOpts,
|
PlistPrinter(const FIDMap& FM,
|
||||||
const Preprocessor &PP,
|
const Preprocessor &PP,
|
||||||
const cross_tu::CrossTranslationUnitContext &CTU)
|
const cross_tu::CrossTranslationUnitContext &CTU)
|
||||||
: FM(FM), AnOpts(AnOpts), PP(PP), CTU(CTU) {
|
: FM(FM), PP(PP), CTU(CTU) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ReportDiag(raw_ostream &o, const PathDiagnosticPiece& P) {
|
void ReportDiag(raw_ostream &o, const PathDiagnosticPiece& P) {
|
||||||
ReportPiece(o, P, /*indent*/ 4, /*depth*/ 0, /*includeControlFlow*/ true);
|
ReportPiece(o, P, /*indent*/ 4, /*depth*/ 0, /*includeControlFlow*/ true);
|
||||||
|
|
||||||
// Don't emit a warning about an unused private field.
|
|
||||||
(void)AnOpts;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Print the expansions of the collected macro pieces.
|
/// Print the expansions of the collected macro pieces.
|
||||||
|
@ -166,11 +165,6 @@ struct ExpansionInfo {
|
||||||
|
|
||||||
} // end of anonymous namespace
|
} // end of anonymous namespace
|
||||||
|
|
||||||
static void printBugPath(llvm::raw_ostream &o, const FIDMap& FM,
|
|
||||||
AnalyzerOptions &AnOpts, const Preprocessor &PP,
|
|
||||||
const cross_tu::CrossTranslationUnitContext &CTU,
|
|
||||||
const PathPieces &Path);
|
|
||||||
|
|
||||||
/// Print coverage information to output stream {@code o}.
|
/// Print coverage information to output stream {@code o}.
|
||||||
/// May modify the used list of files {@code Fids} by inserting new ones.
|
/// May modify the used list of files {@code Fids} by inserting new ones.
|
||||||
static void printCoverage(const PathDiagnostic *D,
|
static void printCoverage(const PathDiagnostic *D,
|
||||||
|
@ -521,11 +515,53 @@ static void printCoverage(const PathDiagnostic *D,
|
||||||
assert(IndentLevel == InputIndentLevel);
|
assert(IndentLevel == InputIndentLevel);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void printBugPath(llvm::raw_ostream &o, const FIDMap& FM,
|
//===----------------------------------------------------------------------===//
|
||||||
AnalyzerOptions &AnOpts, const Preprocessor &PP,
|
// Methods of PlistDiagnostics.
|
||||||
const cross_tu::CrossTranslationUnitContext &CTU,
|
//===----------------------------------------------------------------------===//
|
||||||
const PathPieces &Path) {
|
|
||||||
PlistPrinter Printer(FM, AnOpts, PP, CTU);
|
PlistDiagnostics::PlistDiagnostics(
|
||||||
|
PathDiagnosticConsumerOptions DiagOpts, const std::string &output,
|
||||||
|
const Preprocessor &PP, const cross_tu::CrossTranslationUnitContext &CTU,
|
||||||
|
bool supportsMultipleFiles)
|
||||||
|
: DiagOpts(std::move(DiagOpts)), OutputFile(output), PP(PP), CTU(CTU),
|
||||||
|
SupportsCrossFileDiagnostics(supportsMultipleFiles) {
|
||||||
|
// FIXME: Will be used by a later planned change.
|
||||||
|
(void)this->CTU;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ento::createPlistDiagnosticConsumer(
|
||||||
|
PathDiagnosticConsumerOptions DiagOpts, PathDiagnosticConsumers &C,
|
||||||
|
const std::string &OutputFile, const Preprocessor &PP,
|
||||||
|
const cross_tu::CrossTranslationUnitContext &CTU) {
|
||||||
|
|
||||||
|
// TODO: Emit an error here.
|
||||||
|
if (OutputFile.empty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
C.push_back(new PlistDiagnostics(DiagOpts, OutputFile, PP, CTU,
|
||||||
|
/*supportsMultipleFiles=*/false));
|
||||||
|
createTextMinimalPathDiagnosticConsumer(std::move(DiagOpts), C, OutputFile,
|
||||||
|
PP, CTU);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ento::createPlistMultiFileDiagnosticConsumer(
|
||||||
|
PathDiagnosticConsumerOptions DiagOpts, PathDiagnosticConsumers &C,
|
||||||
|
const std::string &OutputFile, const Preprocessor &PP,
|
||||||
|
const cross_tu::CrossTranslationUnitContext &CTU) {
|
||||||
|
|
||||||
|
// TODO: Emit an error here.
|
||||||
|
if (OutputFile.empty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
C.push_back(new PlistDiagnostics(DiagOpts, OutputFile, PP, CTU,
|
||||||
|
/*supportsMultipleFiles=*/true));
|
||||||
|
createTextMinimalPathDiagnosticConsumer(std::move(DiagOpts), C, OutputFile,
|
||||||
|
PP, CTU);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlistDiagnostics::printBugPath(llvm::raw_ostream &o, const FIDMap &FM,
|
||||||
|
const PathPieces &Path) {
|
||||||
|
PlistPrinter Printer(FM, PP, CTU);
|
||||||
assert(std::is_partitioned(Path.begin(), Path.end(),
|
assert(std::is_partitioned(Path.begin(), Path.end(),
|
||||||
[](const PathDiagnosticPieceRef &E) {
|
[](const PathDiagnosticPieceRef &E) {
|
||||||
return E->getKind() == PathDiagnosticPiece::Note;
|
return E->getKind() == PathDiagnosticPiece::Note;
|
||||||
|
@ -558,7 +594,7 @@ static void printBugPath(llvm::raw_ostream &o, const FIDMap& FM,
|
||||||
|
|
||||||
o << " </array>\n";
|
o << " </array>\n";
|
||||||
|
|
||||||
if (!AnOpts.ShouldDisplayMacroExpansions)
|
if (!DiagOpts.ShouldDisplayMacroExpansions)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
o << " <key>macro_expansions</key>\n"
|
o << " <key>macro_expansions</key>\n"
|
||||||
|
@ -567,48 +603,6 @@ static void printBugPath(llvm::raw_ostream &o, const FIDMap& FM,
|
||||||
o << " </array>\n";
|
o << " </array>\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
// Methods of PlistDiagnostics.
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
|
|
||||||
PlistDiagnostics::PlistDiagnostics(
|
|
||||||
AnalyzerOptions &AnalyzerOpts, const std::string &output,
|
|
||||||
const Preprocessor &PP, const cross_tu::CrossTranslationUnitContext &CTU,
|
|
||||||
bool supportsMultipleFiles)
|
|
||||||
: OutputFile(output), PP(PP), CTU(CTU), AnOpts(AnalyzerOpts),
|
|
||||||
SupportsCrossFileDiagnostics(supportsMultipleFiles) {
|
|
||||||
// FIXME: Will be used by a later planned change.
|
|
||||||
(void)this->CTU;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ento::createPlistDiagnosticConsumer(
|
|
||||||
AnalyzerOptions &AnalyzerOpts, PathDiagnosticConsumers &C,
|
|
||||||
const std::string &OutputFile, const Preprocessor &PP,
|
|
||||||
const cross_tu::CrossTranslationUnitContext &CTU) {
|
|
||||||
|
|
||||||
// TODO: Emit an error here.
|
|
||||||
if (OutputFile.empty())
|
|
||||||
return;
|
|
||||||
|
|
||||||
C.push_back(new PlistDiagnostics(AnalyzerOpts, OutputFile, PP, CTU,
|
|
||||||
/*supportsMultipleFiles*/ false));
|
|
||||||
createTextMinimalPathDiagnosticConsumer(AnalyzerOpts, C, OutputFile, PP, CTU);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ento::createPlistMultiFileDiagnosticConsumer(
|
|
||||||
AnalyzerOptions &AnalyzerOpts, PathDiagnosticConsumers &C,
|
|
||||||
const std::string &OutputFile, const Preprocessor &PP,
|
|
||||||
const cross_tu::CrossTranslationUnitContext &CTU) {
|
|
||||||
|
|
||||||
// TODO: Emit an error here.
|
|
||||||
if (OutputFile.empty())
|
|
||||||
return;
|
|
||||||
|
|
||||||
C.push_back(new PlistDiagnostics(AnalyzerOpts, OutputFile, PP, CTU,
|
|
||||||
/*supportsMultipleFiles*/ true));
|
|
||||||
createTextMinimalPathDiagnosticConsumer(AnalyzerOpts, C, OutputFile, PP, CTU);
|
|
||||||
}
|
|
||||||
|
|
||||||
void PlistDiagnostics::FlushDiagnosticsImpl(
|
void PlistDiagnostics::FlushDiagnosticsImpl(
|
||||||
std::vector<const PathDiagnostic *> &Diags,
|
std::vector<const PathDiagnostic *> &Diags,
|
||||||
FilesMade *filesMade) {
|
FilesMade *filesMade) {
|
||||||
|
@ -683,7 +677,7 @@ void PlistDiagnostics::FlushDiagnosticsImpl(
|
||||||
o << " <dict>\n";
|
o << " <dict>\n";
|
||||||
|
|
||||||
const PathDiagnostic *D = *DI;
|
const PathDiagnostic *D = *DI;
|
||||||
printBugPath(o, FM, AnOpts, PP, CTU, D->path);
|
printBugPath(o, FM, D->path);
|
||||||
|
|
||||||
// Output the bug type and bug category.
|
// Output the bug type and bug category.
|
||||||
o << " <key>description</key>";
|
o << " <key>description</key>";
|
||||||
|
@ -807,7 +801,7 @@ void PlistDiagnostics::FlushDiagnosticsImpl(
|
||||||
EmitString(o << " ", SM.getFileEntryForID(FID)->getName()) << '\n';
|
EmitString(o << " ", SM.getFileEntryForID(FID)->getName()) << '\n';
|
||||||
o << " </array>\n";
|
o << " </array>\n";
|
||||||
|
|
||||||
if (llvm::AreStatisticsEnabled() && AnOpts.ShouldSerializeStats) {
|
if (llvm::AreStatisticsEnabled() && DiagOpts.ShouldSerializeStats) {
|
||||||
o << " <key>statistics</key>\n";
|
o << " <key>statistics</key>\n";
|
||||||
std::string stats;
|
std::string stats;
|
||||||
llvm::raw_string_ostream os(stats);
|
llvm::raw_string_ostream os(stats);
|
||||||
|
|
|
@ -14,7 +14,6 @@
|
||||||
#include "clang/Basic/FileManager.h"
|
#include "clang/Basic/FileManager.h"
|
||||||
#include "clang/Basic/Version.h"
|
#include "clang/Basic/Version.h"
|
||||||
#include "clang/Lex/Preprocessor.h"
|
#include "clang/Lex/Preprocessor.h"
|
||||||
#include "clang/StaticAnalyzer/Core/AnalyzerOptions.h"
|
|
||||||
#include "clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h"
|
#include "clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h"
|
||||||
#include "llvm/ADT/STLExtras.h"
|
#include "llvm/ADT/STLExtras.h"
|
||||||
#include "llvm/ADT/StringMap.h"
|
#include "llvm/ADT/StringMap.h"
|
||||||
|
@ -32,8 +31,7 @@ class SarifDiagnostics : public PathDiagnosticConsumer {
|
||||||
const LangOptions &LO;
|
const LangOptions &LO;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SarifDiagnostics(AnalyzerOptions &, const std::string &Output,
|
SarifDiagnostics(const std::string &Output, const LangOptions &LO)
|
||||||
const LangOptions &LO)
|
|
||||||
: OutputFile(Output), LO(LO) {}
|
: OutputFile(Output), LO(LO) {}
|
||||||
~SarifDiagnostics() override = default;
|
~SarifDiagnostics() override = default;
|
||||||
|
|
||||||
|
@ -48,7 +46,7 @@ public:
|
||||||
} // end anonymous namespace
|
} // end anonymous namespace
|
||||||
|
|
||||||
void ento::createSarifDiagnosticConsumer(
|
void ento::createSarifDiagnosticConsumer(
|
||||||
AnalyzerOptions &AnalyzerOpts, PathDiagnosticConsumers &C,
|
PathDiagnosticConsumerOptions DiagOpts, PathDiagnosticConsumers &C,
|
||||||
const std::string &Output, const Preprocessor &PP,
|
const std::string &Output, const Preprocessor &PP,
|
||||||
const cross_tu::CrossTranslationUnitContext &CTU) {
|
const cross_tu::CrossTranslationUnitContext &CTU) {
|
||||||
|
|
||||||
|
@ -56,8 +54,9 @@ void ento::createSarifDiagnosticConsumer(
|
||||||
if (Output.empty())
|
if (Output.empty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
C.push_back(new SarifDiagnostics(AnalyzerOpts, Output, PP.getLangOpts()));
|
C.push_back(new SarifDiagnostics(Output, PP.getLangOpts()));
|
||||||
createTextMinimalPathDiagnosticConsumer(AnalyzerOpts, C, Output, PP, CTU);
|
createTextMinimalPathDiagnosticConsumer(std::move(DiagOpts), C, Output, PP,
|
||||||
|
CTU);
|
||||||
}
|
}
|
||||||
|
|
||||||
static StringRef getFileName(const FileEntry &FE) {
|
static StringRef getFileName(const FileEntry &FE) {
|
||||||
|
|
|
@ -34,20 +34,17 @@ namespace {
|
||||||
/// type to the standard error, or to to compliment many others. Emits detailed
|
/// type to the standard error, or to to compliment many others. Emits detailed
|
||||||
/// diagnostics in textual format for the 'text' output type.
|
/// diagnostics in textual format for the 'text' output type.
|
||||||
class TextDiagnostics : public PathDiagnosticConsumer {
|
class TextDiagnostics : public PathDiagnosticConsumer {
|
||||||
|
PathDiagnosticConsumerOptions DiagOpts;
|
||||||
DiagnosticsEngine &DiagEng;
|
DiagnosticsEngine &DiagEng;
|
||||||
const LangOptions &LO;
|
const LangOptions &LO;
|
||||||
const bool IncludePath = false;
|
bool ShouldDisplayPathNotes;
|
||||||
const bool ShouldEmitAsError = false;
|
|
||||||
const bool ApplyFixIts = false;
|
|
||||||
const bool ShouldDisplayCheckerName = false;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
TextDiagnostics(DiagnosticsEngine &DiagEng, const LangOptions &LO,
|
TextDiagnostics(PathDiagnosticConsumerOptions DiagOpts,
|
||||||
bool ShouldIncludePath, const AnalyzerOptions &AnOpts)
|
DiagnosticsEngine &DiagEng, const LangOptions &LO,
|
||||||
: DiagEng(DiagEng), LO(LO), IncludePath(ShouldIncludePath),
|
bool ShouldDisplayPathNotes)
|
||||||
ShouldEmitAsError(AnOpts.AnalyzerWerror),
|
: DiagOpts(std::move(DiagOpts)), DiagEng(DiagEng), LO(LO),
|
||||||
ApplyFixIts(AnOpts.ShouldApplyFixIts),
|
ShouldDisplayPathNotes(ShouldDisplayPathNotes) {}
|
||||||
ShouldDisplayCheckerName(AnOpts.ShouldDisplayCheckerNameForText) {}
|
|
||||||
~TextDiagnostics() override {}
|
~TextDiagnostics() override {}
|
||||||
|
|
||||||
StringRef getName() const override { return "TextDiagnostics"; }
|
StringRef getName() const override { return "TextDiagnostics"; }
|
||||||
|
@ -56,13 +53,13 @@ public:
|
||||||
bool supportsCrossFileDiagnostics() const override { return true; }
|
bool supportsCrossFileDiagnostics() const override { return true; }
|
||||||
|
|
||||||
PathGenerationScheme getGenerationScheme() const override {
|
PathGenerationScheme getGenerationScheme() const override {
|
||||||
return IncludePath ? Minimal : None;
|
return ShouldDisplayPathNotes ? Minimal : None;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FlushDiagnosticsImpl(std::vector<const PathDiagnostic *> &Diags,
|
void FlushDiagnosticsImpl(std::vector<const PathDiagnostic *> &Diags,
|
||||||
FilesMade *filesMade) override {
|
FilesMade *filesMade) override {
|
||||||
unsigned WarnID =
|
unsigned WarnID =
|
||||||
ShouldEmitAsError
|
DiagOpts.ShouldDisplayWarningsAsErrors
|
||||||
? DiagEng.getCustomDiagID(DiagnosticsEngine::Error, "%0")
|
? DiagEng.getCustomDiagID(DiagnosticsEngine::Error, "%0")
|
||||||
: DiagEng.getCustomDiagID(DiagnosticsEngine::Warning, "%0");
|
: DiagEng.getCustomDiagID(DiagnosticsEngine::Warning, "%0");
|
||||||
unsigned NoteID = DiagEng.getCustomDiagID(DiagnosticsEngine::Note, "%0");
|
unsigned NoteID = DiagEng.getCustomDiagID(DiagnosticsEngine::Note, "%0");
|
||||||
|
@ -72,7 +69,7 @@ public:
|
||||||
auto reportPiece = [&](unsigned ID, FullSourceLoc Loc, StringRef String,
|
auto reportPiece = [&](unsigned ID, FullSourceLoc Loc, StringRef String,
|
||||||
ArrayRef<SourceRange> Ranges,
|
ArrayRef<SourceRange> Ranges,
|
||||||
ArrayRef<FixItHint> Fixits) {
|
ArrayRef<FixItHint> Fixits) {
|
||||||
if (!ApplyFixIts) {
|
if (!DiagOpts.ShouldApplyFixIts) {
|
||||||
DiagEng.Report(Loc, ID) << String << Ranges << Fixits;
|
DiagEng.Report(Loc, ID) << String << Ranges << Fixits;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -92,9 +89,10 @@ public:
|
||||||
E = Diags.end();
|
E = Diags.end();
|
||||||
I != E; ++I) {
|
I != E; ++I) {
|
||||||
const PathDiagnostic *PD = *I;
|
const PathDiagnostic *PD = *I;
|
||||||
std::string WarningMsg =
|
std::string WarningMsg = (DiagOpts.ShouldDisplayDiagnosticName
|
||||||
(ShouldDisplayCheckerName ? " [" + PD->getCheckerName() + "]" : "")
|
? " [" + PD->getCheckerName() + "]"
|
||||||
.str();
|
: "")
|
||||||
|
.str();
|
||||||
|
|
||||||
reportPiece(WarnID, PD->getLocation().asLocation(),
|
reportPiece(WarnID, PD->getLocation().asLocation(),
|
||||||
(PD->getShortDescription() + WarningMsg).str(),
|
(PD->getShortDescription() + WarningMsg).str(),
|
||||||
|
@ -110,7 +108,7 @@ public:
|
||||||
Piece->getFixits());
|
Piece->getFixits());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!IncludePath)
|
if (!ShouldDisplayPathNotes)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Then, add the path notes if necessary.
|
// Then, add the path notes if necessary.
|
||||||
|
@ -125,7 +123,7 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ApplyFixIts || Repls.empty())
|
if (Repls.empty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Rewriter Rewrite(SM, LO);
|
Rewriter Rewrite(SM, LO);
|
||||||
|
@ -139,18 +137,19 @@ public:
|
||||||
} // end anonymous namespace
|
} // end anonymous namespace
|
||||||
|
|
||||||
void ento::createTextPathDiagnosticConsumer(
|
void ento::createTextPathDiagnosticConsumer(
|
||||||
AnalyzerOptions &AnalyzerOpts, PathDiagnosticConsumers &C,
|
PathDiagnosticConsumerOptions DiagOpts, PathDiagnosticConsumers &C,
|
||||||
const std::string &Prefix, const clang::Preprocessor &PP,
|
const std::string &Prefix, const clang::Preprocessor &PP,
|
||||||
const cross_tu::CrossTranslationUnitContext &CTU) {
|
const cross_tu::CrossTranslationUnitContext &CTU) {
|
||||||
C.emplace_back(new TextDiagnostics(PP.getDiagnostics(), PP.getLangOpts(),
|
C.emplace_back(new TextDiagnostics(std::move(DiagOpts), PP.getDiagnostics(),
|
||||||
/*ShouldIncludePath*/ true, AnalyzerOpts));
|
PP.getLangOpts(),
|
||||||
|
/*ShouldDisplayPathNotes=*/true));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ento::createTextMinimalPathDiagnosticConsumer(
|
void ento::createTextMinimalPathDiagnosticConsumer(
|
||||||
AnalyzerOptions &AnalyzerOpts, PathDiagnosticConsumers &C,
|
PathDiagnosticConsumerOptions DiagOpts, PathDiagnosticConsumers &C,
|
||||||
const std::string &Prefix, const clang::Preprocessor &PP,
|
const std::string &Prefix, const clang::Preprocessor &PP,
|
||||||
const cross_tu::CrossTranslationUnitContext &CTU) {
|
const cross_tu::CrossTranslationUnitContext &CTU) {
|
||||||
C.emplace_back(new TextDiagnostics(PP.getDiagnostics(), PP.getLangOpts(),
|
C.emplace_back(new TextDiagnostics(std::move(DiagOpts), PP.getDiagnostics(),
|
||||||
/*ShouldIncludePath*/ false,
|
PP.getLangOpts(),
|
||||||
AnalyzerOpts));
|
/*ShouldDisplayPathNotes=*/false));
|
||||||
}
|
}
|
||||||
|
|
|
@ -150,7 +150,7 @@ public:
|
||||||
break;
|
break;
|
||||||
#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATEFN) \
|
#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATEFN) \
|
||||||
case PD_##NAME: \
|
case PD_##NAME: \
|
||||||
CREATEFN(*Opts.get(), PathConsumers, OutDir, PP, CTU); \
|
CREATEFN(Opts->getDiagOpts(), PathConsumers, OutDir, PP, CTU); \
|
||||||
break;
|
break;
|
||||||
#include "clang/StaticAnalyzer/Core/Analyses.def"
|
#include "clang/StaticAnalyzer/Core/Analyses.def"
|
||||||
default:
|
default:
|
||||||
|
|
Loading…
Reference in New Issue