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