1*0b57cec5SDimitry Andric //===- SerializedDiagnosticReader.cpp - Reads diagnostics -----------------===// 2*0b57cec5SDimitry Andric // 3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*0b57cec5SDimitry Andric // 7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 8*0b57cec5SDimitry Andric 9*0b57cec5SDimitry Andric #include "clang/Frontend/SerializedDiagnosticReader.h" 10*0b57cec5SDimitry Andric #include "clang/Basic/FileManager.h" 11*0b57cec5SDimitry Andric #include "clang/Basic/FileSystemOptions.h" 12*0b57cec5SDimitry Andric #include "clang/Frontend/SerializedDiagnostics.h" 13*0b57cec5SDimitry Andric #include "llvm/ADT/Optional.h" 14*0b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h" 15*0b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h" 16*0b57cec5SDimitry Andric #include "llvm/Bitstream/BitCodes.h" 17*0b57cec5SDimitry Andric #include "llvm/Bitstream/BitstreamReader.h" 18*0b57cec5SDimitry Andric #include "llvm/Support/Compiler.h" 19*0b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h" 20*0b57cec5SDimitry Andric #include "llvm/Support/ErrorOr.h" 21*0b57cec5SDimitry Andric #include "llvm/Support/ManagedStatic.h" 22*0b57cec5SDimitry Andric #include <cstdint> 23*0b57cec5SDimitry Andric #include <system_error> 24*0b57cec5SDimitry Andric 25*0b57cec5SDimitry Andric using namespace clang; 26*0b57cec5SDimitry Andric using namespace serialized_diags; 27*0b57cec5SDimitry Andric 28*0b57cec5SDimitry Andric std::error_code SerializedDiagnosticReader::readDiagnostics(StringRef File) { 29*0b57cec5SDimitry Andric // Open the diagnostics file. 30*0b57cec5SDimitry Andric FileSystemOptions FO; 31*0b57cec5SDimitry Andric FileManager FileMgr(FO); 32*0b57cec5SDimitry Andric 33*0b57cec5SDimitry Andric auto Buffer = FileMgr.getBufferForFile(File); 34*0b57cec5SDimitry Andric if (!Buffer) 35*0b57cec5SDimitry Andric return SDError::CouldNotLoad; 36*0b57cec5SDimitry Andric 37*0b57cec5SDimitry Andric llvm::BitstreamCursor Stream(**Buffer); 38*0b57cec5SDimitry Andric Optional<llvm::BitstreamBlockInfo> BlockInfo; 39*0b57cec5SDimitry Andric 40*0b57cec5SDimitry Andric if (Stream.AtEndOfStream()) 41*0b57cec5SDimitry Andric return SDError::InvalidSignature; 42*0b57cec5SDimitry Andric 43*0b57cec5SDimitry Andric // Sniff for the signature. 44*0b57cec5SDimitry Andric for (unsigned char C : {'D', 'I', 'A', 'G'}) { 45*0b57cec5SDimitry Andric if (Expected<llvm::SimpleBitstreamCursor::word_t> Res = Stream.Read(8)) { 46*0b57cec5SDimitry Andric if (Res.get() == C) 47*0b57cec5SDimitry Andric continue; 48*0b57cec5SDimitry Andric } else { 49*0b57cec5SDimitry Andric // FIXME this drops the error on the floor. 50*0b57cec5SDimitry Andric consumeError(Res.takeError()); 51*0b57cec5SDimitry Andric } 52*0b57cec5SDimitry Andric return SDError::InvalidSignature; 53*0b57cec5SDimitry Andric } 54*0b57cec5SDimitry Andric 55*0b57cec5SDimitry Andric // Read the top level blocks. 56*0b57cec5SDimitry Andric while (!Stream.AtEndOfStream()) { 57*0b57cec5SDimitry Andric if (Expected<unsigned> Res = Stream.ReadCode()) { 58*0b57cec5SDimitry Andric if (Res.get() != llvm::bitc::ENTER_SUBBLOCK) 59*0b57cec5SDimitry Andric return SDError::InvalidDiagnostics; 60*0b57cec5SDimitry Andric } else { 61*0b57cec5SDimitry Andric // FIXME this drops the error on the floor. 62*0b57cec5SDimitry Andric consumeError(Res.takeError()); 63*0b57cec5SDimitry Andric return SDError::InvalidDiagnostics; 64*0b57cec5SDimitry Andric } 65*0b57cec5SDimitry Andric 66*0b57cec5SDimitry Andric std::error_code EC; 67*0b57cec5SDimitry Andric Expected<unsigned> MaybeSubBlockID = Stream.ReadSubBlockID(); 68*0b57cec5SDimitry Andric if (!MaybeSubBlockID) { 69*0b57cec5SDimitry Andric // FIXME this drops the error on the floor. 70*0b57cec5SDimitry Andric consumeError(MaybeSubBlockID.takeError()); 71*0b57cec5SDimitry Andric return SDError::InvalidDiagnostics; 72*0b57cec5SDimitry Andric } 73*0b57cec5SDimitry Andric 74*0b57cec5SDimitry Andric switch (MaybeSubBlockID.get()) { 75*0b57cec5SDimitry Andric case llvm::bitc::BLOCKINFO_BLOCK_ID: { 76*0b57cec5SDimitry Andric Expected<Optional<llvm::BitstreamBlockInfo>> MaybeBlockInfo = 77*0b57cec5SDimitry Andric Stream.ReadBlockInfoBlock(); 78*0b57cec5SDimitry Andric if (!MaybeBlockInfo) { 79*0b57cec5SDimitry Andric // FIXME this drops the error on the floor. 80*0b57cec5SDimitry Andric consumeError(MaybeBlockInfo.takeError()); 81*0b57cec5SDimitry Andric return SDError::InvalidDiagnostics; 82*0b57cec5SDimitry Andric } 83*0b57cec5SDimitry Andric BlockInfo = std::move(MaybeBlockInfo.get()); 84*0b57cec5SDimitry Andric } 85*0b57cec5SDimitry Andric if (!BlockInfo) 86*0b57cec5SDimitry Andric return SDError::MalformedBlockInfoBlock; 87*0b57cec5SDimitry Andric Stream.setBlockInfo(&*BlockInfo); 88*0b57cec5SDimitry Andric continue; 89*0b57cec5SDimitry Andric case BLOCK_META: 90*0b57cec5SDimitry Andric if ((EC = readMetaBlock(Stream))) 91*0b57cec5SDimitry Andric return EC; 92*0b57cec5SDimitry Andric continue; 93*0b57cec5SDimitry Andric case BLOCK_DIAG: 94*0b57cec5SDimitry Andric if ((EC = readDiagnosticBlock(Stream))) 95*0b57cec5SDimitry Andric return EC; 96*0b57cec5SDimitry Andric continue; 97*0b57cec5SDimitry Andric default: 98*0b57cec5SDimitry Andric if (llvm::Error Err = Stream.SkipBlock()) { 99*0b57cec5SDimitry Andric // FIXME this drops the error on the floor. 100*0b57cec5SDimitry Andric consumeError(std::move(Err)); 101*0b57cec5SDimitry Andric return SDError::MalformedTopLevelBlock; 102*0b57cec5SDimitry Andric } 103*0b57cec5SDimitry Andric continue; 104*0b57cec5SDimitry Andric } 105*0b57cec5SDimitry Andric } 106*0b57cec5SDimitry Andric return {}; 107*0b57cec5SDimitry Andric } 108*0b57cec5SDimitry Andric 109*0b57cec5SDimitry Andric enum class SerializedDiagnosticReader::Cursor { 110*0b57cec5SDimitry Andric Record = 1, 111*0b57cec5SDimitry Andric BlockEnd, 112*0b57cec5SDimitry Andric BlockBegin 113*0b57cec5SDimitry Andric }; 114*0b57cec5SDimitry Andric 115*0b57cec5SDimitry Andric llvm::ErrorOr<SerializedDiagnosticReader::Cursor> 116*0b57cec5SDimitry Andric SerializedDiagnosticReader::skipUntilRecordOrBlock( 117*0b57cec5SDimitry Andric llvm::BitstreamCursor &Stream, unsigned &BlockOrRecordID) { 118*0b57cec5SDimitry Andric BlockOrRecordID = 0; 119*0b57cec5SDimitry Andric 120*0b57cec5SDimitry Andric while (!Stream.AtEndOfStream()) { 121*0b57cec5SDimitry Andric unsigned Code; 122*0b57cec5SDimitry Andric if (Expected<unsigned> Res = Stream.ReadCode()) 123*0b57cec5SDimitry Andric Code = Res.get(); 124*0b57cec5SDimitry Andric else 125*0b57cec5SDimitry Andric return llvm::errorToErrorCode(Res.takeError()); 126*0b57cec5SDimitry Andric 127*0b57cec5SDimitry Andric if (Code >= static_cast<unsigned>(llvm::bitc::FIRST_APPLICATION_ABBREV)) { 128*0b57cec5SDimitry Andric // We found a record. 129*0b57cec5SDimitry Andric BlockOrRecordID = Code; 130*0b57cec5SDimitry Andric return Cursor::Record; 131*0b57cec5SDimitry Andric } 132*0b57cec5SDimitry Andric switch (static_cast<llvm::bitc::FixedAbbrevIDs>(Code)) { 133*0b57cec5SDimitry Andric case llvm::bitc::ENTER_SUBBLOCK: 134*0b57cec5SDimitry Andric if (Expected<unsigned> Res = Stream.ReadSubBlockID()) 135*0b57cec5SDimitry Andric BlockOrRecordID = Res.get(); 136*0b57cec5SDimitry Andric else 137*0b57cec5SDimitry Andric return llvm::errorToErrorCode(Res.takeError()); 138*0b57cec5SDimitry Andric return Cursor::BlockBegin; 139*0b57cec5SDimitry Andric 140*0b57cec5SDimitry Andric case llvm::bitc::END_BLOCK: 141*0b57cec5SDimitry Andric if (Stream.ReadBlockEnd()) 142*0b57cec5SDimitry Andric return SDError::InvalidDiagnostics; 143*0b57cec5SDimitry Andric return Cursor::BlockEnd; 144*0b57cec5SDimitry Andric 145*0b57cec5SDimitry Andric case llvm::bitc::DEFINE_ABBREV: 146*0b57cec5SDimitry Andric if (llvm::Error Err = Stream.ReadAbbrevRecord()) 147*0b57cec5SDimitry Andric return llvm::errorToErrorCode(std::move(Err)); 148*0b57cec5SDimitry Andric continue; 149*0b57cec5SDimitry Andric 150*0b57cec5SDimitry Andric case llvm::bitc::UNABBREV_RECORD: 151*0b57cec5SDimitry Andric return SDError::UnsupportedConstruct; 152*0b57cec5SDimitry Andric 153*0b57cec5SDimitry Andric case llvm::bitc::FIRST_APPLICATION_ABBREV: 154*0b57cec5SDimitry Andric llvm_unreachable("Unexpected abbrev id."); 155*0b57cec5SDimitry Andric } 156*0b57cec5SDimitry Andric } 157*0b57cec5SDimitry Andric 158*0b57cec5SDimitry Andric return SDError::InvalidDiagnostics; 159*0b57cec5SDimitry Andric } 160*0b57cec5SDimitry Andric 161*0b57cec5SDimitry Andric std::error_code 162*0b57cec5SDimitry Andric SerializedDiagnosticReader::readMetaBlock(llvm::BitstreamCursor &Stream) { 163*0b57cec5SDimitry Andric if (llvm::Error Err = 164*0b57cec5SDimitry Andric Stream.EnterSubBlock(clang::serialized_diags::BLOCK_META)) { 165*0b57cec5SDimitry Andric // FIXME this drops the error on the floor. 166*0b57cec5SDimitry Andric consumeError(std::move(Err)); 167*0b57cec5SDimitry Andric return SDError::MalformedMetadataBlock; 168*0b57cec5SDimitry Andric } 169*0b57cec5SDimitry Andric 170*0b57cec5SDimitry Andric bool VersionChecked = false; 171*0b57cec5SDimitry Andric 172*0b57cec5SDimitry Andric while (true) { 173*0b57cec5SDimitry Andric unsigned BlockOrCode = 0; 174*0b57cec5SDimitry Andric llvm::ErrorOr<Cursor> Res = skipUntilRecordOrBlock(Stream, BlockOrCode); 175*0b57cec5SDimitry Andric if (!Res) 176*0b57cec5SDimitry Andric Res.getError(); 177*0b57cec5SDimitry Andric 178*0b57cec5SDimitry Andric switch (Res.get()) { 179*0b57cec5SDimitry Andric case Cursor::Record: 180*0b57cec5SDimitry Andric break; 181*0b57cec5SDimitry Andric case Cursor::BlockBegin: 182*0b57cec5SDimitry Andric if (llvm::Error Err = Stream.SkipBlock()) { 183*0b57cec5SDimitry Andric // FIXME this drops the error on the floor. 184*0b57cec5SDimitry Andric consumeError(std::move(Err)); 185*0b57cec5SDimitry Andric return SDError::MalformedMetadataBlock; 186*0b57cec5SDimitry Andric } 187*0b57cec5SDimitry Andric LLVM_FALLTHROUGH; 188*0b57cec5SDimitry Andric case Cursor::BlockEnd: 189*0b57cec5SDimitry Andric if (!VersionChecked) 190*0b57cec5SDimitry Andric return SDError::MissingVersion; 191*0b57cec5SDimitry Andric return {}; 192*0b57cec5SDimitry Andric } 193*0b57cec5SDimitry Andric 194*0b57cec5SDimitry Andric SmallVector<uint64_t, 1> Record; 195*0b57cec5SDimitry Andric Expected<unsigned> MaybeRecordID = Stream.readRecord(BlockOrCode, Record); 196*0b57cec5SDimitry Andric if (!MaybeRecordID) 197*0b57cec5SDimitry Andric return errorToErrorCode(MaybeRecordID.takeError()); 198*0b57cec5SDimitry Andric unsigned RecordID = MaybeRecordID.get(); 199*0b57cec5SDimitry Andric 200*0b57cec5SDimitry Andric if (RecordID == RECORD_VERSION) { 201*0b57cec5SDimitry Andric if (Record.size() < 1) 202*0b57cec5SDimitry Andric return SDError::MissingVersion; 203*0b57cec5SDimitry Andric if (Record[0] > VersionNumber) 204*0b57cec5SDimitry Andric return SDError::VersionMismatch; 205*0b57cec5SDimitry Andric VersionChecked = true; 206*0b57cec5SDimitry Andric } 207*0b57cec5SDimitry Andric } 208*0b57cec5SDimitry Andric } 209*0b57cec5SDimitry Andric 210*0b57cec5SDimitry Andric std::error_code 211*0b57cec5SDimitry Andric SerializedDiagnosticReader::readDiagnosticBlock(llvm::BitstreamCursor &Stream) { 212*0b57cec5SDimitry Andric if (llvm::Error Err = 213*0b57cec5SDimitry Andric Stream.EnterSubBlock(clang::serialized_diags::BLOCK_DIAG)) { 214*0b57cec5SDimitry Andric // FIXME this drops the error on the floor. 215*0b57cec5SDimitry Andric consumeError(std::move(Err)); 216*0b57cec5SDimitry Andric return SDError::MalformedDiagnosticBlock; 217*0b57cec5SDimitry Andric } 218*0b57cec5SDimitry Andric 219*0b57cec5SDimitry Andric std::error_code EC; 220*0b57cec5SDimitry Andric if ((EC = visitStartOfDiagnostic())) 221*0b57cec5SDimitry Andric return EC; 222*0b57cec5SDimitry Andric 223*0b57cec5SDimitry Andric SmallVector<uint64_t, 16> Record; 224*0b57cec5SDimitry Andric while (true) { 225*0b57cec5SDimitry Andric unsigned BlockOrCode = 0; 226*0b57cec5SDimitry Andric llvm::ErrorOr<Cursor> Res = skipUntilRecordOrBlock(Stream, BlockOrCode); 227*0b57cec5SDimitry Andric if (!Res) 228*0b57cec5SDimitry Andric Res.getError(); 229*0b57cec5SDimitry Andric 230*0b57cec5SDimitry Andric switch (Res.get()) { 231*0b57cec5SDimitry Andric case Cursor::BlockBegin: 232*0b57cec5SDimitry Andric // The only blocks we care about are subdiagnostics. 233*0b57cec5SDimitry Andric if (BlockOrCode == serialized_diags::BLOCK_DIAG) { 234*0b57cec5SDimitry Andric if ((EC = readDiagnosticBlock(Stream))) 235*0b57cec5SDimitry Andric return EC; 236*0b57cec5SDimitry Andric } else if (llvm::Error Err = Stream.SkipBlock()) { 237*0b57cec5SDimitry Andric // FIXME this drops the error on the floor. 238*0b57cec5SDimitry Andric consumeError(std::move(Err)); 239*0b57cec5SDimitry Andric return SDError::MalformedSubBlock; 240*0b57cec5SDimitry Andric } 241*0b57cec5SDimitry Andric continue; 242*0b57cec5SDimitry Andric case Cursor::BlockEnd: 243*0b57cec5SDimitry Andric if ((EC = visitEndOfDiagnostic())) 244*0b57cec5SDimitry Andric return EC; 245*0b57cec5SDimitry Andric return {}; 246*0b57cec5SDimitry Andric case Cursor::Record: 247*0b57cec5SDimitry Andric break; 248*0b57cec5SDimitry Andric } 249*0b57cec5SDimitry Andric 250*0b57cec5SDimitry Andric // Read the record. 251*0b57cec5SDimitry Andric Record.clear(); 252*0b57cec5SDimitry Andric StringRef Blob; 253*0b57cec5SDimitry Andric Expected<unsigned> MaybeRecID = 254*0b57cec5SDimitry Andric Stream.readRecord(BlockOrCode, Record, &Blob); 255*0b57cec5SDimitry Andric if (!MaybeRecID) 256*0b57cec5SDimitry Andric return errorToErrorCode(MaybeRecID.takeError()); 257*0b57cec5SDimitry Andric unsigned RecID = MaybeRecID.get(); 258*0b57cec5SDimitry Andric 259*0b57cec5SDimitry Andric if (RecID < serialized_diags::RECORD_FIRST || 260*0b57cec5SDimitry Andric RecID > serialized_diags::RECORD_LAST) 261*0b57cec5SDimitry Andric continue; 262*0b57cec5SDimitry Andric 263*0b57cec5SDimitry Andric switch ((RecordIDs)RecID) { 264*0b57cec5SDimitry Andric case RECORD_CATEGORY: 265*0b57cec5SDimitry Andric // A category has ID and name size. 266*0b57cec5SDimitry Andric if (Record.size() != 2) 267*0b57cec5SDimitry Andric return SDError::MalformedDiagnosticRecord; 268*0b57cec5SDimitry Andric if ((EC = visitCategoryRecord(Record[0], Blob))) 269*0b57cec5SDimitry Andric return EC; 270*0b57cec5SDimitry Andric continue; 271*0b57cec5SDimitry Andric case RECORD_DIAG: 272*0b57cec5SDimitry Andric // A diagnostic has severity, location (4), category, flag, and message 273*0b57cec5SDimitry Andric // size. 274*0b57cec5SDimitry Andric if (Record.size() != 8) 275*0b57cec5SDimitry Andric return SDError::MalformedDiagnosticRecord; 276*0b57cec5SDimitry Andric if ((EC = visitDiagnosticRecord( 277*0b57cec5SDimitry Andric Record[0], Location(Record[1], Record[2], Record[3], Record[4]), 278*0b57cec5SDimitry Andric Record[5], Record[6], Blob))) 279*0b57cec5SDimitry Andric return EC; 280*0b57cec5SDimitry Andric continue; 281*0b57cec5SDimitry Andric case RECORD_DIAG_FLAG: 282*0b57cec5SDimitry Andric // A diagnostic flag has ID and name size. 283*0b57cec5SDimitry Andric if (Record.size() != 2) 284*0b57cec5SDimitry Andric return SDError::MalformedDiagnosticRecord; 285*0b57cec5SDimitry Andric if ((EC = visitDiagFlagRecord(Record[0], Blob))) 286*0b57cec5SDimitry Andric return EC; 287*0b57cec5SDimitry Andric continue; 288*0b57cec5SDimitry Andric case RECORD_FILENAME: 289*0b57cec5SDimitry Andric // A filename has ID, size, timestamp, and name size. The size and 290*0b57cec5SDimitry Andric // timestamp are legacy fields that are always zero these days. 291*0b57cec5SDimitry Andric if (Record.size() != 4) 292*0b57cec5SDimitry Andric return SDError::MalformedDiagnosticRecord; 293*0b57cec5SDimitry Andric if ((EC = visitFilenameRecord(Record[0], Record[1], Record[2], Blob))) 294*0b57cec5SDimitry Andric return EC; 295*0b57cec5SDimitry Andric continue; 296*0b57cec5SDimitry Andric case RECORD_FIXIT: 297*0b57cec5SDimitry Andric // A fixit has two locations (4 each) and message size. 298*0b57cec5SDimitry Andric if (Record.size() != 9) 299*0b57cec5SDimitry Andric return SDError::MalformedDiagnosticRecord; 300*0b57cec5SDimitry Andric if ((EC = visitFixitRecord( 301*0b57cec5SDimitry Andric Location(Record[0], Record[1], Record[2], Record[3]), 302*0b57cec5SDimitry Andric Location(Record[4], Record[5], Record[6], Record[7]), Blob))) 303*0b57cec5SDimitry Andric return EC; 304*0b57cec5SDimitry Andric continue; 305*0b57cec5SDimitry Andric case RECORD_SOURCE_RANGE: 306*0b57cec5SDimitry Andric // A source range is two locations (4 each). 307*0b57cec5SDimitry Andric if (Record.size() != 8) 308*0b57cec5SDimitry Andric return SDError::MalformedDiagnosticRecord; 309*0b57cec5SDimitry Andric if ((EC = visitSourceRangeRecord( 310*0b57cec5SDimitry Andric Location(Record[0], Record[1], Record[2], Record[3]), 311*0b57cec5SDimitry Andric Location(Record[4], Record[5], Record[6], Record[7])))) 312*0b57cec5SDimitry Andric return EC; 313*0b57cec5SDimitry Andric continue; 314*0b57cec5SDimitry Andric case RECORD_VERSION: 315*0b57cec5SDimitry Andric // A version is just a number. 316*0b57cec5SDimitry Andric if (Record.size() != 1) 317*0b57cec5SDimitry Andric return SDError::MalformedDiagnosticRecord; 318*0b57cec5SDimitry Andric if ((EC = visitVersionRecord(Record[0]))) 319*0b57cec5SDimitry Andric return EC; 320*0b57cec5SDimitry Andric continue; 321*0b57cec5SDimitry Andric } 322*0b57cec5SDimitry Andric } 323*0b57cec5SDimitry Andric } 324*0b57cec5SDimitry Andric 325*0b57cec5SDimitry Andric namespace { 326*0b57cec5SDimitry Andric 327*0b57cec5SDimitry Andric class SDErrorCategoryType final : public std::error_category { 328*0b57cec5SDimitry Andric const char *name() const noexcept override { 329*0b57cec5SDimitry Andric return "clang.serialized_diags"; 330*0b57cec5SDimitry Andric } 331*0b57cec5SDimitry Andric 332*0b57cec5SDimitry Andric std::string message(int IE) const override { 333*0b57cec5SDimitry Andric auto E = static_cast<SDError>(IE); 334*0b57cec5SDimitry Andric switch (E) { 335*0b57cec5SDimitry Andric case SDError::CouldNotLoad: 336*0b57cec5SDimitry Andric return "Failed to open diagnostics file"; 337*0b57cec5SDimitry Andric case SDError::InvalidSignature: 338*0b57cec5SDimitry Andric return "Invalid diagnostics signature"; 339*0b57cec5SDimitry Andric case SDError::InvalidDiagnostics: 340*0b57cec5SDimitry Andric return "Parse error reading diagnostics"; 341*0b57cec5SDimitry Andric case SDError::MalformedTopLevelBlock: 342*0b57cec5SDimitry Andric return "Malformed block at top-level of diagnostics"; 343*0b57cec5SDimitry Andric case SDError::MalformedSubBlock: 344*0b57cec5SDimitry Andric return "Malformed sub-block in a diagnostic"; 345*0b57cec5SDimitry Andric case SDError::MalformedBlockInfoBlock: 346*0b57cec5SDimitry Andric return "Malformed BlockInfo block"; 347*0b57cec5SDimitry Andric case SDError::MalformedMetadataBlock: 348*0b57cec5SDimitry Andric return "Malformed Metadata block"; 349*0b57cec5SDimitry Andric case SDError::MalformedDiagnosticBlock: 350*0b57cec5SDimitry Andric return "Malformed Diagnostic block"; 351*0b57cec5SDimitry Andric case SDError::MalformedDiagnosticRecord: 352*0b57cec5SDimitry Andric return "Malformed Diagnostic record"; 353*0b57cec5SDimitry Andric case SDError::MissingVersion: 354*0b57cec5SDimitry Andric return "No version provided in diagnostics"; 355*0b57cec5SDimitry Andric case SDError::VersionMismatch: 356*0b57cec5SDimitry Andric return "Unsupported diagnostics version"; 357*0b57cec5SDimitry Andric case SDError::UnsupportedConstruct: 358*0b57cec5SDimitry Andric return "Bitcode constructs that are not supported in diagnostics appear"; 359*0b57cec5SDimitry Andric case SDError::HandlerFailed: 360*0b57cec5SDimitry Andric return "Generic error occurred while handling a record"; 361*0b57cec5SDimitry Andric } 362*0b57cec5SDimitry Andric llvm_unreachable("Unknown error type!"); 363*0b57cec5SDimitry Andric } 364*0b57cec5SDimitry Andric }; 365*0b57cec5SDimitry Andric 366*0b57cec5SDimitry Andric } // namespace 367*0b57cec5SDimitry Andric 368*0b57cec5SDimitry Andric static llvm::ManagedStatic<SDErrorCategoryType> ErrorCategory; 369*0b57cec5SDimitry Andric const std::error_category &clang::serialized_diags::SDErrorCategory() { 370*0b57cec5SDimitry Andric return *ErrorCategory; 371*0b57cec5SDimitry Andric } 372