clang API Documentation
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 }