xref: /llvm-project/clang-tools-extra/clang-doc/BitcodeReader.cpp (revision 5ef2456a438578b0783241a2744efc62d47e5ab6)
1d0f9a872SJulie Hockett //===--  BitcodeReader.cpp - ClangDoc Bitcode Reader ------------*- C++ -*-===//
2d0f9a872SJulie Hockett //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6d0f9a872SJulie Hockett //
7d0f9a872SJulie Hockett //===----------------------------------------------------------------------===//
8d0f9a872SJulie Hockett 
9d0f9a872SJulie Hockett #include "BitcodeReader.h"
10d0f9a872SJulie Hockett #include "llvm/ADT/IndexedMap.h"
1146fc9592SJulie Hockett #include "llvm/Support/Error.h"
12d0f9a872SJulie Hockett #include "llvm/Support/raw_ostream.h"
13c589730aSKrzysztof Parzyszek #include <optional>
14d0f9a872SJulie Hockett 
15d0f9a872SJulie Hockett namespace clang {
16d0f9a872SJulie Hockett namespace doc {
17d0f9a872SJulie Hockett 
18d0f9a872SJulie Hockett using Record = llvm::SmallVector<uint64_t, 1024>;
19d0f9a872SJulie Hockett 
20eaa7b324SBrett Wilson // This implements decode for SmallString.
2145617e1dSSimon Pilgrim llvm::Error decodeRecord(const Record &R, llvm::SmallVectorImpl<char> &Field,
22d0f9a872SJulie Hockett                          llvm::StringRef Blob) {
23d0f9a872SJulie Hockett   Field.assign(Blob.begin(), Blob.end());
2446fc9592SJulie Hockett   return llvm::Error::success();
25d0f9a872SJulie Hockett }
26d0f9a872SJulie Hockett 
2745617e1dSSimon Pilgrim llvm::Error decodeRecord(const Record &R, SymbolID &Field,
2845617e1dSSimon Pilgrim                          llvm::StringRef Blob) {
29d0f9a872SJulie Hockett   if (R[0] != BitCodeConstants::USRHashSize)
3018038065SFangrui Song     return llvm::createStringError(llvm::inconvertibleErrorCode(),
3118038065SFangrui Song                                    "incorrect USR size");
32d0f9a872SJulie Hockett 
33d0f9a872SJulie Hockett   // First position in the record is the length of the following array, so we
34d0f9a872SJulie Hockett   // copy the following elements to the field.
35d0f9a872SJulie Hockett   for (int I = 0, E = R[0]; I < E; ++I)
36d0f9a872SJulie Hockett     Field[I] = R[I + 1];
3746fc9592SJulie Hockett   return llvm::Error::success();
38d0f9a872SJulie Hockett }
39d0f9a872SJulie Hockett 
4045617e1dSSimon Pilgrim llvm::Error decodeRecord(const Record &R, bool &Field, llvm::StringRef Blob) {
41d0f9a872SJulie Hockett   Field = R[0] != 0;
4246fc9592SJulie Hockett   return llvm::Error::success();
43d0f9a872SJulie Hockett }
44d0f9a872SJulie Hockett 
4545617e1dSSimon Pilgrim llvm::Error decodeRecord(const Record &R, int &Field, llvm::StringRef Blob) {
46d0f9a872SJulie Hockett   if (R[0] > INT_MAX)
4718038065SFangrui Song     return llvm::createStringError(llvm::inconvertibleErrorCode(),
4818038065SFangrui Song                                    "integer too large to parse");
49d0f9a872SJulie Hockett   Field = (int)R[0];
5046fc9592SJulie Hockett   return llvm::Error::success();
51d0f9a872SJulie Hockett }
52d0f9a872SJulie Hockett 
5345617e1dSSimon Pilgrim llvm::Error decodeRecord(const Record &R, AccessSpecifier &Field,
5446fc9592SJulie Hockett                          llvm::StringRef Blob) {
55d0f9a872SJulie Hockett   switch (R[0]) {
56d0f9a872SJulie Hockett   case AS_public:
57d0f9a872SJulie Hockett   case AS_private:
58d0f9a872SJulie Hockett   case AS_protected:
59d0f9a872SJulie Hockett   case AS_none:
60d0f9a872SJulie Hockett     Field = (AccessSpecifier)R[0];
6146fc9592SJulie Hockett     return llvm::Error::success();
62d0f9a872SJulie Hockett   default:
6318038065SFangrui Song     return llvm::createStringError(llvm::inconvertibleErrorCode(),
6418038065SFangrui Song                                    "invalid value for AccessSpecifier");
65d0f9a872SJulie Hockett   }
66d0f9a872SJulie Hockett }
67d0f9a872SJulie Hockett 
6845617e1dSSimon Pilgrim llvm::Error decodeRecord(const Record &R, TagTypeKind &Field,
6945617e1dSSimon Pilgrim                          llvm::StringRef Blob) {
70edd690b0SVlad Serebrennikov   switch (static_cast<TagTypeKind>(R[0])) {
71edd690b0SVlad Serebrennikov   case TagTypeKind::Struct:
72edd690b0SVlad Serebrennikov   case TagTypeKind::Interface:
73edd690b0SVlad Serebrennikov   case TagTypeKind::Union:
74edd690b0SVlad Serebrennikov   case TagTypeKind::Class:
75edd690b0SVlad Serebrennikov   case TagTypeKind::Enum:
76edd690b0SVlad Serebrennikov     Field = static_cast<TagTypeKind>(R[0]);
7746fc9592SJulie Hockett     return llvm::Error::success();
782b76bdc3SKazu Hirata   }
7918038065SFangrui Song   return llvm::createStringError(llvm::inconvertibleErrorCode(),
8018038065SFangrui Song                                  "invalid value for TagTypeKind");
81d0f9a872SJulie Hockett }
82d0f9a872SJulie Hockett 
83c589730aSKrzysztof Parzyszek llvm::Error decodeRecord(const Record &R, std::optional<Location> &Field,
84d0f9a872SJulie Hockett                          llvm::StringRef Blob) {
85d0f9a872SJulie Hockett   if (R[0] > INT_MAX)
8618038065SFangrui Song     return llvm::createStringError(llvm::inconvertibleErrorCode(),
8718038065SFangrui Song                                    "integer too large to parse");
88665e9676SDiego Astiazaran   Field.emplace((int)R[0], Blob, (bool)R[1]);
8946fc9592SJulie Hockett   return llvm::Error::success();
90d0f9a872SJulie Hockett }
91d0f9a872SJulie Hockett 
9245617e1dSSimon Pilgrim llvm::Error decodeRecord(const Record &R, InfoType &Field,
9345617e1dSSimon Pilgrim                          llvm::StringRef Blob) {
94d0f9a872SJulie Hockett   switch (auto IT = static_cast<InfoType>(R[0])) {
95d0f9a872SJulie Hockett   case InfoType::IT_namespace:
96d0f9a872SJulie Hockett   case InfoType::IT_record:
97d0f9a872SJulie Hockett   case InfoType::IT_function:
98d0f9a872SJulie Hockett   case InfoType::IT_default:
99d0f9a872SJulie Hockett   case InfoType::IT_enum:
10021fb70c6SBrett Wilson   case InfoType::IT_typedef:
101d0f9a872SJulie Hockett     Field = IT;
10246fc9592SJulie Hockett     return llvm::Error::success();
103d0f9a872SJulie Hockett   }
10418038065SFangrui Song   return llvm::createStringError(llvm::inconvertibleErrorCode(),
10518038065SFangrui Song                                  "invalid value for InfoType");
106d0f9a872SJulie Hockett }
107d0f9a872SJulie Hockett 
10845617e1dSSimon Pilgrim llvm::Error decodeRecord(const Record &R, FieldId &Field,
10945617e1dSSimon Pilgrim                          llvm::StringRef Blob) {
110d0f9a872SJulie Hockett   switch (auto F = static_cast<FieldId>(R[0])) {
111d0f9a872SJulie Hockett   case FieldId::F_namespace:
112d0f9a872SJulie Hockett   case FieldId::F_parent:
113d0f9a872SJulie Hockett   case FieldId::F_vparent:
114d0f9a872SJulie Hockett   case FieldId::F_type:
1158899c29bSJulie Hockett   case FieldId::F_child_namespace:
1168899c29bSJulie Hockett   case FieldId::F_child_record:
117d0f9a872SJulie Hockett   case FieldId::F_default:
118d0f9a872SJulie Hockett     Field = F;
11946fc9592SJulie Hockett     return llvm::Error::success();
120d0f9a872SJulie Hockett   }
12118038065SFangrui Song   return llvm::createStringError(llvm::inconvertibleErrorCode(),
12218038065SFangrui Song                                  "invalid value for FieldId");
123d0f9a872SJulie Hockett }
124d0f9a872SJulie Hockett 
12545617e1dSSimon Pilgrim llvm::Error decodeRecord(const Record &R,
12646fc9592SJulie Hockett                          llvm::SmallVectorImpl<llvm::SmallString<16>> &Field,
127d0f9a872SJulie Hockett                          llvm::StringRef Blob) {
128d0f9a872SJulie Hockett   Field.push_back(Blob);
12946fc9592SJulie Hockett   return llvm::Error::success();
130d0f9a872SJulie Hockett }
131d0f9a872SJulie Hockett 
13245617e1dSSimon Pilgrim llvm::Error decodeRecord(const Record &R,
13345617e1dSSimon Pilgrim                          llvm::SmallVectorImpl<Location> &Field,
134d0f9a872SJulie Hockett                          llvm::StringRef Blob) {
135d0f9a872SJulie Hockett   if (R[0] > INT_MAX)
13618038065SFangrui Song     return llvm::createStringError(llvm::inconvertibleErrorCode(),
13718038065SFangrui Song                                    "integer too large to parse");
138665e9676SDiego Astiazaran   Field.emplace_back((int)R[0], Blob, (bool)R[1]);
13946fc9592SJulie Hockett   return llvm::Error::success();
140d0f9a872SJulie Hockett }
141d0f9a872SJulie Hockett 
14245617e1dSSimon Pilgrim llvm::Error parseRecord(const Record &R, unsigned ID, llvm::StringRef Blob,
143d0f9a872SJulie Hockett                         const unsigned VersionNo) {
144d0f9a872SJulie Hockett   if (ID == VERSION && R[0] == VersionNo)
14546fc9592SJulie Hockett     return llvm::Error::success();
14618038065SFangrui Song   return llvm::createStringError(llvm::inconvertibleErrorCode(),
14718038065SFangrui Song                                  "mismatched bitcode version number");
148d0f9a872SJulie Hockett }
149d0f9a872SJulie Hockett 
15045617e1dSSimon Pilgrim llvm::Error parseRecord(const Record &R, unsigned ID, llvm::StringRef Blob,
151d0f9a872SJulie Hockett                         NamespaceInfo *I) {
152d0f9a872SJulie Hockett   switch (ID) {
153d0f9a872SJulie Hockett   case NAMESPACE_USR:
154d0f9a872SJulie Hockett     return decodeRecord(R, I->USR, Blob);
155d0f9a872SJulie Hockett   case NAMESPACE_NAME:
156d0f9a872SJulie Hockett     return decodeRecord(R, I->Name, Blob);
1572c1c9a24SJulie Hockett   case NAMESPACE_PATH:
1582c1c9a24SJulie Hockett     return decodeRecord(R, I->Path, Blob);
159d0f9a872SJulie Hockett   default:
16018038065SFangrui Song     return llvm::createStringError(llvm::inconvertibleErrorCode(),
16118038065SFangrui Song                                    "invalid field for NamespaceInfo");
162d0f9a872SJulie Hockett   }
163d0f9a872SJulie Hockett }
164d0f9a872SJulie Hockett 
16545617e1dSSimon Pilgrim llvm::Error parseRecord(const Record &R, unsigned ID, llvm::StringRef Blob,
16646fc9592SJulie Hockett                         RecordInfo *I) {
167d0f9a872SJulie Hockett   switch (ID) {
168d0f9a872SJulie Hockett   case RECORD_USR:
169d0f9a872SJulie Hockett     return decodeRecord(R, I->USR, Blob);
170d0f9a872SJulie Hockett   case RECORD_NAME:
171d0f9a872SJulie Hockett     return decodeRecord(R, I->Name, Blob);
1722c1c9a24SJulie Hockett   case RECORD_PATH:
1732c1c9a24SJulie Hockett     return decodeRecord(R, I->Path, Blob);
174d0f9a872SJulie Hockett   case RECORD_DEFLOCATION:
175d0f9a872SJulie Hockett     return decodeRecord(R, I->DefLoc, Blob);
176d0f9a872SJulie Hockett   case RECORD_LOCATION:
177d0f9a872SJulie Hockett     return decodeRecord(R, I->Loc, Blob);
178d0f9a872SJulie Hockett   case RECORD_TAG_TYPE:
179d0f9a872SJulie Hockett     return decodeRecord(R, I->TagType, Blob);
180b1f01e27SJulie Hockett   case RECORD_IS_TYPE_DEF:
181b1f01e27SJulie Hockett     return decodeRecord(R, I->IsTypeDef, Blob);
182d0f9a872SJulie Hockett   default:
18318038065SFangrui Song     return llvm::createStringError(llvm::inconvertibleErrorCode(),
18418038065SFangrui Song                                    "invalid field for RecordInfo");
185d0f9a872SJulie Hockett   }
186d0f9a872SJulie Hockett }
187d0f9a872SJulie Hockett 
18845617e1dSSimon Pilgrim llvm::Error parseRecord(const Record &R, unsigned ID, llvm::StringRef Blob,
189ba3d595fSDiego Astiazaran                         BaseRecordInfo *I) {
190ba3d595fSDiego Astiazaran   switch (ID) {
191ba3d595fSDiego Astiazaran   case BASE_RECORD_USR:
192ba3d595fSDiego Astiazaran     return decodeRecord(R, I->USR, Blob);
193ba3d595fSDiego Astiazaran   case BASE_RECORD_NAME:
194ba3d595fSDiego Astiazaran     return decodeRecord(R, I->Name, Blob);
195ba3d595fSDiego Astiazaran   case BASE_RECORD_PATH:
196ba3d595fSDiego Astiazaran     return decodeRecord(R, I->Path, Blob);
197ba3d595fSDiego Astiazaran   case BASE_RECORD_TAG_TYPE:
198ba3d595fSDiego Astiazaran     return decodeRecord(R, I->TagType, Blob);
199ba3d595fSDiego Astiazaran   case BASE_RECORD_IS_VIRTUAL:
200ba3d595fSDiego Astiazaran     return decodeRecord(R, I->IsVirtual, Blob);
201ba3d595fSDiego Astiazaran   case BASE_RECORD_ACCESS:
202ba3d595fSDiego Astiazaran     return decodeRecord(R, I->Access, Blob);
203ba3d595fSDiego Astiazaran   case BASE_RECORD_IS_PARENT:
204ba3d595fSDiego Astiazaran     return decodeRecord(R, I->IsParent, Blob);
205ba3d595fSDiego Astiazaran   default:
20618038065SFangrui Song     return llvm::createStringError(llvm::inconvertibleErrorCode(),
20718038065SFangrui Song                                    "invalid field for BaseRecordInfo");
208ba3d595fSDiego Astiazaran   }
209ba3d595fSDiego Astiazaran }
210ba3d595fSDiego Astiazaran 
21145617e1dSSimon Pilgrim llvm::Error parseRecord(const Record &R, unsigned ID, llvm::StringRef Blob,
21246fc9592SJulie Hockett                         EnumInfo *I) {
213d0f9a872SJulie Hockett   switch (ID) {
214d0f9a872SJulie Hockett   case ENUM_USR:
215d0f9a872SJulie Hockett     return decodeRecord(R, I->USR, Blob);
216d0f9a872SJulie Hockett   case ENUM_NAME:
217d0f9a872SJulie Hockett     return decodeRecord(R, I->Name, Blob);
218d0f9a872SJulie Hockett   case ENUM_DEFLOCATION:
219d0f9a872SJulie Hockett     return decodeRecord(R, I->DefLoc, Blob);
220d0f9a872SJulie Hockett   case ENUM_LOCATION:
221d0f9a872SJulie Hockett     return decodeRecord(R, I->Loc, Blob);
222d0f9a872SJulie Hockett   case ENUM_SCOPED:
223d0f9a872SJulie Hockett     return decodeRecord(R, I->Scoped, Blob);
224d0f9a872SJulie Hockett   default:
22518038065SFangrui Song     return llvm::createStringError(llvm::inconvertibleErrorCode(),
22618038065SFangrui Song                                    "invalid field for EnumInfo");
227d0f9a872SJulie Hockett   }
228d0f9a872SJulie Hockett }
229d0f9a872SJulie Hockett 
23045617e1dSSimon Pilgrim llvm::Error parseRecord(const Record &R, unsigned ID, llvm::StringRef Blob,
23121fb70c6SBrett Wilson                         TypedefInfo *I) {
23221fb70c6SBrett Wilson   switch (ID) {
23321fb70c6SBrett Wilson   case TYPEDEF_USR:
23421fb70c6SBrett Wilson     return decodeRecord(R, I->USR, Blob);
23521fb70c6SBrett Wilson   case TYPEDEF_NAME:
23621fb70c6SBrett Wilson     return decodeRecord(R, I->Name, Blob);
23721fb70c6SBrett Wilson   case TYPEDEF_DEFLOCATION:
23821fb70c6SBrett Wilson     return decodeRecord(R, I->DefLoc, Blob);
23921fb70c6SBrett Wilson   case TYPEDEF_IS_USING:
24021fb70c6SBrett Wilson     return decodeRecord(R, I->IsUsing, Blob);
24121fb70c6SBrett Wilson   default:
24221fb70c6SBrett Wilson     return llvm::createStringError(llvm::inconvertibleErrorCode(),
24321fb70c6SBrett Wilson                                    "invalid field for TypedefInfo");
24421fb70c6SBrett Wilson   }
24521fb70c6SBrett Wilson }
24621fb70c6SBrett Wilson 
24721fb70c6SBrett Wilson llvm::Error parseRecord(const Record &R, unsigned ID, llvm::StringRef Blob,
248eaa7b324SBrett Wilson                         EnumValueInfo *I) {
249eaa7b324SBrett Wilson   switch (ID) {
250eaa7b324SBrett Wilson   case ENUM_VALUE_NAME:
251eaa7b324SBrett Wilson     return decodeRecord(R, I->Name, Blob);
252eaa7b324SBrett Wilson   case ENUM_VALUE_VALUE:
253eaa7b324SBrett Wilson     return decodeRecord(R, I->Value, Blob);
254eaa7b324SBrett Wilson   case ENUM_VALUE_EXPR:
255eaa7b324SBrett Wilson     return decodeRecord(R, I->ValueExpr, Blob);
256eaa7b324SBrett Wilson   default:
257eaa7b324SBrett Wilson     return llvm::createStringError(llvm::inconvertibleErrorCode(),
258eaa7b324SBrett Wilson                                    "invalid field for EnumValueInfo");
259eaa7b324SBrett Wilson   }
260eaa7b324SBrett Wilson }
261eaa7b324SBrett Wilson 
262eaa7b324SBrett Wilson llvm::Error parseRecord(const Record &R, unsigned ID, llvm::StringRef Blob,
26346fc9592SJulie Hockett                         FunctionInfo *I) {
264d0f9a872SJulie Hockett   switch (ID) {
265d0f9a872SJulie Hockett   case FUNCTION_USR:
266d0f9a872SJulie Hockett     return decodeRecord(R, I->USR, Blob);
267d0f9a872SJulie Hockett   case FUNCTION_NAME:
268d0f9a872SJulie Hockett     return decodeRecord(R, I->Name, Blob);
269d0f9a872SJulie Hockett   case FUNCTION_DEFLOCATION:
270d0f9a872SJulie Hockett     return decodeRecord(R, I->DefLoc, Blob);
271d0f9a872SJulie Hockett   case FUNCTION_LOCATION:
272d0f9a872SJulie Hockett     return decodeRecord(R, I->Loc, Blob);
273d0f9a872SJulie Hockett   case FUNCTION_ACCESS:
274d0f9a872SJulie Hockett     return decodeRecord(R, I->Access, Blob);
275d0f9a872SJulie Hockett   case FUNCTION_IS_METHOD:
276d0f9a872SJulie Hockett     return decodeRecord(R, I->IsMethod, Blob);
277d0f9a872SJulie Hockett   default:
27818038065SFangrui Song     return llvm::createStringError(llvm::inconvertibleErrorCode(),
27918038065SFangrui Song                                    "invalid field for FunctionInfo");
280d0f9a872SJulie Hockett   }
281d0f9a872SJulie Hockett }
282d0f9a872SJulie Hockett 
28345617e1dSSimon Pilgrim llvm::Error parseRecord(const Record &R, unsigned ID, llvm::StringRef Blob,
28446fc9592SJulie Hockett                         TypeInfo *I) {
28546fc9592SJulie Hockett   return llvm::Error::success();
286d0f9a872SJulie Hockett }
287d0f9a872SJulie Hockett 
28845617e1dSSimon Pilgrim llvm::Error parseRecord(const Record &R, unsigned ID, llvm::StringRef Blob,
289d0f9a872SJulie Hockett                         FieldTypeInfo *I) {
290d0f9a872SJulie Hockett   switch (ID) {
291d0f9a872SJulie Hockett   case FIELD_TYPE_NAME:
292d0f9a872SJulie Hockett     return decodeRecord(R, I->Name, Blob);
293e191086bSBrett Wilson   case FIELD_DEFAULT_VALUE:
294e191086bSBrett Wilson     return decodeRecord(R, I->DefaultValue, Blob);
295d0f9a872SJulie Hockett   default:
29618038065SFangrui Song     return llvm::createStringError(llvm::inconvertibleErrorCode(),
29718038065SFangrui Song                                    "invalid field for TypeInfo");
298d0f9a872SJulie Hockett   }
299d0f9a872SJulie Hockett }
300d0f9a872SJulie Hockett 
30145617e1dSSimon Pilgrim llvm::Error parseRecord(const Record &R, unsigned ID, llvm::StringRef Blob,
302d0f9a872SJulie Hockett                         MemberTypeInfo *I) {
303d0f9a872SJulie Hockett   switch (ID) {
304d0f9a872SJulie Hockett   case MEMBER_TYPE_NAME:
305d0f9a872SJulie Hockett     return decodeRecord(R, I->Name, Blob);
306d0f9a872SJulie Hockett   case MEMBER_TYPE_ACCESS:
307d0f9a872SJulie Hockett     return decodeRecord(R, I->Access, Blob);
308d0f9a872SJulie Hockett   default:
30918038065SFangrui Song     return llvm::createStringError(llvm::inconvertibleErrorCode(),
31018038065SFangrui Song                                    "invalid field for MemberTypeInfo");
311d0f9a872SJulie Hockett   }
312d0f9a872SJulie Hockett }
313d0f9a872SJulie Hockett 
31445617e1dSSimon Pilgrim llvm::Error parseRecord(const Record &R, unsigned ID, llvm::StringRef Blob,
31546fc9592SJulie Hockett                         CommentInfo *I) {
316d0f9a872SJulie Hockett   switch (ID) {
317d0f9a872SJulie Hockett   case COMMENT_KIND:
318d0f9a872SJulie Hockett     return decodeRecord(R, I->Kind, Blob);
319d0f9a872SJulie Hockett   case COMMENT_TEXT:
320d0f9a872SJulie Hockett     return decodeRecord(R, I->Text, Blob);
321d0f9a872SJulie Hockett   case COMMENT_NAME:
322d0f9a872SJulie Hockett     return decodeRecord(R, I->Name, Blob);
323d0f9a872SJulie Hockett   case COMMENT_DIRECTION:
324d0f9a872SJulie Hockett     return decodeRecord(R, I->Direction, Blob);
325d0f9a872SJulie Hockett   case COMMENT_PARAMNAME:
326d0f9a872SJulie Hockett     return decodeRecord(R, I->ParamName, Blob);
327d0f9a872SJulie Hockett   case COMMENT_CLOSENAME:
328d0f9a872SJulie Hockett     return decodeRecord(R, I->CloseName, Blob);
329d0f9a872SJulie Hockett   case COMMENT_ATTRKEY:
330d0f9a872SJulie Hockett     return decodeRecord(R, I->AttrKeys, Blob);
331d0f9a872SJulie Hockett   case COMMENT_ATTRVAL:
332d0f9a872SJulie Hockett     return decodeRecord(R, I->AttrValues, Blob);
333d0f9a872SJulie Hockett   case COMMENT_ARG:
334d0f9a872SJulie Hockett     return decodeRecord(R, I->Args, Blob);
335d0f9a872SJulie Hockett   case COMMENT_SELFCLOSING:
336d0f9a872SJulie Hockett     return decodeRecord(R, I->SelfClosing, Blob);
337d0f9a872SJulie Hockett   case COMMENT_EXPLICIT:
338d0f9a872SJulie Hockett     return decodeRecord(R, I->Explicit, Blob);
339d0f9a872SJulie Hockett   default:
34018038065SFangrui Song     return llvm::createStringError(llvm::inconvertibleErrorCode(),
34118038065SFangrui Song                                    "invalid field for CommentInfo");
342d0f9a872SJulie Hockett   }
343d0f9a872SJulie Hockett }
344d0f9a872SJulie Hockett 
34545617e1dSSimon Pilgrim llvm::Error parseRecord(const Record &R, unsigned ID, llvm::StringRef Blob,
34646fc9592SJulie Hockett                         Reference *I, FieldId &F) {
347d0f9a872SJulie Hockett   switch (ID) {
348d0f9a872SJulie Hockett   case REFERENCE_USR:
349d0f9a872SJulie Hockett     return decodeRecord(R, I->USR, Blob);
350d0f9a872SJulie Hockett   case REFERENCE_NAME:
351d0f9a872SJulie Hockett     return decodeRecord(R, I->Name, Blob);
3524a68babdSBrett Wilson   case REFERENCE_QUAL_NAME:
3534a68babdSBrett Wilson     return decodeRecord(R, I->QualName, Blob);
354d0f9a872SJulie Hockett   case REFERENCE_TYPE:
355d0f9a872SJulie Hockett     return decodeRecord(R, I->RefType, Blob);
3562c1c9a24SJulie Hockett   case REFERENCE_PATH:
3572c1c9a24SJulie Hockett     return decodeRecord(R, I->Path, Blob);
358d0f9a872SJulie Hockett   case REFERENCE_FIELD:
359d0f9a872SJulie Hockett     return decodeRecord(R, F, Blob);
360d0f9a872SJulie Hockett   default:
36118038065SFangrui Song     return llvm::createStringError(llvm::inconvertibleErrorCode(),
36218038065SFangrui Song                                    "invalid field for Reference");
363d0f9a872SJulie Hockett   }
364d0f9a872SJulie Hockett }
365d0f9a872SJulie Hockett 
3664a68babdSBrett Wilson llvm::Error parseRecord(const Record &R, unsigned ID, llvm::StringRef Blob,
3674a68babdSBrett Wilson                         TemplateInfo *I) {
3684a68babdSBrett Wilson   // Currently there are no child records of TemplateInfo (only child blocks).
3694a68babdSBrett Wilson   return llvm::createStringError(llvm::inconvertibleErrorCode(),
3704a68babdSBrett Wilson                                  "invalid field for TemplateParamInfo");
3714a68babdSBrett Wilson }
3724a68babdSBrett Wilson 
3734a68babdSBrett Wilson llvm::Error parseRecord(const Record &R, unsigned ID, llvm::StringRef Blob,
3744a68babdSBrett Wilson                         TemplateSpecializationInfo *I) {
3754a68babdSBrett Wilson   if (ID == TEMPLATE_SPECIALIZATION_OF)
3764a68babdSBrett Wilson     return decodeRecord(R, I->SpecializationOf, Blob);
3774a68babdSBrett Wilson   return llvm::createStringError(llvm::inconvertibleErrorCode(),
3784a68babdSBrett Wilson                                  "invalid field for TemplateParamInfo");
3794a68babdSBrett Wilson }
3804a68babdSBrett Wilson 
3814a68babdSBrett Wilson llvm::Error parseRecord(const Record &R, unsigned ID, llvm::StringRef Blob,
3824a68babdSBrett Wilson                         TemplateParamInfo *I) {
3834a68babdSBrett Wilson   if (ID == TEMPLATE_PARAM_CONTENTS)
3844a68babdSBrett Wilson     return decodeRecord(R, I->Contents, Blob);
3854a68babdSBrett Wilson   return llvm::createStringError(llvm::inconvertibleErrorCode(),
3864a68babdSBrett Wilson                                  "invalid field for TemplateParamInfo");
3874a68babdSBrett Wilson }
3884a68babdSBrett Wilson 
38946fc9592SJulie Hockett template <typename T> llvm::Expected<CommentInfo *> getCommentInfo(T I) {
39018038065SFangrui Song   return llvm::createStringError(llvm::inconvertibleErrorCode(),
39118038065SFangrui Song                                  "invalid type cannot contain CommentInfo");
392d0f9a872SJulie Hockett }
393d0f9a872SJulie Hockett 
39446fc9592SJulie Hockett template <> llvm::Expected<CommentInfo *> getCommentInfo(FunctionInfo *I) {
3957231c996SBrett Wilson   return &I->Description.emplace_back();
396d0f9a872SJulie Hockett }
397d0f9a872SJulie Hockett 
39846fc9592SJulie Hockett template <> llvm::Expected<CommentInfo *> getCommentInfo(NamespaceInfo *I) {
3997231c996SBrett Wilson   return &I->Description.emplace_back();
400d0f9a872SJulie Hockett }
401d0f9a872SJulie Hockett 
40246fc9592SJulie Hockett template <> llvm::Expected<CommentInfo *> getCommentInfo(RecordInfo *I) {
4037231c996SBrett Wilson   return &I->Description.emplace_back();
404d0f9a872SJulie Hockett }
405d0f9a872SJulie Hockett 
40699baa10fSBrett Wilson template <> llvm::Expected<CommentInfo *> getCommentInfo(MemberTypeInfo *I) {
4077231c996SBrett Wilson   return &I->Description.emplace_back();
40899baa10fSBrett Wilson }
40999baa10fSBrett Wilson 
41046fc9592SJulie Hockett template <> llvm::Expected<CommentInfo *> getCommentInfo(EnumInfo *I) {
4117231c996SBrett Wilson   return &I->Description.emplace_back();
4127231c996SBrett Wilson }
4137231c996SBrett Wilson 
4147231c996SBrett Wilson template <> llvm::Expected<CommentInfo *> getCommentInfo(TypedefInfo *I) {
4157231c996SBrett Wilson   return &I->Description.emplace_back();
416d0f9a872SJulie Hockett }
417d0f9a872SJulie Hockett 
418*5ef2456aSPeterChou1 template <> llvm::Expected<CommentInfo *> getCommentInfo(EnumValueInfo *I) {
419*5ef2456aSPeterChou1   return &I->Description.emplace_back();
420*5ef2456aSPeterChou1 }
421*5ef2456aSPeterChou1 
42246fc9592SJulie Hockett template <> llvm::Expected<CommentInfo *> getCommentInfo(CommentInfo *I) {
4231c705d9cSJonas Devlieghere   I->Children.emplace_back(std::make_unique<CommentInfo>());
424d0f9a872SJulie Hockett   return I->Children.back().get();
425d0f9a872SJulie Hockett }
426d0f9a872SJulie Hockett 
42746fc9592SJulie Hockett template <>
42846fc9592SJulie Hockett llvm::Expected<CommentInfo *> getCommentInfo(std::unique_ptr<CommentInfo> &I) {
429d0f9a872SJulie Hockett   return getCommentInfo(I.get());
430d0f9a872SJulie Hockett }
431d0f9a872SJulie Hockett 
432eaa7b324SBrett Wilson // When readSubBlock encounters a TypeInfo sub-block, it calls addTypeInfo on
433eaa7b324SBrett Wilson // the parent block to set it. The template specializations define what to do
434eaa7b324SBrett Wilson // for each supported parent block.
435d0f9a872SJulie Hockett template <typename T, typename TTypeInfo>
43646fc9592SJulie Hockett llvm::Error addTypeInfo(T I, TTypeInfo &&TI) {
43718038065SFangrui Song   return llvm::createStringError(llvm::inconvertibleErrorCode(),
43818038065SFangrui Song                                  "invalid type cannot contain TypeInfo");
439d0f9a872SJulie Hockett }
440d0f9a872SJulie Hockett 
44146fc9592SJulie Hockett template <> llvm::Error addTypeInfo(RecordInfo *I, MemberTypeInfo &&T) {
442d0f9a872SJulie Hockett   I->Members.emplace_back(std::move(T));
44346fc9592SJulie Hockett   return llvm::Error::success();
444d0f9a872SJulie Hockett }
445d0f9a872SJulie Hockett 
446ba3d595fSDiego Astiazaran template <> llvm::Error addTypeInfo(BaseRecordInfo *I, MemberTypeInfo &&T) {
447ba3d595fSDiego Astiazaran   I->Members.emplace_back(std::move(T));
448ba3d595fSDiego Astiazaran   return llvm::Error::success();
449ba3d595fSDiego Astiazaran }
450ba3d595fSDiego Astiazaran 
45146fc9592SJulie Hockett template <> llvm::Error addTypeInfo(FunctionInfo *I, TypeInfo &&T) {
452d0f9a872SJulie Hockett   I->ReturnType = std::move(T);
45346fc9592SJulie Hockett   return llvm::Error::success();
454d0f9a872SJulie Hockett }
455d0f9a872SJulie Hockett 
45646fc9592SJulie Hockett template <> llvm::Error addTypeInfo(FunctionInfo *I, FieldTypeInfo &&T) {
457d0f9a872SJulie Hockett   I->Params.emplace_back(std::move(T));
45846fc9592SJulie Hockett   return llvm::Error::success();
459d0f9a872SJulie Hockett }
460d0f9a872SJulie Hockett 
461eaa7b324SBrett Wilson template <> llvm::Error addTypeInfo(EnumInfo *I, TypeInfo &&T) {
462eaa7b324SBrett Wilson   I->BaseType = std::move(T);
463eaa7b324SBrett Wilson   return llvm::Error::success();
464eaa7b324SBrett Wilson }
465eaa7b324SBrett Wilson 
46621fb70c6SBrett Wilson template <> llvm::Error addTypeInfo(TypedefInfo *I, TypeInfo &&T) {
46721fb70c6SBrett Wilson   I->Underlying = std::move(T);
46821fb70c6SBrett Wilson   return llvm::Error::success();
46921fb70c6SBrett Wilson }
47021fb70c6SBrett Wilson 
47146fc9592SJulie Hockett template <typename T> llvm::Error addReference(T I, Reference &&R, FieldId F) {
47218038065SFangrui Song   return llvm::createStringError(llvm::inconvertibleErrorCode(),
47318038065SFangrui Song                                  "invalid type cannot contain Reference");
474d0f9a872SJulie Hockett }
475d0f9a872SJulie Hockett 
47646fc9592SJulie Hockett template <> llvm::Error addReference(TypeInfo *I, Reference &&R, FieldId F) {
477d0f9a872SJulie Hockett   switch (F) {
478d0f9a872SJulie Hockett   case FieldId::F_type:
479d0f9a872SJulie Hockett     I->Type = std::move(R);
48046fc9592SJulie Hockett     return llvm::Error::success();
481d0f9a872SJulie Hockett   default:
48218038065SFangrui Song     return llvm::createStringError(llvm::inconvertibleErrorCode(),
48318038065SFangrui Song                                    "invalid type cannot contain Reference");
484d0f9a872SJulie Hockett   }
485d0f9a872SJulie Hockett }
486d0f9a872SJulie Hockett 
48746fc9592SJulie Hockett template <>
48846fc9592SJulie Hockett llvm::Error addReference(FieldTypeInfo *I, Reference &&R, FieldId F) {
489d0f9a872SJulie Hockett   switch (F) {
490d0f9a872SJulie Hockett   case FieldId::F_type:
491d0f9a872SJulie Hockett     I->Type = std::move(R);
49246fc9592SJulie Hockett     return llvm::Error::success();
493d0f9a872SJulie Hockett   default:
49418038065SFangrui Song     return llvm::createStringError(llvm::inconvertibleErrorCode(),
49518038065SFangrui Song                                    "invalid type cannot contain Reference");
496d0f9a872SJulie Hockett   }
497d0f9a872SJulie Hockett }
498d0f9a872SJulie Hockett 
49946fc9592SJulie Hockett template <>
50046fc9592SJulie Hockett llvm::Error addReference(MemberTypeInfo *I, Reference &&R, FieldId F) {
501d0f9a872SJulie Hockett   switch (F) {
502d0f9a872SJulie Hockett   case FieldId::F_type:
503d0f9a872SJulie Hockett     I->Type = std::move(R);
50446fc9592SJulie Hockett     return llvm::Error::success();
505d0f9a872SJulie Hockett   default:
50618038065SFangrui Song     return llvm::createStringError(llvm::inconvertibleErrorCode(),
50718038065SFangrui Song                                    "invalid type cannot contain Reference");
508d0f9a872SJulie Hockett   }
509d0f9a872SJulie Hockett }
510d0f9a872SJulie Hockett 
51146fc9592SJulie Hockett template <> llvm::Error addReference(EnumInfo *I, Reference &&R, FieldId F) {
512d0f9a872SJulie Hockett   switch (F) {
513d0f9a872SJulie Hockett   case FieldId::F_namespace:
514d0f9a872SJulie Hockett     I->Namespace.emplace_back(std::move(R));
51546fc9592SJulie Hockett     return llvm::Error::success();
516d0f9a872SJulie Hockett   default:
51718038065SFangrui Song     return llvm::createStringError(llvm::inconvertibleErrorCode(),
51818038065SFangrui Song                                    "invalid type cannot contain Reference");
519d0f9a872SJulie Hockett   }
520d0f9a872SJulie Hockett }
521d0f9a872SJulie Hockett 
52221fb70c6SBrett Wilson template <> llvm::Error addReference(TypedefInfo *I, Reference &&R, FieldId F) {
52321fb70c6SBrett Wilson   switch (F) {
52421fb70c6SBrett Wilson   case FieldId::F_namespace:
52521fb70c6SBrett Wilson     I->Namespace.emplace_back(std::move(R));
52621fb70c6SBrett Wilson     return llvm::Error::success();
52721fb70c6SBrett Wilson   default:
52821fb70c6SBrett Wilson     return llvm::createStringError(llvm::inconvertibleErrorCode(),
52921fb70c6SBrett Wilson                                    "invalid type cannot contain Reference");
53021fb70c6SBrett Wilson   }
53121fb70c6SBrett Wilson }
53221fb70c6SBrett Wilson 
53346fc9592SJulie Hockett template <>
53446fc9592SJulie Hockett llvm::Error addReference(NamespaceInfo *I, Reference &&R, FieldId F) {
535d0f9a872SJulie Hockett   switch (F) {
536d0f9a872SJulie Hockett   case FieldId::F_namespace:
537d0f9a872SJulie Hockett     I->Namespace.emplace_back(std::move(R));
53846fc9592SJulie Hockett     return llvm::Error::success();
5398899c29bSJulie Hockett   case FieldId::F_child_namespace:
54021fb70c6SBrett Wilson     I->Children.Namespaces.emplace_back(std::move(R));
54146fc9592SJulie Hockett     return llvm::Error::success();
5428899c29bSJulie Hockett   case FieldId::F_child_record:
54321fb70c6SBrett Wilson     I->Children.Records.emplace_back(std::move(R));
54446fc9592SJulie Hockett     return llvm::Error::success();
545d0f9a872SJulie Hockett   default:
54618038065SFangrui Song     return llvm::createStringError(llvm::inconvertibleErrorCode(),
54718038065SFangrui Song                                    "invalid type cannot contain Reference");
548d0f9a872SJulie Hockett   }
549d0f9a872SJulie Hockett }
550d0f9a872SJulie Hockett 
55146fc9592SJulie Hockett template <>
55246fc9592SJulie Hockett llvm::Error addReference(FunctionInfo *I, Reference &&R, FieldId F) {
553d0f9a872SJulie Hockett   switch (F) {
554d0f9a872SJulie Hockett   case FieldId::F_namespace:
555d0f9a872SJulie Hockett     I->Namespace.emplace_back(std::move(R));
55646fc9592SJulie Hockett     return llvm::Error::success();
557d0f9a872SJulie Hockett   case FieldId::F_parent:
558d0f9a872SJulie Hockett     I->Parent = std::move(R);
55946fc9592SJulie Hockett     return llvm::Error::success();
560d0f9a872SJulie Hockett   default:
56118038065SFangrui Song     return llvm::createStringError(llvm::inconvertibleErrorCode(),
56218038065SFangrui Song                                    "invalid type cannot contain Reference");
563d0f9a872SJulie Hockett   }
564d0f9a872SJulie Hockett }
565d0f9a872SJulie Hockett 
56646fc9592SJulie Hockett template <> llvm::Error addReference(RecordInfo *I, Reference &&R, FieldId F) {
567d0f9a872SJulie Hockett   switch (F) {
568d0f9a872SJulie Hockett   case FieldId::F_namespace:
569d0f9a872SJulie Hockett     I->Namespace.emplace_back(std::move(R));
57046fc9592SJulie Hockett     return llvm::Error::success();
571d0f9a872SJulie Hockett   case FieldId::F_parent:
572d0f9a872SJulie Hockett     I->Parents.emplace_back(std::move(R));
57346fc9592SJulie Hockett     return llvm::Error::success();
574d0f9a872SJulie Hockett   case FieldId::F_vparent:
575d0f9a872SJulie Hockett     I->VirtualParents.emplace_back(std::move(R));
57646fc9592SJulie Hockett     return llvm::Error::success();
5778899c29bSJulie Hockett   case FieldId::F_child_record:
57821fb70c6SBrett Wilson     I->Children.Records.emplace_back(std::move(R));
57946fc9592SJulie Hockett     return llvm::Error::success();
580d0f9a872SJulie Hockett   default:
58118038065SFangrui Song     return llvm::createStringError(llvm::inconvertibleErrorCode(),
58218038065SFangrui Song                                    "invalid type cannot contain Reference");
583d0f9a872SJulie Hockett   }
584d0f9a872SJulie Hockett }
585d0f9a872SJulie Hockett 
5868899c29bSJulie Hockett template <typename T, typename ChildInfoType>
5878899c29bSJulie Hockett void addChild(T I, ChildInfoType &&R) {
58818038065SFangrui Song   llvm::errs() << "invalid child type for info";
5898899c29bSJulie Hockett   exit(1);
5908899c29bSJulie Hockett }
5918899c29bSJulie Hockett 
59221fb70c6SBrett Wilson // Namespace children:
5938899c29bSJulie Hockett template <> void addChild(NamespaceInfo *I, FunctionInfo &&R) {
59421fb70c6SBrett Wilson   I->Children.Functions.emplace_back(std::move(R));
5958899c29bSJulie Hockett }
5968899c29bSJulie Hockett template <> void addChild(NamespaceInfo *I, EnumInfo &&R) {
59721fb70c6SBrett Wilson   I->Children.Enums.emplace_back(std::move(R));
59821fb70c6SBrett Wilson }
59921fb70c6SBrett Wilson template <> void addChild(NamespaceInfo *I, TypedefInfo &&R) {
60021fb70c6SBrett Wilson   I->Children.Typedefs.emplace_back(std::move(R));
6018899c29bSJulie Hockett }
6028899c29bSJulie Hockett 
60321fb70c6SBrett Wilson // Record children:
6048899c29bSJulie Hockett template <> void addChild(RecordInfo *I, FunctionInfo &&R) {
60521fb70c6SBrett Wilson   I->Children.Functions.emplace_back(std::move(R));
6068899c29bSJulie Hockett }
607a7594772SHaowei Wu template <> void addChild(RecordInfo *I, EnumInfo &&R) {
60821fb70c6SBrett Wilson   I->Children.Enums.emplace_back(std::move(R));
60921fb70c6SBrett Wilson }
61021fb70c6SBrett Wilson template <> void addChild(RecordInfo *I, TypedefInfo &&R) {
61121fb70c6SBrett Wilson   I->Children.Typedefs.emplace_back(std::move(R));
612a7594772SHaowei Wu }
613a7594772SHaowei Wu 
61421fb70c6SBrett Wilson // Other types of children:
615eaa7b324SBrett Wilson template <> void addChild(EnumInfo *I, EnumValueInfo &&R) {
616eaa7b324SBrett Wilson   I->Members.emplace_back(std::move(R));
617eaa7b324SBrett Wilson }
618ba3d595fSDiego Astiazaran template <> void addChild(RecordInfo *I, BaseRecordInfo &&R) {
619ba3d595fSDiego Astiazaran   I->Bases.emplace_back(std::move(R));
620ba3d595fSDiego Astiazaran }
621ba3d595fSDiego Astiazaran template <> void addChild(BaseRecordInfo *I, FunctionInfo &&R) {
62221fb70c6SBrett Wilson   I->Children.Functions.emplace_back(std::move(R));
623ba3d595fSDiego Astiazaran }
624ba3d595fSDiego Astiazaran 
6254a68babdSBrett Wilson // TemplateParam children. These go into either a TemplateInfo (for template
6264a68babdSBrett Wilson // parameters) or TemplateSpecializationInfo (for the specialization's
6274a68babdSBrett Wilson // parameters).
6284a68babdSBrett Wilson template <typename T> void addTemplateParam(T I, TemplateParamInfo &&P) {
6294a68babdSBrett Wilson   llvm::errs() << "invalid container for template parameter";
6304a68babdSBrett Wilson   exit(1);
6314a68babdSBrett Wilson }
6324a68babdSBrett Wilson template <> void addTemplateParam(TemplateInfo *I, TemplateParamInfo &&P) {
6334a68babdSBrett Wilson   I->Params.emplace_back(std::move(P));
6344a68babdSBrett Wilson }
6354a68babdSBrett Wilson template <>
6364a68babdSBrett Wilson void addTemplateParam(TemplateSpecializationInfo *I, TemplateParamInfo &&P) {
6374a68babdSBrett Wilson   I->Params.emplace_back(std::move(P));
6384a68babdSBrett Wilson }
6394a68babdSBrett Wilson 
6404a68babdSBrett Wilson // Template info. These apply to either records or functions.
6414a68babdSBrett Wilson template <typename T> void addTemplate(T I, TemplateInfo &&P) {
6424a68babdSBrett Wilson   llvm::errs() << "invalid container for template info";
6434a68babdSBrett Wilson   exit(1);
6444a68babdSBrett Wilson }
6454a68babdSBrett Wilson template <> void addTemplate(RecordInfo *I, TemplateInfo &&P) {
6464a68babdSBrett Wilson   I->Template.emplace(std::move(P));
6474a68babdSBrett Wilson }
6484a68babdSBrett Wilson template <> void addTemplate(FunctionInfo *I, TemplateInfo &&P) {
6494a68babdSBrett Wilson   I->Template.emplace(std::move(P));
6504a68babdSBrett Wilson }
6514a68babdSBrett Wilson 
6524a68babdSBrett Wilson // Template specializations go only into template records.
6534a68babdSBrett Wilson template <typename T>
6544a68babdSBrett Wilson void addTemplateSpecialization(T I, TemplateSpecializationInfo &&TSI) {
6554a68babdSBrett Wilson   llvm::errs() << "invalid container for template specialization info";
6564a68babdSBrett Wilson   exit(1);
6574a68babdSBrett Wilson }
6584a68babdSBrett Wilson template <>
6594a68babdSBrett Wilson void addTemplateSpecialization(TemplateInfo *I,
6604a68babdSBrett Wilson                                TemplateSpecializationInfo &&TSI) {
6614a68babdSBrett Wilson   I->Specialization.emplace(std::move(TSI));
6624a68babdSBrett Wilson }
6634a68babdSBrett Wilson 
664d0f9a872SJulie Hockett // Read records from bitcode into a given info.
66546fc9592SJulie Hockett template <typename T>
66646fc9592SJulie Hockett llvm::Error ClangDocBitcodeReader::readRecord(unsigned ID, T I) {
667d0f9a872SJulie Hockett   Record R;
668d0f9a872SJulie Hockett   llvm::StringRef Blob;
6690e828958SJF Bastien   llvm::Expected<unsigned> MaybeRecID = Stream.readRecord(ID, R, &Blob);
6700e828958SJF Bastien   if (!MaybeRecID)
6710e828958SJF Bastien     return MaybeRecID.takeError();
6720e828958SJF Bastien   return parseRecord(R, MaybeRecID.get(), Blob, I);
673d0f9a872SJulie Hockett }
674d0f9a872SJulie Hockett 
67546fc9592SJulie Hockett template <>
67646fc9592SJulie Hockett llvm::Error ClangDocBitcodeReader::readRecord(unsigned ID, Reference *I) {
677d0f9a872SJulie Hockett   Record R;
678d0f9a872SJulie Hockett   llvm::StringRef Blob;
6790e828958SJF Bastien   llvm::Expected<unsigned> MaybeRecID = Stream.readRecord(ID, R, &Blob);
6800e828958SJF Bastien   if (!MaybeRecID)
6810e828958SJF Bastien     return MaybeRecID.takeError();
6820e828958SJF Bastien   return parseRecord(R, MaybeRecID.get(), Blob, I, CurrentReferenceField);
683d0f9a872SJulie Hockett }
684d0f9a872SJulie Hockett 
685d0f9a872SJulie Hockett // Read a block of records into a single info.
68646fc9592SJulie Hockett template <typename T>
68746fc9592SJulie Hockett llvm::Error ClangDocBitcodeReader::readBlock(unsigned ID, T I) {
6880e828958SJF Bastien   if (llvm::Error Err = Stream.EnterSubBlock(ID))
6890e828958SJF Bastien     return Err;
690d0f9a872SJulie Hockett 
691d0f9a872SJulie Hockett   while (true) {
692d0f9a872SJulie Hockett     unsigned BlockOrCode = 0;
693d0f9a872SJulie Hockett     Cursor Res = skipUntilRecordOrBlock(BlockOrCode);
694d0f9a872SJulie Hockett 
695d0f9a872SJulie Hockett     switch (Res) {
696d0f9a872SJulie Hockett     case Cursor::BadBlock:
69718038065SFangrui Song       return llvm::createStringError(llvm::inconvertibleErrorCode(),
69818038065SFangrui Song                                      "bad block found");
699d0f9a872SJulie Hockett     case Cursor::BlockEnd:
70046fc9592SJulie Hockett       return llvm::Error::success();
701d0f9a872SJulie Hockett     case Cursor::BlockBegin:
7020e828958SJF Bastien       if (llvm::Error Err = readSubBlock(BlockOrCode, I)) {
7030e828958SJF Bastien         if (llvm::Error Skipped = Stream.SkipBlock())
7040e828958SJF Bastien           return joinErrors(std::move(Err), std::move(Skipped));
70546fc9592SJulie Hockett         return Err;
70646fc9592SJulie Hockett       }
707d0f9a872SJulie Hockett       continue;
708d0f9a872SJulie Hockett     case Cursor::Record:
709d0f9a872SJulie Hockett       break;
710d0f9a872SJulie Hockett     }
71146fc9592SJulie Hockett     if (auto Err = readRecord(BlockOrCode, I))
71246fc9592SJulie Hockett       return Err;
713d0f9a872SJulie Hockett   }
714d0f9a872SJulie Hockett }
715d0f9a872SJulie Hockett 
716d0f9a872SJulie Hockett template <typename T>
71746fc9592SJulie Hockett llvm::Error ClangDocBitcodeReader::readSubBlock(unsigned ID, T I) {
718d0f9a872SJulie Hockett   switch (ID) {
719eaa7b324SBrett Wilson   // Blocks can only have certain types of sub blocks.
72046fc9592SJulie Hockett   case BI_COMMENT_BLOCK_ID: {
72146fc9592SJulie Hockett     auto Comment = getCommentInfo(I);
72246fc9592SJulie Hockett     if (!Comment)
72346fc9592SJulie Hockett       return Comment.takeError();
72446fc9592SJulie Hockett     if (auto Err = readBlock(ID, Comment.get()))
72546fc9592SJulie Hockett       return Err;
72646fc9592SJulie Hockett     return llvm::Error::success();
72746fc9592SJulie Hockett   }
728d0f9a872SJulie Hockett   case BI_TYPE_BLOCK_ID: {
729d0f9a872SJulie Hockett     TypeInfo TI;
73046fc9592SJulie Hockett     if (auto Err = readBlock(ID, &TI))
73146fc9592SJulie Hockett       return Err;
73246fc9592SJulie Hockett     if (auto Err = addTypeInfo(I, std::move(TI)))
73346fc9592SJulie Hockett       return Err;
73446fc9592SJulie Hockett     return llvm::Error::success();
735d0f9a872SJulie Hockett   }
736d0f9a872SJulie Hockett   case BI_FIELD_TYPE_BLOCK_ID: {
737d0f9a872SJulie Hockett     FieldTypeInfo TI;
73846fc9592SJulie Hockett     if (auto Err = readBlock(ID, &TI))
73946fc9592SJulie Hockett       return Err;
74046fc9592SJulie Hockett     if (auto Err = addTypeInfo(I, std::move(TI)))
74146fc9592SJulie Hockett       return Err;
74246fc9592SJulie Hockett     return llvm::Error::success();
743d0f9a872SJulie Hockett   }
744d0f9a872SJulie Hockett   case BI_MEMBER_TYPE_BLOCK_ID: {
745d0f9a872SJulie Hockett     MemberTypeInfo TI;
74646fc9592SJulie Hockett     if (auto Err = readBlock(ID, &TI))
74746fc9592SJulie Hockett       return Err;
74846fc9592SJulie Hockett     if (auto Err = addTypeInfo(I, std::move(TI)))
74946fc9592SJulie Hockett       return Err;
75046fc9592SJulie Hockett     return llvm::Error::success();
751d0f9a872SJulie Hockett   }
752d0f9a872SJulie Hockett   case BI_REFERENCE_BLOCK_ID: {
753d0f9a872SJulie Hockett     Reference R;
75446fc9592SJulie Hockett     if (auto Err = readBlock(ID, &R))
75546fc9592SJulie Hockett       return Err;
75646fc9592SJulie Hockett     if (auto Err = addReference(I, std::move(R), CurrentReferenceField))
75746fc9592SJulie Hockett       return Err;
75846fc9592SJulie Hockett     return llvm::Error::success();
759d0f9a872SJulie Hockett   }
7608899c29bSJulie Hockett   case BI_FUNCTION_BLOCK_ID: {
7618899c29bSJulie Hockett     FunctionInfo F;
76246fc9592SJulie Hockett     if (auto Err = readBlock(ID, &F))
76346fc9592SJulie Hockett       return Err;
7648899c29bSJulie Hockett     addChild(I, std::move(F));
76546fc9592SJulie Hockett     return llvm::Error::success();
7668899c29bSJulie Hockett   }
767ba3d595fSDiego Astiazaran   case BI_BASE_RECORD_BLOCK_ID: {
768ba3d595fSDiego Astiazaran     BaseRecordInfo BR;
769ba3d595fSDiego Astiazaran     if (auto Err = readBlock(ID, &BR))
770ba3d595fSDiego Astiazaran       return Err;
771ba3d595fSDiego Astiazaran     addChild(I, std::move(BR));
772ba3d595fSDiego Astiazaran     return llvm::Error::success();
773ba3d595fSDiego Astiazaran   }
7748899c29bSJulie Hockett   case BI_ENUM_BLOCK_ID: {
7758899c29bSJulie Hockett     EnumInfo E;
77646fc9592SJulie Hockett     if (auto Err = readBlock(ID, &E))
77746fc9592SJulie Hockett       return Err;
7788899c29bSJulie Hockett     addChild(I, std::move(E));
77946fc9592SJulie Hockett     return llvm::Error::success();
7808899c29bSJulie Hockett   }
781eaa7b324SBrett Wilson   case BI_ENUM_VALUE_BLOCK_ID: {
782eaa7b324SBrett Wilson     EnumValueInfo EV;
783eaa7b324SBrett Wilson     if (auto Err = readBlock(ID, &EV))
784eaa7b324SBrett Wilson       return Err;
785eaa7b324SBrett Wilson     addChild(I, std::move(EV));
786eaa7b324SBrett Wilson     return llvm::Error::success();
787eaa7b324SBrett Wilson   }
7884a68babdSBrett Wilson   case BI_TEMPLATE_BLOCK_ID: {
7894a68babdSBrett Wilson     TemplateInfo TI;
7904a68babdSBrett Wilson     if (auto Err = readBlock(ID, &TI))
7914a68babdSBrett Wilson       return Err;
7924a68babdSBrett Wilson     addTemplate(I, std::move(TI));
7934a68babdSBrett Wilson     return llvm::Error::success();
7944a68babdSBrett Wilson   }
7954a68babdSBrett Wilson   case BI_TEMPLATE_SPECIALIZATION_BLOCK_ID: {
7964a68babdSBrett Wilson     TemplateSpecializationInfo TSI;
7974a68babdSBrett Wilson     if (auto Err = readBlock(ID, &TSI))
7984a68babdSBrett Wilson       return Err;
7994a68babdSBrett Wilson     addTemplateSpecialization(I, std::move(TSI));
8004a68babdSBrett Wilson     return llvm::Error::success();
8014a68babdSBrett Wilson   }
8024a68babdSBrett Wilson   case BI_TEMPLATE_PARAM_BLOCK_ID: {
8034a68babdSBrett Wilson     TemplateParamInfo TPI;
8044a68babdSBrett Wilson     if (auto Err = readBlock(ID, &TPI))
8054a68babdSBrett Wilson       return Err;
8064a68babdSBrett Wilson     addTemplateParam(I, std::move(TPI));
8074a68babdSBrett Wilson     return llvm::Error::success();
8084a68babdSBrett Wilson   }
80921fb70c6SBrett Wilson   case BI_TYPEDEF_BLOCK_ID: {
81021fb70c6SBrett Wilson     TypedefInfo TI;
81121fb70c6SBrett Wilson     if (auto Err = readBlock(ID, &TI))
81221fb70c6SBrett Wilson       return Err;
81321fb70c6SBrett Wilson     addChild(I, std::move(TI));
81421fb70c6SBrett Wilson     return llvm::Error::success();
81521fb70c6SBrett Wilson   }
816d0f9a872SJulie Hockett   default:
81718038065SFangrui Song     return llvm::createStringError(llvm::inconvertibleErrorCode(),
81818038065SFangrui Song                                    "invalid subblock type");
819d0f9a872SJulie Hockett   }
820d0f9a872SJulie Hockett }
821d0f9a872SJulie Hockett 
822d0f9a872SJulie Hockett ClangDocBitcodeReader::Cursor
823d0f9a872SJulie Hockett ClangDocBitcodeReader::skipUntilRecordOrBlock(unsigned &BlockOrRecordID) {
824d0f9a872SJulie Hockett   BlockOrRecordID = 0;
825d0f9a872SJulie Hockett 
826d0f9a872SJulie Hockett   while (!Stream.AtEndOfStream()) {
8270e828958SJF Bastien     Expected<unsigned> MaybeCode = Stream.ReadCode();
8280e828958SJF Bastien     if (!MaybeCode) {
8290e828958SJF Bastien       // FIXME this drops the error on the floor.
8300e828958SJF Bastien       consumeError(MaybeCode.takeError());
8310e828958SJF Bastien       return Cursor::BadBlock;
8320e828958SJF Bastien     }
833d0f9a872SJulie Hockett 
83400922537SBjorn Pettersson     unsigned Code = MaybeCode.get();
83500922537SBjorn Pettersson     if (Code >= static_cast<unsigned>(llvm::bitc::FIRST_APPLICATION_ABBREV)) {
83600922537SBjorn Pettersson       BlockOrRecordID = Code;
83700922537SBjorn Pettersson       return Cursor::Record;
83800922537SBjorn Pettersson     }
83900922537SBjorn Pettersson     switch (static_cast<llvm::bitc::FixedAbbrevIDs>(Code)) {
840d0f9a872SJulie Hockett     case llvm::bitc::ENTER_SUBBLOCK:
8410e828958SJF Bastien       if (Expected<unsigned> MaybeID = Stream.ReadSubBlockID())
8420e828958SJF Bastien         BlockOrRecordID = MaybeID.get();
8430e828958SJF Bastien       else {
8440e828958SJF Bastien         // FIXME this drops the error on the floor.
8450e828958SJF Bastien         consumeError(MaybeID.takeError());
8460e828958SJF Bastien       }
847d0f9a872SJulie Hockett       return Cursor::BlockBegin;
848d0f9a872SJulie Hockett     case llvm::bitc::END_BLOCK:
849d0f9a872SJulie Hockett       if (Stream.ReadBlockEnd())
850d0f9a872SJulie Hockett         return Cursor::BadBlock;
851d0f9a872SJulie Hockett       return Cursor::BlockEnd;
852d0f9a872SJulie Hockett     case llvm::bitc::DEFINE_ABBREV:
8530e828958SJF Bastien       if (llvm::Error Err = Stream.ReadAbbrevRecord()) {
8540e828958SJF Bastien         // FIXME this drops the error on the floor.
8550e828958SJF Bastien         consumeError(std::move(Err));
8560e828958SJF Bastien       }
857d0f9a872SJulie Hockett       continue;
858d0f9a872SJulie Hockett     case llvm::bitc::UNABBREV_RECORD:
859d0f9a872SJulie Hockett       return Cursor::BadBlock;
86000922537SBjorn Pettersson     case llvm::bitc::FIRST_APPLICATION_ABBREV:
86100922537SBjorn Pettersson       llvm_unreachable("Unexpected abbrev id.");
862d0f9a872SJulie Hockett     }
863d0f9a872SJulie Hockett   }
864d0f9a872SJulie Hockett   llvm_unreachable("Premature stream end.");
865d0f9a872SJulie Hockett }
866d0f9a872SJulie Hockett 
86746fc9592SJulie Hockett llvm::Error ClangDocBitcodeReader::validateStream() {
868d0f9a872SJulie Hockett   if (Stream.AtEndOfStream())
86918038065SFangrui Song     return llvm::createStringError(llvm::inconvertibleErrorCode(),
87018038065SFangrui Song                                    "premature end of stream");
871d0f9a872SJulie Hockett 
872d0f9a872SJulie Hockett   // Sniff for the signature.
8730e828958SJF Bastien   for (int Idx = 0; Idx != 4; ++Idx) {
8740e828958SJF Bastien     Expected<llvm::SimpleBitstreamCursor::word_t> MaybeRead = Stream.Read(8);
8750e828958SJF Bastien     if (!MaybeRead)
8760e828958SJF Bastien       return MaybeRead.takeError();
8770e828958SJF Bastien     else if (MaybeRead.get() != BitCodeConstants::Signature[Idx])
87818038065SFangrui Song       return llvm::createStringError(llvm::inconvertibleErrorCode(),
87918038065SFangrui Song                                      "invalid bitcode signature");
8800e828958SJF Bastien   }
88146fc9592SJulie Hockett   return llvm::Error::success();
882d0f9a872SJulie Hockett }
883d0f9a872SJulie Hockett 
88446fc9592SJulie Hockett llvm::Error ClangDocBitcodeReader::readBlockInfoBlock() {
88549e75ebdSKrzysztof Parzyszek   Expected<std::optional<llvm::BitstreamBlockInfo>> MaybeBlockInfo =
8860e828958SJF Bastien       Stream.ReadBlockInfoBlock();
8870e828958SJF Bastien   if (!MaybeBlockInfo)
8880e828958SJF Bastien     return MaybeBlockInfo.takeError();
8890e828958SJF Bastien   else
8900e828958SJF Bastien     BlockInfo = MaybeBlockInfo.get();
891d0f9a872SJulie Hockett   if (!BlockInfo)
89218038065SFangrui Song     return llvm::createStringError(llvm::inconvertibleErrorCode(),
89318038065SFangrui Song                                    "unable to parse BlockInfoBlock");
894d0f9a872SJulie Hockett   Stream.setBlockInfo(&*BlockInfo);
89546fc9592SJulie Hockett   return llvm::Error::success();
896d0f9a872SJulie Hockett }
897d0f9a872SJulie Hockett 
898d0f9a872SJulie Hockett template <typename T>
89946fc9592SJulie Hockett llvm::Expected<std::unique_ptr<Info>>
90046fc9592SJulie Hockett ClangDocBitcodeReader::createInfo(unsigned ID) {
9011c705d9cSJonas Devlieghere   std::unique_ptr<Info> I = std::make_unique<T>();
90246fc9592SJulie Hockett   if (auto Err = readBlock(ID, static_cast<T *>(I.get())))
90346fc9592SJulie Hockett     return std::move(Err);
9042c1c9a24SJulie Hockett   return std::unique_ptr<Info>{std::move(I)};
905d0f9a872SJulie Hockett }
906d0f9a872SJulie Hockett 
90746fc9592SJulie Hockett llvm::Expected<std::unique_ptr<Info>>
90846fc9592SJulie Hockett ClangDocBitcodeReader::readBlockToInfo(unsigned ID) {
909d0f9a872SJulie Hockett   switch (ID) {
910d0f9a872SJulie Hockett   case BI_NAMESPACE_BLOCK_ID:
911d0f9a872SJulie Hockett     return createInfo<NamespaceInfo>(ID);
912d0f9a872SJulie Hockett   case BI_RECORD_BLOCK_ID:
913d0f9a872SJulie Hockett     return createInfo<RecordInfo>(ID);
914d0f9a872SJulie Hockett   case BI_ENUM_BLOCK_ID:
915d0f9a872SJulie Hockett     return createInfo<EnumInfo>(ID);
91621fb70c6SBrett Wilson   case BI_TYPEDEF_BLOCK_ID:
91721fb70c6SBrett Wilson     return createInfo<TypedefInfo>(ID);
918d0f9a872SJulie Hockett   case BI_FUNCTION_BLOCK_ID:
919d0f9a872SJulie Hockett     return createInfo<FunctionInfo>(ID);
920d0f9a872SJulie Hockett   default:
92118038065SFangrui Song     return llvm::createStringError(llvm::inconvertibleErrorCode(),
92218038065SFangrui Song                                    "cannot create info");
923d0f9a872SJulie Hockett   }
924d0f9a872SJulie Hockett }
925d0f9a872SJulie Hockett 
926d0f9a872SJulie Hockett // Entry point
9278899c29bSJulie Hockett llvm::Expected<std::vector<std::unique_ptr<Info>>>
9288899c29bSJulie Hockett ClangDocBitcodeReader::readBitcode() {
929d0f9a872SJulie Hockett   std::vector<std::unique_ptr<Info>> Infos;
93046fc9592SJulie Hockett   if (auto Err = validateStream())
93146fc9592SJulie Hockett     return std::move(Err);
932d0f9a872SJulie Hockett 
933d0f9a872SJulie Hockett   // Read the top level blocks.
934d0f9a872SJulie Hockett   while (!Stream.AtEndOfStream()) {
9350e828958SJF Bastien     Expected<unsigned> MaybeCode = Stream.ReadCode();
9360e828958SJF Bastien     if (!MaybeCode)
9370e828958SJF Bastien       return MaybeCode.takeError();
9380e828958SJF Bastien     if (MaybeCode.get() != llvm::bitc::ENTER_SUBBLOCK)
93918038065SFangrui Song       return llvm::createStringError(llvm::inconvertibleErrorCode(),
94018038065SFangrui Song                                      "no blocks in input");
9410e828958SJF Bastien     Expected<unsigned> MaybeID = Stream.ReadSubBlockID();
9420e828958SJF Bastien     if (!MaybeID)
9430e828958SJF Bastien       return MaybeID.takeError();
9440e828958SJF Bastien     unsigned ID = MaybeID.get();
945d0f9a872SJulie Hockett     switch (ID) {
946d0f9a872SJulie Hockett     // NamedType and Comment blocks should not appear at the top level
947d0f9a872SJulie Hockett     case BI_TYPE_BLOCK_ID:
948d0f9a872SJulie Hockett     case BI_FIELD_TYPE_BLOCK_ID:
949d0f9a872SJulie Hockett     case BI_MEMBER_TYPE_BLOCK_ID:
950d0f9a872SJulie Hockett     case BI_COMMENT_BLOCK_ID:
951d0f9a872SJulie Hockett     case BI_REFERENCE_BLOCK_ID:
95218038065SFangrui Song       return llvm::createStringError(llvm::inconvertibleErrorCode(),
95318038065SFangrui Song                                      "invalid top level block");
954d0f9a872SJulie Hockett     case BI_NAMESPACE_BLOCK_ID:
955d0f9a872SJulie Hockett     case BI_RECORD_BLOCK_ID:
956d0f9a872SJulie Hockett     case BI_ENUM_BLOCK_ID:
95721fb70c6SBrett Wilson     case BI_TYPEDEF_BLOCK_ID:
95846fc9592SJulie Hockett     case BI_FUNCTION_BLOCK_ID: {
95946fc9592SJulie Hockett       auto InfoOrErr = readBlockToInfo(ID);
96046fc9592SJulie Hockett       if (!InfoOrErr)
96146fc9592SJulie Hockett         return InfoOrErr.takeError();
96246fc9592SJulie Hockett       Infos.emplace_back(std::move(InfoOrErr.get()));
9638899c29bSJulie Hockett       continue;
96446fc9592SJulie Hockett     }
965d0f9a872SJulie Hockett     case BI_VERSION_BLOCK_ID:
96646fc9592SJulie Hockett       if (auto Err = readBlock(ID, VersionNumber))
96746fc9592SJulie Hockett         return std::move(Err);
968d0f9a872SJulie Hockett       continue;
969d0f9a872SJulie Hockett     case llvm::bitc::BLOCKINFO_BLOCK_ID:
97046fc9592SJulie Hockett       if (auto Err = readBlockInfoBlock())
97146fc9592SJulie Hockett         return std::move(Err);
972d0f9a872SJulie Hockett       continue;
973d0f9a872SJulie Hockett     default:
9740e828958SJF Bastien       if (llvm::Error Err = Stream.SkipBlock()) {
9750e828958SJF Bastien         // FIXME this drops the error on the floor.
9760e828958SJF Bastien         consumeError(std::move(Err));
9770e828958SJF Bastien       }
978d0f9a872SJulie Hockett       continue;
979d0f9a872SJulie Hockett     }
980d0f9a872SJulie Hockett   }
9818899c29bSJulie Hockett   return std::move(Infos);
982d0f9a872SJulie Hockett }
983d0f9a872SJulie Hockett 
984d0f9a872SJulie Hockett } // namespace doc
985d0f9a872SJulie Hockett } // namespace clang
986