/src/llvm-project/clang/lib/Basic/SourceMgrAdapter.cpp
Line | Count | Source (jump to first uncovered line) |
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 | | |
14 | | #include "clang/Basic/SourceMgrAdapter.h" |
15 | | #include "clang/Basic/Diagnostic.h" |
16 | | |
17 | | using namespace clang; |
18 | | |
19 | | void SourceMgrAdapter::handleDiag(const llvm::SMDiagnostic &Diag, |
20 | 0 | void *Context) { |
21 | 0 | static_cast<SourceMgrAdapter *>(Context)->handleDiag(Diag); |
22 | 0 | } |
23 | | |
24 | | SourceMgrAdapter::SourceMgrAdapter(SourceManager &SM, |
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 | 0 | DefaultFile(DefaultFile) {} |
32 | | |
33 | 0 | SourceMgrAdapter::~SourceMgrAdapter() {} |
34 | | |
35 | | SourceLocation SourceMgrAdapter::mapLocation(const llvm::SourceMgr &LLVMSrcMgr, |
36 | 0 | llvm::SMLoc Loc) { |
37 | | // Map invalid locations. |
38 | 0 | if (!Loc.isValid()) |
39 | 0 | return SourceLocation(); |
40 | | |
41 | | // Find the buffer containing the location. |
42 | 0 | unsigned BufferID = LLVMSrcMgr.FindBufferContainingLoc(Loc); |
43 | 0 | if (!BufferID) |
44 | 0 | return SourceLocation(); |
45 | | |
46 | | // If we haven't seen this buffer before, copy it over. |
47 | 0 | auto Buffer = LLVMSrcMgr.getMemoryBuffer(BufferID); |
48 | 0 | auto KnownBuffer = FileIDMapping.find(std::make_pair(&LLVMSrcMgr, BufferID)); |
49 | 0 | if (KnownBuffer == FileIDMapping.end()) { |
50 | 0 | FileID FileID; |
51 | 0 | if (DefaultFile) { |
52 | | // Map to the default file. |
53 | 0 | FileID = SrcMgr.getOrCreateFileID(*DefaultFile, SrcMgr::C_User); |
54 | | |
55 | | // Only do this once. |
56 | 0 | DefaultFile = std::nullopt; |
57 | 0 | } else { |
58 | | // Make a copy of the memory buffer. |
59 | 0 | StringRef bufferName = Buffer->getBufferIdentifier(); |
60 | 0 | auto bufferCopy = std::unique_ptr<llvm::MemoryBuffer>( |
61 | 0 | llvm::MemoryBuffer::getMemBufferCopy(Buffer->getBuffer(), |
62 | 0 | bufferName)); |
63 | | |
64 | | // Add this memory buffer to the Clang source manager. |
65 | 0 | FileID = SrcMgr.createFileID(std::move(bufferCopy)); |
66 | 0 | } |
67 | | |
68 | | // Save the mapping. |
69 | 0 | KnownBuffer = FileIDMapping |
70 | 0 | .insert(std::make_pair( |
71 | 0 | std::make_pair(&LLVMSrcMgr, BufferID), FileID)) |
72 | 0 | .first; |
73 | 0 | } |
74 | | |
75 | | // Translate the offset into the file. |
76 | 0 | unsigned Offset = Loc.getPointer() - Buffer->getBufferStart(); |
77 | 0 | return SrcMgr.getLocForStartOfFile(KnownBuffer->second) |
78 | 0 | .getLocWithOffset(Offset); |
79 | 0 | } |
80 | | |
81 | | SourceRange SourceMgrAdapter::mapRange(const llvm::SourceMgr &LLVMSrcMgr, |
82 | 0 | llvm::SMRange Range) { |
83 | 0 | if (!Range.isValid()) |
84 | 0 | return SourceRange(); |
85 | | |
86 | 0 | SourceLocation Start = mapLocation(LLVMSrcMgr, Range.Start); |
87 | 0 | SourceLocation End = mapLocation(LLVMSrcMgr, Range.End); |
88 | 0 | return SourceRange(Start, End); |
89 | 0 | } |
90 | | |
91 | 0 | void SourceMgrAdapter::handleDiag(const llvm::SMDiagnostic &Diag) { |
92 | | // Map the location. |
93 | 0 | SourceLocation Loc; |
94 | 0 | if (auto *LLVMSrcMgr = Diag.getSourceMgr()) |
95 | 0 | Loc = mapLocation(*LLVMSrcMgr, Diag.getLoc()); |
96 | | |
97 | | // Extract the message. |
98 | 0 | StringRef Message = Diag.getMessage(); |
99 | | |
100 | | // Map the diagnostic kind. |
101 | 0 | unsigned DiagID; |
102 | 0 | switch (Diag.getKind()) { |
103 | 0 | case llvm::SourceMgr::DK_Error: |
104 | 0 | DiagID = ErrorDiagID; |
105 | 0 | break; |
106 | | |
107 | 0 | case llvm::SourceMgr::DK_Warning: |
108 | 0 | DiagID = WarningDiagID; |
109 | 0 | break; |
110 | | |
111 | 0 | case llvm::SourceMgr::DK_Remark: |
112 | 0 | llvm_unreachable("remarks not implemented"); |
113 | |
|
114 | 0 | case llvm::SourceMgr::DK_Note: |
115 | 0 | DiagID = NoteDiagID; |
116 | 0 | break; |
117 | 0 | } |
118 | | |
119 | | // Report the diagnostic. |
120 | 0 | DiagnosticBuilder Builder = Diagnostics.Report(Loc, DiagID) << Message; |
121 | |
|
122 | 0 | if (auto *LLVMSrcMgr = Diag.getSourceMgr()) { |
123 | | // Translate ranges. |
124 | 0 | SourceLocation StartOfLine = Loc.getLocWithOffset(-Diag.getColumnNo()); |
125 | 0 | for (auto Range : Diag.getRanges()) { |
126 | 0 | Builder << SourceRange(StartOfLine.getLocWithOffset(Range.first), |
127 | 0 | StartOfLine.getLocWithOffset(Range.second)); |
128 | 0 | } |
129 | | |
130 | | // Translate Fix-Its. |
131 | 0 | for (const llvm::SMFixIt &FixIt : Diag.getFixIts()) { |
132 | 0 | CharSourceRange Range(mapRange(*LLVMSrcMgr, FixIt.getRange()), false); |
133 | 0 | Builder << FixItHint::CreateReplacement(Range, FixIt.getText()); |
134 | 0 | } |
135 | 0 | } |
136 | 0 | } |