SerializedDiagnosticReader.cpp 9.0 KB

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