clang: lib/StaticAnalyzer/Core/SarifDiagnostics.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

23#include "llvm/ADT/StringMap.h"

24#include "llvm/Support/ConvertUTF.h"

25#include "llvm/Support/JSON.h"

26#include

27

28using namespace llvm;

29using namespace clang;

30using namespace ento;

31

32namespace {

34 std::string OutputFile;

35 const LangOptions &LO;

36 const SourceManager &SM;

37 SarifDocumentWriter SarifWriter;

38

39public:

40 SarifDiagnostics(const std::string &Output, const LangOptions &LO,

41 const SourceManager &SM)

42 : OutputFile(Output), LO(LO), SM(SM), SarifWriter(SM) {}

43 ~SarifDiagnostics() override = default;

44

45 void FlushDiagnosticsImpl(std::vector<const PathDiagnostic *> &Diags,

46 FilesMade *FM) override;

47

48 StringRef getName() const override { return "SarifDiagnostics"; }

49 PathGenerationScheme getGenerationScheme() const override { return Minimal; }

50 bool supportsLogicalOpControlFlow() const override { return true; }

51 bool supportsCrossFileDiagnostics() const override { return true; }

52

53private:

54 SarifResult createResult(const PathDiagnostic *Diag,

55 const StringMap<uint32_t> &RuleMapping,

56 const LangOptions &LO, FilesMade *FM);

57};

58}

59

60void ento::createSarifDiagnosticConsumer(

62 const std::string &Output, const Preprocessor &PP,

65

67

68 createTextMinimalPathDiagnosticConsumer(std::move(DiagOpts), C, Output, PP,

69 CTU, MacroExpansions);

70}

71

72

73

76 const std::string &Output, const Preprocessor &PP) {

77

78

79 if (Output.empty())

80 return;

81

82 C.push_back(std::make_unique(Output, PP.getLangOpts(),

84}

85

87 return llvm::StringSwitch(CheckName)

88#define GET_CHECKERS

89#define CHECKER(FULLNAME, CLASS, HELPTEXT, DOC_URI, IS_HIDDEN) \

90 .Case(FULLNAME, HELPTEXT)

91#include "clang/StaticAnalyzer/Checkers/Checkers.inc"

92#undef CHECKER

93#undef GET_CHECKERS

94 ;

95}

96

98 return llvm::StringSwitch(CheckName)

99#define GET_CHECKERS

100#define CHECKER(FULLNAME, CLASS, HELPTEXT, DOC_URI, IS_HIDDEN) \

101 .Case(FULLNAME, DOC_URI)

102#include "clang/StaticAnalyzer/Checkers/Checkers.inc"

103#undef CHECKER

104#undef GET_CHECKERS

105 ;

106}

107

110 switch (Piece.getKind()) {

115

116 break;

118 return Piece.getTagStr() == "ConditionBRVisitor"

123 }

125}

126

127

128

132

133

136

138

139

140

144}

145

149 const PathPieces &Pieces = Diag->path.flatten(false);

150 for (const auto &Piece : Pieces) {

152 Piece->getLocation().asRange(), Piece->getLocation().getManager(), LO);

157 Flows.push_back(Flow);

158 }

159 return Flows;

160}

161

162static StringMap<uint32_t>

165 StringMap<uint32_t> RuleMapping;

166 llvm::StringSet<> Seen;

167

169 StringRef CheckName = D->getCheckerName();

170 std::pair<llvm::StringSet<>::iterator, bool> P = Seen.insert(CheckName);

171 if (P.second) {

177 size_t RuleIdx = SarifWriter.createRule(Rule);

178 RuleMapping[CheckName] = RuleIdx;

179 }

180 }

181 return RuleMapping;

182}

183

184static const llvm::StringRef IssueHashKey = "clang/issueHash/v1";

185

188 const StringMap<uint32_t> &RuleMapping,

190

191 StringRef CheckName = Diag->getCheckerName();

192 uint32_t RuleIdx = RuleMapping.lookup(CheckName);

194 Diag->getLocation().asRange(), Diag->getLocation().getManager(), LO);

195

197

198 auto IssueHash = Diag->getIssueHash(SM, LO);

199

200 std::string HtmlReportURL;

201 if (FM && !FM->empty()) {

202

203 PDFileEntry::ConsumerFiles *Files = FM->getFiles(*Diag);

204 if (Files) {

205 auto HtmlFile = llvm::find_if(*Files, [](const auto &File) {

207 });

208 if (HtmlFile != Files->end()) {

210 llvm::sys::path::parent_path(OutputFile);

211 llvm::sys::path::append(HtmlReportPath, HtmlFile->second);

213 }

214 }

215 }

216

222 .addPartialFingerprint(IssueHashKey, IssueHash)

225 return Result;

226}

227

228void SarifDiagnostics::FlushDiagnosticsImpl(

229 std::vector<const PathDiagnostic *> &Diags, FilesMade *FM) {

230

231

232

233

234

235 std::error_code EC;

236 llvm::raw_fd_ostream OS(OutputFile, EC, llvm::sys::fs::OF_TextWithCRLF);

237 if (EC) {

238 llvm::errs() << "warning: could not create file: " << EC.message() << '\n';

239 return;

240 }

241

243 SarifWriter.createRun("clang", "clang static analyzer", ToolVersion);

244 StringMap<uint32_t> RuleMapping = createRuleMapping(Diags, SarifWriter);

245 for (const PathDiagnostic *D : Diags) {

246 SarifResult Result = createResult(D, RuleMapping, LO, FM);

248 }

250 OS << llvm::formatv("{0:2}\n", json::Value(std::move(Document)));

251}

#define HTML_DIAGNOSTICS_NAME

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)

Definition SarifDiagnostics.cpp:97

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...

Definition SarifDiagnostics.cpp:129

static StringRef getRuleDescription(StringRef CheckName)

Definition SarifDiagnostics.cpp:86

static StringMap< uint32_t > createRuleMapping(const std::vector< const PathDiagnostic * > &Diags, SarifDocumentWriter &SarifWriter)

Definition SarifDiagnostics.cpp:163

static const llvm::StringRef IssueHashKey

Definition SarifDiagnostics.cpp:184

static ThreadFlowImportance calculateImportance(const PathDiagnosticPiece &Piece)

Definition SarifDiagnostics.cpp:109

static SmallVector< ThreadFlow, 8 > createThreadFlows(const PathDiagnostic *Diag, const LangOptions &LO)

Definition SarifDiagnostics.cpp:146

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.

void createRun(const llvm::StringRef ShortToolName, const llvm::StringRef LongToolName, const llvm::StringRef ToolVersion=CLANG_VERSION_STRING)

Create a new run with which any upcoming analysis will be associated.

size_t createRule(const SarifRule &Rule)

Associate the given rule with the current run.

static std::string fileNameToURI(llvm::StringRef Filename)

llvm::json::Object createDocument()

Return the SARIF document in its current state.

void appendResult(const SarifResult &SarifResult)

Append a new result to the currently in-flight run.

A SARIF result (also called a "reporting item") is a unit of output produced when one of the tool's r...

SarifResult setHostedViewerURI(llvm::StringRef URI)

SarifResult setThreadFlows(llvm::ArrayRef< ThreadFlow > ThreadFlowResults)

SarifResult setDiagnosticMessage(llvm::StringRef Message)

SarifResult setRuleId(llvm::StringRef Id)

SarifResult addLocations(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.

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< std::unique_ptr< PathDiagnosticConsumer > > PathDiagnosticConsumers

@ OS

Indicates that the tracking object is a descendant of a referenced-counted OSObject,...

void createSarifDiagnosticConsumerImpl(PathDiagnosticConsumerOptions DiagOpts, PathDiagnosticConsumers &C, const std::string &Output, const Preprocessor &PP)

Creates and registers a SARIF diagnostic consumer, without any additional text consumer.

Definition SarifDiagnostics.cpp:74

StringRef getName(const HeaderType T)

The JSON file list parser is used to communicate input to InstallAPI.

@ Result

The result type of a method or function.

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.