clang  19.0.0git
SourceMgrAdapter.cpp
Go to the documentation of this file.
1 //=== SourceMgrAdapter.cpp - SourceMgr to SourceManager Adapter -----------===//
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 //
9 // This file implements the adapter that maps diagnostics from llvm::SourceMgr
10 // to Clang's SourceManager.
11 //
12 //===----------------------------------------------------------------------===//
13 
15 #include "clang/Basic/Diagnostic.h"
16 
17 using namespace clang;
18 
19 void SourceMgrAdapter::handleDiag(const llvm::SMDiagnostic &Diag,
20  void *Context) {
21  static_cast<SourceMgrAdapter *>(Context)->handleDiag(Diag);
22 }
23 
25  DiagnosticsEngine &Diagnostics,
26  unsigned ErrorDiagID, unsigned WarningDiagID,
27  unsigned NoteDiagID,
28  OptionalFileEntryRef DefaultFile)
29  : SrcMgr(SM), Diagnostics(Diagnostics), ErrorDiagID(ErrorDiagID),
30  WarningDiagID(WarningDiagID), NoteDiagID(NoteDiagID),
31  DefaultFile(DefaultFile) {}
32 
34 
35 SourceLocation SourceMgrAdapter::mapLocation(const llvm::SourceMgr &LLVMSrcMgr,
36  llvm::SMLoc Loc) {
37  // Map invalid locations.
38  if (!Loc.isValid())
39  return SourceLocation();
40 
41  // Find the buffer containing the location.
42  unsigned BufferID = LLVMSrcMgr.FindBufferContainingLoc(Loc);
43  if (!BufferID)
44  return SourceLocation();
45 
46  // If we haven't seen this buffer before, copy it over.
47  auto Buffer = LLVMSrcMgr.getMemoryBuffer(BufferID);
48  auto KnownBuffer = FileIDMapping.find(std::make_pair(&LLVMSrcMgr, BufferID));
49  if (KnownBuffer == FileIDMapping.end()) {
50  FileID FileID;
51  if (DefaultFile) {
52  // Map to the default file.
53  FileID = SrcMgr.getOrCreateFileID(*DefaultFile, SrcMgr::C_User);
54 
55  // Only do this once.
56  DefaultFile = std::nullopt;
57  } else {
58  // Make a copy of the memory buffer.
59  StringRef bufferName = Buffer->getBufferIdentifier();
60  auto bufferCopy = std::unique_ptr<llvm::MemoryBuffer>(
61  llvm::MemoryBuffer::getMemBufferCopy(Buffer->getBuffer(),
62  bufferName));
63 
64  // Add this memory buffer to the Clang source manager.
65  FileID = SrcMgr.createFileID(std::move(bufferCopy));
66  }
67 
68  // Save the mapping.
69  KnownBuffer = FileIDMapping
70  .insert(std::make_pair(
71  std::make_pair(&LLVMSrcMgr, BufferID), FileID))
72  .first;
73  }
74 
75  // Translate the offset into the file.
76  unsigned Offset = Loc.getPointer() - Buffer->getBufferStart();
77  return SrcMgr.getLocForStartOfFile(KnownBuffer->second)
79 }
80 
81 SourceRange SourceMgrAdapter::mapRange(const llvm::SourceMgr &LLVMSrcMgr,
82  llvm::SMRange Range) {
83  if (!Range.isValid())
84  return SourceRange();
85 
86  SourceLocation Start = mapLocation(LLVMSrcMgr, Range.Start);
87  SourceLocation End = mapLocation(LLVMSrcMgr, Range.End);
88  return SourceRange(Start, End);
89 }
90 
91 void SourceMgrAdapter::handleDiag(const llvm::SMDiagnostic &Diag) {
92  // Map the location.
94  if (auto *LLVMSrcMgr = Diag.getSourceMgr())
95  Loc = mapLocation(*LLVMSrcMgr, Diag.getLoc());
96 
97  // Extract the message.
98  StringRef Message = Diag.getMessage();
99 
100  // Map the diagnostic kind.
101  unsigned DiagID;
102  switch (Diag.getKind()) {
103  case llvm::SourceMgr::DK_Error:
104  DiagID = ErrorDiagID;
105  break;
106 
107  case llvm::SourceMgr::DK_Warning:
108  DiagID = WarningDiagID;
109  break;
110 
111  case llvm::SourceMgr::DK_Remark:
112  llvm_unreachable("remarks not implemented");
113 
114  case llvm::SourceMgr::DK_Note:
115  DiagID = NoteDiagID;
116  break;
117  }
118 
119  // Report the diagnostic.
120  DiagnosticBuilder Builder = Diagnostics.Report(Loc, DiagID) << Message;
121 
122  if (auto *LLVMSrcMgr = Diag.getSourceMgr()) {
123  // Translate ranges.
124  SourceLocation StartOfLine = Loc.getLocWithOffset(-Diag.getColumnNo());
125  for (auto Range : Diag.getRanges()) {
126  Builder << SourceRange(StartOfLine.getLocWithOffset(Range.first),
127  StartOfLine.getLocWithOffset(Range.second));
128  }
129 
130  // Translate Fix-Its.
131  for (const llvm::SMFixIt &FixIt : Diag.getFixIts()) {
132  CharSourceRange Range(mapRange(*LLVMSrcMgr, FixIt.getRange()), false);
133  Builder << FixItHint::CreateReplacement(Range, FixIt.getText());
134  }
135  }
136 }
#define SM(sm)
Definition: Cuda.cpp:83
Defines the Diagnostic-related interfaces.
unsigned Offset
Definition: Format.cpp:2978
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.
SourceRange Range
Definition: SemaObjC.cpp:754
SourceLocation Loc
Definition: SemaObjC.cpp:755
SourceLocation End
Represents a character-granular source range.
A little helper class used to produce diagnostics.
Definition: Diagnostic.h:1277
Concrete class used by the front-end to report problems and issues.
Definition: Diagnostic.h:193
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
Definition: Diagnostic.h:1553
An opaque identifier used by SourceManager which refers to a source file (MemoryBuffer) along with it...
static FixItHint CreateReplacement(CharSourceRange RemoveRange, StringRef Code)
Create a code modification hint that replaces the given source range with the given code string.
Definition: Diagnostic.h:135
Encodes a location in the source.
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...
FileID getOrCreateFileID(FileEntryRef SourceFile, SrcMgr::CharacteristicKind FileCharacter)
Get the FileID for SourceFile if it exists.
SourceLocation getLocForStartOfFile(FileID FID) const
Return the source location corresponding to the first byte of the specified file.
An adapter that can be used to translate diagnostics from one or more llvm::SourceMgr instances to a ...
SourceLocation mapLocation(const llvm::SourceMgr &LLVMSrcMgr, llvm::SMLoc Loc)
Map a source location in the given LLVM source manager to its corresponding location in the Clang sou...
SourceRange mapRange(const llvm::SourceMgr &LLVMSrcMgr, llvm::SMRange Range)
Map a source range in the given LLVM source manager to its corresponding range in the Clang source ma...
SourceMgrAdapter(SourceManager &SM, DiagnosticsEngine &Diagnostics, unsigned ErrorDiagID, unsigned WarningDiagID, unsigned NoteDiagID, OptionalFileEntryRef DefaultFile=std::nullopt)
Create a new SourceMgr adaptor that maps to the given source manager and diagnostics engine.
A trivial tuple used to represent a source range.
bool isValid() const
@ FixIt
Parse and apply any fixits to the source.
The JSON file list parser is used to communicate input to InstallAPI.