clang: lib/StaticAnalyzer/Core/SarifDiagnostics.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
21#include "llvm/ADT/STLExtras.h"
22#include "llvm/ADT/StringMap.h"
23#include "llvm/Support/ConvertUTF.h"
24#include "llvm/Support/JSON.h"
25#include "llvm/Support/Path.h"
26
27using namespace llvm;
28using namespace clang;
29using namespace ento;
30
31namespace {
33 std::string OutputFile;
36
37public:
38 SarifDiagnostics(const std::string &Output, const LangOptions &LO,
40 : OutputFile(Output), LO(LO), SarifWriter(SM) {}
41 ~SarifDiagnostics() override = default;
42
44 FilesMade *FM) override;
45
46 StringRef getName() const override { return "SarifDiagnostics"; }
50};
51}
52
53void ento::createSarifDiagnosticConsumer(
55 const std::string &Output, const Preprocessor &PP,
58
59
60 if (Output.empty())
61 return;
62
63 C.push_back(
65 createTextMinimalPathDiagnosticConsumer(std::move(DiagOpts), C, Output, PP,
66 CTU, MacroExpansions);
67}
68
70 return llvm::StringSwitch(CheckName)
71#define GET_CHECKERS
72#define CHECKER(FULLNAME, CLASS, HELPTEXT, DOC_URI, IS_HIDDEN) \
73 .Case(FULLNAME, HELPTEXT)
74#include "clang/StaticAnalyzer/Checkers/Checkers.inc"
75#undef CHECKER
76#undef GET_CHECKERS
77 ;
78}
79
81 return llvm::StringSwitch(CheckName)
82#define GET_CHECKERS
83#define CHECKER(FULLNAME, CLASS, HELPTEXT, DOC_URI, IS_HIDDEN) \
84 .Case(FULLNAME, DOC_URI)
85#include "clang/StaticAnalyzer/Checkers/Checkers.inc"
86#undef CHECKER
87#undef GET_CHECKERS
88 ;
89}
90
93 switch (Piece.getKind()) {
98
99 break;
101 return Piece.getTagStr() == "ConditionBRVisitor"
102 ? ThreadFlowImportance::Important
103 : ThreadFlowImportance::Essential;
105 return ThreadFlowImportance::Unimportant;
106 }
107 return ThreadFlowImportance::Unimportant;
108}
109
110
111
115
116
119
121
122
123
127}
128
132 const PathPieces &Pieces = Diag->path.flatten(false);
133 for (const auto &Piece : Pieces) {
135 Piece->getLocation().asRange(), Piece->getLocation().getManager(), LO);
140 Flows.push_back(Flow);
141 }
142 return Flows;
143}
144
145static StringMap<uint32_t>
148 StringMap<uint32_t> RuleMapping;
149 llvm::StringSet<> Seen;
150
152 StringRef CheckName = D->getCheckerName();
153 std::pair<llvm::StringSet<>::iterator, bool> P = Seen.insert(CheckName);
154 if (P.second) {
160 size_t RuleIdx = SarifWriter.createRule(Rule);
161 RuleMapping[CheckName] = RuleIdx;
162 }
163 }
164 return RuleMapping;
165}
166
168 const StringMap<uint32_t> &RuleMapping,
170
171 StringRef CheckName = Diag->getCheckerName();
172 uint32_t RuleIdx = RuleMapping.lookup(CheckName);
174 Diag->getLocation().asRange(), Diag->getLocation().getManager(), LO);
175
182 .setThreadFlows(Flows);
183 return Result;
184}
185
186void SarifDiagnostics::FlushDiagnosticsImpl(
187 std::vector<const PathDiagnostic *> &Diags, FilesMade *) {
188
189
190
191
192
193 std::error_code EC;
194 llvm::raw_fd_ostream OS(OutputFile, EC, llvm::sys::fs::OF_TextWithCRLF);
195 if (EC) {
196 llvm::errs() << "warning: could not create file: " << EC.message() << '\n';
197 return;
198 }
199
201 SarifWriter.createRun("clang", "clang static analyzer", ToolVersion);
202 StringMap<uint32_t> RuleMapping = createRuleMapping(Diags, SarifWriter);
205 SarifWriter.appendResult(Result);
206 }
207 auto Document = SarifWriter.createDocument();
208 OS << llvm::formatv("{0:2}\n", json::Value(std::move(Document)));
209}
Defines the clang::FileManager interface and associated types.
static DiagnosticBuilder Diag(DiagnosticsEngine *Diags, const LangOptions &Features, FullSourceLoc TokLoc, const char *TokBegin, const char *TokRangeBegin, const char *TokRangeEnd, unsigned DiagID)
Produce a diagnostic highlighting some portion of a literal.
Defines the clang::Preprocessor interface.
static StringRef getRuleHelpURIStr(StringRef CheckName)
static CharSourceRange convertTokenRangeToCharRange(const SourceRange &R, const SourceManager &SM, const LangOptions &LO)
Accepts a SourceRange corresponding to a pair of the first and last tokens and converts to a Characte...
static StringRef getRuleDescription(StringRef CheckName)
static SarifResult createResult(const PathDiagnostic *Diag, const StringMap< uint32_t > &RuleMapping, const LangOptions &LO)
static StringMap< uint32_t > createRuleMapping(const std::vector< const PathDiagnostic * > &Diags, SarifDocumentWriter &SarifWriter)
static ThreadFlowImportance calculateImportance(const PathDiagnosticPiece &Piece)
static SmallVector< ThreadFlow, 8 > createThreadFlows(const PathDiagnostic *Diag, const LangOptions &LO)
Defines clang::SarifDocumentWriter, clang::SarifRule, clang::SarifResult.
Defines the SourceManager interface.
Defines version macros and version-related utility functions for Clang.
Represents a character-granular source range.
static CharSourceRange getCharRange(SourceRange R)
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
static SourceLocation getLocForEndOfToken(SourceLocation Loc, unsigned Offset, const SourceManager &SM, const LangOptions &LangOpts)
Computes the source location just past the end of the token at this source location.
MacroExpansionContext tracks the macro expansions processed by the Preprocessor.
Engages in a tight little dance with the lexer to efficiently preprocess tokens.
SourceManager & getSourceManager() const
const LangOptions & getLangOpts() const
This class handles creating a valid SARIF document given various input attributes.
size_t createRule(const SarifRule &Rule)
Associate the given rule with the current run.
A SARIF result (also called a "reporting item") is a unit of output produced when one of the tool's r...
SarifResult setDiagnosticMessage(llvm::StringRef Message)
SarifResult setRuleId(llvm::StringRef Id)
SarifResult setLocations(llvm::ArrayRef< CharSourceRange > DiagLocs)
SarifResult setDiagnosticLevel(const SarifResultLevel &TheLevel)
static SarifResult create(uint32_t RuleIdx)
SarifRule setDescription(llvm::StringRef RuleDesc)
SarifRule setHelpURI(llvm::StringRef RuleHelpURI)
SarifRule setRuleId(llvm::StringRef RuleId)
static SarifRule create()
SarifRule setName(llvm::StringRef RuleName)
Encodes a location in the source.
This class handles loading and caching of source files into memory.
A trivial tuple used to represent a source range.
SourceLocation getEnd() const
SourceLocation getBegin() const
ThreadFlow setImportance(const ThreadFlowImportance &ItemImportance)
ThreadFlow setRange(const CharSourceRange &ItemRange)
static ThreadFlow create()
ThreadFlow setMessage(llvm::StringRef ItemMessage)
This class is used for tools that requires cross translation unit capability.
@ Minimal
Used for SARIF and text output.
virtual bool supportsLogicalOpControlFlow() const
virtual void FlushDiagnosticsImpl(std::vector< const PathDiagnostic * > &Diags, FilesMade *filesMade)=0
virtual bool supportsCrossFileDiagnostics() const
Return true if the PathDiagnosticConsumer supports individual PathDiagnostics that span multiple file...
virtual StringRef getName() const =0
virtual PathGenerationScheme getGenerationScheme() const
StringRef getTagStr() const
Return the string representation of the tag.
PathDiagnostic - PathDiagnostic objects represent a single path-sensitive diagnostic.
A Range represents the closed range [from, to].
std::vector< PathDiagnosticConsumer * > PathDiagnosticConsumers
The JSON file list parser is used to communicate input to InstallAPI.
std::string getClangFullVersion()
Retrieves a string representing the complete clang version, which includes the clang version number,...
Diagnostic wrappers for TextAPI types for error reporting.
These options tweak the behavior of path diangostic consumers.