1f4a2713aSLionel Sambuc //===-- CXLoadedDiagnostic.cpp - Handling of persisent diags ----*- C++ -*-===//
2f4a2713aSLionel Sambuc //
3f4a2713aSLionel Sambuc // The LLVM Compiler Infrastructure
4f4a2713aSLionel Sambuc //
5f4a2713aSLionel Sambuc // This file is distributed under the University of Illinois Open Source
6f4a2713aSLionel Sambuc // License. See LICENSE.TXT for details.
7f4a2713aSLionel Sambuc //
8f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
9f4a2713aSLionel Sambuc //
10f4a2713aSLionel Sambuc // Implements handling of persisent diagnostics.
11f4a2713aSLionel Sambuc //
12f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
13f4a2713aSLionel Sambuc
14f4a2713aSLionel Sambuc #include "CXLoadedDiagnostic.h"
15f4a2713aSLionel Sambuc #include "CXString.h"
16f4a2713aSLionel Sambuc #include "clang/Basic/Diagnostic.h"
17f4a2713aSLionel Sambuc #include "clang/Basic/FileManager.h"
18*0a6a1f1dSLionel Sambuc #include "clang/Basic/LLVM.h"
19*0a6a1f1dSLionel Sambuc #include "clang/Frontend/SerializedDiagnosticReader.h"
20*0a6a1f1dSLionel Sambuc #include "clang/Frontend/SerializedDiagnostics.h"
21*0a6a1f1dSLionel Sambuc #include "llvm/ADT/Optional.h"
22f4a2713aSLionel Sambuc #include "llvm/ADT/StringRef.h"
23f4a2713aSLionel Sambuc #include "llvm/ADT/Twine.h"
24f4a2713aSLionel Sambuc #include "llvm/Bitcode/BitstreamReader.h"
25*0a6a1f1dSLionel Sambuc #include "llvm/Support/ErrorHandling.h"
26f4a2713aSLionel Sambuc #include "llvm/Support/MemoryBuffer.h"
27f4a2713aSLionel Sambuc using namespace clang;
28f4a2713aSLionel Sambuc
29f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
30f4a2713aSLionel Sambuc // Extend CXDiagnosticSetImpl which contains strings for diagnostics.
31f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
32f4a2713aSLionel Sambuc
33f4a2713aSLionel Sambuc typedef llvm::DenseMap<unsigned, const char *> Strings;
34f4a2713aSLionel Sambuc
35f4a2713aSLionel Sambuc namespace {
36f4a2713aSLionel Sambuc class CXLoadedDiagnosticSetImpl : public CXDiagnosticSetImpl {
37f4a2713aSLionel Sambuc public:
CXLoadedDiagnosticSetImpl()38f4a2713aSLionel Sambuc CXLoadedDiagnosticSetImpl() : CXDiagnosticSetImpl(true), FakeFiles(FO) {}
~CXLoadedDiagnosticSetImpl()39f4a2713aSLionel Sambuc virtual ~CXLoadedDiagnosticSetImpl() {}
40f4a2713aSLionel Sambuc
41f4a2713aSLionel Sambuc llvm::BumpPtrAllocator Alloc;
42f4a2713aSLionel Sambuc Strings Categories;
43f4a2713aSLionel Sambuc Strings WarningFlags;
44f4a2713aSLionel Sambuc Strings FileNames;
45f4a2713aSLionel Sambuc
46f4a2713aSLionel Sambuc FileSystemOptions FO;
47f4a2713aSLionel Sambuc FileManager FakeFiles;
48f4a2713aSLionel Sambuc llvm::DenseMap<unsigned, const FileEntry *> Files;
49f4a2713aSLionel Sambuc
50f4a2713aSLionel Sambuc /// \brief Copy the string into our own allocator.
copyString(StringRef Blob)51f4a2713aSLionel Sambuc const char *copyString(StringRef Blob) {
52f4a2713aSLionel Sambuc char *mem = Alloc.Allocate<char>(Blob.size() + 1);
53f4a2713aSLionel Sambuc memcpy(mem, Blob.data(), Blob.size());
54f4a2713aSLionel Sambuc mem[Blob.size()] = '\0';
55f4a2713aSLionel Sambuc return mem;
56f4a2713aSLionel Sambuc }
57f4a2713aSLionel Sambuc };
58f4a2713aSLionel Sambuc }
59f4a2713aSLionel Sambuc
60f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
61f4a2713aSLionel Sambuc // Cleanup.
62f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
63f4a2713aSLionel Sambuc
~CXLoadedDiagnostic()64f4a2713aSLionel Sambuc CXLoadedDiagnostic::~CXLoadedDiagnostic() {}
65f4a2713aSLionel Sambuc
66f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
67f4a2713aSLionel Sambuc // Public CXLoadedDiagnostic methods.
68f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
69f4a2713aSLionel Sambuc
getSeverity() const70f4a2713aSLionel Sambuc CXDiagnosticSeverity CXLoadedDiagnostic::getSeverity() const {
71*0a6a1f1dSLionel Sambuc // FIXME: Fail more softly if the diagnostic level is unknown?
72*0a6a1f1dSLionel Sambuc auto severityAsLevel = static_cast<serialized_diags::Level>(severity);
73*0a6a1f1dSLionel Sambuc assert(severity == static_cast<unsigned>(severityAsLevel) &&
74*0a6a1f1dSLionel Sambuc "unknown serialized diagnostic level");
75*0a6a1f1dSLionel Sambuc
76*0a6a1f1dSLionel Sambuc switch (severityAsLevel) {
77*0a6a1f1dSLionel Sambuc #define CASE(X) case serialized_diags::X: return CXDiagnostic_##X;
78*0a6a1f1dSLionel Sambuc CASE(Ignored)
79*0a6a1f1dSLionel Sambuc CASE(Note)
80*0a6a1f1dSLionel Sambuc CASE(Warning)
81*0a6a1f1dSLionel Sambuc CASE(Error)
82*0a6a1f1dSLionel Sambuc CASE(Fatal)
83*0a6a1f1dSLionel Sambuc #undef CASE
84*0a6a1f1dSLionel Sambuc // The 'Remark' level isn't represented in the stable API.
85*0a6a1f1dSLionel Sambuc case serialized_diags::Remark: return CXDiagnostic_Warning;
86f4a2713aSLionel Sambuc }
87f4a2713aSLionel Sambuc
88f4a2713aSLionel Sambuc llvm_unreachable("Invalid diagnostic level");
89f4a2713aSLionel Sambuc }
90f4a2713aSLionel Sambuc
makeLocation(const CXLoadedDiagnostic::Location * DLoc)91f4a2713aSLionel Sambuc static CXSourceLocation makeLocation(const CXLoadedDiagnostic::Location *DLoc) {
92f4a2713aSLionel Sambuc // The lowest bit of ptr_data[0] is always set to 1 to indicate this
93f4a2713aSLionel Sambuc // is a persistent diagnostic.
94f4a2713aSLionel Sambuc uintptr_t V = (uintptr_t) DLoc;
95f4a2713aSLionel Sambuc V |= 0x1;
96*0a6a1f1dSLionel Sambuc CXSourceLocation Loc = { { (void*) V, nullptr }, 0 };
97f4a2713aSLionel Sambuc return Loc;
98f4a2713aSLionel Sambuc }
99f4a2713aSLionel Sambuc
getLocation() const100f4a2713aSLionel Sambuc CXSourceLocation CXLoadedDiagnostic::getLocation() const {
101f4a2713aSLionel Sambuc // The lowest bit of ptr_data[0] is always set to 1 to indicate this
102f4a2713aSLionel Sambuc // is a persistent diagnostic.
103f4a2713aSLionel Sambuc return makeLocation(&DiagLoc);
104f4a2713aSLionel Sambuc }
105f4a2713aSLionel Sambuc
getSpelling() const106f4a2713aSLionel Sambuc CXString CXLoadedDiagnostic::getSpelling() const {
107f4a2713aSLionel Sambuc return cxstring::createRef(Spelling);
108f4a2713aSLionel Sambuc }
109f4a2713aSLionel Sambuc
getDiagnosticOption(CXString * Disable) const110f4a2713aSLionel Sambuc CXString CXLoadedDiagnostic::getDiagnosticOption(CXString *Disable) const {
111f4a2713aSLionel Sambuc if (DiagOption.empty())
112f4a2713aSLionel Sambuc return cxstring::createEmpty();
113f4a2713aSLionel Sambuc
114f4a2713aSLionel Sambuc // FIXME: possibly refactor with logic in CXStoredDiagnostic.
115f4a2713aSLionel Sambuc if (Disable)
116f4a2713aSLionel Sambuc *Disable = cxstring::createDup((Twine("-Wno-") + DiagOption).str());
117f4a2713aSLionel Sambuc return cxstring::createDup((Twine("-W") + DiagOption).str());
118f4a2713aSLionel Sambuc }
119f4a2713aSLionel Sambuc
getCategory() const120f4a2713aSLionel Sambuc unsigned CXLoadedDiagnostic::getCategory() const {
121f4a2713aSLionel Sambuc return category;
122f4a2713aSLionel Sambuc }
123f4a2713aSLionel Sambuc
getCategoryText() const124f4a2713aSLionel Sambuc CXString CXLoadedDiagnostic::getCategoryText() const {
125f4a2713aSLionel Sambuc return cxstring::createDup(CategoryText);
126f4a2713aSLionel Sambuc }
127f4a2713aSLionel Sambuc
getNumRanges() const128f4a2713aSLionel Sambuc unsigned CXLoadedDiagnostic::getNumRanges() const {
129f4a2713aSLionel Sambuc return Ranges.size();
130f4a2713aSLionel Sambuc }
131f4a2713aSLionel Sambuc
getRange(unsigned Range) const132f4a2713aSLionel Sambuc CXSourceRange CXLoadedDiagnostic::getRange(unsigned Range) const {
133f4a2713aSLionel Sambuc assert(Range < Ranges.size());
134f4a2713aSLionel Sambuc return Ranges[Range];
135f4a2713aSLionel Sambuc }
136f4a2713aSLionel Sambuc
getNumFixIts() const137f4a2713aSLionel Sambuc unsigned CXLoadedDiagnostic::getNumFixIts() const {
138f4a2713aSLionel Sambuc return FixIts.size();
139f4a2713aSLionel Sambuc }
140f4a2713aSLionel Sambuc
getFixIt(unsigned FixIt,CXSourceRange * ReplacementRange) const141f4a2713aSLionel Sambuc CXString CXLoadedDiagnostic::getFixIt(unsigned FixIt,
142f4a2713aSLionel Sambuc CXSourceRange *ReplacementRange) const {
143f4a2713aSLionel Sambuc assert(FixIt < FixIts.size());
144f4a2713aSLionel Sambuc if (ReplacementRange)
145f4a2713aSLionel Sambuc *ReplacementRange = FixIts[FixIt].first;
146f4a2713aSLionel Sambuc return cxstring::createRef(FixIts[FixIt].second);
147f4a2713aSLionel Sambuc }
148f4a2713aSLionel Sambuc
decodeLocation(CXSourceLocation location,CXFile * file,unsigned int * line,unsigned int * column,unsigned int * offset)149f4a2713aSLionel Sambuc void CXLoadedDiagnostic::decodeLocation(CXSourceLocation location,
150f4a2713aSLionel Sambuc CXFile *file,
151f4a2713aSLionel Sambuc unsigned int *line,
152f4a2713aSLionel Sambuc unsigned int *column,
153f4a2713aSLionel Sambuc unsigned int *offset) {
154f4a2713aSLionel Sambuc
155f4a2713aSLionel Sambuc
156f4a2713aSLionel Sambuc // CXSourceLocation consists of the following fields:
157f4a2713aSLionel Sambuc //
158f4a2713aSLionel Sambuc // void *ptr_data[2];
159f4a2713aSLionel Sambuc // unsigned int_data;
160f4a2713aSLionel Sambuc //
161f4a2713aSLionel Sambuc // The lowest bit of ptr_data[0] is always set to 1 to indicate this
162f4a2713aSLionel Sambuc // is a persistent diagnostic.
163f4a2713aSLionel Sambuc //
164f4a2713aSLionel Sambuc // For now, do the unoptimized approach and store the data in a side
165f4a2713aSLionel Sambuc // data structure. We can optimize this case later.
166f4a2713aSLionel Sambuc
167f4a2713aSLionel Sambuc uintptr_t V = (uintptr_t) location.ptr_data[0];
168f4a2713aSLionel Sambuc assert((V & 0x1) == 1);
169f4a2713aSLionel Sambuc V &= ~(uintptr_t)1;
170f4a2713aSLionel Sambuc
171f4a2713aSLionel Sambuc const Location &Loc = *((Location*)V);
172f4a2713aSLionel Sambuc
173f4a2713aSLionel Sambuc if (file)
174f4a2713aSLionel Sambuc *file = Loc.file;
175f4a2713aSLionel Sambuc if (line)
176f4a2713aSLionel Sambuc *line = Loc.line;
177f4a2713aSLionel Sambuc if (column)
178f4a2713aSLionel Sambuc *column = Loc.column;
179f4a2713aSLionel Sambuc if (offset)
180f4a2713aSLionel Sambuc *offset = Loc.offset;
181f4a2713aSLionel Sambuc }
182f4a2713aSLionel Sambuc
183f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
184f4a2713aSLionel Sambuc // Deserialize diagnostics.
185f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
186f4a2713aSLionel Sambuc
187f4a2713aSLionel Sambuc namespace {
188*0a6a1f1dSLionel Sambuc class DiagLoader : serialized_diags::SerializedDiagnosticReader {
189f4a2713aSLionel Sambuc enum CXLoadDiag_Error *error;
190f4a2713aSLionel Sambuc CXString *errorString;
191*0a6a1f1dSLionel Sambuc std::unique_ptr<CXLoadedDiagnosticSetImpl> TopDiags;
192*0a6a1f1dSLionel Sambuc SmallVector<std::unique_ptr<CXLoadedDiagnostic>, 8> CurrentDiags;
193f4a2713aSLionel Sambuc
reportBad(enum CXLoadDiag_Error code,llvm::StringRef err)194*0a6a1f1dSLionel Sambuc std::error_code reportBad(enum CXLoadDiag_Error code, llvm::StringRef err) {
195f4a2713aSLionel Sambuc if (error)
196f4a2713aSLionel Sambuc *error = code;
197f4a2713aSLionel Sambuc if (errorString)
198f4a2713aSLionel Sambuc *errorString = cxstring::createDup(err);
199*0a6a1f1dSLionel Sambuc return serialized_diags::SDError::HandlerFailed;
200f4a2713aSLionel Sambuc }
201f4a2713aSLionel Sambuc
reportInvalidFile(llvm::StringRef err)202*0a6a1f1dSLionel Sambuc std::error_code reportInvalidFile(llvm::StringRef err) {
203f4a2713aSLionel Sambuc return reportBad(CXLoadDiag_InvalidFile, err);
204f4a2713aSLionel Sambuc }
205f4a2713aSLionel Sambuc
206*0a6a1f1dSLionel Sambuc std::error_code readRange(const serialized_diags::Location &SDStart,
207*0a6a1f1dSLionel Sambuc const serialized_diags::Location &SDEnd,
208f4a2713aSLionel Sambuc CXSourceRange &SR);
209f4a2713aSLionel Sambuc
210*0a6a1f1dSLionel Sambuc std::error_code readLocation(const serialized_diags::Location &SDLoc,
211*0a6a1f1dSLionel Sambuc CXLoadedDiagnostic::Location &LoadedLoc);
212*0a6a1f1dSLionel Sambuc
213*0a6a1f1dSLionel Sambuc protected:
214*0a6a1f1dSLionel Sambuc std::error_code visitStartOfDiagnostic() override;
215*0a6a1f1dSLionel Sambuc std::error_code visitEndOfDiagnostic() override;
216*0a6a1f1dSLionel Sambuc
217*0a6a1f1dSLionel Sambuc std::error_code visitCategoryRecord(unsigned ID, StringRef Name) override;
218*0a6a1f1dSLionel Sambuc
219*0a6a1f1dSLionel Sambuc std::error_code visitDiagFlagRecord(unsigned ID, StringRef Name) override;
220*0a6a1f1dSLionel Sambuc
221*0a6a1f1dSLionel Sambuc std::error_code visitDiagnosticRecord(
222*0a6a1f1dSLionel Sambuc unsigned Severity, const serialized_diags::Location &Location,
223*0a6a1f1dSLionel Sambuc unsigned Category, unsigned Flag, StringRef Message) override;
224*0a6a1f1dSLionel Sambuc
225*0a6a1f1dSLionel Sambuc std::error_code visitFilenameRecord(unsigned ID, unsigned Size,
226*0a6a1f1dSLionel Sambuc unsigned Timestamp,
227*0a6a1f1dSLionel Sambuc StringRef Name) override;
228*0a6a1f1dSLionel Sambuc
229*0a6a1f1dSLionel Sambuc std::error_code visitFixitRecord(const serialized_diags::Location &Start,
230*0a6a1f1dSLionel Sambuc const serialized_diags::Location &End,
231*0a6a1f1dSLionel Sambuc StringRef CodeToInsert) override;
232*0a6a1f1dSLionel Sambuc
233*0a6a1f1dSLionel Sambuc std::error_code
234*0a6a1f1dSLionel Sambuc visitSourceRangeRecord(const serialized_diags::Location &Start,
235*0a6a1f1dSLionel Sambuc const serialized_diags::Location &End) override;
236f4a2713aSLionel Sambuc
237f4a2713aSLionel Sambuc public:
DiagLoader(enum CXLoadDiag_Error * e,CXString * es)238f4a2713aSLionel Sambuc DiagLoader(enum CXLoadDiag_Error *e, CXString *es)
239*0a6a1f1dSLionel Sambuc : SerializedDiagnosticReader(), error(e), errorString(es) {
240f4a2713aSLionel Sambuc if (error)
241f4a2713aSLionel Sambuc *error = CXLoadDiag_None;
242f4a2713aSLionel Sambuc if (errorString)
243f4a2713aSLionel Sambuc *errorString = cxstring::createEmpty();
244f4a2713aSLionel Sambuc }
245f4a2713aSLionel Sambuc
246f4a2713aSLionel Sambuc CXDiagnosticSet load(const char *file);
247f4a2713aSLionel Sambuc };
248f4a2713aSLionel Sambuc }
249f4a2713aSLionel Sambuc
load(const char * file)250f4a2713aSLionel Sambuc CXDiagnosticSet DiagLoader::load(const char *file) {
251*0a6a1f1dSLionel Sambuc TopDiags = llvm::make_unique<CXLoadedDiagnosticSetImpl>();
252f4a2713aSLionel Sambuc
253*0a6a1f1dSLionel Sambuc std::error_code EC = readDiagnostics(file);
254*0a6a1f1dSLionel Sambuc if (EC) {
255*0a6a1f1dSLionel Sambuc switch (EC.value()) {
256*0a6a1f1dSLionel Sambuc case static_cast<int>(serialized_diags::SDError::HandlerFailed):
257*0a6a1f1dSLionel Sambuc // We've already reported the problem.
258f4a2713aSLionel Sambuc break;
259*0a6a1f1dSLionel Sambuc case static_cast<int>(serialized_diags::SDError::CouldNotLoad):
260*0a6a1f1dSLionel Sambuc reportBad(CXLoadDiag_CannotLoad, EC.message());
261f4a2713aSLionel Sambuc break;
262f4a2713aSLionel Sambuc default:
263*0a6a1f1dSLionel Sambuc reportInvalidFile(EC.message());
264*0a6a1f1dSLionel Sambuc break;
265*0a6a1f1dSLionel Sambuc }
266f4a2713aSLionel Sambuc return 0;
267f4a2713aSLionel Sambuc }
268*0a6a1f1dSLionel Sambuc
269*0a6a1f1dSLionel Sambuc return (CXDiagnosticSet)TopDiags.release();
270f4a2713aSLionel Sambuc }
271f4a2713aSLionel Sambuc
272*0a6a1f1dSLionel Sambuc std::error_code
readLocation(const serialized_diags::Location & SDLoc,CXLoadedDiagnostic::Location & LoadedLoc)273*0a6a1f1dSLionel Sambuc DiagLoader::readLocation(const serialized_diags::Location &SDLoc,
274*0a6a1f1dSLionel Sambuc CXLoadedDiagnostic::Location &LoadedLoc) {
275*0a6a1f1dSLionel Sambuc unsigned FileID = SDLoc.FileID;
276*0a6a1f1dSLionel Sambuc if (FileID == 0)
277*0a6a1f1dSLionel Sambuc LoadedLoc.file = nullptr;
278*0a6a1f1dSLionel Sambuc else {
279*0a6a1f1dSLionel Sambuc LoadedLoc.file = const_cast<FileEntry *>(TopDiags->Files[FileID]);
280*0a6a1f1dSLionel Sambuc if (!LoadedLoc.file)
281*0a6a1f1dSLionel Sambuc return reportInvalidFile("Corrupted file entry in source location");
282f4a2713aSLionel Sambuc }
283*0a6a1f1dSLionel Sambuc LoadedLoc.line = SDLoc.Line;
284*0a6a1f1dSLionel Sambuc LoadedLoc.column = SDLoc.Col;
285*0a6a1f1dSLionel Sambuc LoadedLoc.offset = SDLoc.Offset;
286*0a6a1f1dSLionel Sambuc return std::error_code();
287f4a2713aSLionel Sambuc }
288f4a2713aSLionel Sambuc
289*0a6a1f1dSLionel Sambuc std::error_code
readRange(const serialized_diags::Location & SDStart,const serialized_diags::Location & SDEnd,CXSourceRange & SR)290*0a6a1f1dSLionel Sambuc DiagLoader::readRange(const serialized_diags::Location &SDStart,
291*0a6a1f1dSLionel Sambuc const serialized_diags::Location &SDEnd,
292f4a2713aSLionel Sambuc CXSourceRange &SR) {
293f4a2713aSLionel Sambuc CXLoadedDiagnostic::Location *Start, *End;
294*0a6a1f1dSLionel Sambuc Start = TopDiags->Alloc.Allocate<CXLoadedDiagnostic::Location>();
295*0a6a1f1dSLionel Sambuc End = TopDiags->Alloc.Allocate<CXLoadedDiagnostic::Location>();
296f4a2713aSLionel Sambuc
297*0a6a1f1dSLionel Sambuc std::error_code EC;
298*0a6a1f1dSLionel Sambuc if ((EC = readLocation(SDStart, *Start)))
299*0a6a1f1dSLionel Sambuc return EC;
300*0a6a1f1dSLionel Sambuc if ((EC = readLocation(SDEnd, *End)))
301*0a6a1f1dSLionel Sambuc return EC;
302f4a2713aSLionel Sambuc
303f4a2713aSLionel Sambuc CXSourceLocation startLoc = makeLocation(Start);
304f4a2713aSLionel Sambuc CXSourceLocation endLoc = makeLocation(End);
305f4a2713aSLionel Sambuc SR = clang_getRange(startLoc, endLoc);
306*0a6a1f1dSLionel Sambuc return std::error_code();
307f4a2713aSLionel Sambuc }
308f4a2713aSLionel Sambuc
visitStartOfDiagnostic()309*0a6a1f1dSLionel Sambuc std::error_code DiagLoader::visitStartOfDiagnostic() {
310*0a6a1f1dSLionel Sambuc CurrentDiags.push_back(llvm::make_unique<CXLoadedDiagnostic>());
311*0a6a1f1dSLionel Sambuc return std::error_code();
312f4a2713aSLionel Sambuc }
313f4a2713aSLionel Sambuc
visitEndOfDiagnostic()314*0a6a1f1dSLionel Sambuc std::error_code DiagLoader::visitEndOfDiagnostic() {
315*0a6a1f1dSLionel Sambuc auto D = CurrentDiags.pop_back_val();
316*0a6a1f1dSLionel Sambuc if (CurrentDiags.empty())
317*0a6a1f1dSLionel Sambuc TopDiags->appendDiagnostic(std::move(D));
318*0a6a1f1dSLionel Sambuc else
319*0a6a1f1dSLionel Sambuc CurrentDiags.back()->getChildDiagnostics().appendDiagnostic(std::move(D));
320*0a6a1f1dSLionel Sambuc return std::error_code();
321f4a2713aSLionel Sambuc }
322f4a2713aSLionel Sambuc
visitCategoryRecord(unsigned ID,StringRef Name)323*0a6a1f1dSLionel Sambuc std::error_code DiagLoader::visitCategoryRecord(unsigned ID, StringRef Name) {
324*0a6a1f1dSLionel Sambuc // FIXME: Why do we care about long strings?
325*0a6a1f1dSLionel Sambuc if (Name.size() > 65536)
326*0a6a1f1dSLionel Sambuc return reportInvalidFile("Out-of-bounds string in category");
327*0a6a1f1dSLionel Sambuc TopDiags->Categories[ID] = TopDiags->copyString(Name);
328*0a6a1f1dSLionel Sambuc return std::error_code();
329f4a2713aSLionel Sambuc }
330f4a2713aSLionel Sambuc
visitDiagFlagRecord(unsigned ID,StringRef Name)331*0a6a1f1dSLionel Sambuc std::error_code DiagLoader::visitDiagFlagRecord(unsigned ID, StringRef Name) {
332*0a6a1f1dSLionel Sambuc // FIXME: Why do we care about long strings?
333*0a6a1f1dSLionel Sambuc if (Name.size() > 65536)
334*0a6a1f1dSLionel Sambuc return reportInvalidFile("Out-of-bounds string in warning flag");
335*0a6a1f1dSLionel Sambuc TopDiags->WarningFlags[ID] = TopDiags->copyString(Name);
336*0a6a1f1dSLionel Sambuc return std::error_code();
337f4a2713aSLionel Sambuc }
338f4a2713aSLionel Sambuc
visitFilenameRecord(unsigned ID,unsigned Size,unsigned Timestamp,StringRef Name)339*0a6a1f1dSLionel Sambuc std::error_code DiagLoader::visitFilenameRecord(unsigned ID, unsigned Size,
340*0a6a1f1dSLionel Sambuc unsigned Timestamp,
341*0a6a1f1dSLionel Sambuc StringRef Name) {
342*0a6a1f1dSLionel Sambuc // FIXME: Why do we care about long strings?
343*0a6a1f1dSLionel Sambuc if (Name.size() > 65536)
344*0a6a1f1dSLionel Sambuc return reportInvalidFile("Out-of-bounds string in filename");
345*0a6a1f1dSLionel Sambuc TopDiags->FileNames[ID] = TopDiags->copyString(Name);
346*0a6a1f1dSLionel Sambuc TopDiags->Files[ID] =
347*0a6a1f1dSLionel Sambuc TopDiags->FakeFiles.getVirtualFile(Name, Size, Timestamp);
348*0a6a1f1dSLionel Sambuc return std::error_code();
349f4a2713aSLionel Sambuc }
350f4a2713aSLionel Sambuc
351*0a6a1f1dSLionel Sambuc std::error_code
visitSourceRangeRecord(const serialized_diags::Location & Start,const serialized_diags::Location & End)352*0a6a1f1dSLionel Sambuc DiagLoader::visitSourceRangeRecord(const serialized_diags::Location &Start,
353*0a6a1f1dSLionel Sambuc const serialized_diags::Location &End) {
354f4a2713aSLionel Sambuc CXSourceRange SR;
355*0a6a1f1dSLionel Sambuc if (std::error_code EC = readRange(Start, End, SR))
356*0a6a1f1dSLionel Sambuc return EC;
357*0a6a1f1dSLionel Sambuc CurrentDiags.back()->Ranges.push_back(SR);
358*0a6a1f1dSLionel Sambuc return std::error_code();
359f4a2713aSLionel Sambuc }
360f4a2713aSLionel Sambuc
361*0a6a1f1dSLionel Sambuc std::error_code
visitFixitRecord(const serialized_diags::Location & Start,const serialized_diags::Location & End,StringRef CodeToInsert)362*0a6a1f1dSLionel Sambuc DiagLoader::visitFixitRecord(const serialized_diags::Location &Start,
363*0a6a1f1dSLionel Sambuc const serialized_diags::Location &End,
364*0a6a1f1dSLionel Sambuc StringRef CodeToInsert) {
365f4a2713aSLionel Sambuc CXSourceRange SR;
366*0a6a1f1dSLionel Sambuc if (std::error_code EC = readRange(Start, End, SR))
367*0a6a1f1dSLionel Sambuc return EC;
368*0a6a1f1dSLionel Sambuc // FIXME: Why do we care about long strings?
369*0a6a1f1dSLionel Sambuc if (CodeToInsert.size() > 65536)
370*0a6a1f1dSLionel Sambuc return reportInvalidFile("Out-of-bounds string in FIXIT");
371*0a6a1f1dSLionel Sambuc CurrentDiags.back()->FixIts.push_back(
372*0a6a1f1dSLionel Sambuc std::make_pair(SR, TopDiags->copyString(CodeToInsert)));
373*0a6a1f1dSLionel Sambuc return std::error_code();
374f4a2713aSLionel Sambuc }
375f4a2713aSLionel Sambuc
visitDiagnosticRecord(unsigned Severity,const serialized_diags::Location & Location,unsigned Category,unsigned Flag,StringRef Message)376*0a6a1f1dSLionel Sambuc std::error_code DiagLoader::visitDiagnosticRecord(
377*0a6a1f1dSLionel Sambuc unsigned Severity, const serialized_diags::Location &Location,
378*0a6a1f1dSLionel Sambuc unsigned Category, unsigned Flag, StringRef Message) {
379*0a6a1f1dSLionel Sambuc CXLoadedDiagnostic &D = *CurrentDiags.back();
380*0a6a1f1dSLionel Sambuc D.severity = Severity;
381*0a6a1f1dSLionel Sambuc if (std::error_code EC = readLocation(Location, D.DiagLoc))
382*0a6a1f1dSLionel Sambuc return EC;
383*0a6a1f1dSLionel Sambuc D.category = Category;
384*0a6a1f1dSLionel Sambuc D.DiagOption = Flag ? TopDiags->WarningFlags[Flag] : "";
385*0a6a1f1dSLionel Sambuc D.CategoryText = Category ? TopDiags->Categories[Category] : "";
386*0a6a1f1dSLionel Sambuc D.Spelling = TopDiags->copyString(Message);
387*0a6a1f1dSLionel Sambuc return std::error_code();
388f4a2713aSLionel Sambuc }
389f4a2713aSLionel Sambuc
390f4a2713aSLionel Sambuc extern "C" {
clang_loadDiagnostics(const char * file,enum CXLoadDiag_Error * error,CXString * errorString)391f4a2713aSLionel Sambuc CXDiagnosticSet clang_loadDiagnostics(const char *file,
392f4a2713aSLionel Sambuc enum CXLoadDiag_Error *error,
393f4a2713aSLionel Sambuc CXString *errorString) {
394f4a2713aSLionel Sambuc DiagLoader L(error, errorString);
395f4a2713aSLionel Sambuc return L.load(file);
396f4a2713aSLionel Sambuc }
397f4a2713aSLionel Sambuc } // end extern 'C'.
398