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