SerializedDiagnosticReader.cpp 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294
  1. //===--- SerializedDiagnosticReader.cpp - Reads diagnostics ---------------===//
  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. #include "clang/Frontend/SerializedDiagnosticReader.h"
  10. #include "clang/Basic/FileManager.h"
  11. #include "clang/Frontend/SerializedDiagnostics.h"
  12. #include "llvm/Support/ManagedStatic.h"
  13. using namespace clang;
  14. using namespace clang::serialized_diags;
  15. std::error_code SerializedDiagnosticReader::readDiagnostics(StringRef File) {
  16. // Open the diagnostics file.
  17. FileSystemOptions FO;
  18. FileManager FileMgr(FO);
  19. auto Buffer = FileMgr.getBufferForFile(File);
  20. if (!Buffer)
  21. return SDError::CouldNotLoad;
  22. llvm::BitstreamReader StreamFile;
  23. StreamFile.init((const unsigned char *)(*Buffer)->getBufferStart(),
  24. (const unsigned char *)(*Buffer)->getBufferEnd());
  25. llvm::BitstreamCursor Stream(StreamFile);
  26. // Sniff for the signature.
  27. if (Stream.Read(8) != 'D' ||
  28. Stream.Read(8) != 'I' ||
  29. Stream.Read(8) != 'A' ||
  30. Stream.Read(8) != 'G')
  31. return SDError::InvalidSignature;
  32. // Read the top level blocks.
  33. while (!Stream.AtEndOfStream()) {
  34. if (Stream.ReadCode() != llvm::bitc::ENTER_SUBBLOCK)
  35. return SDError::InvalidDiagnostics;
  36. std::error_code EC;
  37. switch (Stream.ReadSubBlockID()) {
  38. case llvm::bitc::BLOCKINFO_BLOCK_ID:
  39. if (Stream.ReadBlockInfoBlock())
  40. return SDError::MalformedBlockInfoBlock;
  41. continue;
  42. case BLOCK_META:
  43. if ((EC = readMetaBlock(Stream)))
  44. return EC;
  45. continue;
  46. case BLOCK_DIAG:
  47. if ((EC = readDiagnosticBlock(Stream)))
  48. return EC;
  49. continue;
  50. default:
  51. if (!Stream.SkipBlock())
  52. return SDError::MalformedTopLevelBlock;
  53. continue;
  54. }
  55. }
  56. return std::error_code();
  57. }
  58. enum class SerializedDiagnosticReader::Cursor {
  59. Record = 1,
  60. BlockEnd,
  61. BlockBegin
  62. };
  63. llvm::ErrorOr<SerializedDiagnosticReader::Cursor>
  64. SerializedDiagnosticReader::skipUntilRecordOrBlock(
  65. llvm::BitstreamCursor &Stream, unsigned &BlockOrRecordID) {
  66. BlockOrRecordID = 0;
  67. while (!Stream.AtEndOfStream()) {
  68. unsigned Code = Stream.ReadCode();
  69. switch ((llvm::bitc::FixedAbbrevIDs)Code) {
  70. case llvm::bitc::ENTER_SUBBLOCK:
  71. BlockOrRecordID = Stream.ReadSubBlockID();
  72. return Cursor::BlockBegin;
  73. case llvm::bitc::END_BLOCK:
  74. if (Stream.ReadBlockEnd())
  75. return SDError::InvalidDiagnostics;
  76. return Cursor::BlockEnd;
  77. case llvm::bitc::DEFINE_ABBREV:
  78. Stream.ReadAbbrevRecord();
  79. continue;
  80. case llvm::bitc::UNABBREV_RECORD:
  81. return SDError::UnsupportedConstruct;
  82. default:
  83. // We found a record.
  84. BlockOrRecordID = Code;
  85. return Cursor::Record;
  86. }
  87. }
  88. return SDError::InvalidDiagnostics;
  89. }
  90. std::error_code
  91. SerializedDiagnosticReader::readMetaBlock(llvm::BitstreamCursor &Stream) {
  92. if (Stream.EnterSubBlock(clang::serialized_diags::BLOCK_META))
  93. return SDError::MalformedMetadataBlock;
  94. bool VersionChecked = false;
  95. while (true) {
  96. unsigned BlockOrCode = 0;
  97. llvm::ErrorOr<Cursor> Res = skipUntilRecordOrBlock(Stream, BlockOrCode);
  98. if (!Res)
  99. Res.getError();
  100. switch (Res.get()) {
  101. case Cursor::Record:
  102. break;
  103. case Cursor::BlockBegin:
  104. if (Stream.SkipBlock())
  105. return SDError::MalformedMetadataBlock;
  106. case Cursor::BlockEnd:
  107. if (!VersionChecked)
  108. return SDError::MissingVersion;
  109. return std::error_code();
  110. }
  111. SmallVector<uint64_t, 1> Record;
  112. unsigned RecordID = Stream.readRecord(BlockOrCode, Record);
  113. if (RecordID == RECORD_VERSION) {
  114. if (Record.size() < 1)
  115. return SDError::MissingVersion;
  116. if (Record[0] > VersionNumber)
  117. return SDError::VersionMismatch;
  118. VersionChecked = true;
  119. }
  120. }
  121. }
  122. std::error_code
  123. SerializedDiagnosticReader::readDiagnosticBlock(llvm::BitstreamCursor &Stream) {
  124. if (Stream.EnterSubBlock(clang::serialized_diags::BLOCK_DIAG))
  125. return SDError::MalformedDiagnosticBlock;
  126. std::error_code EC;
  127. if ((EC = visitStartOfDiagnostic()))
  128. return EC;
  129. SmallVector<uint64_t, 16> Record;
  130. while (true) {
  131. unsigned BlockOrCode = 0;
  132. llvm::ErrorOr<Cursor> Res = skipUntilRecordOrBlock(Stream, BlockOrCode);
  133. if (!Res)
  134. Res.getError();
  135. switch (Res.get()) {
  136. case Cursor::BlockBegin:
  137. // The only blocks we care about are subdiagnostics.
  138. if (BlockOrCode == serialized_diags::BLOCK_DIAG) {
  139. if ((EC = readDiagnosticBlock(Stream)))
  140. return EC;
  141. } else if (!Stream.SkipBlock())
  142. return SDError::MalformedSubBlock;
  143. continue;
  144. case Cursor::BlockEnd:
  145. if ((EC = visitEndOfDiagnostic()))
  146. return EC;
  147. return std::error_code();
  148. case Cursor::Record:
  149. break;
  150. }
  151. // Read the record.
  152. Record.clear();
  153. StringRef Blob;
  154. unsigned RecID = Stream.readRecord(BlockOrCode, Record, &Blob);
  155. if (RecID < serialized_diags::RECORD_FIRST ||
  156. RecID > serialized_diags::RECORD_LAST)
  157. continue;
  158. switch ((RecordIDs)RecID) {
  159. case RECORD_CATEGORY:
  160. // A category has ID and name size.
  161. if (Record.size() != 2)
  162. return SDError::MalformedDiagnosticRecord;
  163. if ((EC = visitCategoryRecord(Record[0], Blob)))
  164. return EC;
  165. continue;
  166. case RECORD_DIAG:
  167. // A diagnostic has severity, location (4), category, flag, and message
  168. // size.
  169. if (Record.size() != 8)
  170. return SDError::MalformedDiagnosticRecord;
  171. if ((EC = visitDiagnosticRecord(
  172. Record[0], Location(Record[1], Record[2], Record[3], Record[4]),
  173. Record[5], Record[6], Blob)))
  174. return EC;
  175. continue;
  176. case RECORD_DIAG_FLAG:
  177. // A diagnostic flag has ID and name size.
  178. if (Record.size() != 2)
  179. return SDError::MalformedDiagnosticRecord;
  180. if ((EC = visitDiagFlagRecord(Record[0], Blob)))
  181. return EC;
  182. continue;
  183. case RECORD_FILENAME:
  184. // A filename has ID, size, timestamp, and name size. The size and
  185. // timestamp are legacy fields that are always zero these days.
  186. if (Record.size() != 4)
  187. return SDError::MalformedDiagnosticRecord;
  188. if ((EC = visitFilenameRecord(Record[0], Record[1], Record[2], Blob)))
  189. return EC;
  190. continue;
  191. case RECORD_FIXIT:
  192. // A fixit has two locations (4 each) and message size.
  193. if (Record.size() != 9)
  194. return SDError::MalformedDiagnosticRecord;
  195. if ((EC = visitFixitRecord(
  196. Location(Record[0], Record[1], Record[2], Record[3]),
  197. Location(Record[4], Record[5], Record[6], Record[7]), Blob)))
  198. return EC;
  199. continue;
  200. case RECORD_SOURCE_RANGE:
  201. // A source range is two locations (4 each).
  202. if (Record.size() != 8)
  203. return SDError::MalformedDiagnosticRecord;
  204. if ((EC = visitSourceRangeRecord(
  205. Location(Record[0], Record[1], Record[2], Record[3]),
  206. Location(Record[4], Record[5], Record[6], Record[7]))))
  207. return EC;
  208. continue;
  209. case RECORD_VERSION:
  210. // A version is just a number.
  211. if (Record.size() != 1)
  212. return SDError::MalformedDiagnosticRecord;
  213. if ((EC = visitVersionRecord(Record[0])))
  214. return EC;
  215. continue;
  216. }
  217. }
  218. }
  219. namespace {
  220. class SDErrorCategoryType final : public std::error_category {
  221. const char *name() const noexcept override {
  222. return "clang.serialized_diags";
  223. }
  224. std::string message(int IE) const override {
  225. SDError E = static_cast<SDError>(IE);
  226. switch (E) {
  227. case SDError::CouldNotLoad:
  228. return "Failed to open diagnostics file";
  229. case SDError::InvalidSignature:
  230. return "Invalid diagnostics signature";
  231. case SDError::InvalidDiagnostics:
  232. return "Parse error reading diagnostics";
  233. case SDError::MalformedTopLevelBlock:
  234. return "Malformed block at top-level of diagnostics";
  235. case SDError::MalformedSubBlock:
  236. return "Malformed sub-block in a diagnostic";
  237. case SDError::MalformedBlockInfoBlock:
  238. return "Malformed BlockInfo block";
  239. case SDError::MalformedMetadataBlock:
  240. return "Malformed Metadata block";
  241. case SDError::MalformedDiagnosticBlock:
  242. return "Malformed Diagnostic block";
  243. case SDError::MalformedDiagnosticRecord:
  244. return "Malformed Diagnostic record";
  245. case SDError::MissingVersion:
  246. return "No version provided in diagnostics";
  247. case SDError::VersionMismatch:
  248. return "Unsupported diagnostics version";
  249. case SDError::UnsupportedConstruct:
  250. return "Bitcode constructs that are not supported in diagnostics appear";
  251. case SDError::HandlerFailed:
  252. return "Generic error occurred while handling a record";
  253. }
  254. llvm_unreachable("Unknown error type!");
  255. }
  256. };
  257. }
  258. static llvm::ManagedStatic<SDErrorCategoryType> ErrorCategory;
  259. const std::error_category &clang::serialized_diags::SDErrorCategory() {
  260. return *ErrorCategory;
  261. }