blob: 65b816c3976d19dc185a72f5eab7b8a09a42d7e6 [file] [log] [blame]
Chris Lattner2815bc92013-01-19 18:47:35 +00001//===-- CXLoadedDiagnostic.cpp - Handling of persisent diags ----*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// Implements handling of persisent diagnostics.
11//
12//===----------------------------------------------------------------------===//
Ted Kremenek15322172011-11-10 08:43:12 +000013
14#include "CXLoadedDiagnostic.h"
15#include "CXString.h"
16#include "clang/Basic/Diagnostic.h"
17#include "clang/Basic/FileManager.h"
18#include "clang/Frontend/SerializedDiagnosticPrinter.h"
19#include "llvm/ADT/StringRef.h"
20#include "llvm/ADT/Twine.h"
21#include "llvm/ADT/Optional.h"
22#include "clang/Basic/LLVM.h"
23#include "llvm/Support/ErrorHandling.h"
24#include "llvm/Bitcode/BitstreamReader.h"
25#include "llvm/Support/MemoryBuffer.h"
Ted Kremenek15322172011-11-10 08:43:12 +000026using namespace clang;
27using namespace clang::cxstring;
28
29//===----------------------------------------------------------------------===//
30// Extend CXDiagnosticSetImpl which contains strings for diagnostics.
31//===----------------------------------------------------------------------===//
32
33typedef llvm::DenseMap<unsigned, llvm::StringRef> Strings;
34
35namespace {
36class CXLoadedDiagnosticSetImpl : public CXDiagnosticSetImpl {
37public:
38 CXLoadedDiagnosticSetImpl() : CXDiagnosticSetImpl(true), FakeFiles(FO) {}
39 virtual ~CXLoadedDiagnosticSetImpl() {}
40
Ted Kremenek15322172011-11-10 08:43:12 +000041 llvm::BumpPtrAllocator Alloc;
42 Strings Categories;
43 Strings WarningFlags;
44 Strings FileNames;
45
46 FileSystemOptions FO;
47 FileManager FakeFiles;
48 llvm::DenseMap<unsigned, const FileEntry *> Files;
Chris Lattnerb3ce3572013-01-20 02:38:54 +000049
50 llvm::StringRef makeString(StringRef Blob) {
51 char *mem = Alloc.Allocate<char>(Blob.size() + 1);
52 memcpy(mem, Blob.data(), Blob.size());
53 // Add a null terminator for those clients accessing the buffer
54 // like a c-string.
55 mem[Blob.size()] = '\0';
56 return llvm::StringRef(mem, Blob.size());
57 }
Ted Kremenek15322172011-11-10 08:43:12 +000058};
59}
60
Ted Kremenek15322172011-11-10 08:43:12 +000061//===----------------------------------------------------------------------===//
62// Cleanup.
63//===----------------------------------------------------------------------===//
64
65CXLoadedDiagnostic::~CXLoadedDiagnostic() {}
66
67//===----------------------------------------------------------------------===//
68// Public CXLoadedDiagnostic methods.
69//===----------------------------------------------------------------------===//
70
71CXDiagnosticSeverity CXLoadedDiagnostic::getSeverity() const {
72 // FIXME: possibly refactor with logic in CXStoredDiagnostic.
73 switch (severity) {
74 case DiagnosticsEngine::Ignored: return CXDiagnostic_Ignored;
75 case DiagnosticsEngine::Note: return CXDiagnostic_Note;
76 case DiagnosticsEngine::Warning: return CXDiagnostic_Warning;
77 case DiagnosticsEngine::Error: return CXDiagnostic_Error;
78 case DiagnosticsEngine::Fatal: return CXDiagnostic_Fatal;
79 }
80
81 llvm_unreachable("Invalid diagnostic level");
Ted Kremenek15322172011-11-10 08:43:12 +000082}
83
84static CXSourceLocation makeLocation(const CXLoadedDiagnostic::Location *DLoc) {
85 // The lowest bit of ptr_data[0] is always set to 1 to indicate this
86 // is a persistent diagnostic.
87 uintptr_t V = (uintptr_t) DLoc;
88 V |= 0x1;
89 CXSourceLocation Loc = { { (void*) V, 0 }, 0 };
90 return Loc;
91}
92
93CXSourceLocation CXLoadedDiagnostic::getLocation() const {
94 // The lowest bit of ptr_data[0] is always set to 1 to indicate this
95 // is a persistent diagnostic.
96 return makeLocation(&DiagLoc);
97}
98
99CXString CXLoadedDiagnostic::getSpelling() const {
Ted Kremeneke97ac9e2011-11-11 15:19:48 +0000100 return cxstring::createCXString(Spelling, false);
Ted Kremenek15322172011-11-10 08:43:12 +0000101}
102
103CXString CXLoadedDiagnostic::getDiagnosticOption(CXString *Disable) const {
104 if (DiagOption.empty())
105 return createCXString("");
106
107 // FIXME: possibly refactor with logic in CXStoredDiagnostic.
108 if (Disable)
109 *Disable = createCXString((Twine("-Wno-") + DiagOption).str());
110 return createCXString((Twine("-W") + DiagOption).str());
111}
112
113unsigned CXLoadedDiagnostic::getCategory() const {
114 return category;
115}
116
Ted Kremenek78d5d3b2012-04-12 00:03:31 +0000117CXString CXLoadedDiagnostic::getCategoryText() const {
118 return cxstring::createCXString(CategoryText);
119}
120
Ted Kremenek15322172011-11-10 08:43:12 +0000121unsigned CXLoadedDiagnostic::getNumRanges() const {
122 return Ranges.size();
123}
124
125CXSourceRange CXLoadedDiagnostic::getRange(unsigned Range) const {
126 assert(Range < Ranges.size());
127 return Ranges[Range];
128}
129
130unsigned CXLoadedDiagnostic::getNumFixIts() const {
131 return FixIts.size();
132}
133
134CXString CXLoadedDiagnostic::getFixIt(unsigned FixIt,
135 CXSourceRange *ReplacementRange) const {
136 assert(FixIt < FixIts.size());
137 if (ReplacementRange)
138 *ReplacementRange = FixIts[FixIt].first;
139 return FixIts[FixIt].second;
140}
141
142void CXLoadedDiagnostic::decodeLocation(CXSourceLocation location,
143 CXFile *file,
144 unsigned int *line,
145 unsigned int *column,
146 unsigned int *offset) {
147
148
149 // CXSourceLocation consists of the following fields:
150 //
151 // void *ptr_data[2];
152 // unsigned int_data;
153 //
154 // The lowest bit of ptr_data[0] is always set to 1 to indicate this
155 // is a persistent diagnostic.
156 //
157 // For now, do the unoptimized approach and store the data in a side
158 // data structure. We can optimize this case later.
159
160 uintptr_t V = (uintptr_t) location.ptr_data[0];
161 assert((V & 0x1) == 1);
162 V &= ~(uintptr_t)1;
163
164 const Location &Loc = *((Location*)V);
165
166 if (file)
167 *file = Loc.file;
168 if (line)
169 *line = Loc.line;
170 if (column)
171 *column = Loc.column;
172 if (offset)
173 *offset = Loc.offset;
174}
175
176//===----------------------------------------------------------------------===//
177// Deserialize diagnostics.
178//===----------------------------------------------------------------------===//
179
180enum { MaxSupportedVersion = 1 };
181typedef SmallVector<uint64_t, 64> RecordData;
182enum LoadResult { Failure = 1, Success = 0 };
183enum StreamResult { Read_EndOfStream,
184 Read_BlockBegin,
185 Read_Failure,
186 Read_Record,
187 Read_BlockEnd };
188
189namespace {
190class DiagLoader {
191 enum CXLoadDiag_Error *error;
192 CXString *errorString;
193
194 void reportBad(enum CXLoadDiag_Error code, llvm::StringRef err) {
195 if (error)
196 *error = code;
197 if (errorString)
198 *errorString = createCXString(err);
199 }
200
201 void reportInvalidFile(llvm::StringRef err) {
202 return reportBad(CXLoadDiag_InvalidFile, err);
203 }
204
205 LoadResult readMetaBlock(llvm::BitstreamCursor &Stream);
206
207 LoadResult readDiagnosticBlock(llvm::BitstreamCursor &Stream,
208 CXDiagnosticSetImpl &Diags,
209 CXLoadedDiagnosticSetImpl &TopDiags);
210
211 StreamResult readToNextRecordOrBlock(llvm::BitstreamCursor &Stream,
212 llvm::StringRef errorContext,
213 unsigned &BlockOrRecordID,
Chris Lattnere485f072013-01-19 21:35:35 +0000214 bool atTopLevel = false);
Ted Kremenek15322172011-11-10 08:43:12 +0000215
216
217 LoadResult readString(CXLoadedDiagnosticSetImpl &TopDiags,
218 Strings &strings, llvm::StringRef errorContext,
219 RecordData &Record,
Chris Lattnerb3ce3572013-01-20 02:38:54 +0000220 StringRef Blob,
Ted Kremenek952538d2011-11-29 00:30:52 +0000221 bool allowEmptyString = false);
Ted Kremenek15322172011-11-10 08:43:12 +0000222
223 LoadResult readString(CXLoadedDiagnosticSetImpl &TopDiags,
224 llvm::StringRef &RetStr,
225 llvm::StringRef errorContext,
226 RecordData &Record,
Chris Lattnerb3ce3572013-01-20 02:38:54 +0000227 StringRef Blob,
Ted Kremenek952538d2011-11-29 00:30:52 +0000228 bool allowEmptyString = false);
Ted Kremenek15322172011-11-10 08:43:12 +0000229
230 LoadResult readRange(CXLoadedDiagnosticSetImpl &TopDiags,
231 RecordData &Record, unsigned RecStartIdx,
232 CXSourceRange &SR);
233
234 LoadResult readLocation(CXLoadedDiagnosticSetImpl &TopDiags,
235 RecordData &Record, unsigned &offset,
236 CXLoadedDiagnostic::Location &Loc);
237
238public:
239 DiagLoader(enum CXLoadDiag_Error *e, CXString *es)
240 : error(e), errorString(es) {
241 if (error)
242 *error = CXLoadDiag_None;
243 if (errorString)
244 *errorString = createCXString("");
245 }
Ted Kremeneke97ac9e2011-11-11 15:19:48 +0000246
Ted Kremenek15322172011-11-10 08:43:12 +0000247 CXDiagnosticSet load(const char *file);
248};
249}
250
251CXDiagnosticSet DiagLoader::load(const char *file) {
252 // Open the diagnostics file.
253 std::string ErrStr;
254 FileSystemOptions FO;
255 FileManager FileMgr(FO);
256
Dylan Noblesmith1e4c01b2012-02-13 12:32:21 +0000257 OwningPtr<llvm::MemoryBuffer> Buffer;
Ted Kremenek15322172011-11-10 08:43:12 +0000258 Buffer.reset(FileMgr.getBufferForFile(file));
259
260 if (!Buffer) {
261 reportBad(CXLoadDiag_CannotLoad, ErrStr);
262 return 0;
263 }
264
265 llvm::BitstreamReader StreamFile;
266 StreamFile.init((const unsigned char *)Buffer->getBufferStart(),
267 (const unsigned char *)Buffer->getBufferEnd());
268
269 llvm::BitstreamCursor Stream;
270 Stream.init(StreamFile);
271
272 // Sniff for the signature.
273 if (Stream.Read(8) != 'D' ||
274 Stream.Read(8) != 'I' ||
275 Stream.Read(8) != 'A' ||
276 Stream.Read(8) != 'G') {
277 reportBad(CXLoadDiag_InvalidFile,
278 "Bad header in diagnostics file");
279 return 0;
280 }
281
Chris Lattnere485f072013-01-19 21:35:35 +0000282 OwningPtr<CXLoadedDiagnosticSetImpl> Diags(new CXLoadedDiagnosticSetImpl());
Ted Kremenek15322172011-11-10 08:43:12 +0000283
284 while (true) {
285 unsigned BlockID = 0;
286 StreamResult Res = readToNextRecordOrBlock(Stream, "Top-level",
287 BlockID, true);
288 switch (Res) {
289 case Read_EndOfStream:
290 return (CXDiagnosticSet) Diags.take();
291 case Read_Failure:
292 return 0;
293 case Read_Record:
294 llvm_unreachable("Top-level does not have records");
Ted Kremenek15322172011-11-10 08:43:12 +0000295 case Read_BlockEnd:
296 continue;
297 case Read_BlockBegin:
298 break;
299 }
300
301 switch (BlockID) {
302 case serialized_diags::BLOCK_META:
303 if (readMetaBlock(Stream))
304 return 0;
305 break;
306 case serialized_diags::BLOCK_DIAG:
307 if (readDiagnosticBlock(Stream, *Diags.get(), *Diags.get()))
308 return 0;
309 break;
310 default:
311 if (!Stream.SkipBlock()) {
312 reportInvalidFile("Malformed block at top-level of diagnostics file");
313 return 0;
314 }
315 break;
316 }
317 }
318}
319
320StreamResult DiagLoader::readToNextRecordOrBlock(llvm::BitstreamCursor &Stream,
321 llvm::StringRef errorContext,
322 unsigned &blockOrRecordID,
Chris Lattnere485f072013-01-19 21:35:35 +0000323 bool atTopLevel) {
Ted Kremenek15322172011-11-10 08:43:12 +0000324
325 blockOrRecordID = 0;
326
327 while (!Stream.AtEndOfStream()) {
328 unsigned Code = Stream.ReadCode();
329
330 // Handle the top-level specially.
331 if (atTopLevel) {
332 if (Code == llvm::bitc::ENTER_SUBBLOCK) {
333 unsigned BlockID = Stream.ReadSubBlockID();
334 if (BlockID == llvm::bitc::BLOCKINFO_BLOCK_ID) {
335 if (Stream.ReadBlockInfoBlock()) {
336 reportInvalidFile("Malformed BlockInfoBlock in diagnostics file");
337 return Read_Failure;
338 }
339 continue;
340 }
341 blockOrRecordID = BlockID;
342 return Read_BlockBegin;
343 }
344 reportInvalidFile("Only blocks can appear at the top of a "
345 "diagnostic file");
346 return Read_Failure;
347 }
348
349 switch ((llvm::bitc::FixedAbbrevIDs)Code) {
350 case llvm::bitc::ENTER_SUBBLOCK:
351 blockOrRecordID = Stream.ReadSubBlockID();
352 return Read_BlockBegin;
353
354 case llvm::bitc::END_BLOCK:
355 if (Stream.ReadBlockEnd()) {
356 reportInvalidFile("Cannot read end of block");
357 return Read_Failure;
358 }
359 return Read_BlockEnd;
360
361 case llvm::bitc::DEFINE_ABBREV:
362 Stream.ReadAbbrevRecord();
363 continue;
364
365 case llvm::bitc::UNABBREV_RECORD:
366 reportInvalidFile("Diagnostics file should have no unabbreviated "
367 "records");
368 return Read_Failure;
369
370 default:
371 // We found a record.
372 blockOrRecordID = Code;
373 return Read_Record;
374 }
375 }
376
377 if (atTopLevel)
378 return Read_EndOfStream;
379
380 reportInvalidFile(Twine("Premature end of diagnostics file within ").str() +
381 errorContext.str());
382 return Read_Failure;
383}
384
385LoadResult DiagLoader::readMetaBlock(llvm::BitstreamCursor &Stream) {
386 if (Stream.EnterSubBlock(clang::serialized_diags::BLOCK_META)) {
387 reportInvalidFile("Malformed metadata block");
388 return Failure;
389 }
390
391 bool versionChecked = false;
392
393 while (true) {
394 unsigned blockOrCode = 0;
395 StreamResult Res = readToNextRecordOrBlock(Stream, "Metadata Block",
396 blockOrCode);
397
398 switch(Res) {
399 case Read_EndOfStream:
400 llvm_unreachable("EndOfStream handled by readToNextRecordOrBlock");
401 case Read_Failure:
402 return Failure;
403 case Read_Record:
404 break;
405 case Read_BlockBegin:
406 if (Stream.SkipBlock()) {
407 reportInvalidFile("Malformed metadata block");
408 return Failure;
409 }
410 case Read_BlockEnd:
411 if (!versionChecked) {
412 reportInvalidFile("Diagnostics file does not contain version"
413 " information");
414 return Failure;
415 }
416 return Success;
417 }
418
419 RecordData Record;
Chris Lattnerb3ce3572013-01-20 02:38:54 +0000420 unsigned recordID = Stream.readRecord(blockOrCode, Record);
Ted Kremenek15322172011-11-10 08:43:12 +0000421
422 if (recordID == serialized_diags::RECORD_VERSION) {
423 if (Record.size() < 1) {
424 reportInvalidFile("malformed VERSION identifier in diagnostics file");
425 return Failure;
426 }
427 if (Record[0] > MaxSupportedVersion) {
428 reportInvalidFile("diagnosics file is a newer version than the one "
429 "supported");
430 return Failure;
431 }
432 versionChecked = true;
433 }
434 }
435}
436
437LoadResult DiagLoader::readString(CXLoadedDiagnosticSetImpl &TopDiags,
438 llvm::StringRef &RetStr,
439 llvm::StringRef errorContext,
440 RecordData &Record,
Chris Lattnerb3ce3572013-01-20 02:38:54 +0000441 StringRef Blob,
Ted Kremenek952538d2011-11-29 00:30:52 +0000442 bool allowEmptyString) {
Ted Kremenek15322172011-11-10 08:43:12 +0000443
444 // Basic buffer overflow check.
Chris Lattnerb3ce3572013-01-20 02:38:54 +0000445 if (Blob.size() > 65536) {
Ted Kremenek15322172011-11-10 08:43:12 +0000446 reportInvalidFile(std::string("Out-of-bounds string in ") +
447 std::string(errorContext));
448 return Failure;
449 }
Ted Kremenek952538d2011-11-29 00:30:52 +0000450
Chris Lattnerb3ce3572013-01-20 02:38:54 +0000451 if (allowEmptyString && Record.size() >= 1 && Blob.size() == 0) {
Ted Kremenek952538d2011-11-29 00:30:52 +0000452 RetStr = "";
453 return Success;
454 }
Ted Kremenek15322172011-11-10 08:43:12 +0000455
Chris Lattnerb3ce3572013-01-20 02:38:54 +0000456 if (Record.size() < 1 || Blob.size() == 0) {
Ted Kremenek15322172011-11-10 08:43:12 +0000457 reportInvalidFile(std::string("Corrupted ") + std::string(errorContext)
458 + std::string(" entry"));
459 return Failure;
460 }
461
Chris Lattnerb3ce3572013-01-20 02:38:54 +0000462 RetStr = TopDiags.makeString(Blob);
Ted Kremenek15322172011-11-10 08:43:12 +0000463 return Success;
464}
465
466LoadResult DiagLoader::readString(CXLoadedDiagnosticSetImpl &TopDiags,
467 Strings &strings,
468 llvm::StringRef errorContext,
469 RecordData &Record,
Chris Lattnerb3ce3572013-01-20 02:38:54 +0000470 StringRef Blob,
Ted Kremenek952538d2011-11-29 00:30:52 +0000471 bool allowEmptyString) {
Ted Kremenek15322172011-11-10 08:43:12 +0000472 llvm::StringRef RetStr;
Chris Lattnerb3ce3572013-01-20 02:38:54 +0000473 if (readString(TopDiags, RetStr, errorContext, Record, Blob,
Ted Kremenek952538d2011-11-29 00:30:52 +0000474 allowEmptyString))
Ted Kremenek15322172011-11-10 08:43:12 +0000475 return Failure;
476 strings[Record[0]] = RetStr;
477 return Success;
478}
479
480LoadResult DiagLoader::readLocation(CXLoadedDiagnosticSetImpl &TopDiags,
481 RecordData &Record, unsigned &offset,
482 CXLoadedDiagnostic::Location &Loc) {
483 if (Record.size() < offset + 3) {
484 reportInvalidFile("Corrupted source location");
485 return Failure;
486 }
487
488 unsigned fileID = Record[offset++];
489 if (fileID == 0) {
490 // Sentinel value.
491 Loc.file = 0;
492 Loc.line = 0;
493 Loc.column = 0;
494 Loc.offset = 0;
495 return Success;
496 }
497
498 const FileEntry *FE = TopDiags.Files[fileID];
499 if (!FE) {
500 reportInvalidFile("Corrupted file entry in source location");
501 return Failure;
502 }
David Greene527ce9f2013-01-15 22:09:48 +0000503 Loc.file = const_cast<FileEntry *>(FE);
Ted Kremenek15322172011-11-10 08:43:12 +0000504 Loc.line = Record[offset++];
505 Loc.column = Record[offset++];
506 Loc.offset = Record[offset++];
507 return Success;
508}
509
510LoadResult DiagLoader::readRange(CXLoadedDiagnosticSetImpl &TopDiags,
511 RecordData &Record,
512 unsigned int RecStartIdx,
513 CXSourceRange &SR) {
514 CXLoadedDiagnostic::Location *Start, *End;
515 Start = TopDiags.Alloc.Allocate<CXLoadedDiagnostic::Location>();
516 End = TopDiags.Alloc.Allocate<CXLoadedDiagnostic::Location>();
517
518 if (readLocation(TopDiags, Record, RecStartIdx, *Start))
519 return Failure;
520 if (readLocation(TopDiags, Record, RecStartIdx, *End))
521 return Failure;
522
523 CXSourceLocation startLoc = makeLocation(Start);
524 CXSourceLocation endLoc = makeLocation(End);
525 SR = clang_getRange(startLoc, endLoc);
526 return Success;
527}
528
529LoadResult DiagLoader::readDiagnosticBlock(llvm::BitstreamCursor &Stream,
530 CXDiagnosticSetImpl &Diags,
531 CXLoadedDiagnosticSetImpl &TopDiags){
532
533 if (Stream.EnterSubBlock(clang::serialized_diags::BLOCK_DIAG)) {
534 reportInvalidFile("malformed diagnostic block");
535 return Failure;
536 }
537
Dylan Noblesmith1e4c01b2012-02-13 12:32:21 +0000538 OwningPtr<CXLoadedDiagnostic> D(new CXLoadedDiagnostic());
Ted Kremenek15322172011-11-10 08:43:12 +0000539 RecordData Record;
540
541 while (true) {
542 unsigned blockOrCode = 0;
543 StreamResult Res = readToNextRecordOrBlock(Stream, "Diagnostic Block",
544 blockOrCode);
545 switch (Res) {
546 case Read_EndOfStream:
547 llvm_unreachable("EndOfStream handled in readToNextRecordOrBlock");
Ted Kremenek15322172011-11-10 08:43:12 +0000548 case Read_Failure:
549 return Failure;
550 case Read_BlockBegin: {
551 // The only blocks we care about are subdiagnostics.
552 if (blockOrCode != serialized_diags::BLOCK_DIAG) {
553 if (!Stream.SkipBlock()) {
554 reportInvalidFile("Invalid subblock in Diagnostics block");
555 return Failure;
556 }
557 } else if (readDiagnosticBlock(Stream, D->getChildDiagnostics(),
558 TopDiags)) {
559 return Failure;
560 }
561
562 continue;
563 }
564 case Read_BlockEnd:
565 Diags.appendDiagnostic(D.take());
566 return Success;
567 case Read_Record:
568 break;
569 }
570
571 // Read the record.
572 Record.clear();
Chris Lattnerb3ce3572013-01-20 02:38:54 +0000573 StringRef Blob;
574 unsigned recID = Stream.readRecord(blockOrCode, Record, &Blob);
Ted Kremenek15322172011-11-10 08:43:12 +0000575
576 if (recID < serialized_diags::RECORD_FIRST ||
577 recID > serialized_diags::RECORD_LAST)
578 continue;
579
580 switch ((serialized_diags::RecordIDs)recID) {
581 case serialized_diags::RECORD_VERSION:
582 continue;
583 case serialized_diags::RECORD_CATEGORY:
584 if (readString(TopDiags, TopDiags.Categories, "category", Record,
Chris Lattnerb3ce3572013-01-20 02:38:54 +0000585 Blob, /* allowEmptyString */ true))
Ted Kremenek15322172011-11-10 08:43:12 +0000586 return Failure;
587 continue;
588
589 case serialized_diags::RECORD_DIAG_FLAG:
590 if (readString(TopDiags, TopDiags.WarningFlags, "warning flag", Record,
Chris Lattnerb3ce3572013-01-20 02:38:54 +0000591 Blob))
Ted Kremenek15322172011-11-10 08:43:12 +0000592 return Failure;
593 continue;
594
595 case serialized_diags::RECORD_FILENAME: {
596 if (readString(TopDiags, TopDiags.FileNames, "filename", Record,
Chris Lattnerb3ce3572013-01-20 02:38:54 +0000597 Blob))
Ted Kremenek15322172011-11-10 08:43:12 +0000598 return Failure;
599
600 if (Record.size() < 3) {
601 reportInvalidFile("Invalid file entry");
602 return Failure;
603 }
604
605 const FileEntry *FE =
606 TopDiags.FakeFiles.getVirtualFile(TopDiags.FileNames[Record[0]],
607 /* size */ Record[1],
608 /* time */ Record[2]);
609
610 TopDiags.Files[Record[0]] = FE;
611 continue;
612 }
613
614 case serialized_diags::RECORD_SOURCE_RANGE: {
615 CXSourceRange SR;
616 if (readRange(TopDiags, Record, 0, SR))
617 return Failure;
618 D->Ranges.push_back(SR);
619 continue;
620 }
621
622 case serialized_diags::RECORD_FIXIT: {
623 CXSourceRange SR;
624 if (readRange(TopDiags, Record, 0, SR))
625 return Failure;
626 llvm::StringRef RetStr;
Chris Lattnerb3ce3572013-01-20 02:38:54 +0000627 if (readString(TopDiags, RetStr, "FIXIT", Record, Blob,
Ted Kremenek952538d2011-11-29 00:30:52 +0000628 /* allowEmptyString */ true))
Ted Kremenek15322172011-11-10 08:43:12 +0000629 return Failure;
Ted Kremeneke97ac9e2011-11-11 15:19:48 +0000630 D->FixIts.push_back(std::make_pair(SR, createCXString(RetStr, false)));
631 continue;
Ted Kremenek15322172011-11-10 08:43:12 +0000632 }
633
634 case serialized_diags::RECORD_DIAG: {
635 D->severity = Record[0];
636 unsigned offset = 1;
637 if (readLocation(TopDiags, Record, offset, D->DiagLoc))
638 return Failure;
639 D->category = Record[offset++];
640 unsigned diagFlag = Record[offset++];
641 D->DiagOption = diagFlag ? TopDiags.WarningFlags[diagFlag] : "";
Ted Kremenek78d5d3b2012-04-12 00:03:31 +0000642 D->CategoryText = D->category ? TopDiags.Categories[D->category] : "";
Chris Lattnerb3ce3572013-01-20 02:38:54 +0000643 D->Spelling = TopDiags.makeString(Blob);
Ted Kremenek15322172011-11-10 08:43:12 +0000644 continue;
645 }
646 }
647 }
648}
649
650extern "C" {
651CXDiagnosticSet clang_loadDiagnostics(const char *file,
652 enum CXLoadDiag_Error *error,
653 CXString *errorString) {
654 DiagLoader L(error, errorString);
655 return L.load(file);
656}
657} // end extern 'C'.