Coverage Report

Created: 2024-01-17 10:31

/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
}