llvm-project

Форк
0
/
SourceMgrAdapter.cpp 
136 строк · 4.6 Кб
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
                                  void *Context) {
21
  static_cast<SourceMgrAdapter *>(Context)->handleDiag(Diag);
22
}
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
      DefaultFile(DefaultFile) {}
32

33
SourceMgrAdapter::~SourceMgrAdapter() {}
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)
78
      .getLocWithOffset(Offset);
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.
93
  SourceLocation Loc;
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
}
137

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.