Rename GetLanguageInfo to GetLanguageSpecificData (#117012)
[llvm-project.git] / clang / lib / Basic / SourceMgrAdapter.cpp
blobe39e4de9d42debcf15cbbff527ba0bd7c4697eba
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.
12 //===----------------------------------------------------------------------===//
14 #include "clang/Basic/SourceMgrAdapter.h"
15 #include "clang/Basic/Diagnostic.h"
17 using namespace clang;
19 void SourceMgrAdapter::handleDiag(const llvm::SMDiagnostic &Diag,
20 void *Context) {
21 static_cast<SourceMgrAdapter *>(Context)->handleDiag(Diag);
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 DefaultFile(DefaultFile) {}
33 SourceMgrAdapter::~SourceMgrAdapter() {}
35 SourceLocation SourceMgrAdapter::mapLocation(const llvm::SourceMgr &LLVMSrcMgr,
36 llvm::SMLoc Loc) {
37 // Map invalid locations.
38 if (!Loc.isValid())
39 return SourceLocation();
41 // Find the buffer containing the location.
42 unsigned BufferID = LLVMSrcMgr.FindBufferContainingLoc(Loc);
43 if (!BufferID)
44 return SourceLocation();
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);
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));
64 // Add this memory buffer to the Clang source manager.
65 FileID = SrcMgr.createFileID(std::move(bufferCopy));
68 // Save the mapping.
69 KnownBuffer = FileIDMapping
70 .insert(std::make_pair(
71 std::make_pair(&LLVMSrcMgr, BufferID), FileID))
72 .first;
75 // Translate the offset into the file.
76 unsigned Offset = Loc.getPointer() - Buffer->getBufferStart();
77 return SrcMgr.getLocForStartOfFile(KnownBuffer->second)
78 .getLocWithOffset(Offset);
81 SourceRange SourceMgrAdapter::mapRange(const llvm::SourceMgr &LLVMSrcMgr,
82 llvm::SMRange Range) {
83 if (!Range.isValid())
84 return SourceRange();
86 SourceLocation Start = mapLocation(LLVMSrcMgr, Range.Start);
87 SourceLocation End = mapLocation(LLVMSrcMgr, Range.End);
88 return SourceRange(Start, End);
91 void SourceMgrAdapter::handleDiag(const llvm::SMDiagnostic &Diag) {
92 // Map the location.
93 SourceLocation Loc;
94 if (auto *LLVMSrcMgr = Diag.getSourceMgr())
95 Loc = mapLocation(*LLVMSrcMgr, Diag.getLoc());
97 // Extract the message.
98 StringRef Message = Diag.getMessage();
100 // Map the diagnostic kind.
101 unsigned DiagID;
102 switch (Diag.getKind()) {
103 case llvm::SourceMgr::DK_Error:
104 DiagID = ErrorDiagID;
105 break;
107 case llvm::SourceMgr::DK_Warning:
108 DiagID = WarningDiagID;
109 break;
111 case llvm::SourceMgr::DK_Remark:
112 llvm_unreachable("remarks not implemented");
114 case llvm::SourceMgr::DK_Note:
115 DiagID = NoteDiagID;
116 break;
119 // Report the diagnostic.
120 DiagnosticBuilder Builder = Diagnostics.Report(Loc, DiagID) << Message;
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));
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());