1176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//===--- SerializedDiagnosticReader.cpp - Reads diagnostics ---------------===//
2176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//
3176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//                     The LLVM Compiler Infrastructure
4176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//
5176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines// This file is distributed under the University of Illinois Open Source
6176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines// License. See LICENSE.TXT for details.
7176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//
8176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines//===----------------------------------------------------------------------===//
9176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines
10176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines#include "clang/Frontend/SerializedDiagnosticReader.h"
11176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines#include "clang/Basic/FileManager.h"
120e2c34f92f00628d48968dfea096d36381f494cbStephen Hines#include "clang/Frontend/SerializedDiagnostics.h"
13176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines#include "llvm/Support/ManagedStatic.h"
14176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines#include "llvm/Support/MemoryBuffer.h"
15176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines
16176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hinesusing namespace clang;
17176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hinesusing namespace clang::serialized_diags;
18176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines
19176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hinesstd::error_code SerializedDiagnosticReader::readDiagnostics(StringRef File) {
20176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  // Open the diagnostics file.
21176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  FileSystemOptions FO;
22176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  FileManager FileMgr(FO);
23176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines
24176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  auto Buffer = FileMgr.getBufferForFile(File);
25176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  if (!Buffer)
26176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    return SDError::CouldNotLoad;
27176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines
28176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  llvm::BitstreamReader StreamFile;
29176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  StreamFile.init((const unsigned char *)(*Buffer)->getBufferStart(),
30176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines                  (const unsigned char *)(*Buffer)->getBufferEnd());
31176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines
32176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  llvm::BitstreamCursor Stream(StreamFile);
33176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines
34176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  // Sniff for the signature.
35176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  if (Stream.Read(8) != 'D' ||
36176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      Stream.Read(8) != 'I' ||
37176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      Stream.Read(8) != 'A' ||
38176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      Stream.Read(8) != 'G')
39176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    return SDError::InvalidSignature;
40176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines
41176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  // Read the top level blocks.
42176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  while (!Stream.AtEndOfStream()) {
43176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    if (Stream.ReadCode() != llvm::bitc::ENTER_SUBBLOCK)
44176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      return SDError::InvalidDiagnostics;
45176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines
46176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    std::error_code EC;
47176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    switch (Stream.ReadSubBlockID()) {
48176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    case llvm::bitc::BLOCKINFO_BLOCK_ID:
49176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      if (Stream.ReadBlockInfoBlock())
50176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines        return SDError::MalformedBlockInfoBlock;
51176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      continue;
52176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    case BLOCK_META:
53176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      if ((EC = readMetaBlock(Stream)))
54176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines        return EC;
55176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      continue;
56176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    case BLOCK_DIAG:
57176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      if ((EC = readDiagnosticBlock(Stream)))
58176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines        return EC;
59176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      continue;
60176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    default:
61176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      if (!Stream.SkipBlock())
62176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines        return SDError::MalformedTopLevelBlock;
63176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      continue;
64176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    }
65176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  }
66176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  return std::error_code();
67176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines}
68176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines
69176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hinesenum class SerializedDiagnosticReader::Cursor {
70176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  Record = 1,
71176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  BlockEnd,
72176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  BlockBegin
73176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines};
74176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines
75176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hinesllvm::ErrorOr<SerializedDiagnosticReader::Cursor>
76176edba5311f6eff0cad2631449885ddf4fbc9eaStephen HinesSerializedDiagnosticReader::skipUntilRecordOrBlock(
77176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    llvm::BitstreamCursor &Stream, unsigned &BlockOrRecordID) {
78176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  BlockOrRecordID = 0;
79176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines
80176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  while (!Stream.AtEndOfStream()) {
81176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    unsigned Code = Stream.ReadCode();
82176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines
83176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    switch ((llvm::bitc::FixedAbbrevIDs)Code) {
84176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    case llvm::bitc::ENTER_SUBBLOCK:
85176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      BlockOrRecordID = Stream.ReadSubBlockID();
86176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      return Cursor::BlockBegin;
87176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines
88176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    case llvm::bitc::END_BLOCK:
89176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      if (Stream.ReadBlockEnd())
90176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines        return SDError::InvalidDiagnostics;
91176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      return Cursor::BlockEnd;
92176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines
93176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    case llvm::bitc::DEFINE_ABBREV:
94176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      Stream.ReadAbbrevRecord();
95176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      continue;
96176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines
97176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    case llvm::bitc::UNABBREV_RECORD:
98176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      return SDError::UnsupportedConstruct;
99176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines
100176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    default:
101176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      // We found a record.
102176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      BlockOrRecordID = Code;
103176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      return Cursor::Record;
104176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    }
105176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  }
106176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines
107176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  return SDError::InvalidDiagnostics;
108176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines}
109176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines
110176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hinesstd::error_code
111176edba5311f6eff0cad2631449885ddf4fbc9eaStephen HinesSerializedDiagnosticReader::readMetaBlock(llvm::BitstreamCursor &Stream) {
112176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  if (Stream.EnterSubBlock(clang::serialized_diags::BLOCK_META))
113176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    return SDError::MalformedMetadataBlock;
114176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines
115176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  bool VersionChecked = false;
116176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines
117176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  while (true) {
118176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    unsigned BlockOrCode = 0;
119176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    llvm::ErrorOr<Cursor> Res = skipUntilRecordOrBlock(Stream, BlockOrCode);
120176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    if (!Res)
121176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      Res.getError();
122176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines
123176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    switch (Res.get()) {
124176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    case Cursor::Record:
125176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      break;
126176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    case Cursor::BlockBegin:
127176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      if (Stream.SkipBlock())
128176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines        return SDError::MalformedMetadataBlock;
129176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    case Cursor::BlockEnd:
130176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      if (!VersionChecked)
131176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines        return SDError::MissingVersion;
132176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      return std::error_code();
133176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    }
134176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines
135176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    SmallVector<uint64_t, 1> Record;
136176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    unsigned RecordID = Stream.readRecord(BlockOrCode, Record);
137176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines
138176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    if (RecordID == RECORD_VERSION) {
139176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      if (Record.size() < 1)
140176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines        return SDError::MissingVersion;
141176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      if (Record[0] > VersionNumber)
142176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines        return SDError::VersionMismatch;
143176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      VersionChecked = true;
144176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    }
145176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  }
146176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines}
147176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines
148176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hinesstd::error_code
149176edba5311f6eff0cad2631449885ddf4fbc9eaStephen HinesSerializedDiagnosticReader::readDiagnosticBlock(llvm::BitstreamCursor &Stream) {
150176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  if (Stream.EnterSubBlock(clang::serialized_diags::BLOCK_DIAG))
151176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    return SDError::MalformedDiagnosticBlock;
152176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines
153176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  std::error_code EC;
154176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  if ((EC = visitStartOfDiagnostic()))
155176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    return EC;
156176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines
157176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  SmallVector<uint64_t, 16> Record;
158176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  while (true) {
159176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    unsigned BlockOrCode = 0;
160176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    llvm::ErrorOr<Cursor> Res = skipUntilRecordOrBlock(Stream, BlockOrCode);
161176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    if (!Res)
162176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      Res.getError();
163176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines
164176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    switch (Res.get()) {
165176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    case Cursor::BlockBegin:
166176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      // The only blocks we care about are subdiagnostics.
167176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      if (BlockOrCode == serialized_diags::BLOCK_DIAG) {
168176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines        if ((EC = readDiagnosticBlock(Stream)))
169176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines          return EC;
170176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      } else if (!Stream.SkipBlock())
171176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines        return SDError::MalformedSubBlock;
172176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      continue;
173176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    case Cursor::BlockEnd:
174176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      if ((EC = visitEndOfDiagnostic()))
175176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines        return EC;
176176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      return std::error_code();
177176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    case Cursor::Record:
178176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      break;
179176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    }
180176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines
181176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    // Read the record.
182176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    Record.clear();
183176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    StringRef Blob;
184176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    unsigned RecID = Stream.readRecord(BlockOrCode, Record, &Blob);
185176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines
186176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    if (RecID < serialized_diags::RECORD_FIRST ||
187176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines        RecID > serialized_diags::RECORD_LAST)
188176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      continue;
189176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines
190176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    switch ((RecordIDs)RecID) {
191176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    case RECORD_CATEGORY:
192176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      // A category has ID and name size.
193176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      if (Record.size() != 2)
194176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines        return SDError::MalformedDiagnosticRecord;
195176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      if ((EC = visitCategoryRecord(Record[0], Blob)))
196176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines        return EC;
197176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      continue;
198176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    case RECORD_DIAG:
199176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      // A diagnostic has severity, location (4), category, flag, and message
200176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      // size.
201176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      if (Record.size() != 8)
202176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines        return SDError::MalformedDiagnosticRecord;
203176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      if ((EC = visitDiagnosticRecord(
204176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines               Record[0], Location(Record[1], Record[2], Record[3], Record[4]),
205176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines               Record[5], Record[6], Blob)))
206176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines        return EC;
207176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      continue;
208176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    case RECORD_DIAG_FLAG:
209176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      // A diagnostic flag has ID and name size.
210176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      if (Record.size() != 2)
211176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines        return SDError::MalformedDiagnosticRecord;
212176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      if ((EC = visitDiagFlagRecord(Record[0], Blob)))
213176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines        return EC;
214176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      continue;
215176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    case RECORD_FILENAME:
216176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      // A filename has ID, size, timestamp, and name size. The size and
217176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      // timestamp are legacy fields that are always zero these days.
218176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      if (Record.size() != 4)
219176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines        return SDError::MalformedDiagnosticRecord;
220176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      if ((EC = visitFilenameRecord(Record[0], Record[1], Record[2], Blob)))
221176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines        return EC;
222176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      continue;
223176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    case RECORD_FIXIT:
224176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      // A fixit has two locations (4 each) and message size.
225176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      if (Record.size() != 9)
226176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines        return SDError::MalformedDiagnosticRecord;
227176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      if ((EC = visitFixitRecord(
228176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines               Location(Record[0], Record[1], Record[2], Record[3]),
229176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines               Location(Record[4], Record[5], Record[6], Record[7]), Blob)))
230176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines        return EC;
231176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      continue;
232176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    case RECORD_SOURCE_RANGE:
233176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      // A source range is two locations (4 each).
234176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      if (Record.size() != 8)
235176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines        return SDError::MalformedDiagnosticRecord;
236176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      if ((EC = visitSourceRangeRecord(
237176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines               Location(Record[0], Record[1], Record[2], Record[3]),
238176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines               Location(Record[4], Record[5], Record[6], Record[7]))))
239176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines        return EC;
240176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      continue;
241176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    case RECORD_VERSION:
242176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      // A version is just a number.
243176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      if (Record.size() != 1)
244176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines        return SDError::MalformedDiagnosticRecord;
245176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      if ((EC = visitVersionRecord(Record[0])))
246176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines        return EC;
247176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      continue;
248176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    }
249176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  }
250176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines}
251176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines
252176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hinesnamespace {
253176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hinesclass SDErrorCategoryType final : public std::error_category {
254176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  const char *name() const LLVM_NOEXCEPT override {
255176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    return "clang.serialized_diags";
256176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  }
257176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  std::string message(int IE) const override {
258176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    SDError E = static_cast<SDError>(IE);
259176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    switch (E) {
260176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    case SDError::CouldNotLoad:
261176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      return "Failed to open diagnostics file";
262176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    case SDError::InvalidSignature:
263176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      return "Invalid diagnostics signature";
264176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    case SDError::InvalidDiagnostics:
265176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      return "Parse error reading diagnostics";
266176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    case SDError::MalformedTopLevelBlock:
267176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      return "Malformed block at top-level of diagnostics";
268176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    case SDError::MalformedSubBlock:
269176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      return "Malformed sub-block in a diagnostic";
270176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    case SDError::MalformedBlockInfoBlock:
271176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      return "Malformed BlockInfo block";
272176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    case SDError::MalformedMetadataBlock:
273176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      return "Malformed Metadata block";
274176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    case SDError::MalformedDiagnosticBlock:
275176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      return "Malformed Diagnostic block";
276176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    case SDError::MalformedDiagnosticRecord:
277176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      return "Malformed Diagnostic record";
278176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    case SDError::MissingVersion:
279176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      return "No version provided in diagnostics";
280176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    case SDError::VersionMismatch:
281176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      return "Unsupported diagnostics version";
282176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    case SDError::UnsupportedConstruct:
283176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      return "Bitcode constructs that are not supported in diagnostics appear";
284176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    case SDError::HandlerFailed:
285176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      return "Generic error occurred while handling a record";
286176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    }
287176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    llvm_unreachable("Unknown error type!");
288176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  }
289176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines};
290176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines}
291176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines
292176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hinesstatic llvm::ManagedStatic<SDErrorCategoryType> ErrorCategory;
293176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hinesconst std::error_category &clang::serialized_diags::SDErrorCategory() {
294176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  return *ErrorCategory;
295176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines}
296