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
16
17using namespace clang;
18
19void 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
35SourceLocation 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()) {
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)
78 .getLocWithOffset(Offset);
79}
80
81SourceRange 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
91void 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:82
Defines the Diagnostic-related interfaces.
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.
Represents a character-granular source range.
A little helper class used to produce diagnostics.
Definition: Diagnostic.h:1271
Concrete class used by the front-end to report problems and issues.
Definition: Diagnostic.h:192
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
Definition: Diagnostic.h:1547
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:134
Encodes a location in the source.
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.
The JSON file list parser is used to communicate input to InstallAPI.