clang 22.0.0git
SARIFDiagnostic.cpp
Go to the documentation of this file.
1//===--------- SARIFDiagnostic.cpp - SARIF Diagnostic Formatting ----------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
13#include "clang/Basic/Sarif.h"
16#include "clang/Lex/Lexer.h"
17#include "llvm/ADT/ArrayRef.h"
18#include "llvm/ADT/SmallString.h"
19#include "llvm/ADT/StringExtras.h"
20#include "llvm/ADT/StringRef.h"
21#include "llvm/Support/Casting.h"
22#include "llvm/Support/ConvertUTF.h"
23#include "llvm/Support/ErrorHandling.h"
24#include "llvm/Support/ErrorOr.h"
25#include "llvm/Support/Locale.h"
26#include "llvm/Support/Path.h"
27#include "llvm/Support/raw_ostream.h"
28#include <algorithm>
29#include <string>
30
31namespace clang {
32
37
38// FIXME(llvm-project/issues/57323): Refactor Diagnostic classes.
41 StringRef Message, ArrayRef<clang::CharSourceRange> Ranges,
43
44 const auto *Diag = D.dyn_cast<const Diagnostic *>();
45
46 if (!Diag)
47 return;
48
49 SarifRule Rule = SarifRule::create().setRuleId(std::to_string(Diag->getID()));
50
51 Rule = addDiagnosticLevelToRule(Rule, Level);
52
53 unsigned RuleIdx = Writer->createRule(Rule);
54
57
58 if (Loc.isValid())
59 Result = addLocationToResult(Result, Loc, PLoc, Ranges, *Diag);
60
61 Writer->appendResult(Result);
62}
63
64SarifResult SARIFDiagnostic::addLocationToResult(
67 SmallVector<CharSourceRange> Locations = {};
68
69 if (PLoc.isInvalid()) {
70 // At least add the file name if available:
71 FileID FID = Loc.getFileID();
72 if (FID.isValid()) {
74 emitFilename(FE->getName(), Loc.getManager());
75 // FIXME(llvm-project/issues/57366): File-only locations
76 }
77 }
78 return Result;
79 }
80
81 FileID CaretFileID = Loc.getExpansionLoc().getFileID();
82
83 for (const CharSourceRange Range : Ranges) {
84 // Ignore invalid ranges.
85 if (Range.isInvalid())
86 continue;
87
88 auto &SM = Loc.getManager();
89 SourceLocation B = SM.getExpansionLoc(Range.getBegin());
90 CharSourceRange ERange = SM.getExpansionRange(Range.getEnd());
91 SourceLocation E = ERange.getEnd();
92 bool IsTokenRange = ERange.isTokenRange();
93
94 FileIDAndOffset BInfo = SM.getDecomposedLoc(B);
95 FileIDAndOffset EInfo = SM.getDecomposedLoc(E);
96
97 // If the start or end of the range is in another file, just discard
98 // it.
99 if (BInfo.first != CaretFileID || EInfo.first != CaretFileID)
100 continue;
101
102 // Add in the length of the token, so that we cover multi-char
103 // tokens.
104 unsigned TokSize = 0;
105 if (IsTokenRange)
107
108 FullSourceLoc BF(B, SM), EF(E, SM);
109 SourceLocation BeginLoc = SM.translateLineCol(
110 BF.getFileID(), BF.getLineNumber(), BF.getColumnNumber());
111 SourceLocation EndLoc = SM.translateLineCol(
112 EF.getFileID(), EF.getLineNumber(), EF.getColumnNumber() + TokSize);
113
114 Locations.push_back(
115 CharSourceRange{SourceRange{BeginLoc, EndLoc}, /* ITR = */ false});
116 // FIXME: Additional ranges should use presumed location in both
117 // Text and SARIF diagnostics.
118 }
119
120 auto &SM = Loc.getManager();
121 auto FID = PLoc.getFileID();
122 // Visual Studio 2010 or earlier expects column number to be off by one.
123 unsigned int ColNo = (LangOpts.MSCompatibilityVersion &&
124 !LangOpts.isCompatibleWithMSVC(LangOptions::MSVC2012))
125 ? PLoc.getColumn() - 1
126 : PLoc.getColumn();
127 SourceLocation DiagLoc = SM.translateLineCol(FID, PLoc.getLine(), ColNo);
128
129 // FIXME(llvm-project/issues/57366): Properly process #line directives.
130 Locations.push_back(
131 CharSourceRange{SourceRange{DiagLoc, DiagLoc}, /* ITR = */ false});
132
133 return Result.setLocations(Locations);
134}
135
137SARIFDiagnostic::addDiagnosticLevelToRule(SarifRule Rule,
140
141 switch (Level) {
143 Config = Config.setLevel(SarifResultLevel::Note);
144 break;
146 Config = Config.setLevel(SarifResultLevel::None);
147 break;
149 Config = Config.setLevel(SarifResultLevel::Warning);
150 break;
152 Config = Config.setLevel(SarifResultLevel::Error).setRank(50);
153 break;
155 Config = Config.setLevel(SarifResultLevel::Error).setRank(100);
156 break;
158 assert(false && "Invalid diagnostic type");
159 }
160
161 return Rule.setDefaultConfiguration(Config);
162}
163
164llvm::StringRef SARIFDiagnostic::emitFilename(StringRef Filename,
165 const SourceManager &SM) {
166 if (DiagOpts.AbsolutePath) {
167 auto File = SM.getFileManager().getOptionalFileRef(Filename);
168 if (File) {
169 // We want to print a simplified absolute path, i. e. without "dots".
170 //
171 // The hardest part here are the paths like "<part1>/<link>/../<part2>".
172 // On Unix-like systems, we cannot just collapse "<link>/..", because
173 // paths are resolved sequentially, and, thereby, the path
174 // "<part1>/<part2>" may point to a different location. That is why
175 // we use FileManager::getCanonicalName(), which expands all indirections
176 // with llvm::sys::fs::real_path() and caches the result.
177 //
178 // On the other hand, it would be better to preserve as much of the
179 // original path as possible, because that helps a user to recognize it.
180 // real_path() expands all links, which is sometimes too much. Luckily,
181 // on Windows we can just use llvm::sys::path::remove_dots(), because,
182 // on that system, both aforementioned paths point to the same place.
183#ifdef _WIN32
184 SmallString<256> TmpFilename = File->getName();
185 llvm::sys::fs::make_absolute(TmpFilename);
186 llvm::sys::path::native(TmpFilename);
187 llvm::sys::path::remove_dots(TmpFilename, /* remove_dot_dot */ true);
188 Filename = StringRef(TmpFilename.data(), TmpFilename.size());
189#else
190 Filename = SM.getFileManager().getCanonicalName(*File);
191#endif
192 }
193 }
194
195 return Filename;
196}
197
198/// Print out the file/line/column information and include trace.
199///
200/// This method handlen the emission of the diagnostic location information.
201/// This includes extracting as much location information as is present for
202/// the diagnostic and printing it, as well as any include stack or source
203/// ranges necessary.
207 assert(false && "Not implemented in SARIF mode");
208}
209
211 assert(false && "Not implemented in SARIF mode");
212}
213
215 StringRef ModuleName) {
216 assert(false && "Not implemented in SARIF mode");
217}
218
220 PresumedLoc PLoc,
221 StringRef ModuleName) {
222 assert(false && "Not implemented in SARIF mode");
223}
224} // namespace clang
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.
#define SM(sm)
Defines clang::SarifDocumentWriter, clang::SarifRule, clang::SarifResult.
Defines the clang::SourceLocation class and associated facilities.
Defines the SourceManager interface.
Options for controlling the compiler diagnostics engine.
const LangOptions & LangOpts
DiagnosticOptions & DiagOpts
DiagnosticRenderer(const LangOptions &LangOpts, DiagnosticOptions &DiagOpts)
A little helper class (which is basically a smart pointer that forwards info from DiagnosticsEngine a...
Level
The level of the diagnostic, after it has been through mapping.
Definition Diagnostic.h:236
A SourceLocation and its associated SourceManager.
FullSourceLoc getExpansionLoc() const
OptionalFileEntryRef getFileEntryRef() const
const SourceManager & getManager() const
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
static unsigned MeasureTokenLength(SourceLocation Loc, const SourceManager &SM, const LangOptions &LangOpts)
MeasureTokenLength - Relex the token at the specified location and return its length in bytes in the ...
Definition Lexer.cpp:498
Represents an unpacked "presumed" location which can be presented to the user.
unsigned getColumn() const
Return the presumed column number of this location.
unsigned getLine() const
Return the presumed line number of this location.
bool isInvalid() const
Return true if this object is invalid or uninitialized.
FileID getFileID() const
SARIFDiagnostic(raw_ostream &OS, const LangOptions &LangOpts, DiagnosticOptions &DiagOpts, SarifDocumentWriter *Writer)
void emitIncludeLocation(FullSourceLoc Loc, PresumedLoc PLoc) override
void emitDiagnosticMessage(FullSourceLoc Loc, PresumedLoc PLoc, DiagnosticsEngine::Level Level, StringRef Message, ArrayRef< CharSourceRange > Ranges, DiagOrStoredDiag D) override
void emitDiagnosticLoc(FullSourceLoc Loc, PresumedLoc PLoc, DiagnosticsEngine::Level Level, ArrayRef< CharSourceRange > Ranges) override
Print out the file/line/column information and include trace.
void emitImportLocation(FullSourceLoc Loc, PresumedLoc PLoc, StringRef ModuleName) override
void emitBuildingModuleLocation(FullSourceLoc Loc, PresumedLoc PLoc, StringRef ModuleName) override
This class handles creating a valid SARIF document given various input attributes.
Definition Sarif.h:380
static SarifReportingConfiguration create()
Definition Sarif.h:221
A SARIF result (also called a "reporting item") is a unit of output produced when one of the tool's r...
Definition Sarif.h:315
SarifResult setDiagnosticMessage(llvm::StringRef Message)
Definition Sarif.h:345
static SarifResult create(uint32_t RuleIdx)
Definition Sarif.h:333
A SARIF rule (reportingDescriptor object) contains information that describes a reporting item genera...
Definition Sarif.h:257
SarifRule setRuleId(llvm::StringRef RuleId)
Definition Sarif.h:276
static SarifRule create()
Definition Sarif.h:269
bool isValid() const
Return true if this is a valid SourceLocation object.
This class handles loading and caching of source files into memory.
SourceLocation getExpansionLoc(SourceLocation Loc) const
Given a SourceLocation object Loc, return the expansion location referenced by the ID.
const Regex Rule("(.+)/(.+)\\.framework/")
The JSON file list parser is used to communicate input to InstallAPI.
CustomizableOptional< FileEntryRef > OptionalFileEntryRef
Definition FileEntry.h:208
llvm::PointerUnion< const Diagnostic *, const StoredDiagnostic * > DiagOrStoredDiag
std::pair< FileID, unsigned > FileIDAndOffset
@ Result
The result type of a method or function.
Definition TypeBase.h:905