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.