clang 24.0.0git
BackendDiagnosticHandler.cpp
Go to the documentation of this file.
1//===--- BackendDiagnosticHandler.cpp - Shared Backend Diagnostics ------===//
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
15#include "llvm/ADT/Hashing.h"
16#include "llvm/CodeGen/MachineOptimizationRemarkEmitter.h"
17#include "llvm/Demangle/Demangle.h"
18#include "llvm/IR/DiagnosticInfo.h"
19#include "llvm/IR/DiagnosticPrinter.h"
20#include "llvm/IR/Function.h"
21#include "llvm/IR/Module.h"
22#include "llvm/Support/raw_ostream.h"
23
24using namespace clang;
25using namespace llvm;
26
27namespace {
28/// Forwards llvm::DiagnosticHandler callbacks into a BackendDiagnosticConsumer.
29class BackendDiagnosticHandlerImpl final : public DiagnosticHandler {
30public:
31 BackendDiagnosticHandlerImpl(const CodeGenOptions &CGOpts,
32 BackendDiagnosticConsumer *Consumer)
33 : CodeGenOpts(CGOpts), Consumer(Consumer) {}
34
35 bool handleDiagnostics(const DiagnosticInfo &DI) override {
36 Consumer->handleDiagnostics(DI);
37 return true;
38 }
39
40 bool isAnalysisRemarkEnabled(StringRef PassName) const override {
41 return CodeGenOpts.OptimizationRemarkAnalysis.patternMatches(PassName);
42 }
43 bool isMissedOptRemarkEnabled(StringRef PassName) const override {
44 return CodeGenOpts.OptimizationRemarkMissed.patternMatches(PassName);
45 }
46 bool isPassedOptRemarkEnabled(StringRef PassName) const override {
47 return CodeGenOpts.OptimizationRemark.patternMatches(PassName);
48 }
49
50 bool isAnyRemarkEnabled() const override {
51 return CodeGenOpts.OptimizationRemarkAnalysis.hasValidPattern() ||
52 CodeGenOpts.OptimizationRemarkMissed.hasValidPattern() ||
53 CodeGenOpts.OptimizationRemark.hasValidPattern();
54 }
55
56private:
57 const CodeGenOptions &CodeGenOpts;
58 BackendDiagnosticConsumer *Consumer;
59};
60
61/// Convert a location in a temporary llvm::SourceMgr buffer to be a valid
62/// FullSourceLoc.
63FullSourceLoc ConvertBackendLocation(const llvm::SMDiagnostic &D,
64 SourceManager &CSM) {
65 // Get both the clang and llvm source managers. The location is relative to
66 // a memory buffer that the LLVM Source Manager is handling, we need to add
67 // a copy to the Clang source manager.
68 const llvm::SourceMgr &LSM = *D.getSourceMgr();
69
70 // We need to copy the underlying LLVM memory buffer because llvm::SourceMgr
71 // already owns its one and clang::SourceManager wants to own its one.
72 const MemoryBuffer *LBuf =
73 LSM.getMemoryBuffer(LSM.FindBufferContainingLoc(D.getLoc()));
74
75 // Create the copy and transfer ownership to clang::SourceManager.
76 // TODO: Avoid copying files into memory.
77 std::unique_ptr<llvm::MemoryBuffer> CBuf =
78 llvm::MemoryBuffer::getMemBufferCopy(LBuf->getBuffer(),
79 LBuf->getBufferIdentifier());
80 // FIXME: Keep a file ID map instead of creating new IDs for each location.
81 FileID FID = CSM.createFileID(std::move(CBuf));
82
83 // Translate the offset into the file.
84 unsigned Offset = D.getLoc().getPointer() - LBuf->getBufferStart();
85 SourceLocation NewLoc =
87 return FullSourceLoc(NewLoc, CSM);
88}
89
90} // namespace
91
92#define ComputeDiagID(Severity, GroupName, DiagID) \
93 do { \
94 switch (Severity) { \
95 case llvm::DS_Error: \
96 DiagID = diag::err_fe_##GroupName; \
97 break; \
98 case llvm::DS_Warning: \
99 DiagID = diag::warn_fe_##GroupName; \
100 break; \
101 case llvm::DS_Remark: \
102 llvm_unreachable("'remark' severity not expected"); \
103 break; \
104 case llvm::DS_Note: \
105 DiagID = diag::note_fe_##GroupName; \
106 break; \
107 } \
108 } while (false)
109
110#define ComputeDiagRemarkID(Severity, GroupName, DiagID) \
111 do { \
112 switch (Severity) { \
113 case llvm::DS_Error: \
114 DiagID = diag::err_fe_##GroupName; \
115 break; \
116 case llvm::DS_Warning: \
117 DiagID = diag::warn_fe_##GroupName; \
118 break; \
119 case llvm::DS_Remark: \
120 DiagID = diag::remark_fe_##GroupName; \
121 break; \
122 case llvm::DS_Note: \
123 DiagID = diag::note_fe_##GroupName; \
124 break; \
125 } \
126 } while (false)
127
128std::unique_ptr<llvm::DiagnosticHandler>
130 return std::make_unique<BackendDiagnosticHandlerImpl>(CodeGenOpts, this);
131}
132
134 FullSourceLoc Loc) {
135 // TODO: use a fast content hash when available.
136 auto NameHash = llvm::hash_value(MangledName);
137 ManglingFullSourceLocs.push_back(std::make_pair(NameHash, Loc));
138}
139
140std::optional<FullSourceLoc>
142 auto Hash = llvm::hash_value(F.getName());
143 for (const auto &Pair : ManglingFullSourceLocs) {
144 if (Pair.first == Hash)
145 return Pair.second;
146 }
147 return std::nullopt;
148}
149
151 const llvm::DiagnosticInfoWithLocationBase &D, bool &BadDebugInfo,
152 StringRef &Filename, unsigned &Line, unsigned &Column) const {
153 SourceManager &SourceMgr = *SM;
154 FileManager &FileMgr = SourceMgr.getFileManager();
155 SourceLocation DILoc;
156
157 if (D.isLocationAvailable()) {
158 D.getLocation(Filename, Line, Column);
159 if (Line > 0) {
160 auto FE = FileMgr.getOptionalFileRef(Filename);
161 if (!FE)
162 FE = FileMgr.getOptionalFileRef(D.getAbsolutePath());
163 if (FE) {
164 // If -gcolumn-info was not used, Column will be 0. This upsets the
165 // source manager, so pass 1 if Column is not set.
166 DILoc = SourceMgr.translateFileLineCol(*FE, Line, Column ? Column : 1);
167 }
168 }
169 BadDebugInfo = DILoc.isInvalid();
170 }
171
172 // If a location isn't available, try to approximate it using the associated
173 // function definition. We use the definition's right brace to differentiate
174 // from diagnostics that genuinely relate to the function itself.
175 FullSourceLoc Loc(DILoc, SourceMgr);
176 if (Loc.isInvalid()) {
177 if (auto MaybeLoc = getFunctionSourceLocation(D.getFunction()))
178 Loc = *MaybeLoc;
179 }
180
181 if (DILoc.isInvalid() && D.isLocationAvailable())
182 // If we were not able to translate the file:line:col information
183 // back to a SourceLocation, at least emit a note stating that
184 // we could not translate this location. This can happen in the
185 // case of #line directives.
186 Diags.Report(Loc, diag::note_fe_backend_invalid_loc)
187 << Filename << Line << Column;
188
189 return Loc;
190}
191
192void BackendDiagnosticConsumer::SrcMgrDiagHandler(
193 const llvm::DiagnosticInfoSrcMgr &DI) {
194 const llvm::SMDiagnostic &D = DI.getSMDiag();
195
196 unsigned DiagID;
197 if (DI.isInlineAsmDiag())
198 ComputeDiagID(DI.getSeverity(), inline_asm, DiagID);
199 else
200 ComputeDiagID(DI.getSeverity(), source_mgr, DiagID);
201
202 // This is for the empty consumer that uses the clang diagnostic
203 // handler for IR input files.
204 if (!SM) {
205 D.print(nullptr, llvm::errs());
206 Diags.Report(DiagID).AddString("cannot compile inline asm");
207 return;
208 }
209
210 // There are a couple of different kinds of errors we could get here.
211 // First, we re-format the SMDiagnostic in terms of a clang diagnostic.
212
213 // Strip "error: " off the start of the message string.
214 StringRef Message = D.getMessage();
215 (void)Message.consume_front("error: ");
216
217 // If the SMDiagnostic has an inline asm source location, translate it.
218 FullSourceLoc Loc;
219 if (D.getLoc() != SMLoc())
220 Loc = ConvertBackendLocation(D, *SM);
221
222 // If this problem has clang-level source location information, report the
223 // issue in the source with a note showing the instantiated
224 // code.
225 if (DI.isInlineAsmDiag()) {
226 SourceLocation LocCookie =
227 SourceLocation::getFromRawEncoding(DI.getLocCookie());
228 if (LocCookie.isValid()) {
229 Diags.Report(LocCookie, DiagID).AddString(Message);
230
231 if (D.getLoc().isValid()) {
232 DiagnosticBuilder B = Diags.Report(Loc, diag::note_fe_inline_asm_here);
233 // Convert the SMDiagnostic ranges into SourceRange and attach them
234 // to the diagnostic.
235 for (const std::pair<unsigned, unsigned> &Range : D.getRanges()) {
236 unsigned Column = D.getColumnNo();
237 B << SourceRange(Loc.getLocWithOffset(Range.first - Column),
238 Loc.getLocWithOffset(Range.second - Column));
239 }
240 }
241 return;
242 }
243 }
244
245 // Otherwise, report the backend issue as occurring in the generated .s file.
246 // If Loc is invalid, we still need to report the issue, it just gets no
247 // location info.
248 Diags.Report(Loc, DiagID).AddString(Message);
249}
250
251bool BackendDiagnosticConsumer::InlineAsmDiagHandler(
252 const llvm::DiagnosticInfoInlineAsm &D) {
253 unsigned DiagID;
254 ComputeDiagID(D.getSeverity(), inline_asm, DiagID);
255 std::string Message = D.getMsgStr().str();
256
257 // If this problem has clang-level source location information, report the
258 // issue as being a problem in the source with a note showing the instantiated
259 // code.
260 SourceLocation LocCookie =
261 SourceLocation::getFromRawEncoding(D.getLocCookie());
262 if (LocCookie.isValid())
263 Diags.Report(LocCookie, DiagID).AddString(Message);
264 else {
265 // Otherwise, report the backend diagnostic as occurring in the generated
266 // .s file.
267 // If Loc is invalid, we still need to report the diagnostic, it just gets
268 // no location info.
269 FullSourceLoc Loc;
270 Diags.Report(Loc, DiagID).AddString(Message);
271 }
272 // We handled all the possible severities.
273 return true;
274}
275
276bool BackendDiagnosticConsumer::StackSizeDiagHandler(
277 const llvm::DiagnosticInfoStackSize &D) {
278 if (D.getSeverity() != llvm::DS_Warning)
279 // For now, the only support we have for StackSize diagnostic is warning.
280 // We do not know how to format other severities.
281 return false;
282
283 auto Loc = getFunctionSourceLocation(D.getFunction());
284 if (!Loc)
285 return false;
286
287 Diags.Report(*Loc, diag::warn_fe_frame_larger_than)
288 << D.getStackSize() << D.getStackLimit()
289 << llvm::demangle(D.getFunction().getName());
290 return true;
291}
292
293bool BackendDiagnosticConsumer::ResourceLimitDiagHandler(
294 const llvm::DiagnosticInfoResourceLimit &D) {
295 auto Loc = getFunctionSourceLocation(D.getFunction());
296 if (!Loc)
297 return false;
298 unsigned DiagID = diag::err_fe_backend_resource_limit;
299 ComputeDiagID(D.getSeverity(), backend_resource_limit, DiagID);
300
301 Diags.Report(*Loc, DiagID)
302 << D.getResourceName() << D.getResourceSize() << D.getResourceLimit()
303 << llvm::demangle(D.getFunction().getName());
304 return true;
305}
306
307void BackendDiagnosticConsumer::UnsupportedDiagHandler(
308 const llvm::DiagnosticInfoUnsupported &D) {
309 // We only support warnings or errors.
310 assert(D.getSeverity() == llvm::DS_Error ||
311 D.getSeverity() == llvm::DS_Warning);
312
313 StringRef Filename;
314 unsigned Line, Column;
315 bool BadDebugInfo = false;
316 FullSourceLoc Loc;
317 std::string Msg;
318 raw_string_ostream MsgStream(Msg);
319
320 // SM will be null for IR input files, we will construct the diag
321 // message from llvm::DiagnosticInfoUnsupported.
322 if (SM != nullptr) {
323 Loc = getBestLocationFromDebugLoc(D, BadDebugInfo, Filename, Line, Column);
324 MsgStream << D.getMessage();
325 } else {
326 DiagnosticPrinterRawOStream DP(MsgStream);
327 D.print(DP);
328 }
329
330 auto DiagType = D.getSeverity() == llvm::DS_Error
331 ? diag::err_fe_backend_unsupported
332 : diag::warn_fe_backend_unsupported;
333 Diags.Report(Loc, DiagType) << Msg;
334
335 if (BadDebugInfo)
336 // If we were not able to translate the file:line:col information
337 // back to a SourceLocation, at least emit a note stating that
338 // we could not translate this location. This can happen in the
339 // case of #line directives.
340 Diags.Report(Loc, diag::note_fe_backend_invalid_loc)
341 << Filename << Line << Column;
342}
343
344void BackendDiagnosticConsumer::UnsupportedTargetIntrinsicDiagHandler(
345 const llvm::DiagnosticInfoUnsupportedTargetIntrinsic &D) {
346 assert(D.getSeverity() == llvm::DS_Error &&
347 "unsupported target intrinsic diagnostic should be an error");
348
349 StringRef Filename;
350 unsigned Line, Column;
351 bool BadDebugInfo = false;
352 FullSourceLoc Loc;
353 std::string Msg;
354 raw_string_ostream MsgStream(Msg);
355
356 // SM will be null for IR input files, so construct the diagnostic
357 // message from llvm::DiagnosticInfoUnsupportedTargetIntrinsic.
358 if (SM != nullptr) {
359 Loc = getBestLocationFromDebugLoc(D, BadDebugInfo, Filename, Line, Column);
360 MsgStream << D.getMessage();
361 } else {
362 DiagnosticPrinterRawOStream DP(MsgStream);
363 D.print(DP);
364 }
365
366 Diags.Report(Loc, diag::err_fe_backend_unsupported) << Msg;
367
368 if (BadDebugInfo) {
369 // If we were not able to translate the file:line:col information
370 // back to a SourceLocation, at least emit a note stating that
371 // we could not translate this location. This can happen in the
372 // case of #line directives.
373 Diags.Report(Loc, diag::note_fe_backend_invalid_loc)
374 << Filename << Line << Column;
375 }
376}
377
378void BackendDiagnosticConsumer::EmitOptimizationMessage(
379 const llvm::DiagnosticInfoOptimizationBase &D, unsigned DiagID) {
380 // We only support warnings and remarks.
381 assert(D.getSeverity() == llvm::DS_Remark ||
382 D.getSeverity() == llvm::DS_Warning);
383
384 StringRef Filename;
385 unsigned Line, Column;
386 bool BadDebugInfo = false;
387 FullSourceLoc Loc;
388 std::string Msg;
389 raw_string_ostream MsgStream(Msg);
390
391 // SM will be null for IR input files, we will construct the remark
392 // message from llvm::DiagnosticInfoOptimizationBase.
393 if (SM != nullptr) {
394 Loc = getBestLocationFromDebugLoc(D, BadDebugInfo, Filename, Line, Column);
395 MsgStream << D.getMsg();
396 } else {
397 DiagnosticPrinterRawOStream DP(MsgStream);
398 D.print(DP);
399 }
400
401 if (D.getHotness())
402 MsgStream << " (hotness: " << *D.getHotness() << ")";
403
404 Diags.Report(Loc, DiagID) << AddFlagValue(D.getPassName()) << Msg;
405
406 if (BadDebugInfo)
407 // If we were not able to translate the file:line:col information
408 // back to a SourceLocation, at least emit a note stating that
409 // we could not translate this location. This can happen in the
410 // case of #line directives.
411 Diags.Report(Loc, diag::note_fe_backend_invalid_loc)
412 << Filename << Line << Column;
413}
414
415void BackendDiagnosticConsumer::OptimizationRemarkHandler(
416 const llvm::DiagnosticInfoOptimizationBase &D) {
417 // Without hotness information, don't show noisy remarks.
418 if (D.isVerbose() && !D.getHotness())
419 return;
420
421 if (D.isPassed()) {
422 // Optimization remarks are active only if the -Rpass flag has a regular
423 // expression that matches the name of the pass name in \p D.
424 if (CodeGenOpts.OptimizationRemark.patternMatches(D.getPassName()))
425 EmitOptimizationMessage(D, diag::remark_fe_backend_optimization_remark);
426 } else if (D.isMissed()) {
427 // Missed optimization remarks are active only if the -Rpass-missed
428 // flag has a regular expression that matches the name of the pass
429 // name in \p D.
430 if (CodeGenOpts.OptimizationRemarkMissed.patternMatches(D.getPassName()))
431 EmitOptimizationMessage(
432 D, diag::remark_fe_backend_optimization_remark_missed);
433 } else {
434 assert(D.isAnalysis() && "Unknown remark type");
435
436 bool ShouldAlwaysPrint = false;
437 if (auto *ORA = dyn_cast<llvm::OptimizationRemarkAnalysis>(&D))
438 ShouldAlwaysPrint = ORA->shouldAlwaysPrint();
439
440 if (ShouldAlwaysPrint ||
441 CodeGenOpts.OptimizationRemarkAnalysis.patternMatches(D.getPassName()))
442 EmitOptimizationMessage(
443 D, diag::remark_fe_backend_optimization_remark_analysis);
444 }
445}
446
447void BackendDiagnosticConsumer::OptimizationRemarkHandler(
448 const llvm::OptimizationRemarkAnalysisFPCommute &D) {
449 // Optimization analysis remarks are active if the pass name is set to
450 // llvm::DiagnosticInfo::AlwaysPrint or if the -Rpass-analysis flag has a
451 // regular expression that matches the name of the pass name in \p D.
452
453 if (D.shouldAlwaysPrint() ||
454 CodeGenOpts.OptimizationRemarkAnalysis.patternMatches(D.getPassName()))
455 EmitOptimizationMessage(
456 D, diag::remark_fe_backend_optimization_remark_analysis_fpcommute);
457}
458
459void BackendDiagnosticConsumer::OptimizationRemarkHandler(
460 const llvm::OptimizationRemarkAnalysisAliasing &D) {
461 // Optimization analysis remarks are active if the pass name is set to
462 // llvm::DiagnosticInfo::AlwaysPrint or if the -Rpass-analysis flag has a
463 // regular expression that matches the name of the pass name in \p D.
464
465 if (D.shouldAlwaysPrint() ||
466 CodeGenOpts.OptimizationRemarkAnalysis.patternMatches(D.getPassName()))
467 EmitOptimizationMessage(
468 D, diag::remark_fe_backend_optimization_remark_analysis_aliasing);
469}
470
471void BackendDiagnosticConsumer::OptimizationFailureHandler(
472 const llvm::DiagnosticInfoOptimizationFailure &D) {
473 EmitOptimizationMessage(D, diag::warn_fe_backend_optimization_failure);
474}
475
476void BackendDiagnosticConsumer::DontCallDiagHandler(
477 const DiagnosticInfoDontCall &D) {
478 SourceLocation LocCookie =
479 SourceLocation::getFromRawEncoding(D.getLocCookie());
480
481 // FIXME: we can't yet diagnose indirect calls. When/if we can, we
482 // should instead assert that LocCookie.isValid().
483 if (!LocCookie.isValid())
484 return;
485
486 Diags.Report(LocCookie, D.getSeverity() == DiagnosticSeverity::DS_Error
487 ? diag::err_fe_backend_error_attr
488 : diag::warn_fe_backend_warning_attr)
489 << llvm::demangle(D.getFunctionName()) << D.getNote();
490
491 if (!CodeGenOpts.ShowInliningChain)
492 return;
493
494 auto EmitNote = [&](SourceLocation Loc, StringRef FuncName, bool IsFirst) {
495 if (!Loc.isValid())
496 Loc = LocCookie;
497 unsigned DiagID =
498 IsFirst ? diag::note_fe_backend_in : diag::note_fe_backend_inlined;
499 Diags.Report(Loc, DiagID) << llvm::demangle(FuncName.str());
500 };
501
502 // Try debug info first for accurate source locations.
503 if (!D.getDebugInlineChain().empty()) {
504 SourceManager &SrcMgr = *SM;
505 FileManager &FM = SrcMgr.getFileManager();
506 for (const auto &[I, Info] : llvm::enumerate(D.getDebugInlineChain())) {
507 SourceLocation Loc;
508 if (Info.Line > 0)
509 if (auto FE = FM.getOptionalFileRef(Info.Filename))
510 Loc = SrcMgr.translateFileLineCol(*FE, Info.Line,
511 Info.Column ? Info.Column : 1);
512 EmitNote(Loc, Info.FuncName, I == 0);
513 }
514 return;
515 }
516
517 // Fall back to heuristic (srcloc metadata) when debug info is unavailable.
518 auto InliningDecisions = D.getInliningDecisions();
519 if (InliningDecisions.empty())
520 return;
521
522 for (const auto &[I, Entry] : llvm::enumerate(InliningDecisions)) {
523 SourceLocation Loc =
524 I == 0 ? LocCookie : SourceLocation::getFromRawEncoding(Entry.second);
525 EmitNote(Loc, Entry.first, I == 0);
526 }
527
528 // Suggest enabling debug info (at least -gline-directives-only) for more
529 // accurate locations.
530 Diags.Report(LocCookie, diag::note_fe_backend_inlining_debug_info);
531}
532
533void BackendDiagnosticConsumer::MisExpectDiagHandler(
534 const llvm::DiagnosticInfoMisExpect &D) {
535 StringRef Filename;
536 unsigned Line, Column;
537 bool BadDebugInfo = false;
538 FullSourceLoc Loc =
539 getBestLocationFromDebugLoc(D, BadDebugInfo, Filename, Line, Column);
540
541 Diags.Report(Loc, diag::warn_profile_data_misexpect) << D.getMsg().str();
542
543 if (BadDebugInfo)
544 // If we were not able to translate the file:line:col information
545 // back to a SourceLocation, at least emit a note stating that
546 // we could not translate this location. This can happen in the
547 // case of #line directives.
548 Diags.Report(Loc, diag::note_fe_backend_invalid_loc)
549 << Filename << Line << Column;
550}
551
552void BackendDiagnosticConsumer::handleDiagnostics(const DiagnosticInfo &DI) {
553 unsigned DiagID = diag::err_fe_inline_asm;
554 llvm::DiagnosticSeverity Severity = DI.getSeverity();
555 // Get the diagnostic ID based.
556 switch (DI.getKind()) {
557 case llvm::DK_InlineAsm:
558 if (InlineAsmDiagHandler(cast<DiagnosticInfoInlineAsm>(DI)))
559 return;
560 ComputeDiagID(Severity, inline_asm, DiagID);
561 break;
562 case llvm::DK_SrcMgr:
563 SrcMgrDiagHandler(cast<DiagnosticInfoSrcMgr>(DI));
564 return;
565 case llvm::DK_StackSize:
566 if (StackSizeDiagHandler(cast<DiagnosticInfoStackSize>(DI)))
567 return;
568 ComputeDiagID(Severity, backend_frame_larger_than, DiagID);
569 break;
570 case llvm::DK_ResourceLimit:
571 if (ResourceLimitDiagHandler(cast<DiagnosticInfoResourceLimit>(DI)))
572 return;
573 ComputeDiagID(Severity, backend_resource_limit, DiagID);
574 break;
575 case DK_Linker:
576 ComputeDiagID(Severity, linking_module, DiagID);
577 break;
578 case llvm::DK_OptimizationRemark:
579 // Optimization remarks are always handled completely by this
580 // handler. There is no generic way of emitting them.
581 OptimizationRemarkHandler(cast<OptimizationRemark>(DI));
582 return;
583 case llvm::DK_OptimizationRemarkMissed:
584 // Optimization remarks are always handled completely by this
585 // handler. There is no generic way of emitting them.
586 OptimizationRemarkHandler(cast<OptimizationRemarkMissed>(DI));
587 return;
588 case llvm::DK_OptimizationRemarkAnalysis:
589 // Optimization remarks are always handled completely by this
590 // handler. There is no generic way of emitting them.
591 OptimizationRemarkHandler(cast<OptimizationRemarkAnalysis>(DI));
592 return;
593 case llvm::DK_OptimizationRemarkAnalysisFPCommute:
594 // Optimization remarks are always handled completely by this
595 // handler. There is no generic way of emitting them.
596 OptimizationRemarkHandler(cast<OptimizationRemarkAnalysisFPCommute>(DI));
597 return;
598 case llvm::DK_OptimizationRemarkAnalysisAliasing:
599 // Optimization remarks are always handled completely by this
600 // handler. There is no generic way of emitting them.
601 OptimizationRemarkHandler(cast<OptimizationRemarkAnalysisAliasing>(DI));
602 return;
603 case llvm::DK_MachineOptimizationRemark:
604 // Optimization remarks are always handled completely by this
605 // handler. There is no generic way of emitting them.
606 OptimizationRemarkHandler(cast<MachineOptimizationRemark>(DI));
607 return;
608 case llvm::DK_MachineOptimizationRemarkMissed:
609 // Optimization remarks are always handled completely by this
610 // handler. There is no generic way of emitting them.
611 OptimizationRemarkHandler(cast<MachineOptimizationRemarkMissed>(DI));
612 return;
613 case llvm::DK_MachineOptimizationRemarkAnalysis:
614 // Optimization remarks are always handled completely by this
615 // handler. There is no generic way of emitting them.
616 OptimizationRemarkHandler(cast<MachineOptimizationRemarkAnalysis>(DI));
617 return;
618 case llvm::DK_OptimizationFailure:
619 // Optimization failures are always handled completely by this
620 // handler.
621 OptimizationFailureHandler(cast<DiagnosticInfoOptimizationFailure>(DI));
622 return;
623 case llvm::DK_Unsupported:
624 UnsupportedDiagHandler(cast<DiagnosticInfoUnsupported>(DI));
625 return;
626 case llvm::DK_UnsupportedTargetIntrinsic:
627 UnsupportedTargetIntrinsicDiagHandler(
629 return;
630 case llvm::DK_DontCall:
631 DontCallDiagHandler(cast<DiagnosticInfoDontCall>(DI));
632 return;
633 case llvm::DK_MisExpect:
634 MisExpectDiagHandler(cast<DiagnosticInfoMisExpect>(DI));
635 return;
636 default:
637 // Plugin IDs are not bound to any value as they are set dynamically.
638 ComputeDiagRemarkID(Severity, backend_plugin, DiagID);
639 break;
640 }
641 std::string MsgStorage;
642 {
643 raw_string_ostream Stream(MsgStorage);
644 DiagnosticPrinterRawOStream DP(Stream);
645 DI.print(DP);
646 }
647
648 if (DI.getKind() == DK_Linker) {
649 assert(CurLinkModule && "CurLinkModule must be set for linker diagnostics");
650 Diags.Report(DiagID) << CurLinkModule->getModuleIdentifier() << MsgStorage;
651 return;
652 }
653
654 // Report the backend message using the usual diagnostic mechanism.
655 FullSourceLoc Loc;
656 Diags.Report(Loc, DiagID).AddString(MsgStorage);
657}
658
659#undef ComputeDiagID
660#undef ComputeDiagRemarkID
#define ComputeDiagID(Severity, GroupName, DiagID)
#define ComputeDiagRemarkID(Severity, GroupName, DiagID)
Defines the Diagnostic-related interfaces.
Defines the clang::FileManager interface and associated types.
unsigned IsFirst
Indicates that this is the first token of the file.
Defines the SourceManager interface.
void addFunctionSourceLocation(StringRef MangledName, FullSourceLoc Loc)
Record the source location of the function with the given mangled name, used to approximate a locatio...
std::unique_ptr< llvm::DiagnosticHandler > createDiagnosticHandler()
Create an llvm::DiagnosticHandler that forwards diagnostics to this consumer.
std::optional< FullSourceLoc > getFunctionSourceLocation(const llvm::Function &F) const
void handleDiagnostics(const llvm::DiagnosticInfo &DI)
This is invoked when the backend needs to report something to the user.
const FullSourceLoc getBestLocationFromDebugLoc(const llvm::DiagnosticInfoWithLocationBase &D, bool &BadDebugInfo, StringRef &Filename, unsigned &Line, unsigned &Column) const
Get the best possible source location to represent a diagnostic that may have associated debug info.
A little helper class used to produce diagnostics.
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
An opaque identifier used by SourceManager which refers to a source file (MemoryBuffer) along with it...
Implements support for file system lookup, file system caching, and directory search management.
Definition FileManager.h:57
OptionalFileEntryRef getOptionalFileRef(StringRef Filename, bool OpenFile=false, bool CacheFailure=true, bool IsText=true)
Get a FileEntryRef if it exists, without doing anything on error.
A SourceLocation and its associated SourceManager.
Encodes a location in the source.
static SourceLocation getFromRawEncoding(UIntTy Encoding)
Turn a raw encoding of a SourceLocation object into a real SourceLocation.
bool isValid() const
Return true if this is a valid SourceLocation object.
SourceLocation getLocWithOffset(IntTy Offset) const
Return a source location with the specified offset from this SourceLocation.
This class handles loading and caching of source files into memory.
FileID createFileID(FileEntryRef SourceFile, SourceLocation IncludePos, SrcMgr::CharacteristicKind FileCharacter, int LoadedID=0, SourceLocation::UIntTy LoadedOffset=0)
Create a new FileID that represents the specified file being #included from the specified IncludePosi...
FileManager & getFileManager() const
SourceLocation translateFileLineCol(const FileEntry *SourceFile, unsigned Line, unsigned Col) const
Get the source location for the given file:line:col triplet.
SourceLocation getLocForStartOfFile(FileID FID) const
Return the source location corresponding to the first byte of the specified file.
A trivial tuple used to represent a source range.
void AddString(StringRef V) const
Top level wrappers for InstallAPI frontend operations.
U cast(CodeGen::Address addr)
Definition Address.h:327
Diagnostic wrappers for TextAPI types for error reporting.
Definition Dominators.h:30
hash_code hash_value(const clang::dependencies::ModuleID &ID)