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