clang API Documentation

SerializedDiagnosticReader.cpp
Go to the documentation of this file.
00001 //===--- SerializedDiagnosticReader.cpp - Reads diagnostics ---------------===//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 
00010 #include "clang/Frontend/SerializedDiagnosticReader.h"
00011 #include "clang/Frontend/SerializedDiagnostics.h"
00012 #include "clang/Basic/FileManager.h"
00013 #include "llvm/Support/ManagedStatic.h"
00014 #include "llvm/Support/MemoryBuffer.h"
00015 
00016 using namespace clang;
00017 using namespace clang::serialized_diags;
00018 
00019 std::error_code SerializedDiagnosticReader::readDiagnostics(StringRef File) {
00020   // Open the diagnostics file.
00021   FileSystemOptions FO;
00022   FileManager FileMgr(FO);
00023 
00024   auto Buffer = FileMgr.getBufferForFile(File);
00025   if (!Buffer)
00026     return SDError::CouldNotLoad;
00027 
00028   llvm::BitstreamReader StreamFile;
00029   StreamFile.init((const unsigned char *)(*Buffer)->getBufferStart(),
00030                   (const unsigned char *)(*Buffer)->getBufferEnd());
00031 
00032   llvm::BitstreamCursor Stream(StreamFile);
00033 
00034   // Sniff for the signature.
00035   if (Stream.Read(8) != 'D' ||
00036       Stream.Read(8) != 'I' ||
00037       Stream.Read(8) != 'A' ||
00038       Stream.Read(8) != 'G')
00039     return SDError::InvalidSignature;
00040 
00041   // Read the top level blocks.
00042   while (!Stream.AtEndOfStream()) {
00043     if (Stream.ReadCode() != llvm::bitc::ENTER_SUBBLOCK)
00044       return SDError::InvalidDiagnostics;
00045 
00046     std::error_code EC;
00047     switch (Stream.ReadSubBlockID()) {
00048     case llvm::bitc::BLOCKINFO_BLOCK_ID:
00049       if (Stream.ReadBlockInfoBlock())
00050         return SDError::MalformedBlockInfoBlock;
00051       continue;
00052     case BLOCK_META:
00053       if ((EC = readMetaBlock(Stream)))
00054         return EC;
00055       continue;
00056     case BLOCK_DIAG:
00057       if ((EC = readDiagnosticBlock(Stream)))
00058         return EC;
00059       continue;
00060     default:
00061       if (!Stream.SkipBlock())
00062         return SDError::MalformedTopLevelBlock;
00063       continue;
00064     }
00065   }
00066   return std::error_code();
00067 }
00068 
00069 enum class SerializedDiagnosticReader::Cursor {
00070   Record = 1,
00071   BlockEnd,
00072   BlockBegin
00073 };
00074 
00075 llvm::ErrorOr<SerializedDiagnosticReader::Cursor>
00076 SerializedDiagnosticReader::skipUntilRecordOrBlock(
00077     llvm::BitstreamCursor &Stream, unsigned &BlockOrRecordID) {
00078   BlockOrRecordID = 0;
00079 
00080   while (!Stream.AtEndOfStream()) {
00081     unsigned Code = Stream.ReadCode();
00082 
00083     switch ((llvm::bitc::FixedAbbrevIDs)Code) {
00084     case llvm::bitc::ENTER_SUBBLOCK:
00085       BlockOrRecordID = Stream.ReadSubBlockID();
00086       return Cursor::BlockBegin;
00087 
00088     case llvm::bitc::END_BLOCK:
00089       if (Stream.ReadBlockEnd())
00090         return SDError::InvalidDiagnostics;
00091       return Cursor::BlockEnd;
00092 
00093     case llvm::bitc::DEFINE_ABBREV:
00094       Stream.ReadAbbrevRecord();
00095       continue;
00096 
00097     case llvm::bitc::UNABBREV_RECORD:
00098       return SDError::UnsupportedConstruct;
00099 
00100     default:
00101       // We found a record.
00102       BlockOrRecordID = Code;
00103       return Cursor::Record;
00104     }
00105   }
00106 
00107   return SDError::InvalidDiagnostics;
00108 }
00109 
00110 std::error_code
00111 SerializedDiagnosticReader::readMetaBlock(llvm::BitstreamCursor &Stream) {
00112   if (Stream.EnterSubBlock(clang::serialized_diags::BLOCK_META))
00113     return SDError::MalformedMetadataBlock;
00114 
00115   bool VersionChecked = false;
00116 
00117   while (true) {
00118     unsigned BlockOrCode = 0;
00119     llvm::ErrorOr<Cursor> Res = skipUntilRecordOrBlock(Stream, BlockOrCode);
00120     if (!Res)
00121       Res.getError();
00122 
00123     switch (Res.get()) {
00124     case Cursor::Record:
00125       break;
00126     case Cursor::BlockBegin:
00127       if (Stream.SkipBlock())
00128         return SDError::MalformedMetadataBlock;
00129     case Cursor::BlockEnd:
00130       if (!VersionChecked)
00131         return SDError::MissingVersion;
00132       return std::error_code();
00133     }
00134 
00135     SmallVector<uint64_t, 1> Record;
00136     unsigned RecordID = Stream.readRecord(BlockOrCode, Record);
00137 
00138     if (RecordID == RECORD_VERSION) {
00139       if (Record.size() < 1)
00140         return SDError::MissingVersion;
00141       if (Record[0] > VersionNumber)
00142         return SDError::VersionMismatch;
00143       VersionChecked = true;
00144     }
00145   }
00146 }
00147 
00148 std::error_code
00149 SerializedDiagnosticReader::readDiagnosticBlock(llvm::BitstreamCursor &Stream) {
00150   if (Stream.EnterSubBlock(clang::serialized_diags::BLOCK_DIAG))
00151     return SDError::MalformedDiagnosticBlock;
00152 
00153   std::error_code EC;
00154   if ((EC = visitStartOfDiagnostic()))
00155     return EC;
00156 
00157   SmallVector<uint64_t, 16> Record;
00158   while (true) {
00159     unsigned BlockOrCode = 0;
00160     llvm::ErrorOr<Cursor> Res = skipUntilRecordOrBlock(Stream, BlockOrCode);
00161     if (!Res)
00162       Res.getError();
00163 
00164     switch (Res.get()) {
00165     case Cursor::BlockBegin:
00166       // The only blocks we care about are subdiagnostics.
00167       if (BlockOrCode == serialized_diags::BLOCK_DIAG) {
00168         if ((EC = readDiagnosticBlock(Stream)))
00169           return EC;
00170       } else if (!Stream.SkipBlock())
00171         return SDError::MalformedSubBlock;
00172       continue;
00173     case Cursor::BlockEnd:
00174       if ((EC = visitEndOfDiagnostic()))
00175         return EC;
00176       return std::error_code();
00177     case Cursor::Record:
00178       break;
00179     }
00180 
00181     // Read the record.
00182     Record.clear();
00183     StringRef Blob;
00184     unsigned RecID = Stream.readRecord(BlockOrCode, Record, &Blob);
00185 
00186     if (RecID < serialized_diags::RECORD_FIRST ||
00187         RecID > serialized_diags::RECORD_LAST)
00188       continue;
00189 
00190     switch ((RecordIDs)RecID) {
00191     case RECORD_CATEGORY:
00192       // A category has ID and name size.
00193       if (Record.size() != 2)
00194         return SDError::MalformedDiagnosticRecord;
00195       if ((EC = visitCategoryRecord(Record[0], Blob)))
00196         return EC;
00197       continue;
00198     case RECORD_DIAG:
00199       // A diagnostic has severity, location (4), category, flag, and message
00200       // size.
00201       if (Record.size() != 8)
00202         return SDError::MalformedDiagnosticRecord;
00203       if ((EC = visitDiagnosticRecord(
00204                Record[0], Location(Record[1], Record[2], Record[3], Record[4]),
00205                Record[5], Record[6], Blob)))
00206         return EC;
00207       continue;
00208     case RECORD_DIAG_FLAG:
00209       // A diagnostic flag has ID and name size.
00210       if (Record.size() != 2)
00211         return SDError::MalformedDiagnosticRecord;
00212       if ((EC = visitDiagFlagRecord(Record[0], Blob)))
00213         return EC;
00214       continue;
00215     case RECORD_FILENAME:
00216       // A filename has ID, size, timestamp, and name size. The size and
00217       // timestamp are legacy fields that are always zero these days.
00218       if (Record.size() != 4)
00219         return SDError::MalformedDiagnosticRecord;
00220       if ((EC = visitFilenameRecord(Record[0], Record[1], Record[2], Blob)))
00221         return EC;
00222       continue;
00223     case RECORD_FIXIT:
00224       // A fixit has two locations (4 each) and message size.
00225       if (Record.size() != 9)
00226         return SDError::MalformedDiagnosticRecord;
00227       if ((EC = visitFixitRecord(
00228                Location(Record[0], Record[1], Record[2], Record[3]),
00229                Location(Record[4], Record[5], Record[6], Record[7]), Blob)))
00230         return EC;
00231       continue;
00232     case RECORD_SOURCE_RANGE:
00233       // A source range is two locations (4 each).
00234       if (Record.size() != 8)
00235         return SDError::MalformedDiagnosticRecord;
00236       if ((EC = visitSourceRangeRecord(
00237                Location(Record[0], Record[1], Record[2], Record[3]),
00238                Location(Record[4], Record[5], Record[6], Record[7]))))
00239         return EC;
00240       continue;
00241     case RECORD_VERSION:
00242       // A version is just a number.
00243       if (Record.size() != 1)
00244         return SDError::MalformedDiagnosticRecord;
00245       if ((EC = visitVersionRecord(Record[0])))
00246         return EC;
00247       continue;
00248     }
00249   }
00250 }
00251 
00252 namespace {
00253 class SDErrorCategoryType final : public std::error_category {
00254   const char *name() const LLVM_NOEXCEPT override {
00255     return "clang.serialized_diags";
00256   }
00257   std::string message(int IE) const override {
00258     SDError E = static_cast<SDError>(IE);
00259     switch (E) {
00260     case SDError::CouldNotLoad:
00261       return "Failed to open diagnostics file";
00262     case SDError::InvalidSignature:
00263       return "Invalid diagnostics signature";
00264     case SDError::InvalidDiagnostics:
00265       return "Parse error reading diagnostics";
00266     case SDError::MalformedTopLevelBlock:
00267       return "Malformed block at top-level of diagnostics";
00268     case SDError::MalformedSubBlock:
00269       return "Malformed sub-block in a diagnostic";
00270     case SDError::MalformedBlockInfoBlock:
00271       return "Malformed BlockInfo block";
00272     case SDError::MalformedMetadataBlock:
00273       return "Malformed Metadata block";
00274     case SDError::MalformedDiagnosticBlock:
00275       return "Malformed Diagnostic block";
00276     case SDError::MalformedDiagnosticRecord:
00277       return "Malformed Diagnostic record";
00278     case SDError::MissingVersion:
00279       return "No version provided in diagnostics";
00280     case SDError::VersionMismatch:
00281       return "Unsupported diagnostics version";
00282     case SDError::UnsupportedConstruct:
00283       return "Bitcode constructs that are not supported in diagnostics appear";
00284     case SDError::HandlerFailed:
00285       return "Generic error occurred while handling a record";
00286     }
00287     llvm_unreachable("Unknown error type!");
00288   }
00289 };
00290 }
00291 
00292 static llvm::ManagedStatic<SDErrorCategoryType> ErrorCategory;
00293 const std::error_category &clang::serialized_diags::SDErrorCategory() {
00294   return *ErrorCategory;
00295 }