llvm::Error ClangDocBitcodeReader::readRecord(unsigned ID, T I) {
Record R;
llvm::StringRef Blob;
- unsigned RecID = Stream.readRecord(ID, R, &Blob);
- return parseRecord(R, RecID, Blob, I);
+ llvm::Expected<unsigned> MaybeRecID = Stream.readRecord(ID, R, &Blob);
+ if (!MaybeRecID)
+ return MaybeRecID.takeError();
+ return parseRecord(R, MaybeRecID.get(), Blob, I);
}
template <>
llvm::Error ClangDocBitcodeReader::readRecord(unsigned ID, Reference *I) {
Record R;
llvm::StringRef Blob;
- unsigned RecID = Stream.readRecord(ID, R, &Blob);
- return parseRecord(R, RecID, Blob, I, CurrentReferenceField);
+ llvm::Expected<unsigned> MaybeRecID = Stream.readRecord(ID, R, &Blob);
+ if (!MaybeRecID)
+ return MaybeRecID.takeError();
+ return parseRecord(R, MaybeRecID.get(), Blob, I, CurrentReferenceField);
}
// Read a block of records into a single info.
template <typename T>
llvm::Error ClangDocBitcodeReader::readBlock(unsigned ID, T I) {
- if (Stream.EnterSubBlock(ID))
- return llvm::make_error<llvm::StringError>("Unable to enter subblock.\n",
- llvm::inconvertibleErrorCode());
+ if (llvm::Error Err = Stream.EnterSubBlock(ID))
+ return Err;
while (true) {
unsigned BlockOrCode = 0;
case Cursor::BlockEnd:
return llvm::Error::success();
case Cursor::BlockBegin:
- if (auto Err = readSubBlock(BlockOrCode, I)) {
- if (!Stream.SkipBlock())
- continue;
+ if (llvm::Error Err = readSubBlock(BlockOrCode, I)) {
+ if (llvm::Error Skipped = Stream.SkipBlock())
+ return joinErrors(std::move(Err), std::move(Skipped));
return Err;
}
continue;
BlockOrRecordID = 0;
while (!Stream.AtEndOfStream()) {
- unsigned Code = Stream.ReadCode();
+ Expected<unsigned> MaybeCode = Stream.ReadCode();
+ if (!MaybeCode) {
+ // FIXME this drops the error on the floor.
+ consumeError(MaybeCode.takeError());
+ return Cursor::BadBlock;
+ }
- switch ((llvm::bitc::FixedAbbrevIDs)Code) {
+ // FIXME check that the enum is in range.
+ auto Code = static_cast<llvm::bitc::FixedAbbrevIDs>(MaybeCode.get());
+
+ switch (Code) {
case llvm::bitc::ENTER_SUBBLOCK:
- BlockOrRecordID = Stream.ReadSubBlockID();
+ if (Expected<unsigned> MaybeID = Stream.ReadSubBlockID())
+ BlockOrRecordID = MaybeID.get();
+ else {
+ // FIXME this drops the error on the floor.
+ consumeError(MaybeID.takeError());
+ }
return Cursor::BlockBegin;
case llvm::bitc::END_BLOCK:
if (Stream.ReadBlockEnd())
return Cursor::BadBlock;
return Cursor::BlockEnd;
case llvm::bitc::DEFINE_ABBREV:
- Stream.ReadAbbrevRecord();
+ if (llvm::Error Err = Stream.ReadAbbrevRecord()) {
+ // FIXME this drops the error on the floor.
+ consumeError(std::move(Err));
+ }
continue;
case llvm::bitc::UNABBREV_RECORD:
return Cursor::BadBlock;
llvm::inconvertibleErrorCode());
// Sniff for the signature.
- if (Stream.Read(8) != BitCodeConstants::Signature[0] ||
- Stream.Read(8) != BitCodeConstants::Signature[1] ||
- Stream.Read(8) != BitCodeConstants::Signature[2] ||
- Stream.Read(8) != BitCodeConstants::Signature[3])
- return llvm::make_error<llvm::StringError>("Invalid bitcode signature.\n",
- llvm::inconvertibleErrorCode());
+ for (int Idx = 0; Idx != 4; ++Idx) {
+ Expected<llvm::SimpleBitstreamCursor::word_t> MaybeRead = Stream.Read(8);
+ if (!MaybeRead)
+ return MaybeRead.takeError();
+ else if (MaybeRead.get() != BitCodeConstants::Signature[Idx])
+ return llvm::make_error<llvm::StringError>(
+ "Invalid bitcode signature.\n", llvm::inconvertibleErrorCode());
+ }
return llvm::Error::success();
}
llvm::Error ClangDocBitcodeReader::readBlockInfoBlock() {
- BlockInfo = Stream.ReadBlockInfoBlock();
+ Expected<Optional<llvm::BitstreamBlockInfo>> MaybeBlockInfo =
+ Stream.ReadBlockInfoBlock();
+ if (!MaybeBlockInfo)
+ return MaybeBlockInfo.takeError();
+ else
+ BlockInfo = MaybeBlockInfo.get();
if (!BlockInfo)
return llvm::make_error<llvm::StringError>(
"Unable to parse BlockInfoBlock.\n", llvm::inconvertibleErrorCode());
// Read the top level blocks.
while (!Stream.AtEndOfStream()) {
- unsigned Code = Stream.ReadCode();
- if (Code != llvm::bitc::ENTER_SUBBLOCK)
+ Expected<unsigned> MaybeCode = Stream.ReadCode();
+ if (!MaybeCode)
+ return MaybeCode.takeError();
+ if (MaybeCode.get() != llvm::bitc::ENTER_SUBBLOCK)
return llvm::make_error<llvm::StringError>(
"No blocks in input.\n", llvm::inconvertibleErrorCode());
- unsigned ID = Stream.ReadSubBlockID();
+ Expected<unsigned> MaybeID = Stream.ReadSubBlockID();
+ if (!MaybeID)
+ return MaybeID.takeError();
+ unsigned ID = MaybeID.get();
switch (ID) {
// NamedType and Comment blocks should not appear at the top level
case BI_TYPE_BLOCK_ID:
return std::move(Err);
continue;
default:
- if (!Stream.SkipBlock())
- continue;
+ if (llvm::Error Err = Stream.SkipBlock()) {
+ // FIXME this drops the error on the floor.
+ consumeError(std::move(Err));
+ }
+ continue;
}
}
return std::move(Infos);
// AbbreviationMap
-constexpr char BitCodeConstants::Signature[];
+constexpr unsigned char BitCodeConstants::Signature[];
void ClangDocBitcodeWriter::AbbreviationMap::add(RecordId RID,
unsigned AbbrevID) {
static constexpr unsigned ReferenceTypeSize = 8U;
static constexpr unsigned USRLengthSize = 6U;
static constexpr unsigned USRBitLengthSize = 8U;
- static constexpr char Signature[4] = {'D', 'O', 'C', 'S'};
+ static constexpr unsigned char Signature[4] = {'D', 'O', 'C', 'S'};
static constexpr int USRHashSize = 20;
};
// Collect tokens of the main file.
syntax::TokenCollector Tokens(Clang->getPreprocessor());
- if (!Action->Execute())
- log("Execute() failed when building AST for {0}", MainInput.getFile());
+ if (llvm::Error Err = Action->Execute())
+ log("Execute() failed when building AST for {0}: {1}", MainInput.getFile(),
+ toString(std::move(Err)));
std::vector<Decl *> ParsedDecls = Action->takeTopLevelDecls();
// AST traversals should exclude the preamble, to avoid performance cliffs.
if (Includes)
Clang->getPreprocessor().addPPCallbacks(
collectIncludeStructureCallback(Clang->getSourceManager(), Includes));
- if (!Action.Execute()) {
- log("Execute() failed when running codeComplete for {0}", Input.FileName);
+ if (llvm::Error Err = Action.Execute()) {
+ log("Execute() failed when running codeComplete for {0}: {1}",
+ Input.FileName, toString(std::move(Err)));
return false;
}
Action.EndSourceFile();
if (!Action->BeginSourceFile(*Clang, Input))
return llvm::createStringError(llvm::inconvertibleErrorCode(),
"BeginSourceFile() failed");
- if (!Action->Execute())
- return llvm::createStringError(llvm::inconvertibleErrorCode(),
- "Execute() failed");
+ if (llvm::Error Err = Action->Execute())
+ return Err;
+
Action->EndSourceFile();
if (Clang->hasDiagnostics() &&
Clang->getDiagnostics().hasUncompilableErrorOccurred()) {
IncludeStructure Includes;
Clang->getPreprocessor().addPPCallbacks(
collectIncludeStructureCallback(Clang->getSourceManager(), &Includes));
- EXPECT_TRUE(Action.Execute());
+ EXPECT_FALSE(Action.Execute());
Action.EndSourceFile();
return Includes;
}
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/Support/Compiler.h"
+#include "llvm/Support/Error.h"
#include <cassert>
#include <cstdint>
#include <limits>
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);
}
#include "clang/Frontend/ASTUnit.h"
#include "clang/Frontend/FrontendOptions.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Error.h"
#include <memory>
#include <string>
#include <vector>
bool BeginSourceFile(CompilerInstance &CI, const FrontendInputFile &Input);
/// Set the source manager's main input file, and run the action.
- bool Execute();
+ llvm::Error Execute();
/// Perform any per-file post processing, deallocate per-file
/// objects, and run statistics and output file cleanup code.
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
/// Reads a record with id AbbrevID from Cursor, resetting the
/// internal state.
- unsigned readRecord(llvm::BitstreamCursor &Cursor, unsigned AbbrevID);
+ Expected<unsigned> 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(); }
: 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:
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Error.h"
#include <memory>
#include <utility>
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<GlobalModuleIndex *, ErrorCode>
+ /// the error.
+ static std::pair<GlobalModuleIndex *, llvm::Error>
readIndex(llvm::StringRef Path);
/// Returns an iterator for identifiers stored in the index table.
/// 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);
};
}
else
PreambleSrcLocCache.clear();
- if (!Act->Execute())
+ if (llvm::Error Err = Act->Execute()) {
+ consumeError(std::move(Err)); // FIXME this drops errors on the floor.
goto error;
+ }
transferASTDataFromCompilerInstance(*Clang);
Clang->setASTConsumer(
llvm::make_unique<MultiplexConsumer>(std::move(Consumers)));
}
- if (!Act->Execute()) {
+ if (llvm::Error Err = Act->Execute()) {
+ consumeError(std::move(Err)); // FIXME this drops errors on the floor.
AST->transferASTDataFromCompilerInstance(*Clang);
if (OwnAST && ErrAST)
ErrAST->swap(OwnAST);
std::unique_ptr<SyntaxOnlyAction> Act;
Act.reset(new SyntaxOnlyAction);
if (Act->BeginSourceFile(*Clang.get(), Clang->getFrontendOpts().Inputs[0])) {
- Act->Execute();
+ if (llvm::Error Err = Act->Execute()) {
+ consumeError(std::move(Err)); // FIXME this drops errors on the floor.
+ }
Act->EndSourceFile();
}
}
getSourceManager().clearIDTables();
if (Act.BeginSourceFile(*this, FIF)) {
- Act.Execute();
+ if (llvm::Error Err = Act.Execute()) {
+ consumeError(std::move(Err)); // FIXME this drops errors on the floor.
+ }
Act.EndSourceFile();
}
}
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). It should handle the
+ // error.
+ consumeError(std::move(Err));
+ return nullptr;
+ }
ModuleManager->resetForReload();
ModuleManager->loadGlobalIndex();
GlobalIndex = ModuleManager->getGlobalIndex();
}
}
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.
+ consumeError(std::move(Err));
+ return nullptr;
+ }
ModuleManager->resetForReload();
ModuleManager->loadGlobalIndex();
GlobalIndex = ModuleManager->getGlobalIndex();
return false;
}
-bool FrontendAction::Execute() {
+llvm::Error FrontendAction::Execute() {
CompilerInstance &CI = getCompilerInstance();
if (CI.hasFrontendTimer()) {
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)) {
+ // FIXME this drops the error on the floor, but
+ // Index/pch-from-libclang.c seems to rely on dropping at least some of
+ // the error conditions!
+ consumeError(std::move(Err));
+ }
+ }
}
- return true;
+ return llvm::Error::success();
}
void FrontendAction::EndSourceFile() {
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);
FixItOpts->FixOnlyWarnings = FEOpts.FixOnlyWarnings;
FixItRewriter Rewriter(CI.getDiagnostics(), CI.getSourceManager(),
CI.getLangOpts(), FixItOpts.get());
- FixAction->Execute();
+ if (llvm::Error Err = FixAction->Execute()) {
+ // FIXME this drops the error on the floor.
+ consumeError(std::move(Err));
+ return false;
+ }
err = Rewriter.WriteFixedFiles(&RewrittenFiles);
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<llvm::SimpleBitstreamCursor::word_t> Res = Stream.Read(8)) {
+ if (Res.get() == C)
+ continue;
+ } else {
+ // FIXME this drops the error on the floor.
+ consumeError(Res.takeError());
+ }
return SDError::InvalidSignature;
+ }
// Read the top level blocks.
while (!Stream.AtEndOfStream()) {
- if (Stream.ReadCode() != llvm::bitc::ENTER_SUBBLOCK)
+ if (Expected<unsigned> Res = Stream.ReadCode()) {
+ if (Res.get() != llvm::bitc::ENTER_SUBBLOCK)
+ return SDError::InvalidDiagnostics;
+ } else {
+ // FIXME this drops the error on the floor.
+ consumeError(Res.takeError());
return SDError::InvalidDiagnostics;
+ }
std::error_code EC;
- switch (Stream.ReadSubBlockID()) {
- case llvm::bitc::BLOCKINFO_BLOCK_ID:
- BlockInfo = Stream.ReadBlockInfoBlock();
+ Expected<unsigned> MaybeSubBlockID = Stream.ReadSubBlockID();
+ if (!MaybeSubBlockID) {
+ // FIXME this drops the error on the floor.
+ consumeError(MaybeSubBlockID.takeError());
+ return SDError::InvalidDiagnostics;
+ }
+
+ switch (MaybeSubBlockID.get()) {
+ case llvm::bitc::BLOCKINFO_BLOCK_ID: {
+ Expected<Optional<llvm::BitstreamBlockInfo>> MaybeBlockInfo =
+ Stream.ReadBlockInfoBlock();
+ if (!MaybeBlockInfo) {
+ // FIXME this drops the error on the floor.
+ consumeError(MaybeBlockInfo.takeError());
+ return SDError::InvalidDiagnostics;
+ }
+ BlockInfo = std::move(MaybeBlockInfo.get());
+ }
if (!BlockInfo)
return SDError::MalformedBlockInfoBlock;
Stream.setBlockInfo(&*BlockInfo);
return EC;
continue;
default:
- if (!Stream.SkipBlock())
+ if (llvm::Error Err = Stream.SkipBlock()) {
+ // FIXME this drops the error on the floor.
+ consumeError(std::move(Err));
return SDError::MalformedTopLevelBlock;
+ }
continue;
}
}
BlockOrRecordID = 0;
while (!Stream.AtEndOfStream()) {
- unsigned Code = Stream.ReadCode();
+ unsigned Code;
+ if (Expected<unsigned> 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<unsigned> Res = Stream.ReadSubBlockID())
+ BlockOrRecordID = Res.get();
+ else
+ return llvm::errorToErrorCode(Res.takeError());
return Cursor::BlockBegin;
case llvm::bitc::END_BLOCK:
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:
std::error_code
SerializedDiagnosticReader::readMetaBlock(llvm::BitstreamCursor &Stream) {
- if (Stream.EnterSubBlock(clang::serialized_diags::BLOCK_META))
+ if (llvm::Error Err =
+ Stream.EnterSubBlock(clang::serialized_diags::BLOCK_META)) {
+ // FIXME this drops the error on the floor.
+ consumeError(std::move(Err));
return SDError::MalformedMetadataBlock;
+ }
bool VersionChecked = false;
case Cursor::Record:
break;
case Cursor::BlockBegin:
- if (Stream.SkipBlock())
+ if (llvm::Error Err = Stream.SkipBlock()) {
+ // FIXME this drops the error on the floor.
+ consumeError(std::move(Err));
return SDError::MalformedMetadataBlock;
+ }
LLVM_FALLTHROUGH;
case Cursor::BlockEnd:
if (!VersionChecked)
}
SmallVector<uint64_t, 1> Record;
- unsigned RecordID = Stream.readRecord(BlockOrCode, Record);
+ Expected<unsigned> MaybeRecordID = Stream.readRecord(BlockOrCode, Record);
+ if (!MaybeRecordID)
+ return errorToErrorCode(MaybeRecordID.takeError());
+ unsigned RecordID = MaybeRecordID.get();
if (RecordID == RECORD_VERSION) {
if (Record.size() < 1)
std::error_code
SerializedDiagnosticReader::readDiagnosticBlock(llvm::BitstreamCursor &Stream) {
- if (Stream.EnterSubBlock(clang::serialized_diags::BLOCK_DIAG))
+ if (llvm::Error Err =
+ Stream.EnterSubBlock(clang::serialized_diags::BLOCK_DIAG)) {
+ // FIXME this drops the error on the floor.
+ consumeError(std::move(Err));
return SDError::MalformedDiagnosticBlock;
+ }
std::error_code EC;
if ((EC = visitStartOfDiagnostic()))
if (BlockOrCode == serialized_diags::BLOCK_DIAG) {
if ((EC = readDiagnosticBlock(Stream)))
return EC;
- } else if (!Stream.SkipBlock())
+ } else if (llvm::Error Err = Stream.SkipBlock()) {
+ // FIXME this drops the error on the floor.
+ consumeError(std::move(Err));
return SDError::MalformedSubBlock;
+ }
continue;
case Cursor::BlockEnd:
if ((EC = visitEndOfDiagnostic()))
// Read the record.
Record.clear();
StringRef Blob;
- unsigned RecID = Stream.readRecord(BlockOrCode, Record, &Blob);
+ Expected<unsigned> 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)
// Read the extension block.
SmallVector<uint64_t, 4> Record;
while (true) {
- llvm::BitstreamEntry Entry = Stream.advanceSkippingSubblocks();
+ llvm::Expected<llvm::BitstreamEntry> MaybeEntry =
+ Stream.advanceSkippingSubblocks();
+ if (!MaybeEntry)
+ (void)MaybeEntry.takeError();
+ llvm::BitstreamEntry Entry = MaybeEntry.get();
+
switch (Entry.Kind) {
case llvm::BitstreamEntry::SubBlock:
case llvm::BitstreamEntry::EndBlock:
Record.clear();
StringRef Blob;
- unsigned RecCode = Stream.readRecord(Entry.ID, Record, &Blob);
- switch (RecCode) {
+ Expected<unsigned> 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",
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<unsigned> MaybeCode = Cursor.ReadCode();
+ if (!MaybeCode) {
+ Error(MaybeCode.takeError());
+ return true;
+ }
+ unsigned Code = MaybeCode.get();
+
+ Expected<unsigned> 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;
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<unsigned> MaybeCode = Cursor.ReadCode();
+ if (!MaybeCode) {
+ Error(MaybeCode.takeError());
+ return true;
+ }
+ unsigned Code = MaybeCode.get();
+
+ Expected<unsigned> 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;
Diag(DiagID) << Arg1 << Arg2;
}
+void ASTReader::Error(llvm::Error &&Err) const {
+ Error(toString(std::move(Err)));
+}
+
//===----------------------------------------------------------------------===//
// Source Manager Deserialization
//===----------------------------------------------------------------------===//
SLocEntryCursor = F.Stream;
// The stream itself is going to skip over the source manager block.
- if (F.Stream.SkipBlock()) {
- Error("malformed block record in AST file");
+ if (llvm::Error Err = F.Stream.SkipBlock()) {
+ Error(std::move(Err));
return true;
}
// Enter the source manager block.
- if (SLocEntryCursor.EnterSubBlock(SOURCE_MANAGER_BLOCK_ID)) {
- Error("malformed source manager block record in AST file");
+ if (llvm::Error Err =
+ SLocEntryCursor.EnterSubBlock(SOURCE_MANAGER_BLOCK_ID)) {
+ Error(std::move(Err));
return true;
}
RecordData Record;
while (true) {
- llvm::BitstreamEntry E = SLocEntryCursor.advanceSkippingSubblocks();
+ Expected<llvm::BitstreamEntry> 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.
// Read a record.
Record.clear();
StringRef Blob;
- switch (SLocEntryCursor.readRecord(E.ID, Record, &Blob)) {
+ Expected<unsigned> MaybeRecord =
+ SLocEntryCursor.readRecord(E.ID, Record, &Blob);
+ if (!MaybeRecord) {
+ Error(MaybeRecord.takeError());
+ return true;
+ }
+ switch (MaybeRecord.get()) {
default: // Default behavior: ignore.
break;
StringRef Name) -> std::unique_ptr<llvm::MemoryBuffer> {
RecordData Record;
StringRef Blob;
- unsigned Code = SLocEntryCursor.ReadCode();
- unsigned RecCode = SLocEntryCursor.readRecord(Code, Record, &Blob);
+ Expected<unsigned> MaybeCode = SLocEntryCursor.ReadCode();
+ if (!MaybeCode) {
+ Error(MaybeCode.takeError());
+ return nullptr;
+ }
+ unsigned Code = MaybeCode.get();
+
+ Expected<unsigned> 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()) {
};
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<llvm::BitstreamEntry> 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;
RecordData Record;
StringRef Blob;
- switch (SLocEntryCursor.readRecord(Entry.ID, Record, &Blob)) {
+ Expected<unsigned> 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;
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))
+ if (llvm::Error Err = Cursor.EnterSubBlock(BlockID)) {
+ // FIXME this drops errors on the floor.
+ consumeError(std::move(Err));
return true;
+ }
while (true) {
uint64_t Offset = Cursor.GetCurrentBitNo();
- unsigned Code = Cursor.ReadCode();
+ Expected<unsigned> MaybeCode = Cursor.ReadCode();
+ if (!MaybeCode) {
+ // FIXME this drops errors on the floor.
+ consumeError(MaybeCode.takeError());
+ 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.
+ consumeError(std::move(Err));
+ return true;
+ }
return false;
}
- Cursor.ReadAbbrevRecord();
+ if (llvm::Error Err = Cursor.ReadAbbrevRecord()) {
+ // FIXME this drops errors on the floor.
+ consumeError(std::move(Err));
+ return true;
+ }
}
}
// after reading this macro.
SavedStreamPosition SavedPosition(Stream);
- Stream.JumpToBit(Offset);
+ if (llvm::Error Err = Stream.JumpToBit(Offset)) {
+ // FIXME this drops errors on the floor.
+ consumeError(std::move(Err));
+ return nullptr;
+ }
RecordData Record;
SmallVector<IdentifierInfo*, 16> MacroParams;
MacroInfo *Macro = nullptr;
// 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<llvm::BitstreamEntry> 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.
// Read a record.
Record.clear();
- PreprocessorRecordTypes RecType =
- (PreprocessorRecordTypes)Stream.readRecord(Entry.ID, Record);
+ PreprocessorRecordTypes RecType;
+ if (Expected<unsigned> 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:
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<llvm::BitstreamEntry> 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.
case llvm::BitstreamEntry::EndBlock:
goto NextCursor;
- case llvm::BitstreamEntry::Record:
+ case llvm::BitstreamEntry::Record: {
Record.clear();
- switch (Cursor.readRecord(E.ID, Record)) {
+ Expected<unsigned> MaybeRecord = Cursor.readRecord(E.ID, Record);
+ if (!MaybeRecord) {
+ Error(MaybeRecord.takeError());
+ return;
+ }
+ switch (MaybeRecord.get()) {
default: // Default behavior: ignore.
break;
}
break;
}
+ }
}
NextCursor: ;
}
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;
// macro histroy.
RecordData Record;
while (true) {
- llvm::BitstreamEntry Entry =
+ Expected<llvm::BitstreamEntry> 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<unsigned> MaybePP = Cursor.readRecord(Entry.ID, Record);
+ if (!MaybePP) {
+ Error(MaybePP.takeError());
+ return;
+ }
+ switch ((PreprocessorRecordTypes)MaybePP.get()) {
case PP_MACRO_DIRECTIVE_HISTORY:
break;
// 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.
+ consumeError(std::move(Err));
+ }
- unsigned Code = Cursor.ReadCode();
+ Expected<unsigned> MaybeCode = Cursor.ReadCode();
+ if (!MaybeCode) {
+ // FIXME this drops errors on the floor.
+ consumeError(MaybeCode.takeError());
+ }
+ unsigned Code = MaybeCode.get();
RecordData Record;
StringRef Blob;
- unsigned Result = Cursor.readRecord(Code, Record, &Blob);
- assert(static_cast<InputFileRecordTypes>(Result) == INPUT_FILE &&
- "invalid record type for input file");
- (void)Result;
+ if (Expected<unsigned> Maybe = Cursor.readRecord(Code, Record, &Blob))
+ assert(static_cast<InputFileRecordTypes>(Maybe.get()) == INPUT_FILE &&
+ "invalid record type for input file");
+ else {
+ // FIXME this drops errors on the floor.
+ consumeError(Maybe.takeError());
+ }
assert(Record[0] == ID && "Bogus stored ID or offset");
InputFileInfo R;
// 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.
+ consumeError(std::move(Err));
+ }
InputFileInfo FI = readInputFileInfo(F, ID);
off_t StoredSize = FI.StoredSize;
BitstreamCursor &Stream, unsigned ClientLoadCapabilities,
bool AllowCompatibleConfigurationMismatch, ASTReaderListener &Listener,
std::string &SuggestedPredefines) {
- if (Stream.EnterSubBlock(OPTIONS_BLOCK_ID))
+ if (llvm::Error Err = Stream.EnterSubBlock(OPTIONS_BLOCK_ID)) {
+ // FIXME this drops errors on the floor.
+ consumeError(std::move(Err));
return Failure;
+ }
// Read all of the records in the options block.
RecordData Record;
ASTReadResult Result = Success;
while (true) {
- llvm::BitstreamEntry Entry = Stream.advance();
+ Expected<llvm::BitstreamEntry> MaybeEntry = Stream.advance();
+ if (!MaybeEntry) {
+ // FIXME this drops errors on the floor.
+ consumeError(MaybeEntry.takeError());
+ return Failure;
+ }
+ llvm::BitstreamEntry Entry = MaybeEntry.get();
switch (Entry.Kind) {
case llvm::BitstreamEntry::Error:
// Read and process a record.
Record.clear();
- switch ((OptionsRecordTypes)Stream.readRecord(Entry.ID, Record)) {
+ Expected<unsigned> MaybeRecordType = Stream.readRecord(Entry.ID, Record);
+ if (!MaybeRecordType) {
+ // FIXME this drops errors on the floor.
+ consumeError(MaybeRecordType.takeError());
+ return Failure;
+ }
+ switch ((OptionsRecordTypes)MaybeRecordType.get()) {
case LANGUAGE_OPTIONS: {
bool Complain = (ClientLoadCapabilities & ARR_ConfigurationMismatch) == 0;
if (ParseLanguageOptions(Record, Complain, Listener,
BitstreamCursor &Stream = F.Stream;
ASTReadResult Result = Success;
- if (Stream.EnterSubBlock(CONTROL_BLOCK_ID)) {
- Error("malformed block record in AST file");
+ if (llvm::Error Err = Stream.EnterSubBlock(CONTROL_BLOCK_ID)) {
+ Error(std::move(Err));
return Failure;
}
unsigned NumUserInputs = 0;
StringRef BaseDirectoryAsWritten;
while (true) {
- llvm::BitstreamEntry Entry = Stream.advance();
+ Expected<llvm::BitstreamEntry> MaybeEntry = Stream.advance();
+ if (!MaybeEntry) {
+ Error(MaybeEntry.takeError());
+ return Failure;
+ }
+ llvm::BitstreamEntry Entry = MaybeEntry.get();
switch (Entry.Kind) {
case llvm::BitstreamEntry::Error:
switch (Entry.ID) {
case INPUT_FILES_BLOCK_ID:
F.InputFilesCursor = Stream;
- if (Stream.SkipBlock() || // Skip with the main cursor
- // Read the abbreviations
- ReadBlockAbbrevs(F.InputFilesCursor, INPUT_FILES_BLOCK_ID)) {
+ if (llvm::Error Err = Stream.SkipBlock()) {
+ Error(std::move(Err));
+ return Failure;
+ }
+ if (ReadBlockAbbrevs(F.InputFilesCursor, INPUT_FILES_BLOCK_ID)) {
Error("malformed block record in AST file");
return Failure;
}
// middle of a block.
if (Result != Success)
return Result;
- } else if (Stream.SkipBlock()) {
- Error("malformed block record in AST file");
+ } else if (llvm::Error Err = Stream.SkipBlock()) {
+ Error(std::move(Err));
return Failure;
}
continue;
default:
- if (Stream.SkipBlock()) {
- Error("malformed block record in AST file");
+ if (llvm::Error Err = Stream.SkipBlock()) {
+ Error(std::move(Err));
return Failure;
}
continue;
// Read and process a record.
Record.clear();
StringRef Blob;
- switch ((ControlRecordTypes)Stream.readRecord(Entry.ID, Record, &Blob)) {
+ Expected<unsigned> 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)
ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
BitstreamCursor &Stream = F.Stream;
- if (Stream.EnterSubBlock(AST_BLOCK_ID)) {
- Error("malformed block record in AST file");
+ if (llvm::Error Err = Stream.EnterSubBlock(AST_BLOCK_ID)) {
+ Error(std::move(Err));
return Failure;
}
// Read all of the records and blocks for the AST file.
RecordData Record;
while (true) {
- llvm::BitstreamEntry Entry = Stream.advance();
+ Expected<llvm::BitstreamEntry> MaybeEntry = Stream.advance();
+ if (!MaybeEntry) {
+ Error(MaybeEntry.takeError());
+ return Failure;
+ }
+ llvm::BitstreamEntry Entry = MaybeEntry.get();
switch (Entry.Kind) {
case llvm::BitstreamEntry::Error:
// cursor to it, enter the block and read the abbrevs in that block.
// With the main cursor, we just skip over it.
F.DeclsCursor = Stream;
- if (Stream.SkipBlock() || // Skip with the main cursor.
- // Read the abbrevs.
- ReadBlockAbbrevs(F.DeclsCursor, DECLTYPES_BLOCK_ID)) {
+ if (llvm::Error Err = Stream.SkipBlock()) {
+ Error(std::move(Err));
+ return Failure;
+ }
+ if (ReadBlockAbbrevs(F.DeclsCursor, DECLTYPES_BLOCK_ID)) {
Error("malformed block record in AST file");
return Failure;
}
if (!PP.getExternalSource())
PP.setExternalSource(this);
- if (Stream.SkipBlock() ||
- ReadBlockAbbrevs(F.MacroCursor, PREPROCESSOR_BLOCK_ID)) {
+ if (llvm::Error Err = Stream.SkipBlock()) {
+ Error(std::move(Err));
+ return Failure;
+ }
+ if (ReadBlockAbbrevs(F.MacroCursor, PREPROCESSOR_BLOCK_ID)) {
Error("malformed block record in AST file");
return Failure;
}
case PREPROCESSOR_DETAIL_BLOCK_ID:
F.PreprocessorDetailCursor = Stream;
- if (Stream.SkipBlock() ||
- ReadBlockAbbrevs(F.PreprocessorDetailCursor,
+
+ if (llvm::Error Err = Stream.SkipBlock()) {
+ Error(std::move(Err));
+ return Failure;
+ }
+ if (ReadBlockAbbrevs(F.PreprocessorDetailCursor,
PREPROCESSOR_DETAIL_BLOCK_ID)) {
- Error("malformed preprocessor detail record in AST file");
- return Failure;
- }
+ Error("malformed preprocessor detail record in AST file");
+ return Failure;
+ }
F.PreprocessorDetailStartOffset
= F.PreprocessorDetailCursor.GetCurrentBitNo();
case COMMENTS_BLOCK_ID: {
BitstreamCursor C = Stream;
- if (Stream.SkipBlock() ||
- ReadBlockAbbrevs(C, COMMENTS_BLOCK_ID)) {
+
+ if (llvm::Error Err = Stream.SkipBlock()) {
+ Error(std::move(Err));
+ return Failure;
+ }
+ if (ReadBlockAbbrevs(C, COMMENTS_BLOCK_ID)) {
Error("malformed comments block in AST file");
return Failure;
}
}
default:
- if (Stream.SkipBlock()) {
- Error("malformed block record in AST file");
+ if (llvm::Error Err = Stream.SkipBlock()) {
+ Error(std::move(Err));
return Failure;
}
break;
// Read and process a record.
Record.clear();
StringRef Blob;
- auto RecordType =
- (ASTRecordTypes)Stream.readRecord(Entry.ID, Record, &Blob);
+ Expected<unsigned> 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) {
TriedLoadingGlobalIndex = true;
StringRef ModuleCachePath
= getPreprocessor().getHeaderSearchInfo().getModuleCachePath();
- std::pair<GlobalModuleIndex *, GlobalModuleIndex::ErrorCode> Result
- = GlobalModuleIndex::readIndex(ModuleCachePath);
- if (!Result.first)
+ std::pair<GlobalModuleIndex *, llvm::Error> Result =
+ GlobalModuleIndex::readIndex(ModuleCachePath);
+ if (llvm::Error Err = std::move(Result.second)) {
+ assert(!Result.first);
+ consumeError(std::move(Err)); // FIXME this drops errors on the floor.
return true;
+ }
GlobalIndex.reset(Result.first);
ModuleMgr.setGlobalIndex(GlobalIndex.get());
/// true on failure.
static bool SkipCursorToBlock(BitstreamCursor &Cursor, unsigned BlockID) {
while (true) {
- llvm::BitstreamEntry Entry = Cursor.advance();
+ Expected<llvm::BitstreamEntry> MaybeEntry = Cursor.advance();
+ if (!MaybeEntry) {
+ // FIXME this drops errors on the floor.
+ consumeError(MaybeEntry.takeError());
+ return true;
+ }
+ llvm::BitstreamEntry Entry = MaybeEntry.get();
+
switch (Entry.Kind) {
case llvm::BitstreamEntry::Error:
case llvm::BitstreamEntry::EndBlock:
case llvm::BitstreamEntry::Record:
// Ignore top-level records.
- Cursor.skipRecord(Entry.ID);
- break;
+ if (Expected<unsigned> Skipped = Cursor.skipRecord(Entry.ID))
+ break;
+ else {
+ // FIXME this drops errors on the floor.
+ consumeError(Skipped.takeError());
+ return true;
+ }
case llvm::BitstreamEntry::SubBlock:
if (Entry.ID == BlockID) {
- if (Cursor.EnterSubBlock(BlockID))
+ if (llvm::Error Err = Cursor.EnterSubBlock(BlockID)) {
+ // FIXME this drops the error on the floor.
+ consumeError(std::move(Err));
return true;
+ }
// Found it!
return false;
}
- if (Cursor.SkipBlock())
+ if (llvm::Error Err = Cursor.SkipBlock()) {
+ // FIXME this drops the error on the floor.
+ consumeError(std::move(Err));
return true;
+ }
}
}
}
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<llvm::SimpleBitstreamCursor::word_t> 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) {
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<llvm::BitstreamEntry> MaybeEntry = Stream.advance();
+ if (!MaybeEntry) {
+ Error(MaybeEntry.takeError());
+ return Failure;
+ }
+ llvm::BitstreamEntry Entry = MaybeEntry.get();
switch (Entry.Kind) {
case llvm::BitstreamEntry::Error:
return Failure;
default:
- if (Stream.SkipBlock()) {
- Error("malformed block record in AST file");
+ if (llvm::Error Err = Stream.SkipBlock()) {
+ Error(std::move(Err));
return Failure;
}
break;
BitstreamCursor Stream(StreamData);
// Sniff for the signature.
- if (!startsWithASTFileMagic(Stream))
+ if (llvm::Error Err = doesntStartWithASTFileMagic(Stream)) {
+ // FIXME this drops the error on the floor.
+ consumeError(std::move(Err));
return Failure;
+ }
// Scan for the UNHASHED_CONTROL_BLOCK_ID block.
if (SkipCursorToBlock(Stream, UNHASHED_CONTROL_BLOCK_ID))
RecordData Record;
ASTReadResult Result = Success;
while (true) {
- llvm::BitstreamEntry Entry = Stream.advance();
+ Expected<llvm::BitstreamEntry> MaybeEntry = Stream.advance();
+ if (!MaybeEntry) {
+ // FIXME this drops the error on the floor.
+ consumeError(MaybeEntry.takeError());
+ return Failure;
+ }
+ llvm::BitstreamEntry Entry = MaybeEntry.get();
switch (Entry.Kind) {
case llvm::BitstreamEntry::Error:
// Read and process a record.
Record.clear();
- switch (
- (UnhashedControlBlockRecordTypes)Stream.readRecord(Entry.ID, Record)) {
+ Expected<unsigned> 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());
RecordData Record;
while (true) {
- llvm::BitstreamEntry Entry = Stream.advance();
+ Expected<llvm::BitstreamEntry> 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())
+ if (llvm::Error Err = Stream.SkipBlock()) {
+ Error(std::move(Err));
return Failure;
-
+ }
continue;
case llvm::BitstreamEntry::EndBlock:
Record.clear();
StringRef Blob;
- unsigned RecCode = Stream.readRecord(Entry.ID, Record, &Blob);
- switch (RecCode) {
+ Expected<unsigned> 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))
/// 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.
+ consumeError(std::move(Err));
return ASTFileSignature();
+ }
// Scan for the UNHASHED_CONTROL_BLOCK_ID block.
if (SkipCursorToBlock(Stream, UNHASHED_CONTROL_BLOCK_ID))
// Scan for SIGNATURE inside the diagnostic options block.
ASTReader::RecordData Record;
while (true) {
- llvm::BitstreamEntry Entry = Stream.advanceSkippingSubblocks();
+ Expected<llvm::BitstreamEntry> MaybeEntry =
+ Stream.advanceSkippingSubblocks();
+ if (!MaybeEntry) {
+ // FIXME this drops the error on the floor.
+ consumeError(MaybeEntry.takeError());
+ 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<unsigned> MaybeRecord = Stream.readRecord(Entry.ID, Record, &Blob);
+ if (!MaybeRecord) {
+ // FIXME this drops the error on the floor.
+ consumeError(MaybeRecord.takeError());
+ 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]}}};
}
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();
}
// Scan for ORIGINAL_FILE inside the control block.
RecordData Record;
while (true) {
- llvm::BitstreamEntry Entry = Stream.advanceSkippingSubblocks();
+ Expected<llvm::BitstreamEntry> MaybeEntry =
+ Stream.advanceSkippingSubblocks();
+ if (!MaybeEntry) {
+ // FIXME this drops errors on the floor.
+ consumeError(MaybeEntry.takeError());
+ return std::string();
+ }
+ llvm::BitstreamEntry Entry = MaybeEntry.get();
+
if (Entry.Kind == llvm::BitstreamEntry::EndBlock)
return std::string();
Record.clear();
StringRef Blob;
- if (Stream.readRecord(Entry.ID, Record, &Blob) == ORIGINAL_FILE)
+ Expected<unsigned> MaybeRecord = Stream.readRecord(Entry.ID, Record, &Blob);
+ if (!MaybeRecord) {
+ // FIXME this drops the errors on the floor.
+ consumeError(MaybeRecord.takeError());
+ return std::string();
+ }
+ if (ORIGINAL_FILE == MaybeRecord.get())
return Blob.str();
}
}
BitstreamCursor Stream(Bytes);
// Sniff for the signature.
- if (!startsWithASTFileMagic(Stream))
+ if (llvm::Error Err = doesntStartWithASTFileMagic(Stream)) {
+ consumeError(std::move(Err)); // FIXME this drops errors on the floor.
return true;
+ }
// Scan for the CONTROL_BLOCK_ID block.
if (SkipCursorToBlock(Stream, CONTROL_BLOCK_ID))
std::string ModuleDir;
bool DoneWithControlBlock = false;
while (!DoneWithControlBlock) {
- llvm::BitstreamEntry Entry = Stream.advance();
+ Expected<llvm::BitstreamEntry> MaybeEntry = Stream.advance();
+ if (!MaybeEntry) {
+ // FIXME this drops the error on the floor.
+ consumeError(MaybeEntry.takeError());
+ return true;
+ }
+ llvm::BitstreamEntry Entry = MaybeEntry.get();
switch (Entry.Kind) {
case llvm::BitstreamEntry::SubBlock: {
case INPUT_FILES_BLOCK_ID:
InputFilesCursor = Stream;
- if (Stream.SkipBlock() ||
- (NeedsInputFiles &&
- ReadBlockAbbrevs(InputFilesCursor, INPUT_FILES_BLOCK_ID)))
+ if (llvm::Error Err = Stream.SkipBlock()) {
+ // FIXME this drops the error on the floor.
+ consumeError(std::move(Err));
+ return true;
+ }
+ if (NeedsInputFiles &&
+ ReadBlockAbbrevs(InputFilesCursor, INPUT_FILES_BLOCK_ID))
return true;
break;
default:
- if (Stream.SkipBlock())
+ if (llvm::Error Err = Stream.SkipBlock()) {
+ // FIXME this drops the error on the floor.
+ consumeError(std::move(Err));
return true;
+ }
break;
}
Record.clear();
StringRef Blob;
- unsigned RecCode = Stream.readRecord(Entry.ID, Record, &Blob);
- switch ((ControlRecordTypes)RecCode) {
+ Expected<unsigned> 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;
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.
+ consumeError(std::move(Err));
+ }
+
+ Expected<unsigned> MaybeCode = Cursor.ReadCode();
+ if (!MaybeCode) {
+ // FIXME this drops errors on the floor.
+ consumeError(MaybeCode.takeError());
+ }
+ unsigned Code = MaybeCode.get();
- unsigned Code = Cursor.ReadCode();
RecordData Record;
StringRef Blob;
bool shouldContinue = false;
- switch ((InputFileRecordTypes)Cursor.readRecord(Code, Record, &Blob)) {
+ Expected<unsigned> MaybeRecordType =
+ Cursor.readRecord(Code, Record, &Blob);
+ if (!MaybeRecordType) {
+ // FIXME this drops errors on the floor.
+ consumeError(MaybeRecordType.takeError());
+ }
+ switch ((InputFileRecordTypes)MaybeRecordType.get()) {
case INPUT_FILE:
bool Overridden = static_cast<bool>(Record[3]);
std::string Filename = Blob;
while (!SkipCursorToBlock(Stream, EXTENSION_BLOCK_ID)) {
bool DoneWithExtensionBlock = false;
while (!DoneWithExtensionBlock) {
- llvm::BitstreamEntry Entry = Stream.advance();
-
- switch (Entry.Kind) {
- case llvm::BitstreamEntry::SubBlock:
- if (Stream.SkipBlock())
- return true;
-
- continue;
+ Expected<llvm::BitstreamEntry> MaybeEntry = Stream.advance();
+ if (!MaybeEntry) {
+ // FIXME this drops the error.
+ return true;
+ }
+ llvm::BitstreamEntry Entry = MaybeEntry.get();
+
+ switch (Entry.Kind) {
+ case llvm::BitstreamEntry::SubBlock:
+ if (llvm::Error Err = Stream.SkipBlock()) {
+ // FIXME this drops the error on the floor.
+ consumeError(std::move(Err));
+ return true;
+ }
+ continue;
- case llvm::BitstreamEntry::EndBlock:
- DoneWithExtensionBlock = true;
- continue;
+ case llvm::BitstreamEntry::EndBlock:
+ DoneWithExtensionBlock = true;
+ continue;
- case llvm::BitstreamEntry::Error:
- return true;
+ case llvm::BitstreamEntry::Error:
+ return true;
- case llvm::BitstreamEntry::Record:
- break;
- }
+ case llvm::BitstreamEntry::Record:
+ break;
+ }
Record.clear();
StringRef Blob;
- unsigned RecCode = Stream.readRecord(Entry.ID, Record, &Blob);
- switch (RecCode) {
+ Expected<unsigned> 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))
ASTReader::ASTReadResult
ASTReader::ReadSubmoduleBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
// Enter the submodule block.
- if (F.Stream.EnterSubBlock(SUBMODULE_BLOCK_ID)) {
- Error("malformed submodule block record in AST file");
+ if (llvm::Error Err = F.Stream.EnterSubBlock(SUBMODULE_BLOCK_ID)) {
+ Error(std::move(Err));
return Failure;
}
Module *CurrentModule = nullptr;
RecordData Record;
while (true) {
- llvm::BitstreamEntry Entry = F.Stream.advanceSkippingSubblocks();
+ Expected<llvm::BitstreamEntry> 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.
// Read a record.
StringRef Blob;
Record.clear();
- auto Kind = F.Stream.readRecord(Entry.ID, Record, &Blob);
+ Expected<unsigned> 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");
}
SavedStreamPosition SavedPosition(M.PreprocessorDetailCursor);
- M.PreprocessorDetailCursor.JumpToBit(PPOffs.BitOffset);
+ if (llvm::Error Err =
+ M.PreprocessorDetailCursor.JumpToBit(PPOffs.BitOffset)) {
+ Error(std::move(Err));
+ return nullptr;
+ }
+
+ Expected<llvm::BitstreamEntry> MaybeEntry =
+ M.PreprocessorDetailCursor.advance(BitstreamCursor::AF_DontPopBlockAtEnd);
+ if (!MaybeEntry) {
+ Error(MaybeEntry.takeError());
+ return nullptr;
+ }
+ llvm::BitstreamEntry Entry = MaybeEntry.get();
- llvm::BitstreamEntry Entry =
- M.PreprocessorDetailCursor.advance(BitstreamCursor::AF_DontPopBlockAtEnd);
if (Entry.Kind != llvm::BitstreamEntry::Record)
return nullptr;
PreprocessingRecord &PPRec = *PP.getPreprocessingRecord();
StringRef Blob;
RecordData Record;
- PreprocessorDetailRecordTypes RecType =
- (PreprocessorDetailRecordTypes)M.PreprocessorDetailCursor.readRecord(
- Entry.ID, Record, &Blob);
- switch (RecType) {
+ Expected<unsigned> 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;
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<unsigned> MaybeCode = DeclsCursor.ReadCode();
+ if (!MaybeCode) {
+ Error(MaybeCode.takeError());
+ return QualType();
+ }
+ unsigned Code = MaybeCode.get();
+
+ Expected<unsigned> 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");
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<unsigned> MaybeCode = Cursor.ReadCode();
+ if (!MaybeCode) {
+ Error(MaybeCode.takeError());
+ return nullptr;
+ }
+ unsigned Code = MaybeCode.get();
+
+ Expected<unsigned> 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;
}
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<unsigned> MaybeCode = Cursor.ReadCode();
+ if (!MaybeCode) {
+ Error(MaybeCode.takeError());
+ return nullptr;
+ }
+ unsigned Code = MaybeCode.get();
+
+ Expected<unsigned> 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;
// 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);
RecordData Record;
while (true) {
- llvm::BitstreamEntry Entry =
- Cursor.advanceSkippingSubblocks(BitstreamCursor::AF_DontPopBlockAtEnd);
+ Expected<llvm::BitstreamEntry> 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.
// Read a record.
Record.clear();
- switch ((CommentRecordTypes)Cursor.readRecord(Entry.ID, Record)) {
+ Expected<unsigned> 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);
return SemaObj ? SemaObj->IdResolver : DummyIdResolver;
}
-unsigned ASTRecordReader::readRecord(llvm::BitstreamCursor &Cursor,
- unsigned AbbrevID) {
+Expected<unsigned> ASTRecordReader::readRecord(llvm::BitstreamCursor &Cursor,
+ unsigned AbbrevID) {
Idx = 0;
Record.clear();
return Cursor.readRecord(AbbrevID, Record);
// 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<unsigned> 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<unsigned> 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");
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<unsigned> 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<unsigned> 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());
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<unsigned> MaybeCode = Cursor.ReadCode();
+ if (!MaybeCode)
+ llvm::report_fatal_error(
+ "ASTReader::loadPendingDeclChain failed reading code: " +
+ toString(MaybeCode.takeError()));
+ unsigned Code = MaybeCode.get();
+ if (Expected<unsigned> 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?
Stmt::EmptyShell Empty;
while (true) {
- llvm::BitstreamEntry Entry = Cursor.advanceSkippingSubblocks();
+ llvm::Expected<llvm::BitstreamEntry> 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.
Stmt *S = nullptr;
bool Finished = false;
bool IsStmtReference = false;
- switch ((StmtCode)Record.readRecord(Cursor, Entry.ID)) {
+ Expected<unsigned> MaybeStmtCode = Record.readRecord(Cursor, Entry.ID);
+ if (!MaybeStmtCode) {
+ Error(toString(MaybeStmtCode.takeError()));
+ return nullptr;
+ }
+ switch ((StmtCode)MaybeStmtCode.get()) {
case STMT_STOP:
Finished = true;
break;
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<llvm::BitstreamEntry> Res = Cursor.advance())
+ Entry = Res.get();
+ else
+ Fail(Res.takeError());
switch (Entry.Kind) {
case llvm::BitstreamEntry::Error:
case llvm::BitstreamEntry::SubBlock:
if (!InGlobalIndexBlock && Entry.ID == GLOBAL_INDEX_BLOCK_ID) {
- if (Cursor.EnterSubBlock(GLOBAL_INDEX_BLOCK_ID))
- return;
-
+ if (llvm::Error Err = Cursor.EnterSubBlock(GLOBAL_INDEX_BLOCK_ID))
+ Fail(std::move(Err));
InGlobalIndexBlock = true;
- } else if (Cursor.SkipBlock()) {
- return;
- }
+ } else if (llvm::Error Err = Cursor.SkipBlock())
+ Fail(std::move(Err));
continue;
}
SmallVector<uint64_t, 64> Record;
StringRef Blob;
- switch ((IndexRecordTypes)Cursor.readRecord(Entry.ID, Record, &Blob)) {
+ Expected<unsigned> MaybeIndexRecord =
+ Cursor.readRecord(Entry.ID, Record, &Blob);
+ if (!MaybeIndexRecord)
+ Fail(MaybeIndexRecord.takeError());
+ IndexRecordTypes IndexRecord =
+ static_cast<IndexRecordTypes>(MaybeIndexRecord.get());
+ switch (IndexRecord) {
case INDEX_METADATA:
// Make sure that the version matches.
if (Record.size() < 1 || Record[0] != CurrentVersion)
delete static_cast<IdentifierIndexTable *>(IdentifierIndex);
}
-std::pair<GlobalModuleIndex *, GlobalModuleIndex::ErrorCode>
+std::pair<GlobalModuleIndex *, llvm::Error>
GlobalModuleIndex::readIndex(StringRef Path) {
// Load the index file, if it's there.
llvm::SmallString<128> IndexPath;
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> 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<llvm::MemoryBuffer> 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<llvm::SimpleBitstreamCursor::word_t> 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);
+ llvm::Error::success());
}
void
: 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.
};
}
-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<llvm::SimpleBitstreamCursor::word_t> 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).
enum { Other, ControlBlock, ASTBlock, DiagnosticOptionsBlock } State = Other;
bool Done = false;
while (!Done) {
- llvm::BitstreamEntry Entry = InStream.advance();
+ Expected<llvm::BitstreamEntry> MaybeEntry = InStream.advance();
+ if (!MaybeEntry)
+ return MaybeEntry.takeError();
+ llvm::BitstreamEntry Entry = MaybeEntry.get();
+
switch (Entry.Kind) {
case llvm::BitstreamEntry::Error:
Done = true;
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<unsigned> Skipped = InStream.skipRecord(Entry.ID))
+ continue;
+ else
+ return Skipped.takeError();
}
// Handle potentially-interesting records below.
case llvm::BitstreamEntry::SubBlock:
if (Entry.ID == CONTROL_BLOCK_ID) {
- if (InStream.EnterSubBlock(CONTROL_BLOCK_ID))
- return true;
+ if (llvm::Error Err = InStream.EnterSubBlock(CONTROL_BLOCK_ID))
+ return Err;
// Found the control block.
State = ControlBlock;
}
if (Entry.ID == AST_BLOCK_ID) {
- if (InStream.EnterSubBlock(AST_BLOCK_ID))
- return true;
+ if (llvm::Error Err = InStream.EnterSubBlock(AST_BLOCK_ID))
+ return Err;
// Found the AST block.
State = ASTBlock;
}
if (Entry.ID == UNHASHED_CONTROL_BLOCK_ID) {
- if (InStream.EnterSubBlock(UNHASHED_CONTROL_BLOCK_ID))
- return true;
+ if (llvm::Error Err = InStream.EnterSubBlock(UNHASHED_CONTROL_BLOCK_ID))
+ return Err;
// Found the Diagnostic Options block.
State = DiagnosticOptionsBlock;
continue;
}
- if (InStream.SkipBlock())
- return true;
+ if (llvm::Error Err = InStream.SkipBlock())
+ return Err;
continue;
// Read the given record.
SmallVector<uint64_t, 64> Record;
StringRef Blob;
- unsigned Code = InStream.readRecord(Entry.ID, Record, &Blob);
+ Expected<unsigned> MaybeCode = InStream.readRecord(Entry.ID, Record, &Blob);
+ if (!MaybeCode)
+ return MaybeCode.takeError();
+ unsigned Code = MaybeCode.get();
// Handle module dependencies.
if (State == ControlBlock && Code == IMPORTS) {
/*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.
// We don't care about this record.
}
- return false;
+ return llvm::Error::success();
}
namespace {
return false;
}
-GlobalModuleIndex::ErrorCode
+llvm::Error
GlobalModuleIndex::writeIndex(FileManager &FileMgr,
const PCHContainerReader &PCHContainerRdr,
StringRef Path) {
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.
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.
// 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;
}
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.
{
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.
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 {
// - a/../b/ and b/ are not considered the same
// - on Windows, c:\ and C:\ (only different in case) are not the same
+// RUN: rm -rf %t.mcp %t.h.pch
// RUN: %clang_cc1 -fsyntax-only %s -verify
// RUN: c-index-test -write-pch %t.h.pch %s -fmodules -fmodules-cache-path=%t.mcp -Xclang -triple -Xclang x86_64-apple-darwin
// RUN: %clang -fsyntax-only -include %t.h %s -Xclang -verify -fmodules -fmodules-cache-path=%t.mcp -Xclang -detailed-preprocessing-record -Xclang -triple -Xclang x86_64-apple-darwin -Xclang -fallow-pch-with-compiler-errors
unsigned BitsInCurWord = 0;
public:
- static const size_t MaxChunkSize = sizeof(word_t) * 8;
+ static const constexpr size_t MaxChunkSize = sizeof(word_t) * 8;
SimpleBitstreamCursor() = default;
explicit SimpleBitstreamCursor(ArrayRef<uint8_t> BitcodeBytes)
ArrayRef<uint8_t> 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");
BitsInCurWord = 0;
// Skip over any bits that are already consumed.
- if (WordBitNo)
- Read(WordBitNo);
+ if (WordBitNo) {
+ if (Expected<word_t> Res = Read(WordBitNo))
+ return Error::success();
+ else
+ return Res.takeError();
+ }
+
+ return Error::success();
}
/// Get a pointer into the bitstream at the specified byte offset.
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;
}
NextChar += BytesRead;
BitsInCurWord = BytesRead * 8;
+ return Error::success();
}
- word_t Read(unsigned NumBits) {
+ Expected<word_t> Read(unsigned NumBits) {
static const unsigned BitsInWord = MaxChunkSize;
assert(NumBits && NumBits <= BitsInWord &&
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));
return R;
}
- uint32_t ReadVBR(unsigned NumBits) {
- uint32_t Piece = Read(NumBits);
+ Expected<uint32_t> ReadVBR(unsigned NumBits) {
+ Expected<unsigned> MaybeRead = Read(NumBits);
+ if (!MaybeRead)
+ return MaybeRead;
+ uint32_t Piece = MaybeRead.get();
+
if ((Piece & (1U << (NumBits-1))) == 0)
return Piece;
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<uint64_t> ReadVBR64(unsigned NumBits) {
+ Expected<unsigned> MaybeRead = Read(NumBits);
+ if (!MaybeRead)
+ return MaybeRead;
+ uint32_t Piece = MaybeRead.get();
+
if ((Piece & (1U << (NumBits-1))) == 0)
return uint64_t(Piece);
return Result;
NextBit += NumBits-1;
- Piece = Read(NumBits);
+ MaybeRead = Read(NumBits);
+ if (!MaybeRead)
+ return MaybeRead;
+ Piece = MaybeRead.get();
}
}
};
/// Advance the current bitstream, returning the next entry in the stream.
- BitstreamEntry advance(unsigned Flags = 0) {
+ Expected<BitstreamEntry> advance(unsigned Flags = 0) {
while (true) {
if (AtEndOfStream())
return BitstreamEntry::getError();
- unsigned Code = ReadCode();
+ Expected<unsigned> 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())
return BitstreamEntry::getEndBlock();
}
- if (Code == bitc::ENTER_SUBBLOCK)
- return BitstreamEntry::getSubBlock(ReadSubBlockID());
+ if (Code == bitc::ENTER_SUBBLOCK) {
+ if (Expected<unsigned> 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;
}
/// 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<BitstreamEntry> advanceSkippingSubblocks(unsigned Flags = 0) {
while (true) {
// If we found a normal entry, return it.
- BitstreamEntry Entry = advance(Flags);
+ Expected<BitstreamEntry> MaybeEntry = advance(Flags);
+ if (!MaybeEntry)
+ return MaybeEntry;
+ BitstreamEntry Entry = MaybeEntry.get();
+
if (Entry.Kind != BitstreamEntry::SubBlock)
return Entry;
// If we found a sub-block, just skip over it and check the next entry.
- if (SkipBlock())
- return BitstreamEntry::getError();
+ if (Error Err = SkipBlock())
+ return std::move(Err);
}
}
- unsigned ReadCode() {
- return Read(CurCodeSize);
- }
+ Expected<unsigned> ReadCode() { return Read(CurCodeSize); }
// Block header:
// [ENTER_SUBBLOCK, blockid, newcodelen, <align4bytes>, blocklen]
/// Having read the ENTER_SUBBLOCK code, read the BlockID for the block.
- unsigned ReadSubBlockID() {
- return ReadVBR(bitc::BlockIDWidth);
- }
+ Expected<unsigned> 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);
+ /// of this block.
+ Error SkipBlock() {
+ // Read and ignore the codelen value.
+ if (Expected<uint32_t> 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<unsigned> MaybeNum = Read(bitc::BlockSizeWidth);
+ if (!MaybeNum)
+ return MaybeNum.takeError();
+ size_t NumFourBytes = MaybeNum.get();
// Check that the block wasn't partially defined, and that the offset isn't
// bogus.
- size_t SkipTo = GetCurrentBitNo() + NumFourBytes*4*8;
- if (AtEndOfStream() || !canSkipToPos(SkipTo/8))
- return true;
-
- JumpToBit(SkipTo);
- return false;
+ size_t SkipTo = GetCurrentBitNo() + NumFourBytes * 4 * 8;
+ if (AtEndOfStream())
+ return createStringError(std::errc::illegal_byte_sequence,
+ "can't skip block: already at end of stream");
+ if (!canSkipToPos(SkipTo / 8))
+ return createStringError(std::errc::illegal_byte_sequence,
+ "can't skip to bit %zu from %" PRIu64, SkipTo,
+ GetCurrentBitNo());
+
+ if (Error Res = JumpToBit(SkipTo))
+ return Res;
+
+ return Error::success();
}
- /// 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);
+ /// Having read the ENTER_SUBBLOCK abbrevid, and enter the block.
+ Error EnterSubBlock(unsigned BlockID, unsigned *NumWordsP = nullptr);
bool ReadBlockEnd() {
if (BlockScope.empty()) return true;
}
/// Read the current record and discard it, returning the code for the record.
- unsigned skipRecord(unsigned AbbrevID);
+ Expected<unsigned> skipRecord(unsigned AbbrevID);
- unsigned readRecord(unsigned AbbrevID, SmallVectorImpl<uint64_t> &Vals,
- StringRef *Blob = nullptr);
+ Expected<unsigned> readRecord(unsigned AbbrevID,
+ SmallVectorImpl<uint64_t> &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<BitstreamBlockInfo>
+ Expected<Optional<BitstreamBlockInfo>>
ReadBlockInfoBlock(bool ReadBlockInfoNames = false);
/// Set the block info to be used by this BitstreamCursor to interpret
/// Create formatted StringError object.
template <typename... Ts>
-Error createStringError(std::error_code EC, char const *Fmt,
- const Ts &... Vals) {
+inline Error createStringError(std::error_code EC, char const *Fmt,
+ const Ts &... Vals) {
std::string Buffer;
raw_string_ostream Stream(Buffer);
Stream << format(Fmt, Vals...);
Error createStringError(std::error_code EC, char const *Msg);
+template <typename... Ts>
+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
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<SimpleBitstreamCursor::word_t> 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<SimpleBitstreamCursor::word_t> 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<BitstreamCursor> initStream(MemoryBufferRef Buffer) {
return error("Invalid bitcode wrapper header");
BitstreamCursor Stream(ArrayRef<uint8_t>(BufPtr, BufEnd));
- if (!hasValidBitcodeHeader(Stream))
- return error("Invalid bitcode signature");
+ if (Error Err = hasInvalidBitcodeHeader(Stream))
+ return std::move(Err);
return std::move(Stream);
}
/// Read the "IDENTIFICATION_BLOCK_ID" block, do some basic enforcement on the
/// "epoch" encoded in the bitcode, and return the producer name if any.
static Expected<std::string> readIdentificationBlock(BitstreamCursor &Stream) {
- if (Stream.EnterSubBlock(bitc::IDENTIFICATION_BLOCK_ID))
- return error("Invalid record");
+ if (Error Err = Stream.EnterSubBlock(bitc::IDENTIFICATION_BLOCK_ID))
+ return std::move(Err);
// Read all the records.
SmallVector<uint64_t, 64> Record;
std::string ProducerIdentification;
while (true) {
- BitstreamEntry Entry = Stream.advance();
+ BitstreamEntry Entry;
+ if (Expected<BitstreamEntry> Res = Stream.advance())
+ Entry = Res.get();
+ else
+ return Res.takeError();
switch (Entry.Kind) {
default:
// Read a record.
Record.clear();
- unsigned BitCode = Stream.readRecord(Entry.ID, Record);
- switch (BitCode) {
+ Expected<unsigned> 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]
if (Stream.AtEndOfStream())
return "";
- BitstreamEntry Entry = Stream.advance();
+ BitstreamEntry Entry;
+ if (Expected<BitstreamEntry> Res = Stream.advance())
+ Entry = std::move(Res.get());
+ else
+ return Res.takeError();
+
switch (Entry.Kind) {
case BitstreamEntry::EndBlock:
case BitstreamEntry::Error:
return readIdentificationBlock(Stream);
// Ignore other sub-blocks.
- if (Stream.SkipBlock())
- return error("Malformed block");
+ if (Error Err = Stream.SkipBlock())
+ return std::move(Err);
continue;
case BitstreamEntry::Record:
- Stream.skipRecord(Entry.ID);
- continue;
+ if (Expected<unsigned> Skipped = Stream.skipRecord(Entry.ID))
+ continue;
+ else
+ return Skipped.takeError();
}
}
}
static Expected<bool> hasObjCCategoryInModule(BitstreamCursor &Stream) {
- if (Stream.EnterSubBlock(bitc::MODULE_BLOCK_ID))
- return error("Invalid record");
+ if (Error Err = Stream.EnterSubBlock(bitc::MODULE_BLOCK_ID))
+ return std::move(Err);
SmallVector<uint64_t, 64> Record;
// Read all the records for this module.
while (true) {
- BitstreamEntry Entry = Stream.advanceSkippingSubblocks();
+ Expected<BitstreamEntry> MaybeEntry = Stream.advanceSkippingSubblocks();
+ if (!MaybeEntry)
+ return MaybeEntry.takeError();
+ BitstreamEntry Entry = MaybeEntry.get();
switch (Entry.Kind) {
case BitstreamEntry::SubBlock: // Handled for us already.
}
// Read a record.
- switch (Stream.readRecord(Entry.ID, Record)) {
+ Expected<unsigned> 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]
// 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<BitstreamEntry> Res = Stream.advance())
+ Entry = std::move(Res.get());
+ else
+ return Res.takeError();
switch (Entry.Kind) {
case BitstreamEntry::Error:
return hasObjCCategoryInModule(Stream);
// Ignore other sub-blocks.
- if (Stream.SkipBlock())
- return error("Malformed block");
+ if (Error Err = Stream.SkipBlock())
+ return std::move(Err);
continue;
case BitstreamEntry::Record:
- Stream.skipRecord(Entry.ID);
- continue;
+ if (Expected<unsigned> Skipped = Stream.skipRecord(Entry.ID))
+ continue;
+ else
+ return Skipped.takeError();
}
}
}
static Expected<std::string> readModuleTriple(BitstreamCursor &Stream) {
- if (Stream.EnterSubBlock(bitc::MODULE_BLOCK_ID))
- return error("Invalid record");
+ if (Error Err = Stream.EnterSubBlock(bitc::MODULE_BLOCK_ID))
+ return std::move(Err);
SmallVector<uint64_t, 64> Record;
// Read all the records for this module.
while (true) {
- BitstreamEntry Entry = Stream.advanceSkippingSubblocks();
+ Expected<BitstreamEntry> MaybeEntry = Stream.advanceSkippingSubblocks();
+ if (!MaybeEntry)
+ return MaybeEntry.takeError();
+ BitstreamEntry Entry = MaybeEntry.get();
switch (Entry.Kind) {
case BitstreamEntry::SubBlock: // Handled for us already.
}
// Read a record.
- switch (Stream.readRecord(Entry.ID, Record)) {
+ Expected<unsigned> 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;
// 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<BitstreamEntry> MaybeEntry = Stream.advance();
+ if (!MaybeEntry)
+ return MaybeEntry.takeError();
+ BitstreamEntry Entry = MaybeEntry.get();
switch (Entry.Kind) {
case BitstreamEntry::Error:
return readModuleTriple(Stream);
// Ignore other sub-blocks.
- if (Stream.SkipBlock())
- return error("Malformed block");
+ if (Error Err = Stream.SkipBlock())
+ return std::move(Err);
continue;
case BitstreamEntry::Record:
- Stream.skipRecord(Entry.ID);
- continue;
+ if (llvm::Expected<unsigned> Skipped = Stream.skipRecord(Entry.ID))
+ continue;
+ else
+ return Skipped.takeError();
}
}
}
}
Error BitcodeReader::parseAttributeBlock() {
- if (Stream.EnterSubBlock(bitc::PARAMATTR_BLOCK_ID))
- return error("Invalid record");
+ if (Error Err = Stream.EnterSubBlock(bitc::PARAMATTR_BLOCK_ID))
+ return Err;
if (!MAttributes.empty())
return error("Invalid multiple blocks");
// Read all the records.
while (true) {
- BitstreamEntry Entry = Stream.advanceSkippingSubblocks();
+ Expected<BitstreamEntry> MaybeEntry = Stream.advanceSkippingSubblocks();
+ if (!MaybeEntry)
+ return MaybeEntry.takeError();
+ BitstreamEntry Entry = MaybeEntry.get();
switch (Entry.Kind) {
case BitstreamEntry::SubBlock: // Handled for us already.
// Read a record.
Record.clear();
- switch (Stream.readRecord(Entry.ID, Record)) {
+ Expected<unsigned> 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, ...]
}
Error BitcodeReader::parseAttributeGroupBlock() {
- if (Stream.EnterSubBlock(bitc::PARAMATTR_GROUP_BLOCK_ID))
- return error("Invalid record");
+ if (Error Err = Stream.EnterSubBlock(bitc::PARAMATTR_GROUP_BLOCK_ID))
+ return Err;
if (!MAttributeGroups.empty())
return error("Invalid multiple blocks");
// Read all the records.
while (true) {
- BitstreamEntry Entry = Stream.advanceSkippingSubblocks();
+ Expected<BitstreamEntry> MaybeEntry = Stream.advanceSkippingSubblocks();
+ if (!MaybeEntry)
+ return MaybeEntry.takeError();
+ BitstreamEntry Entry = MaybeEntry.get();
switch (Entry.Kind) {
case BitstreamEntry::SubBlock: // Handled for us already.
// Read a record.
Record.clear();
- switch (Stream.readRecord(Entry.ID, Record)) {
+ Expected<unsigned> 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, ...]
}
Error BitcodeReader::parseTypeTable() {
- if (Stream.EnterSubBlock(bitc::TYPE_BLOCK_ID_NEW))
- return error("Invalid record");
+ if (Error Err = Stream.EnterSubBlock(bitc::TYPE_BLOCK_ID_NEW))
+ return Err;
return parseTypeTableBody();
}
// Read all the records for this type table.
while (true) {
- BitstreamEntry Entry = Stream.advanceSkippingSubblocks();
+ Expected<BitstreamEntry> MaybeEntry = Stream.advanceSkippingSubblocks();
+ if (!MaybeEntry)
+ return MaybeEntry.takeError();
+ BitstreamEntry Entry = MaybeEntry.get();
switch (Entry.Kind) {
case BitstreamEntry::SubBlock: // Handled for us already.
// Read a record.
Record.clear();
Type *ResultTy = nullptr;
- switch (Stream.readRecord(Entry.ID, Record)) {
+ Expected<unsigned> 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]
}
Error BitcodeReader::parseOperandBundleTags() {
- if (Stream.EnterSubBlock(bitc::OPERAND_BUNDLE_TAGS_BLOCK_ID))
- return error("Invalid record");
+ if (Error Err = Stream.EnterSubBlock(bitc::OPERAND_BUNDLE_TAGS_BLOCK_ID))
+ return Err;
if (!BundleTags.empty())
return error("Invalid multiple blocks");
SmallVector<uint64_t, 64> Record;
while (true) {
- BitstreamEntry Entry = Stream.advanceSkippingSubblocks();
+ Expected<BitstreamEntry> MaybeEntry = Stream.advanceSkippingSubblocks();
+ if (!MaybeEntry)
+ return MaybeEntry.takeError();
+ BitstreamEntry Entry = MaybeEntry.get();
switch (Entry.Kind) {
case BitstreamEntry::SubBlock: // Handled for us already.
// Tags are implicitly mapped to integers by their order.
- if (Stream.readRecord(Entry.ID, Record) != bitc::OPERAND_BUNDLE_TAG)
+ Expected<unsigned> 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]
}
Error BitcodeReader::parseSyncScopeNames() {
- if (Stream.EnterSubBlock(bitc::SYNC_SCOPE_NAMES_BLOCK_ID))
- return error("Invalid record");
+ if (Error Err = Stream.EnterSubBlock(bitc::SYNC_SCOPE_NAMES_BLOCK_ID))
+ return Err;
if (!SSIDs.empty())
return error("Invalid multiple synchronization scope names blocks");
SmallVector<uint64_t, 64> Record;
while (true) {
- BitstreamEntry Entry = Stream.advanceSkippingSubblocks();
+ Expected<BitstreamEntry> 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:
// Synchronization scope names are implicitly mapped to synchronization
// scope IDs by their order.
- if (Stream.readRecord(Entry.ID, Record) != bitc::SYNC_SCOPE_NAME)
+ Expected<unsigned> 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;
/// 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<uint64_t> 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<BitstreamEntry> 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;
}
unsigned FuncBitcodeOffsetDelta =
Stream.getAbbrevIDWidth() + bitc::BlockIDWidth;
- if (Stream.EnterSubBlock(bitc::VALUE_SYMTAB_BLOCK_ID))
- return error("Invalid record");
+ if (Error Err = Stream.EnterSubBlock(bitc::VALUE_SYMTAB_BLOCK_ID))
+ return Err;
SmallVector<uint64_t, 64> Record;
while (true) {
- BitstreamEntry Entry = Stream.advanceSkippingSubblocks();
+ Expected<BitstreamEntry> MaybeEntry = Stream.advanceSkippingSubblocks();
+ if (!MaybeEntry)
+ return MaybeEntry.takeError();
+ BitstreamEntry Entry = MaybeEntry.get();
switch (Entry.Kind) {
case BitstreamEntry::SubBlock:
}
Record.clear();
- switch (Stream.readRecord(Entry.ID, Record)) {
+ Expected<unsigned> MaybeRecord = Stream.readRecord(Entry.ID, Record);
+ if (!MaybeRecord)
+ return MaybeRecord.takeError();
+ switch (MaybeRecord.get()) {
case bitc::VST_CODE_FNENTRY: // [valueid, offset]
setDeferredFunctionInfo(FuncBitcodeOffsetDelta,
cast<Function>(ValueList[Record[0]]), Record);
// 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<uint64_t> 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,
unsigned FuncBitcodeOffsetDelta =
Stream.getAbbrevIDWidth() + bitc::BlockIDWidth;
- if (Stream.EnterSubBlock(bitc::VALUE_SYMTAB_BLOCK_ID))
- return error("Invalid record");
+ if (Error Err = Stream.EnterSubBlock(bitc::VALUE_SYMTAB_BLOCK_ID))
+ return Err;
SmallVector<uint64_t, 64> Record;
SmallString<128> ValueName;
while (true) {
- BitstreamEntry Entry = Stream.advanceSkippingSubblocks();
+ Expected<BitstreamEntry> MaybeEntry = Stream.advanceSkippingSubblocks();
+ if (!MaybeEntry)
+ return MaybeEntry.takeError();
+ BitstreamEntry Entry = MaybeEntry.get();
switch (Entry.Kind) {
case BitstreamEntry::SubBlock: // Handled for us already.
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.
// Read a record.
Record.clear();
- switch (Stream.readRecord(Entry.ID, Record)) {
+ Expected<unsigned> 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]
}
Error BitcodeReader::parseConstants() {
- if (Stream.EnterSubBlock(bitc::CONSTANTS_BLOCK_ID))
- return error("Invalid record");
+ if (Error Err = Stream.EnterSubBlock(bitc::CONSTANTS_BLOCK_ID))
+ return Err;
SmallVector<uint64_t, 64> Record;
unsigned NextCstNo = ValueList.size();
while (true) {
- BitstreamEntry Entry = Stream.advanceSkippingSubblocks();
+ Expected<BitstreamEntry> MaybeEntry = Stream.advanceSkippingSubblocks();
+ if (!MaybeEntry)
+ return MaybeEntry.takeError();
+ BitstreamEntry Entry = MaybeEntry.get();
switch (Entry.Kind) {
case BitstreamEntry::SubBlock: // Handled for us already.
Record.clear();
Type *VoidType = Type::getVoidTy(Context);
Value *V = nullptr;
- unsigned BitCode = Stream.readRecord(Entry.ID, Record);
- switch (BitCode) {
+ Expected<unsigned> 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);
}
Error BitcodeReader::parseUseLists() {
- if (Stream.EnterSubBlock(bitc::USELIST_BLOCK_ID))
- return error("Invalid record");
+ if (Error Err = Stream.EnterSubBlock(bitc::USELIST_BLOCK_ID))
+ return Err;
// Read all the records.
SmallVector<uint64_t, 64> Record;
while (true) {
- BitstreamEntry Entry = Stream.advanceSkippingSubblocks();
+ Expected<BitstreamEntry> MaybeEntry = Stream.advanceSkippingSubblocks();
+ if (!MaybeEntry)
+ return MaybeEntry.takeError();
+ BitstreamEntry Entry = MaybeEntry.get();
switch (Entry.Kind) {
case BitstreamEntry::SubBlock: // Handled for us already.
// Read a use list record.
Record.clear();
bool IsBB = false;
- switch (Stream.readRecord(Entry.ID, Record)) {
+ Expected<unsigned> 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:
DeferredMetadataInfo.push_back(CurBit);
// Skip over the block for now.
- if (Stream.SkipBlock())
- return error("Invalid record");
+ if (Error Err = Stream.SkipBlock())
+ return Err;
return Error::success();
}
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;
}
DeferredFunctionInfo[Fn] = CurBit;
// Skip over the function block for now.
- if (Stream.SkipBlock())
- return error("Invalid record");
+ if (Error Err = Stream.SkipBlock())
+ return Err;
return Error::success();
}
/// 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");
SmallVector<uint64_t, 64> Record;
while (true) {
- BitstreamEntry Entry = Stream.advance();
+ Expected<llvm::BitstreamEntry> MaybeEntry = Stream.advance();
+ if (!MaybeEntry)
+ return MaybeEntry.takeError();
+ llvm::BitstreamEntry Entry = MaybeEntry.get();
+
switch (Entry.Kind) {
default:
return error("Expect SubBlock");
}
bool BitcodeReaderBase::readBlockInfo() {
- Optional<BitstreamBlockInfo> NewBlockInfo = Stream.ReadBlockInfoBlock();
+ Expected<Optional<BitstreamBlockInfo>> MaybeNewBlockInfo =
+ Stream.ReadBlockInfoBlock();
+ if (!MaybeNewBlockInfo)
+ return true; // FIXME Handle the error.
+ Optional<BitstreamBlockInfo> NewBlockInfo =
+ std::move(MaybeNewBlockInfo.get());
if (!NewBlockInfo)
return true;
BlockInfo = std::move(*NewBlockInfo);
Error BitcodeReader::parseModule(uint64_t ResumeBit,
bool ShouldLazyLoadMetadata) {
- if (ResumeBit)
- Stream.JumpToBit(ResumeBit);
- else if (Stream.EnterSubBlock(bitc::MODULE_BLOCK_ID))
- return error("Invalid record");
+ if (ResumeBit) {
+ if (Error JumpFailed = Stream.JumpToBit(ResumeBit))
+ return JumpFailed;
+ } else if (Error Err = Stream.EnterSubBlock(bitc::MODULE_BLOCK_ID))
+ return Err;
SmallVector<uint64_t, 64> Record;
// Read all the records for this module.
while (true) {
- BitstreamEntry Entry = Stream.advance();
+ Expected<llvm::BitstreamEntry> MaybeEntry = Stream.advance();
+ if (!MaybeEntry)
+ return MaybeEntry.takeError();
+ llvm::BitstreamEntry Entry = MaybeEntry.get();
switch (Entry.Kind) {
case BitstreamEntry::Error:
case BitstreamEntry::SubBlock:
switch (Entry.ID) {
default: // Skip unknown content.
- if (Stream.SkipBlock())
- return error("Invalid record");
+ if (Error Err = Stream.SkipBlock())
+ return Err;
break;
case bitc::BLOCKINFO_BLOCK_ID:
if (readBlockInfo())
// We must have had a VST forward declaration record, which caused
// the parser to jump to and parse the VST earlier.
assert(VSTOffset > 0);
- if (Stream.SkipBlock())
- return error("Invalid record");
+ if (Error Err = Stream.SkipBlock())
+ return Err;
}
break;
case bitc::CONSTANTS_BLOCK_ID:
// materializing functions. The ResumeBit points to the
// start of the last function block recorded in the
// DeferredFunctionInfo map. Skip it.
- if (Stream.SkipBlock())
- return error("Invalid record");
+ if (Error Err = Stream.SkipBlock())
+ return Err;
continue;
}
}
}
// Read a record.
- auto BitCode = Stream.readRecord(Entry.ID, Record);
- switch (BitCode) {
+ Expected<unsigned> 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<unsigned> VersionOrErr = parseVersionRecord(Record);
/// Lazily parse the specified function body block.
Error BitcodeReader::parseFunctionBody(Function *F) {
- if (Stream.EnterSubBlock(bitc::FUNCTION_BLOCK_ID))
- return error("Invalid record");
+ if (Error Err = Stream.EnterSubBlock(bitc::FUNCTION_BLOCK_ID))
+ return Err;
// Unexpected unresolved metadata when parsing function.
if (MDLoader->hasFwdRefs())
SmallVector<uint64_t, 64> Record;
while (true) {
- BitstreamEntry Entry = Stream.advance();
+ Expected<llvm::BitstreamEntry> MaybeEntry = Stream.advance();
+ if (!MaybeEntry)
+ return MaybeEntry.takeError();
+ llvm::BitstreamEntry Entry = MaybeEntry.get();
switch (Entry.Kind) {
case BitstreamEntry::Error:
case BitstreamEntry::SubBlock:
switch (Entry.ID) {
default: // Skip unknown content.
- if (Stream.SkipBlock())
- return error("Invalid record");
+ if (Error Err = Stream.SkipBlock())
+ return Err;
break;
case bitc::CONSTANTS_BLOCK_ID:
if (Error Err = parseConstants())
// Read a record.
Record.clear();
Instruction *I = nullptr;
- unsigned BitCode = Stream.readRecord(Entry.ID, Record);
- switch (BitCode) {
+ Expected<unsigned> 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]
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);
return Error::success();
assert(Offset > 0 && "Expected non-zero VST offset");
- uint64_t CurrentBit = jumpToValueSymbolTable(Offset, Stream);
+ Expected<uint64_t> 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");
+ if (Error Err = Stream.EnterSubBlock(bitc::VALUE_SYMTAB_BLOCK_ID))
+ return Err;
SmallVector<uint64_t, 64> Record;
SmallString<128> ValueName;
while (true) {
- BitstreamEntry Entry = Stream.advanceSkippingSubblocks();
+ Expected<BitstreamEntry> MaybeEntry = Stream.advanceSkippingSubblocks();
+ if (!MaybeEntry)
+ return MaybeEntry.takeError();
+ BitstreamEntry Entry = MaybeEntry.get();
switch (Entry.Kind) {
case BitstreamEntry::SubBlock: // Handled for us already.
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.
// Read a record.
Record.clear();
- switch (Stream.readRecord(Entry.ID, Record)) {
+ Expected<unsigned> 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]
// At the end of this routine the module Index is populated with a map
// from global value id to GlobalValueSummary objects.
Error ModuleSummaryIndexBitcodeReader::parseModule() {
- if (Stream.EnterSubBlock(bitc::MODULE_BLOCK_ID))
- return error("Invalid record");
+ if (Error Err = Stream.EnterSubBlock(bitc::MODULE_BLOCK_ID))
+ return Err;
SmallVector<uint64_t, 64> Record;
DenseMap<unsigned, GlobalValue::LinkageTypes> ValueIdToLinkageMap;
// Read the index for this module.
while (true) {
- BitstreamEntry Entry = Stream.advance();
+ Expected<llvm::BitstreamEntry> MaybeEntry = Stream.advance();
+ if (!MaybeEntry)
+ return MaybeEntry.takeError();
+ llvm::BitstreamEntry Entry = MaybeEntry.get();
switch (Entry.Kind) {
case BitstreamEntry::Error:
case BitstreamEntry::SubBlock:
switch (Entry.ID) {
default: // Skip unknown content.
- if (Stream.SkipBlock())
- return error("Invalid record");
+ if (Error Err = Stream.SkipBlock())
+ return Err;
break;
case bitc::BLOCKINFO_BLOCK_ID:
// Need to parse these to get abbrev ids (e.g. for VST)
assert(((SeenValueSymbolTable && VSTOffset > 0) ||
!SeenGlobalValSummary) &&
"Expected early VST parse via VSTOffset record");
- if (Stream.SkipBlock())
- return error("Invalid record");
+ if (Error Err = Stream.SkipBlock())
+ return Err;
break;
case bitc::GLOBALVAL_SUMMARY_BLOCK_ID:
case bitc::FULL_LTO_GLOBALVAL_SUMMARY_BLOCK_ID:
case BitstreamEntry::Record: {
Record.clear();
- auto BitCode = Stream.readRecord(Entry.ID, Record);
- switch (BitCode) {
+ Expected<unsigned> 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: {
// Eagerly parse the entire summary block. This populates the GlobalValueSummary
// objects in the index.
Error ModuleSummaryIndexBitcodeReader::parseEntireSummary(unsigned ID) {
- if (Stream.EnterSubBlock(ID))
- return error("Invalid record");
+ if (Error Err = Stream.EnterSubBlock(ID))
+ return Err;
SmallVector<uint64_t, 64> Record;
// Parse version
{
- BitstreamEntry Entry = Stream.advanceSkippingSubblocks();
+ Expected<BitstreamEntry> 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<unsigned> 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];
PendingTypeCheckedLoadConstVCalls;
while (true) {
- BitstreamEntry Entry = Stream.advanceSkippingSubblocks();
+ Expected<BitstreamEntry> MaybeEntry = Stream.advanceSkippingSubblocks();
+ if (!MaybeEntry)
+ return MaybeEntry.takeError();
+ BitstreamEntry Entry = MaybeEntry.get();
switch (Entry.Kind) {
case BitstreamEntry::SubBlock: // Handled for us already.
// 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<unsigned> 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]
// Parse the module string table block into the Index.
// This populates the ModulePathStringTable map in the index.
Error ModuleSummaryIndexBitcodeReader::parseModuleStringTable() {
- if (Stream.EnterSubBlock(bitc::MODULE_STRTAB_BLOCK_ID))
- return error("Invalid record");
+ if (Error Err = Stream.EnterSubBlock(bitc::MODULE_STRTAB_BLOCK_ID))
+ return Err;
SmallVector<uint64_t, 64> Record;
ModuleSummaryIndex::ModuleInfo *LastSeenModule = nullptr;
while (true) {
- BitstreamEntry Entry = Stream.advanceSkippingSubblocks();
+ Expected<BitstreamEntry> MaybeEntry = Stream.advanceSkippingSubblocks();
+ if (!MaybeEntry)
+ return MaybeEntry.takeError();
+ BitstreamEntry Entry = MaybeEntry.get();
switch (Entry.Kind) {
case BitstreamEntry::SubBlock: // Handled for us already.
}
Record.clear();
- switch (Stream.readRecord(Entry.ID, Record)) {
+ Expected<unsigned> MaybeRecord = Stream.readRecord(Entry.ID, Record);
+ if (!MaybeRecord)
+ return MaybeRecord.takeError();
+ switch (MaybeRecord.get()) {
default: // Default behavior: ignore.
break;
case bitc::MST_CODE_ENTRY: {
static Expected<StringRef> readBlobInRecord(BitstreamCursor &Stream,
unsigned Block, unsigned RecordID) {
- if (Stream.EnterSubBlock(Block))
- return error("Invalid record");
+ if (Error Err = Stream.EnterSubBlock(Block))
+ return std::move(Err);
StringRef Strtab;
while (true) {
- BitstreamEntry Entry = Stream.advance();
+ Expected<llvm::BitstreamEntry> MaybeEntry = Stream.advance();
+ if (!MaybeEntry)
+ return MaybeEntry.takeError();
+ llvm::BitstreamEntry Entry = MaybeEntry.get();
+
switch (Entry.Kind) {
case BitstreamEntry::EndBlock:
return Strtab;
return error("Malformed block");
case BitstreamEntry::SubBlock:
- if (Stream.SkipBlock())
- return error("Malformed block");
+ if (Error Err = Stream.SkipBlock())
+ return std::move(Err);
break;
case BitstreamEntry::Record:
StringRef Blob;
SmallVector<uint64_t, 1> Record;
- if (Stream.readRecord(Entry.ID, Record, &Blob) == RecordID)
+ Expected<unsigned> MaybeRecord =
+ Stream.readRecord(Entry.ID, Record, &Blob);
+ if (!MaybeRecord)
+ return MaybeRecord.takeError();
+ if (MaybeRecord.get() == RecordID)
Strtab = Blob;
break;
}
if (BCBegin + 8 >= Stream.getBitcodeBytes().size())
return F;
- BitstreamEntry Entry = Stream.advance();
+ Expected<llvm::BitstreamEntry> MaybeEntry = Stream.advance();
+ if (!MaybeEntry)
+ return MaybeEntry.takeError();
+ llvm::BitstreamEntry Entry = MaybeEntry.get();
+
switch (Entry.Kind) {
case BitstreamEntry::EndBlock:
case BitstreamEntry::Error:
uint64_t IdentificationBit = -1ull;
if (Entry.ID == bitc::IDENTIFICATION_BLOCK_ID) {
IdentificationBit = Stream.GetCurrentBitNo() - BCBegin * 8;
- if (Stream.SkipBlock())
- return error("Malformed block");
+ if (Error Err = Stream.SkipBlock())
+ return std::move(Err);
+
+ {
+ Expected<llvm::BitstreamEntry> MaybeEntry = Stream.advance();
+ if (!MaybeEntry)
+ return MaybeEntry.takeError();
+ Entry = MaybeEntry.get();
+ }
- Entry = Stream.advance();
if (Entry.Kind != BitstreamEntry::SubBlock ||
Entry.ID != bitc::MODULE_BLOCK_ID)
return error("Malformed block");
if (Entry.ID == bitc::MODULE_BLOCK_ID) {
uint64_t ModuleBit = Stream.GetCurrentBitNo() - BCBegin * 8;
- if (Stream.SkipBlock())
- return error("Malformed block");
+ if (Error Err = Stream.SkipBlock())
+ return std::move(Err);
F.Mods.push_back({Stream.getBitcodeBytes().slice(
BCBegin, Stream.getCurrentByteNo() - BCBegin),
continue;
}
- if (Stream.SkipBlock())
- return error("Malformed block");
+ if (Error Err = Stream.SkipBlock())
+ return std::move(Err);
continue;
}
case BitstreamEntry::Record:
- Stream.skipRecord(Entry.ID);
- continue;
+ if (Expected<unsigned> StreamFailed = Stream.skipRecord(Entry.ID))
+ continue;
+ else
+ return StreamFailed.takeError();
}
}
}
std::string ProducerIdentification;
if (IdentificationBit != -1ull) {
- Stream.JumpToBit(IdentificationBit);
+ if (Error JumpFailed = Stream.JumpToBit(IdentificationBit))
+ return std::move(JumpFailed);
Expected<std::string> ProducerIdentificationOrErr =
readIdentificationBlock(Stream);
if (!ProducerIdentificationOrErr)
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);
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);
// Parse the specified bitcode buffer, returning the function info index.
Expected<std::unique_ptr<ModuleSummaryIndex>> BitcodeModule::getSummary() {
BitstreamCursor Stream(Buffer);
- Stream.JumpToBit(ModuleBit);
+ if (Error JumpFailed = Stream.JumpToBit(ModuleBit))
+ return std::move(JumpFailed);
auto Index = llvm::make_unique<ModuleSummaryIndex>(/*HaveGVs=*/false);
ModuleSummaryIndexBitcodeReader R(std::move(Stream), Strtab, *Index,
static Expected<bool> getEnableSplitLTOUnitFlag(BitstreamCursor &Stream,
unsigned ID) {
- if (Stream.EnterSubBlock(ID))
- return error("Invalid record");
+ if (Error Err = Stream.EnterSubBlock(ID))
+ return std::move(Err);
SmallVector<uint64_t, 64> Record;
while (true) {
- BitstreamEntry Entry = Stream.advanceSkippingSubblocks();
+ Expected<BitstreamEntry> MaybeEntry = Stream.advanceSkippingSubblocks();
+ if (!MaybeEntry)
+ return MaybeEntry.takeError();
+ BitstreamEntry Entry = MaybeEntry.get();
switch (Entry.Kind) {
case BitstreamEntry::SubBlock: // Handled for us already.
// Look for the FS_FLAGS record.
Record.clear();
- auto BitCode = Stream.readRecord(Entry.ID, Record);
- switch (BitCode) {
+ Expected<unsigned> MaybeBitCode = Stream.readRecord(Entry.ID, Record);
+ if (!MaybeBitCode)
+ return MaybeBitCode.takeError();
+ switch (MaybeBitCode.get()) {
default: // Default behavior: ignore.
break;
case bitc::FS_FLAGS: { // [flags]
// Check if the given bitcode buffer contains a global value summary block.
Expected<BitcodeLTOInfo> 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");
+ if (Error Err = Stream.EnterSubBlock(bitc::MODULE_BLOCK_ID))
+ return std::move(Err);
while (true) {
- BitstreamEntry Entry = Stream.advance();
+ Expected<llvm::BitstreamEntry> MaybeEntry = Stream.advance();
+ if (!MaybeEntry)
+ return MaybeEntry.takeError();
+ llvm::BitstreamEntry Entry = MaybeEntry.get();
switch (Entry.Kind) {
case BitstreamEntry::Error:
}
// Ignore other sub-blocks.
- if (Stream.SkipBlock())
- return error("Malformed block");
+ if (Error Err = Stream.SkipBlock())
+ return std::move(Err);
continue;
case BitstreamEntry::Record:
- Stream.skipRecord(Entry.ID);
- continue;
+ if (Expected<unsigned> StreamFailed = Stream.skipRecord(Entry.ID))
+ continue;
+ else
+ return StreamFailed.takeError();
}
}
}
// BitstreamCursor implementation
//===----------------------------------------------------------------------===//
-/// 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) {
+/// Having read the ENTER_SUBBLOCK abbrevid, enter the block.
+Error BitstreamCursor::EnterSubBlock(unsigned BlockID, unsigned *NumWordsP) {
// Save the current block's state on BlockScope.
BlockScope.push_back(Block(CurCodeSize));
BlockScope.back().PrevAbbrevs.swap(CurAbbrevs);
}
// Get the codesize of this block.
- CurCodeSize = ReadVBR(bitc::CodeLenWidth);
- // We can't read more than MaxChunkSize at a time
+ Expected<uint32_t> MaybeVBR = ReadVBR(bitc::CodeLenWidth);
+ if (!MaybeVBR)
+ return MaybeVBR.takeError();
+ CurCodeSize = MaybeVBR.get();
+
if (CurCodeSize > MaxChunkSize)
- return true;
+ return llvm::createStringError(
+ std::errc::illegal_byte_sequence,
+ "can't read more than %zu at a time, trying to read %u", +MaxChunkSize,
+ CurCodeSize);
SkipToFourByteBoundary();
- unsigned NumWords = Read(bitc::BlockSizeWidth);
- if (NumWordsP) *NumWordsP = NumWords;
-
- // Validate that this block is sane.
- return CurCodeSize == 0 || AtEndOfStream();
+ Expected<word_t> MaybeNum = Read(bitc::BlockSizeWidth);
+ if (!MaybeNum)
+ return MaybeNum.takeError();
+ word_t NumWords = MaybeNum.get();
+ if (NumWordsP)
+ *NumWordsP = NumWords;
+
+ if (CurCodeSize == 0)
+ return llvm::createStringError(
+ std::errc::illegal_byte_sequence,
+ "can't enter sub-block: current code size is 0");
+ if (AtEndOfStream())
+ return llvm::createStringError(
+ std::errc::illegal_byte_sequence,
+ "can't enter sub block: already at end of stream");
+
+ return Error::success();
}
-static uint64_t readAbbreviatedField(BitstreamCursor &Cursor,
- const BitCodeAbbrevOp &Op) {
+static Expected<uint64_t> readAbbreviatedField(BitstreamCursor &Cursor,
+ const BitCodeAbbrevOp &Op) {
assert(!Op.isLiteral() && "Not to be used with literals!");
// Decode the value as we are commanded.
assert((unsigned)Op.getEncodingData() <= Cursor.MaxChunkSize);
return Cursor.ReadVBR64((unsigned)Op.getEncodingData());
case BitCodeAbbrevOp::Char6:
- return BitCodeAbbrevOp::DecodeChar6(Cursor.Read(6));
+ if (Expected<unsigned> 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.
llvm_unreachable("Should not reach here");
case BitCodeAbbrevOp::Fixed:
assert((unsigned)Op.getEncodingData() <= Cursor.MaxChunkSize);
- Cursor.Read((unsigned)Op.getEncodingData());
- break;
+ if (Expected<unsigned> 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<uint64_t> Res =
+ Cursor.ReadVBR64((unsigned)Op.getEncodingData()))
+ break;
+ else
+ return Res.takeError();
case BitCodeAbbrevOp::Char6:
- Cursor.Read(6);
- break;
+ if (Expected<unsigned> 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<unsigned> 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<uint32_t> MaybeCode = ReadVBR(6);
+ if (!MaybeCode)
+ return MaybeCode.takeError();
+ unsigned Code = MaybeCode.get();
+ Expected<uint32_t> MaybeVBR = ReadVBR(6);
+ if (!MaybeVBR)
+ return MaybeVBR.get();
+ unsigned NumElts = MaybeVBR.get();
for (unsigned i = 0; i != NumElts; ++i)
- (void)ReadVBR64(6);
+ if (Expected<uint64_t> Res = ReadVBR64(6))
+ ; // Skip!
+ else
+ return Res.takeError();
return Code;
}
else {
if (CodeOp.getEncoding() == BitCodeAbbrevOp::Array ||
CodeOp.getEncoding() == BitCodeAbbrevOp::Blob)
- report_fatal_error("Abbreviation starts with an Array or a Blob");
- Code = readAbbreviatedField(*this, CodeOp);
+ return llvm::createStringError(
+ std::errc::illegal_byte_sequence,
+ "Abbreviation starts with an Array or a Blob");
+ Expected<uint64_t> MaybeCode = readAbbreviatedField(*this, CodeOp);
+ if (!MaybeCode)
+ return MaybeCode.takeError();
+ Code = MaybeCode.get();
}
for (unsigned i = 1, e = Abbv->getNumOperandInfos(); i < e; ++i) {
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<uint32_t> 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?");
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<uint64_t> 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;
assert(Op.getEncoding() == BitCodeAbbrevOp::Blob);
// Blob case. Read the number of bytes as a vbr6.
- unsigned NumElts = ReadVBR(6);
+ Expected<uint32_t> 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.
}
// Skip over the blob.
- JumpToBit(NewEnd);
+ if (Error Err = JumpToBit(NewEnd))
+ return std::move(Err);
}
return Code;
}
-unsigned BitstreamCursor::readRecord(unsigned AbbrevID,
- SmallVectorImpl<uint64_t> &Vals,
- StringRef *Blob) {
+Expected<unsigned> BitstreamCursor::readRecord(unsigned AbbrevID,
+ SmallVectorImpl<uint64_t> &Vals,
+ StringRef *Blob) {
if (AbbrevID == bitc::UNABBREV_RECORD) {
- unsigned Code = ReadVBR(6);
- unsigned NumElts = ReadVBR(6);
+ Expected<uint32_t> MaybeCode = ReadVBR(6);
+ if (!MaybeCode)
+ return MaybeCode.takeError();
+ uint32_t Code = MaybeCode.get();
+ Expected<uint32_t> 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<uint64_t> MaybeVal = ReadVBR64(6))
+ Vals.push_back(MaybeVal.get());
+ else
+ return MaybeVal.takeError();
return Code;
}
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<uint64_t> MaybeCode = readAbbreviatedField(*this, CodeOp))
+ Code = MaybeCode.get();
+ else
+ return MaybeCode.takeError();
}
for (unsigned i = 1, e = Abbv->getNumOperandInfos(); i != e; ++i) {
if (Op.getEncoding() != BitCodeAbbrevOp::Array &&
Op.getEncoding() != BitCodeAbbrevOp::Blob) {
- Vals.push_back(readAbbreviatedField(*this, Op));
+ if (Expected<uint64_t> 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<uint32_t> MaybeNumElts = ReadVBR(6);
+ if (!MaybeNumElts)
+ return MaybeNumElts.takeError();
+ uint32_t NumElts = MaybeNumElts.get();
// Get the element encoding.
if (i + 2 != e)
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<SimpleBitstreamCursor::word_t> 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<uint64_t> 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<SimpleBitstreamCursor::word_t> 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<uint32_t> 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.
// 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.
return Code;
}
-void BitstreamCursor::ReadAbbrevRecord() {
+Error BitstreamCursor::ReadAbbrevRecord() {
auto Abbv = std::make_shared<BitCodeAbbrev>();
- unsigned NumOpInfo = ReadVBR(5);
+ Expected<uint32_t> MaybeNumOpInfo = ReadVBR(5);
+ if (!MaybeNumOpInfo)
+ return MaybeNumOpInfo.takeError();
+ unsigned NumOpInfo = MaybeNumOpInfo.get();
for (unsigned i = 0; i != NumOpInfo; ++i) {
- bool IsLiteral = Read(1);
+ Expected<word_t> MaybeIsLiteral = Read(1);
+ if (!MaybeIsLiteral)
+ return MaybeIsLiteral.takeError();
+ bool IsLiteral = MaybeIsLiteral.get();
if (IsLiteral) {
- Abbv->Add(BitCodeAbbrevOp(ReadVBR64(8)));
+ Expected<uint64_t> MaybeOp = ReadVBR64(8);
+ if (!MaybeOp)
+ return MaybeOp.takeError();
+ Abbv->Add(BitCodeAbbrevOp(MaybeOp.get()));
continue;
}
- BitCodeAbbrevOp::Encoding E = (BitCodeAbbrevOp::Encoding)Read(3);
+ Expected<word_t> 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<uint64_t> 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
if (Abbv->getNumOperandInfos() == 0)
report_fatal_error("Abbrev record with no operands");
CurAbbrevs.push_back(std::move(Abbv));
+
+ return Error::success();
}
-Optional<BitstreamBlockInfo>
+Expected<Optional<BitstreamBlockInfo>>
BitstreamCursor::ReadBlockInfoBlock(bool ReadBlockInfoNames) {
- if (EnterSubBlock(bitc::BLOCKINFO_BLOCK_ID)) return None;
+ if (llvm::Error Err = EnterSubBlock(bitc::BLOCKINFO_BLOCK_ID))
+ return std::move(Err);
BitstreamBlockInfo NewBlockInfo;
// Read all the records for this module.
while (true) {
- BitstreamEntry Entry = advanceSkippingSubblocks(AF_DontAutoprocessAbbrevs);
+ Expected<BitstreamEntry> MaybeEntry =
+ advanceSkippingSubblocks(AF_DontAutoprocessAbbrevs);
+ if (!MaybeEntry)
+ return MaybeEntry.takeError();
+ BitstreamEntry Entry = MaybeEntry.get();
switch (Entry.Kind) {
case llvm::BitstreamEntry::SubBlock: // Handled for us already.
// 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.
// Read a record.
Record.clear();
- switch (readRecord(Entry.ID, Record)) {
- default: break; // Default behavior, ignore unknown content.
- case bitc::BLOCKINFO_CODE_SETBID:
- if (Record.size() < 1) return None;
- CurBlockInfo = &NewBlockInfo.getOrCreateBlockInfo((unsigned)Record[0]);
- break;
- case bitc::BLOCKINFO_CODE_BLOCKNAME: {
- if (!CurBlockInfo) return None;
- if (!ReadBlockInfoNames)
- break; // Ignore name.
- std::string Name;
- for (unsigned i = 0, e = Record.size(); i != e; ++i)
- Name += (char)Record[i];
- CurBlockInfo->Name = Name;
- break;
- }
+ Expected<unsigned> 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;
+ CurBlockInfo = &NewBlockInfo.getOrCreateBlockInfo((unsigned)Record[0]);
+ break;
+ case bitc::BLOCKINFO_CODE_BLOCKNAME: {
+ if (!CurBlockInfo)
+ return None;
+ if (!ReadBlockInfoNames)
+ break; // Ignore name.
+ std::string Name;
+ for (unsigned i = 0, e = Record.size(); i != e; ++i)
+ Name += (char)Record[i];
+ CurBlockInfo->Name = Name;
+ break;
+ }
case bitc::BLOCKINFO_CODE_SETRECORDNAME: {
if (!CurBlockInfo) return None;
if (!ReadBlockInfoNames)
Name));
break;
}
- }
+ }
}
}
SmallVector<uint64_t, 64> Record;
// Get the abbrevs, and preload record positions to make them lazy-loadable.
while (true) {
- BitstreamEntry Entry = IndexCursor.advanceSkippingSubblocks(
+ Expected<BitstreamEntry> 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:
// The interesting case.
++NumMDRecordLoaded;
uint64_t CurrentPos = IndexCursor.GetCurrentBitNo();
- auto Code = IndexCursor.skipRecord(Entry.ID);
+ Expected<unsigned> 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<unsigned> MaybeRecord =
+ IndexCursor.readRecord(Entry.ID, Record, &Blob))
+ ;
+ else
+ return MaybeRecord.takeError();
unsigned NumStrings = Record[0];
MDStringRef.reserve(NumStrings);
auto IndexNextMDString = [&](StringRef Str) {
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<unsigned> 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<BitstreamEntry> 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<unsigned> 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());
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<unsigned> 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<unsigned> 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<unsigned> MaybeNextBitCode =
+ IndexCursor.readRecord(Code, Record))
+ assert(MaybeNextBitCode.get() == bitc::METADATA_NAMED_NODE);
+ else
+ return MaybeNextBitCode.takeError();
// Read named metadata elements.
unsigned Size = Record.size();
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<unsigned> MaybeRecord =
+ IndexCursor.readRecord(Entry.ID, Record))
+ ;
+ else
+ return MaybeRecord.takeError();
if (Record.size() % 2 == 0)
return error("Invalid record");
unsigned ValueID = Record[0];
// skip the whole block in case we lazy-load.
auto EntryPos = Stream.GetCurrentBitNo();
- if (Stream.EnterSubBlock(bitc::METADATA_BLOCK_ID))
- return error("Invalid record");
+ if (Error Err = Stream.EnterSubBlock(bitc::METADATA_BLOCK_ID))
+ return Err;
SmallVector<uint64_t, 64> Record;
PlaceholderQueue Placeholders;
// 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 (Stream.SkipBlock())
- return error("Invalid record");
+ if (Error Err = IndexCursor.JumpToBit(EntryPos))
+ return Err;
+ if (Error Err = Stream.SkipBlock()) {
+ // FIXME this drops the error on the floor, which
+ // ThinLTO/X86/debuginfo-cu-import.ll relies on.
+ consumeError(std::move(Err));
+ return Error::success();
+ }
return Error::success();
}
// Couldn't load an index, fallback to loading all the block "old-style".
// Read all the records.
while (true) {
- BitstreamEntry Entry = Stream.advanceSkippingSubblocks();
+ Expected<BitstreamEntry> MaybeEntry = Stream.advanceSkippingSubblocks();
+ if (!MaybeEntry)
+ return MaybeEntry.takeError();
+ BitstreamEntry Entry = MaybeEntry.get();
switch (Entry.Kind) {
case BitstreamEntry::SubBlock: // Handled for us already.
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<unsigned> MaybeCode =
+ Stream.readRecord(Entry.ID, Record, &Blob)) {
+ if (Error Err = parseOneMetadata(Record, MaybeCode.get(), Placeholders,
+ Blob, NextMetadataNo))
+ return Err;
+ } else
+ return MaybeCode.takeError();
}
}
}
SmallVector<uint64_t, 64> 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<BitstreamEntry> MaybeEntry = IndexCursor.advanceSkippingSubblocks();
+ if (!MaybeEntry)
+ // FIXME this drops the error on the floor.
+ report_fatal_error("lazyLoadOneMetadata failed advanceSkippingSubblocks: " +
+ toString(MaybeEntry.takeError()));
+ 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<unsigned> 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.
// Read name of the named metadata.
SmallString<8> Name(Record.begin(), Record.end());
Record.clear();
- Code = Stream.ReadCode();
+ Expected<unsigned> 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<unsigned> 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();
if (R.AtEndOfStream())
return error("Invalid record: metadata strings bad length");
- unsigned Size = R.ReadVBR(6);
+ Expected<uint32_t> 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");
/// Parse metadata attachments.
Error MetadataLoader::MetadataLoaderImpl::parseMetadataAttachment(
Function &F, const SmallVectorImpl<Instruction *> &InstructionList) {
- if (Stream.EnterSubBlock(bitc::METADATA_ATTACHMENT_ID))
- return error("Invalid record");
+ if (Error Err = Stream.EnterSubBlock(bitc::METADATA_ATTACHMENT_ID))
+ return Err;
SmallVector<uint64_t, 64> Record;
PlaceholderQueue Placeholders;
while (true) {
- BitstreamEntry Entry = Stream.advanceSkippingSubblocks();
+ Expected<BitstreamEntry> MaybeEntry = Stream.advanceSkippingSubblocks();
+ if (!MaybeEntry)
+ return MaybeEntry.takeError();
+ BitstreamEntry Entry = MaybeEntry.get();
switch (Entry.Kind) {
case BitstreamEntry::SubBlock: // Handled for us already.
// Read a metadata attachment record.
Record.clear();
++NumMDRecordLoaded;
- switch (Stream.readRecord(Entry.ID, Record)) {
+ Expected<unsigned> MaybeRecord = Stream.readRecord(Entry.ID, Record);
+ if (!MaybeRecord)
+ return MaybeRecord.takeError();
+ switch (MaybeRecord.get()) {
default: // Default behavior: ignore.
break;
case bitc::METADATA_ATTACHMENT: {
/// Parse the metadata kinds out of the METADATA_KIND_BLOCK.
Error MetadataLoader::MetadataLoaderImpl::parseMetadataKinds() {
- if (Stream.EnterSubBlock(bitc::METADATA_KIND_BLOCK_ID))
- return error("Invalid record");
+ if (Error Err = Stream.EnterSubBlock(bitc::METADATA_KIND_BLOCK_ID))
+ return Err;
SmallVector<uint64_t, 64> Record;
// Read all the records.
while (true) {
- BitstreamEntry Entry = Stream.advanceSkippingSubblocks();
+ Expected<BitstreamEntry> MaybeEntry = Stream.advanceSkippingSubblocks();
+ if (!MaybeEntry)
+ return MaybeEntry.takeError();
+ BitstreamEntry Entry = MaybeEntry.get();
switch (Entry.Kind) {
case BitstreamEntry::SubBlock: // Handled for us already.
// Read a record.
Record.clear();
++NumMDRecordLoaded;
- unsigned Code = Stream.readRecord(Entry.ID, Record);
- switch (Code) {
+ Expected<unsigned> MaybeCode = Stream.readRecord(Entry.ID, Record);
+ if (!MaybeCode)
+ return MaybeCode.takeError();
+ switch (MaybeCode.get()) {
default: // Default behavior: ignore.
break;
case bitc::METADATA_KIND: {
RUN: not llvm-dis -disable-output %p/Inputs/invalid-invoke-non-function-explicit-type.bc 2>&1 | \
RUN: FileCheck --check-prefix=NON-FUNCTION-EXPLICIT-INVOKE %s
-INVALID-EMPTY: Invalid bitcode signature
+INVALID-EMPTY: error: file too small to contain bitcode header
INVALID-ENCODING: Invalid encoding
-BAD-ABBREV: Malformed block
-UNEXPECTED-EOF: Malformed block
-BAD-ABBREV-NUMBER: Malformed block
+BAD-ABBREV: error: can't skip to bit 25870861920 from 96
+UNEXPECTED-EOF: error: can't skip to bit 25870861920 from 96
+BAD-ABBREV-NUMBER: error: can't skip to bit 25870861920 from 96
BAD-TYPE-TABLE-FORWARD-REF: Invalid TYPE table: Only named structs can be forward referenced
-BAD-BITWIDTH: Malformed block
+BAD-BITWIDTH: error: can't skip to bit 3616 from 96
BAD-ALIGN: Invalid alignment value
MISMATCHED-EXPLICIT-GEP: Explicit gep type does not match pointee type of pointer operand
MISMATCHED-EXPLICIT-LOAD: Explicit load/store type does not match pointee type of pointer operand
RUN: not llvm-dis -disable-output %p/Inputs/invalid-load-ptr-type.bc 2>&1 | \
RUN: FileCheck --check-prefix=BAD-LOAD-PTR-TYPE %s
-BAD-LOAD-PTR-TYPE: Malformed block
+BAD-LOAD-PTR-TYPE: error: can't skip to bit 3616 from 96
RUN: not llvm-dis -disable-output %p/Inputs/invalid-inserted-value-type-mismatch.bc 2>&1 | \
RUN: FileCheck --check-prefix=INSERT-TYPE-MISMATCH %s
RUN: not llvm-dis -disable-output %p/Inputs/invalid-code-len-width.bc 2>&1 | \
RUN: FileCheck --check-prefix=INVALID-CODELENWIDTH %s
-INVALID-CODELENWIDTH: Malformed block
+INVALID-CODELENWIDTH: error: can't skip to bit 3616 from 96
RUN: not llvm-dis -disable-output %p/Inputs/invalid-function-argument-type.bc 2>&1 | \
RUN: FileCheck --check-prefix=INVALID-ARGUMENT-TYPE %s
; CHECK-LIBS: llvm-lto: {{.*}}/Inputs/empty.bc: Could not read LTO input file: The file was not recognized as a valid object file
; RUN: not llvm-lto --thinlto %S/Inputs/empty.bc 2>&1 | FileCheck %s --check-prefix=CHECK-THIN
-; CHECK-THIN: llvm-lto: error loading file '{{.*}}/Inputs/empty.bc': Invalid bitcode signature
+; CHECK-THIN: llvm-lto: error loading file '{{.*}}/Inputs/empty.bc': file too small to contain bitcode header
static std::map<unsigned, PerBlockIDStats> BlockIDStats;
-
-
-/// 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<uint64_t> Record,
StringRef Blob) {
if (R.AtEndOfStream())
return ReportError("bad length");
- unsigned Size = R.ReadVBR(6);
+ Expected<uint32_t> MaybeSize = R.ReadVBR(6);
+ if (!MaybeSize)
+ return ReportError(MaybeSize.takeError());
+ uint32_t Size = MaybeSize.get();
if (Strings.size() < Size)
return ReportError("truncated chars");
bool DumpRecords = Dump;
if (BlockID == bitc::BLOCKINFO_BLOCK_ID) {
if (Dump) outs() << Indent << "<BLOCKINFO_BLOCK/>\n";
- Optional<BitstreamBlockInfo> NewBlockInfo =
+ Expected<Optional<BitstreamBlockInfo>> MaybeNewBlockInfo =
Stream.ReadBlockInfoBlock(/*ReadBlockInfoNames=*/true);
+ if (!MaybeNewBlockInfo)
+ return ReportError(MaybeNewBlockInfo.takeError());
+ Optional<BitstreamBlockInfo> 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;
}
unsigned NumWords = 0;
- if (Stream.EnterSubBlock(BlockID, &NumWords))
- return ReportError("Malformed block record");
+ if (Error Err = Stream.EnterSubBlock(BlockID, &NumWords))
+ return ReportError(std::move(Err));
// Keep it for later, when we see a MODULE_HASH record
uint64_t BlockEntryPos = Stream.getCurrentByteNo();
uint64_t RecordStartBit = Stream.GetCurrentBitNo();
- BitstreamEntry Entry =
- Stream.advance(BitstreamCursor::AF_DontAutoprocessAbbrevs);
-
+ Expected<BitstreamEntry> 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");
}
if (Entry.ID == bitc::DEFINE_ABBREV) {
- Stream.ReadAbbrevRecord();
+ if (Error Err = Stream.ReadAbbrevRecord())
+ return ReportError(std::move(Err));
++BlockStats.NumAbbrevs;
continue;
}
StringRef Blob;
uint64_t CurrentRecordPos = Stream.GetCurrentBitNo();
- unsigned Code = Stream.readRecord(Entry.ID, Record, &Blob);
+ Expected<unsigned> 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)
}
// 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<unsigned> Skipped = Stream.skipRecord(Entry.ID))
+ ; // Do nothing.
+ else
+ return ReportError(Skipped.takeError());
}
}
(double)Bits/8, (unsigned long)(Bits/32));
}
-static CurStreamTypeType ReadSignature(BitstreamCursor &Stream) {
+static Expected<CurStreamTypeType> ReadSignature(BitstreamCursor &Stream) {
+ auto tryRead = [&Stream](char &Dest, size_t size) -> Error {
+ if (Expected<SimpleBitstreamCursor::word_t> 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)
}
Stream = BitstreamCursor(ArrayRef<uint8_t>(BufPtr, EndBufPtr));
- CurStreamType = ReadSignature(Stream);
+ Expected<CurStreamTypeType> MaybeSignature = ReadSignature(Stream);
+ if (!MaybeSignature)
+ return ReportError(MaybeSignature.takeError());
+ CurStreamType = std::move(MaybeSignature.get());
return false;
}
return true;
while (!BlockInfoCursor.AtEndOfStream()) {
- unsigned Code = BlockInfoCursor.ReadCode();
- if (Code != bitc::ENTER_SUBBLOCK)
+ Expected<unsigned> 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<BitstreamBlockInfo> NewBlockInfo =
+ Expected<unsigned> MaybeBlockID = BlockInfoCursor.ReadSubBlockID();
+ if (!MaybeBlockID)
+ return ReportError(MaybeBlockID.takeError());
+ if (MaybeBlockID.get() == bitc::BLOCKINFO_BLOCK_ID) {
+ Expected<Optional<BitstreamBlockInfo>> MaybeNewBlockInfo =
BlockInfoCursor.ReadBlockInfoBlock(/*ReadBlockInfoNames=*/true);
+ if (!MaybeNewBlockInfo)
+ return ReportError(MaybeNewBlockInfo.takeError());
+ Optional<BitstreamBlockInfo> NewBlockInfo =
+ std::move(MaybeNewBlockInfo.get());
if (!NewBlockInfo)
return ReportError("Malformed BlockInfoBlock in block info file");
BlockInfo = std::move(*NewBlockInfo);
break;
}
- BlockInfoCursor.SkipBlock();
+ if (Error Err = BlockInfoCursor.SkipBlock())
+ return ReportError(std::move(Err));
}
}
// 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<unsigned> 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<unsigned> 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;
}
BitstreamCursor Cursor(Bytes);
EXPECT_FALSE(Cursor.AtEndOfStream());
- (void)Cursor.Read(8);
+ Expected<SimpleBitstreamCursor::word_t> MaybeRead = Cursor.Read(8);
+ EXPECT_TRUE((bool)MaybeRead);
EXPECT_FALSE(Cursor.AtEndOfStream());
- (void)Cursor.Read(24);
+ MaybeRead = Cursor.Read(24);
+ EXPECT_TRUE((bool)MaybeRead);
EXPECT_TRUE(Cursor.AtEndOfStream());
- Cursor.JumpToBit(0);
+ EXPECT_FALSE(Cursor.JumpToBit(0));
EXPECT_FALSE(Cursor.AtEndOfStream());
- Cursor.JumpToBit(32);
+ EXPECT_FALSE(Cursor.JumpToBit(32));
EXPECT_TRUE(Cursor.AtEndOfStream());
}
};
BitstreamCursor Cursor(Bytes);
- Cursor.JumpToBit(32);
+ EXPECT_FALSE(Cursor.JumpToBit(32));
EXPECT_TRUE(Cursor.AtEndOfStream());
}
for (unsigned I = 0, E = 32; I != E; ++I) {
EXPECT_EQ(I / 8, Cursor.getCurrentByteNo());
- (void)Cursor.Read(1);
+ Expected<SimpleBitstreamCursor::word_t> MaybeRead = Cursor.Read(1);
+ EXPECT_TRUE((bool)MaybeRead);
}
EXPECT_EQ(4u, Cursor.getCurrentByteNo());
}
// Header. Included in test so that we can run llvm-bcanalyzer to debug
// when there are problems.
- ASSERT_EQ(Magic, Stream.Read(32));
+ Expected<SimpleBitstreamCursor::word_t> MaybeRead = Stream.Read(32);
+ ASSERT_TRUE((bool)MaybeRead);
+ ASSERT_EQ(Magic, MaybeRead.get());
// Block.
- BitstreamEntry Entry =
+ Expected<BitstreamEntry> MaybeEntry =
Stream.advance(BitstreamCursor::AF_DontAutoprocessAbbrevs);
+ ASSERT_TRUE((bool)MaybeEntry);
+ BitstreamEntry Entry = MaybeEntry.get();
ASSERT_EQ(BitstreamEntry::SubBlock, Entry.Kind);
ASSERT_EQ(BlockID, Entry.ID);
ASSERT_FALSE(Stream.EnterSubBlock(BlockID));
// Abbreviation.
- Entry = Stream.advance();
+ MaybeEntry = Stream.advance();
+ ASSERT_TRUE((bool)MaybeEntry);
+ Entry = MaybeEntry.get();
ASSERT_EQ(BitstreamEntry::Record, Entry.Kind);
ASSERT_EQ(AbbrevID, Entry.ID);
// Record.
StringRef BlobOut;
SmallVector<uint64_t, 1> Record;
- ASSERT_EQ(RecordID, Stream.readRecord(Entry.ID, Record, &BlobOut));
+ Expected<unsigned> MaybeRecord =
+ Stream.readRecord(Entry.ID, Record, &BlobOut);
+ ASSERT_TRUE((bool)MaybeRecord);
+ ASSERT_EQ(RecordID, MaybeRecord.get());
EXPECT_TRUE(Record.empty());
EXPECT_EQ(BlobIn, BlobOut);
}
uint8_t Bytes[] = {8, 7, 6, 5, 4, 3, 2, 1};
for (unsigned I = 1; I != 8; ++I) {
SimpleBitstreamCursor Cursor(ArrayRef<uint8_t>(Bytes, I));
- EXPECT_EQ(8ull, Cursor.Read(8));
+ Expected<SimpleBitstreamCursor::word_t> MaybeRead = Cursor.Read(8);
+ ASSERT_TRUE((bool)MaybeRead);
+ EXPECT_EQ(8ull, MaybeRead.get());
}
}