blob: e5b6ccc5b7e81ea32b6d04c2193f2190adfd0eeb [file] [log] [blame]
Ted Kremenek15322172011-11-10 08:43:12 +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\*===----------------------------------------------------------------------===*/
13
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"
26#include <assert.h>
27
28using namespace clang;
29using namespace clang::cxstring;
30
31//===----------------------------------------------------------------------===//
32// Extend CXDiagnosticSetImpl which contains strings for diagnostics.
33//===----------------------------------------------------------------------===//
34
35typedef llvm::DenseMap<unsigned, llvm::StringRef> Strings;
36
37namespace {
38class CXLoadedDiagnosticSetImpl : public CXDiagnosticSetImpl {
39public:
40 CXLoadedDiagnosticSetImpl() : CXDiagnosticSetImpl(true), FakeFiles(FO) {}
41 virtual ~CXLoadedDiagnosticSetImpl() {}
42
43 llvm::StringRef makeString(const char *blob, unsigned blobLen);
44
45 llvm::BumpPtrAllocator Alloc;
46 Strings Categories;
47 Strings WarningFlags;
48 Strings FileNames;
49
50 FileSystemOptions FO;
51 FileManager FakeFiles;
52 llvm::DenseMap<unsigned, const FileEntry *> Files;
53};
54}
55
56llvm::StringRef CXLoadedDiagnosticSetImpl::makeString(const char *blob,
57 unsigned bloblen) {
Ted Kremeneke97ac9e2011-11-11 15:19:48 +000058 char *mem = Alloc.Allocate<char>(bloblen + 1);
Ted Kremenek15322172011-11-10 08:43:12 +000059 memcpy(mem, blob, bloblen);
Ted Kremeneke97ac9e2011-11-11 15:19:48 +000060 // Add a null terminator for those clients accessing the buffer
61 // like a c-string.
62 mem[bloblen] = '\0';
Ted Kremenek15322172011-11-10 08:43:12 +000063 return llvm::StringRef(mem, bloblen);
64}
65
66//===----------------------------------------------------------------------===//
67// Cleanup.
68//===----------------------------------------------------------------------===//
69
70CXLoadedDiagnostic::~CXLoadedDiagnostic() {}
71
72//===----------------------------------------------------------------------===//
73// Public CXLoadedDiagnostic methods.
74//===----------------------------------------------------------------------===//
75
76CXDiagnosticSeverity CXLoadedDiagnostic::getSeverity() const {
77 // FIXME: possibly refactor with logic in CXStoredDiagnostic.
78 switch (severity) {
79 case DiagnosticsEngine::Ignored: return CXDiagnostic_Ignored;
80 case DiagnosticsEngine::Note: return CXDiagnostic_Note;
81 case DiagnosticsEngine::Warning: return CXDiagnostic_Warning;
82 case DiagnosticsEngine::Error: return CXDiagnostic_Error;
83 case DiagnosticsEngine::Fatal: return CXDiagnostic_Fatal;
84 }
85
86 llvm_unreachable("Invalid diagnostic level");
Ted Kremenek15322172011-11-10 08:43:12 +000087}
88
89static CXSourceLocation makeLocation(const CXLoadedDiagnostic::Location *DLoc) {
90 // The lowest bit of ptr_data[0] is always set to 1 to indicate this
91 // is a persistent diagnostic.
92 uintptr_t V = (uintptr_t) DLoc;
93 V |= 0x1;
94 CXSourceLocation Loc = { { (void*) V, 0 }, 0 };
95 return Loc;
96}
97
98CXSourceLocation CXLoadedDiagnostic::getLocation() const {
99 // The lowest bit of ptr_data[0] is always set to 1 to indicate this
100 // is a persistent diagnostic.
101 return makeLocation(&DiagLoc);
102}
103
104CXString CXLoadedDiagnostic::getSpelling() const {
Ted Kremeneke97ac9e2011-11-11 15:19:48 +0000105 return cxstring::createCXString(Spelling, false);
Ted Kremenek15322172011-11-10 08:43:12 +0000106}
107
108CXString CXLoadedDiagnostic::getDiagnosticOption(CXString *Disable) const {
109 if (DiagOption.empty())
110 return createCXString("");
111
112 // FIXME: possibly refactor with logic in CXStoredDiagnostic.
113 if (Disable)
114 *Disable = createCXString((Twine("-Wno-") + DiagOption).str());
115 return createCXString((Twine("-W") + DiagOption).str());
116}
117
118unsigned CXLoadedDiagnostic::getCategory() const {
119 return category;
120}
121
Ted Kremenek78d5d3b2012-04-12 00:03:31 +0000122CXString CXLoadedDiagnostic::getCategoryText() const {
123 return cxstring::createCXString(CategoryText);
124}
125
Ted Kremenek15322172011-11-10 08:43:12 +0000126unsigned CXLoadedDiagnostic::getNumRanges() const {
127 return Ranges.size();
128}
129
130CXSourceRange CXLoadedDiagnostic::getRange(unsigned Range) const {
131 assert(Range < Ranges.size());
132 return Ranges[Range];
133}
134
135unsigned CXLoadedDiagnostic::getNumFixIts() const {
136 return FixIts.size();
137}
138
139CXString CXLoadedDiagnostic::getFixIt(unsigned FixIt,
140 CXSourceRange *ReplacementRange) const {
141 assert(FixIt < FixIts.size());
142 if (ReplacementRange)
143 *ReplacementRange = FixIts[FixIt].first;
144 return FixIts[FixIt].second;
145}
146
147void CXLoadedDiagnostic::decodeLocation(CXSourceLocation location,
148 CXFile *file,
149 unsigned int *line,
150 unsigned int *column,
151 unsigned int *offset) {
152
153
154 // CXSourceLocation consists of the following fields:
155 //
156 // void *ptr_data[2];
157 // unsigned int_data;
158 //
159 // The lowest bit of ptr_data[0] is always set to 1 to indicate this
160 // is a persistent diagnostic.
161 //
162 // For now, do the unoptimized approach and store the data in a side
163 // data structure. We can optimize this case later.
164
165 uintptr_t V = (uintptr_t) location.ptr_data[0];
166 assert((V & 0x1) == 1);
167 V &= ~(uintptr_t)1;
168
169 const Location &Loc = *((Location*)V);
170
171 if (file)
172 *file = Loc.file;
173 if (line)
174 *line = Loc.line;
175 if (column)
176 *column = Loc.column;
177 if (offset)
178 *offset = Loc.offset;
179}
180
181//===----------------------------------------------------------------------===//
182// Deserialize diagnostics.
183//===----------------------------------------------------------------------===//
184
185enum { MaxSupportedVersion = 1 };
186typedef SmallVector<uint64_t, 64> RecordData;
187enum LoadResult { Failure = 1, Success = 0 };
188enum StreamResult { Read_EndOfStream,
189 Read_BlockBegin,
190 Read_Failure,
191 Read_Record,
192 Read_BlockEnd };
193
194namespace {
195class DiagLoader {
196 enum CXLoadDiag_Error *error;
197 CXString *errorString;
198
199 void reportBad(enum CXLoadDiag_Error code, llvm::StringRef err) {
200 if (error)
201 *error = code;
202 if (errorString)
203 *errorString = createCXString(err);
204 }
205
206 void reportInvalidFile(llvm::StringRef err) {
207 return reportBad(CXLoadDiag_InvalidFile, err);
208 }
209
210 LoadResult readMetaBlock(llvm::BitstreamCursor &Stream);
211
212 LoadResult readDiagnosticBlock(llvm::BitstreamCursor &Stream,
213 CXDiagnosticSetImpl &Diags,
214 CXLoadedDiagnosticSetImpl &TopDiags);
215
216 StreamResult readToNextRecordOrBlock(llvm::BitstreamCursor &Stream,
217 llvm::StringRef errorContext,
218 unsigned &BlockOrRecordID,
219 const bool atTopLevel = false);
220
221
222 LoadResult readString(CXLoadedDiagnosticSetImpl &TopDiags,
223 Strings &strings, llvm::StringRef errorContext,
224 RecordData &Record,
225 const char *BlobStart,
Ted Kremenek952538d2011-11-29 00:30:52 +0000226 unsigned BlobLen,
227 bool allowEmptyString = false);
Ted Kremenek15322172011-11-10 08:43:12 +0000228
229 LoadResult readString(CXLoadedDiagnosticSetImpl &TopDiags,
230 llvm::StringRef &RetStr,
231 llvm::StringRef errorContext,
232 RecordData &Record,
233 const char *BlobStart,
Ted Kremenek952538d2011-11-29 00:30:52 +0000234 unsigned BlobLen,
235 bool allowEmptyString = false);
Ted Kremenek15322172011-11-10 08:43:12 +0000236
237 LoadResult readRange(CXLoadedDiagnosticSetImpl &TopDiags,
238 RecordData &Record, unsigned RecStartIdx,
239 CXSourceRange &SR);
240
241 LoadResult readLocation(CXLoadedDiagnosticSetImpl &TopDiags,
242 RecordData &Record, unsigned &offset,
243 CXLoadedDiagnostic::Location &Loc);
244
245public:
246 DiagLoader(enum CXLoadDiag_Error *e, CXString *es)
247 : error(e), errorString(es) {
248 if (error)
249 *error = CXLoadDiag_None;
250 if (errorString)
251 *errorString = createCXString("");
252 }
Ted Kremeneke97ac9e2011-11-11 15:19:48 +0000253
Ted Kremenek15322172011-11-10 08:43:12 +0000254 CXDiagnosticSet load(const char *file);
255};
256}
257
258CXDiagnosticSet DiagLoader::load(const char *file) {
259 // Open the diagnostics file.
260 std::string ErrStr;
261 FileSystemOptions FO;
262 FileManager FileMgr(FO);
263
Dylan Noblesmith1e4c01b2012-02-13 12:32:21 +0000264 OwningPtr<llvm::MemoryBuffer> Buffer;
Ted Kremenek15322172011-11-10 08:43:12 +0000265 Buffer.reset(FileMgr.getBufferForFile(file));
266
267 if (!Buffer) {
268 reportBad(CXLoadDiag_CannotLoad, ErrStr);
269 return 0;
270 }
271
272 llvm::BitstreamReader StreamFile;
273 StreamFile.init((const unsigned char *)Buffer->getBufferStart(),
274 (const unsigned char *)Buffer->getBufferEnd());
275
276 llvm::BitstreamCursor Stream;
277 Stream.init(StreamFile);
278
279 // Sniff for the signature.
280 if (Stream.Read(8) != 'D' ||
281 Stream.Read(8) != 'I' ||
282 Stream.Read(8) != 'A' ||
283 Stream.Read(8) != 'G') {
284 reportBad(CXLoadDiag_InvalidFile,
285 "Bad header in diagnostics file");
286 return 0;
287 }
288
Dylan Noblesmith1e4c01b2012-02-13 12:32:21 +0000289 OwningPtr<CXLoadedDiagnosticSetImpl>
Ted Kremenek15322172011-11-10 08:43:12 +0000290 Diags(new CXLoadedDiagnosticSetImpl());
291
292 while (true) {
293 unsigned BlockID = 0;
294 StreamResult Res = readToNextRecordOrBlock(Stream, "Top-level",
295 BlockID, true);
296 switch (Res) {
297 case Read_EndOfStream:
298 return (CXDiagnosticSet) Diags.take();
299 case Read_Failure:
300 return 0;
301 case Read_Record:
302 llvm_unreachable("Top-level does not have records");
Ted Kremenek15322172011-11-10 08:43:12 +0000303 case Read_BlockEnd:
304 continue;
305 case Read_BlockBegin:
306 break;
307 }
308
309 switch (BlockID) {
310 case serialized_diags::BLOCK_META:
311 if (readMetaBlock(Stream))
312 return 0;
313 break;
314 case serialized_diags::BLOCK_DIAG:
315 if (readDiagnosticBlock(Stream, *Diags.get(), *Diags.get()))
316 return 0;
317 break;
318 default:
319 if (!Stream.SkipBlock()) {
320 reportInvalidFile("Malformed block at top-level of diagnostics file");
321 return 0;
322 }
323 break;
324 }
325 }
326}
327
328StreamResult DiagLoader::readToNextRecordOrBlock(llvm::BitstreamCursor &Stream,
329 llvm::StringRef errorContext,
330 unsigned &blockOrRecordID,
331 const bool atTopLevel) {
332
333 blockOrRecordID = 0;
334
335 while (!Stream.AtEndOfStream()) {
336 unsigned Code = Stream.ReadCode();
337
338 // Handle the top-level specially.
339 if (atTopLevel) {
340 if (Code == llvm::bitc::ENTER_SUBBLOCK) {
341 unsigned BlockID = Stream.ReadSubBlockID();
342 if (BlockID == llvm::bitc::BLOCKINFO_BLOCK_ID) {
343 if (Stream.ReadBlockInfoBlock()) {
344 reportInvalidFile("Malformed BlockInfoBlock in diagnostics file");
345 return Read_Failure;
346 }
347 continue;
348 }
349 blockOrRecordID = BlockID;
350 return Read_BlockBegin;
351 }
352 reportInvalidFile("Only blocks can appear at the top of a "
353 "diagnostic file");
354 return Read_Failure;
355 }
356
357 switch ((llvm::bitc::FixedAbbrevIDs)Code) {
358 case llvm::bitc::ENTER_SUBBLOCK:
359 blockOrRecordID = Stream.ReadSubBlockID();
360 return Read_BlockBegin;
361
362 case llvm::bitc::END_BLOCK:
363 if (Stream.ReadBlockEnd()) {
364 reportInvalidFile("Cannot read end of block");
365 return Read_Failure;
366 }
367 return Read_BlockEnd;
368
369 case llvm::bitc::DEFINE_ABBREV:
370 Stream.ReadAbbrevRecord();
371 continue;
372
373 case llvm::bitc::UNABBREV_RECORD:
374 reportInvalidFile("Diagnostics file should have no unabbreviated "
375 "records");
376 return Read_Failure;
377
378 default:
379 // We found a record.
380 blockOrRecordID = Code;
381 return Read_Record;
382 }
383 }
384
385 if (atTopLevel)
386 return Read_EndOfStream;
387
388 reportInvalidFile(Twine("Premature end of diagnostics file within ").str() +
389 errorContext.str());
390 return Read_Failure;
391}
392
393LoadResult DiagLoader::readMetaBlock(llvm::BitstreamCursor &Stream) {
394 if (Stream.EnterSubBlock(clang::serialized_diags::BLOCK_META)) {
395 reportInvalidFile("Malformed metadata block");
396 return Failure;
397 }
398
399 bool versionChecked = false;
400
401 while (true) {
402 unsigned blockOrCode = 0;
403 StreamResult Res = readToNextRecordOrBlock(Stream, "Metadata Block",
404 blockOrCode);
405
406 switch(Res) {
407 case Read_EndOfStream:
408 llvm_unreachable("EndOfStream handled by readToNextRecordOrBlock");
409 case Read_Failure:
410 return Failure;
411 case Read_Record:
412 break;
413 case Read_BlockBegin:
414 if (Stream.SkipBlock()) {
415 reportInvalidFile("Malformed metadata block");
416 return Failure;
417 }
418 case Read_BlockEnd:
419 if (!versionChecked) {
420 reportInvalidFile("Diagnostics file does not contain version"
421 " information");
422 return Failure;
423 }
424 return Success;
425 }
426
427 RecordData Record;
428 const char *Blob;
429 unsigned BlobLen;
430 unsigned recordID = Stream.ReadRecord(blockOrCode, Record, &Blob, &BlobLen);
431
432 if (recordID == serialized_diags::RECORD_VERSION) {
433 if (Record.size() < 1) {
434 reportInvalidFile("malformed VERSION identifier in diagnostics file");
435 return Failure;
436 }
437 if (Record[0] > MaxSupportedVersion) {
438 reportInvalidFile("diagnosics file is a newer version than the one "
439 "supported");
440 return Failure;
441 }
442 versionChecked = true;
443 }
444 }
445}
446
447LoadResult DiagLoader::readString(CXLoadedDiagnosticSetImpl &TopDiags,
448 llvm::StringRef &RetStr,
449 llvm::StringRef errorContext,
450 RecordData &Record,
451 const char *BlobStart,
Ted Kremenek952538d2011-11-29 00:30:52 +0000452 unsigned BlobLen,
453 bool allowEmptyString) {
Ted Kremenek15322172011-11-10 08:43:12 +0000454
455 // Basic buffer overflow check.
456 if (BlobLen > 65536) {
457 reportInvalidFile(std::string("Out-of-bounds string in ") +
458 std::string(errorContext));
459 return Failure;
460 }
Ted Kremenek952538d2011-11-29 00:30:52 +0000461
462 if (allowEmptyString && Record.size() >= 1 && BlobLen == 0) {
463 RetStr = "";
464 return Success;
465 }
Ted Kremenek15322172011-11-10 08:43:12 +0000466
467 if (Record.size() < 1 || BlobLen == 0) {
468 reportInvalidFile(std::string("Corrupted ") + std::string(errorContext)
469 + std::string(" entry"));
470 return Failure;
471 }
472
473 RetStr = TopDiags.makeString(BlobStart, BlobLen);
474 return Success;
475}
476
477LoadResult DiagLoader::readString(CXLoadedDiagnosticSetImpl &TopDiags,
478 Strings &strings,
479 llvm::StringRef errorContext,
480 RecordData &Record,
481 const char *BlobStart,
Ted Kremenek952538d2011-11-29 00:30:52 +0000482 unsigned BlobLen,
483 bool allowEmptyString) {
Ted Kremenek15322172011-11-10 08:43:12 +0000484 llvm::StringRef RetStr;
Ted Kremenek952538d2011-11-29 00:30:52 +0000485 if (readString(TopDiags, RetStr, errorContext, Record, BlobStart, BlobLen,
486 allowEmptyString))
Ted Kremenek15322172011-11-10 08:43:12 +0000487 return Failure;
488 strings[Record[0]] = RetStr;
489 return Success;
490}
491
492LoadResult DiagLoader::readLocation(CXLoadedDiagnosticSetImpl &TopDiags,
493 RecordData &Record, unsigned &offset,
494 CXLoadedDiagnostic::Location &Loc) {
495 if (Record.size() < offset + 3) {
496 reportInvalidFile("Corrupted source location");
497 return Failure;
498 }
499
500 unsigned fileID = Record[offset++];
501 if (fileID == 0) {
502 // Sentinel value.
503 Loc.file = 0;
504 Loc.line = 0;
505 Loc.column = 0;
506 Loc.offset = 0;
507 return Success;
508 }
509
510 const FileEntry *FE = TopDiags.Files[fileID];
511 if (!FE) {
512 reportInvalidFile("Corrupted file entry in source location");
513 return Failure;
514 }
515 Loc.file = (void*) FE;
516 Loc.line = Record[offset++];
517 Loc.column = Record[offset++];
518 Loc.offset = Record[offset++];
519 return Success;
520}
521
522LoadResult DiagLoader::readRange(CXLoadedDiagnosticSetImpl &TopDiags,
523 RecordData &Record,
524 unsigned int RecStartIdx,
525 CXSourceRange &SR) {
526 CXLoadedDiagnostic::Location *Start, *End;
527 Start = TopDiags.Alloc.Allocate<CXLoadedDiagnostic::Location>();
528 End = TopDiags.Alloc.Allocate<CXLoadedDiagnostic::Location>();
529
530 if (readLocation(TopDiags, Record, RecStartIdx, *Start))
531 return Failure;
532 if (readLocation(TopDiags, Record, RecStartIdx, *End))
533 return Failure;
534
535 CXSourceLocation startLoc = makeLocation(Start);
536 CXSourceLocation endLoc = makeLocation(End);
537 SR = clang_getRange(startLoc, endLoc);
538 return Success;
539}
540
541LoadResult DiagLoader::readDiagnosticBlock(llvm::BitstreamCursor &Stream,
542 CXDiagnosticSetImpl &Diags,
543 CXLoadedDiagnosticSetImpl &TopDiags){
544
545 if (Stream.EnterSubBlock(clang::serialized_diags::BLOCK_DIAG)) {
546 reportInvalidFile("malformed diagnostic block");
547 return Failure;
548 }
549
Dylan Noblesmith1e4c01b2012-02-13 12:32:21 +0000550 OwningPtr<CXLoadedDiagnostic> D(new CXLoadedDiagnostic());
Ted Kremenek15322172011-11-10 08:43:12 +0000551 RecordData Record;
552
553 while (true) {
554 unsigned blockOrCode = 0;
555 StreamResult Res = readToNextRecordOrBlock(Stream, "Diagnostic Block",
556 blockOrCode);
557 switch (Res) {
558 case Read_EndOfStream:
559 llvm_unreachable("EndOfStream handled in readToNextRecordOrBlock");
Ted Kremenek15322172011-11-10 08:43:12 +0000560 case Read_Failure:
561 return Failure;
562 case Read_BlockBegin: {
563 // The only blocks we care about are subdiagnostics.
564 if (blockOrCode != serialized_diags::BLOCK_DIAG) {
565 if (!Stream.SkipBlock()) {
566 reportInvalidFile("Invalid subblock in Diagnostics block");
567 return Failure;
568 }
569 } else if (readDiagnosticBlock(Stream, D->getChildDiagnostics(),
570 TopDiags)) {
571 return Failure;
572 }
573
574 continue;
575 }
576 case Read_BlockEnd:
577 Diags.appendDiagnostic(D.take());
578 return Success;
579 case Read_Record:
580 break;
581 }
582
583 // Read the record.
584 Record.clear();
585 const char *BlobStart = 0;
586 unsigned BlobLen = 0;
587 unsigned recID = Stream.ReadRecord(blockOrCode, Record,
588 BlobStart, BlobLen);
589
590 if (recID < serialized_diags::RECORD_FIRST ||
591 recID > serialized_diags::RECORD_LAST)
592 continue;
593
594 switch ((serialized_diags::RecordIDs)recID) {
595 case serialized_diags::RECORD_VERSION:
596 continue;
597 case serialized_diags::RECORD_CATEGORY:
598 if (readString(TopDiags, TopDiags.Categories, "category", Record,
Ted Kremenek13eee192011-12-07 02:08:00 +0000599 BlobStart, BlobLen,
600 /* allowEmptyString */ true))
Ted Kremenek15322172011-11-10 08:43:12 +0000601 return Failure;
602 continue;
603
604 case serialized_diags::RECORD_DIAG_FLAG:
605 if (readString(TopDiags, TopDiags.WarningFlags, "warning flag", Record,
606 BlobStart, BlobLen))
607 return Failure;
608 continue;
609
610 case serialized_diags::RECORD_FILENAME: {
611 if (readString(TopDiags, TopDiags.FileNames, "filename", Record,
612 BlobStart, BlobLen))
613 return Failure;
614
615 if (Record.size() < 3) {
616 reportInvalidFile("Invalid file entry");
617 return Failure;
618 }
619
620 const FileEntry *FE =
621 TopDiags.FakeFiles.getVirtualFile(TopDiags.FileNames[Record[0]],
622 /* size */ Record[1],
623 /* time */ Record[2]);
624
625 TopDiags.Files[Record[0]] = FE;
626 continue;
627 }
628
629 case serialized_diags::RECORD_SOURCE_RANGE: {
630 CXSourceRange SR;
631 if (readRange(TopDiags, Record, 0, SR))
632 return Failure;
633 D->Ranges.push_back(SR);
634 continue;
635 }
636
637 case serialized_diags::RECORD_FIXIT: {
638 CXSourceRange SR;
639 if (readRange(TopDiags, Record, 0, SR))
640 return Failure;
641 llvm::StringRef RetStr;
Ted Kremenek952538d2011-11-29 00:30:52 +0000642 if (readString(TopDiags, RetStr, "FIXIT", Record, BlobStart, BlobLen,
643 /* allowEmptyString */ true))
Ted Kremenek15322172011-11-10 08:43:12 +0000644 return Failure;
Ted Kremeneke97ac9e2011-11-11 15:19:48 +0000645 D->FixIts.push_back(std::make_pair(SR, createCXString(RetStr, false)));
646 continue;
Ted Kremenek15322172011-11-10 08:43:12 +0000647 }
648
649 case serialized_diags::RECORD_DIAG: {
650 D->severity = Record[0];
651 unsigned offset = 1;
652 if (readLocation(TopDiags, Record, offset, D->DiagLoc))
653 return Failure;
654 D->category = Record[offset++];
655 unsigned diagFlag = Record[offset++];
656 D->DiagOption = diagFlag ? TopDiags.WarningFlags[diagFlag] : "";
Ted Kremenek78d5d3b2012-04-12 00:03:31 +0000657 D->CategoryText = D->category ? TopDiags.Categories[D->category] : "";
Ted Kremenek15322172011-11-10 08:43:12 +0000658 D->Spelling = TopDiags.makeString(BlobStart, BlobLen);
659 continue;
660 }
661 }
662 }
663}
664
665extern "C" {
666CXDiagnosticSet clang_loadDiagnostics(const char *file,
667 enum CXLoadDiag_Error *error,
668 CXString *errorString) {
669 DiagLoader L(error, errorString);
670 return L.load(file);
671}
672} // end extern 'C'.