clang-tools 23.0.0git
BitcodeReader.cpp
Go to the documentation of this file.
1//===-- BitcodeReader.cpp - ClangDoc Bitcode Reader ------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "BitcodeReader.h"
10#include "llvm/Support/Error.h"
11#include "llvm/Support/ErrorHandling.h"
12#include "llvm/Support/TimeProfiler.h"
13#include "llvm/Support/raw_ostream.h"
14#include <optional>
15#include <utility>
16
17namespace clang {
18namespace doc {
19
20static llvm::ExitOnError ExitOnErr("clang-doc error: ");
21
22using Record = llvm::SmallVector<uint64_t, 1024>;
23
24// This implements decode for SmallString.
25static llvm::Error decodeRecord(const Record &R,
27 llvm::StringRef Blob) {
28 Field.assign(Blob.begin(), Blob.end());
29 return llvm::Error::success();
30}
31
32static llvm::Error decodeRecord(const Record &R, llvm::StringRef &Field,
33 llvm::StringRef Blob) {
34 Field = internString(Blob);
35 return llvm::Error::success();
36}
37
38static llvm::Error decodeRecord(const Record &R, SymbolID &Field,
39 llvm::StringRef Blob) {
40 if (R.empty())
41 return llvm::createStringError(llvm::inconvertibleErrorCode(),
42 "empty record for SymbolID");
44 return llvm::createStringError(llvm::inconvertibleErrorCode(),
45 "incorrect USR size");
46 if (R.size() < R[0] + 1)
47 return llvm::createStringError(llvm::inconvertibleErrorCode(),
48 "record too short for SymbolID");
49
50 // First position in the record is the length of the following array, so we
51 // copy the following elements to the field.
52 for (int I = 0, E = R[0]; I < E; ++I)
53 Field[I] = R[I + 1];
54 return llvm::Error::success();
55}
56
57static llvm::Error decodeRecord(const Record &R, bool &Field,
58 llvm::StringRef Blob) {
59 if (R.empty())
60 return llvm::createStringError(llvm::inconvertibleErrorCode(),
61 "empty record for bool");
62 Field = R[0] != 0;
63 return llvm::Error::success();
64}
65
66static llvm::Error decodeRecord(const Record &R, AccessSpecifier &Field,
67 llvm::StringRef Blob) {
68 if (R.empty())
69 return llvm::createStringError(llvm::inconvertibleErrorCode(),
70 "empty record for AccessSpecifier");
71 switch (R[0]) {
72 case AS_public:
73 case AS_private:
74 case AS_protected:
75 case AS_none:
76 Field = (AccessSpecifier)R[0];
77 return llvm::Error::success();
78 }
79 llvm_unreachable("invalid value for AccessSpecifier");
80}
81
82static llvm::Error decodeRecord(const Record &R, TagTypeKind &Field,
83 llvm::StringRef Blob) {
84 if (R.empty())
85 return llvm::createStringError(llvm::inconvertibleErrorCode(),
86 "empty record for TagTypeKind");
87 switch (static_cast<TagTypeKind>(R[0])) {
88 case TagTypeKind::Struct:
89 case TagTypeKind::Interface:
90 case TagTypeKind::Union:
91 case TagTypeKind::Class:
92 case TagTypeKind::Enum:
93 Field = static_cast<TagTypeKind>(R[0]);
94 return llvm::Error::success();
95 }
96 return llvm::createStringError(llvm::inconvertibleErrorCode(),
97 "invalid value for TagTypeKind");
98}
99
100static llvm::Error decodeRecord(const Record &R, std::optional<Location> &Field,
101 llvm::StringRef Blob) {
102 if (R.size() < 3)
103 return llvm::createStringError(llvm::inconvertibleErrorCode(),
104 "record too short for Location");
105 if (R[0] > INT_MAX)
106 return llvm::createStringError(llvm::inconvertibleErrorCode(),
107 "integer too large to parse");
108 Field.emplace(static_cast<int>(R[0]), static_cast<int>(R[1]), Blob,
109 static_cast<bool>(R[2]));
110 return llvm::Error::success();
111}
112
113static llvm::Error decodeRecord(const Record &R, InfoType &Field,
114 llvm::StringRef Blob) {
115 if (R.empty())
116 return llvm::createStringError(llvm::inconvertibleErrorCode(),
117 "empty record for InfoType");
118 switch (auto IT = static_cast<InfoType>(R[0])) {
128 Field = IT;
129 return llvm::Error::success();
130 }
131 return llvm::createStringError(llvm::inconvertibleErrorCode(),
132 "invalid value for InfoType");
133}
134
135static llvm::Error decodeRecord(const Record &R, FieldId &Field,
136 llvm::StringRef Blob) {
137 if (R.empty())
138 return llvm::createStringError(llvm::inconvertibleErrorCode(),
139 "empty record for FieldId");
140 switch (auto F = static_cast<FieldId>(R[0])) {
144 case FieldId::F_type:
150 Field = F;
151 return llvm::Error::success();
152 }
153 return llvm::createStringError(llvm::inconvertibleErrorCode(),
154 "invalid value for FieldId");
155}
156
157static llvm::Error decodeRecord(const Record &R, DocList<Location> &Field,
158 llvm::StringRef Blob) {
159 if (R.size() < 3)
160 return llvm::createStringError(llvm::inconvertibleErrorCode(),
161 "record too short for Location");
162 if (R[0] > INT_MAX)
163 return llvm::createStringError(llvm::inconvertibleErrorCode(),
164 "integer too large to parse");
165
167 static_cast<int>(R[0]), static_cast<int>(R[1]), Blob,
168 static_cast<bool>(R[2])));
169 return llvm::Error::success();
170}
171
172static llvm::Error parseRecord(const Record &R, unsigned ID,
173 llvm::StringRef Blob, const unsigned VersionNo) {
174 if (ID == VERSION && R[0] == VersionNo)
175 return llvm::Error::success();
176 return llvm::createStringError(llvm::inconvertibleErrorCode(),
177 "mismatched bitcode version number");
178}
179
180static llvm::Error parseRecord(const Record &R, unsigned ID,
181 llvm::StringRef Blob, NamespaceInfo *I) {
182 switch (ID) {
183 case NAMESPACE_USR:
184 return decodeRecord(R, I->USR, Blob);
185 case NAMESPACE_NAME:
186 return decodeRecord(R, I->Name, Blob);
187 case NAMESPACE_PATH:
188 return decodeRecord(R, I->Path, Blob);
190 return decodeRecord(R, I->ParentUSR, Blob);
191 default:
192 return llvm::createStringError(llvm::inconvertibleErrorCode(),
193 "invalid field for NamespaceInfo");
194 }
195}
196
197static llvm::Error parseRecord(const Record &R, unsigned ID,
198 llvm::StringRef Blob, RecordInfo *I) {
199 switch (ID) {
200 case RECORD_USR:
201 return decodeRecord(R, I->USR, Blob);
202 case RECORD_NAME:
203 return decodeRecord(R, I->Name, Blob);
204 case RECORD_PATH:
205 return decodeRecord(R, I->Path, Blob);
207 return decodeRecord(R, I->DefLoc, Blob);
208 case RECORD_LOCATION:
209 return decodeRecord(R, I->Loc, Blob);
210 case RECORD_TAG_TYPE:
211 return decodeRecord(R, I->TagType, Blob);
213 return decodeRecord(R, I->IsTypeDef, Blob);
215 return decodeRecord(R, I->MangledName, Blob);
217 return decodeRecord(R, I->ParentUSR, Blob);
218 default:
219 return llvm::createStringError(llvm::inconvertibleErrorCode(),
220 "invalid field for RecordInfo");
221 }
222}
223
224static llvm::Error parseRecord(const Record &R, unsigned ID,
225 llvm::StringRef Blob, BaseRecordInfo *I) {
226 switch (ID) {
227 case BASE_RECORD_USR:
228 return decodeRecord(R, I->USR, Blob);
229 case BASE_RECORD_NAME:
230 return decodeRecord(R, I->Name, Blob);
231 case BASE_RECORD_PATH:
232 return decodeRecord(R, I->Path, Blob);
234 return decodeRecord(R, I->TagType, Blob);
236 return decodeRecord(R, I->IsVirtual, Blob);
238 return decodeRecord(R, I->Access, Blob);
240 return decodeRecord(R, I->IsParent, Blob);
241 default:
242 return llvm::createStringError(llvm::inconvertibleErrorCode(),
243 "invalid field for BaseRecordInfo");
244 }
245}
246
247static llvm::Error parseRecord(const Record &R, unsigned ID,
248 llvm::StringRef Blob, EnumInfo *I) {
249 switch (ID) {
250 case ENUM_USR:
251 return decodeRecord(R, I->USR, Blob);
252 case ENUM_NAME:
253 return decodeRecord(R, I->Name, Blob);
254 case ENUM_DEFLOCATION:
255 return decodeRecord(R, I->DefLoc, Blob);
256 case ENUM_LOCATION:
257 return decodeRecord(R, I->Loc, Blob);
258 case ENUM_SCOPED:
259 return decodeRecord(R, I->Scoped, Blob);
260 default:
261 return llvm::createStringError(llvm::inconvertibleErrorCode(),
262 "invalid field for EnumInfo");
263 }
264}
265
266static llvm::Error parseRecord(const Record &R, unsigned ID,
267 llvm::StringRef Blob, TypedefInfo *I) {
268 switch (ID) {
269 case TYPEDEF_USR:
270 return decodeRecord(R, I->USR, Blob);
271 case TYPEDEF_NAME:
272 return decodeRecord(R, I->Name, Blob);
274 return decodeRecord(R, I->DefLoc, Blob);
275 case TYPEDEF_IS_USING:
276 return decodeRecord(R, I->IsUsing, Blob);
277 default:
278 return llvm::createStringError(llvm::inconvertibleErrorCode(),
279 "invalid field for TypedefInfo");
280 }
281}
282
283static llvm::Error parseRecord(const Record &R, unsigned ID,
284 llvm::StringRef Blob, EnumValueInfo *I) {
285 switch (ID) {
286 case ENUM_VALUE_NAME:
287 return decodeRecord(R, I->Name, Blob);
288 case ENUM_VALUE_VALUE:
289 return decodeRecord(R, I->Value, Blob);
290 case ENUM_VALUE_EXPR:
291 return decodeRecord(R, I->ValueExpr, Blob);
292 default:
293 return llvm::createStringError(llvm::inconvertibleErrorCode(),
294 "invalid field for EnumValueInfo");
295 }
296}
297
298static llvm::Error parseRecord(const Record &R, unsigned ID,
299 llvm::StringRef Blob, FunctionInfo *I) {
300 switch (ID) {
301 case FUNCTION_USR:
302 return decodeRecord(R, I->USR, Blob);
303 case FUNCTION_NAME:
304 return decodeRecord(R, I->Name, Blob);
306 return decodeRecord(R, I->DefLoc, Blob);
308 return decodeRecord(R, I->Loc, Blob);
309 case FUNCTION_ACCESS:
310 return decodeRecord(R, I->Access, Blob);
312 return decodeRecord(R, I->IsMethod, Blob);
314 return decodeRecord(R, I->IsStatic, Blob);
315 default:
316 return llvm::createStringError(llvm::inconvertibleErrorCode(),
317 "invalid field for FunctionInfo");
318 }
319}
320
321static llvm::Error parseRecord(const Record &R, unsigned ID,
322 llvm::StringRef Blob, TypeInfo *I) {
323 switch (ID) {
324 case TYPE_IS_BUILTIN:
325 return decodeRecord(R, I->IsBuiltIn, Blob);
326 case TYPE_IS_TEMPLATE:
327 return decodeRecord(R, I->IsTemplate, Blob);
328 default:
329 return llvm::createStringError(llvm::inconvertibleErrorCode(),
330 "invalid field for TypeInfo");
331 }
332}
333
334static llvm::Error parseRecord(const Record &R, unsigned ID,
335 llvm::StringRef Blob, FieldTypeInfo *I) {
336 switch (ID) {
337 case FIELD_TYPE_NAME:
338 return decodeRecord(R, I->Name, Blob);
340 return decodeRecord(R, I->DefaultValue, Blob);
342 return decodeRecord(R, I->IsBuiltIn, Blob);
344 return decodeRecord(R, I->IsTemplate, Blob);
345 default:
346 return llvm::createStringError(llvm::inconvertibleErrorCode(),
347 "invalid field for TypeInfo");
348 }
349}
350
351static llvm::Error parseRecord(const Record &R, unsigned ID,
352 llvm::StringRef Blob, MemberTypeInfo *I) {
353 switch (ID) {
354 case MEMBER_TYPE_NAME:
355 return decodeRecord(R, I->Name, Blob);
357 return decodeRecord(R, I->Access, Blob);
359 return decodeRecord(R, I->IsStatic, Blob);
361 return decodeRecord(R, I->IsBuiltIn, Blob);
363 return decodeRecord(R, I->IsTemplate, Blob);
364 default:
365 return llvm::createStringError(llvm::inconvertibleErrorCode(),
366 "invalid field for MemberTypeInfo");
367 }
368}
369
370static llvm::Error parseRecord(const Record &R, unsigned ID,
371 llvm::StringRef Blob, CommentInfo *I,
375 llvm::SmallString<16> KindStr;
376 switch (ID) {
377 case COMMENT_KIND:
378 if (llvm::Error Err = decodeRecord(R, KindStr, Blob))
379 return Err;
380 I->Kind = stringToCommentKind(KindStr);
381 return llvm::Error::success();
382 case COMMENT_TEXT:
383 return decodeRecord(R, I->Text, Blob);
384 case COMMENT_NAME:
385 return decodeRecord(R, I->Name, Blob);
387 return decodeRecord(R, I->Direction, Blob);
389 return decodeRecord(R, I->ParamName, Blob);
391 return decodeRecord(R, I->CloseName, Blob);
392 case COMMENT_ATTRKEY:
393 AttrKeys.push_back(internString(Blob));
394 return llvm::Error::success();
395 case COMMENT_ATTRVAL:
396 AttrValues.push_back(internString(Blob));
397 return llvm::Error::success();
398 case COMMENT_ARG:
399 Args.push_back(internString(Blob));
400 return llvm::Error::success();
402 return decodeRecord(R, I->SelfClosing, Blob);
403 case COMMENT_EXPLICIT:
404 return decodeRecord(R, I->Explicit, Blob);
405 default:
406 return llvm::createStringError(llvm::inconvertibleErrorCode(),
407 "invalid field for CommentInfo");
408 }
409}
410
411template <typename T, typename BlockBeginHandler, typename BlockEndHandler,
412 typename RecordHandler>
413llvm::Error
414ClangDocBitcodeReader::parseBlock(unsigned ID, T I, BlockBeginHandler &&BBH,
415 BlockEndHandler &&BEH, RecordHandler &&RH) {
416 llvm::TimeTraceScope("Reducing infos", "readBlock");
417 if (llvm::Error Err = Stream.EnterSubBlock(ID))
418 return Err;
419
420 while (true) {
421 unsigned BlockOrCode = 0;
422 llvm::Expected<Cursor> C = skipUntilRecordOrBlock(BlockOrCode);
423 if (!C)
424 return C.takeError();
425
426 switch (*C) {
427 case Cursor::BadBlock:
428 return llvm::createStringError(llvm::inconvertibleErrorCode(),
429 "bad block found");
430 case Cursor::BlockEnd:
431 if (llvm::Error Err = BEH())
432 return Err;
433 return llvm::Error::success();
434 case Cursor::BlockBegin: {
435 llvm::Expected<bool> Handled = BBH(BlockOrCode);
436 if (!Handled)
437 return Handled.takeError();
438 if (*Handled)
439 continue;
440
441 if (llvm::Error Err = readSubBlock(BlockOrCode, I)) {
442 if (llvm::Error Skipped = Stream.SkipBlock())
443 return joinErrors(std::move(Err), std::move(Skipped));
444 return Err;
445 }
446 continue;
447 }
448 case Cursor::Record:
449 break;
450 }
451
452 if (llvm::Error Err = RH(BlockOrCode))
453 return Err;
454 }
455}
456
457template <typename T, typename BlockBeginHandler, typename BlockEndHandler>
458llvm::Error ClangDocBitcodeReader::parseBlock(unsigned ID, T I,
459 BlockBeginHandler &&BBH,
460 BlockEndHandler &&BEH) {
461 return parseBlock(ID, I, std::forward<BlockBeginHandler>(BBH),
462 std::forward<BlockEndHandler>(BEH),
463 [&](unsigned Code) { return readRecord(Code, I); });
464}
465
466template <typename ChildType>
467llvm::Expected<bool> ClangDocBitcodeReader::readSubBlockIfMatch(
468 unsigned ID, unsigned TargetID, llvm::SmallVectorImpl<ChildType> &V) {
469 if (ID != TargetID)
470 return false;
471 ChildType Val;
472 if (auto Err = readBlock(ID, &Val))
473 return std::move(Err);
474 V.push_back(std::move(Val));
475 return true;
476}
477
478template <typename T>
479static llvm::Error addReference(T I, Reference &&R, FieldId F);
480
481template <> llvm::Error addReference(VarInfo *I, Reference &&R, FieldId F);
482template <> llvm::Error addReference(TypeInfo *I, Reference &&R, FieldId F);
483template <>
484llvm::Error addReference(FieldTypeInfo *I, Reference &&R, FieldId F);
485template <>
486llvm::Error addReference(MemberTypeInfo *I, Reference &&R, FieldId F);
487template <> llvm::Error addReference(EnumInfo *I, Reference &&R, FieldId F);
488template <> llvm::Error addReference(TypedefInfo *I, Reference &&R, FieldId F);
489template <>
490llvm::Error addReference(NamespaceInfo *I, Reference &&R, FieldId F);
491template <> llvm::Error addReference(FunctionInfo *I, Reference &&R, FieldId F);
492template <> llvm::Error addReference(RecordInfo *I, Reference &&R, FieldId F);
493template <>
494llvm::Error addReference(ConstraintInfo *I, Reference &&R, FieldId F);
495template <>
496llvm::Error addReference(FriendInfo *Friend, Reference &&R, FieldId F);
497
498template <typename InfoT>
499llvm::Expected<bool> ClangDocBitcodeReader::routeReferenceBlock(
500 unsigned ID, llvm::SmallVectorImpl<Reference> &Namespaces, InfoT *I,
501 std::initializer_list<ReferenceMap> Mappings) {
502 if (ID != BI_REFERENCE_BLOCK_ID)
503 return false;
504 Reference R;
505 if (auto Err = readBlock(ID, &R))
506 return std::move(Err);
507
508 for (const auto &Map : Mappings) {
509 if (CurrentReferenceField == Map.Field) {
510 Map.Vec->push_back(std::move(R));
511 return true;
512 }
513 }
514
515 if (CurrentReferenceField == FieldId::F_namespace) {
516 Namespaces.push_back(std::move(R));
517 return true;
518 }
519
520 if (auto Err = addReference(I, std::move(R), CurrentReferenceField))
521 return std::move(Err);
522
523 return true;
524}
525
526template <>
527llvm::Error ClangDocBitcodeReader::readBlock(unsigned ID, CommentInfo *I);
528template <>
529llvm::Error ClangDocBitcodeReader::readBlock(unsigned ID, FunctionInfo *I);
530template <>
531llvm::Error ClangDocBitcodeReader::readBlock(unsigned ID, EnumInfo *I);
532template <>
533llvm::Error ClangDocBitcodeReader::readBlock(unsigned ID, BaseRecordInfo *I);
534template <>
535llvm::Error ClangDocBitcodeReader::readBlock(unsigned ID, RecordInfo *I);
536template <>
537llvm::Error ClangDocBitcodeReader::readBlock(unsigned ID, TemplateInfo *I);
538template <>
539llvm::Error ClangDocBitcodeReader::readBlock(unsigned ID,
541template <>
542llvm::Error ClangDocBitcodeReader::readBlock(unsigned ID, VarInfo *I);
543template <>
544llvm::Error ClangDocBitcodeReader::readBlock(unsigned ID, TypedefInfo *I);
545template <>
546llvm::Error ClangDocBitcodeReader::readBlock(unsigned ID, NamespaceInfo *I);
547template <>
548llvm::Error ClangDocBitcodeReader::readBlock(unsigned ID, FriendInfo *I);
549
550template <>
551llvm::Error ClangDocBitcodeReader::readBlock(unsigned ID, CommentInfo *I) {
552 llvm::SmallVector<CommentInfo> LocalChildren;
553 llvm::SmallVector<StringRef> AttrKeys;
554 llvm::SmallVector<StringRef> AttrValues;
555 llvm::SmallVector<StringRef> Args;
556
557 return parseBlock(
558 ID, I,
559 [&](unsigned BlockOrCode) -> llvm::Expected<bool> {
560 if (BlockOrCode == BI_COMMENT_BLOCK_ID) {
561 CommentInfo Child;
562 if (llvm::Error Err = readBlock(BlockOrCode, &Child))
563 return std::move(Err);
564 LocalChildren.push_back(std::move(Child));
565 return true;
566 }
567 return false;
568 },
569 [&]() -> llvm::Error {
570 if (!LocalChildren.empty())
571 I->Children =
573 if (!AttrKeys.empty())
574 I->AttrKeys = allocateArray(AttrKeys, TransientArena);
575 if (!AttrValues.empty())
576 I->AttrValues = allocateArray(AttrValues, TransientArena);
577 if (!Args.empty())
579
580 return llvm::Error::success();
581 },
582 [&](unsigned BlockOrCode) -> llvm::Error {
583 Record R;
584 llvm::StringRef Blob;
585 llvm::Expected<unsigned> MaybeRecID =
586 Stream.readRecord(BlockOrCode, R, &Blob);
587 if (!MaybeRecID)
588 return MaybeRecID.takeError();
589 return parseRecord(R, MaybeRecID.get(), Blob, I, AttrKeys, AttrValues,
590 Args);
591 });
592}
593
594template <>
595llvm::Error ClangDocBitcodeReader::readBlock(unsigned ID, FunctionInfo *I) {
596 llvm::SmallVector<FieldTypeInfo, 4> LocalParams;
597 llvm::SmallVector<Reference> LocalNamespaces;
598
599 return parseBlock(
600 ID, I,
601 [&](unsigned BlockOrCode) -> llvm::Expected<bool> {
602 auto B = readSubBlockIfMatch(BlockOrCode, BI_FIELD_TYPE_BLOCK_ID,
603 LocalParams);
604 if (!B)
605 return B.takeError();
606 if (*B)
607 return true;
608 return routeReferenceBlock(BlockOrCode, LocalNamespaces, I);
609 },
610 [&]() -> llvm::Error {
611 I->Params = allocateArray(LocalParams, TransientArena);
612 if (!LocalNamespaces.empty())
613 I->Namespace = allocateArray(LocalNamespaces, TransientArena);
614 return llvm::Error::success();
615 });
616}
617
618template <>
619llvm::Error ClangDocBitcodeReader::readBlock(unsigned ID, EnumInfo *I) {
620 llvm::SmallVector<EnumValueInfo, 4> LocalMembers;
621 llvm::SmallVector<Reference> LocalNamespaces;
622
623 return parseBlock(
624 ID, I,
625 [&](unsigned BlockOrCode) -> llvm::Expected<bool> {
626 auto B = readSubBlockIfMatch(BlockOrCode, BI_ENUM_VALUE_BLOCK_ID,
627 LocalMembers);
628 if (!B)
629 return B.takeError();
630 if (*B)
631 return true;
632 return routeReferenceBlock(BlockOrCode, LocalNamespaces, I);
633 },
634 [&]() -> llvm::Error {
635 I->Members = allocateArray(LocalMembers, TransientArena);
636 if (!LocalNamespaces.empty())
637 I->Namespace = allocateArray(LocalNamespaces, TransientArena);
638 return llvm::Error::success();
639 });
640}
641
642template <>
643llvm::Error ClangDocBitcodeReader::readBlock(unsigned ID, BaseRecordInfo *I) {
644 // BaseRecordInfo and FriendInfo are over 256 bytes and require a size.
645 llvm::SmallVector<BaseRecordInfo, 4> LocalBases;
646 llvm::SmallVector<FriendInfo, 4> LocalFriends;
647 llvm::SmallVector<MemberTypeInfo> LocalMembers;
648 llvm::SmallVector<Reference> LocalParents;
649 llvm::SmallVector<Reference> LocalVirtualParents;
650
651 return parseBlock(
652 ID, I,
653 [&](unsigned BlockOrCode) -> llvm::Expected<bool> {
654 auto B = readSubBlockIfMatch(BlockOrCode, BI_MEMBER_TYPE_BLOCK_ID,
655 LocalMembers);
656 if (!B)
657 return B.takeError();
658 if (*B)
659 return true;
660
661 B = readSubBlockIfMatch(BlockOrCode, BI_BASE_RECORD_BLOCK_ID,
662 LocalBases);
663 if (!B)
664 return B.takeError();
665 if (*B)
666 return true;
667
668 B = readSubBlockIfMatch(BlockOrCode, BI_FRIEND_BLOCK_ID, LocalFriends);
669 if (!B)
670 return B.takeError();
671 if (*B)
672 return true;
673
674 llvm::SmallVector<Reference> Dummy;
675 return routeReferenceBlock(
676 BlockOrCode, Dummy, I,
677 {{FieldId::F_parent, &LocalParents},
678 {FieldId::F_vparent, &LocalVirtualParents}});
679 },
680 [&]() -> llvm::Error {
681 if (!LocalMembers.empty())
682 I->Members = allocateArray(LocalMembers, TransientArena);
683 if (!LocalParents.empty())
684 I->Parents = allocateArray(LocalParents, TransientArena);
685 if (!LocalVirtualParents.empty())
686 I->VirtualParents =
687 allocateArray(LocalVirtualParents, TransientArena);
688 I->Bases = allocateArray(LocalBases, TransientArena);
689 I->Friends = allocateArray(LocalFriends, TransientArena);
690 return llvm::Error::success();
691 });
692}
693
694template <>
695llvm::Error ClangDocBitcodeReader::readBlock(unsigned ID, RecordInfo *I) {
696 llvm::SmallVector<BaseRecordInfo, 4> LocalBases;
697 llvm::SmallVector<FriendInfo, 4> LocalFriends;
698 llvm::SmallVector<MemberTypeInfo> LocalMembers;
699 llvm::SmallVector<Reference> LocalParents;
700 llvm::SmallVector<Reference> LocalVirtualParents;
701 llvm::SmallVector<Reference> LocalNamespaces;
702
703 return parseBlock(
704 ID, I,
705 [&](unsigned BlockOrCode) -> llvm::Expected<bool> {
706 auto B = readSubBlockIfMatch(BlockOrCode, BI_MEMBER_TYPE_BLOCK_ID,
707 LocalMembers);
708 if (!B)
709 return B.takeError();
710 if (*B)
711 return true;
712
713 B = readSubBlockIfMatch(BlockOrCode, BI_BASE_RECORD_BLOCK_ID,
714 LocalBases);
715 if (!B)
716 return B.takeError();
717 if (*B)
718 return true;
719
720 B = readSubBlockIfMatch(BlockOrCode, BI_FRIEND_BLOCK_ID, LocalFriends);
721 if (!B)
722 return B.takeError();
723 if (*B)
724 return true;
725
726 return routeReferenceBlock(
727 BlockOrCode, LocalNamespaces, I,
728 {{FieldId::F_parent, &LocalParents},
729 {FieldId::F_vparent, &LocalVirtualParents}});
730 },
731 [&]() -> llvm::Error {
732 if (!LocalMembers.empty())
733 I->Members = allocateArray(LocalMembers, TransientArena);
734 if (!LocalParents.empty())
735 I->Parents = allocateArray(LocalParents, TransientArena);
736 if (!LocalVirtualParents.empty())
737 I->VirtualParents =
738 allocateArray(LocalVirtualParents, TransientArena);
739 if (!LocalNamespaces.empty())
740 I->Namespace = allocateArray(LocalNamespaces, TransientArena);
741 I->Bases = allocateArray(LocalBases, TransientArena);
742 I->Friends = allocateArray(LocalFriends, TransientArena);
743 return llvm::Error::success();
744 });
745}
746
747template <>
748llvm::Error ClangDocBitcodeReader::readBlock(unsigned ID, TemplateInfo *I) {
749 llvm::SmallVector<TemplateParamInfo> LocalParams;
750 llvm::SmallVector<ConstraintInfo> LocalConstraints;
751
752 return parseBlock(
753 ID, I,
754 [&](unsigned BlockOrCode) -> llvm::Expected<bool> {
755 auto B = readSubBlockIfMatch(BlockOrCode, BI_TEMPLATE_PARAM_BLOCK_ID,
756 LocalParams);
757 if (!B)
758 return B.takeError();
759 if (*B)
760 return true;
761
762 B = readSubBlockIfMatch(BlockOrCode, BI_CONSTRAINT_BLOCK_ID,
763 LocalConstraints);
764 if (!B)
765 return B.takeError();
766 if (*B)
767 return true;
768
769 return false;
770 },
771 [&]() -> llvm::Error {
772 I->Params = allocateArray(LocalParams, TransientArena);
773 I->Constraints = allocateArray(LocalConstraints, TransientArena);
774 return llvm::Error::success();
775 },
776 [&](unsigned BlockOrCode) -> llvm::Error {
777 return readRecord(BlockOrCode, I);
778 });
779}
780
781template <>
782llvm::Error ClangDocBitcodeReader::readBlock(unsigned ID,
784 llvm::SmallVector<TemplateParamInfo> LocalParams;
785
786 return parseBlock(
787 ID, I,
788 [&](unsigned BlockOrCode) -> llvm::Expected<bool> {
789 auto B = readSubBlockIfMatch(BlockOrCode, BI_TEMPLATE_PARAM_BLOCK_ID,
790 LocalParams);
791 if (!B)
792 return B.takeError();
793 if (*B)
794 return true;
795
796 return false;
797 },
798 [&]() -> llvm::Error {
799 I->Params = allocateArray(LocalParams, TransientArena);
800 return llvm::Error::success();
801 },
802 [&](unsigned BlockOrCode) -> llvm::Error {
803 return readRecord(BlockOrCode, I);
804 });
805}
806
807static llvm::Error parseRecord(const Record &R, unsigned ID,
808 llvm::StringRef Blob, Reference *I, FieldId &F) {
809 switch (ID) {
810 case REFERENCE_USR:
811 return decodeRecord(R, I->USR, Blob);
812 case REFERENCE_NAME:
813 return decodeRecord(R, I->Name, Blob);
815 return decodeRecord(R, I->QualName, Blob);
816 case REFERENCE_TYPE:
817 return decodeRecord(R, I->RefType, Blob);
818 case REFERENCE_PATH:
819 return decodeRecord(R, I->Path, Blob);
820 case REFERENCE_FIELD:
821 return decodeRecord(R, F, Blob);
822 case REFERENCE_FILE:
823 return decodeRecord(R, I->DocumentationFileName, Blob);
824 default:
825 return llvm::createStringError(llvm::inconvertibleErrorCode(),
826 "invalid field for Reference");
827 }
828}
829
830static llvm::Error parseRecord(const Record &R, unsigned ID,
831 llvm::StringRef Blob, TemplateInfo *I) {
832 // Currently there are no child records of TemplateInfo (only child blocks).
833 return llvm::createStringError(llvm::inconvertibleErrorCode(),
834 "invalid field for TemplateParamInfo");
835}
836
837static llvm::Error parseRecord(const Record &R, unsigned ID,
838 llvm::StringRef Blob,
841 return decodeRecord(R, I->SpecializationOf, Blob);
842 return llvm::createStringError(llvm::inconvertibleErrorCode(),
843 "invalid field for TemplateParamInfo");
844}
845
846static llvm::Error parseRecord(const Record &R, unsigned ID,
847 llvm::StringRef Blob, TemplateParamInfo *I) {
848 if (ID == TEMPLATE_PARAM_CONTENTS)
849 return decodeRecord(R, I->Contents, Blob);
850 return llvm::createStringError(llvm::inconvertibleErrorCode(),
851 "invalid field for TemplateParamInfo");
852}
853
854static llvm::Error parseRecord(const Record &R, unsigned ID,
855 llvm::StringRef Blob, ConceptInfo *I) {
856 switch (ID) {
857 case CONCEPT_USR:
858 return decodeRecord(R, I->USR, Blob);
859 case CONCEPT_NAME:
860 return decodeRecord(R, I->Name, Blob);
861 case CONCEPT_IS_TYPE:
862 return decodeRecord(R, I->IsType, Blob);
864 return decodeRecord(R, I->ConstraintExpression, Blob);
866 return decodeRecord(R, I->DefLoc, Blob);
867 }
868 llvm_unreachable("invalid field for ConceptInfo");
869}
870
871static llvm::Error parseRecord(const Record &R, unsigned ID,
872 llvm::StringRef Blob, ConstraintInfo *I) {
873 if (ID == CONSTRAINT_EXPRESSION)
874 return decodeRecord(R, I->ConstraintExpr, Blob);
875 return llvm::createStringError(llvm::inconvertibleErrorCode(),
876 "invalid field for ConstraintInfo");
877}
878
879static llvm::Error parseRecord(const Record &R, unsigned ID,
880 llvm::StringRef Blob, VarInfo *I) {
881 switch (ID) {
882 case VAR_USR:
883 return decodeRecord(R, I->USR, Blob);
884 case VAR_NAME:
885 return decodeRecord(R, I->Name, Blob);
886 case VAR_DEFLOCATION:
887 return decodeRecord(R, I->DefLoc, Blob);
888 case VAR_IS_STATIC:
889 return decodeRecord(R, I->IsStatic, Blob);
890 default:
891 return llvm::createStringError(llvm::inconvertibleErrorCode(),
892 "invalid field for VarInfo");
893 }
894}
895
896static llvm::Error parseRecord(const Record &R, unsigned ID, StringRef Blob,
897 FriendInfo *F) {
898 if (ID == FRIEND_IS_CLASS) {
899 return decodeRecord(R, F->IsClass, Blob);
900 }
901 return llvm::createStringError(llvm::inconvertibleErrorCode(),
902 "invalid field for Friend");
903}
904
905template <typename, typename = void>
906struct has_description : std::false_type {};
907template <typename T>
908struct has_description<T, std::void_t<decltype(std::declval<T>().Description)>>
909 : std::true_type {};
910
911template <typename T> static llvm::Expected<CommentInfo *> getCommentInfo(T I) {
912 if constexpr (std::is_pointer_v<T>) {
913 using Pointee = std::remove_pointer_t<T>;
914 if constexpr (has_description<Pointee>::value) {
915 auto *NewComment = allocateListNodeTransient<CommentInfo>();
916 I->Description.push_back(*NewComment);
917 return NewComment->Ptr;
918 }
919 }
920 return llvm::createStringError(llvm::inconvertibleErrorCode(),
921 "invalid type cannot contain CommentInfo");
922}
923
924// When readSubBlock encounters a TypeInfo sub-block, it calls addTypeInfo on
925// the parent block to set it. The template specializations define what to do
926// for each supported parent block.
927template <typename T, typename TTypeInfo>
928static llvm::Error addTypeInfo(T I, TTypeInfo &&TI) {
929 return llvm::createStringError(llvm::inconvertibleErrorCode(),
930 "invalid type cannot contain TypeInfo");
931}
932
933template <> llvm::Error addTypeInfo(FunctionInfo *I, TypeInfo &&T) {
934 I->ReturnType = std::move(T);
935 return llvm::Error::success();
936}
937
938template <> llvm::Error addTypeInfo(FriendInfo *I, TypeInfo &&T) {
939 I->ReturnType.emplace(std::move(T));
940 return llvm::Error::success();
941}
942
943template <> llvm::Error addTypeInfo(EnumInfo *I, TypeInfo &&T) {
944 I->BaseType = std::move(T);
945 return llvm::Error::success();
946}
947
948template <> llvm::Error addTypeInfo(TypedefInfo *I, TypeInfo &&T) {
949 I->Underlying = std::move(T);
950 return llvm::Error::success();
951}
952
953template <> llvm::Error addTypeInfo(VarInfo *I, TypeInfo &&T) {
954 I->Type = std::move(T);
955 return llvm::Error::success();
956}
957
958template <typename T>
959static llvm::Error addReference(T I, Reference &&R, FieldId F) {
960 return llvm::createStringError(llvm::inconvertibleErrorCode(),
961 "invalid type cannot contain Reference");
962}
963
964template <> llvm::Error addReference(VarInfo *I, Reference &&R, FieldId F) {
965 return llvm::createStringError(llvm::inconvertibleErrorCode(),
966 "VarInfo cannot contain this Reference");
967}
968
969template <> llvm::Error addReference(TypeInfo *I, Reference &&R, FieldId F) {
970 switch (F) {
971 case FieldId::F_type:
972 I->Type = std::move(R);
973 return llvm::Error::success();
974 default:
975 return llvm::createStringError(llvm::inconvertibleErrorCode(),
976 "invalid type cannot contain Reference");
977 }
978}
979
980template <>
982 switch (F) {
983 case FieldId::F_type:
984 I->Type = std::move(R);
985 return llvm::Error::success();
986 default:
987 return llvm::createStringError(llvm::inconvertibleErrorCode(),
988 "invalid type cannot contain Reference");
989 }
990}
991
992template <>
994 switch (F) {
995 case FieldId::F_type:
996 I->Type = std::move(R);
997 return llvm::Error::success();
998 default:
999 return llvm::createStringError(llvm::inconvertibleErrorCode(),
1000 "invalid type cannot contain Reference");
1001 }
1002}
1003
1004template <> llvm::Error addReference(EnumInfo *I, Reference &&R, FieldId F) {
1005 return llvm::createStringError(llvm::inconvertibleErrorCode(),
1006 "invalid type cannot contain Reference");
1007}
1008
1009template <> llvm::Error addReference(TypedefInfo *I, Reference &&R, FieldId F) {
1010 return llvm::createStringError(llvm::inconvertibleErrorCode(),
1011 "invalid type cannot contain Reference");
1012}
1013
1014template <>
1016 switch (F) {
1018 I->Children.Namespaces.push_back(
1020 return llvm::Error::success();
1022 I->Children.Records.push_back(
1024 return llvm::Error::success();
1025 default:
1026 return llvm::createStringError(llvm::inconvertibleErrorCode(),
1027 "invalid type cannot contain Reference");
1028 }
1029}
1030
1031template <>
1033 switch (F) {
1034 case FieldId::F_parent:
1035 I->Parent = std::move(R);
1036 return llvm::Error::success();
1037 default:
1038 return llvm::createStringError(llvm::inconvertibleErrorCode(),
1039 "invalid type cannot contain Reference");
1040 }
1041}
1042
1043template <> llvm::Error addReference(RecordInfo *I, Reference &&R, FieldId F) {
1044 switch (F) {
1046 I->Children.Records.push_back(
1048 return llvm::Error::success();
1049 default:
1050 return llvm::createStringError(llvm::inconvertibleErrorCode(),
1051 "invalid type cannot contain Reference");
1052 }
1053}
1054
1055template <>
1057 if (F == FieldId::F_concept) {
1058 I->ConceptRef = std::move(R);
1059 return llvm::Error::success();
1060 }
1061 return llvm::createStringError(
1062 llvm::inconvertibleErrorCode(),
1063 "ConstraintInfo cannot contain this Reference");
1064}
1065
1066template <>
1067llvm::Error addReference(FriendInfo *Friend, Reference &&R, FieldId F) {
1068 if (F == FieldId::F_friend) {
1069 Friend->Ref = std::move(R);
1070 return llvm::Error::success();
1071 }
1072 return llvm::createStringError(llvm::inconvertibleErrorCode(),
1073 "Friend cannot contain this Reference");
1074}
1075
1076static auto &getList(ScopeChildren &C, FunctionInfo *) { return C.Functions; }
1077static auto &getList(ScopeChildren &C, EnumInfo *) { return C.Enums; }
1078static auto &getList(ScopeChildren &C, TypedefInfo *) { return C.Typedefs; }
1079static auto &getList(ScopeChildren &C, ConceptInfo *) { return C.Concepts; }
1080static auto &getList(ScopeChildren &C, VarInfo *) { return C.Variables; }
1081
1082template <typename T, typename = void> struct has_children : std::false_type {};
1083template <typename T>
1084struct has_children<T, std::void_t<decltype(std::declval<T>().Children)>>
1085 : std::is_same<decltype(std::declval<T>().Children), ScopeChildren> {};
1086
1087template <typename TargetChild, typename = void>
1088struct is_valid_child : std::false_type {};
1089template <typename TargetChild>
1091 TargetChild, std::void_t<decltype(getList(std::declval<ScopeChildren &>(),
1092 std::declval<TargetChild *>()))>>
1093 : std::true_type {};
1094
1095template <typename Target, typename Child>
1096static void addChild(Target I, Child &&R) {
1097 if constexpr (std::is_pointer_v<Target>) {
1098 using Pointee = std::remove_pointer_t<Target>;
1099 if constexpr (has_children<Pointee>::value) {
1100 using BareChild = std::remove_cv_t<std::remove_reference_t<Child>>;
1101 if constexpr (is_valid_child<BareChild>::value) {
1102 auto *Node =
1103 allocateListNodeTransient<BareChild>(std::forward<Child>(R));
1104 getList(I->Children, Node->Ptr).push_back(*Node);
1105 return;
1106 }
1107 }
1108 }
1109 ExitOnErr(llvm::createStringError(llvm::inconvertibleErrorCode(),
1110 "invalid child type for info"));
1111}
1112
1113template <typename Target, typename Child>
1114static void addChildPtr(Target I, Child *Node) {
1115 if constexpr (std::is_pointer_v<Target>) {
1116 using Pointee = std::remove_pointer_t<Target>;
1117 if constexpr (has_children<Pointee>::value &&
1119 getList(I->Children, Node).push_back(*allocateListNodeTransient(Node));
1120 return;
1121 }
1122 }
1123 ExitOnErr(llvm::createStringError(llvm::inconvertibleErrorCode(),
1124 "invalid child type for info"));
1125}
1126
1127// TemplateParam children. These go into either a TemplateInfo (for template
1128// parameters) or TemplateSpecializationInfo (for the specialization's
1129// parameters).
1130template <typename T> static void addTemplateParam(T I, TemplateParamInfo &&P) {
1131 ExitOnErr(
1132 llvm::createStringError(llvm::inconvertibleErrorCode(),
1133 "invalid container for template parameter"));
1134}
1135
1136// Template info. These apply to either records or functions.
1137template <typename T> static void addTemplate(T I, TemplateInfo &&P) {
1138 ExitOnErr(llvm::createStringError(llvm::inconvertibleErrorCode(),
1139 "invalid container for template info"));
1140}
1141template <> void addTemplate(RecordInfo *I, TemplateInfo &&P) {
1142 I->Template.emplace(std::move(P));
1143}
1144template <> void addTemplate(FunctionInfo *I, TemplateInfo &&P) {
1145 I->Template.emplace(std::move(P));
1146}
1147template <> void addTemplate(ConceptInfo *I, TemplateInfo &&P) {
1148 I->Template = std::move(P);
1149}
1150template <> void addTemplate(FriendInfo *I, TemplateInfo &&P) {
1151 I->Template.emplace(std::move(P));
1152}
1153template <> void addTemplate(TypedefInfo *I, TemplateInfo &&P) {
1154 I->Template.emplace(std::move(P));
1155}
1156
1157// Template specializations go only into template records.
1158template <typename T>
1160 ExitOnErr(llvm::createStringError(
1161 llvm::inconvertibleErrorCode(),
1162 "invalid container for template specialization info"));
1163}
1164template <>
1167 I->Specialization.emplace(std::move(TSI));
1168}
1169
1170template <typename T> static void addConstraint(T I, ConstraintInfo &&C) {
1171 ExitOnErr(llvm::createStringError(llvm::inconvertibleErrorCode(),
1172 "invalid container for constraint info"));
1173}
1174
1175// Read records from bitcode into a given info.
1176template <typename T>
1177llvm::Error ClangDocBitcodeReader::readRecord(unsigned ID, T I) {
1178 Record R;
1179 llvm::StringRef Blob;
1180 llvm::Expected<unsigned> MaybeRecID = Stream.readRecord(ID, R, &Blob);
1181 if (!MaybeRecID)
1182 return MaybeRecID.takeError();
1183 return parseRecord(R, MaybeRecID.get(), Blob, I);
1184}
1185
1186template <>
1187llvm::Error ClangDocBitcodeReader::readRecord(unsigned ID, Reference *I) {
1188 llvm::TimeTraceScope("Reducing infos", "readRecord");
1189 Record R;
1190 llvm::StringRef Blob;
1191 llvm::Expected<unsigned> MaybeRecID = Stream.readRecord(ID, R, &Blob);
1192 if (!MaybeRecID)
1193 return MaybeRecID.takeError();
1194 return parseRecord(R, MaybeRecID.get(), Blob, I, CurrentReferenceField);
1195}
1196
1197// Read a block of records into a single info.
1198
1199template <>
1200llvm::Error ClangDocBitcodeReader::readBlock(unsigned ID, VarInfo *I) {
1201 return readBlockWithNamespace(ID, I);
1202}
1203
1204template <>
1205llvm::Error ClangDocBitcodeReader::readBlock(unsigned ID, TypedefInfo *I) {
1206 return readBlockWithNamespace(ID, I);
1207}
1208
1209template <>
1210llvm::Error ClangDocBitcodeReader::readBlock(unsigned ID, NamespaceInfo *I) {
1211 return readBlockWithNamespace(ID, I);
1212}
1213
1214template <typename T>
1215llvm::Error ClangDocBitcodeReader::readBlockWithNamespace(unsigned ID, T I) {
1216 llvm::SmallVector<Reference> LocalNamespaces;
1217 return parseBlock(
1218 ID, I,
1219 [&](unsigned BlockOrCode) -> llvm::Expected<bool> {
1220 return routeReferenceBlock(BlockOrCode, LocalNamespaces, I);
1221 },
1222 [&]() -> llvm::Error {
1223 if (!LocalNamespaces.empty())
1224 I->Namespace = allocateArray(LocalNamespaces, TransientArena);
1225 return llvm::Error::success();
1226 });
1227}
1228
1229template <typename T>
1230llvm::Error ClangDocBitcodeReader::readBlock(unsigned ID, T I) {
1231 return parseBlock(
1232 ID, I, [](unsigned BlockOrCode) -> llvm::Expected<bool> { return false; },
1233 []() -> llvm::Error { return llvm::Error::success(); },
1234 [&](unsigned BlockOrCode) -> llvm::Error {
1235 return readRecord(BlockOrCode, I);
1236 });
1237}
1238
1239template <>
1240llvm::Error ClangDocBitcodeReader::readBlock(unsigned ID, FriendInfo *I) {
1241 llvm::SmallVector<FieldTypeInfo, 4> LocalParams;
1242
1243 return parseBlock(
1244 ID, I,
1245 [&](unsigned BlockOrCode) -> llvm::Expected<bool> {
1246 auto B = readSubBlockIfMatch(BlockOrCode, BI_FIELD_TYPE_BLOCK_ID,
1247 LocalParams);
1248 if (!B)
1249 return B.takeError();
1250 if (*B)
1251 return true;
1252
1253 return false;
1254 },
1255 [&]() -> llvm::Error {
1256 if (!LocalParams.empty())
1258 return llvm::Error::success();
1259 },
1260 [&](unsigned BlockOrCode) -> llvm::Error {
1261 return readRecord(BlockOrCode, I);
1262 });
1263}
1264
1265template <typename InfoType, typename T, typename Callback>
1266llvm::Error ClangDocBitcodeReader::handleSubBlock(unsigned ID, T Parent,
1267 Callback Function) {
1268 InfoType Info;
1269 if (auto Err = readBlock(ID, &Info))
1270 return Err;
1271 if constexpr (std::is_void_v<
1272 std::invoke_result_t<Callback, T, InfoType &&>>) {
1273 Function(Parent, std::move(Info));
1274 return llvm::Error::success();
1275 } else {
1276 return Function(Parent, std::move(Info));
1277 }
1278}
1279
1280template <typename InfoType, typename T>
1281llvm::Error ClangDocBitcodeReader::handleSubBlock(unsigned ID, T Parent) {
1283 if (auto Err = readBlock(ID, Info))
1284 return Err;
1285 addChildPtr(Parent, Info);
1286 return llvm::Error::success();
1287}
1288
1289template <typename T>
1290llvm::Error ClangDocBitcodeReader::readSubBlock(unsigned ID, T I) {
1291 llvm::TimeTraceScope("Reducing infos", "readSubBlock");
1292
1293 static auto CreateAddFunc = [](auto AddFunc) {
1294 return [AddFunc](auto Parent, auto Child) {
1295 return AddFunc(Parent, std::move(Child));
1296 };
1297 };
1298
1299 switch (ID) {
1300 // Blocks can only have certain types of sub blocks.
1301 case BI_COMMENT_BLOCK_ID: {
1302 auto Comment = getCommentInfo(I);
1303 if (!Comment)
1304 return Comment.takeError();
1305 if (auto Err = readBlock(ID, Comment.get()))
1306 return Err;
1307 return llvm::Error::success();
1308 }
1309 case BI_TYPE_BLOCK_ID: {
1310 return handleSubBlock<TypeInfo>(ID, I,
1311 CreateAddFunc(addTypeInfo<T, TypeInfo>));
1312 }
1314 return handleSubBlock<FieldTypeInfo>(
1315 ID, I, CreateAddFunc(addTypeInfo<T, FieldTypeInfo>));
1316 }
1318 return handleSubBlock<MemberTypeInfo>(
1319 ID, I, CreateAddFunc(addTypeInfo<T, MemberTypeInfo>));
1320 }
1321 case BI_REFERENCE_BLOCK_ID: {
1322 Reference R;
1323 if (auto Err = readBlock(ID, &R))
1324 return Err;
1325 if (auto Err = addReference(I, std::move(R), CurrentReferenceField))
1326 return Err;
1327 return llvm::Error::success();
1328 }
1329 case BI_FUNCTION_BLOCK_ID: {
1330 return handleSubBlock<FunctionInfo>(ID, I);
1331 }
1333 return handleSubBlock<BaseRecordInfo>(
1334 ID, I, CreateAddFunc(addChild<T, BaseRecordInfo>));
1335 }
1336 case BI_ENUM_BLOCK_ID: {
1337 return handleSubBlock<EnumInfo>(ID, I);
1338 }
1340 return handleSubBlock<EnumValueInfo>(
1341 ID, I, CreateAddFunc(addChild<T, EnumValueInfo>));
1342 }
1343 case BI_TEMPLATE_BLOCK_ID: {
1344 return handleSubBlock<TemplateInfo>(ID, I, CreateAddFunc(addTemplate<T>));
1345 }
1347 return handleSubBlock<TemplateSpecializationInfo>(
1348 ID, I, CreateAddFunc(addTemplateSpecialization<T>));
1349 }
1351 return handleSubBlock<TemplateParamInfo>(
1352 ID, I, CreateAddFunc(addTemplateParam<T>));
1353 }
1354 case BI_TYPEDEF_BLOCK_ID: {
1355 return handleSubBlock<TypedefInfo>(ID, I);
1356 }
1358 return handleSubBlock<ConstraintInfo>(ID, I,
1359 CreateAddFunc(addConstraint<T>));
1360 }
1361 case BI_CONCEPT_BLOCK_ID: {
1362 return handleSubBlock<ConceptInfo>(ID, I);
1363 }
1364 case BI_VAR_BLOCK_ID: {
1365 return handleSubBlock<VarInfo>(ID, I);
1366 }
1367 case BI_FRIEND_BLOCK_ID: {
1368 return handleSubBlock<FriendInfo>(ID, I,
1369 CreateAddFunc(addChild<T, FriendInfo>));
1370 }
1371 default:
1372 return llvm::createStringError(llvm::inconvertibleErrorCode(),
1373 "invalid subblock type");
1374 }
1375}
1376
1377llvm::Expected<ClangDocBitcodeReader::Cursor>
1378ClangDocBitcodeReader::skipUntilRecordOrBlock(unsigned &BlockOrRecordID) {
1379 llvm::TimeTraceScope("Reducing infos", "skipUntilRecordOrBlock");
1380 BlockOrRecordID = 0;
1381
1382 while (!Stream.AtEndOfStream()) {
1383 Expected<unsigned> Code = Stream.ReadCode();
1384 if (!Code)
1385 return Code.takeError();
1386
1387 if (*Code >= static_cast<unsigned>(llvm::bitc::FIRST_APPLICATION_ABBREV)) {
1388 BlockOrRecordID = *Code;
1389 return Cursor::Record;
1390 }
1391 switch (static_cast<llvm::bitc::FixedAbbrevIDs>(*Code)) {
1392 case llvm::bitc::ENTER_SUBBLOCK:
1393 if (Expected<unsigned> MaybeID = Stream.ReadSubBlockID())
1394 BlockOrRecordID = MaybeID.get();
1395 else
1396 return MaybeID.takeError();
1397 return Cursor::BlockBegin;
1398 case llvm::bitc::END_BLOCK:
1399 if (Stream.ReadBlockEnd())
1400 return llvm::createStringError(llvm::inconvertibleErrorCode(),
1401 "error at end of block");
1402 return Cursor::BlockEnd;
1403 case llvm::bitc::DEFINE_ABBREV:
1404 if (llvm::Error Err = Stream.ReadAbbrevRecord())
1405 return std::move(Err);
1406 continue;
1407 case llvm::bitc::UNABBREV_RECORD:
1408 return llvm::createStringError(llvm::inconvertibleErrorCode(),
1409 "found unabbreviated record");
1410 case llvm::bitc::FIRST_APPLICATION_ABBREV:
1411 llvm_unreachable("Unexpected abbrev id.");
1412 }
1413 }
1414 llvm_unreachable("Premature stream end.");
1415}
1416
1417llvm::Error ClangDocBitcodeReader::validateStream() {
1418 if (Stream.AtEndOfStream())
1419 return llvm::createStringError(llvm::inconvertibleErrorCode(),
1420 "premature end of stream");
1421
1422 // Sniff for the signature.
1423 for (int Idx = 0; Idx != 4; ++Idx) {
1424 Expected<llvm::SimpleBitstreamCursor::word_t> MaybeRead = Stream.Read(8);
1425 if (!MaybeRead)
1426 return MaybeRead.takeError();
1427 if (MaybeRead.get() != BitCodeConstants::Signature[Idx])
1428 return llvm::createStringError(llvm::inconvertibleErrorCode(),
1429 "invalid bitcode signature");
1430 }
1431 return llvm::Error::success();
1432}
1433
1434llvm::Error ClangDocBitcodeReader::readBlockInfoBlock() {
1435 llvm::TimeTraceScope("Reducing infos", "readBlockInfoBlock");
1436 Expected<std::optional<llvm::BitstreamBlockInfo>> MaybeBlockInfo =
1437 Stream.ReadBlockInfoBlock();
1438 if (!MaybeBlockInfo)
1439 return MaybeBlockInfo.takeError();
1440 BlockInfo = MaybeBlockInfo.get();
1441 if (!BlockInfo)
1442 return llvm::createStringError(llvm::inconvertibleErrorCode(),
1443 "unable to parse BlockInfoBlock");
1444 Stream.setBlockInfo(&*BlockInfo);
1445 return llvm::Error::success();
1446}
1447
1448template <typename T>
1449llvm::Expected<Info *> ClangDocBitcodeReader::createInfo(unsigned ID) {
1450 llvm::TimeTraceScope("Reducing infos", "createInfo");
1451 auto *I = doc::allocateTransient<T>();
1452 if (auto Err = readBlock(ID, I))
1453 return std::move(Err);
1454 return I;
1455}
1456
1457llvm::Expected<Info *> ClangDocBitcodeReader::readBlockToInfo(unsigned ID) {
1458 llvm::TimeTraceScope("Reducing infos", "readBlockToInfo");
1459 switch (ID) {
1461 return createInfo<NamespaceInfo>(ID);
1462 case BI_RECORD_BLOCK_ID:
1463 return createInfo<RecordInfo>(ID);
1464 case BI_ENUM_BLOCK_ID:
1465 return createInfo<EnumInfo>(ID);
1467 return createInfo<TypedefInfo>(ID);
1469 return createInfo<ConceptInfo>(ID);
1471 return createInfo<FunctionInfo>(ID);
1472 case BI_VAR_BLOCK_ID:
1473 return createInfo<VarInfo>(ID);
1474 case BI_FRIEND_BLOCK_ID:
1475 return createInfo<FriendInfo>(ID);
1476 default:
1477 return llvm::createStringError(llvm::inconvertibleErrorCode(),
1478 "cannot create info");
1479 }
1480}
1481
1482// Entry point
1483llvm::Expected<std::vector<Info *>> ClangDocBitcodeReader::readBitcode() {
1484 std::vector<Info *> Infos;
1485 if (auto Err = validateStream())
1486 return std::move(Err);
1487
1488 // Read the top level blocks.
1489 while (!Stream.AtEndOfStream()) {
1490 Expected<unsigned> MaybeCode = Stream.ReadCode();
1491 if (!MaybeCode)
1492 return MaybeCode.takeError();
1493 if (MaybeCode.get() != llvm::bitc::ENTER_SUBBLOCK)
1494 return llvm::createStringError(llvm::inconvertibleErrorCode(),
1495 "no blocks in input");
1496 Expected<unsigned> MaybeID = Stream.ReadSubBlockID();
1497 if (!MaybeID)
1498 return MaybeID.takeError();
1499 unsigned ID = MaybeID.get();
1500 switch (ID) {
1501 // NamedType and Comment blocks should not appear at the top level
1502 case BI_TYPE_BLOCK_ID:
1507 return llvm::createStringError(llvm::inconvertibleErrorCode(),
1508 "invalid top level block");
1510 case BI_RECORD_BLOCK_ID:
1511 case BI_ENUM_BLOCK_ID:
1514 case BI_VAR_BLOCK_ID:
1515 case BI_FRIEND_BLOCK_ID:
1516 case BI_FUNCTION_BLOCK_ID: {
1517 auto InfoOrErr = readBlockToInfo(ID);
1518 if (!InfoOrErr)
1519 return InfoOrErr.takeError();
1520 Infos.emplace_back(std::move(InfoOrErr.get()));
1521 continue;
1522 }
1524 if (auto Err = readBlock(ID, VersionNumber))
1525 return std::move(Err);
1526 continue;
1527 case llvm::bitc::BLOCKINFO_BLOCK_ID:
1528 if (auto Err = readBlockInfoBlock())
1529 return std::move(Err);
1530 continue;
1531 default:
1532 if (llvm::Error Err = Stream.SkipBlock())
1533 return std::move(Err);
1534 continue;
1535 }
1536 }
1537 return std::move(Infos);
1538}
1539
1540} // namespace doc
1541} // namespace clang
static llvm::ExitOnError ExitOnErr
llvm::Expected< std::vector< Info * > > readBitcode()
static llvm::Error parseRecord(const Record &R, unsigned ID, llvm::StringRef Blob, const unsigned VersionNo)
static llvm::Expected< CommentInfo * > getCommentInfo(T I)
llvm::simple_ilist< InfoNode< T > > DocList
@ TEMPLATE_SPECIALIZATION_OF
@ MEMBER_TYPE_IS_TEMPLATE
@ TEMPLATE_PARAM_CONTENTS
@ CONCEPT_CONSTRAINT_EXPRESSION
llvm::SmallVector< uint64_t, 1024 > Record
static llvm::Error decodeRecord(const Record &R, llvm::SmallVectorImpl< char > &Field, llvm::StringRef Blob)
T * allocateTransient(Args &&...args)
static const unsigned VersionNumber
CommentKind stringToCommentKind(llvm::StringRef KindStr)
static llvm::Error addTypeInfo(T I, TTypeInfo &&TI)
static void addTemplateSpecialization(T I, TemplateSpecializationInfo &&TSI)
static void addChildPtr(Target I, Child *Node)
static void addTemplate(T I, TemplateInfo &&P)
static void addChild(Target I, Child &&R)
thread_local llvm::BumpPtrAllocator TransientArena
StringRef internString(const Twine &T)
llvm::ArrayRef< T > allocateArray(llvm::SmallVectorImpl< T > &V, llvm::BumpPtrAllocator &Alloc)
InfoNode< T > * allocateListNodeTransient(Args &&...args)
static auto & getList(ScopeChildren &C, FunctionInfo *)
static llvm::Error addReference(T I, Reference &&R, FieldId F)
std::array< uint8_t, 20 > SymbolID
static void addTemplateParam(T I, TemplateParamInfo &&P)
@ BI_CONSTRAINT_BLOCK_ID
@ BI_ENUM_VALUE_BLOCK_ID
@ BI_TEMPLATE_SPECIALIZATION_BLOCK_ID
@ BI_NAMESPACE_BLOCK_ID
@ BI_TEMPLATE_PARAM_BLOCK_ID
@ BI_MEMBER_TYPE_BLOCK_ID
@ BI_BASE_RECORD_BLOCK_ID
@ BI_FIELD_TYPE_BLOCK_ID
@ BI_REFERENCE_BLOCK_ID
static void addConstraint(T I, ConstraintInfo &&C)
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
static constexpr int USRHashSize
static constexpr unsigned char Signature[4]
ArrayRef< StringRef > Args
ArrayRef< CommentInfo > Children
ArrayRef< StringRef > AttrKeys
ArrayRef< StringRef > AttrValues
llvm::ArrayRef< EnumValueInfo > Members
std::optional< TypeInfo > BaseType
std::optional< TypeInfo > ReturnType
llvm::ArrayRef< FieldTypeInfo > Params
std::optional< TemplateInfo > Template
llvm::ArrayRef< FieldTypeInfo > Params
std::optional< TemplateInfo > Template
A base struct for Infos.
llvm::ArrayRef< Reference > Namespace
llvm::ArrayRef< BaseRecordInfo > Bases
llvm::ArrayRef< FriendInfo > Friends
llvm::ArrayRef< Reference > VirtualParents
std::optional< TemplateInfo > Template
llvm::ArrayRef< Reference > Parents
llvm::ArrayRef< MemberTypeInfo > Members
DocList< Reference > Records
DocList< Reference > Namespaces
DocList< Location > Loc
std::optional< Location > DefLoc
llvm::ArrayRef< TemplateParamInfo > Params
llvm::ArrayRef< ConstraintInfo > Constraints
std::optional< TemplateSpecializationInfo > Specialization
llvm::ArrayRef< TemplateParamInfo > Params
std::optional< TemplateInfo > Template