clang-tools 22.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
16namespace clang {
17namespace doc {
18
19static llvm::ExitOnError ExitOnErr("clang-doc error: ");
20
21using Record = llvm::SmallVector<uint64_t, 1024>;
22
23// This implements decode for SmallString.
24static llvm::Error decodeRecord(const Record &R,
26 llvm::StringRef Blob) {
27 Field.assign(Blob.begin(), Blob.end());
28 return llvm::Error::success();
29}
30
31static llvm::Error decodeRecord(const Record &R, SymbolID &Field,
32 llvm::StringRef Blob) {
34 return llvm::createStringError(llvm::inconvertibleErrorCode(),
35 "incorrect USR size");
36
37 // First position in the record is the length of the following array, so we
38 // copy the following elements to the field.
39 for (int I = 0, E = R[0]; I < E; ++I)
40 Field[I] = R[I + 1];
41 return llvm::Error::success();
42}
43
44static llvm::Error decodeRecord(const Record &R, bool &Field,
45 llvm::StringRef Blob) {
46 Field = R[0] != 0;
47 return llvm::Error::success();
48}
49
50static llvm::Error decodeRecord(const Record &R, AccessSpecifier &Field,
51 llvm::StringRef Blob) {
52 switch (R[0]) {
53 case AS_public:
54 case AS_private:
55 case AS_protected:
56 case AS_none:
57 Field = (AccessSpecifier)R[0];
58 return llvm::Error::success();
59 }
60 llvm_unreachable("invalid value for AccessSpecifier");
61}
62
63static llvm::Error decodeRecord(const Record &R, TagTypeKind &Field,
64 llvm::StringRef Blob) {
65 switch (static_cast<TagTypeKind>(R[0])) {
66 case TagTypeKind::Struct:
67 case TagTypeKind::Interface:
68 case TagTypeKind::Union:
69 case TagTypeKind::Class:
70 case TagTypeKind::Enum:
71 Field = static_cast<TagTypeKind>(R[0]);
72 return llvm::Error::success();
73 }
74 return llvm::createStringError(llvm::inconvertibleErrorCode(),
75 "invalid value for TagTypeKind");
76}
77
78static llvm::Error decodeRecord(const Record &R, std::optional<Location> &Field,
79 llvm::StringRef Blob) {
80 if (R[0] > INT_MAX)
81 return llvm::createStringError(llvm::inconvertibleErrorCode(),
82 "integer too large to parse");
83 Field.emplace(static_cast<int>(R[0]), static_cast<int>(R[1]), Blob,
84 static_cast<bool>(R[2]));
85 return llvm::Error::success();
86}
87
88static llvm::Error decodeRecord(const Record &R, InfoType &Field,
89 llvm::StringRef Blob) {
90 switch (auto IT = static_cast<InfoType>(R[0])) {
100 Field = IT;
101 return llvm::Error::success();
102 }
103 return llvm::createStringError(llvm::inconvertibleErrorCode(),
104 "invalid value for InfoType");
105}
106
107static llvm::Error decodeRecord(const Record &R, FieldId &Field,
108 llvm::StringRef Blob) {
109 switch (auto F = static_cast<FieldId>(R[0])) {
113 case FieldId::F_type:
119 Field = F;
120 return llvm::Error::success();
121 }
122 return llvm::createStringError(llvm::inconvertibleErrorCode(),
123 "invalid value for FieldId");
124}
125
126static llvm::Error
128 llvm::SmallVectorImpl<llvm::SmallString<16>> &Field,
129 llvm::StringRef Blob) {
130 Field.push_back(Blob);
131 return llvm::Error::success();
132}
133
134static llvm::Error decodeRecord(const Record &R,
136 llvm::StringRef Blob) {
137 if (R[0] > INT_MAX)
138 return llvm::createStringError(llvm::inconvertibleErrorCode(),
139 "integer too large to parse");
140 Field.emplace_back(static_cast<int>(R[0]), static_cast<int>(R[1]), Blob,
141 static_cast<bool>(R[2]));
142 return llvm::Error::success();
143}
144
145static llvm::Error parseRecord(const Record &R, unsigned ID,
146 llvm::StringRef Blob, const unsigned VersionNo) {
147 if (ID == VERSION && R[0] == VersionNo)
148 return llvm::Error::success();
149 return llvm::createStringError(llvm::inconvertibleErrorCode(),
150 "mismatched bitcode version number");
151}
152
153static llvm::Error parseRecord(const Record &R, unsigned ID,
154 llvm::StringRef Blob, NamespaceInfo *I) {
155 switch (ID) {
156 case NAMESPACE_USR:
157 return decodeRecord(R, I->USR, Blob);
158 case NAMESPACE_NAME:
159 return decodeRecord(R, I->Name, Blob);
160 case NAMESPACE_PATH:
161 return decodeRecord(R, I->Path, Blob);
162 default:
163 return llvm::createStringError(llvm::inconvertibleErrorCode(),
164 "invalid field for NamespaceInfo");
165 }
166}
167
168static llvm::Error parseRecord(const Record &R, unsigned ID,
169 llvm::StringRef Blob, RecordInfo *I) {
170 switch (ID) {
171 case RECORD_USR:
172 return decodeRecord(R, I->USR, Blob);
173 case RECORD_NAME:
174 return decodeRecord(R, I->Name, Blob);
175 case RECORD_PATH:
176 return decodeRecord(R, I->Path, Blob);
178 return decodeRecord(R, I->DefLoc, Blob);
179 case RECORD_LOCATION:
180 return decodeRecord(R, I->Loc, Blob);
181 case RECORD_TAG_TYPE:
182 return decodeRecord(R, I->TagType, Blob);
184 return decodeRecord(R, I->IsTypeDef, Blob);
186 return decodeRecord(R, I->MangledName, Blob);
187 default:
188 return llvm::createStringError(llvm::inconvertibleErrorCode(),
189 "invalid field for RecordInfo");
190 }
191}
192
193static llvm::Error parseRecord(const Record &R, unsigned ID,
194 llvm::StringRef Blob, BaseRecordInfo *I) {
195 switch (ID) {
196 case BASE_RECORD_USR:
197 return decodeRecord(R, I->USR, Blob);
198 case BASE_RECORD_NAME:
199 return decodeRecord(R, I->Name, Blob);
200 case BASE_RECORD_PATH:
201 return decodeRecord(R, I->Path, Blob);
203 return decodeRecord(R, I->TagType, Blob);
205 return decodeRecord(R, I->IsVirtual, Blob);
207 return decodeRecord(R, I->Access, Blob);
209 return decodeRecord(R, I->IsParent, Blob);
210 default:
211 return llvm::createStringError(llvm::inconvertibleErrorCode(),
212 "invalid field for BaseRecordInfo");
213 }
214}
215
216static llvm::Error parseRecord(const Record &R, unsigned ID,
217 llvm::StringRef Blob, EnumInfo *I) {
218 switch (ID) {
219 case ENUM_USR:
220 return decodeRecord(R, I->USR, Blob);
221 case ENUM_NAME:
222 return decodeRecord(R, I->Name, Blob);
223 case ENUM_DEFLOCATION:
224 return decodeRecord(R, I->DefLoc, Blob);
225 case ENUM_LOCATION:
226 return decodeRecord(R, I->Loc, Blob);
227 case ENUM_SCOPED:
228 return decodeRecord(R, I->Scoped, Blob);
229 default:
230 return llvm::createStringError(llvm::inconvertibleErrorCode(),
231 "invalid field for EnumInfo");
232 }
233}
234
235static llvm::Error parseRecord(const Record &R, unsigned ID,
236 llvm::StringRef Blob, TypedefInfo *I) {
237 switch (ID) {
238 case TYPEDEF_USR:
239 return decodeRecord(R, I->USR, Blob);
240 case TYPEDEF_NAME:
241 return decodeRecord(R, I->Name, Blob);
243 return decodeRecord(R, I->DefLoc, Blob);
244 case TYPEDEF_IS_USING:
245 return decodeRecord(R, I->IsUsing, Blob);
246 default:
247 return llvm::createStringError(llvm::inconvertibleErrorCode(),
248 "invalid field for TypedefInfo");
249 }
250}
251
252static llvm::Error parseRecord(const Record &R, unsigned ID,
253 llvm::StringRef Blob, EnumValueInfo *I) {
254 switch (ID) {
255 case ENUM_VALUE_NAME:
256 return decodeRecord(R, I->Name, Blob);
257 case ENUM_VALUE_VALUE:
258 return decodeRecord(R, I->Value, Blob);
259 case ENUM_VALUE_EXPR:
260 return decodeRecord(R, I->ValueExpr, Blob);
261 default:
262 return llvm::createStringError(llvm::inconvertibleErrorCode(),
263 "invalid field for EnumValueInfo");
264 }
265}
266
267static llvm::Error parseRecord(const Record &R, unsigned ID,
268 llvm::StringRef Blob, FunctionInfo *I) {
269 switch (ID) {
270 case FUNCTION_USR:
271 return decodeRecord(R, I->USR, Blob);
272 case FUNCTION_NAME:
273 return decodeRecord(R, I->Name, Blob);
275 return decodeRecord(R, I->DefLoc, Blob);
277 return decodeRecord(R, I->Loc, Blob);
278 case FUNCTION_ACCESS:
279 return decodeRecord(R, I->Access, Blob);
281 return decodeRecord(R, I->IsMethod, Blob);
283 return decodeRecord(R, I->IsStatic, Blob);
284 default:
285 return llvm::createStringError(llvm::inconvertibleErrorCode(),
286 "invalid field for FunctionInfo");
287 }
288}
289
290static llvm::Error parseRecord(const Record &R, unsigned ID,
291 llvm::StringRef Blob, TypeInfo *I) {
292 switch (ID) {
293 case TYPE_IS_BUILTIN:
294 return decodeRecord(R, I->IsBuiltIn, Blob);
295 case TYPE_IS_TEMPLATE:
296 return decodeRecord(R, I->IsTemplate, Blob);
297 default:
298 return llvm::createStringError(llvm::inconvertibleErrorCode(),
299 "invalid field for TypeInfo");
300 }
301}
302
303static llvm::Error parseRecord(const Record &R, unsigned ID,
304 llvm::StringRef Blob, FieldTypeInfo *I) {
305 switch (ID) {
306 case FIELD_TYPE_NAME:
307 return decodeRecord(R, I->Name, Blob);
309 return decodeRecord(R, I->DefaultValue, Blob);
311 return decodeRecord(R, I->IsBuiltIn, Blob);
313 return decodeRecord(R, I->IsTemplate, Blob);
314 default:
315 return llvm::createStringError(llvm::inconvertibleErrorCode(),
316 "invalid field for TypeInfo");
317 }
318}
319
320static llvm::Error parseRecord(const Record &R, unsigned ID,
321 llvm::StringRef Blob, MemberTypeInfo *I) {
322 switch (ID) {
323 case MEMBER_TYPE_NAME:
324 return decodeRecord(R, I->Name, Blob);
326 return decodeRecord(R, I->Access, Blob);
328 return decodeRecord(R, I->IsStatic, Blob);
330 return decodeRecord(R, I->IsBuiltIn, Blob);
332 return decodeRecord(R, I->IsTemplate, Blob);
333 default:
334 return llvm::createStringError(llvm::inconvertibleErrorCode(),
335 "invalid field for MemberTypeInfo");
336 }
337}
338
339static llvm::Error parseRecord(const Record &R, unsigned ID,
340 llvm::StringRef Blob, CommentInfo *I) {
341 llvm::SmallString<16> KindStr;
342 switch (ID) {
343 case COMMENT_KIND:
344 if (llvm::Error Err = decodeRecord(R, KindStr, Blob))
345 return Err;
346 I->Kind = stringToCommentKind(KindStr);
347 return llvm::Error::success();
348 case COMMENT_TEXT:
349 return decodeRecord(R, I->Text, Blob);
350 case COMMENT_NAME:
351 return decodeRecord(R, I->Name, Blob);
353 return decodeRecord(R, I->Direction, Blob);
355 return decodeRecord(R, I->ParamName, Blob);
357 return decodeRecord(R, I->CloseName, Blob);
358 case COMMENT_ATTRKEY:
359 return decodeRecord(R, I->AttrKeys, Blob);
360 case COMMENT_ATTRVAL:
361 return decodeRecord(R, I->AttrValues, Blob);
362 case COMMENT_ARG:
363 return decodeRecord(R, I->Args, Blob);
365 return decodeRecord(R, I->SelfClosing, Blob);
366 case COMMENT_EXPLICIT:
367 return decodeRecord(R, I->Explicit, Blob);
368 default:
369 return llvm::createStringError(llvm::inconvertibleErrorCode(),
370 "invalid field for CommentInfo");
371 }
372}
373
374static llvm::Error parseRecord(const Record &R, unsigned ID,
375 llvm::StringRef Blob, Reference *I, FieldId &F) {
376 switch (ID) {
377 case REFERENCE_USR:
378 return decodeRecord(R, I->USR, Blob);
379 case REFERENCE_NAME:
380 return decodeRecord(R, I->Name, Blob);
382 return decodeRecord(R, I->QualName, Blob);
383 case REFERENCE_TYPE:
384 return decodeRecord(R, I->RefType, Blob);
385 case REFERENCE_PATH:
386 return decodeRecord(R, I->Path, Blob);
387 case REFERENCE_FIELD:
388 return decodeRecord(R, F, Blob);
389 case REFERENCE_FILE:
390 return decodeRecord(R, I->DocumentationFileName, Blob);
391 default:
392 return llvm::createStringError(llvm::inconvertibleErrorCode(),
393 "invalid field for Reference");
394 }
395}
396
397static llvm::Error parseRecord(const Record &R, unsigned ID,
398 llvm::StringRef Blob, TemplateInfo *I) {
399 // Currently there are no child records of TemplateInfo (only child blocks).
400 return llvm::createStringError(llvm::inconvertibleErrorCode(),
401 "invalid field for TemplateParamInfo");
402}
403
404static llvm::Error parseRecord(const Record &R, unsigned ID,
405 llvm::StringRef Blob,
408 return decodeRecord(R, I->SpecializationOf, Blob);
409 return llvm::createStringError(llvm::inconvertibleErrorCode(),
410 "invalid field for TemplateParamInfo");
411}
412
413static llvm::Error parseRecord(const Record &R, unsigned ID,
414 llvm::StringRef Blob, TemplateParamInfo *I) {
415 if (ID == TEMPLATE_PARAM_CONTENTS)
416 return decodeRecord(R, I->Contents, Blob);
417 return llvm::createStringError(llvm::inconvertibleErrorCode(),
418 "invalid field for TemplateParamInfo");
419}
420
421static llvm::Error parseRecord(const Record &R, unsigned ID,
422 llvm::StringRef Blob, ConceptInfo *I) {
423 switch (ID) {
424 case CONCEPT_USR:
425 return decodeRecord(R, I->USR, Blob);
426 case CONCEPT_NAME:
427 return decodeRecord(R, I->Name, Blob);
428 case CONCEPT_IS_TYPE:
429 return decodeRecord(R, I->IsType, Blob);
431 return decodeRecord(R, I->ConstraintExpression, Blob);
432 }
433 llvm_unreachable("invalid field for ConceptInfo");
434}
435
436static llvm::Error parseRecord(const Record &R, unsigned ID,
437 llvm::StringRef Blob, ConstraintInfo *I) {
438 if (ID == CONSTRAINT_EXPRESSION)
439 return decodeRecord(R, I->ConstraintExpr, Blob);
440 return llvm::createStringError(llvm::inconvertibleErrorCode(),
441 "invalid field for ConstraintInfo");
442}
443
444static llvm::Error parseRecord(const Record &R, unsigned ID,
445 llvm::StringRef Blob, VarInfo *I) {
446 switch (ID) {
447 case VAR_USR:
448 return decodeRecord(R, I->USR, Blob);
449 case VAR_NAME:
450 return decodeRecord(R, I->Name, Blob);
451 case VAR_DEFLOCATION:
452 return decodeRecord(R, I->DefLoc, Blob);
453 case VAR_IS_STATIC:
454 return decodeRecord(R, I->IsStatic, Blob);
455 default:
456 return llvm::createStringError(llvm::inconvertibleErrorCode(),
457 "invalid field for VarInfo");
458 }
459}
460
461static llvm::Error parseRecord(const Record &R, unsigned ID, StringRef Blob,
462 FriendInfo *F) {
463 if (ID == FRIEND_IS_CLASS) {
464 return decodeRecord(R, F->IsClass, Blob);
465 }
466 return llvm::createStringError(llvm::inconvertibleErrorCode(),
467 "invalid field for Friend");
468}
469
470template <typename T> static llvm::Expected<CommentInfo *> getCommentInfo(T I) {
471 return llvm::createStringError(llvm::inconvertibleErrorCode(),
472 "invalid type cannot contain CommentInfo");
473}
474
475template <> llvm::Expected<CommentInfo *> getCommentInfo(FunctionInfo *I) {
476 return &I->Description.emplace_back();
477}
478
479template <> llvm::Expected<CommentInfo *> getCommentInfo(NamespaceInfo *I) {
480 return &I->Description.emplace_back();
481}
482
483template <> llvm::Expected<CommentInfo *> getCommentInfo(RecordInfo *I) {
484 return &I->Description.emplace_back();
485}
486
487template <> llvm::Expected<CommentInfo *> getCommentInfo(MemberTypeInfo *I) {
488 return &I->Description.emplace_back();
489}
490
491template <> llvm::Expected<CommentInfo *> getCommentInfo(EnumInfo *I) {
492 return &I->Description.emplace_back();
493}
494
495template <> llvm::Expected<CommentInfo *> getCommentInfo(TypedefInfo *I) {
496 return &I->Description.emplace_back();
497}
498
499template <> llvm::Expected<CommentInfo *> getCommentInfo(EnumValueInfo *I) {
500 return &I->Description.emplace_back();
501}
502
503template <> llvm::Expected<CommentInfo *> getCommentInfo(CommentInfo *I) {
504 I->Children.emplace_back(std::make_unique<CommentInfo>());
505 return I->Children.back().get();
506}
507
508template <> llvm::Expected<CommentInfo *> getCommentInfo(ConceptInfo *I) {
509 return &I->Description.emplace_back();
510}
511
512template <> Expected<CommentInfo *> getCommentInfo(VarInfo *I) {
513 return &I->Description.emplace_back();
514}
515
516// When readSubBlock encounters a TypeInfo sub-block, it calls addTypeInfo on
517// the parent block to set it. The template specializations define what to do
518// for each supported parent block.
519template <typename T, typename TTypeInfo>
520static llvm::Error addTypeInfo(T I, TTypeInfo &&TI) {
521 return llvm::createStringError(llvm::inconvertibleErrorCode(),
522 "invalid type cannot contain TypeInfo");
523}
524
525template <> llvm::Error addTypeInfo(RecordInfo *I, MemberTypeInfo &&T) {
526 I->Members.emplace_back(std::move(T));
527 return llvm::Error::success();
528}
529
530template <> llvm::Error addTypeInfo(BaseRecordInfo *I, MemberTypeInfo &&T) {
531 I->Members.emplace_back(std::move(T));
532 return llvm::Error::success();
533}
534
535template <> llvm::Error addTypeInfo(FunctionInfo *I, TypeInfo &&T) {
536 I->ReturnType = std::move(T);
537 return llvm::Error::success();
538}
539
540template <> llvm::Error addTypeInfo(FunctionInfo *I, FieldTypeInfo &&T) {
541 I->Params.emplace_back(std::move(T));
542 return llvm::Error::success();
543}
544
545template <> llvm::Error addTypeInfo(FriendInfo *I, FieldTypeInfo &&T) {
546 if (!I->Params)
547 I->Params.emplace();
548 I->Params->emplace_back(std::move(T));
549 return llvm::Error::success();
550}
551
552template <> llvm::Error addTypeInfo(FriendInfo *I, TypeInfo &&T) {
553 I->ReturnType.emplace(std::move(T));
554 return llvm::Error::success();
555}
556
557template <> llvm::Error addTypeInfo(EnumInfo *I, TypeInfo &&T) {
558 I->BaseType = std::move(T);
559 return llvm::Error::success();
560}
561
562template <> llvm::Error addTypeInfo(TypedefInfo *I, TypeInfo &&T) {
563 I->Underlying = std::move(T);
564 return llvm::Error::success();
565}
566
567template <> llvm::Error addTypeInfo(VarInfo *I, TypeInfo &&T) {
568 I->Type = std::move(T);
569 return llvm::Error::success();
570}
571
572template <typename T>
573static llvm::Error addReference(T I, Reference &&R, FieldId F) {
574 return llvm::createStringError(llvm::inconvertibleErrorCode(),
575 "invalid type cannot contain Reference");
576}
577
578template <> llvm::Error addReference(VarInfo *I, Reference &&R, FieldId F) {
579 switch (F) {
581 I->Namespace.emplace_back(std::move(R));
582 return llvm::Error::success();
583 default:
584 return llvm::createStringError(llvm::inconvertibleErrorCode(),
585 "VarInfo cannot contain this Reference");
586 }
587}
588
589template <> llvm::Error addReference(TypeInfo *I, Reference &&R, FieldId F) {
590 switch (F) {
591 case FieldId::F_type:
592 I->Type = std::move(R);
593 return llvm::Error::success();
594 default:
595 return llvm::createStringError(llvm::inconvertibleErrorCode(),
596 "invalid type cannot contain Reference");
597 }
598}
599
600template <>
602 switch (F) {
603 case FieldId::F_type:
604 I->Type = std::move(R);
605 return llvm::Error::success();
606 default:
607 return llvm::createStringError(llvm::inconvertibleErrorCode(),
608 "invalid type cannot contain Reference");
609 }
610}
611
612template <>
614 switch (F) {
615 case FieldId::F_type:
616 I->Type = std::move(R);
617 return llvm::Error::success();
618 default:
619 return llvm::createStringError(llvm::inconvertibleErrorCode(),
620 "invalid type cannot contain Reference");
621 }
622}
623
624template <> llvm::Error addReference(EnumInfo *I, Reference &&R, FieldId F) {
625 switch (F) {
627 I->Namespace.emplace_back(std::move(R));
628 return llvm::Error::success();
629 default:
630 return llvm::createStringError(llvm::inconvertibleErrorCode(),
631 "invalid type cannot contain Reference");
632 }
633}
634
635template <> llvm::Error addReference(TypedefInfo *I, Reference &&R, FieldId F) {
636 switch (F) {
638 I->Namespace.emplace_back(std::move(R));
639 return llvm::Error::success();
640 default:
641 return llvm::createStringError(llvm::inconvertibleErrorCode(),
642 "invalid type cannot contain Reference");
643 }
644}
645
646template <>
648 switch (F) {
650 I->Namespace.emplace_back(std::move(R));
651 return llvm::Error::success();
653 I->Children.Namespaces.emplace_back(std::move(R));
654 return llvm::Error::success();
656 I->Children.Records.emplace_back(std::move(R));
657 return llvm::Error::success();
658 default:
659 return llvm::createStringError(llvm::inconvertibleErrorCode(),
660 "invalid type cannot contain Reference");
661 }
662}
663
664template <>
666 switch (F) {
668 I->Namespace.emplace_back(std::move(R));
669 return llvm::Error::success();
671 I->Parent = std::move(R);
672 return llvm::Error::success();
673 default:
674 return llvm::createStringError(llvm::inconvertibleErrorCode(),
675 "invalid type cannot contain Reference");
676 }
677}
678
679template <> llvm::Error addReference(RecordInfo *I, Reference &&R, FieldId F) {
680 switch (F) {
682 I->Namespace.emplace_back(std::move(R));
683 return llvm::Error::success();
685 I->Parents.emplace_back(std::move(R));
686 return llvm::Error::success();
688 I->VirtualParents.emplace_back(std::move(R));
689 return llvm::Error::success();
691 I->Children.Records.emplace_back(std::move(R));
692 return llvm::Error::success();
693 default:
694 return llvm::createStringError(llvm::inconvertibleErrorCode(),
695 "invalid type cannot contain Reference");
696 }
697}
698
699template <>
701 if (F == FieldId::F_concept) {
702 I->ConceptRef = std::move(R);
703 return llvm::Error::success();
704 }
705 return llvm::createStringError(
706 llvm::inconvertibleErrorCode(),
707 "ConstraintInfo cannot contain this Reference");
708}
709
710template <>
711llvm::Error addReference(FriendInfo *Friend, Reference &&R, FieldId F) {
712 if (F == FieldId::F_friend) {
713 Friend->Ref = std::move(R);
714 return llvm::Error::success();
715 }
716 return llvm::createStringError(llvm::inconvertibleErrorCode(),
717 "Friend cannot contain this Reference");
718}
719
720template <typename T, typename ChildInfoType>
721static void addChild(T I, ChildInfoType &&R) {
722 ExitOnErr(llvm::createStringError(llvm::inconvertibleErrorCode(),
723 "invalid child type for info"));
724}
725
726// Namespace children:
727template <> void addChild(NamespaceInfo *I, FunctionInfo &&R) {
728 I->Children.Functions.emplace_back(std::move(R));
729}
730template <> void addChild(NamespaceInfo *I, EnumInfo &&R) {
731 I->Children.Enums.emplace_back(std::move(R));
732}
733template <> void addChild(NamespaceInfo *I, TypedefInfo &&R) {
734 I->Children.Typedefs.emplace_back(std::move(R));
735}
736template <> void addChild(NamespaceInfo *I, ConceptInfo &&R) {
737 I->Children.Concepts.emplace_back(std::move(R));
738}
739template <> void addChild(NamespaceInfo *I, VarInfo &&R) {
740 I->Children.Variables.emplace_back(std::move(R));
741}
742
743// Record children:
744template <> void addChild(RecordInfo *I, FunctionInfo &&R) {
745 I->Children.Functions.emplace_back(std::move(R));
746}
747template <> void addChild(RecordInfo *I, EnumInfo &&R) {
748 I->Children.Enums.emplace_back(std::move(R));
749}
750template <> void addChild(RecordInfo *I, TypedefInfo &&R) {
751 I->Children.Typedefs.emplace_back(std::move(R));
752}
753template <> void addChild(RecordInfo *I, FriendInfo &&R) {
754 I->Friends.emplace_back(std::move(R));
755}
756
757// Other types of children:
758template <> void addChild(EnumInfo *I, EnumValueInfo &&R) {
759 I->Members.emplace_back(std::move(R));
760}
761template <> void addChild(RecordInfo *I, BaseRecordInfo &&R) {
762 I->Bases.emplace_back(std::move(R));
763}
764template <> void addChild(BaseRecordInfo *I, FunctionInfo &&R) {
765 I->Children.Functions.emplace_back(std::move(R));
766}
767
768// TemplateParam children. These go into either a TemplateInfo (for template
769// parameters) or TemplateSpecializationInfo (for the specialization's
770// parameters).
771template <typename T> static void addTemplateParam(T I, TemplateParamInfo &&P) {
772 ExitOnErr(
773 llvm::createStringError(llvm::inconvertibleErrorCode(),
774 "invalid container for template parameter"));
775}
777 I->Params.emplace_back(std::move(P));
778}
779template <>
781 I->Params.emplace_back(std::move(P));
782}
783
784// Template info. These apply to either records or functions.
785template <typename T> static void addTemplate(T I, TemplateInfo &&P) {
786 ExitOnErr(llvm::createStringError(llvm::inconvertibleErrorCode(),
787 "invalid container for template info"));
788}
789template <> void addTemplate(RecordInfo *I, TemplateInfo &&P) {
790 I->Template.emplace(std::move(P));
791}
792template <> void addTemplate(FunctionInfo *I, TemplateInfo &&P) {
793 I->Template.emplace(std::move(P));
794}
795template <> void addTemplate(ConceptInfo *I, TemplateInfo &&P) {
796 I->Template = std::move(P);
797}
798template <> void addTemplate(FriendInfo *I, TemplateInfo &&P) {
799 I->Template.emplace(std::move(P));
800}
801
802// Template specializations go only into template records.
803template <typename T>
805 ExitOnErr(llvm::createStringError(
806 llvm::inconvertibleErrorCode(),
807 "invalid container for template specialization info"));
808}
809template <>
812 I->Specialization.emplace(std::move(TSI));
813}
814
815template <typename T> static void addConstraint(T I, ConstraintInfo &&C) {
816 ExitOnErr(llvm::createStringError(llvm::inconvertibleErrorCode(),
817 "invalid container for constraint info"));
818}
819template <> void addConstraint(TemplateInfo *I, ConstraintInfo &&C) {
820 I->Constraints.emplace_back(std::move(C));
821}
822
823// Read records from bitcode into a given info.
824template <typename T>
825llvm::Error ClangDocBitcodeReader::readRecord(unsigned ID, T I) {
826 Record R;
827 llvm::StringRef Blob;
828 llvm::Expected<unsigned> MaybeRecID = Stream.readRecord(ID, R, &Blob);
829 if (!MaybeRecID)
830 return MaybeRecID.takeError();
831 return parseRecord(R, MaybeRecID.get(), Blob, I);
832}
833
834template <>
835llvm::Error ClangDocBitcodeReader::readRecord(unsigned ID, Reference *I) {
836 llvm::TimeTraceScope("Reducing infos", "readRecord");
837 Record R;
838 llvm::StringRef Blob;
839 llvm::Expected<unsigned> MaybeRecID = Stream.readRecord(ID, R, &Blob);
840 if (!MaybeRecID)
841 return MaybeRecID.takeError();
842 return parseRecord(R, MaybeRecID.get(), Blob, I, CurrentReferenceField);
843}
844
845// Read a block of records into a single info.
846template <typename T>
847llvm::Error ClangDocBitcodeReader::readBlock(unsigned ID, T I) {
848 llvm::TimeTraceScope("Reducing infos", "readBlock");
849 if (llvm::Error Err = Stream.EnterSubBlock(ID))
850 return Err;
851
852 while (true) {
853 unsigned BlockOrCode = 0;
854 llvm::Expected<Cursor> C = skipUntilRecordOrBlock(BlockOrCode);
855 if (!C)
856 return C.takeError();
857
858 switch (*C) {
859 case Cursor::BadBlock:
860 return llvm::createStringError(llvm::inconvertibleErrorCode(),
861 "bad block found");
862 case Cursor::BlockEnd:
863 return llvm::Error::success();
864 case Cursor::BlockBegin:
865 if (llvm::Error Err = readSubBlock(BlockOrCode, I)) {
866 if (llvm::Error Skipped = Stream.SkipBlock())
867 return joinErrors(std::move(Err), std::move(Skipped));
868 return Err;
869 }
870 continue;
871 case Cursor::Record:
872 break;
873 }
874 if (auto Err = readRecord(BlockOrCode, I))
875 return Err;
876 }
877}
878
879// TODO: fix inconsistentent returning of errors in add callbacks.
880// Once that's fixed, we only need one handleSubBlock.
881template <typename InfoType, typename T, typename Callback>
882llvm::Error ClangDocBitcodeReader::handleSubBlock(unsigned ID, T Parent,
883 Callback Function) {
885 if (auto Err = readBlock(ID, &Info))
886 return Err;
887 Function(Parent, std::move(Info));
888 return llvm::Error::success();
889}
890
891template <typename InfoType, typename T, typename Callback>
892llvm::Error ClangDocBitcodeReader::handleTypeSubBlock(unsigned ID, T Parent,
893 Callback Function) {
895 if (auto Err = readBlock(ID, &Info))
896 return Err;
897 if (auto Err = Function(Parent, std::move(Info)))
898 return Err;
899 return llvm::Error::success();
900}
901
902template <typename T>
903llvm::Error ClangDocBitcodeReader::readSubBlock(unsigned ID, T I) {
904 llvm::TimeTraceScope("Reducing infos", "readSubBlock");
905
906 static auto CreateAddFunc = [](auto AddFunc) {
907 return [AddFunc](auto Parent, auto Child) {
908 return AddFunc(Parent, std::move(Child));
909 };
910 };
911
912 switch (ID) {
913 // Blocks can only have certain types of sub blocks.
914 case BI_COMMENT_BLOCK_ID: {
915 auto Comment = getCommentInfo(I);
916 if (!Comment)
917 return Comment.takeError();
918 if (auto Err = readBlock(ID, Comment.get()))
919 return Err;
920 return llvm::Error::success();
921 }
922 case BI_TYPE_BLOCK_ID: {
923 return handleTypeSubBlock<TypeInfo>(
924 ID, I, CreateAddFunc(addTypeInfo<T, TypeInfo>));
925 }
927 return handleTypeSubBlock<FieldTypeInfo>(
928 ID, I, CreateAddFunc(addTypeInfo<T, FieldTypeInfo>));
929 }
931 return handleTypeSubBlock<MemberTypeInfo>(
932 ID, I, CreateAddFunc(addTypeInfo<T, MemberTypeInfo>));
933 }
935 Reference R;
936 if (auto Err = readBlock(ID, &R))
937 return Err;
938 if (auto Err = addReference(I, std::move(R), CurrentReferenceField))
939 return Err;
940 return llvm::Error::success();
941 }
943 return handleSubBlock<FunctionInfo>(
944 ID, I, CreateAddFunc(addChild<T, FunctionInfo>));
945 }
947 return handleSubBlock<BaseRecordInfo>(
948 ID, I, CreateAddFunc(addChild<T, BaseRecordInfo>));
949 }
950 case BI_ENUM_BLOCK_ID: {
951 return handleSubBlock<EnumInfo>(ID, I,
952 CreateAddFunc(addChild<T, EnumInfo>));
953 }
955 return handleSubBlock<EnumValueInfo>(
956 ID, I, CreateAddFunc(addChild<T, EnumValueInfo>));
957 }
959 return handleSubBlock<TemplateInfo>(ID, I, CreateAddFunc(addTemplate<T>));
960 }
962 return handleSubBlock<TemplateSpecializationInfo>(
963 ID, I, CreateAddFunc(addTemplateSpecialization<T>));
964 }
966 return handleSubBlock<TemplateParamInfo>(
967 ID, I, CreateAddFunc(addTemplateParam<T>));
968 }
969 case BI_TYPEDEF_BLOCK_ID: {
970 return handleSubBlock<TypedefInfo>(ID, I,
971 CreateAddFunc(addChild<T, TypedefInfo>));
972 }
974 return handleSubBlock<ConstraintInfo>(ID, I,
975 CreateAddFunc(addConstraint<T>));
976 }
977 case BI_CONCEPT_BLOCK_ID: {
978 return handleSubBlock<ConceptInfo>(ID, I,
979 CreateAddFunc(addChild<T, ConceptInfo>));
980 }
981 case BI_VAR_BLOCK_ID: {
982 return handleSubBlock<VarInfo>(ID, I, CreateAddFunc(addChild<T, VarInfo>));
983 }
984 case BI_FRIEND_BLOCK_ID: {
985 return handleSubBlock<FriendInfo>(ID, I,
986 CreateAddFunc(addChild<T, FriendInfo>));
987 }
988 default:
989 return llvm::createStringError(llvm::inconvertibleErrorCode(),
990 "invalid subblock type");
991 }
992}
993
994llvm::Expected<ClangDocBitcodeReader::Cursor>
995ClangDocBitcodeReader::skipUntilRecordOrBlock(unsigned &BlockOrRecordID) {
996 llvm::TimeTraceScope("Reducing infos", "skipUntilRecordOrBlock");
997 BlockOrRecordID = 0;
998
999 while (!Stream.AtEndOfStream()) {
1000 Expected<unsigned> Code = Stream.ReadCode();
1001 if (!Code)
1002 return Code.takeError();
1003
1004 if (*Code >= static_cast<unsigned>(llvm::bitc::FIRST_APPLICATION_ABBREV)) {
1005 BlockOrRecordID = *Code;
1006 return Cursor::Record;
1007 }
1008 switch (static_cast<llvm::bitc::FixedAbbrevIDs>(*Code)) {
1009 case llvm::bitc::ENTER_SUBBLOCK:
1010 if (Expected<unsigned> MaybeID = Stream.ReadSubBlockID())
1011 BlockOrRecordID = MaybeID.get();
1012 else
1013 return MaybeID.takeError();
1014 return Cursor::BlockBegin;
1015 case llvm::bitc::END_BLOCK:
1016 if (Stream.ReadBlockEnd())
1017 return llvm::createStringError(llvm::inconvertibleErrorCode(),
1018 "error at end of block");
1019 return Cursor::BlockEnd;
1020 case llvm::bitc::DEFINE_ABBREV:
1021 if (llvm::Error Err = Stream.ReadAbbrevRecord())
1022 return std::move(Err);
1023 continue;
1024 case llvm::bitc::UNABBREV_RECORD:
1025 return llvm::createStringError(llvm::inconvertibleErrorCode(),
1026 "found unabbreviated record");
1027 case llvm::bitc::FIRST_APPLICATION_ABBREV:
1028 llvm_unreachable("Unexpected abbrev id.");
1029 }
1030 }
1031 llvm_unreachable("Premature stream end.");
1032}
1033
1034llvm::Error ClangDocBitcodeReader::validateStream() {
1035 if (Stream.AtEndOfStream())
1036 return llvm::createStringError(llvm::inconvertibleErrorCode(),
1037 "premature end of stream");
1038
1039 // Sniff for the signature.
1040 for (int Idx = 0; Idx != 4; ++Idx) {
1041 Expected<llvm::SimpleBitstreamCursor::word_t> MaybeRead = Stream.Read(8);
1042 if (!MaybeRead)
1043 return MaybeRead.takeError();
1044 if (MaybeRead.get() != BitCodeConstants::Signature[Idx])
1045 return llvm::createStringError(llvm::inconvertibleErrorCode(),
1046 "invalid bitcode signature");
1047 }
1048 return llvm::Error::success();
1049}
1050
1051llvm::Error ClangDocBitcodeReader::readBlockInfoBlock() {
1052 llvm::TimeTraceScope("Reducing infos", "readBlockInfoBlock");
1053 Expected<std::optional<llvm::BitstreamBlockInfo>> MaybeBlockInfo =
1054 Stream.ReadBlockInfoBlock();
1055 if (!MaybeBlockInfo)
1056 return MaybeBlockInfo.takeError();
1057 BlockInfo = MaybeBlockInfo.get();
1058 if (!BlockInfo)
1059 return llvm::createStringError(llvm::inconvertibleErrorCode(),
1060 "unable to parse BlockInfoBlock");
1061 Stream.setBlockInfo(&*BlockInfo);
1062 return llvm::Error::success();
1063}
1064
1065template <typename T>
1066llvm::Expected<std::unique_ptr<Info>>
1067ClangDocBitcodeReader::createInfo(unsigned ID) {
1068 llvm::TimeTraceScope("Reducing infos", "createInfo");
1069 std::unique_ptr<Info> I = std::make_unique<T>();
1070 if (auto Err = readBlock(ID, static_cast<T *>(I.get())))
1071 return std::move(Err);
1072 return std::unique_ptr<Info>{std::move(I)};
1073}
1074
1075llvm::Expected<std::unique_ptr<Info>>
1076ClangDocBitcodeReader::readBlockToInfo(unsigned ID) {
1077 llvm::TimeTraceScope("Reducing infos", "readBlockToInfo");
1078 switch (ID) {
1080 return createInfo<NamespaceInfo>(ID);
1081 case BI_RECORD_BLOCK_ID:
1082 return createInfo<RecordInfo>(ID);
1083 case BI_ENUM_BLOCK_ID:
1084 return createInfo<EnumInfo>(ID);
1086 return createInfo<TypedefInfo>(ID);
1088 return createInfo<ConceptInfo>(ID);
1090 return createInfo<FunctionInfo>(ID);
1091 case BI_VAR_BLOCK_ID:
1092 return createInfo<VarInfo>(ID);
1093 case BI_FRIEND_BLOCK_ID:
1094 return createInfo<FriendInfo>(ID);
1095 default:
1096 return llvm::createStringError(llvm::inconvertibleErrorCode(),
1097 "cannot create info");
1098 }
1099}
1100
1101// Entry point
1102llvm::Expected<std::vector<std::unique_ptr<Info>>>
1104 std::vector<std::unique_ptr<Info>> Infos;
1105 if (auto Err = validateStream())
1106 return std::move(Err);
1107
1108 // Read the top level blocks.
1109 while (!Stream.AtEndOfStream()) {
1110 Expected<unsigned> MaybeCode = Stream.ReadCode();
1111 if (!MaybeCode)
1112 return MaybeCode.takeError();
1113 if (MaybeCode.get() != llvm::bitc::ENTER_SUBBLOCK)
1114 return llvm::createStringError(llvm::inconvertibleErrorCode(),
1115 "no blocks in input");
1116 Expected<unsigned> MaybeID = Stream.ReadSubBlockID();
1117 if (!MaybeID)
1118 return MaybeID.takeError();
1119 unsigned ID = MaybeID.get();
1120 switch (ID) {
1121 // NamedType and Comment blocks should not appear at the top level
1122 case BI_TYPE_BLOCK_ID:
1127 return llvm::createStringError(llvm::inconvertibleErrorCode(),
1128 "invalid top level block");
1130 case BI_RECORD_BLOCK_ID:
1131 case BI_ENUM_BLOCK_ID:
1134 case BI_VAR_BLOCK_ID:
1135 case BI_FRIEND_BLOCK_ID:
1136 case BI_FUNCTION_BLOCK_ID: {
1137 auto InfoOrErr = readBlockToInfo(ID);
1138 if (!InfoOrErr)
1139 return InfoOrErr.takeError();
1140 Infos.emplace_back(std::move(InfoOrErr.get()));
1141 continue;
1142 }
1144 if (auto Err = readBlock(ID, VersionNumber))
1145 return std::move(Err);
1146 continue;
1147 case llvm::bitc::BLOCKINFO_BLOCK_ID:
1148 if (auto Err = readBlockInfoBlock())
1149 return std::move(Err);
1150 continue;
1151 default:
1152 if (llvm::Error Err = Stream.SkipBlock())
1153 return std::move(Err);
1154 continue;
1155 }
1156 }
1157 return std::move(Infos);
1158}
1159
1160} // namespace doc
1161} // namespace clang
static llvm::ExitOnError ExitOnErr
llvm::Expected< std::vector< std::unique_ptr< Info > > > readBitcode()
static llvm::Error parseRecord(const Record &R, unsigned ID, llvm::StringRef Blob, const unsigned VersionNo)
static llvm::Expected< CommentInfo * > getCommentInfo(T I)
@ 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)
static const unsigned VersionNumber
static void addChild(T I, ChildInfoType &&R)
CommentKind stringToCommentKind(llvm::StringRef KindStr)
static llvm::Error addTypeInfo(T I, TTypeInfo &&TI)
static void addTemplateSpecialization(T I, TemplateSpecializationInfo &&TSI)
static void addTemplate(T I, TemplateInfo &&P)
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]
SmallString< 8 > Direction
std::vector< std::unique_ptr< CommentInfo > > Children
llvm::SmallVector< SmallString< 16 >, 4 > AttrValues
SmallString< 16 > CloseName
SmallString< 16 > Name
SmallString< 64 > Text
llvm::SmallVector< SmallString< 16 >, 4 > AttrKeys
llvm::SmallVector< SmallString< 16 >, 4 > Args
SmallString< 16 > ParamName
SmallString< 16 > ConstraintExpression
SmallString< 16 > ConstraintExpr
llvm::SmallVector< EnumValueInfo, 4 > Members
std::optional< TypeInfo > BaseType
std::vector< CommentInfo > Description
Comment description of this field.
SmallString< 16 > ValueExpr
SmallString< 16 > DefaultValue
std::optional< TypeInfo > ReturnType
std::optional< SmallVector< FieldTypeInfo, 4 > > Params
std::optional< TemplateInfo > Template
llvm::SmallVector< FieldTypeInfo, 4 > Params
std::optional< TemplateInfo > Template
A base struct for Infos.
SmallString< 16 > Name
std::vector< CommentInfo > Description
llvm::SmallString< 128 > Path
llvm::SmallVector< Reference, 4 > Namespace
std::vector< CommentInfo > Description
llvm::SmallVector< MemberTypeInfo, 4 > Members
std::optional< TemplateInfo > Template
std::vector< FriendInfo > Friends
llvm::SmallVector< Reference, 4 > VirtualParents
llvm::SmallVector< Reference, 4 > Parents
std::vector< BaseRecordInfo > Bases
SmallString< 16 > QualName
llvm::SmallString< 128 > Path
SmallString< 16 > DocumentationFileName
SmallString< 16 > Name
std::vector< Reference > Records
std::vector< TypedefInfo > Typedefs
std::vector< FunctionInfo > Functions
std::vector< Reference > Namespaces
std::vector< VarInfo > Variables
std::vector< EnumInfo > Enums
std::vector< ConceptInfo > Concepts
llvm::SmallVector< Location, 2 > Loc
std::optional< Location > DefLoc
SmallString< 16 > MangledName
std::vector< ConstraintInfo > Constraints
std::vector< TemplateParamInfo > Params
std::optional< TemplateSpecializationInfo > Specialization
std::vector< TemplateParamInfo > Params
std::vector< CommentInfo > Description
Comment description for the typedef.