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);
163 return decodeRecord(R, I->ParentUSR, Blob);
164 default:
165 return llvm::createStringError(llvm::inconvertibleErrorCode(),
166 "invalid field for NamespaceInfo");
167 }
168}
169
170static llvm::Error parseRecord(const Record &R, unsigned ID,
171 llvm::StringRef Blob, RecordInfo *I) {
172 switch (ID) {
173 case RECORD_USR:
174 return decodeRecord(R, I->USR, Blob);
175 case RECORD_NAME:
176 return decodeRecord(R, I->Name, Blob);
177 case RECORD_PATH:
178 return decodeRecord(R, I->Path, Blob);
180 return decodeRecord(R, I->DefLoc, Blob);
181 case RECORD_LOCATION:
182 return decodeRecord(R, I->Loc, Blob);
183 case RECORD_TAG_TYPE:
184 return decodeRecord(R, I->TagType, Blob);
186 return decodeRecord(R, I->IsTypeDef, Blob);
188 return decodeRecord(R, I->MangledName, Blob);
190 return decodeRecord(R, I->ParentUSR, Blob);
191 default:
192 return llvm::createStringError(llvm::inconvertibleErrorCode(),
193 "invalid field for RecordInfo");
194 }
195}
196
197static llvm::Error parseRecord(const Record &R, unsigned ID,
198 llvm::StringRef Blob, BaseRecordInfo *I) {
199 switch (ID) {
200 case BASE_RECORD_USR:
201 return decodeRecord(R, I->USR, Blob);
202 case BASE_RECORD_NAME:
203 return decodeRecord(R, I->Name, Blob);
204 case BASE_RECORD_PATH:
205 return decodeRecord(R, I->Path, Blob);
207 return decodeRecord(R, I->TagType, Blob);
209 return decodeRecord(R, I->IsVirtual, Blob);
211 return decodeRecord(R, I->Access, Blob);
213 return decodeRecord(R, I->IsParent, Blob);
214 default:
215 return llvm::createStringError(llvm::inconvertibleErrorCode(),
216 "invalid field for BaseRecordInfo");
217 }
218}
219
220static llvm::Error parseRecord(const Record &R, unsigned ID,
221 llvm::StringRef Blob, EnumInfo *I) {
222 switch (ID) {
223 case ENUM_USR:
224 return decodeRecord(R, I->USR, Blob);
225 case ENUM_NAME:
226 return decodeRecord(R, I->Name, Blob);
227 case ENUM_DEFLOCATION:
228 return decodeRecord(R, I->DefLoc, Blob);
229 case ENUM_LOCATION:
230 return decodeRecord(R, I->Loc, Blob);
231 case ENUM_SCOPED:
232 return decodeRecord(R, I->Scoped, Blob);
233 default:
234 return llvm::createStringError(llvm::inconvertibleErrorCode(),
235 "invalid field for EnumInfo");
236 }
237}
238
239static llvm::Error parseRecord(const Record &R, unsigned ID,
240 llvm::StringRef Blob, TypedefInfo *I) {
241 switch (ID) {
242 case TYPEDEF_USR:
243 return decodeRecord(R, I->USR, Blob);
244 case TYPEDEF_NAME:
245 return decodeRecord(R, I->Name, Blob);
247 return decodeRecord(R, I->DefLoc, Blob);
248 case TYPEDEF_IS_USING:
249 return decodeRecord(R, I->IsUsing, Blob);
250 default:
251 return llvm::createStringError(llvm::inconvertibleErrorCode(),
252 "invalid field for TypedefInfo");
253 }
254}
255
256static llvm::Error parseRecord(const Record &R, unsigned ID,
257 llvm::StringRef Blob, EnumValueInfo *I) {
258 switch (ID) {
259 case ENUM_VALUE_NAME:
260 return decodeRecord(R, I->Name, Blob);
261 case ENUM_VALUE_VALUE:
262 return decodeRecord(R, I->Value, Blob);
263 case ENUM_VALUE_EXPR:
264 return decodeRecord(R, I->ValueExpr, Blob);
265 default:
266 return llvm::createStringError(llvm::inconvertibleErrorCode(),
267 "invalid field for EnumValueInfo");
268 }
269}
270
271static llvm::Error parseRecord(const Record &R, unsigned ID,
272 llvm::StringRef Blob, FunctionInfo *I) {
273 switch (ID) {
274 case FUNCTION_USR:
275 return decodeRecord(R, I->USR, Blob);
276 case FUNCTION_NAME:
277 return decodeRecord(R, I->Name, Blob);
279 return decodeRecord(R, I->DefLoc, Blob);
281 return decodeRecord(R, I->Loc, Blob);
282 case FUNCTION_ACCESS:
283 return decodeRecord(R, I->Access, Blob);
285 return decodeRecord(R, I->IsMethod, Blob);
287 return decodeRecord(R, I->IsStatic, Blob);
288 default:
289 return llvm::createStringError(llvm::inconvertibleErrorCode(),
290 "invalid field for FunctionInfo");
291 }
292}
293
294static llvm::Error parseRecord(const Record &R, unsigned ID,
295 llvm::StringRef Blob, TypeInfo *I) {
296 switch (ID) {
297 case TYPE_IS_BUILTIN:
298 return decodeRecord(R, I->IsBuiltIn, Blob);
299 case TYPE_IS_TEMPLATE:
300 return decodeRecord(R, I->IsTemplate, Blob);
301 default:
302 return llvm::createStringError(llvm::inconvertibleErrorCode(),
303 "invalid field for TypeInfo");
304 }
305}
306
307static llvm::Error parseRecord(const Record &R, unsigned ID,
308 llvm::StringRef Blob, FieldTypeInfo *I) {
309 switch (ID) {
310 case FIELD_TYPE_NAME:
311 return decodeRecord(R, I->Name, Blob);
313 return decodeRecord(R, I->DefaultValue, Blob);
315 return decodeRecord(R, I->IsBuiltIn, Blob);
317 return decodeRecord(R, I->IsTemplate, Blob);
318 default:
319 return llvm::createStringError(llvm::inconvertibleErrorCode(),
320 "invalid field for TypeInfo");
321 }
322}
323
324static llvm::Error parseRecord(const Record &R, unsigned ID,
325 llvm::StringRef Blob, MemberTypeInfo *I) {
326 switch (ID) {
327 case MEMBER_TYPE_NAME:
328 return decodeRecord(R, I->Name, Blob);
330 return decodeRecord(R, I->Access, Blob);
332 return decodeRecord(R, I->IsStatic, Blob);
334 return decodeRecord(R, I->IsBuiltIn, Blob);
336 return decodeRecord(R, I->IsTemplate, Blob);
337 default:
338 return llvm::createStringError(llvm::inconvertibleErrorCode(),
339 "invalid field for MemberTypeInfo");
340 }
341}
342
343static llvm::Error parseRecord(const Record &R, unsigned ID,
344 llvm::StringRef Blob, CommentInfo *I) {
345 llvm::SmallString<16> KindStr;
346 switch (ID) {
347 case COMMENT_KIND:
348 if (llvm::Error Err = decodeRecord(R, KindStr, Blob))
349 return Err;
350 I->Kind = stringToCommentKind(KindStr);
351 return llvm::Error::success();
352 case COMMENT_TEXT:
353 return decodeRecord(R, I->Text, Blob);
354 case COMMENT_NAME:
355 return decodeRecord(R, I->Name, Blob);
357 return decodeRecord(R, I->Direction, Blob);
359 return decodeRecord(R, I->ParamName, Blob);
361 return decodeRecord(R, I->CloseName, Blob);
362 case COMMENT_ATTRKEY:
363 return decodeRecord(R, I->AttrKeys, Blob);
364 case COMMENT_ATTRVAL:
365 return decodeRecord(R, I->AttrValues, Blob);
366 case COMMENT_ARG:
367 return decodeRecord(R, I->Args, Blob);
369 return decodeRecord(R, I->SelfClosing, Blob);
370 case COMMENT_EXPLICIT:
371 return decodeRecord(R, I->Explicit, Blob);
372 default:
373 return llvm::createStringError(llvm::inconvertibleErrorCode(),
374 "invalid field for CommentInfo");
375 }
376}
377
378static llvm::Error parseRecord(const Record &R, unsigned ID,
379 llvm::StringRef Blob, Reference *I, FieldId &F) {
380 switch (ID) {
381 case REFERENCE_USR:
382 return decodeRecord(R, I->USR, Blob);
383 case REFERENCE_NAME:
384 return decodeRecord(R, I->Name, Blob);
386 return decodeRecord(R, I->QualName, Blob);
387 case REFERENCE_TYPE:
388 return decodeRecord(R, I->RefType, Blob);
389 case REFERENCE_PATH:
390 return decodeRecord(R, I->Path, Blob);
391 case REFERENCE_FIELD:
392 return decodeRecord(R, F, Blob);
393 case REFERENCE_FILE:
394 return decodeRecord(R, I->DocumentationFileName, Blob);
395 default:
396 return llvm::createStringError(llvm::inconvertibleErrorCode(),
397 "invalid field for Reference");
398 }
399}
400
401static llvm::Error parseRecord(const Record &R, unsigned ID,
402 llvm::StringRef Blob, TemplateInfo *I) {
403 // Currently there are no child records of TemplateInfo (only child blocks).
404 return llvm::createStringError(llvm::inconvertibleErrorCode(),
405 "invalid field for TemplateParamInfo");
406}
407
408static llvm::Error parseRecord(const Record &R, unsigned ID,
409 llvm::StringRef Blob,
412 return decodeRecord(R, I->SpecializationOf, Blob);
413 return llvm::createStringError(llvm::inconvertibleErrorCode(),
414 "invalid field for TemplateParamInfo");
415}
416
417static llvm::Error parseRecord(const Record &R, unsigned ID,
418 llvm::StringRef Blob, TemplateParamInfo *I) {
419 if (ID == TEMPLATE_PARAM_CONTENTS)
420 return decodeRecord(R, I->Contents, Blob);
421 return llvm::createStringError(llvm::inconvertibleErrorCode(),
422 "invalid field for TemplateParamInfo");
423}
424
425static llvm::Error parseRecord(const Record &R, unsigned ID,
426 llvm::StringRef Blob, ConceptInfo *I) {
427 switch (ID) {
428 case CONCEPT_USR:
429 return decodeRecord(R, I->USR, Blob);
430 case CONCEPT_NAME:
431 return decodeRecord(R, I->Name, Blob);
432 case CONCEPT_IS_TYPE:
433 return decodeRecord(R, I->IsType, Blob);
435 return decodeRecord(R, I->ConstraintExpression, Blob);
437 return decodeRecord(R, I->DefLoc, Blob);
438 }
439 llvm_unreachable("invalid field for ConceptInfo");
440}
441
442static llvm::Error parseRecord(const Record &R, unsigned ID,
443 llvm::StringRef Blob, ConstraintInfo *I) {
444 if (ID == CONSTRAINT_EXPRESSION)
445 return decodeRecord(R, I->ConstraintExpr, Blob);
446 return llvm::createStringError(llvm::inconvertibleErrorCode(),
447 "invalid field for ConstraintInfo");
448}
449
450static llvm::Error parseRecord(const Record &R, unsigned ID,
451 llvm::StringRef Blob, VarInfo *I) {
452 switch (ID) {
453 case VAR_USR:
454 return decodeRecord(R, I->USR, Blob);
455 case VAR_NAME:
456 return decodeRecord(R, I->Name, Blob);
457 case VAR_DEFLOCATION:
458 return decodeRecord(R, I->DefLoc, Blob);
459 case VAR_IS_STATIC:
460 return decodeRecord(R, I->IsStatic, Blob);
461 default:
462 return llvm::createStringError(llvm::inconvertibleErrorCode(),
463 "invalid field for VarInfo");
464 }
465}
466
467static llvm::Error parseRecord(const Record &R, unsigned ID, StringRef Blob,
468 FriendInfo *F) {
469 if (ID == FRIEND_IS_CLASS) {
470 return decodeRecord(R, F->IsClass, Blob);
471 }
472 return llvm::createStringError(llvm::inconvertibleErrorCode(),
473 "invalid field for Friend");
474}
475
476template <typename T> static llvm::Expected<CommentInfo *> getCommentInfo(T I) {
477 return llvm::createStringError(llvm::inconvertibleErrorCode(),
478 "invalid type cannot contain CommentInfo");
479}
480
481template <> llvm::Expected<CommentInfo *> getCommentInfo(FunctionInfo *I) {
482 return &I->Description.emplace_back();
483}
484
485template <> llvm::Expected<CommentInfo *> getCommentInfo(NamespaceInfo *I) {
486 return &I->Description.emplace_back();
487}
488
489template <> llvm::Expected<CommentInfo *> getCommentInfo(RecordInfo *I) {
490 return &I->Description.emplace_back();
491}
492
493template <> llvm::Expected<CommentInfo *> getCommentInfo(MemberTypeInfo *I) {
494 return &I->Description.emplace_back();
495}
496
497template <> llvm::Expected<CommentInfo *> getCommentInfo(EnumInfo *I) {
498 return &I->Description.emplace_back();
499}
500
501template <> llvm::Expected<CommentInfo *> getCommentInfo(TypedefInfo *I) {
502 return &I->Description.emplace_back();
503}
504
505template <> llvm::Expected<CommentInfo *> getCommentInfo(EnumValueInfo *I) {
506 return &I->Description.emplace_back();
507}
508
509template <> llvm::Expected<CommentInfo *> getCommentInfo(CommentInfo *I) {
510 I->Children.emplace_back(std::make_unique<CommentInfo>());
511 return I->Children.back().get();
512}
513
514template <> llvm::Expected<CommentInfo *> getCommentInfo(ConceptInfo *I) {
515 return &I->Description.emplace_back();
516}
517
518template <> Expected<CommentInfo *> getCommentInfo(VarInfo *I) {
519 return &I->Description.emplace_back();
520}
521
522template <> Expected<CommentInfo *> getCommentInfo(FriendInfo *I) {
523 return &I->Description.emplace_back();
524}
525
526// When readSubBlock encounters a TypeInfo sub-block, it calls addTypeInfo on
527// the parent block to set it. The template specializations define what to do
528// for each supported parent block.
529template <typename T, typename TTypeInfo>
530static llvm::Error addTypeInfo(T I, TTypeInfo &&TI) {
531 return llvm::createStringError(llvm::inconvertibleErrorCode(),
532 "invalid type cannot contain TypeInfo");
533}
534
535template <> llvm::Error addTypeInfo(RecordInfo *I, MemberTypeInfo &&T) {
536 I->Members.emplace_back(std::move(T));
537 return llvm::Error::success();
538}
539
540template <> llvm::Error addTypeInfo(BaseRecordInfo *I, MemberTypeInfo &&T) {
541 I->Members.emplace_back(std::move(T));
542 return llvm::Error::success();
543}
544
545template <> llvm::Error addTypeInfo(FunctionInfo *I, TypeInfo &&T) {
546 I->ReturnType = std::move(T);
547 return llvm::Error::success();
548}
549
550template <> llvm::Error addTypeInfo(FunctionInfo *I, FieldTypeInfo &&T) {
551 I->Params.emplace_back(std::move(T));
552 return llvm::Error::success();
553}
554
555template <> llvm::Error addTypeInfo(FriendInfo *I, FieldTypeInfo &&T) {
556 if (!I->Params)
557 I->Params.emplace();
558 I->Params->emplace_back(std::move(T));
559 return llvm::Error::success();
560}
561
562template <> llvm::Error addTypeInfo(FriendInfo *I, TypeInfo &&T) {
563 I->ReturnType.emplace(std::move(T));
564 return llvm::Error::success();
565}
566
567template <> llvm::Error addTypeInfo(EnumInfo *I, TypeInfo &&T) {
568 I->BaseType = std::move(T);
569 return llvm::Error::success();
570}
571
572template <> llvm::Error addTypeInfo(TypedefInfo *I, TypeInfo &&T) {
573 I->Underlying = std::move(T);
574 return llvm::Error::success();
575}
576
577template <> llvm::Error addTypeInfo(VarInfo *I, TypeInfo &&T) {
578 I->Type = std::move(T);
579 return llvm::Error::success();
580}
581
582template <typename T>
583static llvm::Error addReference(T I, Reference &&R, FieldId F) {
584 return llvm::createStringError(llvm::inconvertibleErrorCode(),
585 "invalid type cannot contain Reference");
586}
587
588template <> llvm::Error addReference(VarInfo *I, Reference &&R, FieldId F) {
589 switch (F) {
591 I->Namespace.emplace_back(std::move(R));
592 return llvm::Error::success();
593 default:
594 return llvm::createStringError(llvm::inconvertibleErrorCode(),
595 "VarInfo cannot contain this Reference");
596 }
597}
598
599template <> llvm::Error addReference(TypeInfo *I, Reference &&R, FieldId F) {
600 switch (F) {
601 case FieldId::F_type:
602 I->Type = std::move(R);
603 return llvm::Error::success();
604 default:
605 return llvm::createStringError(llvm::inconvertibleErrorCode(),
606 "invalid type cannot contain Reference");
607 }
608}
609
610template <>
612 switch (F) {
613 case FieldId::F_type:
614 I->Type = std::move(R);
615 return llvm::Error::success();
616 default:
617 return llvm::createStringError(llvm::inconvertibleErrorCode(),
618 "invalid type cannot contain Reference");
619 }
620}
621
622template <>
624 switch (F) {
625 case FieldId::F_type:
626 I->Type = std::move(R);
627 return llvm::Error::success();
628 default:
629 return llvm::createStringError(llvm::inconvertibleErrorCode(),
630 "invalid type cannot contain Reference");
631 }
632}
633
634template <> llvm::Error addReference(EnumInfo *I, Reference &&R, FieldId F) {
635 switch (F) {
637 I->Namespace.emplace_back(std::move(R));
638 return llvm::Error::success();
639 default:
640 return llvm::createStringError(llvm::inconvertibleErrorCode(),
641 "invalid type cannot contain Reference");
642 }
643}
644
645template <> llvm::Error addReference(TypedefInfo *I, Reference &&R, FieldId F) {
646 switch (F) {
648 I->Namespace.emplace_back(std::move(R));
649 return llvm::Error::success();
650 default:
651 return llvm::createStringError(llvm::inconvertibleErrorCode(),
652 "invalid type cannot contain Reference");
653 }
654}
655
656template <>
658 switch (F) {
660 I->Namespace.emplace_back(std::move(R));
661 return llvm::Error::success();
663 I->Children.Namespaces.emplace_back(std::move(R));
664 return llvm::Error::success();
666 I->Children.Records.emplace_back(std::move(R));
667 return llvm::Error::success();
668 default:
669 return llvm::createStringError(llvm::inconvertibleErrorCode(),
670 "invalid type cannot contain Reference");
671 }
672}
673
674template <>
676 switch (F) {
678 I->Namespace.emplace_back(std::move(R));
679 return llvm::Error::success();
681 I->Parent = std::move(R);
682 return llvm::Error::success();
683 default:
684 return llvm::createStringError(llvm::inconvertibleErrorCode(),
685 "invalid type cannot contain Reference");
686 }
687}
688
689template <> llvm::Error addReference(RecordInfo *I, Reference &&R, FieldId F) {
690 switch (F) {
692 I->Namespace.emplace_back(std::move(R));
693 return llvm::Error::success();
695 I->Parents.emplace_back(std::move(R));
696 return llvm::Error::success();
698 I->VirtualParents.emplace_back(std::move(R));
699 return llvm::Error::success();
701 I->Children.Records.emplace_back(std::move(R));
702 return llvm::Error::success();
703 default:
704 return llvm::createStringError(llvm::inconvertibleErrorCode(),
705 "invalid type cannot contain Reference");
706 }
707}
708
709template <>
711 if (F == FieldId::F_concept) {
712 I->ConceptRef = std::move(R);
713 return llvm::Error::success();
714 }
715 return llvm::createStringError(
716 llvm::inconvertibleErrorCode(),
717 "ConstraintInfo cannot contain this Reference");
718}
719
720template <>
721llvm::Error addReference(FriendInfo *Friend, Reference &&R, FieldId F) {
722 if (F == FieldId::F_friend) {
723 Friend->Ref = std::move(R);
724 return llvm::Error::success();
725 }
726 return llvm::createStringError(llvm::inconvertibleErrorCode(),
727 "Friend cannot contain this Reference");
728}
729
730template <typename T, typename ChildInfoType>
731static void addChild(T I, ChildInfoType &&R) {
732 ExitOnErr(llvm::createStringError(llvm::inconvertibleErrorCode(),
733 "invalid child type for info"));
734}
735
736// Namespace children:
737template <> void addChild(NamespaceInfo *I, FunctionInfo &&R) {
738 I->Children.Functions.emplace_back(std::move(R));
739}
740template <> void addChild(NamespaceInfo *I, EnumInfo &&R) {
741 I->Children.Enums.emplace_back(std::move(R));
742}
743template <> void addChild(NamespaceInfo *I, TypedefInfo &&R) {
744 I->Children.Typedefs.emplace_back(std::move(R));
745}
746template <> void addChild(NamespaceInfo *I, ConceptInfo &&R) {
747 I->Children.Concepts.emplace_back(std::move(R));
748}
749template <> void addChild(NamespaceInfo *I, VarInfo &&R) {
750 I->Children.Variables.emplace_back(std::move(R));
751}
752
753// Record children:
754template <> void addChild(RecordInfo *I, FunctionInfo &&R) {
755 I->Children.Functions.emplace_back(std::move(R));
756}
757template <> void addChild(RecordInfo *I, EnumInfo &&R) {
758 I->Children.Enums.emplace_back(std::move(R));
759}
760template <> void addChild(RecordInfo *I, TypedefInfo &&R) {
761 I->Children.Typedefs.emplace_back(std::move(R));
762}
763template <> void addChild(RecordInfo *I, FriendInfo &&R) {
764 I->Friends.emplace_back(std::move(R));
765}
766
767// Other types of children:
768template <> void addChild(EnumInfo *I, EnumValueInfo &&R) {
769 I->Members.emplace_back(std::move(R));
770}
771template <> void addChild(RecordInfo *I, BaseRecordInfo &&R) {
772 I->Bases.emplace_back(std::move(R));
773}
774template <> void addChild(BaseRecordInfo *I, FunctionInfo &&R) {
775 I->Children.Functions.emplace_back(std::move(R));
776}
777
778// TemplateParam children. These go into either a TemplateInfo (for template
779// parameters) or TemplateSpecializationInfo (for the specialization's
780// parameters).
781template <typename T> static void addTemplateParam(T I, TemplateParamInfo &&P) {
782 ExitOnErr(
783 llvm::createStringError(llvm::inconvertibleErrorCode(),
784 "invalid container for template parameter"));
785}
787 I->Params.emplace_back(std::move(P));
788}
789template <>
791 I->Params.emplace_back(std::move(P));
792}
793
794// Template info. These apply to either records or functions.
795template <typename T> static void addTemplate(T I, TemplateInfo &&P) {
796 ExitOnErr(llvm::createStringError(llvm::inconvertibleErrorCode(),
797 "invalid container for template info"));
798}
799template <> void addTemplate(RecordInfo *I, TemplateInfo &&P) {
800 I->Template.emplace(std::move(P));
801}
802template <> void addTemplate(FunctionInfo *I, TemplateInfo &&P) {
803 I->Template.emplace(std::move(P));
804}
805template <> void addTemplate(ConceptInfo *I, TemplateInfo &&P) {
806 I->Template = std::move(P);
807}
808template <> void addTemplate(FriendInfo *I, TemplateInfo &&P) {
809 I->Template.emplace(std::move(P));
810}
811template <> void addTemplate(TypedefInfo *I, TemplateInfo &&P) {
812 I->Template.emplace(std::move(P));
813}
814
815// Template specializations go only into template records.
816template <typename T>
818 ExitOnErr(llvm::createStringError(
819 llvm::inconvertibleErrorCode(),
820 "invalid container for template specialization info"));
821}
822template <>
825 I->Specialization.emplace(std::move(TSI));
826}
827
828template <typename T> static void addConstraint(T I, ConstraintInfo &&C) {
829 ExitOnErr(llvm::createStringError(llvm::inconvertibleErrorCode(),
830 "invalid container for constraint info"));
831}
832template <> void addConstraint(TemplateInfo *I, ConstraintInfo &&C) {
833 I->Constraints.emplace_back(std::move(C));
834}
835
836// Read records from bitcode into a given info.
837template <typename T>
838llvm::Error ClangDocBitcodeReader::readRecord(unsigned ID, T I) {
839 Record R;
840 llvm::StringRef Blob;
841 llvm::Expected<unsigned> MaybeRecID = Stream.readRecord(ID, R, &Blob);
842 if (!MaybeRecID)
843 return MaybeRecID.takeError();
844 return parseRecord(R, MaybeRecID.get(), Blob, I);
845}
846
847template <>
848llvm::Error ClangDocBitcodeReader::readRecord(unsigned ID, Reference *I) {
849 llvm::TimeTraceScope("Reducing infos", "readRecord");
850 Record R;
851 llvm::StringRef Blob;
852 llvm::Expected<unsigned> MaybeRecID = Stream.readRecord(ID, R, &Blob);
853 if (!MaybeRecID)
854 return MaybeRecID.takeError();
855 return parseRecord(R, MaybeRecID.get(), Blob, I, CurrentReferenceField);
856}
857
858// Read a block of records into a single info.
859template <typename T>
860llvm::Error ClangDocBitcodeReader::readBlock(unsigned ID, T I) {
861 llvm::TimeTraceScope("Reducing infos", "readBlock");
862 if (llvm::Error Err = Stream.EnterSubBlock(ID))
863 return Err;
864
865 while (true) {
866 unsigned BlockOrCode = 0;
867 llvm::Expected<Cursor> C = skipUntilRecordOrBlock(BlockOrCode);
868 if (!C)
869 return C.takeError();
870
871 switch (*C) {
872 case Cursor::BadBlock:
873 return llvm::createStringError(llvm::inconvertibleErrorCode(),
874 "bad block found");
875 case Cursor::BlockEnd:
876 return llvm::Error::success();
877 case Cursor::BlockBegin:
878 if (llvm::Error Err = readSubBlock(BlockOrCode, I)) {
879 if (llvm::Error Skipped = Stream.SkipBlock())
880 return joinErrors(std::move(Err), std::move(Skipped));
881 return Err;
882 }
883 continue;
884 case Cursor::Record:
885 break;
886 }
887 if (auto Err = readRecord(BlockOrCode, I))
888 return Err;
889 }
890}
891
892// TODO: fix inconsistentent returning of errors in add callbacks.
893// Once that's fixed, we only need one handleSubBlock.
894template <typename InfoType, typename T, typename Callback>
895llvm::Error ClangDocBitcodeReader::handleSubBlock(unsigned ID, T Parent,
896 Callback Function) {
898 if (auto Err = readBlock(ID, &Info))
899 return Err;
900 Function(Parent, std::move(Info));
901 return llvm::Error::success();
902}
903
904template <typename InfoType, typename T, typename Callback>
905llvm::Error ClangDocBitcodeReader::handleTypeSubBlock(unsigned ID, T Parent,
906 Callback Function) {
908 if (auto Err = readBlock(ID, &Info))
909 return Err;
910 if (auto Err = Function(Parent, std::move(Info)))
911 return Err;
912 return llvm::Error::success();
913}
914
915template <typename T>
916llvm::Error ClangDocBitcodeReader::readSubBlock(unsigned ID, T I) {
917 llvm::TimeTraceScope("Reducing infos", "readSubBlock");
918
919 static auto CreateAddFunc = [](auto AddFunc) {
920 return [AddFunc](auto Parent, auto Child) {
921 return AddFunc(Parent, std::move(Child));
922 };
923 };
924
925 switch (ID) {
926 // Blocks can only have certain types of sub blocks.
927 case BI_COMMENT_BLOCK_ID: {
928 auto Comment = getCommentInfo(I);
929 if (!Comment)
930 return Comment.takeError();
931 if (auto Err = readBlock(ID, Comment.get()))
932 return Err;
933 return llvm::Error::success();
934 }
935 case BI_TYPE_BLOCK_ID: {
936 return handleTypeSubBlock<TypeInfo>(
937 ID, I, CreateAddFunc(addTypeInfo<T, TypeInfo>));
938 }
940 return handleTypeSubBlock<FieldTypeInfo>(
941 ID, I, CreateAddFunc(addTypeInfo<T, FieldTypeInfo>));
942 }
944 return handleTypeSubBlock<MemberTypeInfo>(
945 ID, I, CreateAddFunc(addTypeInfo<T, MemberTypeInfo>));
946 }
948 Reference R;
949 if (auto Err = readBlock(ID, &R))
950 return Err;
951 if (auto Err = addReference(I, std::move(R), CurrentReferenceField))
952 return Err;
953 return llvm::Error::success();
954 }
956 return handleSubBlock<FunctionInfo>(
957 ID, I, CreateAddFunc(addChild<T, FunctionInfo>));
958 }
960 return handleSubBlock<BaseRecordInfo>(
961 ID, I, CreateAddFunc(addChild<T, BaseRecordInfo>));
962 }
963 case BI_ENUM_BLOCK_ID: {
964 return handleSubBlock<EnumInfo>(ID, I,
965 CreateAddFunc(addChild<T, EnumInfo>));
966 }
968 return handleSubBlock<EnumValueInfo>(
969 ID, I, CreateAddFunc(addChild<T, EnumValueInfo>));
970 }
972 return handleSubBlock<TemplateInfo>(ID, I, CreateAddFunc(addTemplate<T>));
973 }
975 return handleSubBlock<TemplateSpecializationInfo>(
976 ID, I, CreateAddFunc(addTemplateSpecialization<T>));
977 }
979 return handleSubBlock<TemplateParamInfo>(
980 ID, I, CreateAddFunc(addTemplateParam<T>));
981 }
982 case BI_TYPEDEF_BLOCK_ID: {
983 return handleSubBlock<TypedefInfo>(ID, I,
984 CreateAddFunc(addChild<T, TypedefInfo>));
985 }
987 return handleSubBlock<ConstraintInfo>(ID, I,
988 CreateAddFunc(addConstraint<T>));
989 }
990 case BI_CONCEPT_BLOCK_ID: {
991 return handleSubBlock<ConceptInfo>(ID, I,
992 CreateAddFunc(addChild<T, ConceptInfo>));
993 }
994 case BI_VAR_BLOCK_ID: {
995 return handleSubBlock<VarInfo>(ID, I, CreateAddFunc(addChild<T, VarInfo>));
996 }
997 case BI_FRIEND_BLOCK_ID: {
998 return handleSubBlock<FriendInfo>(ID, I,
999 CreateAddFunc(addChild<T, FriendInfo>));
1000 }
1001 default:
1002 return llvm::createStringError(llvm::inconvertibleErrorCode(),
1003 "invalid subblock type");
1004 }
1005}
1006
1007llvm::Expected<ClangDocBitcodeReader::Cursor>
1008ClangDocBitcodeReader::skipUntilRecordOrBlock(unsigned &BlockOrRecordID) {
1009 llvm::TimeTraceScope("Reducing infos", "skipUntilRecordOrBlock");
1010 BlockOrRecordID = 0;
1011
1012 while (!Stream.AtEndOfStream()) {
1013 Expected<unsigned> Code = Stream.ReadCode();
1014 if (!Code)
1015 return Code.takeError();
1016
1017 if (*Code >= static_cast<unsigned>(llvm::bitc::FIRST_APPLICATION_ABBREV)) {
1018 BlockOrRecordID = *Code;
1019 return Cursor::Record;
1020 }
1021 switch (static_cast<llvm::bitc::FixedAbbrevIDs>(*Code)) {
1022 case llvm::bitc::ENTER_SUBBLOCK:
1023 if (Expected<unsigned> MaybeID = Stream.ReadSubBlockID())
1024 BlockOrRecordID = MaybeID.get();
1025 else
1026 return MaybeID.takeError();
1027 return Cursor::BlockBegin;
1028 case llvm::bitc::END_BLOCK:
1029 if (Stream.ReadBlockEnd())
1030 return llvm::createStringError(llvm::inconvertibleErrorCode(),
1031 "error at end of block");
1032 return Cursor::BlockEnd;
1033 case llvm::bitc::DEFINE_ABBREV:
1034 if (llvm::Error Err = Stream.ReadAbbrevRecord())
1035 return std::move(Err);
1036 continue;
1037 case llvm::bitc::UNABBREV_RECORD:
1038 return llvm::createStringError(llvm::inconvertibleErrorCode(),
1039 "found unabbreviated record");
1040 case llvm::bitc::FIRST_APPLICATION_ABBREV:
1041 llvm_unreachable("Unexpected abbrev id.");
1042 }
1043 }
1044 llvm_unreachable("Premature stream end.");
1045}
1046
1047llvm::Error ClangDocBitcodeReader::validateStream() {
1048 if (Stream.AtEndOfStream())
1049 return llvm::createStringError(llvm::inconvertibleErrorCode(),
1050 "premature end of stream");
1051
1052 // Sniff for the signature.
1053 for (int Idx = 0; Idx != 4; ++Idx) {
1054 Expected<llvm::SimpleBitstreamCursor::word_t> MaybeRead = Stream.Read(8);
1055 if (!MaybeRead)
1056 return MaybeRead.takeError();
1057 if (MaybeRead.get() != BitCodeConstants::Signature[Idx])
1058 return llvm::createStringError(llvm::inconvertibleErrorCode(),
1059 "invalid bitcode signature");
1060 }
1061 return llvm::Error::success();
1062}
1063
1064llvm::Error ClangDocBitcodeReader::readBlockInfoBlock() {
1065 llvm::TimeTraceScope("Reducing infos", "readBlockInfoBlock");
1066 Expected<std::optional<llvm::BitstreamBlockInfo>> MaybeBlockInfo =
1067 Stream.ReadBlockInfoBlock();
1068 if (!MaybeBlockInfo)
1069 return MaybeBlockInfo.takeError();
1070 BlockInfo = MaybeBlockInfo.get();
1071 if (!BlockInfo)
1072 return llvm::createStringError(llvm::inconvertibleErrorCode(),
1073 "unable to parse BlockInfoBlock");
1074 Stream.setBlockInfo(&*BlockInfo);
1075 return llvm::Error::success();
1076}
1077
1078template <typename T>
1079llvm::Expected<std::unique_ptr<Info>>
1080ClangDocBitcodeReader::createInfo(unsigned ID) {
1081 llvm::TimeTraceScope("Reducing infos", "createInfo");
1082 std::unique_ptr<Info> I = std::make_unique<T>();
1083 if (auto Err = readBlock(ID, static_cast<T *>(I.get())))
1084 return std::move(Err);
1085 return std::unique_ptr<Info>{std::move(I)};
1086}
1087
1088llvm::Expected<std::unique_ptr<Info>>
1089ClangDocBitcodeReader::readBlockToInfo(unsigned ID) {
1090 llvm::TimeTraceScope("Reducing infos", "readBlockToInfo");
1091 switch (ID) {
1093 return createInfo<NamespaceInfo>(ID);
1094 case BI_RECORD_BLOCK_ID:
1095 return createInfo<RecordInfo>(ID);
1096 case BI_ENUM_BLOCK_ID:
1097 return createInfo<EnumInfo>(ID);
1099 return createInfo<TypedefInfo>(ID);
1101 return createInfo<ConceptInfo>(ID);
1103 return createInfo<FunctionInfo>(ID);
1104 case BI_VAR_BLOCK_ID:
1105 return createInfo<VarInfo>(ID);
1106 case BI_FRIEND_BLOCK_ID:
1107 return createInfo<FriendInfo>(ID);
1108 default:
1109 return llvm::createStringError(llvm::inconvertibleErrorCode(),
1110 "cannot create info");
1111 }
1112}
1113
1114// Entry point
1115llvm::Expected<std::vector<std::unique_ptr<Info>>>
1117 std::vector<std::unique_ptr<Info>> Infos;
1118 if (auto Err = validateStream())
1119 return std::move(Err);
1120
1121 // Read the top level blocks.
1122 while (!Stream.AtEndOfStream()) {
1123 Expected<unsigned> MaybeCode = Stream.ReadCode();
1124 if (!MaybeCode)
1125 return MaybeCode.takeError();
1126 if (MaybeCode.get() != llvm::bitc::ENTER_SUBBLOCK)
1127 return llvm::createStringError(llvm::inconvertibleErrorCode(),
1128 "no blocks in input");
1129 Expected<unsigned> MaybeID = Stream.ReadSubBlockID();
1130 if (!MaybeID)
1131 return MaybeID.takeError();
1132 unsigned ID = MaybeID.get();
1133 switch (ID) {
1134 // NamedType and Comment blocks should not appear at the top level
1135 case BI_TYPE_BLOCK_ID:
1140 return llvm::createStringError(llvm::inconvertibleErrorCode(),
1141 "invalid top level block");
1143 case BI_RECORD_BLOCK_ID:
1144 case BI_ENUM_BLOCK_ID:
1147 case BI_VAR_BLOCK_ID:
1148 case BI_FRIEND_BLOCK_ID:
1149 case BI_FUNCTION_BLOCK_ID: {
1150 auto InfoOrErr = readBlockToInfo(ID);
1151 if (!InfoOrErr)
1152 return InfoOrErr.takeError();
1153 Infos.emplace_back(std::move(InfoOrErr.get()));
1154 continue;
1155 }
1157 if (auto Err = readBlock(ID, VersionNumber))
1158 return std::move(Err);
1159 continue;
1160 case llvm::bitc::BLOCKINFO_BLOCK_ID:
1161 if (auto Err = readBlockInfoBlock())
1162 return std::move(Err);
1163 continue;
1164 default:
1165 if (llvm::Error Err = Stream.SkipBlock())
1166 return std::move(Err);
1167 continue;
1168 }
1169 }
1170 return std::move(Infos);
1171}
1172
1173} // namespace doc
1174} // 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::optional< TemplateInfo > Template