diff --git a/clang/include/clang/Basic/Diagnostic.h b/clang/include/clang/Basic/Diagnostic.h --- a/clang/include/clang/Basic/Diagnostic.h +++ b/clang/include/clang/Basic/Diagnostic.h @@ -25,6 +25,7 @@ #include "llvm/ADT/StringRef.h" #include "llvm/ADT/iterator_range.h" #include "llvm/Support/Compiler.h" +#include "llvm/Support/Error.h" #include #include #include @@ -1303,6 +1304,11 @@ return DiagnosticBuilder(this); } +inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, llvm::Error &&E) { + DB.AddString(toString(std::move(E))); + return DB; +} + inline DiagnosticBuilder DiagnosticsEngine::Report(unsigned DiagID) { return Report(SourceLocation(), DiagID); } diff --git a/clang/include/clang/Frontend/FrontendAction.h b/clang/include/clang/Frontend/FrontendAction.h --- a/clang/include/clang/Frontend/FrontendAction.h +++ b/clang/include/clang/Frontend/FrontendAction.h @@ -23,6 +23,7 @@ #include "clang/Frontend/ASTUnit.h" #include "clang/Frontend/FrontendOptions.h" #include "llvm/ADT/StringRef.h" +#include "llvm/Support/Error.h" #include #include #include @@ -229,7 +230,8 @@ bool BeginSourceFile(CompilerInstance &CI, const FrontendInputFile &Input); /// Set the source manager's main input file, and run the action. - bool Execute(); + __attribute__((deprecated("The semantics of this API have changed from bool to Error, changing the polarity of the return value"))) // FIXME remove this, it's here to help me catch all uses of this API. + llvm::Error Execute(); /// Perform any per-file post processing, deallocate per-file /// objects, and run statistics and output file cleanup code. diff --git a/clang/include/clang/Serialization/ASTReader.h b/clang/include/clang/Serialization/ASTReader.h --- a/clang/include/clang/Serialization/ASTReader.h +++ b/clang/include/clang/Serialization/ASTReader.h @@ -1437,6 +1437,7 @@ void Error(StringRef Msg) const; void Error(unsigned DiagID, StringRef Arg1 = StringRef(), StringRef Arg2 = StringRef()) const; + void Error(llvm::Error &&Err) const; public: /// Load the AST file and validate its contents against the given @@ -2379,7 +2380,7 @@ /// Reads a record with id AbbrevID from Cursor, resetting the /// internal state. - unsigned readRecord(llvm::BitstreamCursor &Cursor, unsigned AbbrevID); + Expected readRecord(llvm::BitstreamCursor &Cursor, unsigned AbbrevID); /// Is this a module file for a module (rather than a PCH or similar). bool isModule() const { return F->isModule(); } @@ -2679,7 +2680,8 @@ : Cursor(Cursor), Offset(Cursor.GetCurrentBitNo()) {} ~SavedStreamPosition() { - Cursor.JumpToBit(Offset); + if (llvm::Error Err = Cursor.JumpToBit(Offset)) + llvm::report_fatal_error("Cursor should always be able to go back, failed: " + toString(std::move(Err))); } private: diff --git a/clang/include/clang/Serialization/GlobalModuleIndex.h b/clang/include/clang/Serialization/GlobalModuleIndex.h --- a/clang/include/clang/Serialization/GlobalModuleIndex.h +++ b/clang/include/clang/Serialization/GlobalModuleIndex.h @@ -20,6 +20,7 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" +#include "llvm/Support/Error.h" #include #include @@ -122,28 +123,14 @@ public: ~GlobalModuleIndex(); - /// An error code returned when trying to read an index. - enum ErrorCode { - /// No error occurred. - EC_None, - /// No index was found. - EC_NotFound, - /// Some other process is currently building the index; it is not - /// available yet. - EC_Building, - /// There was an unspecified I/O error reading or writing the index. - EC_IOError - }; - /// Read a global index file for the given directory. /// /// \param Path The path to the specific module cache where the module files /// for the intended configuration reside. /// /// \returns A pair containing the global module index (if it exists) and - /// the error code. - static std::pair - readIndex(llvm::StringRef Path); + /// the error. + static std::pair readIndex(llvm::StringRef Path); /// Returns an iterator for identifiers stored in the index table. /// @@ -194,9 +181,7 @@ /// creating modules. /// \param Path The path to the directory containing module files, into /// which the global index will be written. - static ErrorCode writeIndex(FileManager &FileMgr, - const PCHContainerReader &PCHContainerRdr, - llvm::StringRef Path); + static llvm::Error writeIndex(FileManager &FileMgr, const PCHContainerReader &PCHContainerRdr, llvm::StringRef Path); }; } diff --git a/clang/lib/Frontend/ASTUnit.cpp b/clang/lib/Frontend/ASTUnit.cpp --- a/clang/lib/Frontend/ASTUnit.cpp +++ b/clang/lib/Frontend/ASTUnit.cpp @@ -1206,8 +1206,8 @@ else PreambleSrcLocCache.clear(); - if (!Act->Execute()) - goto error; + if (llvm::Error Err = Act->Execute()) + goto error; // FIXME this drops the error on the floor. transferASTDataFromCompilerInstance(*Clang); @@ -1632,7 +1632,8 @@ Clang->setASTConsumer( llvm::make_unique(std::move(Consumers))); } - if (!Act->Execute()) { + if (llvm::Error Err = Act->Execute()) { + // FIXME this drops the error on the floor. AST->transferASTDataFromCompilerInstance(*Clang); if (OwnAST && ErrAST) ErrAST->swap(OwnAST); @@ -2280,7 +2281,9 @@ std::unique_ptr Act; Act.reset(new SyntaxOnlyAction); if (Act->BeginSourceFile(*Clang.get(), Clang->getFrontendOpts().Inputs[0])) { - Act->Execute(); + if (llvm::Error Err = Act->Execute()) { + // FIXME this drops the error on the floor. + } Act->EndSourceFile(); } } diff --git a/clang/lib/Frontend/CompilerInstance.cpp b/clang/lib/Frontend/CompilerInstance.cpp --- a/clang/lib/Frontend/CompilerInstance.cpp +++ b/clang/lib/Frontend/CompilerInstance.cpp @@ -945,7 +945,9 @@ getSourceManager().clearIDTables(); if (Act.BeginSourceFile(*this, FIF)) { - Act.Execute(); + if (llvm::Error Err = Act.Execute()) { + // FIXME this drops the error on the floor. + } Act.EndSourceFile(); } } @@ -2049,9 +2051,11 @@ hasPreprocessor()) { llvm::sys::fs::create_directories( getPreprocessor().getHeaderSearchInfo().getModuleCachePath()); - GlobalModuleIndex::writeIndex( - getFileManager(), getPCHContainerReader(), - getPreprocessor().getHeaderSearchInfo().getModuleCachePath()); + if (llvm::Error Err = GlobalModuleIndex::writeIndex(getFileManager(), getPCHContainerReader(), getPreprocessor().getHeaderSearchInfo().getModuleCachePath())) { + // FIXME this drops the error on the floor. This code is only used for + // typo correction and drops more than just this one source of errors + // (such as the directory creation failure above). + } ModuleManager->resetForReload(); ModuleManager->loadGlobalIndex(); GlobalIndex = ModuleManager->getGlobalIndex(); @@ -2076,9 +2080,9 @@ } } if (RecreateIndex) { - GlobalModuleIndex::writeIndex( - getFileManager(), getPCHContainerReader(), - getPreprocessor().getHeaderSearchInfo().getModuleCachePath()); + if (llvm::Error Err = GlobalModuleIndex::writeIndex(getFileManager(), getPCHContainerReader(), getPreprocessor().getHeaderSearchInfo().getModuleCachePath())) { + // FIXME As above, this drops the error on the floor. + } ModuleManager->resetForReload(); ModuleManager->loadGlobalIndex(); GlobalIndex = ModuleManager->getGlobalIndex(); diff --git a/clang/lib/Frontend/FrontendAction.cpp b/clang/lib/Frontend/FrontendAction.cpp --- a/clang/lib/Frontend/FrontendAction.cpp +++ b/clang/lib/Frontend/FrontendAction.cpp @@ -924,7 +924,7 @@ return false; } -bool FrontendAction::Execute() { +llvm::Error FrontendAction::Execute() { CompilerInstance &CI = getCompilerInstance(); if (CI.hasFrontendTimer()) { @@ -939,12 +939,13 @@ CI.hasPreprocessor()) { StringRef Cache = CI.getPreprocessor().getHeaderSearchInfo().getModuleCachePath(); - if (!Cache.empty()) - GlobalModuleIndex::writeIndex(CI.getFileManager(), - CI.getPCHContainerReader(), Cache); + if (!Cache.empty()) { + if (llvm::Error Err = GlobalModuleIndex::writeIndex(CI.getFileManager(), CI.getPCHContainerReader(), Cache)) + return Err; + } } - return true; + return llvm::Error::success(); } void FrontendAction::EndSourceFile() { diff --git a/clang/lib/Frontend/PrecompiledPreamble.cpp b/clang/lib/Frontend/PrecompiledPreamble.cpp --- a/clang/lib/Frontend/PrecompiledPreamble.cpp +++ b/clang/lib/Frontend/PrecompiledPreamble.cpp @@ -352,7 +352,8 @@ if (auto CommentHandler = Callbacks.getCommentHandler()) Clang->getPreprocessor().addCommentHandler(CommentHandler); - Act->Execute(); + if (llvm::Error Err = Act->Execute()) + return errorToErrorCode(std::move(Err)); // Run the callbacks. Callbacks.AfterExecute(*Clang); diff --git a/clang/lib/Frontend/Rewrite/FrontendActions.cpp b/clang/lib/Frontend/Rewrite/FrontendActions.cpp --- a/clang/lib/Frontend/Rewrite/FrontendActions.cpp +++ b/clang/lib/Frontend/Rewrite/FrontendActions.cpp @@ -129,7 +129,8 @@ FixItOpts->FixOnlyWarnings = FEOpts.FixOnlyWarnings; FixItRewriter Rewriter(CI.getDiagnostics(), CI.getSourceManager(), CI.getLangOpts(), FixItOpts.get()); - FixAction->Execute(); + if (llvm::Error Err = FixAction->Execute()) + err = true; // FIXME this drops the error on the floor. err = Rewriter.WriteFixedFiles(&RewrittenFiles); diff --git a/clang/lib/Frontend/SerializedDiagnosticReader.cpp b/clang/lib/Frontend/SerializedDiagnosticReader.cpp --- a/clang/lib/Frontend/SerializedDiagnosticReader.cpp +++ b/clang/lib/Frontend/SerializedDiagnosticReader.cpp @@ -41,21 +41,38 @@ return SDError::InvalidSignature; // Sniff for the signature. - if (Stream.Read(8) != 'D' || - Stream.Read(8) != 'I' || - Stream.Read(8) != 'A' || - Stream.Read(8) != 'G') + for (unsigned char C : {'D', 'I', 'A', 'G'}) { + if (Expected Res = Stream.Read(8)) { + if (Res.get() == C) + continue; + } else + (void)Res.takeError(); // FIXME propagate the error details. return SDError::InvalidSignature; + } // Read the top level blocks. while (!Stream.AtEndOfStream()) { - if (Stream.ReadCode() != llvm::bitc::ENTER_SUBBLOCK) - return SDError::InvalidDiagnostics; + if (Expected Res = Stream.ReadCode()) { + if (Res.get() != llvm::bitc::ENTER_SUBBLOCK) + return SDError::InvalidDiagnostics; + } else + return SDError::InvalidDiagnostics; // FIXME propagate the error details. std::error_code EC; - switch (Stream.ReadSubBlockID()) { + Expected SubBlockID = Stream.ReadSubBlockID(); + if (!SubBlockID) + return SDError::InvalidDiagnostics; // FIXME propagate the error details. + + switch (SubBlockID.get()) { case llvm::bitc::BLOCKINFO_BLOCK_ID: - BlockInfo = Stream.ReadBlockInfoBlock(); + { + Expected> MaybeBlockInfo = Stream.ReadBlockInfoBlock(); + if (!MaybeBlockInfo) { + (void)MaybeBlockInfo.takeError(); // FIXME propagate the error details. + return SDError::InvalidDiagnostics; + } + BlockInfo = std::move(MaybeBlockInfo.get()); + } if (!BlockInfo) return SDError::MalformedBlockInfoBlock; Stream.setBlockInfo(&*BlockInfo); @@ -89,11 +106,18 @@ BlockOrRecordID = 0; while (!Stream.AtEndOfStream()) { - unsigned Code = Stream.ReadCode(); + unsigned Code; + if (Expected Res = Stream.ReadCode()) + Code = Res.get(); + else + return llvm::errorToErrorCode(Res.takeError()); switch ((llvm::bitc::FixedAbbrevIDs)Code) { case llvm::bitc::ENTER_SUBBLOCK: - BlockOrRecordID = Stream.ReadSubBlockID(); + if (Expected Res = Stream.ReadSubBlockID()) + BlockOrRecordID = Res.get(); + else + return llvm::errorToErrorCode(Res.takeError()); return Cursor::BlockBegin; case llvm::bitc::END_BLOCK: @@ -102,7 +126,8 @@ return Cursor::BlockEnd; case llvm::bitc::DEFINE_ABBREV: - Stream.ReadAbbrevRecord(); + if (llvm::Error Err = Stream.ReadAbbrevRecord()) + return llvm::errorToErrorCode(std::move(Err)); continue; case llvm::bitc::UNABBREV_RECORD: @@ -145,7 +170,10 @@ } SmallVector Record; - unsigned RecordID = Stream.readRecord(BlockOrCode, Record); + Expected MaybeRecordID = Stream.readRecord(BlockOrCode, Record); + if (!MaybeRecordID) + return errorToErrorCode(MaybeRecordID.takeError()); + unsigned RecordID = MaybeRecordID.get(); if (RecordID == RECORD_VERSION) { if (Record.size() < 1) @@ -193,7 +221,10 @@ // Read the record. Record.clear(); StringRef Blob; - unsigned RecID = Stream.readRecord(BlockOrCode, Record, &Blob); + Expected MaybeRecID = Stream.readRecord(BlockOrCode, Record, &Blob); + if (!MaybeRecID) + return errorToErrorCode(MaybeRecID.takeError()); + unsigned RecID = MaybeRecID.get(); if (RecID < serialized_diags::RECORD_FIRST || RecID > serialized_diags::RECORD_LAST) diff --git a/clang/lib/Frontend/TestModuleFileExtension.cpp b/clang/lib/Frontend/TestModuleFileExtension.cpp --- a/clang/lib/Frontend/TestModuleFileExtension.cpp +++ b/clang/lib/Frontend/TestModuleFileExtension.cpp @@ -48,7 +48,11 @@ // Read the extension block. SmallVector Record; while (true) { - llvm::BitstreamEntry Entry = Stream.advanceSkippingSubblocks(); + llvm::Expected MaybeEntry = Stream.advanceSkippingSubblocks(); + if (!MaybeEntry) + (void)MaybeEntry.takeError(); + llvm::BitstreamEntry Entry = MaybeEntry.get(); + switch (Entry.Kind) { case llvm::BitstreamEntry::SubBlock: case llvm::BitstreamEntry::EndBlock: @@ -61,8 +65,10 @@ Record.clear(); StringRef Blob; - unsigned RecCode = Stream.readRecord(Entry.ID, Record, &Blob); - switch (RecCode) { + Expected MaybeRecCode = Stream.readRecord(Entry.ID, Record, &Blob); + if (!MaybeRecCode) + fprintf(stderr, "Failed reading rec code: %s\n", toString(MaybeRecCode.takeError()).c_str()); + switch (MaybeRecCode.get()) { case FIRST_EXTENSION_RECORD_ID: { StringRef Message = Blob.substr(0, Record[0]); fprintf(stderr, "Read extension block message: %s\n", diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -1148,12 +1148,26 @@ assert(Offset != 0); SavedStreamPosition SavedPosition(Cursor); - Cursor.JumpToBit(Offset); + if (llvm::Error Err = Cursor.JumpToBit(Offset)) { + Error(std::move(Err)); + return true; + } RecordData Record; StringRef Blob; - unsigned Code = Cursor.ReadCode(); - unsigned RecCode = Cursor.readRecord(Code, Record, &Blob); + Expected MaybeCode = Cursor.ReadCode(); + if (!MaybeCode) { + Error(MaybeCode.takeError()); + return true; + } + unsigned Code = MaybeCode.get(); + + Expected MaybeRecCode = Cursor.readRecord(Code, Record, &Blob); + if (!MaybeRecCode) { + Error(MaybeRecCode.takeError()); + return true; + } + unsigned RecCode = MaybeRecCode.get(); if (RecCode != DECL_CONTEXT_LEXICAL) { Error("Expected lexical block"); return true; @@ -1184,12 +1198,26 @@ assert(Offset != 0); SavedStreamPosition SavedPosition(Cursor); - Cursor.JumpToBit(Offset); + if (llvm::Error Err = Cursor.JumpToBit(Offset)) { + Error(std::move(Err)); + return true; + } RecordData Record; StringRef Blob; - unsigned Code = Cursor.ReadCode(); - unsigned RecCode = Cursor.readRecord(Code, Record, &Blob); + Expected MaybeCode = Cursor.ReadCode(); + if (!MaybeCode) { + Error(MaybeCode.takeError()); + return true; + } + unsigned Code = MaybeCode.get(); + + Expected MaybeRecCode = Cursor.readRecord(Code, Record, &Blob); + if (!MaybeRecCode) { + Error(MaybeRecCode.takeError()); + return true; + } + unsigned RecCode = MaybeRecCode.get(); if (RecCode != DECL_CONTEXT_VISIBLE) { Error("Expected visible lookup table block"); return true; @@ -1219,6 +1247,10 @@ Diag(DiagID) << Arg1 << Arg2; } +void ASTReader::Error(llvm::Error &&Err) const { + Error(toString(std::move(Err))); +} + //===----------------------------------------------------------------------===// // Source Manager Deserialization //===----------------------------------------------------------------------===// @@ -1295,7 +1327,12 @@ RecordData Record; while (true) { - llvm::BitstreamEntry E = SLocEntryCursor.advanceSkippingSubblocks(); + Expected MaybeE = SLocEntryCursor.advanceSkippingSubblocks(); + if (!MaybeE) { + Error(MaybeE.takeError()); + return true; + } + llvm::BitstreamEntry E = MaybeE.get(); switch (E.Kind) { case llvm::BitstreamEntry::SubBlock: // Handled for us already. @@ -1312,7 +1349,12 @@ // Read a record. Record.clear(); StringRef Blob; - switch (SLocEntryCursor.readRecord(E.ID, Record, &Blob)) { + Expected MaybeRecord = SLocEntryCursor.readRecord(E.ID, Record, &Blob); + if (!MaybeRecord) { + Error(MaybeRecord.takeError()); + return true; + } + switch (MaybeRecord.get()) { default: // Default behavior: ignore. break; @@ -1376,8 +1418,19 @@ StringRef Name) -> std::unique_ptr { RecordData Record; StringRef Blob; - unsigned Code = SLocEntryCursor.ReadCode(); - unsigned RecCode = SLocEntryCursor.readRecord(Code, Record, &Blob); + Expected MaybeCode = SLocEntryCursor.ReadCode(); + if (!MaybeCode) { + Error(MaybeCode.takeError()); + return nullptr; + } + unsigned Code = MaybeCode.get(); + + Expected MaybeRecCode = SLocEntryCursor.readRecord(Code, Record, &Blob); + if (!MaybeRecCode) { + Error(MaybeRecCode.takeError()); + return nullptr; + } + unsigned RecCode = MaybeRecCode.get(); if (RecCode == SM_SLOC_BUFFER_BLOB_COMPRESSED) { if (!llvm::zlib::isAvailable()) { @@ -1401,12 +1454,22 @@ }; ModuleFile *F = GlobalSLocEntryMap.find(-ID)->second; - F->SLocEntryCursor.JumpToBit(F->SLocEntryOffsets[ID - F->SLocEntryBaseID]); + if (llvm::Error Err = F->SLocEntryCursor.JumpToBit(F->SLocEntryOffsets[ID - F->SLocEntryBaseID])) { + Error(std::move(Err)); + return true; + } + BitstreamCursor &SLocEntryCursor = F->SLocEntryCursor; unsigned BaseOffset = F->SLocEntryBaseOffset; ++NumSLocEntriesRead; - llvm::BitstreamEntry Entry = SLocEntryCursor.advance(); + Expected MaybeEntry = SLocEntryCursor.advance(); + if (!MaybeEntry) { + Error(MaybeEntry.takeError()); + return true; + } + llvm::BitstreamEntry Entry = MaybeEntry.get(); + if (Entry.Kind != llvm::BitstreamEntry::Record) { Error("incorrectly-formatted source location entry in AST file"); return true; @@ -1414,7 +1477,12 @@ RecordData Record; StringRef Blob; - switch (SLocEntryCursor.readRecord(Entry.ID, Record, &Blob)) { + Expected MaybeSLOC = SLocEntryCursor.readRecord(Entry.ID, Record, &Blob); + if (!MaybeSLOC) { + Error(MaybeSLOC.takeError()); + return true; + } + switch (MaybeSLOC.get()) { default: Error("incorrectly-formatted source location entry in AST file"); return true; @@ -1538,23 +1606,34 @@ return F->ImportedBy[0]->FirstLoc; } -/// ReadBlockAbbrevs - Enter a subblock of the specified BlockID with the -/// specified cursor. Read the abbreviations that are at the top of the block -/// and then leave the cursor pointing into the block. +/// Enter a subblock of the specified BlockID with the specified cursor. Read +/// the abbreviations that are at the top of the block and then leave the cursor +/// pointing into the block. bool ASTReader::ReadBlockAbbrevs(BitstreamCursor &Cursor, unsigned BlockID) { if (Cursor.EnterSubBlock(BlockID)) return true; while (true) { uint64_t Offset = Cursor.GetCurrentBitNo(); - unsigned Code = Cursor.ReadCode(); + Expected MaybeCode = Cursor.ReadCode(); + if (!MaybeCode) { + // FIXME this drops errors on the floor. + return true; + } + unsigned Code = MaybeCode.get(); // We expect all abbrevs to be at the start of the block. if (Code != llvm::bitc::DEFINE_ABBREV) { - Cursor.JumpToBit(Offset); + if (llvm::Error Err = Cursor.JumpToBit(Offset)) { + // FIXME this drops errors on the floor. + return true; + } return false; } - Cursor.ReadAbbrevRecord(); + if (llvm::Error Err = Cursor.ReadAbbrevRecord()) { + // FIXME this drops errors on the floor. + return true; + } } } @@ -1578,7 +1657,10 @@ // after reading this macro. SavedStreamPosition SavedPosition(Stream); - Stream.JumpToBit(Offset); + if (llvm::Error Err = Stream.JumpToBit(Offset)) { + // FIXME this drops errors on the floor. + return nullptr; + } RecordData Record; SmallVector MacroParams; MacroInfo *Macro = nullptr; @@ -1588,7 +1670,12 @@ // pop it (removing all the abbreviations from the cursor) since we want to // be able to reseek within the block and read entries. unsigned Flags = BitstreamCursor::AF_DontPopBlockAtEnd; - llvm::BitstreamEntry Entry = Stream.advanceSkippingSubblocks(Flags); + Expected MaybeEntry = Stream.advanceSkippingSubblocks(Flags); + if (!MaybeEntry) { + Error(MaybeEntry.takeError()); + return Macro; + } + llvm::BitstreamEntry Entry = MaybeEntry.get(); switch (Entry.Kind) { case llvm::BitstreamEntry::SubBlock: // Handled for us already. @@ -1604,8 +1691,13 @@ // Read a record. Record.clear(); - PreprocessorRecordTypes RecType = - (PreprocessorRecordTypes)Stream.readRecord(Entry.ID, Record); + PreprocessorRecordTypes RecType; + if (Expected MaybeRecType = Stream.readRecord(Entry.ID, Record)) + RecType = (PreprocessorRecordTypes)MaybeRecType.get(); + else { + Error(MaybeRecType.takeError()); + return Macro; + } switch (RecType) { case PP_MODULE_MACRO: case PP_MACRO_DIRECTIVE_HISTORY: @@ -1828,11 +1920,19 @@ continue; BitstreamCursor Cursor = MacroCursor; - Cursor.JumpToBit(I.MacroStartOffset); + if (llvm::Error Err = Cursor.JumpToBit(I.MacroStartOffset)) { + Error(std::move(Err)); + return; + } RecordData Record; while (true) { - llvm::BitstreamEntry E = Cursor.advanceSkippingSubblocks(); + Expected MaybeE = Cursor.advanceSkippingSubblocks(); + if (!MaybeE) { + Error(MaybeE.takeError()); + return; + } + llvm::BitstreamEntry E = MaybeE.get(); switch (E.Kind) { case llvm::BitstreamEntry::SubBlock: // Handled for us already. @@ -1842,9 +1942,14 @@ case llvm::BitstreamEntry::EndBlock: goto NextCursor; - case llvm::BitstreamEntry::Record: + case llvm::BitstreamEntry::Record: { Record.clear(); - switch (Cursor.readRecord(E.ID, Record)) { + Expected MaybeRecord = Cursor.readRecord(E.ID, Record); + if (!MaybeRecord) { + Error(MaybeRecord.takeError()); + return; + } + switch (MaybeRecord.get()) { default: // Default behavior: ignore. break; @@ -1862,6 +1967,7 @@ } break; } + } } NextCursor: ; } @@ -1962,7 +2068,10 @@ BitstreamCursor &Cursor = M.MacroCursor; SavedStreamPosition SavedPosition(Cursor); - Cursor.JumpToBit(PMInfo.MacroDirectivesOffset); + if (llvm::Error Err = Cursor.JumpToBit(PMInfo.MacroDirectivesOffset)) { + Error(std::move(Err)); + return; + } struct ModuleMacroRecord { SubmoduleID SubModID; @@ -1976,15 +2085,26 @@ // macro histroy. RecordData Record; while (true) { - llvm::BitstreamEntry Entry = + Expected MaybeEntry = Cursor.advance(BitstreamCursor::AF_DontPopBlockAtEnd); + if (!MaybeEntry) { + Error(MaybeEntry.takeError()); + return; + } + llvm::BitstreamEntry Entry = MaybeEntry.get(); + if (Entry.Kind != llvm::BitstreamEntry::Record) { Error("malformed block record in AST file"); return; } Record.clear(); - switch ((PreprocessorRecordTypes)Cursor.readRecord(Entry.ID, Record)) { + Expected MaybePP = Cursor.readRecord(Entry.ID, Record); + if (!MaybePP) { + Error(MaybePP.takeError()); + return; + } + switch ((PreprocessorRecordTypes)MaybePP.get()) { case PP_MACRO_DIRECTIVE_HISTORY: break; @@ -2070,16 +2190,23 @@ // Go find this input file. BitstreamCursor &Cursor = F.InputFilesCursor; SavedStreamPosition SavedPosition(Cursor); - Cursor.JumpToBit(F.InputFileOffsets[ID-1]); + if (llvm::Error Err = Cursor.JumpToBit(F.InputFileOffsets[ID-1])) { + // FIXME this drops errors on the floor. + } - unsigned Code = Cursor.ReadCode(); + Expected MaybeCode = Cursor.ReadCode(); + if (!MaybeCode) { + // FIXME this drops errors on the floor. + } + unsigned Code = MaybeCode.get(); RecordData Record; StringRef Blob; - unsigned Result = Cursor.readRecord(Code, Record, &Blob); - assert(static_cast(Result) == INPUT_FILE && - "invalid record type for input file"); - (void)Result; + if (Expected Maybe = Cursor.readRecord(Code, Record, &Blob)) + assert(static_cast(Maybe.get()) == INPUT_FILE && "invalid record type for input file"); + else { + // FIXME this drops errors on the floor. + } assert(Record[0] == ID && "Bogus stored ID or offset"); InputFileInfo R; @@ -2109,7 +2236,9 @@ // Go find this input file. BitstreamCursor &Cursor = F.InputFilesCursor; SavedStreamPosition SavedPosition(Cursor); - Cursor.JumpToBit(F.InputFileOffsets[ID-1]); + if (llvm::Error Err = Cursor.JumpToBit(F.InputFileOffsets[ID-1])) { + // FIXME this drops errors on the floor. + } InputFileInfo FI = readInputFileInfo(F, ID); off_t StoredSize = FI.StoredSize; @@ -2265,7 +2394,12 @@ RecordData Record; ASTReadResult Result = Success; while (true) { - llvm::BitstreamEntry Entry = Stream.advance(); + Expected MaybeEntry = Stream.advance(); + if (!MaybeEntry) { + // FIXME this drops errors on the floor. + return Failure; + } + llvm::BitstreamEntry Entry = MaybeEntry.get(); switch (Entry.Kind) { case llvm::BitstreamEntry::Error: @@ -2282,7 +2416,12 @@ // Read and process a record. Record.clear(); - switch ((OptionsRecordTypes)Stream.readRecord(Entry.ID, Record)) { + Expected MaybeRecordType = Stream.readRecord(Entry.ID, Record); + if (!MaybeRecordType) { + // FIXME this drops errors on the floor. + return Failure; + } + switch ((OptionsRecordTypes)MaybeRecordType.get()) { case LANGUAGE_OPTIONS: { bool Complain = (ClientLoadCapabilities & ARR_ConfigurationMismatch) == 0; if (ParseLanguageOptions(Record, Complain, Listener, @@ -2362,7 +2501,12 @@ unsigned NumUserInputs = 0; StringRef BaseDirectoryAsWritten; while (true) { - llvm::BitstreamEntry Entry = Stream.advance(); + Expected MaybeEntry = Stream.advance(); + if (!MaybeEntry) { + Error(MaybeEntry.takeError()); + return Failure; + } + llvm::BitstreamEntry Entry = MaybeEntry.get(); switch (Entry.Kind) { case llvm::BitstreamEntry::Error: @@ -2485,7 +2629,12 @@ // Read and process a record. Record.clear(); StringRef Blob; - switch ((ControlRecordTypes)Stream.readRecord(Entry.ID, Record, &Blob)) { + Expected MaybeRecordType = Stream.readRecord(Entry.ID, Record, &Blob); + if (!MaybeRecordType) { + Error(MaybeRecordType.takeError()); + return Failure; + } + switch ((ControlRecordTypes)MaybeRecordType.get()) { case METADATA: { if (Record[0] != VERSION_MAJOR && !DisableValidation) { if ((ClientLoadCapabilities & ARR_VersionMismatch) == 0) @@ -2690,7 +2839,12 @@ // Read all of the records and blocks for the AST file. RecordData Record; while (true) { - llvm::BitstreamEntry Entry = Stream.advance(); + Expected MaybeEntry = Stream.advance(); + if (!MaybeEntry) { + Error(MaybeEntry.takeError()); + return Failure; + } + llvm::BitstreamEntry Entry = MaybeEntry.get(); switch (Entry.Kind) { case llvm::BitstreamEntry::Error: @@ -2794,8 +2948,12 @@ // Read and process a record. Record.clear(); StringRef Blob; - auto RecordType = - (ASTRecordTypes)Stream.readRecord(Entry.ID, Record, &Blob); + Expected MaybeRecordType = Stream.readRecord(Entry.ID, Record, &Blob); + if (!MaybeRecordType) { + Error(MaybeRecordType.takeError()); + return Failure; + } + ASTRecordTypes RecordType = (ASTRecordTypes)MaybeRecordType.get(); // If we're not loading an AST context, we don't care about most records. if (!ContextObj) { @@ -3814,8 +3972,8 @@ TriedLoadingGlobalIndex = true; StringRef ModuleCachePath = getPreprocessor().getHeaderSearchInfo().getModuleCachePath(); - std::pair Result - = GlobalModuleIndex::readIndex(ModuleCachePath); + std::pair Result = GlobalModuleIndex::readIndex(ModuleCachePath); + // FIXME this drops errors on the floor. if (!Result.first) return true; @@ -3846,7 +4004,13 @@ /// true on failure. static bool SkipCursorToBlock(BitstreamCursor &Cursor, unsigned BlockID) { while (true) { - llvm::BitstreamEntry Entry = Cursor.advance(); + Expected MaybeEntry = Cursor.advance(); + if (!MaybeEntry) { + // FIXME this drops errors on the floor. + return true; + } + llvm::BitstreamEntry Entry = MaybeEntry.get(); + switch (Entry.Kind) { case llvm::BitstreamEntry::Error: case llvm::BitstreamEntry::EndBlock: @@ -3854,8 +4018,12 @@ case llvm::BitstreamEntry::Record: // Ignore top-level records. - Cursor.skipRecord(Entry.ID); - break; + if (Expected Skipped = Cursor.skipRecord(Entry.ID)) + break; + else { + // FIXME this drops errors on the floor. + return true; + } case llvm::BitstreamEntry::SubBlock: if (Entry.ID == BlockID) { @@ -4108,13 +4276,18 @@ static ASTFileSignature readASTFileSignature(StringRef PCH); -/// Whether \p Stream starts with the AST/PCH file magic number 'CPCH'. -static bool startsWithASTFileMagic(BitstreamCursor &Stream) { - return Stream.canSkipToPos(4) && - Stream.Read(8) == 'C' && - Stream.Read(8) == 'P' && - Stream.Read(8) == 'C' && - Stream.Read(8) == 'H'; +/// Whether \p Stream doesn't start with the AST/PCH file magic number 'CPCH'. +static llvm::Error doesntStartWithASTFileMagic(BitstreamCursor &Stream) { + // FIXME checking magic headers is done in other places such as SerializedDiagnosticReader and GlobalModuleIndex, but error handling isn't always done the same. Unify it all with a helper. + if (!Stream.canSkipToPos(4)) + return llvm::createStringError(std::errc::illegal_byte_sequence, "file too small to contain AST file magic"); + for (unsigned C : {'C','P','C','H'}) + if (Expected Res = Stream.Read(8)) { + if (Res.get() != C) + return llvm::createStringError(std::errc::illegal_byte_sequence, "file doesn't start with AST file magic"); + } else + return Res.takeError(); + return llvm::Error::success(); } static unsigned moduleKindForDiagnostic(ModuleKind Kind) { @@ -4201,16 +4374,20 @@ F.SizeInBits = F.Buffer->getBufferSize() * 8; // Sniff for the signature. - if (!startsWithASTFileMagic(Stream)) { - Diag(diag::err_module_file_invalid) << moduleKindForDiagnostic(Type) - << FileName; + if (llvm::Error Err = doesntStartWithASTFileMagic(Stream)) { + Diag(diag::err_module_file_invalid) << moduleKindForDiagnostic(Type) << FileName << std::move(Err); return Failure; } // This is used for compatibility with older PCH formats. bool HaveReadControlBlock = false; while (true) { - llvm::BitstreamEntry Entry = Stream.advance(); + Expected MaybeEntry = Stream.advance(); + if (!MaybeEntry) { + Error(MaybeEntry.takeError()); + return Failure; + } + llvm::BitstreamEntry Entry = MaybeEntry.get(); switch (Entry.Kind) { case llvm::BitstreamEntry::Error: @@ -4342,8 +4519,10 @@ BitstreamCursor Stream(StreamData); // Sniff for the signature. - if (!startsWithASTFileMagic(Stream)) + if (llvm::Error Err = doesntStartWithASTFileMagic(Stream)) { + // FIXME this drops the error on the floor. return Failure; + } // Scan for the UNHASHED_CONTROL_BLOCK_ID block. if (SkipCursorToBlock(Stream, UNHASHED_CONTROL_BLOCK_ID)) @@ -4353,7 +4532,12 @@ RecordData Record; ASTReadResult Result = Success; while (true) { - llvm::BitstreamEntry Entry = Stream.advance(); + Expected MaybeEntry = Stream.advance(); + if (!MaybeEntry) { + // FIXME this drops the error on the floor. + return Failure; + } + llvm::BitstreamEntry Entry = MaybeEntry.get(); switch (Entry.Kind) { case llvm::BitstreamEntry::Error: @@ -4370,8 +4554,12 @@ // Read and process a record. Record.clear(); - switch ( - (UnhashedControlBlockRecordTypes)Stream.readRecord(Entry.ID, Record)) { + Expected MaybeRecordType = Stream.readRecord(Entry.ID, Record); + if (!MaybeRecordType) { + // FIXME this drops the error. + return Failure; + } + switch ((UnhashedControlBlockRecordTypes)MaybeRecordType.get()) { case SIGNATURE: if (F) std::copy(Record.begin(), Record.end(), F->Signature.data()); @@ -4423,7 +4611,13 @@ RecordData Record; while (true) { - llvm::BitstreamEntry Entry = Stream.advance(); + Expected MaybeEntry = Stream.advance(); + if (!MaybeEntry) { + Error(MaybeEntry.takeError()); + return Failure; + } + llvm::BitstreamEntry Entry = MaybeEntry.get(); + switch (Entry.Kind) { case llvm::BitstreamEntry::SubBlock: if (Stream.SkipBlock()) @@ -4443,8 +4637,12 @@ Record.clear(); StringRef Blob; - unsigned RecCode = Stream.readRecord(Entry.ID, Record, &Blob); - switch (RecCode) { + Expected MaybeRecCode = Stream.readRecord(Entry.ID, Record, &Blob); + if (!MaybeRecCode) { + Error(MaybeRecCode.takeError()); + return Failure; + } + switch (MaybeRecCode.get()) { case EXTENSION_METADATA: { ModuleFileExtensionMetadata Metadata; if (parseModuleFileExtensionMetadata(Record, Blob, Metadata)) @@ -4615,8 +4813,10 @@ /// else returns 0. static ASTFileSignature readASTFileSignature(StringRef PCH) { BitstreamCursor Stream(PCH); - if (!startsWithASTFileMagic(Stream)) + if (llvm::Error Err = doesntStartWithASTFileMagic(Stream)) { + // FIXME this drops the error on the floor. return ASTFileSignature(); + } // Scan for the UNHASHED_CONTROL_BLOCK_ID block. if (SkipCursorToBlock(Stream, UNHASHED_CONTROL_BLOCK_ID)) @@ -4625,13 +4825,24 @@ // Scan for SIGNATURE inside the diagnostic options block. ASTReader::RecordData Record; while (true) { - llvm::BitstreamEntry Entry = Stream.advanceSkippingSubblocks(); + Expected MaybeEntry = Stream.advanceSkippingSubblocks(); + if (!MaybeEntry) { + // FIXME this drops the error on the floor. + return ASTFileSignature(); + } + llvm::BitstreamEntry Entry = MaybeEntry.get(); + if (Entry.Kind != llvm::BitstreamEntry::Record) return ASTFileSignature(); Record.clear(); StringRef Blob; - if (SIGNATURE == Stream.readRecord(Entry.ID, Record, &Blob)) + Expected MaybeRecord = Stream.readRecord(Entry.ID, Record, &Blob); + if (!MaybeRecord) { + // FIXME this drops the error on the floor. + return ASTFileSignature(); + } + if (SIGNATURE == MaybeRecord.get()) return {{{(uint32_t)Record[0], (uint32_t)Record[1], (uint32_t)Record[2], (uint32_t)Record[3], (uint32_t)Record[4]}}}; } @@ -4655,8 +4866,8 @@ BitstreamCursor Stream(PCHContainerRdr.ExtractPCH(**Buffer)); // Sniff for the signature. - if (!startsWithASTFileMagic(Stream)) { - Diags.Report(diag::err_fe_not_a_pch_file) << ASTFileName; + if (llvm::Error Err = doesntStartWithASTFileMagic(Stream)) { + Diags.Report(diag::err_fe_not_a_pch_file) << ASTFileName << std::move(Err); return std::string(); } @@ -4669,7 +4880,13 @@ // Scan for ORIGINAL_FILE inside the control block. RecordData Record; while (true) { - llvm::BitstreamEntry Entry = Stream.advanceSkippingSubblocks(); + Expected MaybeEntry = Stream.advanceSkippingSubblocks(); + if (!MaybeEntry) { + // FIXME this drops errors on the floor. + return std::string(); + } + llvm::BitstreamEntry Entry = MaybeEntry.get(); + if (Entry.Kind == llvm::BitstreamEntry::EndBlock) return std::string(); @@ -4680,7 +4897,12 @@ Record.clear(); StringRef Blob; - if (Stream.readRecord(Entry.ID, Record, &Blob) == ORIGINAL_FILE) + Expected MaybeRecord = Stream.readRecord(Entry.ID, Record, &Blob); + if (!MaybeRecord) { + // FIXME this drops the errors on the floor. + return std::string(); + } + if (ORIGINAL_FILE == MaybeRecord.get()) return Blob.str(); } } @@ -4754,8 +4976,10 @@ BitstreamCursor Stream(Bytes); // Sniff for the signature. - if (!startsWithASTFileMagic(Stream)) + if (llvm::Error Err = doesntStartWithASTFileMagic(Stream)) { + // FIXME this drops the error on the floor. return true; + } // Scan for the CONTROL_BLOCK_ID block. if (SkipCursorToBlock(Stream, CONTROL_BLOCK_ID)) @@ -4770,7 +4994,12 @@ std::string ModuleDir; bool DoneWithControlBlock = false; while (!DoneWithControlBlock) { - llvm::BitstreamEntry Entry = Stream.advance(); + Expected MaybeEntry = Stream.advance(); + if (!MaybeEntry) { + // FIXME this drops the error on the floor. + return true; + } + llvm::BitstreamEntry Entry = MaybeEntry.get(); switch (Entry.Kind) { case llvm::BitstreamEntry::SubBlock: { @@ -4816,8 +5045,12 @@ Record.clear(); StringRef Blob; - unsigned RecCode = Stream.readRecord(Entry.ID, Record, &Blob); - switch ((ControlRecordTypes)RecCode) { + Expected MaybeRecCode = Stream.readRecord(Entry.ID, Record, &Blob); + if (!MaybeRecCode) { + // FIXME this drops the error. + return Failure; + } + switch ((ControlRecordTypes)MaybeRecCode.get()) { case METADATA: if (Record[0] != VERSION_MAJOR) return true; @@ -4854,13 +5087,24 @@ BitstreamCursor &Cursor = InputFilesCursor; SavedStreamPosition SavedPosition(Cursor); - Cursor.JumpToBit(InputFileOffs[I]); + if (llvm::Error Err = Cursor.JumpToBit(InputFileOffs[I])) { + // FIXME this drops errors on the floor. + } + + Expected MaybeCode = Cursor.ReadCode(); + if (!MaybeCode) { + // FIXME this drops errors on the floor. + } + unsigned Code = MaybeCode.get(); - unsigned Code = Cursor.ReadCode(); RecordData Record; StringRef Blob; bool shouldContinue = false; - switch ((InputFileRecordTypes)Cursor.readRecord(Code, Record, &Blob)) { + Expected MaybeRecordType = Cursor.readRecord(Code, Record, &Blob); + if (!MaybeRecordType) { + // FIXME this drops errors on the floor. + } + switch ((InputFileRecordTypes)MaybeRecordType.get()) { case INPUT_FILE: bool Overridden = static_cast(Record[3]); std::string Filename = Blob; @@ -4903,7 +5147,12 @@ while (!SkipCursorToBlock(Stream, EXTENSION_BLOCK_ID)) { bool DoneWithExtensionBlock = false; while (!DoneWithExtensionBlock) { - llvm::BitstreamEntry Entry = Stream.advance(); + Expected MaybeEntry = Stream.advance(); + if (!MaybeEntry) { + // FIXME this drops the error. + return true; + } + llvm::BitstreamEntry Entry = MaybeEntry.get(); switch (Entry.Kind) { case llvm::BitstreamEntry::SubBlock: @@ -4925,8 +5174,12 @@ Record.clear(); StringRef Blob; - unsigned RecCode = Stream.readRecord(Entry.ID, Record, &Blob); - switch (RecCode) { + Expected MaybeRecCode = Stream.readRecord(Entry.ID, Record, &Blob); + if (!MaybeRecCode) { + // FIXME this drops the error. + return true; + } + switch (MaybeRecCode.get()) { case EXTENSION_METADATA: { ModuleFileExtensionMetadata Metadata; if (parseModuleFileExtensionMetadata(Record, Blob, Metadata)) @@ -4978,7 +5231,12 @@ Module *CurrentModule = nullptr; RecordData Record; while (true) { - llvm::BitstreamEntry Entry = F.Stream.advanceSkippingSubblocks(); + Expected MaybeEntry = F.Stream.advanceSkippingSubblocks(); + if (!MaybeEntry) { + Error(MaybeEntry.takeError()); + return Failure; + } + llvm::BitstreamEntry Entry = MaybeEntry.get(); switch (Entry.Kind) { case llvm::BitstreamEntry::SubBlock: // Handled for us already. @@ -4995,7 +5253,12 @@ // Read a record. StringRef Blob; Record.clear(); - auto Kind = F.Stream.readRecord(Entry.ID, Record, &Blob); + Expected MaybeKind = F.Stream.readRecord(Entry.ID, Record, &Blob); + if (!MaybeKind) { + Error(MaybeKind.takeError()); + return Failure; + } + unsigned Kind = MaybeKind.get(); if ((Kind == SUBMODULE_METADATA) != First) { Error("submodule metadata record should be at beginning of block"); @@ -5472,10 +5735,18 @@ } SavedStreamPosition SavedPosition(M.PreprocessorDetailCursor); - M.PreprocessorDetailCursor.JumpToBit(PPOffs.BitOffset); + if (llvm::Error Err = M.PreprocessorDetailCursor.JumpToBit(PPOffs.BitOffset)) { + Error(std::move(Err)); + return nullptr; + } - llvm::BitstreamEntry Entry = - M.PreprocessorDetailCursor.advance(BitstreamCursor::AF_DontPopBlockAtEnd); + Expected MaybeEntry = M.PreprocessorDetailCursor.advance(BitstreamCursor::AF_DontPopBlockAtEnd); + if (!MaybeEntry) { + Error(MaybeEntry.takeError()); + return nullptr; + } + llvm::BitstreamEntry Entry = MaybeEntry.get(); + if (Entry.Kind != llvm::BitstreamEntry::Record) return nullptr; @@ -5485,10 +5756,12 @@ PreprocessingRecord &PPRec = *PP.getPreprocessingRecord(); StringRef Blob; RecordData Record; - PreprocessorDetailRecordTypes RecType = - (PreprocessorDetailRecordTypes)M.PreprocessorDetailCursor.readRecord( - Entry.ID, Record, &Blob); - switch (RecType) { + Expected MaybeRecType = M.PreprocessorDetailCursor.readRecord(Entry.ID, Record, &Blob); + if (!MaybeRecType) { + Error(MaybeRecType.takeError()); + return nullptr; + } + switch ((PreprocessorDetailRecordTypes)MaybeRecType.get()) { case PPD_MACRO_EXPANSION: { bool isBuiltin = Record[0]; IdentifierInfo *Name = nullptr; @@ -5897,10 +6170,24 @@ Deserializing AType(this); unsigned Idx = 0; - DeclsCursor.JumpToBit(Loc.Offset); + if (llvm::Error Err = DeclsCursor.JumpToBit(Loc.Offset)) { + Error(std::move(Err)); + return QualType(); + } RecordData Record; - unsigned Code = DeclsCursor.ReadCode(); - switch ((TypeCode)DeclsCursor.readRecord(Code, Record)) { + Expected MaybeCode = DeclsCursor.ReadCode(); + if (!MaybeCode) { + Error(MaybeCode.takeError()); + return QualType(); + } + unsigned Code = MaybeCode.get(); + + Expected MaybeTypeCode = DeclsCursor.readRecord(Code, Record); + if (!MaybeTypeCode) { + Error(MaybeTypeCode.takeError()); + return QualType(); + } + switch ((TypeCode)MaybeTypeCode.get()) { case TYPE_EXT_QUAL: { if (Record.size() != 2) { Error("Incorrect encoding of extended qualifier type"); @@ -7205,13 +7492,26 @@ RecordLocation Loc = getLocalBitOffset(Offset); BitstreamCursor &Cursor = Loc.F->DeclsCursor; SavedStreamPosition SavedPosition(Cursor); - Cursor.JumpToBit(Loc.Offset); + if (llvm::Error Err = Cursor.JumpToBit(Loc.Offset)) { + Error(std::move(Err)); + return nullptr; + } ReadingKindTracker ReadingKind(Read_Decl, *this); RecordData Record; - unsigned Code = Cursor.ReadCode(); - unsigned RecCode = Cursor.readRecord(Code, Record); - if (RecCode != DECL_CXX_CTOR_INITIALIZERS) { + Expected MaybeCode = Cursor.ReadCode(); + if (!MaybeCode) { + Error(MaybeCode.takeError()); + return nullptr; + } + unsigned Code = MaybeCode.get(); + + Expected MaybeRecCode = Cursor.readRecord(Code, Record); + if (!MaybeRecCode) { + Error(MaybeRecCode.takeError()); + return nullptr; + } + if (MaybeRecCode.get() != DECL_CXX_CTOR_INITIALIZERS) { Error("malformed AST file: missing C++ ctor initializers"); return nullptr; } @@ -7227,11 +7527,27 @@ RecordLocation Loc = getLocalBitOffset(Offset); BitstreamCursor &Cursor = Loc.F->DeclsCursor; SavedStreamPosition SavedPosition(Cursor); - Cursor.JumpToBit(Loc.Offset); + if (llvm::Error Err = Cursor.JumpToBit(Loc.Offset)) { + Error(std::move(Err)); + return nullptr; + } ReadingKindTracker ReadingKind(Read_Decl, *this); RecordData Record; - unsigned Code = Cursor.ReadCode(); - unsigned RecCode = Cursor.readRecord(Code, Record); + + Expected MaybeCode = Cursor.ReadCode(); + if (!MaybeCode) { + Error(MaybeCode.takeError()); + return nullptr; + } + unsigned Code = MaybeCode.get(); + + Expected MaybeRecCode = Cursor.readRecord(Code, Record); + if (!MaybeRecCode) { + Error(MaybeCode.takeError()); + return nullptr; + } + unsigned RecCode = MaybeRecCode.get(); + if (RecCode != DECL_CXX_BASE_SPECIFIERS) { Error("malformed AST file: missing C++ base specifiers"); return nullptr; @@ -7439,7 +7755,10 @@ // Offset here is a global offset across the entire chain. RecordLocation Loc = getLocalBitOffset(Offset); - Loc.F->DeclsCursor.JumpToBit(Loc.Offset); + if (llvm::Error Err = Loc.F->DeclsCursor.JumpToBit(Loc.Offset)) { + Error(std::move(Err)); + return nullptr; + } assert(NumCurrentElementsDeserializing == 0 && "should not be called while already deserializing"); Deserializing D(this); @@ -9269,8 +9588,12 @@ RecordData Record; while (true) { - llvm::BitstreamEntry Entry = - Cursor.advanceSkippingSubblocks(BitstreamCursor::AF_DontPopBlockAtEnd); + Expected MaybeEntry = Cursor.advanceSkippingSubblocks(BitstreamCursor::AF_DontPopBlockAtEnd); + if (!MaybeEntry) { + Error(MaybeEntry.takeError()); + return; + } + llvm::BitstreamEntry Entry = MaybeEntry.get(); switch (Entry.Kind) { case llvm::BitstreamEntry::SubBlock: // Handled for us already. @@ -9286,7 +9609,12 @@ // Read a record. Record.clear(); - switch ((CommentRecordTypes)Cursor.readRecord(Entry.ID, Record)) { + Expected MaybeComment = Cursor.readRecord(Entry.ID, Record); + if (!MaybeComment) { + Error(MaybeComment.takeError()); + return; + } + switch ((CommentRecordTypes)MaybeComment.get()) { case COMMENTS_RAW_COMMENT: { unsigned Idx = 0; SourceRange SR = ReadSourceRange(F, Record, Idx); @@ -11756,8 +12084,7 @@ return SemaObj ? SemaObj->IdResolver : DummyIdResolver; } -unsigned ASTRecordReader::readRecord(llvm::BitstreamCursor &Cursor, - unsigned AbbrevID) { +Expected ASTRecordReader::readRecord(llvm::BitstreamCursor &Cursor, unsigned AbbrevID) { Idx = 0; Record.clear(); return Cursor.readRecord(AbbrevID, Record); diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp --- a/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/clang/lib/Serialization/ASTReaderDecl.cpp @@ -3679,14 +3679,25 @@ // Note that we are loading a declaration record. Deserializing ADecl(this); - DeclsCursor.JumpToBit(Loc.Offset); + auto Fail = [] (const char *what, llvm::Error &&Err) { + llvm::report_fatal_error(Twine("ASTReader::ReadDeclRecord failed ") + what + ": " + toString(std::move(Err))); + }; + + if (llvm::Error JumpFailed = DeclsCursor.JumpToBit(Loc.Offset)) + Fail("jumping", std::move(JumpFailed)); ASTRecordReader Record(*this, *Loc.F); ASTDeclReader Reader(*this, Record, Loc, ID, DeclLoc); - unsigned Code = DeclsCursor.ReadCode(); + Expected MaybeCode = DeclsCursor.ReadCode(); + if (!MaybeCode) + Fail("reading code", MaybeCode.takeError()); + unsigned Code = MaybeCode.get(); ASTContext &Context = getContext(); Decl *D = nullptr; - switch ((DeclCode)Record.readRecord(DeclsCursor, Code)) { + Expected MaybeDeclCode = Record.readRecord(DeclsCursor, Code); + if (!MaybeDeclCode) + llvm::report_fatal_error("ASTReader::ReadDeclRecord failed reading decl code: " + toString(MaybeDeclCode.takeError())); + switch ((DeclCode)MaybeDeclCode.get()) { case DECL_CONTEXT_LEXICAL: case DECL_CONTEXT_VISIBLE: llvm_unreachable("Record cannot be de-serialized with ReadDeclRecord"); @@ -4025,12 +4036,18 @@ uint64_t Offset = FileAndOffset.second; llvm::BitstreamCursor &Cursor = F->DeclsCursor; SavedStreamPosition SavedPosition(Cursor); - Cursor.JumpToBit(Offset); - unsigned Code = Cursor.ReadCode(); + if (llvm::Error JumpFailed = Cursor.JumpToBit(Offset)) + // FIXME don't do a fatal error. + llvm::report_fatal_error("ASTReader::loadDeclUpdateRecords failed jumping: " + toString(std::move(JumpFailed))); + Expected MaybeCode = Cursor.ReadCode(); + if (!MaybeCode) + llvm::report_fatal_error("ASTReader::loadDeclUpdateRecords failed reading code: " + toString(MaybeCode.takeError())); + unsigned Code = MaybeCode.get(); ASTRecordReader Record(*this, *F); - unsigned RecCode = Record.readRecord(Cursor, Code); - (void)RecCode; - assert(RecCode == DECL_UPDATES && "Expected DECL_UPDATES record!"); + if (Expected MaybeRecCode = Record.readRecord(Cursor, Code)) + assert(MaybeRecCode.get() == DECL_UPDATES && "Expected DECL_UPDATES record!"); + else + llvm::report_fatal_error("ASTReader::loadDeclUpdateRecords failed reading rec code: " + toString(MaybeCode.takeError())); ASTDeclReader Reader(*this, Record, RecordLocation(F, Offset), ID, SourceLocation()); @@ -4094,13 +4111,18 @@ llvm::BitstreamCursor &Cursor = M->DeclsCursor; SavedStreamPosition SavedPosition(Cursor); - Cursor.JumpToBit(LocalOffset); + if (llvm::Error JumpFailed = Cursor.JumpToBit(LocalOffset)) + llvm::report_fatal_error("ASTReader::loadPendingDeclChain failed jumping: " + toString(std::move(JumpFailed))); RecordData Record; - unsigned Code = Cursor.ReadCode(); - unsigned RecCode = Cursor.readRecord(Code, Record); - (void)RecCode; - assert(RecCode == LOCAL_REDECLARATIONS && "expected LOCAL_REDECLARATIONS record!"); + Expected MaybeCode = Cursor.ReadCode(); + if (!MaybeCode) + llvm::report_fatal_error("ASTReader::loadPendingDeclChain failed reading code: " + toString(MaybeCode.takeError())); + unsigned Code = MaybeCode.get(); + if (Expected MaybeRecCode = Cursor.readRecord(Code, Record)) + assert(MaybeRecCode.get() == LOCAL_REDECLARATIONS && "expected LOCAL_REDECLARATIONS record!"); + else + llvm::report_fatal_error("ASTReader::loadPendingDeclChain failed reading rec code: " + toString(MaybeCode.takeError())); // FIXME: We have several different dispatches on decl kind here; maybe // we should instead generate one loop per kind and dispatch up-front? diff --git a/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp --- a/clang/lib/Serialization/ASTReaderStmt.cpp +++ b/clang/lib/Serialization/ASTReaderStmt.cpp @@ -2392,7 +2392,12 @@ Stmt::EmptyShell Empty; while (true) { - llvm::BitstreamEntry Entry = Cursor.advanceSkippingSubblocks(); + llvm::Expected MaybeEntry = Cursor.advanceSkippingSubblocks(); + if (!MaybeEntry) { + Error(toString(MaybeEntry.takeError())); + return nullptr; + } + llvm::BitstreamEntry Entry = MaybeEntry.get(); switch (Entry.Kind) { case llvm::BitstreamEntry::SubBlock: // Handled for us already. @@ -2410,7 +2415,12 @@ Stmt *S = nullptr; bool Finished = false; bool IsStmtReference = false; - switch ((StmtCode)Record.readRecord(Cursor, Entry.ID)) { + Expected MaybeStmtCode = Record.readRecord(Cursor, Entry.ID); + if (!MaybeStmtCode) { + Error(toString(MaybeStmtCode.takeError())); + return nullptr; + } + switch ((StmtCode)MaybeStmtCode.get()) { case STMT_STOP: Finished = true; break; diff --git a/clang/lib/Serialization/GlobalModuleIndex.cpp b/clang/lib/Serialization/GlobalModuleIndex.cpp --- a/clang/lib/Serialization/GlobalModuleIndex.cpp +++ b/clang/lib/Serialization/GlobalModuleIndex.cpp @@ -128,12 +128,20 @@ llvm::BitstreamCursor Cursor) : Buffer(std::move(Buffer)), IdentifierIndex(), NumIdentifierLookups(), NumIdentifierLookupHits() { + auto Fail = [&Buffer] (llvm::Error &&Err) { + report_fatal_error("Module index '" + Buffer->getBufferIdentifier() + "' failed: " + toString(std::move(Err))); + }; + llvm::TimeTraceScope TimeScope("Module LoadIndex", StringRef("")); // Read the global index. bool InGlobalIndexBlock = false; bool Done = false; while (!Done) { - llvm::BitstreamEntry Entry = Cursor.advance(); + llvm::BitstreamEntry Entry; + if (Expected Res = Cursor.advance()) + Entry = Res.get(); + else + Fail(Res.takeError()); switch (Entry.Kind) { case llvm::BitstreamEntry::Error: @@ -169,7 +177,11 @@ SmallVector Record; StringRef Blob; - switch ((IndexRecordTypes)Cursor.readRecord(Entry.ID, Record, &Blob)) { + Expected MaybeIndexRecord = Cursor.readRecord(Entry.ID, Record, &Blob); + if (!MaybeIndexRecord) + Fail(MaybeIndexRecord.takeError()); + IndexRecordTypes IndexRecord = static_cast(MaybeIndexRecord.get()); + switch (IndexRecord) { case INDEX_METADATA: // Make sure that the version matches. if (Record.size() < 1 || Record[0] != CurrentVersion) @@ -234,7 +246,7 @@ delete static_cast(IdentifierIndex); } -std::pair +std::pair GlobalModuleIndex::readIndex(StringRef Path) { // Load the index file, if it's there. llvm::SmallString<128> IndexPath; @@ -244,22 +256,22 @@ llvm::ErrorOr> BufferOrErr = llvm::MemoryBuffer::getFile(IndexPath.c_str()); if (!BufferOrErr) - return std::make_pair(nullptr, EC_NotFound); + return std::make_pair(nullptr, llvm::errorCodeToError(BufferOrErr.getError())); std::unique_ptr Buffer = std::move(BufferOrErr.get()); /// The main bitstream cursor for the main block. llvm::BitstreamCursor Cursor(*Buffer); // Sniff for the signature. - if (Cursor.Read(8) != 'B' || - Cursor.Read(8) != 'C' || - Cursor.Read(8) != 'G' || - Cursor.Read(8) != 'I') { - return std::make_pair(nullptr, EC_IOError); + for (unsigned char C : {'B', 'C', 'G', 'I'}) { + if (Expected Res = Cursor.Read(8)) { + if (Res.get() != C) + return std::make_pair(nullptr, llvm::createStringError(std::errc::illegal_byte_sequence, "expected signature BCGI")); + } else + return std::make_pair(nullptr, Res.takeError()); } - return std::make_pair(new GlobalModuleIndex(std::move(Buffer), Cursor), - EC_None); + return std::make_pair(new GlobalModuleIndex(std::move(Buffer), Cursor), llvm::Error::success()); } void @@ -438,9 +450,7 @@ : FileMgr(FileMgr), PCHContainerRdr(PCHContainerRdr) {} /// Load the contents of the given module file into the builder. - /// - /// \returns true if an error occurred, false otherwise. - bool loadModuleFile(const FileEntry *File); + llvm::Error loadModuleFile(const FileEntry *File); /// Write the index to the given bitstream. /// \returns true if an error occurred, false otherwise. @@ -511,24 +521,23 @@ }; } -bool GlobalModuleIndexBuilder::loadModuleFile(const FileEntry *File) { +llvm::Error GlobalModuleIndexBuilder::loadModuleFile(const FileEntry *File) { // Open the module file. auto Buffer = FileMgr.getBufferForFile(File, /*isVolatile=*/true); - if (!Buffer) { - return true; - } + if (!Buffer) + return llvm::createStringError(Buffer.getError(), "failed getting buffer for module file"); // Initialize the input stream llvm::BitstreamCursor InStream(PCHContainerRdr.ExtractPCH(**Buffer)); // Sniff for the signature. - if (InStream.Read(8) != 'C' || - InStream.Read(8) != 'P' || - InStream.Read(8) != 'C' || - InStream.Read(8) != 'H') { - return true; - } + for (unsigned char C : {'C','P','C','H'}) + if (Expected Res = InStream.Read(8)) { + if (Res.get() != C) + return llvm::createStringError(std::errc::illegal_byte_sequence, "expected signature CPCH"); + } else + return Res.takeError(); // Record this module file and assign it a unique ID (if it doesn't have // one already). @@ -538,7 +547,11 @@ enum { Other, ControlBlock, ASTBlock, DiagnosticOptionsBlock } State = Other; bool Done = false; while (!Done) { - llvm::BitstreamEntry Entry = InStream.advance(); + Expected MaybeEntry = InStream.advance(); + if (!MaybeEntry) + return MaybeEntry.takeError(); + llvm::BitstreamEntry Entry = MaybeEntry.get(); + switch (Entry.Kind) { case llvm::BitstreamEntry::Error: Done = true; @@ -547,8 +560,10 @@ case llvm::BitstreamEntry::Record: // In the 'other' state, just skip the record. We don't care. if (State == Other) { - InStream.skipRecord(Entry.ID); - continue; + if (llvm::Expected Skipped = InStream.skipRecord(Entry.ID)) + continue; + else + return Skipped.takeError(); } // Handle potentially-interesting records below. @@ -557,7 +572,7 @@ case llvm::BitstreamEntry::SubBlock: if (Entry.ID == CONTROL_BLOCK_ID) { if (InStream.EnterSubBlock(CONTROL_BLOCK_ID)) - return true; + return llvm::createStringError(std::errc::illegal_byte_sequence, "invalid CONTROL_BLOCK_ID sub block"); // Found the control block. State = ControlBlock; @@ -566,7 +581,7 @@ if (Entry.ID == AST_BLOCK_ID) { if (InStream.EnterSubBlock(AST_BLOCK_ID)) - return true; + return llvm::createStringError(std::errc::illegal_byte_sequence, "invalid UNHASHED_CONTROL_BLOCK_ID sub block"); // Found the AST block. State = ASTBlock; @@ -575,7 +590,7 @@ if (Entry.ID == UNHASHED_CONTROL_BLOCK_ID) { if (InStream.EnterSubBlock(UNHASHED_CONTROL_BLOCK_ID)) - return true; + return llvm::createStringError(std::errc::illegal_byte_sequence, "invalid UNHASHED_CONTROL_BLOCK_ID sub block"); // Found the Diagnostic Options block. State = DiagnosticOptionsBlock; @@ -583,7 +598,7 @@ } if (InStream.SkipBlock()) - return true; + return llvm::createStringError(std::errc::illegal_byte_sequence, "failed skipping block"); continue; @@ -595,7 +610,10 @@ // Read the given record. SmallVector Record; StringRef Blob; - unsigned Code = InStream.readRecord(Entry.ID, Record, &Blob); + Expected MaybeCode = InStream.readRecord(Entry.ID, Record, &Blob); + if (!MaybeCode) + return MaybeCode.takeError(); + unsigned Code = MaybeCode.get(); // Handle module dependencies. if (State == ControlBlock && Code == IMPORTS) { @@ -637,7 +655,7 @@ /*cacheFailure=*/false); if (!DependsOnFile) - return true; + return llvm::createStringError(std::errc::bad_file_descriptor, "imported file \"%s\" not found", ImportedFile.c_str()); // Save the information in ImportedModuleFileInfo so we can verify after // loading all pcms. @@ -682,7 +700,7 @@ // We don't care about this record. } - return false; + return llvm::Error::success(); } namespace { @@ -820,7 +838,7 @@ return false; } -GlobalModuleIndex::ErrorCode +llvm::Error GlobalModuleIndex::writeIndex(FileManager &FileMgr, const PCHContainerReader &PCHContainerRdr, StringRef Path) { @@ -833,7 +851,7 @@ llvm::LockFileManager Locked(IndexPath); switch (Locked) { case llvm::LockFileManager::LFS_Error: - return EC_IOError; + return llvm::createStringError(std::errc::io_error, "LFS error"); case llvm::LockFileManager::LFS_Owned: // We're responsible for building the index ourselves. Do so below. @@ -842,7 +860,7 @@ case llvm::LockFileManager::LFS_Shared: // Someone else is responsible for building the index. We don't care // when they finish, so we're done. - return EC_Building; + return llvm::createStringError(std::errc::device_or_resource_busy, "someone else is building the index"); } // The module index builder. @@ -859,7 +877,7 @@ // in the process of rebuilding a module. They'll rebuild the index // at the end of that translation unit, so we don't have to. if (llvm::sys::path::extension(D->path()) == ".pcm.lock") - return EC_Building; + return llvm::createStringError(std::errc::device_or_resource_busy, "someone else is building the index"); continue; } @@ -870,8 +888,8 @@ continue; // Load this module file. - if (Builder.loadModuleFile(ModuleFile)) - return EC_IOError; + if (llvm::Error Err = Builder.loadModuleFile(ModuleFile)) + return Err; } // The output buffer, into which the global index will be written. @@ -879,7 +897,7 @@ { llvm::BitstreamWriter OutputStream(OutputBuffer); if (Builder.writeIndex(OutputStream)) - return EC_IOError; + return llvm::createStringError(std::errc::io_error, "failed writing index"); } // Write the global index file to a temporary file. @@ -887,31 +905,30 @@ int TmpFD; if (llvm::sys::fs::createUniqueFile(IndexPath + "-%%%%%%%%", TmpFD, IndexTmpPath)) - return EC_IOError; + return llvm::createStringError(std::errc::io_error, "failed creating unique file"); // Open the temporary global index file for output. llvm::raw_fd_ostream Out(TmpFD, true); if (Out.has_error()) - return EC_IOError; + return llvm::createStringError(Out.error(), "failed outputting to stream"); // Write the index. Out.write(OutputBuffer.data(), OutputBuffer.size()); Out.close(); if (Out.has_error()) - return EC_IOError; + return llvm::createStringError(Out.error(), "failed writing to stream"); // Remove the old index file. It isn't relevant any more. llvm::sys::fs::remove(IndexPath); // Rename the newly-written index file to the proper name. - if (llvm::sys::fs::rename(IndexTmpPath, IndexPath)) { - // Rename failed; just remove the + if (std::error_code Err = llvm::sys::fs::rename(IndexTmpPath, IndexPath)) { + // Remove the file on failure, don't check whether removal succeeded. llvm::sys::fs::remove(IndexTmpPath); - return EC_IOError; + return llvm::createStringError(Err, "failed renaming file \"%s\" to \"%s\"", IndexTmpPath.c_str(), IndexPath.c_str()); } - // We're done. - return EC_None; + return llvm::Error::success(); } namespace { diff --git a/llvm/include/llvm/Bitcode/BitstreamReader.h b/llvm/include/llvm/Bitcode/BitstreamReader.h --- a/llvm/include/llvm/Bitcode/BitstreamReader.h +++ b/llvm/include/llvm/Bitcode/BitstreamReader.h @@ -127,7 +127,7 @@ ArrayRef getBitcodeBytes() const { return BitcodeBytes; } /// Reset the stream to the specified bit number. - void JumpToBit(uint64_t BitNo) { + Error JumpToBit(uint64_t BitNo) { size_t ByteNo = size_t(BitNo/8) & ~(sizeof(word_t)-1); unsigned WordBitNo = unsigned(BitNo & (sizeof(word_t)*8-1)); assert(canSkipToPos(ByteNo) && "Invalid location"); @@ -137,8 +137,14 @@ BitsInCurWord = 0; // Skip over any bits that are already consumed. - if (WordBitNo) - Read(WordBitNo); + if (WordBitNo) { + if (Expected Res = Read(WordBitNo)) + return Error::success(); + else + return Res.takeError(); + } + + return Error::success(); } /// Get a pointer into the bitstream at the specified byte offset. @@ -154,9 +160,9 @@ return getPointerToByte(BitNo / 8, NumBytes); } - void fillCurWord() { + Error fillCurWord() { if (NextChar >= BitcodeBytes.size()) - report_fatal_error("Unexpected end of file"); + return createStringError(std::errc::io_error, "Unexpected end of file reading %u of %u bytes", NextChar, BitcodeBytes.size()); // Read the next word from the stream. const uint8_t *NextCharPtr = BitcodeBytes.data() + NextChar; @@ -175,9 +181,10 @@ } NextChar += BytesRead; BitsInCurWord = BytesRead * 8; + return Error::success(); } - word_t Read(unsigned NumBits) { + Expected Read(unsigned NumBits) { static const unsigned BitsInWord = MaxChunkSize; assert(NumBits && NumBits <= BitsInWord && @@ -199,11 +206,12 @@ word_t R = BitsInCurWord ? CurWord : 0; unsigned BitsLeft = NumBits - BitsInCurWord; - fillCurWord(); + if (Error fillResult = fillCurWord()) + return std::move(fillResult); // If we run out of data, abort. if (BitsLeft > BitsInCurWord) - report_fatal_error("Unexpected end of file"); + return createStringError(std::errc::io_error, "Unexpected end of file reading %u of %u bits", BitsInCurWord, BitsLeft); word_t R2 = CurWord & (~word_t(0) >> (BitsInWord - BitsLeft)); @@ -217,8 +225,12 @@ return R; } - uint32_t ReadVBR(unsigned NumBits) { - uint32_t Piece = Read(NumBits); + Expected ReadVBR(unsigned NumBits) { + Expected MaybeRead = Read(NumBits); + if (!MaybeRead) + return MaybeRead; + uint32_t Piece = MaybeRead.get(); + if ((Piece & (1U << (NumBits-1))) == 0) return Piece; @@ -231,14 +243,21 @@ return Result; NextBit += NumBits-1; - Piece = Read(NumBits); + MaybeRead = Read(NumBits); + if (!MaybeRead) + return MaybeRead; + Piece = MaybeRead.get(); } } // Read a VBR that may have a value up to 64-bits in size. The chunk size of // the VBR must still be <= 32 bits though. - uint64_t ReadVBR64(unsigned NumBits) { - uint32_t Piece = Read(NumBits); + Expected ReadVBR64(unsigned NumBits) { + Expected MaybeRead = Read(NumBits); + if (!MaybeRead) + return MaybeRead; + uint32_t Piece = MaybeRead.get(); + if ((Piece & (1U << (NumBits-1))) == 0) return uint64_t(Piece); @@ -251,7 +270,10 @@ return Result; NextBit += NumBits-1; - Piece = Read(NumBits); + MaybeRead = Read(NumBits); + if (!MaybeRead) + return MaybeRead; + Piece = MaybeRead.get(); } } @@ -365,12 +387,16 @@ }; /// Advance the current bitstream, returning the next entry in the stream. - BitstreamEntry advance(unsigned Flags = 0) { + Expected advance(unsigned Flags = 0) { while (true) { if (AtEndOfStream()) return BitstreamEntry::getError(); - unsigned Code = ReadCode(); + Expected MaybeCode = ReadCode(); + if (!MaybeCode) + return MaybeCode.takeError(); + unsigned Code = MaybeCode.get(); + if (Code == bitc::END_BLOCK) { // Pop the end of the block unless Flags tells us not to. if (!(Flags & AF_DontPopBlockAtEnd) && ReadBlockEnd()) @@ -378,14 +404,19 @@ return BitstreamEntry::getEndBlock(); } - if (Code == bitc::ENTER_SUBBLOCK) - return BitstreamEntry::getSubBlock(ReadSubBlockID()); + if (Code == bitc::ENTER_SUBBLOCK) { + if (Expected MaybeSubBlock = ReadSubBlockID()) + return BitstreamEntry::getSubBlock(MaybeSubBlock.get()); + else + return MaybeSubBlock.takeError(); + } if (Code == bitc::DEFINE_ABBREV && !(Flags & AF_DontAutoprocessAbbrevs)) { // We read and accumulate abbrev's, the client can't do anything with // them anyway. - ReadAbbrevRecord(); + if (Error Err = ReadAbbrevRecord()) + return std::move(Err); continue; } @@ -395,10 +426,14 @@ /// This is a convenience function for clients that don't expect any /// subblocks. This just skips over them automatically. - BitstreamEntry advanceSkippingSubblocks(unsigned Flags = 0) { + Expected advanceSkippingSubblocks(unsigned Flags = 0) { while (true) { // If we found a normal entry, return it. - BitstreamEntry Entry = advance(Flags); + Expected MaybeEntry = advance(Flags); + if (!MaybeEntry) + return MaybeEntry; + BitstreamEntry Entry = MaybeEntry.get(); + if (Entry.Kind != BitstreamEntry::SubBlock) return Entry; @@ -408,7 +443,7 @@ } } - unsigned ReadCode() { + Expected ReadCode() { return Read(CurCodeSize); } @@ -416,18 +451,24 @@ // [ENTER_SUBBLOCK, blockid, newcodelen, , blocklen] /// Having read the ENTER_SUBBLOCK code, read the BlockID for the block. - unsigned ReadSubBlockID() { + Expected ReadSubBlockID() { return ReadVBR(bitc::BlockIDWidth); } /// Having read the ENTER_SUBBLOCK abbrevid and a BlockID, skip over the body /// of this block. If the block record is malformed, return true. - bool SkipBlock() { - // Read and ignore the codelen value. Since we are skipping this block, we - // don't care what code widths are used inside of it. - ReadVBR(bitc::CodeLenWidth); + Expected SkipBlock() { + // Read and ignore the codelen value. + if (Expected Res = ReadVBR(bitc::CodeLenWidth)) + ; // Since we are skipping this block, we don't care what code widths are used inside of it. + else + return Res.takeError(); + SkipToFourByteBoundary(); - size_t NumFourBytes = Read(bitc::BlockSizeWidth); + Expected MaybeNum = Read(bitc::BlockSizeWidth); + if (!MaybeNum) + return MaybeNum; + size_t NumFourBytes = MaybeNum.get(); // Check that the block wasn't partially defined, and that the offset isn't // bogus. @@ -435,13 +476,15 @@ if (AtEndOfStream() || !canSkipToPos(SkipTo/8)) return true; - JumpToBit(SkipTo); + if (Error Res = JumpToBit(SkipTo)) + return std::move(Res); + return false; } /// Having read the ENTER_SUBBLOCK abbrevid, enter the block, and return true /// if the block has an error. - bool EnterSubBlock(unsigned BlockID, unsigned *NumWordsP = nullptr); + Expected EnterSubBlock(unsigned BlockID, unsigned *NumWordsP = nullptr); bool ReadBlockEnd() { if (BlockScope.empty()) return true; @@ -476,22 +519,21 @@ } /// Read the current record and discard it, returning the code for the record. - unsigned skipRecord(unsigned AbbrevID); + Expected skipRecord(unsigned AbbrevID); - unsigned readRecord(unsigned AbbrevID, SmallVectorImpl &Vals, - StringRef *Blob = nullptr); + Expected readRecord(unsigned AbbrevID, SmallVectorImpl &Vals, StringRef *Blob = nullptr); //===--------------------------------------------------------------------===// // Abbrev Processing //===--------------------------------------------------------------------===// - void ReadAbbrevRecord(); + Error ReadAbbrevRecord(); /// Read and return a block info block from the bitstream. If an error was /// encountered, return None. /// /// \param ReadBlockInfoNames Whether to read block/record name information in /// the BlockInfo block. Only llvm-bcanalyzer uses this. - Optional + Expected> ReadBlockInfoBlock(bool ReadBlockInfoNames = false); /// Set the block info to be used by this BitstreamCursor to interpret diff --git a/llvm/include/llvm/Support/Error.h b/llvm/include/llvm/Support/Error.h --- a/llvm/include/llvm/Support/Error.h +++ b/llvm/include/llvm/Support/Error.h @@ -1160,7 +1160,7 @@ /// Create formatted StringError object. template -Error createStringError(std::error_code EC, char const *Fmt, +inline Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals) { std::string Buffer; raw_string_ostream Stream(Buffer); @@ -1170,6 +1170,11 @@ Error createStringError(std::error_code EC, char const *Msg); +template +inline Error createStringError(std::errc EC, char const *Fmt, const Ts &... Vals) { + return createStringError(std::make_error_code(EC), Fmt, Vals...); +} + /// This class wraps a filename and another Error. /// /// In some cases, an error needs to live along a 'source' name, in order to diff --git a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp --- a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp +++ b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp @@ -105,18 +105,22 @@ Message, make_error_code(BitcodeError::CorruptedBitcode)); } -/// Helper to read the header common to all bitcode files. -static bool hasValidBitcodeHeader(BitstreamCursor &Stream) { - // Sniff for the signature. - if (!Stream.canSkipToPos(4) || - Stream.Read(8) != 'B' || - Stream.Read(8) != 'C' || - Stream.Read(4) != 0x0 || - Stream.Read(4) != 0xC || - Stream.Read(4) != 0xE || - Stream.Read(4) != 0xD) - return false; - return true; +static Error hasInvalidBitcodeHeader(BitstreamCursor &Stream) { + if (!Stream.canSkipToPos(4)) + return createStringError(std::errc::illegal_byte_sequence, "file too small to contain bitcode header"); + for (unsigned C : {'B', 'C'}) + if (Expected Res = Stream.Read(8)) { + if (Res.get() != C) + return createStringError(std::errc::illegal_byte_sequence, "file doesn't start with bitcode header"); + } else + return Res.takeError(); + for (unsigned C : {0x0, 0xC, 0xE, 0xD}) + if (Expected Res = Stream.Read(4)) { + if (Res.get() != C) + return createStringError(std::errc::illegal_byte_sequence, "file doesn't start with bitcode header"); + } else + return Res.takeError(); + return Error::success(); } static Expected initStream(MemoryBufferRef Buffer) { @@ -133,8 +137,8 @@ return error("Invalid bitcode wrapper header"); BitstreamCursor Stream(ArrayRef(BufPtr, BufEnd)); - if (!hasValidBitcodeHeader(Stream)) - return error("Invalid bitcode signature"); + if (Error Err = hasInvalidBitcodeHeader(Stream)) + return std::move(Err); return std::move(Stream); } @@ -173,7 +177,11 @@ std::string ProducerIdentification; while (true) { - BitstreamEntry Entry = Stream.advance(); + BitstreamEntry Entry; + if (Expected Res = Stream.advance()) + Entry = Res.get(); + else + return Res.takeError(); switch (Entry.Kind) { default: @@ -188,8 +196,10 @@ // Read a record. Record.clear(); - unsigned BitCode = Stream.readRecord(Entry.ID, Record); - switch (BitCode) { + Expected MaybeBitCode = Stream.readRecord(Entry.ID, Record); + if (!MaybeBitCode) + return MaybeBitCode.takeError(); + switch (unsigned BitCode = MaybeBitCode.get()) { default: // Default behavior: reject return error("Invalid value"); case bitc::IDENTIFICATION_CODE_STRING: // IDENTIFICATION: [strchr x N] @@ -214,7 +224,12 @@ if (Stream.AtEndOfStream()) return ""; - BitstreamEntry Entry = Stream.advance(); + BitstreamEntry Entry; + if (Expected Res = Stream.advance()) + Entry = std::move(Res.get()); + else + return Res.takeError(); + switch (Entry.Kind) { case BitstreamEntry::EndBlock: case BitstreamEntry::Error: @@ -229,8 +244,10 @@ return error("Malformed block"); continue; case BitstreamEntry::Record: - Stream.skipRecord(Entry.ID); - continue; + if (auto Skipped = Stream.skipRecord(Entry.ID)) + continue; + else + return Skipped.takeError(); } } } @@ -243,7 +260,10 @@ // Read all the records for this module. while (true) { - BitstreamEntry Entry = Stream.advanceSkippingSubblocks(); + Expected MaybeEntry = Stream.advanceSkippingSubblocks(); + if (!MaybeEntry) + return MaybeEntry.takeError(); + BitstreamEntry Entry = MaybeEntry.get(); switch (Entry.Kind) { case BitstreamEntry::SubBlock: // Handled for us already. @@ -257,7 +277,10 @@ } // Read a record. - switch (Stream.readRecord(Entry.ID, Record)) { + Expected MaybeRecord = Stream.readRecord(Entry.ID, Record); + if (!MaybeRecord) + return MaybeRecord.takeError(); + switch (MaybeRecord.get()) { default: break; // Default behavior, ignore unknown content. case bitc::MODULE_CODE_SECTIONNAME: { // SECTIONNAME: [strchr x N] @@ -280,7 +303,11 @@ // We expect a number of well-defined blocks, though we don't necessarily // need to understand them all. while (true) { - BitstreamEntry Entry = Stream.advance(); + BitstreamEntry Entry; + if (Expected Res = Stream.advance()) + Entry = std::move(Res.get()); + else + return Res.takeError(); switch (Entry.Kind) { case BitstreamEntry::Error: @@ -298,8 +325,10 @@ continue; case BitstreamEntry::Record: - Stream.skipRecord(Entry.ID); - continue; + if (auto Skipped = Stream.skipRecord(Entry.ID)) + continue; + else + return Skipped.takeError(); } } } @@ -314,7 +343,10 @@ // Read all the records for this module. while (true) { - BitstreamEntry Entry = Stream.advanceSkippingSubblocks(); + Expected MaybeEntry = Stream.advanceSkippingSubblocks(); + if (!MaybeEntry) + return MaybeEntry.takeError(); + BitstreamEntry Entry = MaybeEntry.get(); switch (Entry.Kind) { case BitstreamEntry::SubBlock: // Handled for us already. @@ -328,7 +360,10 @@ } // Read a record. - switch (Stream.readRecord(Entry.ID, Record)) { + Expected MaybeRecord = Stream.readRecord(Entry.ID, Record); + if (!MaybeRecord) + return MaybeRecord.takeError(); + switch (MaybeRecord.get()) { default: break; // Default behavior, ignore unknown content. case bitc::MODULE_CODE_TRIPLE: { // TRIPLE: [strchr x N] std::string S; @@ -347,7 +382,10 @@ // We expect a number of well-defined blocks, though we don't necessarily // need to understand them all. while (true) { - BitstreamEntry Entry = Stream.advance(); + Expected MaybeEntry = Stream.advance(); + if (!MaybeEntry) + return MaybeEntry.takeError(); + BitstreamEntry Entry = MaybeEntry.get(); switch (Entry.Kind) { case BitstreamEntry::Error: @@ -365,8 +403,10 @@ continue; case BitstreamEntry::Record: - Stream.skipRecord(Entry.ID); - continue; + if (llvm::Expected Skipped = Stream.skipRecord(Entry.ID)) + continue; + else + return Skipped.takeError(); } } } @@ -1265,7 +1305,10 @@ // Read all the records. while (true) { - BitstreamEntry Entry = Stream.advanceSkippingSubblocks(); + Expected MaybeEntry = Stream.advanceSkippingSubblocks(); + if (!MaybeEntry) + return MaybeEntry.takeError(); + BitstreamEntry Entry = MaybeEntry.get(); switch (Entry.Kind) { case BitstreamEntry::SubBlock: // Handled for us already. @@ -1280,7 +1323,10 @@ // Read a record. Record.clear(); - switch (Stream.readRecord(Entry.ID, Record)) { + Expected MaybeRecord = Stream.readRecord(Entry.ID, Record); + if (!MaybeRecord) + return MaybeRecord.takeError(); + switch (MaybeRecord.get()) { default: // Default behavior: ignore. break; case bitc::PARAMATTR_CODE_ENTRY_OLD: // ENTRY: [paramidx0, attr0, ...] @@ -1464,7 +1510,10 @@ // Read all the records. while (true) { - BitstreamEntry Entry = Stream.advanceSkippingSubblocks(); + Expected MaybeEntry = Stream.advanceSkippingSubblocks(); + if (!MaybeEntry) + return MaybeEntry.takeError(); + BitstreamEntry Entry = MaybeEntry.get(); switch (Entry.Kind) { case BitstreamEntry::SubBlock: // Handled for us already. @@ -1479,7 +1528,10 @@ // Read a record. Record.clear(); - switch (Stream.readRecord(Entry.ID, Record)) { + Expected MaybeRecord = Stream.readRecord(Entry.ID, Record); + if (!MaybeRecord) + return MaybeRecord.takeError(); + switch (MaybeRecord.get()) { default: // Default behavior: ignore. break; case bitc::PARAMATTR_GRP_CODE_ENTRY: { // ENTRY: [grpid, idx, a0, a1, ...] @@ -1572,7 +1624,10 @@ // Read all the records for this type table. while (true) { - BitstreamEntry Entry = Stream.advanceSkippingSubblocks(); + Expected MaybeEntry = Stream.advanceSkippingSubblocks(); + if (!MaybeEntry) + return MaybeEntry.takeError(); + BitstreamEntry Entry = MaybeEntry.get(); switch (Entry.Kind) { case BitstreamEntry::SubBlock: // Handled for us already. @@ -1590,7 +1645,10 @@ // Read a record. Record.clear(); Type *ResultTy = nullptr; - switch (Stream.readRecord(Entry.ID, Record)) { + Expected MaybeRecord = Stream.readRecord(Entry.ID, Record); + if (!MaybeRecord) + return MaybeRecord.takeError(); + switch (MaybeRecord.get()) { default: return error("Invalid value"); case bitc::TYPE_CODE_NUMENTRY: // TYPE_CODE_NUMENTRY: [numentries] @@ -1809,7 +1867,10 @@ SmallVector Record; while (true) { - BitstreamEntry Entry = Stream.advanceSkippingSubblocks(); + Expected MaybeEntry = Stream.advanceSkippingSubblocks(); + if (!MaybeEntry) + return MaybeEntry.takeError(); + BitstreamEntry Entry = MaybeEntry.get(); switch (Entry.Kind) { case BitstreamEntry::SubBlock: // Handled for us already. @@ -1824,7 +1885,10 @@ // Tags are implicitly mapped to integers by their order. - if (Stream.readRecord(Entry.ID, Record) != bitc::OPERAND_BUNDLE_TAG) + Expected MaybeRecord = Stream.readRecord(Entry.ID, Record); + if (!MaybeRecord) + return MaybeRecord.takeError(); + if (MaybeRecord.get() != bitc::OPERAND_BUNDLE_TAG) return error("Invalid record"); // OPERAND_BUNDLE_TAG: [strchr x N] @@ -1844,7 +1908,11 @@ SmallVector Record; while (true) { - BitstreamEntry Entry = Stream.advanceSkippingSubblocks(); + Expected MaybeEntry = Stream.advanceSkippingSubblocks(); + if (!MaybeEntry) + return MaybeEntry.takeError(); + BitstreamEntry Entry = MaybeEntry.get(); + switch (Entry.Kind) { case BitstreamEntry::SubBlock: // Handled for us already. case BitstreamEntry::Error: @@ -1861,7 +1929,10 @@ // Synchronization scope names are implicitly mapped to synchronization // scope IDs by their order. - if (Stream.readRecord(Entry.ID, Record) != bitc::SYNC_SCOPE_NAME) + Expected MaybeRecord = Stream.readRecord(Entry.ID, Record); + if (!MaybeRecord) + return MaybeRecord.takeError(); + if (MaybeRecord.get() != bitc::SYNC_SCOPE_NAME) return error("Invalid record"); SmallString<16> SSN; @@ -1902,22 +1973,17 @@ /// Helper to note and return the current location, and jump to the given /// offset. -static uint64_t jumpToValueSymbolTable(uint64_t Offset, - BitstreamCursor &Stream) { +static Expected jumpToValueSymbolTable(uint64_t Offset, BitstreamCursor &Stream) { // Save the current parsing location so we can jump back at the end // of the VST read. uint64_t CurrentBit = Stream.GetCurrentBitNo(); - Stream.JumpToBit(Offset * 32); -#ifndef NDEBUG - // Do some checking if we are in debug mode. - BitstreamEntry Entry = Stream.advance(); - assert(Entry.Kind == BitstreamEntry::SubBlock); - assert(Entry.ID == bitc::VALUE_SYMTAB_BLOCK_ID); -#else - // In NDEBUG mode ignore the output so we don't get an unused variable - // warning. - Stream.advance(); -#endif + if (Error JumpFailed = Stream.JumpToBit(Offset * 32)) + return std::move(JumpFailed); + Expected MaybeEntry = Stream.advance(); + if (!MaybeEntry) + return MaybeEntry.takeError(); + assert(MaybeEntry.get().Kind == BitstreamEntry::SubBlock); + assert(MaybeEntry.get().ID == bitc::VALUE_SYMTAB_BLOCK_ID); return CurrentBit; } @@ -1947,7 +2013,10 @@ SmallVector Record; while (true) { - BitstreamEntry Entry = Stream.advanceSkippingSubblocks(); + Expected MaybeEntry = Stream.advanceSkippingSubblocks(); + if (!MaybeEntry) + return MaybeEntry.takeError(); + BitstreamEntry Entry = MaybeEntry.get(); switch (Entry.Kind) { case BitstreamEntry::SubBlock: @@ -1960,7 +2029,10 @@ } Record.clear(); - switch (Stream.readRecord(Entry.ID, Record)) { + Expected MaybeRecord = Stream.readRecord(Entry.ID, Record); + if (!MaybeRecord) + return MaybeRecord.takeError(); + switch (MaybeRecord.get()) { case bitc::VST_CODE_FNENTRY: // [valueid, offset] setDeferredFunctionInfo(FuncBitcodeOffsetDelta, cast(ValueList[Record[0]]), Record); @@ -1977,12 +2049,16 @@ // VST (where we want to jump to the VST offset) and the function-level // VST (where we don't). if (Offset > 0) { - CurrentBit = jumpToValueSymbolTable(Offset, Stream); + Expected MaybeCurrentBit = jumpToValueSymbolTable(Offset, Stream); + if (!MaybeCurrentBit) + return MaybeCurrentBit.takeError(); + CurrentBit = MaybeCurrentBit.get(); // If this module uses a string table, read this as a module-level VST. if (UseStrtab) { if (Error Err = parseGlobalValueSymbolTable()) return Err; - Stream.JumpToBit(CurrentBit); + if (Error JumpFailed = Stream.JumpToBit(CurrentBit)) + return JumpFailed; return Error::success(); } // Otherwise, the VST will be in a similar format to a function-level VST, @@ -2014,7 +2090,10 @@ SmallString<128> ValueName; while (true) { - BitstreamEntry Entry = Stream.advanceSkippingSubblocks(); + Expected MaybeEntry = Stream.advanceSkippingSubblocks(); + if (!MaybeEntry) + return MaybeEntry.takeError(); + BitstreamEntry Entry = MaybeEntry.get(); switch (Entry.Kind) { case BitstreamEntry::SubBlock: // Handled for us already. @@ -2022,7 +2101,8 @@ return error("Malformed block"); case BitstreamEntry::EndBlock: if (Offset > 0) - Stream.JumpToBit(CurrentBit); + if (Error JumpFailed = Stream.JumpToBit(CurrentBit)) + return JumpFailed; return Error::success(); case BitstreamEntry::Record: // The interesting case. @@ -2031,7 +2111,10 @@ // Read a record. Record.clear(); - switch (Stream.readRecord(Entry.ID, Record)) { + Expected MaybeRecord = Stream.readRecord(Entry.ID, Record); + if (!MaybeRecord) + return MaybeRecord.takeError(); + switch (MaybeRecord.get()) { default: // Default behavior: unknown type. break; case bitc::VST_CODE_ENTRY: { // VST_CODE_ENTRY: [valueid, namechar x N] @@ -2186,7 +2269,10 @@ unsigned NextCstNo = ValueList.size(); while (true) { - BitstreamEntry Entry = Stream.advanceSkippingSubblocks(); + Expected MaybeEntry = Stream.advanceSkippingSubblocks(); + if (!MaybeEntry) + return MaybeEntry.takeError(); + BitstreamEntry Entry = MaybeEntry.get(); switch (Entry.Kind) { case BitstreamEntry::SubBlock: // Handled for us already. @@ -2209,8 +2295,10 @@ Record.clear(); Type *VoidType = Type::getVoidTy(Context); Value *V = nullptr; - unsigned BitCode = Stream.readRecord(Entry.ID, Record); - switch (BitCode) { + Expected MaybeBitCode = Stream.readRecord(Entry.ID, Record); + if (!MaybeBitCode) + return MaybeBitCode.takeError(); + switch (unsigned BitCode = MaybeBitCode.get()) { default: // Default behavior: unknown constant case bitc::CST_CODE_UNDEF: // UNDEF V = UndefValue::get(CurTy); @@ -2676,7 +2764,10 @@ SmallVector Record; while (true) { - BitstreamEntry Entry = Stream.advanceSkippingSubblocks(); + Expected MaybeEntry = Stream.advanceSkippingSubblocks(); + if (!MaybeEntry) + return MaybeEntry.takeError(); + BitstreamEntry Entry = MaybeEntry.get(); switch (Entry.Kind) { case BitstreamEntry::SubBlock: // Handled for us already. @@ -2692,7 +2783,10 @@ // Read a use list record. Record.clear(); bool IsBB = false; - switch (Stream.readRecord(Entry.ID, Record)) { + Expected MaybeRecord = Stream.readRecord(Entry.ID, Record); + if (!MaybeRecord) + return MaybeRecord.takeError(); + switch (MaybeRecord.get()) { default: // Default behavior: unknown type. break; case bitc::USELIST_CODE_BB: @@ -2749,7 +2843,8 @@ Error BitcodeReader::materializeMetadata() { for (uint64_t BitPos : DeferredMetadataInfo) { // Move the bit stream to the saved position. - Stream.JumpToBit(BitPos); + if (Error JumpFailed = Stream.JumpToBit(BitPos)) + return JumpFailed; if (Error Err = MDLoader->parseModuleMetadata()) return Err; } @@ -2835,7 +2930,8 @@ /// or if we have an anonymous function being materialized, since anonymous /// functions do not have a name and are therefore not in the VST. Error BitcodeReader::rememberAndSkipFunctionBodies() { - Stream.JumpToBit(NextUnreadBit); + if (Error JumpFailed = Stream.JumpToBit(NextUnreadBit)) + return JumpFailed; if (Stream.AtEndOfStream()) return error("Could not find function in stream"); @@ -2850,7 +2946,11 @@ SmallVector Record; while (true) { - BitstreamEntry Entry = Stream.advance(); + Expected MaybeEntry = Stream.advance(); + if (!MaybeEntry) + return MaybeEntry.takeError(); + llvm::BitstreamEntry Entry = MaybeEntry.get(); + switch (Entry.Kind) { default: return error("Expect SubBlock"); @@ -2869,7 +2969,10 @@ } bool BitcodeReaderBase::readBlockInfo() { - Optional NewBlockInfo = Stream.ReadBlockInfoBlock(); + Expected> MaybeNewBlockInfo = Stream.ReadBlockInfoBlock(); + if (!MaybeNewBlockInfo) + return true; // FIXME Handle the error. + Optional NewBlockInfo = std::move(MaybeNewBlockInfo.get()); if (!NewBlockInfo) return true; BlockInfo = std::move(*NewBlockInfo); @@ -3205,16 +3308,20 @@ Error BitcodeReader::parseModule(uint64_t ResumeBit, bool ShouldLazyLoadMetadata) { - if (ResumeBit) - Stream.JumpToBit(ResumeBit); - else if (Stream.EnterSubBlock(bitc::MODULE_BLOCK_ID)) + if (ResumeBit) { + if (Error JumpFailed = Stream.JumpToBit(ResumeBit)) + return JumpFailed; + } else if (Stream.EnterSubBlock(bitc::MODULE_BLOCK_ID)) return error("Invalid record"); SmallVector Record; // Read all the records for this module. while (true) { - BitstreamEntry Entry = Stream.advance(); + Expected MaybeEntry = Stream.advance(); + if (!MaybeEntry) + return MaybeEntry.takeError(); + llvm::BitstreamEntry Entry = MaybeEntry.get(); switch (Entry.Kind) { case BitstreamEntry::Error: @@ -3357,8 +3464,10 @@ } // Read a record. - auto BitCode = Stream.readRecord(Entry.ID, Record); - switch (BitCode) { + Expected MaybeBitCode = Stream.readRecord(Entry.ID, Record); + if (!MaybeBitCode) + return MaybeBitCode.takeError(); + switch (unsigned BitCode = MaybeBitCode.get()) { default: break; // Default behavior, ignore unknown content. case bitc::MODULE_CODE_VERSION: { Expected VersionOrErr = parseVersionRecord(Record); @@ -3520,7 +3629,10 @@ SmallVector Record; while (true) { - BitstreamEntry Entry = Stream.advance(); + Expected MaybeEntry = Stream.advance(); + if (!MaybeEntry) + return MaybeEntry.takeError(); + llvm::BitstreamEntry Entry = MaybeEntry.get(); switch (Entry.Kind) { case BitstreamEntry::Error: @@ -3568,8 +3680,10 @@ // Read a record. Record.clear(); Instruction *I = nullptr; - unsigned BitCode = Stream.readRecord(Entry.ID, Record); - switch (BitCode) { + Expected MaybeBitCode = Stream.readRecord(Entry.ID, Record); + if (!MaybeBitCode) + return MaybeBitCode.takeError(); + switch (unsigned BitCode = MaybeBitCode.get()) { default: // Default behavior: reject return error("Invalid value"); case bitc::FUNC_CODE_DECLAREBLOCKS: { // DECLAREBLOCKS: [nblocks] @@ -4922,8 +5036,8 @@ return Err; // Move the bit stream to the saved position of the deferred function body. - Stream.JumpToBit(DFII->second); - + if (Error JumpFailed = Stream.JumpToBit(DFII->second)) + return JumpFailed; if (Error Err = parseFunctionBody(F)) return Err; F->setIsMaterializable(false); @@ -5086,7 +5200,10 @@ return Error::success(); assert(Offset > 0 && "Expected non-zero VST offset"); - uint64_t CurrentBit = jumpToValueSymbolTable(Offset, Stream); + Expected MaybeCurrentBit = jumpToValueSymbolTable(Offset, Stream); + if (!MaybeCurrentBit) + return MaybeCurrentBit.takeError(); + uint64_t CurrentBit = MaybeCurrentBit.get(); if (Stream.EnterSubBlock(bitc::VALUE_SYMTAB_BLOCK_ID)) return error("Invalid record"); @@ -5097,7 +5214,10 @@ SmallString<128> ValueName; while (true) { - BitstreamEntry Entry = Stream.advanceSkippingSubblocks(); + Expected MaybeEntry = Stream.advanceSkippingSubblocks(); + if (!MaybeEntry) + return MaybeEntry.takeError(); + BitstreamEntry Entry = MaybeEntry.get(); switch (Entry.Kind) { case BitstreamEntry::SubBlock: // Handled for us already. @@ -5105,7 +5225,8 @@ return error("Malformed block"); case BitstreamEntry::EndBlock: // Done parsing VST, jump back to wherever we came from. - Stream.JumpToBit(CurrentBit); + if (Error JumpFailed = Stream.JumpToBit(CurrentBit)) + return JumpFailed; return Error::success(); case BitstreamEntry::Record: // The interesting case. @@ -5114,7 +5235,10 @@ // Read a record. Record.clear(); - switch (Stream.readRecord(Entry.ID, Record)) { + Expected MaybeRecord = Stream.readRecord(Entry.ID, Record); + if (!MaybeRecord) + return MaybeRecord.takeError(); + switch (MaybeRecord.get()) { default: // Default behavior: ignore (e.g. VST_CODE_BBENTRY records). break; case bitc::VST_CODE_ENTRY: { // VST_CODE_ENTRY: [valueid, namechar x N] @@ -5171,7 +5295,10 @@ // Read the index for this module. while (true) { - BitstreamEntry Entry = Stream.advance(); + Expected MaybeEntry = Stream.advance(); + if (!MaybeEntry) + return MaybeEntry.takeError(); + llvm::BitstreamEntry Entry = MaybeEntry.get(); switch (Entry.Kind) { case BitstreamEntry::Error: @@ -5228,8 +5355,10 @@ case BitstreamEntry::Record: { Record.clear(); - auto BitCode = Stream.readRecord(Entry.ID, Record); - switch (BitCode) { + Expected MaybeBitCode = Stream.readRecord(Entry.ID, Record); + if (!MaybeBitCode) + return MaybeBitCode.takeError(); + switch (unsigned BitCode = MaybeBitCode.get()) { default: break; // Default behavior, ignore unknown content. case bitc::MODULE_CODE_VERSION: { @@ -5392,10 +5521,17 @@ // Parse version { - BitstreamEntry Entry = Stream.advanceSkippingSubblocks(); + Expected MaybeEntry = Stream.advanceSkippingSubblocks(); + if (!MaybeEntry) + return MaybeEntry.takeError(); + BitstreamEntry Entry = MaybeEntry.get(); + if (Entry.Kind != BitstreamEntry::Record) return error("Invalid Summary Block: record for version expected"); - if (Stream.readRecord(Entry.ID, Record) != bitc::FS_VERSION) + Expected MaybeRecord = Stream.readRecord(Entry.ID, Record); + if (!MaybeRecord) + return MaybeRecord.takeError(); + if (MaybeRecord.get() != bitc::FS_VERSION) return error("Invalid Summary Block: version expected"); } const uint64_t Version = Record[0]; @@ -5420,7 +5556,10 @@ PendingTypeCheckedLoadConstVCalls; while (true) { - BitstreamEntry Entry = Stream.advanceSkippingSubblocks(); + Expected MaybeEntry = Stream.advanceSkippingSubblocks(); + if (!MaybeEntry) + return MaybeEntry.takeError(); + BitstreamEntry Entry = MaybeEntry.get(); switch (Entry.Kind) { case BitstreamEntry::SubBlock: // Handled for us already. @@ -5441,8 +5580,10 @@ // in the combined index VST entries). The records also contain // information used for ThinLTO renaming and importing. Record.clear(); - auto BitCode = Stream.readRecord(Entry.ID, Record); - switch (BitCode) { + Expected MaybeBitCode = Stream.readRecord(Entry.ID, Record); + if (!MaybeBitCode) + return MaybeBitCode.takeError(); + switch (unsigned BitCode = MaybeBitCode.get()) { default: // Default behavior: ignore. break; case bitc::FS_FLAGS: { // [flags] @@ -5774,7 +5915,10 @@ ModuleSummaryIndex::ModuleInfo *LastSeenModule = nullptr; while (true) { - BitstreamEntry Entry = Stream.advanceSkippingSubblocks(); + Expected MaybeEntry = Stream.advanceSkippingSubblocks(); + if (!MaybeEntry) + return MaybeEntry.takeError(); + BitstreamEntry Entry = MaybeEntry.get(); switch (Entry.Kind) { case BitstreamEntry::SubBlock: // Handled for us already. @@ -5788,7 +5932,10 @@ } Record.clear(); - switch (Stream.readRecord(Entry.ID, Record)) { + Expected MaybeRecord = Stream.readRecord(Entry.ID, Record); + if (!MaybeRecord) + return MaybeRecord.takeError(); + switch (MaybeRecord.get()) { default: // Default behavior: ignore. break; case bitc::MST_CODE_ENTRY: { @@ -5859,7 +6006,11 @@ StringRef Strtab; while (true) { - BitstreamEntry Entry = Stream.advance(); + Expected MaybeEntry = Stream.advance(); + if (!MaybeEntry) + return MaybeEntry.takeError(); + llvm::BitstreamEntry Entry = MaybeEntry.get(); + switch (Entry.Kind) { case BitstreamEntry::EndBlock: return Strtab; @@ -5875,7 +6026,10 @@ case BitstreamEntry::Record: StringRef Blob; SmallVector Record; - if (Stream.readRecord(Entry.ID, Record, &Blob) == RecordID) + Expected MaybeRecord = Stream.readRecord(Entry.ID, Record, &Blob); + if (!MaybeRecord) + return MaybeRecord.takeError(); + if (MaybeRecord.get() == RecordID) Strtab = Blob; break; } @@ -5911,7 +6065,11 @@ if (BCBegin + 8 >= Stream.getBitcodeBytes().size()) return F; - BitstreamEntry Entry = Stream.advance(); + Expected MaybeEntry = Stream.advance(); + if (!MaybeEntry) + return MaybeEntry.takeError(); + llvm::BitstreamEntry Entry = MaybeEntry.get(); + switch (Entry.Kind) { case BitstreamEntry::EndBlock: case BitstreamEntry::Error: @@ -5924,7 +6082,13 @@ if (Stream.SkipBlock()) return error("Malformed block"); - Entry = Stream.advance(); + { + Expected MaybeEntry = Stream.advance(); + if (!MaybeEntry) + return MaybeEntry.takeError(); + Entry = MaybeEntry.get(); + } + if (Entry.Kind != BitstreamEntry::SubBlock || Entry.ID != bitc::MODULE_BLOCK_ID) return error("Malformed block"); @@ -5986,8 +6150,10 @@ continue; } case BitstreamEntry::Record: - Stream.skipRecord(Entry.ID); - continue; + if (Expected StreamFailed = Stream.skipRecord(Entry.ID)) + continue; + else + return StreamFailed.takeError(); } } } @@ -6007,7 +6173,8 @@ std::string ProducerIdentification; if (IdentificationBit != -1ull) { - Stream.JumpToBit(IdentificationBit); + if (Error JumpFailed = Stream.JumpToBit(IdentificationBit)) + return std::move(JumpFailed); Expected ProducerIdentificationOrErr = readIdentificationBlock(Stream); if (!ProducerIdentificationOrErr) @@ -6016,7 +6183,8 @@ ProducerIdentification = *ProducerIdentificationOrErr; } - Stream.JumpToBit(ModuleBit); + if (Error JumpFailed = Stream.JumpToBit(ModuleBit)) + return std::move(JumpFailed); auto *R = new BitcodeReader(std::move(Stream), Strtab, ProducerIdentification, Context); @@ -6054,7 +6222,8 @@ Error BitcodeModule::readSummary(ModuleSummaryIndex &CombinedIndex, StringRef ModulePath, uint64_t ModuleId) { BitstreamCursor Stream(Buffer); - Stream.JumpToBit(ModuleBit); + if (Error JumpFailed = Stream.JumpToBit(ModuleBit)) + return JumpFailed; ModuleSummaryIndexBitcodeReader R(std::move(Stream), Strtab, CombinedIndex, ModulePath, ModuleId); @@ -6064,7 +6233,8 @@ // Parse the specified bitcode buffer, returning the function info index. Expected> BitcodeModule::getSummary() { BitstreamCursor Stream(Buffer); - Stream.JumpToBit(ModuleBit); + if (Error JumpFailed = Stream.JumpToBit(ModuleBit)) + return std::move(JumpFailed); auto Index = llvm::make_unique(/*HaveGVs=*/false); ModuleSummaryIndexBitcodeReader R(std::move(Stream), Strtab, *Index, @@ -6083,7 +6253,10 @@ SmallVector Record; while (true) { - BitstreamEntry Entry = Stream.advanceSkippingSubblocks(); + Expected MaybeEntry = Stream.advanceSkippingSubblocks(); + if (!MaybeEntry) + return MaybeEntry.takeError(); + BitstreamEntry Entry = MaybeEntry.get(); switch (Entry.Kind) { case BitstreamEntry::SubBlock: // Handled for us already. @@ -6100,8 +6273,10 @@ // Look for the FS_FLAGS record. Record.clear(); - auto BitCode = Stream.readRecord(Entry.ID, Record); - switch (BitCode) { + Expected MaybeBitCode = Stream.readRecord(Entry.ID, Record); + if (!MaybeBitCode) + return MaybeBitCode.takeError(); + switch (MaybeBitCode.get()) { default: // Default behavior: ignore. break; case bitc::FS_FLAGS: { // [flags] @@ -6119,13 +6294,17 @@ // Check if the given bitcode buffer contains a global value summary block. Expected BitcodeModule::getLTOInfo() { BitstreamCursor Stream(Buffer); - Stream.JumpToBit(ModuleBit); + if (Error JumpFailed = Stream.JumpToBit(ModuleBit)) + return std::move(JumpFailed); if (Stream.EnterSubBlock(bitc::MODULE_BLOCK_ID)) return error("Invalid record"); while (true) { - BitstreamEntry Entry = Stream.advance(); + Expected MaybeEntry = Stream.advance(); + if (!MaybeEntry) + return MaybeEntry.takeError(); + llvm::BitstreamEntry Entry = MaybeEntry.get(); switch (Entry.Kind) { case BitstreamEntry::Error: @@ -6159,8 +6338,10 @@ continue; case BitstreamEntry::Record: - Stream.skipRecord(Entry.ID); - continue; + if (Expected StreamFailed = Stream.skipRecord(Entry.ID)) + continue; + else + return StreamFailed.takeError(); } } } diff --git a/llvm/lib/Bitcode/Reader/BitstreamReader.cpp b/llvm/lib/Bitcode/Reader/BitstreamReader.cpp --- a/llvm/lib/Bitcode/Reader/BitstreamReader.cpp +++ b/llvm/lib/Bitcode/Reader/BitstreamReader.cpp @@ -19,7 +19,7 @@ /// EnterSubBlock - Having read the ENTER_SUBBLOCK abbrevid, enter /// the block, and return true if the block has an error. -bool BitstreamCursor::EnterSubBlock(unsigned BlockID, unsigned *NumWordsP) { +Expected BitstreamCursor::EnterSubBlock(unsigned BlockID, unsigned *NumWordsP) { // Save the current block's state on BlockScope. BlockScope.push_back(Block(CurCodeSize)); BlockScope.back().PrevAbbrevs.swap(CurAbbrevs); @@ -34,21 +34,28 @@ } // Get the codesize of this block. - CurCodeSize = ReadVBR(bitc::CodeLenWidth); + Expected MaybeVBR = ReadVBR(bitc::CodeLenWidth); + if (!MaybeVBR) + return MaybeVBR.takeError(); + CurCodeSize = MaybeVBR.get(); + // We can't read more than MaxChunkSize at a time if (CurCodeSize > MaxChunkSize) return true; SkipToFourByteBoundary(); - unsigned NumWords = Read(bitc::BlockSizeWidth); - if (NumWordsP) *NumWordsP = NumWords; + Expected MaybeNum = Read(bitc::BlockSizeWidth); + if (!MaybeNum) + return MaybeNum.takeError(); + word_t NumWords = MaybeNum.get(); + if (NumWordsP) + *NumWordsP = NumWords; // Validate that this block is sane. return CurCodeSize == 0 || AtEndOfStream(); } -static uint64_t readAbbreviatedField(BitstreamCursor &Cursor, - const BitCodeAbbrevOp &Op) { +static Expected readAbbreviatedField(BitstreamCursor &Cursor, const BitCodeAbbrevOp &Op) { assert(!Op.isLiteral() && "Not to be used with literals!"); // Decode the value as we are commanded. @@ -63,13 +70,15 @@ assert((unsigned)Op.getEncodingData() <= Cursor.MaxChunkSize); return Cursor.ReadVBR64((unsigned)Op.getEncodingData()); case BitCodeAbbrevOp::Char6: - return BitCodeAbbrevOp::DecodeChar6(Cursor.Read(6)); + if (Expected Res = Cursor.Read(6)) + return BitCodeAbbrevOp::DecodeChar6(Res.get()); + else + return Res.takeError(); } llvm_unreachable("invalid abbreviation encoding"); } -static void skipAbbreviatedField(BitstreamCursor &Cursor, - const BitCodeAbbrevOp &Op) { +static Error skipAbbreviatedField(BitstreamCursor &Cursor, const BitCodeAbbrevOp &Op) { assert(!Op.isLiteral() && "Not to be used with literals!"); // Decode the value as we are commanded. @@ -79,26 +88,42 @@ llvm_unreachable("Should not reach here"); case BitCodeAbbrevOp::Fixed: assert((unsigned)Op.getEncodingData() <= Cursor.MaxChunkSize); - Cursor.Read((unsigned)Op.getEncodingData()); - break; + if (Expected Res = Cursor.Read((unsigned)Op.getEncodingData())) + break; + else + return Res.takeError(); case BitCodeAbbrevOp::VBR: assert((unsigned)Op.getEncodingData() <= Cursor.MaxChunkSize); - Cursor.ReadVBR64((unsigned)Op.getEncodingData()); - break; + if (Expected Res = Cursor.ReadVBR64((unsigned)Op.getEncodingData())) + break; + else + return Res.takeError(); case BitCodeAbbrevOp::Char6: - Cursor.Read(6); - break; + if (Expected Res = Cursor.Read(6)) + break; + else + return Res.takeError(); } + return ErrorSuccess(); } /// skipRecord - Read the current record and discard it. -unsigned BitstreamCursor::skipRecord(unsigned AbbrevID) { +Expected BitstreamCursor::skipRecord(unsigned AbbrevID) { // Skip unabbreviated records by reading past their entries. if (AbbrevID == bitc::UNABBREV_RECORD) { - unsigned Code = ReadVBR(6); - unsigned NumElts = ReadVBR(6); + Expected MaybeCode = ReadVBR(6); + if (!MaybeCode) + return MaybeCode.takeError(); + unsigned Code = MaybeCode.get(); + Expected MaybeVBR = ReadVBR(6); + if (!MaybeVBR) + return MaybeVBR.get(); + unsigned NumElts = MaybeVBR.get(); for (unsigned i = 0; i != NumElts; ++i) - (void)ReadVBR64(6); + if (Expected Res = ReadVBR64(6)) + ; // Skip! + else + return Res.takeError(); return Code; } @@ -111,7 +136,10 @@ if (CodeOp.getEncoding() == BitCodeAbbrevOp::Array || CodeOp.getEncoding() == BitCodeAbbrevOp::Blob) report_fatal_error("Abbreviation starts with an Array or a Blob"); - Code = readAbbreviatedField(*this, CodeOp); + Expected MaybeCode = readAbbreviatedField(*this, CodeOp); + if (!MaybeCode) + return MaybeCode.takeError(); + Code = MaybeCode.get(); } for (unsigned i = 1, e = Abbv->getNumOperandInfos(); i < e; ++i) { @@ -121,13 +149,17 @@ if (Op.getEncoding() != BitCodeAbbrevOp::Array && Op.getEncoding() != BitCodeAbbrevOp::Blob) { - skipAbbreviatedField(*this, Op); + if (Error Err = skipAbbreviatedField(*this, Op)) + return std::move(Err); continue; } if (Op.getEncoding() == BitCodeAbbrevOp::Array) { // Array case. Read the number of elements as a vbr6. - unsigned NumElts = ReadVBR(6); + Expected MaybeNum = ReadVBR(6); + if (!MaybeNum) + return MaybeNum.takeError(); + unsigned NumElts = MaybeNum.get(); // Get the element encoding. assert(i+2 == e && "array op not second to last?"); @@ -140,15 +172,20 @@ report_fatal_error("Array element type can't be an Array or a Blob"); case BitCodeAbbrevOp::Fixed: assert((unsigned)EltEnc.getEncodingData() <= MaxChunkSize); - JumpToBit(GetCurrentBitNo() + NumElts * EltEnc.getEncodingData()); + if (Error Err = JumpToBit(GetCurrentBitNo() + NumElts * EltEnc.getEncodingData())) + return std::move(Err); break; case BitCodeAbbrevOp::VBR: assert((unsigned)EltEnc.getEncodingData() <= MaxChunkSize); for (; NumElts; --NumElts) - ReadVBR64((unsigned)EltEnc.getEncodingData()); + if (Expected Res = ReadVBR64((unsigned)EltEnc.getEncodingData())) + ; // Skip! + else + return Res.takeError(); break; case BitCodeAbbrevOp::Char6: - JumpToBit(GetCurrentBitNo() + NumElts * 6); + if (Error Err = JumpToBit(GetCurrentBitNo() + NumElts * 6)) + return std::move(Err); break; } continue; @@ -156,7 +193,10 @@ assert(Op.getEncoding() == BitCodeAbbrevOp::Blob); // Blob case. Read the number of bytes as a vbr6. - unsigned NumElts = ReadVBR(6); + Expected MaybeNum = ReadVBR(6); + if (!MaybeNum) + return MaybeNum.takeError(); + unsigned NumElts = MaybeNum.get(); SkipToFourByteBoundary(); // 32-bit alignment // Figure out where the end of this blob will be including tail padding. @@ -170,19 +210,28 @@ } // Skip over the blob. - JumpToBit(NewEnd); + if (Error Err = JumpToBit(NewEnd)) + return std::move(Err); } return Code; } -unsigned BitstreamCursor::readRecord(unsigned AbbrevID, - SmallVectorImpl &Vals, - StringRef *Blob) { +Expected BitstreamCursor::readRecord(unsigned AbbrevID, SmallVectorImpl &Vals, StringRef *Blob) { if (AbbrevID == bitc::UNABBREV_RECORD) { - unsigned Code = ReadVBR(6); - unsigned NumElts = ReadVBR(6); + Expected MaybeCode = ReadVBR(6); + if (!MaybeCode) + return MaybeCode.takeError(); + uint32_t Code = MaybeCode.get(); + Expected MaybeNumElts = ReadVBR(6); + if (!MaybeNumElts) + return MaybeNumElts.takeError(); + uint32_t NumElts = MaybeNumElts.get(); + for (unsigned i = 0; i != NumElts; ++i) - Vals.push_back(ReadVBR64(6)); + if (Expected MaybeVal = ReadVBR64(6)) + Vals.push_back(MaybeVal.get()); + else + return MaybeVal.takeError(); return Code; } @@ -198,7 +247,10 @@ if (CodeOp.getEncoding() == BitCodeAbbrevOp::Array || CodeOp.getEncoding() == BitCodeAbbrevOp::Blob) report_fatal_error("Abbreviation starts with an Array or a Blob"); - Code = readAbbreviatedField(*this, CodeOp); + if (Expected MaybeCode = readAbbreviatedField(*this, CodeOp)) + Code = MaybeCode.get(); + else + return MaybeCode.takeError(); } for (unsigned i = 1, e = Abbv->getNumOperandInfos(); i != e; ++i) { @@ -210,13 +262,19 @@ if (Op.getEncoding() != BitCodeAbbrevOp::Array && Op.getEncoding() != BitCodeAbbrevOp::Blob) { - Vals.push_back(readAbbreviatedField(*this, Op)); + if (Expected MaybeVal = readAbbreviatedField(*this, Op)) + Vals.push_back(MaybeVal.get()); + else + return MaybeVal.takeError(); continue; } if (Op.getEncoding() == BitCodeAbbrevOp::Array) { // Array case. Read the number of elements as a vbr6. - unsigned NumElts = ReadVBR(6); + Expected MaybeNumElts = ReadVBR(6); + if (!MaybeNumElts) + return MaybeNumElts.takeError(); + uint32_t NumElts = MaybeNumElts.get(); // Get the element encoding. if (i + 2 != e) @@ -232,22 +290,34 @@ report_fatal_error("Array element type can't be an Array or a Blob"); case BitCodeAbbrevOp::Fixed: for (; NumElts; --NumElts) - Vals.push_back(Read((unsigned)EltEnc.getEncodingData())); + if (Expected MaybeVal = Read((unsigned)EltEnc.getEncodingData())) + Vals.push_back(MaybeVal.get()); + else + return MaybeVal.takeError(); break; case BitCodeAbbrevOp::VBR: for (; NumElts; --NumElts) - Vals.push_back(ReadVBR64((unsigned)EltEnc.getEncodingData())); + if (Expected MaybeVal = ReadVBR64((unsigned)EltEnc.getEncodingData())) + Vals.push_back(MaybeVal.get()); + else + return MaybeVal.takeError(); break; case BitCodeAbbrevOp::Char6: for (; NumElts; --NumElts) - Vals.push_back(BitCodeAbbrevOp::DecodeChar6(Read(6))); + if (Expected MaybeVal = Read(6)) + Vals.push_back(BitCodeAbbrevOp::DecodeChar6(MaybeVal.get())); + else + return MaybeVal.takeError(); } continue; } assert(Op.getEncoding() == BitCodeAbbrevOp::Blob); // Blob case. Read the number of bytes as a vbr6. - unsigned NumElts = ReadVBR(6); + Expected MaybeNumElts = ReadVBR(6); + if (!MaybeNumElts) + return MaybeNumElts.takeError(); + uint32_t NumElts = MaybeNumElts.get(); SkipToFourByteBoundary(); // 32-bit alignment // Figure out where the end of this blob will be including tail padding. @@ -265,7 +335,8 @@ // Otherwise, inform the streamer that we need these bytes in memory. Skip // over tail padding first, in case jumping to NewEnd invalidates the Blob // pointer. - JumpToBit(NewEnd); + if (Error Err = JumpToBit(NewEnd)) + return std::move(Err); const char *Ptr = (const char *)getPointerToBit(CurBitPos, NumElts); // If we can return a reference to the data, do so to avoid copying it. @@ -281,19 +352,34 @@ return Code; } -void BitstreamCursor::ReadAbbrevRecord() { +Error BitstreamCursor::ReadAbbrevRecord() { auto Abbv = std::make_shared(); - unsigned NumOpInfo = ReadVBR(5); + Expected MaybeNumOpInfo = ReadVBR(5); + if (!MaybeNumOpInfo) + return MaybeNumOpInfo.takeError(); + unsigned NumOpInfo = MaybeNumOpInfo.get(); for (unsigned i = 0; i != NumOpInfo; ++i) { - bool IsLiteral = Read(1); + Expected MaybeIsLiteral = Read(1); + if (!MaybeIsLiteral) + return MaybeIsLiteral.takeError(); + bool IsLiteral = MaybeIsLiteral.get(); if (IsLiteral) { - Abbv->Add(BitCodeAbbrevOp(ReadVBR64(8))); + Expected MaybeOp = ReadVBR64(8); + if (!MaybeOp) + return MaybeOp.takeError(); + Abbv->Add(BitCodeAbbrevOp(MaybeOp.get())); continue; } - BitCodeAbbrevOp::Encoding E = (BitCodeAbbrevOp::Encoding)Read(3); + Expected MaybeEncoding = Read(3); + if (!MaybeEncoding) + return MaybeEncoding.takeError(); + BitCodeAbbrevOp::Encoding E = (BitCodeAbbrevOp::Encoding)MaybeEncoding.get(); if (BitCodeAbbrevOp::hasEncodingData(E)) { - uint64_t Data = ReadVBR64(5); + Expected MaybeData = ReadVBR64(5); + if (!MaybeData) + return MaybeData.takeError(); + uint64_t Data = MaybeData.get(); // As a special case, handle fixed(0) (i.e., a fixed field with zero bits) // and vbr(0) as a literal zero. This is decoded the same way, and avoids @@ -317,9 +403,11 @@ if (Abbv->getNumOperandInfos() == 0) report_fatal_error("Abbrev record with no operands"); CurAbbrevs.push_back(std::move(Abbv)); + + return Error::success(); } -Optional +Expected> BitstreamCursor::ReadBlockInfoBlock(bool ReadBlockInfoNames) { if (EnterSubBlock(bitc::BLOCKINFO_BLOCK_ID)) return None; @@ -330,7 +418,10 @@ // Read all the records for this module. while (true) { - BitstreamEntry Entry = advanceSkippingSubblocks(AF_DontAutoprocessAbbrevs); + Expected MaybeEntry = advanceSkippingSubblocks(AF_DontAutoprocessAbbrevs); + if (!MaybeEntry) + return MaybeEntry.takeError(); + BitstreamEntry Entry = MaybeEntry.get(); switch (Entry.Kind) { case llvm::BitstreamEntry::SubBlock: // Handled for us already. @@ -346,7 +437,8 @@ // Read abbrev records, associate them with CurBID. if (Entry.ID == bitc::DEFINE_ABBREV) { if (!CurBlockInfo) return None; - ReadAbbrevRecord(); + if (Error Err = ReadAbbrevRecord()) + return std::move(Err); // ReadAbbrevRecord installs the abbrev in CurAbbrevs. Move it to the // appropriate BlockInfo. @@ -357,7 +449,10 @@ // Read a record. Record.clear(); - switch (readRecord(Entry.ID, Record)) { + Expected MaybeBlockInfo = readRecord(Entry.ID, Record); + if (!MaybeBlockInfo) + return MaybeBlockInfo.takeError(); + switch (MaybeBlockInfo.get()) { default: break; // Default behavior, ignore unknown content. case bitc::BLOCKINFO_CODE_SETBID: if (Record.size() < 1) return None; diff --git a/llvm/lib/Bitcode/Reader/MetadataLoader.cpp b/llvm/lib/Bitcode/Reader/MetadataLoader.cpp --- a/llvm/lib/Bitcode/Reader/MetadataLoader.cpp +++ b/llvm/lib/Bitcode/Reader/MetadataLoader.cpp @@ -674,8 +674,11 @@ SmallVector Record; // Get the abbrevs, and preload record positions to make them lazy-loadable. while (true) { - BitstreamEntry Entry = IndexCursor.advanceSkippingSubblocks( - BitstreamCursor::AF_DontPopBlockAtEnd); + Expected MaybeEntry = IndexCursor.advanceSkippingSubblocks(BitstreamCursor::AF_DontPopBlockAtEnd); + if (!MaybeEntry) + return MaybeEntry.takeError(); + BitstreamEntry Entry = MaybeEntry.get(); + switch (Entry.Kind) { case BitstreamEntry::SubBlock: // Handled for us already. case BitstreamEntry::Error: @@ -687,14 +690,21 @@ // The interesting case. ++NumMDRecordLoaded; uint64_t CurrentPos = IndexCursor.GetCurrentBitNo(); - auto Code = IndexCursor.skipRecord(Entry.ID); + Expected MaybeCode = IndexCursor.skipRecord(Entry.ID); + if (!MaybeCode) + return MaybeCode.takeError(); + unsigned Code = MaybeCode.get(); switch (Code) { case bitc::METADATA_STRINGS: { // Rewind and parse the strings. - IndexCursor.JumpToBit(CurrentPos); + if (Error Err = IndexCursor.JumpToBit(CurrentPos)) + return std::move(Err); StringRef Blob; Record.clear(); - IndexCursor.readRecord(Entry.ID, Record, &Blob); + if (Expected MaybeRecord = IndexCursor.readRecord(Entry.ID, Record, &Blob)) + ; + else + return MaybeRecord.takeError(); unsigned NumStrings = Record[0]; MDStringRef.reserve(NumStrings); auto IndexNextMDString = [&](StringRef Str) { @@ -707,26 +717,31 @@ case bitc::METADATA_INDEX_OFFSET: { // This is the offset to the index, when we see this we skip all the // records and load only an index to these. - IndexCursor.JumpToBit(CurrentPos); + if (Error Err = IndexCursor.JumpToBit(CurrentPos)) + return std::move(Err); Record.clear(); - IndexCursor.readRecord(Entry.ID, Record); + if (Expected MaybeRecord = IndexCursor.readRecord(Entry.ID, Record)) + ; + else + return MaybeRecord.takeError(); if (Record.size() != 2) return error("Invalid record"); auto Offset = Record[0] + (Record[1] << 32); auto BeginPos = IndexCursor.GetCurrentBitNo(); - IndexCursor.JumpToBit(BeginPos + Offset); - Entry = IndexCursor.advanceSkippingSubblocks( - BitstreamCursor::AF_DontPopBlockAtEnd); + if (Error Err = IndexCursor.JumpToBit(BeginPos + Offset)) + return std::move(Err); + Expected MaybeEntry = IndexCursor.advanceSkippingSubblocks(BitstreamCursor::AF_DontPopBlockAtEnd); + if (!MaybeEntry) + return MaybeEntry.takeError(); + Entry = MaybeEntry.get(); assert(Entry.Kind == BitstreamEntry::Record && "Corrupted bitcode: Expected `Record` when trying to find the " "Metadata index"); Record.clear(); - auto Code = IndexCursor.readRecord(Entry.ID, Record); - (void)Code; - assert(Code == bitc::METADATA_INDEX && "Corrupted bitcode: Expected " - "`METADATA_INDEX` when trying " - "to find the Metadata index"); - + if (Expected MaybeCode = IndexCursor.readRecord(Entry.ID, Record)) + assert(MaybeCode.get() == bitc::METADATA_INDEX && "Corrupted bitcode: Expected `METADATA_INDEX` when trying to find the Metadata index"); + else + return MaybeCode.takeError(); // Delta unpack auto CurrentValue = BeginPos; GlobalMetadataBitPosIndex.reserve(Record.size()); @@ -742,21 +757,31 @@ return error("Corrupted Metadata block"); case bitc::METADATA_NAME: { // Named metadata need to be materialized now and aren't deferred. - IndexCursor.JumpToBit(CurrentPos); + if (Error Err = IndexCursor.JumpToBit(CurrentPos)) + return std::move(Err); Record.clear(); - unsigned Code = IndexCursor.readRecord(Entry.ID, Record); - assert(Code == bitc::METADATA_NAME); + + unsigned Code; + if (Expected MaybeCode = IndexCursor.readRecord(Entry.ID, Record)) { + Code = MaybeCode.get(); + assert(Code == bitc::METADATA_NAME); + } else + return MaybeCode.takeError(); // Read name of the named metadata. SmallString<8> Name(Record.begin(), Record.end()); - Code = IndexCursor.ReadCode(); + if (Expected MaybeCode = IndexCursor.ReadCode()) + Code = MaybeCode.get(); + else + return MaybeCode.takeError(); // Named Metadata comes in two parts, we expect the name to be followed // by the node Record.clear(); - unsigned NextBitCode = IndexCursor.readRecord(Code, Record); - assert(NextBitCode == bitc::METADATA_NAMED_NODE); - (void)NextBitCode; + if (Expected MaybeNextBitCode = IndexCursor.readRecord(Code, Record)) + assert(MaybeNextBitCode.get() == bitc::METADATA_NAMED_NODE); + else + return MaybeNextBitCode.takeError(); // Read named metadata elements. unsigned Size = Record.size(); @@ -775,9 +800,13 @@ case bitc::METADATA_GLOBAL_DECL_ATTACHMENT: { // FIXME: we need to do this early because we don't materialize global // value explicitly. - IndexCursor.JumpToBit(CurrentPos); + if (Error Err = IndexCursor.JumpToBit(CurrentPos)) + return std::move(Err); Record.clear(); - IndexCursor.readRecord(Entry.ID, Record); + if (Expected MaybeRecord = IndexCursor.readRecord(Entry.ID, Record)) + ; + else + return MaybeRecord.takeError(); if (Record.size() % 2 == 0) return error("Invalid record"); unsigned ValueID = Record[0]; @@ -871,7 +900,8 @@ // Return at the beginning of the block, since it is easy to skip it // entirely from there. Stream.ReadBlockEnd(); // Pop the abbrev block context. - Stream.JumpToBit(EntryPos); + if (Error Err = IndexCursor.JumpToBit(EntryPos)) + return Err; if (Stream.SkipBlock()) return error("Invalid record"); return Error::success(); @@ -883,7 +913,10 @@ // Read all the records. while (true) { - BitstreamEntry Entry = Stream.advanceSkippingSubblocks(); + Expected MaybeEntry = Stream.advanceSkippingSubblocks(); + if (!MaybeEntry) + return MaybeEntry.takeError(); + BitstreamEntry Entry = MaybeEntry.get(); switch (Entry.Kind) { case BitstreamEntry::SubBlock: // Handled for us already. @@ -902,10 +935,11 @@ Record.clear(); StringRef Blob; ++NumMDRecordLoaded; - unsigned Code = Stream.readRecord(Entry.ID, Record, &Blob); - if (Error Err = - parseOneMetadata(Record, Code, Placeholders, Blob, NextMetadataNo)) - return Err; + if (Expected MaybeCode = Stream.readRecord(Entry.ID, Record, &Blob)) { + if (Error Err = parseOneMetadata(Record, MaybeCode.get(), Placeholders, Blob, NextMetadataNo)) + return Err; + } else + return MaybeCode.takeError(); } } @@ -930,12 +964,19 @@ } SmallVector Record; StringRef Blob; - IndexCursor.JumpToBit(GlobalMetadataBitPosIndex[ID - MDStringRef.size()]); - auto Entry = IndexCursor.advanceSkippingSubblocks(); + if (Error Err = IndexCursor.JumpToBit(GlobalMetadataBitPosIndex[ID - MDStringRef.size()])) + report_fatal_error("lazyLoadOneMetadata failed jumping: " + toString(std::move(Err))); + Expected MaybeEntry = IndexCursor.advanceSkippingSubblocks(); + if (!MaybeEntry) + // FIXME this drops the error on the floor. + report_fatal_error("lazyLoadOneMetadata failed advanceSkippingSubblocks"); + BitstreamEntry Entry = MaybeEntry.get(); ++NumMDRecordLoaded; - unsigned Code = IndexCursor.readRecord(Entry.ID, Record, &Blob); - if (Error Err = parseOneMetadata(Record, Code, Placeholders, Blob, ID)) - report_fatal_error("Can't lazyload MD"); + if (Expected MaybeCode = IndexCursor.readRecord(Entry.ID, Record, &Blob)) { + if (Error Err = parseOneMetadata(Record, MaybeCode.get(), Placeholders, Blob, ID)) + report_fatal_error("Can't lazyload MD, parseOneMetadata: " + toString(std::move(Err))); + } else + report_fatal_error("Can't lazyload MD: " + toString(MaybeCode.takeError())); } /// Ensure that all forward-references and placeholders are resolved. @@ -1032,12 +1073,17 @@ // Read name of the named metadata. SmallString<8> Name(Record.begin(), Record.end()); Record.clear(); - Code = Stream.ReadCode(); + Expected MaybeCode = Stream.ReadCode(); + if (!MaybeCode) + return MaybeCode.takeError(); + Code = MaybeCode.get(); ++NumMDRecordLoaded; - unsigned NextBitCode = Stream.readRecord(Code, Record); - if (NextBitCode != bitc::METADATA_NAMED_NODE) - return error("METADATA_NAME not followed by METADATA_NAMED_NODE"); + if (Expected MaybeNextBitCode = Stream.readRecord(Code, Record)) { + if (MaybeNextBitCode.get() != bitc::METADATA_NAMED_NODE) + return error("METADATA_NAME not followed by METADATA_NAMED_NODE"); + } else + return MaybeNextBitCode.takeError(); // Read named metadata elements. unsigned Size = Record.size(); @@ -1863,7 +1909,10 @@ if (R.AtEndOfStream()) return error("Invalid record: metadata strings bad length"); - unsigned Size = R.ReadVBR(6); + Expected MaybeSize = R.ReadVBR(6); + if (!MaybeSize) + return MaybeSize.takeError(); + uint32_t Size = MaybeSize.get(); if (Strings.size() < Size) return error("Invalid record: metadata strings truncated chars"); @@ -1899,7 +1948,10 @@ PlaceholderQueue Placeholders; while (true) { - BitstreamEntry Entry = Stream.advanceSkippingSubblocks(); + Expected MaybeEntry = Stream.advanceSkippingSubblocks(); + if (!MaybeEntry) + return MaybeEntry.takeError(); + BitstreamEntry Entry = MaybeEntry.get(); switch (Entry.Kind) { case BitstreamEntry::SubBlock: // Handled for us already. @@ -1916,7 +1968,10 @@ // Read a metadata attachment record. Record.clear(); ++NumMDRecordLoaded; - switch (Stream.readRecord(Entry.ID, Record)) { + Expected MaybeRecord = Stream.readRecord(Entry.ID, Record); + if (!MaybeRecord) + return MaybeRecord.takeError(); + switch (MaybeRecord.get()) { default: // Default behavior: ignore. break; case bitc::METADATA_ATTACHMENT: { @@ -1997,7 +2052,10 @@ // Read all the records. while (true) { - BitstreamEntry Entry = Stream.advanceSkippingSubblocks(); + Expected MaybeEntry = Stream.advanceSkippingSubblocks(); + if (!MaybeEntry) + return MaybeEntry.takeError(); + BitstreamEntry Entry = MaybeEntry.get(); switch (Entry.Kind) { case BitstreamEntry::SubBlock: // Handled for us already. @@ -2013,8 +2071,10 @@ // Read a record. Record.clear(); ++NumMDRecordLoaded; - unsigned Code = Stream.readRecord(Entry.ID, Record); - switch (Code) { + Expected MaybeCode = Stream.readRecord(Entry.ID, Record); + if (!MaybeCode) + return MaybeCode.takeError(); + switch (MaybeCode.get()) { default: // Default behavior: ignore. break; case bitc::METADATA_KIND: { diff --git a/llvm/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp b/llvm/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp --- a/llvm/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp +++ b/llvm/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp @@ -451,13 +451,17 @@ -/// ReportError - All bitcode analysis errors go through this function, making this a -/// good place to breakpoint if debugging. +/// All bitcode analysis errors go through this function, making this a good +/// place to breakpoint if debugging. static bool ReportError(const Twine &Err) { WithColor::error() << Err << "\n"; return true; } +static bool ReportError(Error &&Err) { + return ReportError(toString(std::move(Err))); +} + static bool decodeMetadataStringsBlob(StringRef Indent, ArrayRef Record, StringRef Blob) { @@ -478,7 +482,10 @@ if (R.AtEndOfStream()) return ReportError("bad length"); - unsigned Size = R.ReadVBR(6); + Expected MaybeSize = R.ReadVBR(6); + if (!MaybeSize) + return ReportError(MaybeSize.takeError()); + uint32_t Size = MaybeSize.get(); if (Strings.size() < Size) return ReportError("truncated chars"); @@ -518,12 +525,16 @@ bool DumpRecords = Dump; if (BlockID == bitc::BLOCKINFO_BLOCK_ID) { if (Dump) outs() << Indent << "\n"; - Optional NewBlockInfo = + Expected> MaybeNewBlockInfo = Stream.ReadBlockInfoBlock(/*ReadBlockInfoNames=*/true); + if (!MaybeNewBlockInfo) + return ReportError(MaybeNewBlockInfo.takeError()); + Optional NewBlockInfo = std::move(MaybeNewBlockInfo.get()); if (!NewBlockInfo) return ReportError("Malformed BlockInfoBlock"); BlockInfo = std::move(*NewBlockInfo); - Stream.JumpToBit(BlockBitStart); + if (Error Err = Stream.JumpToBit(BlockBitStart)) + return ReportError(std::move(Err)); // It's not really interesting to dump the contents of the blockinfo block. DumpRecords = false; } @@ -562,9 +573,11 @@ uint64_t RecordStartBit = Stream.GetCurrentBitNo(); - BitstreamEntry Entry = - Stream.advance(BitstreamCursor::AF_DontAutoprocessAbbrevs); - + Expected MaybeEntry = Stream.advance(BitstreamCursor::AF_DontAutoprocessAbbrevs); + if (!MaybeEntry) + return ReportError(MaybeEntry.takeError()); + BitstreamEntry Entry = MaybeEntry.get(); + switch (Entry.Kind) { case BitstreamEntry::Error: return ReportError("malformed bitcode file"); @@ -599,7 +612,8 @@ } if (Entry.ID == bitc::DEFINE_ABBREV) { - Stream.ReadAbbrevRecord(); + if (Error Err = Stream.ReadAbbrevRecord()) + return ReportError(std::move(Err)); ++BlockStats.NumAbbrevs; continue; } @@ -610,7 +624,10 @@ StringRef Blob; uint64_t CurrentRecordPos = Stream.GetCurrentBitNo(); - unsigned Code = Stream.readRecord(Entry.ID, Record, &Blob); + Expected MaybeCode = Stream.readRecord(Entry.ID, Record, &Blob); + if (!MaybeCode) + return ReportError(MaybeCode.takeError()); + unsigned Code = MaybeCode.get(); // Increment the # occurrences of this code. if (BlockStats.CodeFreq.size() <= Code) @@ -742,8 +759,12 @@ } // Make sure that we can skip the current record. - Stream.JumpToBit(CurrentRecordPos); - Stream.skipRecord(Entry.ID); + if (Error Err = Stream.JumpToBit(CurrentRecordPos)) + return ReportError(std::move(Err)); + if (Expected Skipped = Stream.skipRecord(Entry.ID)) + ; // Do nothing. + else + return ReportError(Skipped.takeError()); } } @@ -755,27 +776,35 @@ (double)Bits/8, (unsigned long)(Bits/32)); } -static CurStreamTypeType ReadSignature(BitstreamCursor &Stream) { +static Expected ReadSignature(BitstreamCursor &Stream) { + auto tryRead = [&Stream] (char &Dest, size_t size) -> Error { + if (Expected MaybeWord = Stream.Read(size)) + Dest = MaybeWord.get(); + else + return MaybeWord.takeError(); + return Error::success(); + }; + char Signature[6]; - Signature[0] = Stream.Read(8); - Signature[1] = Stream.Read(8); + if (Error Err = tryRead(Signature[0], 8)) return std::move(Err); + if (Error Err = tryRead(Signature[1], 8)) return std::move(Err); // Autodetect the file contents, if it is one we know. if (Signature[0] == 'C' && Signature[1] == 'P') { - Signature[2] = Stream.Read(8); - Signature[3] = Stream.Read(8); + if (Error Err = tryRead(Signature[2], 8)) return std::move(Err); + if (Error Err = tryRead(Signature[3], 8)) return std::move(Err); if (Signature[2] == 'C' && Signature[3] == 'H') return ClangSerializedASTBitstream; } else if (Signature[0] == 'D' && Signature[1] == 'I') { - Signature[2] = Stream.Read(8); - Signature[3] = Stream.Read(8); + if (Error Err = tryRead(Signature[2], 8)) return std::move(Err); + if (Error Err = tryRead(Signature[3], 8)) return std::move(Err); if (Signature[2] == 'A' && Signature[3] == 'G') return ClangSerializedDiagnosticsBitstream; } else { - Signature[2] = Stream.Read(4); - Signature[3] = Stream.Read(4); - Signature[4] = Stream.Read(4); - Signature[5] = Stream.Read(4); + if (Error Err = tryRead(Signature[2], 4)) return std::move(Err); + if (Error Err = tryRead(Signature[3], 4)) return std::move(Err); + if (Error Err = tryRead(Signature[4], 4)) return std::move(Err); + if (Error Err = tryRead(Signature[5], 4)) return std::move(Err); if (Signature[0] == 'B' && Signature[1] == 'C' && Signature[2] == 0x0 && Signature[3] == 0xC && Signature[4] == 0xE && Signature[5] == 0xD) @@ -827,7 +856,10 @@ } Stream = BitstreamCursor(ArrayRef(BufPtr, EndBufPtr)); - CurStreamType = ReadSignature(Stream); + Expected MaybeSignature = ReadSignature(Stream); + if (!MaybeSignature) + return ReportError(MaybeSignature.takeError()); + CurStreamType = std::move(MaybeSignature.get()); return false; } @@ -853,21 +885,31 @@ return true; while (!BlockInfoCursor.AtEndOfStream()) { - unsigned Code = BlockInfoCursor.ReadCode(); - if (Code != bitc::ENTER_SUBBLOCK) + Expected MaybeCode = BlockInfoCursor.ReadCode(); + if (!MaybeCode) + return ReportError(MaybeCode.takeError()); + if (MaybeCode.get() != bitc::ENTER_SUBBLOCK) return ReportError("Invalid record at top-level in block info file"); - unsigned BlockID = BlockInfoCursor.ReadSubBlockID(); - if (BlockID == bitc::BLOCKINFO_BLOCK_ID) { - Optional NewBlockInfo = - BlockInfoCursor.ReadBlockInfoBlock(/*ReadBlockInfoNames=*/true); + Expected MaybeBlockID = BlockInfoCursor.ReadSubBlockID(); + if (!MaybeBlockID) + return ReportError(MaybeBlockID.takeError()); + if (MaybeBlockID.get() == bitc::BLOCKINFO_BLOCK_ID) { + Expected> MaybeNewBlockInfo = + BlockInfoCursor.ReadBlockInfoBlock(/*ReadBlockInfoNames=*/true); + if (!MaybeNewBlockInfo) + return ReportError(MaybeNewBlockInfo.takeError()); + Optional NewBlockInfo = std::move(MaybeNewBlockInfo.get()); if (!NewBlockInfo) return ReportError("Malformed BlockInfoBlock in block info file"); BlockInfo = std::move(*NewBlockInfo); break; } - BlockInfoCursor.SkipBlock(); + if (Expected SkipBlock = BlockInfoCursor.SkipBlock()) + ; // Ignore result. + else + return ReportError(SkipBlock.takeError()); } } @@ -875,13 +917,17 @@ // Parse the top-level structure. We only allow blocks at the top-level. while (!Stream.AtEndOfStream()) { - unsigned Code = Stream.ReadCode(); - if (Code != bitc::ENTER_SUBBLOCK) + Expected MaybeCode = Stream.ReadCode(); + if (!MaybeCode) + return ReportError(MaybeCode.takeError()); + if (MaybeCode.get() != bitc::ENTER_SUBBLOCK) return ReportError("Invalid record at top-level"); - unsigned BlockID = Stream.ReadSubBlockID(); + Expected MaybeBlockID = Stream.ReadSubBlockID(); + if (!MaybeBlockID) + return ReportError(MaybeBlockID.takeError()); - if (ParseBlock(Stream, BlockInfo, BlockID, 0, CurStreamType)) + if (ParseBlock(Stream, BlockInfo, MaybeBlockID.get(), 0, CurStreamType)) return true; ++NumTopBlocks; }