Index: clang-tools-extra/clang-doc/BitcodeReader.h =================================================================== --- clang-tools-extra/clang-doc/BitcodeReader.h +++ clang-tools-extra/clang-doc/BitcodeReader.h @@ -22,6 +22,7 @@ #include "llvm/ADT/Optional.h" #include "llvm/ADT/SmallVector.h" #include "llvm/Bitcode/BitstreamReader.h" +#include "llvm/Support/Error.h" namespace clang { namespace doc { @@ -38,30 +39,31 @@ enum class Cursor { BadBlock = 1, Record, BlockEnd, BlockBegin }; // Top level parsing - bool validateStream(); - bool readVersion(); - bool readBlockInfoBlock(); + llvm::Error validateStream(); + llvm::Error readVersion(); + llvm::Error readBlockInfoBlock(); // Read a block of records into a single Info struct, calls readRecord on each // record found. - template bool readBlock(unsigned ID, T I); + template llvm::Error readBlock(unsigned ID, T I); // Step through a block of records to find the next data field. - template bool readSubBlock(unsigned ID, T I); + template llvm::Error readSubBlock(unsigned ID, T I); // Read record data into the given Info data field, calling the appropriate // parseRecord functions to parse and store the data. - template bool readRecord(unsigned ID, T I); + template llvm::Error readRecord(unsigned ID, T I); // Allocate the relevant type of info and add read data to the object. - template std::unique_ptr createInfo(unsigned ID); + template + llvm::Expected> createInfo(unsigned ID); // Helper function to step through blocks to find and dispatch the next record // or block to be read. Cursor skipUntilRecordOrBlock(unsigned &BlockOrRecordID); // Helper function to set up the approriate type of Info. - std::unique_ptr readBlockToInfo(unsigned ID); + llvm::Expected> readBlockToInfo(unsigned ID); llvm::BitstreamCursor &Stream; Optional BlockInfo; Index: clang-tools-extra/clang-doc/BitcodeReader.cpp =================================================================== --- clang-tools-extra/clang-doc/BitcodeReader.cpp +++ clang-tools-extra/clang-doc/BitcodeReader.cpp @@ -10,6 +10,7 @@ #include "BitcodeReader.h" #include "llvm/ADT/IndexedMap.h" #include "llvm/ADT/Optional.h" +#include "llvm/Support/Error.h" #include "llvm/Support/raw_ostream.h" namespace clang { @@ -17,49 +18,53 @@ using Record = llvm::SmallVector; -bool decodeRecord(Record R, llvm::SmallVectorImpl &Field, - llvm::StringRef Blob) { +llvm::Error decodeRecord(Record R, llvm::SmallVectorImpl &Field, + llvm::StringRef Blob) { Field.assign(Blob.begin(), Blob.end()); - return true; + return llvm::Error::success(); } -bool decodeRecord(Record R, SymbolID &Field, llvm::StringRef Blob) { +llvm::Error decodeRecord(Record R, SymbolID &Field, llvm::StringRef Blob) { if (R[0] != BitCodeConstants::USRHashSize) - return false; + return llvm::make_error("Incorrect USR size.\n", + llvm::inconvertibleErrorCode()); // First position in the record is the length of the following array, so we // copy the following elements to the field. for (int I = 0, E = R[0]; I < E; ++I) Field[I] = R[I + 1]; - return true; + return llvm::Error::success(); } -bool decodeRecord(Record R, bool &Field, llvm::StringRef Blob) { +llvm::Error decodeRecord(Record R, bool &Field, llvm::StringRef Blob) { Field = R[0] != 0; - return true; + return llvm::Error::success(); } -bool decodeRecord(Record R, int &Field, llvm::StringRef Blob) { +llvm::Error decodeRecord(Record R, int &Field, llvm::StringRef Blob) { if (R[0] > INT_MAX) - return false; + return llvm::make_error("Integer too large to parse.\n", + llvm::inconvertibleErrorCode()); Field = (int)R[0]; - return true; + return llvm::Error::success(); } -bool decodeRecord(Record R, AccessSpecifier &Field, llvm::StringRef Blob) { +llvm::Error decodeRecord(Record R, AccessSpecifier &Field, + llvm::StringRef Blob) { switch (R[0]) { case AS_public: case AS_private: case AS_protected: case AS_none: Field = (AccessSpecifier)R[0]; - return true; + return llvm::Error::success(); default: - return false; + return llvm::make_error( + "Invalid value for AccessSpecifier.\n", llvm::inconvertibleErrorCode()); } } -bool decodeRecord(Record R, TagTypeKind &Field, llvm::StringRef Blob) { +llvm::Error decodeRecord(Record R, TagTypeKind &Field, llvm::StringRef Blob) { switch (R[0]) { case TTK_Struct: case TTK_Interface: @@ -67,21 +72,23 @@ case TTK_Class: case TTK_Enum: Field = (TagTypeKind)R[0]; - return true; + return llvm::Error::success(); default: - return false; + return llvm::make_error( + "Invalid value for TagTypeKind.\n", llvm::inconvertibleErrorCode()); } } -bool decodeRecord(Record R, llvm::Optional &Field, - llvm::StringRef Blob) { +llvm::Error decodeRecord(Record R, llvm::Optional &Field, + llvm::StringRef Blob) { if (R[0] > INT_MAX) - return false; + return llvm::make_error("Integer too large to parse.\n", + llvm::inconvertibleErrorCode()); Field.emplace((int)R[0], Blob); - return true; + return llvm::Error::success(); } -bool decodeRecord(Record R, InfoType &Field, llvm::StringRef Blob) { +llvm::Error decodeRecord(Record R, InfoType &Field, llvm::StringRef Blob) { switch (auto IT = static_cast(R[0])) { case InfoType::IT_namespace: case InfoType::IT_record: @@ -89,12 +96,13 @@ case InfoType::IT_default: case InfoType::IT_enum: Field = IT; - return true; + return llvm::Error::success(); } - return false; + return llvm::make_error("Invalid value for InfoType.\n", + llvm::inconvertibleErrorCode()); } -bool decodeRecord(Record R, FieldId &Field, llvm::StringRef Blob) { +llvm::Error decodeRecord(Record R, FieldId &Field, llvm::StringRef Blob) { switch (auto F = static_cast(R[0])) { case FieldId::F_namespace: case FieldId::F_parent: @@ -104,45 +112,51 @@ case FieldId::F_child_record: case FieldId::F_default: Field = F; - return true; + return llvm::Error::success(); } - return false; + return llvm::make_error("Invalid value for FieldId.\n", + llvm::inconvertibleErrorCode()); } -bool decodeRecord(Record R, llvm::SmallVectorImpl> &Field, - llvm::StringRef Blob) { +llvm::Error decodeRecord(Record R, + llvm::SmallVectorImpl> &Field, + llvm::StringRef Blob) { Field.push_back(Blob); - return true; + return llvm::Error::success(); } -bool decodeRecord(Record R, llvm::SmallVectorImpl &Field, - llvm::StringRef Blob) { +llvm::Error decodeRecord(Record R, llvm::SmallVectorImpl &Field, + llvm::StringRef Blob) { if (R[0] > INT_MAX) - return false; + return llvm::make_error("Integer too large to parse.\n", + llvm::inconvertibleErrorCode()); Field.emplace_back((int)R[0], Blob); - return true; + return llvm::Error::success(); } -bool parseRecord(Record R, unsigned ID, llvm::StringRef Blob, - const unsigned VersionNo) { +llvm::Error parseRecord(Record R, unsigned ID, llvm::StringRef Blob, + const unsigned VersionNo) { if (ID == VERSION && R[0] == VersionNo) - return true; - return false; + return llvm::Error::success(); + return llvm::make_error( + "Mismatched bitcode version number.\n", llvm::inconvertibleErrorCode()); } -bool parseRecord(Record R, unsigned ID, llvm::StringRef Blob, - NamespaceInfo *I) { +llvm::Error parseRecord(Record R, unsigned ID, llvm::StringRef Blob, + NamespaceInfo *I) { switch (ID) { case NAMESPACE_USR: return decodeRecord(R, I->USR, Blob); case NAMESPACE_NAME: return decodeRecord(R, I->Name, Blob); default: - return false; + return llvm::make_error( + "Invalid field for NamespaceInfo.\n", llvm::inconvertibleErrorCode()); } } -bool parseRecord(Record R, unsigned ID, llvm::StringRef Blob, RecordInfo *I) { +llvm::Error parseRecord(Record R, unsigned ID, llvm::StringRef Blob, + RecordInfo *I) { switch (ID) { case RECORD_USR: return decodeRecord(R, I->USR, Blob); @@ -155,11 +169,13 @@ case RECORD_TAG_TYPE: return decodeRecord(R, I->TagType, Blob); default: - return false; + return llvm::make_error( + "Invalid field for RecordInfo.\n", llvm::inconvertibleErrorCode()); } } -bool parseRecord(Record R, unsigned ID, llvm::StringRef Blob, EnumInfo *I) { +llvm::Error parseRecord(Record R, unsigned ID, llvm::StringRef Blob, + EnumInfo *I) { switch (ID) { case ENUM_USR: return decodeRecord(R, I->USR, Blob); @@ -174,11 +190,13 @@ case ENUM_SCOPED: return decodeRecord(R, I->Scoped, Blob); default: - return false; + return llvm::make_error("Invalid field for EnumInfo.\n", + llvm::inconvertibleErrorCode()); } } -bool parseRecord(Record R, unsigned ID, llvm::StringRef Blob, FunctionInfo *I) { +llvm::Error parseRecord(Record R, unsigned ID, llvm::StringRef Blob, + FunctionInfo *I) { switch (ID) { case FUNCTION_USR: return decodeRecord(R, I->USR, Blob); @@ -193,37 +211,42 @@ case FUNCTION_IS_METHOD: return decodeRecord(R, I->IsMethod, Blob); default: - return false; + return llvm::make_error( + "Invalid field for FunctionInfo.\n", llvm::inconvertibleErrorCode()); } } -bool parseRecord(Record R, unsigned ID, llvm::StringRef Blob, TypeInfo *I) { - return true; +llvm::Error parseRecord(Record R, unsigned ID, llvm::StringRef Blob, + TypeInfo *I) { + return llvm::Error::success(); } -bool parseRecord(Record R, unsigned ID, llvm::StringRef Blob, - FieldTypeInfo *I) { +llvm::Error parseRecord(Record R, unsigned ID, llvm::StringRef Blob, + FieldTypeInfo *I) { switch (ID) { case FIELD_TYPE_NAME: return decodeRecord(R, I->Name, Blob); default: - return false; + return llvm::make_error("Invalid field for TypeInfo.\n", + llvm::inconvertibleErrorCode()); } } -bool parseRecord(Record R, unsigned ID, llvm::StringRef Blob, - MemberTypeInfo *I) { +llvm::Error parseRecord(Record R, unsigned ID, llvm::StringRef Blob, + MemberTypeInfo *I) { switch (ID) { case MEMBER_TYPE_NAME: return decodeRecord(R, I->Name, Blob); case MEMBER_TYPE_ACCESS: return decodeRecord(R, I->Access, Blob); default: - return false; + return llvm::make_error( + "Invalid field for MemberTypeInfo.\n", llvm::inconvertibleErrorCode()); } } -bool parseRecord(Record R, unsigned ID, llvm::StringRef Blob, CommentInfo *I) { +llvm::Error parseRecord(Record R, unsigned ID, llvm::StringRef Blob, + CommentInfo *I) { switch (ID) { case COMMENT_KIND: return decodeRecord(R, I->Kind, Blob); @@ -248,12 +271,13 @@ case COMMENT_EXPLICIT: return decodeRecord(R, I->Explicit, Blob); default: - return false; + return llvm::make_error( + "Invalid field for CommentInfo.\n", llvm::inconvertibleErrorCode()); } } -bool parseRecord(Record R, unsigned ID, llvm::StringRef Blob, Reference *I, - FieldId &F) { +llvm::Error parseRecord(Record R, unsigned ID, llvm::StringRef Blob, + Reference *I, FieldId &F) { switch (ID) { case REFERENCE_USR: return decodeRecord(R, I->USR, Blob); @@ -264,159 +288,178 @@ case REFERENCE_FIELD: return decodeRecord(R, F, Blob); default: - return false; + return llvm::make_error("Invalid field for Reference.\n", + llvm::inconvertibleErrorCode()); } } -template CommentInfo *getCommentInfo(T I) { - llvm::errs() << "Cannot have comment subblock.\n"; - exit(1); +template llvm::Expected getCommentInfo(T I) { + return llvm::make_error( + "Invalid type cannot contain CommentInfo.\n", + llvm::inconvertibleErrorCode()); } -template <> CommentInfo *getCommentInfo(FunctionInfo *I) { +template <> llvm::Expected getCommentInfo(FunctionInfo *I) { I->Description.emplace_back(); return &I->Description.back(); } -template <> CommentInfo *getCommentInfo(NamespaceInfo *I) { +template <> llvm::Expected getCommentInfo(NamespaceInfo *I) { I->Description.emplace_back(); return &I->Description.back(); } -template <> CommentInfo *getCommentInfo(RecordInfo *I) { +template <> llvm::Expected getCommentInfo(RecordInfo *I) { I->Description.emplace_back(); return &I->Description.back(); } -template <> CommentInfo *getCommentInfo(EnumInfo *I) { +template <> llvm::Expected getCommentInfo(EnumInfo *I) { I->Description.emplace_back(); return &I->Description.back(); } -template <> CommentInfo *getCommentInfo(CommentInfo *I) { +template <> llvm::Expected getCommentInfo(CommentInfo *I) { I->Children.emplace_back(llvm::make_unique()); return I->Children.back().get(); } -template <> CommentInfo *getCommentInfo(std::unique_ptr &I) { +template <> +llvm::Expected getCommentInfo(std::unique_ptr &I) { return getCommentInfo(I.get()); } template -void addTypeInfo(T I, TTypeInfo &&TI) { - llvm::errs() << "Invalid type for info.\n"; - exit(1); +llvm::Error addTypeInfo(T I, TTypeInfo &&TI) { + return llvm::make_error( + "Invalid type cannot contain TypeInfo.\n", + llvm::inconvertibleErrorCode()); } -template <> void addTypeInfo(RecordInfo *I, MemberTypeInfo &&T) { +template <> llvm::Error addTypeInfo(RecordInfo *I, MemberTypeInfo &&T) { I->Members.emplace_back(std::move(T)); + return llvm::Error::success(); } -template <> void addTypeInfo(FunctionInfo *I, TypeInfo &&T) { +template <> llvm::Error addTypeInfo(FunctionInfo *I, TypeInfo &&T) { I->ReturnType = std::move(T); + return llvm::Error::success(); } -template <> void addTypeInfo(FunctionInfo *I, FieldTypeInfo &&T) { +template <> llvm::Error addTypeInfo(FunctionInfo *I, FieldTypeInfo &&T) { I->Params.emplace_back(std::move(T)); + return llvm::Error::success(); } -template void addReference(T I, Reference &&R, FieldId F) { - llvm::errs() << "Invalid field type for info.\n"; - exit(1); +template llvm::Error addReference(T I, Reference &&R, FieldId F) { + return llvm::make_error( + "Invalid type cannot contain Reference\n", + llvm::inconvertibleErrorCode()); } -template <> void addReference(TypeInfo *I, Reference &&R, FieldId F) { +template <> llvm::Error addReference(TypeInfo *I, Reference &&R, FieldId F) { switch (F) { case FieldId::F_type: I->Type = std::move(R); - break; + return llvm::Error::success(); default: - llvm::errs() << "Invalid field type for info.\n"; - exit(1); + return llvm::make_error( + "Invalid type cannot contain Reference.\n", + llvm::inconvertibleErrorCode()); } } -template <> void addReference(FieldTypeInfo *I, Reference &&R, FieldId F) { +template <> +llvm::Error addReference(FieldTypeInfo *I, Reference &&R, FieldId F) { switch (F) { case FieldId::F_type: I->Type = std::move(R); - break; + return llvm::Error::success(); default: - llvm::errs() << "Invalid field type for info.\n"; - exit(1); + return llvm::make_error( + "Invalid type cannot contain Reference.\n", + llvm::inconvertibleErrorCode()); } } -template <> void addReference(MemberTypeInfo *I, Reference &&R, FieldId F) { +template <> +llvm::Error addReference(MemberTypeInfo *I, Reference &&R, FieldId F) { switch (F) { case FieldId::F_type: I->Type = std::move(R); - break; + return llvm::Error::success(); default: - llvm::errs() << "Invalid field type for info.\n"; - exit(1); + return llvm::make_error( + "Invalid type cannot contain Reference.\n", + llvm::inconvertibleErrorCode()); } } -template <> void addReference(EnumInfo *I, Reference &&R, FieldId F) { +template <> llvm::Error addReference(EnumInfo *I, Reference &&R, FieldId F) { switch (F) { case FieldId::F_namespace: I->Namespace.emplace_back(std::move(R)); - break; + return llvm::Error::success(); default: - llvm::errs() << "Invalid field type for info.\n"; - exit(1); + return llvm::make_error( + "Invalid type cannot contain Reference.\n", + llvm::inconvertibleErrorCode()); } } -template <> void addReference(NamespaceInfo *I, Reference &&R, FieldId F) { +template <> +llvm::Error addReference(NamespaceInfo *I, Reference &&R, FieldId F) { switch (F) { case FieldId::F_namespace: I->Namespace.emplace_back(std::move(R)); - break; + return llvm::Error::success(); case FieldId::F_child_namespace: I->ChildNamespaces.emplace_back(std::move(R)); - break; + return llvm::Error::success(); case FieldId::F_child_record: I->ChildRecords.emplace_back(std::move(R)); - break; + return llvm::Error::success(); default: - llvm::errs() << "Invalid field type for info.\n"; - exit(1); + return llvm::make_error( + "Invalid type cannot contain Reference.\n", + llvm::inconvertibleErrorCode()); } } -template <> void addReference(FunctionInfo *I, Reference &&R, FieldId F) { +template <> +llvm::Error addReference(FunctionInfo *I, Reference &&R, FieldId F) { switch (F) { case FieldId::F_namespace: I->Namespace.emplace_back(std::move(R)); - break; + return llvm::Error::success(); case FieldId::F_parent: I->Parent = std::move(R); - break; + return llvm::Error::success(); default: - llvm::errs() << "Invalid field type for info.\n"; - exit(1); + return llvm::make_error( + "Invalid type cannot contain Reference.\n", + llvm::inconvertibleErrorCode()); } } -template <> void addReference(RecordInfo *I, Reference &&R, FieldId F) { +template <> llvm::Error addReference(RecordInfo *I, Reference &&R, FieldId F) { switch (F) { case FieldId::F_namespace: I->Namespace.emplace_back(std::move(R)); - break; + return llvm::Error::success(); case FieldId::F_parent: I->Parents.emplace_back(std::move(R)); - break; + return llvm::Error::success(); case FieldId::F_vparent: I->VirtualParents.emplace_back(std::move(R)); - break; + return llvm::Error::success(); case FieldId::F_child_record: I->ChildRecords.emplace_back(std::move(R)); - break; + return llvm::Error::success(); default: - llvm::errs() << "Invalid field type for info.\n"; - exit(1); + return llvm::make_error( + "Invalid type cannot contain Reference.\n", + llvm::inconvertibleErrorCode()); } } @@ -443,14 +486,16 @@ } // Read records from bitcode into a given info. -template bool ClangDocBitcodeReader::readRecord(unsigned ID, T I) { +template +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); } -template <> bool ClangDocBitcodeReader::readRecord(unsigned ID, Reference *I) { +template <> +llvm::Error ClangDocBitcodeReader::readRecord(unsigned ID, Reference *I) { Record R; llvm::StringRef Blob; unsigned RecID = Stream.readRecord(ID, R, &Blob); @@ -458,9 +503,11 @@ } // Read a block of records into a single info. -template bool ClangDocBitcodeReader::readBlock(unsigned ID, T I) { +template +llvm::Error ClangDocBitcodeReader::readBlock(unsigned ID, T I) { if (Stream.EnterSubBlock(ID)) - return false; + return llvm::make_error("Unable to enter subblock.\n", + llvm::inconvertibleErrorCode()); while (true) { unsigned BlockOrCode = 0; @@ -468,83 +515,87 @@ switch (Res) { case Cursor::BadBlock: - return false; + return llvm::make_error( + "Bad block found.\n", llvm::inconvertibleErrorCode()); case Cursor::BlockEnd: - return true; + return llvm::Error::success(); case Cursor::BlockBegin: - if (readSubBlock(BlockOrCode, I)) - continue; - if (!Stream.SkipBlock()) - return false; + if (auto Err = readSubBlock(BlockOrCode, I)) { + if (!Stream.SkipBlock()) + continue; + return Err; + } continue; case Cursor::Record: break; } - if (!readRecord(BlockOrCode, I)) - return false; + if (auto Err = readRecord(BlockOrCode, I)) + return Err; } } template -bool ClangDocBitcodeReader::readSubBlock(unsigned ID, T I) { +llvm::Error ClangDocBitcodeReader::readSubBlock(unsigned ID, T I) { switch (ID) { // Blocks can only have Comment, Reference, TypeInfo, FunctionInfo, or // EnumInfo subblocks - case BI_COMMENT_BLOCK_ID: - if (readBlock(ID, getCommentInfo(I))) - return true; - return false; + case BI_COMMENT_BLOCK_ID: { + auto Comment = getCommentInfo(I); + if (!Comment) + return Comment.takeError(); + if (auto Err = readBlock(ID, Comment.get())) + return Err; + return llvm::Error::success(); + } case BI_TYPE_BLOCK_ID: { TypeInfo TI; - if (readBlock(ID, &TI)) { - addTypeInfo(I, std::move(TI)); - return true; - } - return false; + if (auto Err = readBlock(ID, &TI)) + return Err; + if (auto Err = addTypeInfo(I, std::move(TI))) + return Err; + return llvm::Error::success(); } case BI_FIELD_TYPE_BLOCK_ID: { FieldTypeInfo TI; - if (readBlock(ID, &TI)) { - addTypeInfo(I, std::move(TI)); - return true; - } - return false; + if (auto Err = readBlock(ID, &TI)) + return Err; + if (auto Err = addTypeInfo(I, std::move(TI))) + return Err; + return llvm::Error::success(); } case BI_MEMBER_TYPE_BLOCK_ID: { MemberTypeInfo TI; - if (readBlock(ID, &TI)) { - addTypeInfo(I, std::move(TI)); - return true; - } - return false; + if (auto Err = readBlock(ID, &TI)) + return Err; + if (auto Err = addTypeInfo(I, std::move(TI))) + return Err; + return llvm::Error::success(); } case BI_REFERENCE_BLOCK_ID: { Reference R; - if (readBlock(ID, &R)) { - addReference(I, std::move(R), CurrentReferenceField); - return true; - } - return false; + if (auto Err = readBlock(ID, &R)) + return Err; + if (auto Err = addReference(I, std::move(R), CurrentReferenceField)) + return Err; + return llvm::Error::success(); } case BI_FUNCTION_BLOCK_ID: { FunctionInfo F; - if (readBlock(ID, &F)) { - addChild(I, std::move(F)); - return true; - } - return false; + if (auto Err = readBlock(ID, &F)) + return Err; + addChild(I, std::move(F)); + return llvm::Error::success(); } case BI_ENUM_BLOCK_ID: { EnumInfo E; - if (readBlock(ID, &E)) { - addChild(I, std::move(E)); - return true; - } - return false; + if (auto Err = readBlock(ID, &E)) + return Err; + addChild(I, std::move(E)); + return llvm::Error::success(); } default: - llvm::errs() << "Invalid subblock type.\n"; - return false; + return llvm::make_error("Invalid subblock type.\n", + llvm::inconvertibleErrorCode()); } } @@ -576,37 +627,41 @@ llvm_unreachable("Premature stream end."); } -bool ClangDocBitcodeReader::validateStream() { +llvm::Error ClangDocBitcodeReader::validateStream() { if (Stream.AtEndOfStream()) - return false; + return llvm::make_error("Premature end of stream.\n", + 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 false; - return true; + return llvm::make_error("Invalid bitcode signature.\n", + llvm::inconvertibleErrorCode()); + return llvm::Error::success(); } -bool ClangDocBitcodeReader::readBlockInfoBlock() { +llvm::Error ClangDocBitcodeReader::readBlockInfoBlock() { BlockInfo = Stream.ReadBlockInfoBlock(); if (!BlockInfo) - return false; + return llvm::make_error( + "Unable to parse BlockInfoBlock.\n", llvm::inconvertibleErrorCode()); Stream.setBlockInfo(&*BlockInfo); - return true; + return llvm::Error::success(); } template -std::unique_ptr ClangDocBitcodeReader::createInfo(unsigned ID) { +llvm::Expected> +ClangDocBitcodeReader::createInfo(unsigned ID) { std::unique_ptr I = llvm::make_unique(); - if (readBlock(ID, static_cast(I.get()))) - return I; - llvm::errs() << "Error reading from block.\n"; - return nullptr; + if (auto Err = readBlock(ID, static_cast(I.get()))) + return std::move(Err); + return I; } -std::unique_ptr ClangDocBitcodeReader::readBlockToInfo(unsigned ID) { +llvm::Expected> +ClangDocBitcodeReader::readBlockToInfo(unsigned ID) { switch (ID) { case BI_NAMESPACE_BLOCK_ID: return createInfo(ID); @@ -617,8 +672,8 @@ case BI_FUNCTION_BLOCK_ID: return createInfo(ID); default: - llvm::errs() << "Error reading from block.\n"; - return nullptr; + return llvm::make_error("Cannot create info.\n", + llvm::inconvertibleErrorCode()); } } @@ -626,19 +681,15 @@ llvm::Expected>> ClangDocBitcodeReader::readBitcode() { std::vector> Infos; - if (!validateStream()) - return llvm::make_error("Invalid bitcode stream.\n", - llvm::inconvertibleErrorCode()); - ; + if (auto Err = validateStream()) + return std::move(Err); // Read the top level blocks. while (!Stream.AtEndOfStream()) { unsigned Code = Stream.ReadCode(); if (Code != llvm::bitc::ENTER_SUBBLOCK) return llvm::make_error( - "Missing subblock in bitcode.\n", llvm::inconvertibleErrorCode()); - ; - + "No blocks in input.\n", llvm::inconvertibleErrorCode()); unsigned ID = Stream.ReadSubBlockID(); switch (ID) { // NamedType and Comment blocks should not appear at the top level @@ -648,29 +699,25 @@ case BI_COMMENT_BLOCK_ID: case BI_REFERENCE_BLOCK_ID: return llvm::make_error( - "Invalid top level block in bitcode.\n", - llvm::inconvertibleErrorCode()); - ; + "Invalid top level block.\n", llvm::inconvertibleErrorCode()); case BI_NAMESPACE_BLOCK_ID: case BI_RECORD_BLOCK_ID: case BI_ENUM_BLOCK_ID: - case BI_FUNCTION_BLOCK_ID: - if (std::unique_ptr I = readBlockToInfo(ID)) - Infos.emplace_back(std::move(I)); + case BI_FUNCTION_BLOCK_ID: { + auto InfoOrErr = readBlockToInfo(ID); + if (!InfoOrErr) + return InfoOrErr.takeError(); + Infos.emplace_back(std::move(InfoOrErr.get())); continue; + } case BI_VERSION_BLOCK_ID: - if (readBlock(ID, VersionNumber)) - continue; - return llvm::make_error( - "Invalid bitcode version in bitcode.\n", - llvm::inconvertibleErrorCode()); - ; + if (auto Err = readBlock(ID, VersionNumber)) + return std::move(Err); + continue; case llvm::bitc::BLOCKINFO_BLOCK_ID: - if (readBlockInfoBlock()) - continue; - return llvm::make_error( - "Invalid BlockInfo in bitcode.\n", llvm::inconvertibleErrorCode()); - ; + if (auto Err = readBlockInfoBlock()) + return std::move(Err); + continue; default: if (!Stream.SkipBlock()) continue;