[clang-doc] Updating BitcodeReader to use llvm::Error
authorJulie Hockett <juliehockett@google.com>
Mon, 13 Aug 2018 21:39:03 +0000 (21:39 +0000)
committerJulie Hockett <juliehockett@google.com>
Mon, 13 Aug 2018 21:39:03 +0000 (21:39 +0000)
llvm-svn: 339617

clang-tools-extra/clang-doc/BitcodeReader.cpp
clang-tools-extra/clang-doc/BitcodeReader.h

index 7acf107..dee0930 100644 (file)
@@ -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 @@ namespace doc {
 
 using Record = llvm::SmallVector<uint64_t, 1024>;
 
-bool decodeRecord(Record R, llvm::SmallVectorImpl<char> &Field,
-                  llvm::StringRef Blob) {
+llvm::Error decodeRecord(Record R, llvm::SmallVectorImpl<char> &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<llvm::StringError>("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<llvm::StringError>("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<llvm::StringError>(
+        "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 @@ bool decodeRecord(Record R, TagTypeKind &Field, llvm::StringRef Blob) {
   case TTK_Class:
   case TTK_Enum:
     Field = (TagTypeKind)R[0];
-    return true;
+    return llvm::Error::success();
   default:
-    return false;
+    return llvm::make_error<llvm::StringError>(
+        "Invalid value for TagTypeKind.\n", llvm::inconvertibleErrorCode());
   }
 }
 
-bool decodeRecord(Record R, llvm::Optional<Location> &Field,
-                  llvm::StringRef Blob) {
+llvm::Error decodeRecord(Record R, llvm::Optional<Location> &Field,
+                         llvm::StringRef Blob) {
   if (R[0] > INT_MAX)
-    return false;
+    return llvm::make_error<llvm::StringError>("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<InfoType>(R[0])) {
   case InfoType::IT_namespace:
   case InfoType::IT_record:
@@ -89,12 +96,13 @@ bool decodeRecord(Record R, InfoType &Field, llvm::StringRef Blob) {
   case InfoType::IT_default:
   case InfoType::IT_enum:
     Field = IT;
-    return true;
+    return llvm::Error::success();
   }
-  return false;
+  return llvm::make_error<llvm::StringError>("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<FieldId>(R[0])) {
   case FieldId::F_namespace:
   case FieldId::F_parent:
@@ -104,45 +112,51 @@ bool decodeRecord(Record R, FieldId &Field, llvm::StringRef Blob) {
   case FieldId::F_child_record:
   case FieldId::F_default:
     Field = F;
-    return true;
+    return llvm::Error::success();
   }
-  return false;
+  return llvm::make_error<llvm::StringError>("Invalid value for FieldId.\n",
+                                             llvm::inconvertibleErrorCode());
 }
 
-bool decodeRecord(Record R, llvm::SmallVectorImpl<llvm::SmallString<16>> &Field,
-                  llvm::StringRef Blob) {
+llvm::Error decodeRecord(Record R,
+                         llvm::SmallVectorImpl<llvm::SmallString<16>> &Field,
+                         llvm::StringRef Blob) {
   Field.push_back(Blob);
-  return true;
+  return llvm::Error::success();
 }
 
-bool decodeRecord(Record R, llvm::SmallVectorImpl<Location> &Field,
-                  llvm::StringRef Blob) {
+llvm::Error decodeRecord(Record R, llvm::SmallVectorImpl<Location> &Field,
+                         llvm::StringRef Blob) {
   if (R[0] > INT_MAX)
-    return false;
+    return llvm::make_error<llvm::StringError>("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<llvm::StringError>(
+      "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<llvm::StringError>(
+        "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 @@ bool parseRecord(Record R, unsigned ID, llvm::StringRef Blob, RecordInfo *I) {
   case RECORD_TAG_TYPE:
     return decodeRecord(R, I->TagType, Blob);
   default:
-    return false;
+    return llvm::make_error<llvm::StringError>(
+        "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 @@ bool parseRecord(Record R, unsigned ID, llvm::StringRef Blob, EnumInfo *I) {
   case ENUM_SCOPED:
     return decodeRecord(R, I->Scoped, Blob);
   default:
-    return false;
+    return llvm::make_error<llvm::StringError>("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 @@ bool parseRecord(Record R, unsigned ID, llvm::StringRef Blob, FunctionInfo *I) {
   case FUNCTION_IS_METHOD:
     return decodeRecord(R, I->IsMethod, Blob);
   default:
-    return false;
+    return llvm::make_error<llvm::StringError>(
+        "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<llvm::StringError>("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<llvm::StringError>(
+        "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 @@ bool parseRecord(Record R, unsigned ID, llvm::StringRef Blob, CommentInfo *I) {
   case COMMENT_EXPLICIT:
     return decodeRecord(R, I->Explicit, Blob);
   default:
-    return false;
+    return llvm::make_error<llvm::StringError>(
+        "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 @@ bool parseRecord(Record R, unsigned ID, llvm::StringRef Blob, Reference *I,
   case REFERENCE_FIELD:
     return decodeRecord(R, F, Blob);
   default:
-    return false;
+    return llvm::make_error<llvm::StringError>("Invalid field for Reference.\n",
+                                               llvm::inconvertibleErrorCode());
   }
 }
 
-template <typename T> CommentInfo *getCommentInfo(T I) {
-  llvm::errs() << "Cannot have comment subblock.\n";
-  exit(1);
+template <typename T> llvm::Expected<CommentInfo *> getCommentInfo(T I) {
+  return llvm::make_error<llvm::StringError>(
+      "Invalid type cannot contain CommentInfo.\n",
+      llvm::inconvertibleErrorCode());
 }
 
-template <> CommentInfo *getCommentInfo(FunctionInfo *I) {
+template <> llvm::Expected<CommentInfo *> getCommentInfo(FunctionInfo *I) {
   I->Description.emplace_back();
   return &I->Description.back();
 }
 
-template <> CommentInfo *getCommentInfo(NamespaceInfo *I) {
+template <> llvm::Expected<CommentInfo *> getCommentInfo(NamespaceInfo *I) {
   I->Description.emplace_back();
   return &I->Description.back();
 }
 
-template <> CommentInfo *getCommentInfo(RecordInfo *I) {
+template <> llvm::Expected<CommentInfo *> getCommentInfo(RecordInfo *I) {
   I->Description.emplace_back();
   return &I->Description.back();
 }
 
-template <> CommentInfo *getCommentInfo(EnumInfo *I) {
+template <> llvm::Expected<CommentInfo *> getCommentInfo(EnumInfo *I) {
   I->Description.emplace_back();
   return &I->Description.back();
 }
 
-template <> CommentInfo *getCommentInfo(CommentInfo *I) {
+template <> llvm::Expected<CommentInfo *> getCommentInfo(CommentInfo *I) {
   I->Children.emplace_back(llvm::make_unique<CommentInfo>());
   return I->Children.back().get();
 }
 
-template <> CommentInfo *getCommentInfo(std::unique_ptr<CommentInfo> &I) {
+template <>
+llvm::Expected<CommentInfo *> getCommentInfo(std::unique_ptr<CommentInfo> &I) {
   return getCommentInfo(I.get());
 }
 
 template <typename T, typename TTypeInfo>
-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<llvm::StringError>(
+      "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 <typename T> void addReference(T I, Reference &&R, FieldId F) {
-  llvm::errs() << "Invalid field type for info.\n";
-  exit(1);
+template <typename T> llvm::Error addReference(T I, Reference &&R, FieldId F) {
+  return llvm::make_error<llvm::StringError>(
+      "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<llvm::StringError>(
+        "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<llvm::StringError>(
+        "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<llvm::StringError>(
+        "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<llvm::StringError>(
+        "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<llvm::StringError>(
+        "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<llvm::StringError>(
+        "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<llvm::StringError>(
+        "Invalid type cannot contain Reference.\n",
+        llvm::inconvertibleErrorCode());
   }
 }
 
@@ -443,14 +486,16 @@ template <> void addChild(RecordInfo *I, EnumInfo &&R) {
 }
 
 // Read records from bitcode into a given info.
-template <typename T> bool ClangDocBitcodeReader::readRecord(unsigned ID, T I) {
+template <typename T>
+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 @@ template <> bool ClangDocBitcodeReader::readRecord(unsigned ID, Reference *I) {
 }
 
 // Read a block of records into a single info.
-template <typename T> bool ClangDocBitcodeReader::readBlock(unsigned ID, T I) {
+template <typename T>
+llvm::Error ClangDocBitcodeReader::readBlock(unsigned ID, T I) {
   if (Stream.EnterSubBlock(ID))
-    return false;
+    return llvm::make_error<llvm::StringError>("Unable to enter subblock.\n",
+                                               llvm::inconvertibleErrorCode());
 
   while (true) {
     unsigned BlockOrCode = 0;
@@ -468,83 +515,87 @@ template <typename T> bool ClangDocBitcodeReader::readBlock(unsigned ID, T I) {
 
     switch (Res) {
     case Cursor::BadBlock:
-      return false;
+      return llvm::make_error<llvm::StringError>(
+          "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 <typename T>
-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<llvm::StringError>("Invalid subblock type.\n",
+                                               llvm::inconvertibleErrorCode());
   }
 }
 
@@ -576,37 +627,41 @@ ClangDocBitcodeReader::skipUntilRecordOrBlock(unsigned &BlockOrRecordID) {
   llvm_unreachable("Premature stream end.");
 }
 
-bool ClangDocBitcodeReader::validateStream() {
+llvm::Error ClangDocBitcodeReader::validateStream() {
   if (Stream.AtEndOfStream())
-    return false;
+    return llvm::make_error<llvm::StringError>("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<llvm::StringError>("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<llvm::StringError>(
+        "Unable to parse BlockInfoBlock.\n", llvm::inconvertibleErrorCode());
   Stream.setBlockInfo(&*BlockInfo);
-  return true;
+  return llvm::Error::success();
 }
 
 template <typename T>
-std::unique_ptr<Info> ClangDocBitcodeReader::createInfo(unsigned ID) {
+llvm::Expected<std::unique_ptr<Info>>
+ClangDocBitcodeReader::createInfo(unsigned ID) {
   std::unique_ptr<Info> I = llvm::make_unique<T>();
-  if (readBlock(ID, static_cast<T *>(I.get())))
-    return I;
-  llvm::errs() << "Error reading from block.\n";
-  return nullptr;
+  if (auto Err = readBlock(ID, static_cast<T *>(I.get())))
+    return std::move(Err);
+  return I;
 }
 
-std::unique_ptr<Info> ClangDocBitcodeReader::readBlockToInfo(unsigned ID) {
+llvm::Expected<std::unique_ptr<Info>>
+ClangDocBitcodeReader::readBlockToInfo(unsigned ID) {
   switch (ID) {
   case BI_NAMESPACE_BLOCK_ID:
     return createInfo<NamespaceInfo>(ID);
@@ -617,8 +672,8 @@ std::unique_ptr<Info> ClangDocBitcodeReader::readBlockToInfo(unsigned ID) {
   case BI_FUNCTION_BLOCK_ID:
     return createInfo<FunctionInfo>(ID);
   default:
-    llvm::errs() << "Error reading from block.\n";
-    return nullptr;
+    return llvm::make_error<llvm::StringError>("Cannot create info.\n",
+                                               llvm::inconvertibleErrorCode());
   }
 }
 
@@ -626,19 +681,15 @@ std::unique_ptr<Info> ClangDocBitcodeReader::readBlockToInfo(unsigned ID) {
 llvm::Expected<std::vector<std::unique_ptr<Info>>>
 ClangDocBitcodeReader::readBitcode() {
   std::vector<std::unique_ptr<Info>> Infos;
-  if (!validateStream())
-    return llvm::make_error<llvm::StringError>("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<llvm::StringError>(
-          "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 @@ ClangDocBitcodeReader::readBitcode() {
     case BI_COMMENT_BLOCK_ID:
     case BI_REFERENCE_BLOCK_ID:
       return llvm::make_error<llvm::StringError>(
-          "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<Info> 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<llvm::StringError>(
-          "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<llvm::StringError>(
-          "Invalid BlockInfo in bitcode.\n", llvm::inconvertibleErrorCode());
-      ;
+      if (auto Err = readBlockInfoBlock())
+        return std::move(Err);
+      continue;
     default:
       if (!Stream.SkipBlock())
         continue;
index aaf2525..ec3f6b0 100644 (file)
@@ -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 @@ private:
   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 <typename T> bool readBlock(unsigned ID, T I);
+  template <typename T> llvm::Error readBlock(unsigned ID, T I);
 
   // Step through a block of records to find the next data field.
-  template <typename T> bool readSubBlock(unsigned ID, T I);
+  template <typename T> 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 <typename T> bool readRecord(unsigned ID, T I);
+  template <typename T> llvm::Error readRecord(unsigned ID, T I);
 
   // Allocate the relevant type of info and add read data to the object.
-  template <typename T> std::unique_ptr<Info> createInfo(unsigned ID);
+  template <typename T>
+  llvm::Expected<std::unique_ptr<Info>> 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<Info> readBlockToInfo(unsigned ID);
+  llvm::Expected<std::unique_ptr<Info>> readBlockToInfo(unsigned ID);
 
   llvm::BitstreamCursor &Stream;
   Optional<llvm::BitstreamBlockInfo> BlockInfo;