clang-tools 23.0.0git
BitcodeReader.cpp
Go to the documentation of this file.
1//===-- BitcodeReader.cpp - ClangDoc Bitcode Reader ------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "BitcodeReader.h"
10#include "llvm/Support/Error.h"
11#include "llvm/Support/ErrorHandling.h"
12#include "llvm/Support/TimeProfiler.h"
13#include "llvm/Support/raw_ostream.h"
14#include <optional>
15
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, llvm::StringRef &Field,
32 llvm::StringRef Blob) {
33 Field = internString(Blob);
34 return llvm::Error::success();
35}
36
37static llvm::Error decodeRecord(const Record &R, SymbolID &Field,
38 llvm::StringRef Blob) {
40 return llvm::createStringError(llvm::inconvertibleErrorCode(),
41 "incorrect USR size");
42
43 // First position in the record is the length of the following array, so we
44 // copy the following elements to the field.
45 for (int I = 0, E = R[0]; I < E; ++I)
46 Field[I] = R[I + 1];
47 return llvm::Error::success();
48}
49
50static llvm::Error decodeRecord(const Record &R, bool &Field,
51 llvm::StringRef Blob) {
52 Field = R[0] != 0;
53 return llvm::Error::success();
54}
55
56static llvm::Error decodeRecord(const Record &R, AccessSpecifier &Field,
57 llvm::StringRef Blob) {
58 switch (R[0]) {
59 case AS_public:
60 case AS_private:
61 case AS_protected:
62 case AS_none:
63 Field = (AccessSpecifier)R[0];
64 return llvm::Error::success();
65 }
66 llvm_unreachable("invalid value for AccessSpecifier");
67}
68
69static llvm::Error decodeRecord(const Record &R, TagTypeKind &Field,
70 llvm::StringRef Blob) {
71 switch (static_cast<TagTypeKind>(R[0])) {
72 case TagTypeKind::Struct:
73 case TagTypeKind::Interface:
74 case TagTypeKind::Union:
75 case TagTypeKind::Class:
76 case TagTypeKind::Enum:
77 Field = static_cast<TagTypeKind>(R[0]);
78 return llvm::Error::success();
79 }
80 return llvm::createStringError(llvm::inconvertibleErrorCode(),
81 "invalid value for TagTypeKind");
82}
83
84static llvm::Error decodeRecord(const Record &R, std::optional<Location> &Field,
85 llvm::StringRef Blob) {
86 if (R[0] > INT_MAX)
87 return llvm::createStringError(llvm::inconvertibleErrorCode(),
88 "integer too large to parse");
89 Field.emplace(static_cast<int>(R[0]), static_cast<int>(R[1]), Blob,
90 static_cast<bool>(R[2]));
91 return llvm::Error::success();
92}
93
94static llvm::Error decodeRecord(const Record &R, InfoType &Field,
95 llvm::StringRef Blob) {
96 switch (auto IT = static_cast<InfoType>(R[0])) {
106 Field = IT;
107 return llvm::Error::success();
108 }
109 return llvm::createStringError(llvm::inconvertibleErrorCode(),
110 "invalid value for InfoType");
111}
112
113static llvm::Error decodeRecord(const Record &R, FieldId &Field,
114 llvm::StringRef Blob) {
115 switch (auto F = static_cast<FieldId>(R[0])) {
119 case FieldId::F_type:
125 Field = F;
126 return llvm::Error::success();
127 }
128 return llvm::createStringError(llvm::inconvertibleErrorCode(),
129 "invalid value for FieldId");
130}
131
132static llvm::Error decodeRecord(const Record &R,
134 llvm::StringRef Blob) {
135 if (R[0] > INT_MAX)
136 return llvm::createStringError(llvm::inconvertibleErrorCode(),
137 "integer too large to parse");
138 Field.emplace_back(static_cast<int>(R[0]), static_cast<int>(R[1]), Blob,
139 static_cast<bool>(R[2]));
140 return llvm::Error::success();
141}
142
143static llvm::Error parseRecord(const Record &R, unsigned ID,
144 llvm::StringRef Blob, const unsigned VersionNo) {
145 if (ID == VERSION && R[0] == VersionNo)
146 return llvm::Error::success();
147 return llvm::createStringError(llvm::inconvertibleErrorCode(),
148 "mismatched bitcode version number");
149}
150
151static llvm::Error parseRecord(const Record &R, unsigned ID,
152 llvm::StringRef Blob, NamespaceInfo *I) {
153 switch (ID) {
154 case NAMESPACE_USR:
155 return decodeRecord(R, I->USR, Blob);
156 case NAMESPACE_NAME:
157 return decodeRecord(R, I->Name, Blob);
158 case NAMESPACE_PATH:
159 return decodeRecord(R, I->Path, Blob);
161 return decodeRecord(R, I->ParentUSR, 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);
188 return decodeRecord(R, I->ParentUSR, Blob);
189 default:
190 return llvm::createStringError(llvm::inconvertibleErrorCode(),
191 "invalid field for RecordInfo");
192 }
193}
194
195static llvm::Error parseRecord(const Record &R, unsigned ID,
196 llvm::StringRef Blob, BaseRecordInfo *I) {
197 switch (ID) {
198 case BASE_RECORD_USR:
199 return decodeRecord(R, I->USR, Blob);
200 case BASE_RECORD_NAME:
201 return decodeRecord(R, I->Name, Blob);
202 case BASE_RECORD_PATH:
203 return decodeRecord(R, I->Path, Blob);
205 return decodeRecord(R, I->TagType, Blob);
207 return decodeRecord(R, I->IsVirtual, Blob);
209 return decodeRecord(R, I->Access, Blob);
211 return decodeRecord(R, I->IsParent, Blob);
212 default:
213 return llvm::createStringError(llvm::inconvertibleErrorCode(),
214 "invalid field for BaseRecordInfo");
215 }
216}
217
218static llvm::Error parseRecord(const Record &R, unsigned ID,
219 llvm::StringRef Blob, EnumInfo *I) {
220 switch (ID) {
221 case ENUM_USR:
222 return decodeRecord(R, I->USR, Blob);
223 case ENUM_NAME:
224 return decodeRecord(R, I->Name, Blob);
225 case ENUM_DEFLOCATION:
226 return decodeRecord(R, I->DefLoc, Blob);
227 case ENUM_LOCATION:
228 return decodeRecord(R, I->Loc, Blob);
229 case ENUM_SCOPED:
230 return decodeRecord(R, I->Scoped, Blob);
231 default:
232 return llvm::createStringError(llvm::inconvertibleErrorCode(),
233 "invalid field for EnumInfo");
234 }
235}
236
237static llvm::Error parseRecord(const Record &R, unsigned ID,
238 llvm::StringRef Blob, TypedefInfo *I) {
239 switch (ID) {
240 case TYPEDEF_USR:
241 return decodeRecord(R, I->USR, Blob);
242 case TYPEDEF_NAME:
243 return decodeRecord(R, I->Name, Blob);
245 return decodeRecord(R, I->DefLoc, Blob);
246 case TYPEDEF_IS_USING:
247 return decodeRecord(R, I->IsUsing, Blob);
248 default:
249 return llvm::createStringError(llvm::inconvertibleErrorCode(),
250 "invalid field for TypedefInfo");
251 }
252}
253
254static llvm::Error parseRecord(const Record &R, unsigned ID,
255 llvm::StringRef Blob, EnumValueInfo *I) {
256 switch (ID) {
257 case ENUM_VALUE_NAME:
258 return decodeRecord(R, I->Name, Blob);
259 case ENUM_VALUE_VALUE:
260 return decodeRecord(R, I->Value, Blob);
261 case ENUM_VALUE_EXPR:
262 return decodeRecord(R, I->ValueExpr, Blob);
263 default:
264 return llvm::createStringError(llvm::inconvertibleErrorCode(),
265 "invalid field for EnumValueInfo");
266 }
267}
268
269static llvm::Error parseRecord(const Record &R, unsigned ID,
270 llvm::StringRef Blob, FunctionInfo *I) {
271 switch (ID) {
272 case FUNCTION_USR:
273 return decodeRecord(R, I->USR, Blob);
274 case FUNCTION_NAME:
275 return decodeRecord(R, I->Name, Blob);
277 return decodeRecord(R, I->DefLoc, Blob);
279 return decodeRecord(R, I->Loc, Blob);
280 case FUNCTION_ACCESS:
281 return decodeRecord(R, I->Access, Blob);
283 return decodeRecord(R, I->IsMethod, Blob);
285 return decodeRecord(R, I->IsStatic, Blob);
286 default:
287 return llvm::createStringError(llvm::inconvertibleErrorCode(),
288 "invalid field for FunctionInfo");
289 }
290}
291
292static llvm::Error parseRecord(const Record &R, unsigned ID,
293 llvm::StringRef Blob, TypeInfo *I) {
294 switch (ID) {
295 case TYPE_IS_BUILTIN:
296 return decodeRecord(R, I->IsBuiltIn, Blob);
297 case TYPE_IS_TEMPLATE:
298 return decodeRecord(R, I->IsTemplate, Blob);
299 default:
300 return llvm::createStringError(llvm::inconvertibleErrorCode(),
301 "invalid field for TypeInfo");
302 }
303}
304
305static llvm::Error parseRecord(const Record &R, unsigned ID,
306 llvm::StringRef Blob, FieldTypeInfo *I) {
307 switch (ID) {
308 case FIELD_TYPE_NAME:
309 return decodeRecord(R, I->Name, Blob);
311 return decodeRecord(R, I->DefaultValue, Blob);
313 return decodeRecord(R, I->IsBuiltIn, Blob);
315 return decodeRecord(R, I->IsTemplate, Blob);
316 default:
317 return llvm::createStringError(llvm::inconvertibleErrorCode(),
318 "invalid field for TypeInfo");
319 }
320}
321
322static llvm::Error parseRecord(const Record &R, unsigned ID,
323 llvm::StringRef Blob, MemberTypeInfo *I) {
324 switch (ID) {
325 case MEMBER_TYPE_NAME:
326 return decodeRecord(R, I->Name, Blob);
328 return decodeRecord(R, I->Access, Blob);
330 return decodeRecord(R, I->IsStatic, Blob);
332 return decodeRecord(R, I->IsBuiltIn, Blob);
334 return decodeRecord(R, I->IsTemplate, Blob);
335 default:
336 return llvm::createStringError(llvm::inconvertibleErrorCode(),
337 "invalid field for MemberTypeInfo");
338 }
339}
340
341static llvm::Error parseRecord(const Record &R, unsigned ID,
342 llvm::StringRef Blob, CommentInfo *I,
346 llvm::SmallString<16> KindStr;
347 switch (ID) {
348 case COMMENT_KIND:
349 if (llvm::Error Err = decodeRecord(R, KindStr, Blob))
350 return Err;
351 I->Kind = stringToCommentKind(KindStr);
352 return llvm::Error::success();
353 case COMMENT_TEXT:
354 return decodeRecord(R, I->Text, Blob);
355 case COMMENT_NAME:
356 return decodeRecord(R, I->Name, Blob);
358 return decodeRecord(R, I->Direction, Blob);
360 return decodeRecord(R, I->ParamName, Blob);
362 return decodeRecord(R, I->CloseName, Blob);
363 case COMMENT_ATTRKEY:
364 AttrKeys.push_back(internString(Blob));
365 return llvm::Error::success();
366 case COMMENT_ATTRVAL:
367 AttrValues.push_back(internString(Blob));
368 return llvm::Error::success();
369 case COMMENT_ARG:
370 Args.push_back(internString(Blob));
371 return llvm::Error::success();
373 return decodeRecord(R, I->SelfClosing, Blob);
374 case COMMENT_EXPLICIT:
375 return decodeRecord(R, I->Explicit, Blob);
376 default:
377 return llvm::createStringError(llvm::inconvertibleErrorCode(),
378 "invalid field for CommentInfo");
379 }
380}
381
382template <typename T, typename BlockBeginHandler, typename BlockEndHandler,
383 typename RecordHandler>
384llvm::Error
385ClangDocBitcodeReader::parseBlock(unsigned ID, T I, BlockBeginHandler &&BBH,
386 BlockEndHandler &&BEH, RecordHandler &&RH) {
387 llvm::TimeTraceScope("Reducing infos", "readBlock");
388 if (llvm::Error Err = Stream.EnterSubBlock(ID))
389 return Err;
390
391 while (true) {
392 unsigned BlockOrCode = 0;
393 llvm::Expected<Cursor> C = skipUntilRecordOrBlock(BlockOrCode);
394 if (!C)
395 return C.takeError();
396
397 switch (*C) {
398 case Cursor::BadBlock:
399 return llvm::createStringError(llvm::inconvertibleErrorCode(),
400 "bad block found");
401 case Cursor::BlockEnd:
402 if (llvm::Error Err = BEH())
403 return Err;
404 return llvm::Error::success();
405 case Cursor::BlockBegin: {
406 llvm::Expected<bool> Handled = BBH(BlockOrCode);
407 if (!Handled)
408 return Handled.takeError();
409 if (*Handled)
410 continue;
411
412 if (llvm::Error Err = readSubBlock(BlockOrCode, I)) {
413 if (llvm::Error Skipped = Stream.SkipBlock())
414 return joinErrors(std::move(Err), std::move(Skipped));
415 return Err;
416 }
417 continue;
418 }
419 case Cursor::Record:
420 break;
421 }
422
423 if (llvm::Error Err = RH(BlockOrCode))
424 return Err;
425 }
426}
427
428template <>
429llvm::Error ClangDocBitcodeReader::readBlock(unsigned ID, CommentInfo *I) {
430 llvm::SmallVector<CommentInfo> LocalChildren;
431 llvm::SmallVector<StringRef> AttrKeys;
432 llvm::SmallVector<StringRef> AttrValues;
433 llvm::SmallVector<StringRef> Args;
434
435 return parseBlock(
436 ID, I,
437 [&](unsigned BlockOrCode) -> llvm::Expected<bool> {
438 if (BlockOrCode == BI_COMMENT_BLOCK_ID) {
439 CommentInfo Child;
440 if (llvm::Error Err = readBlock(BlockOrCode, &Child))
441 return std::move(Err);
442 LocalChildren.push_back(std::move(Child));
443 return true;
444 }
445 return false;
446 },
447 [&]() -> llvm::Error {
448 if (!LocalChildren.empty())
449 I->Children =
451 if (!AttrKeys.empty()) {
452 StringRef *KeysMem =
453 TransientArena.Allocate<StringRef>(AttrKeys.size());
454 std::uninitialized_copy(AttrKeys.begin(), AttrKeys.end(), KeysMem);
455 I->AttrKeys = llvm::ArrayRef<StringRef>(KeysMem, AttrKeys.size());
456 }
457 if (!AttrValues.empty()) {
458 StringRef *ValuesMem =
459 TransientArena.Allocate<StringRef>(AttrValues.size());
460 std::uninitialized_copy(AttrValues.begin(), AttrValues.end(),
461 ValuesMem);
462 I->AttrValues =
463 llvm::ArrayRef<StringRef>(ValuesMem, AttrValues.size());
464 }
465 if (!Args.empty()) {
466 StringRef *ArgsMem = TransientArena.Allocate<StringRef>(Args.size());
467 std::uninitialized_copy(Args.begin(), Args.end(), ArgsMem);
468 I->Args = llvm::ArrayRef<StringRef>(ArgsMem, Args.size());
469 }
470 return llvm::Error::success();
471 },
472 [&](unsigned BlockOrCode) -> llvm::Error {
473 Record R;
474 llvm::StringRef Blob;
475 llvm::Expected<unsigned> MaybeRecID =
476 Stream.readRecord(BlockOrCode, R, &Blob);
477 if (!MaybeRecID)
478 return MaybeRecID.takeError();
479 return parseRecord(R, MaybeRecID.get(), Blob, I, AttrKeys, AttrValues,
480 Args);
481 });
482}
483
484static llvm::Error parseRecord(const Record &R, unsigned ID,
485 llvm::StringRef Blob, Reference *I, FieldId &F) {
486 switch (ID) {
487 case REFERENCE_USR:
488 return decodeRecord(R, I->USR, Blob);
489 case REFERENCE_NAME:
490 return decodeRecord(R, I->Name, Blob);
492 return decodeRecord(R, I->QualName, Blob);
493 case REFERENCE_TYPE:
494 return decodeRecord(R, I->RefType, Blob);
495 case REFERENCE_PATH:
496 return decodeRecord(R, I->Path, Blob);
497 case REFERENCE_FIELD:
498 return decodeRecord(R, F, Blob);
499 case REFERENCE_FILE:
500 return decodeRecord(R, I->DocumentationFileName, Blob);
501 default:
502 return llvm::createStringError(llvm::inconvertibleErrorCode(),
503 "invalid field for Reference");
504 }
505}
506
507static llvm::Error parseRecord(const Record &R, unsigned ID,
508 llvm::StringRef Blob, TemplateInfo *I) {
509 // Currently there are no child records of TemplateInfo (only child blocks).
510 return llvm::createStringError(llvm::inconvertibleErrorCode(),
511 "invalid field for TemplateParamInfo");
512}
513
514static llvm::Error parseRecord(const Record &R, unsigned ID,
515 llvm::StringRef Blob,
518 return decodeRecord(R, I->SpecializationOf, Blob);
519 return llvm::createStringError(llvm::inconvertibleErrorCode(),
520 "invalid field for TemplateParamInfo");
521}
522
523static llvm::Error parseRecord(const Record &R, unsigned ID,
524 llvm::StringRef Blob, TemplateParamInfo *I) {
525 if (ID == TEMPLATE_PARAM_CONTENTS)
526 return decodeRecord(R, I->Contents, Blob);
527 return llvm::createStringError(llvm::inconvertibleErrorCode(),
528 "invalid field for TemplateParamInfo");
529}
530
531static llvm::Error parseRecord(const Record &R, unsigned ID,
532 llvm::StringRef Blob, ConceptInfo *I) {
533 switch (ID) {
534 case CONCEPT_USR:
535 return decodeRecord(R, I->USR, Blob);
536 case CONCEPT_NAME:
537 return decodeRecord(R, I->Name, Blob);
538 case CONCEPT_IS_TYPE:
539 return decodeRecord(R, I->IsType, Blob);
541 return decodeRecord(R, I->ConstraintExpression, Blob);
543 return decodeRecord(R, I->DefLoc, Blob);
544 }
545 llvm_unreachable("invalid field for ConceptInfo");
546}
547
548static llvm::Error parseRecord(const Record &R, unsigned ID,
549 llvm::StringRef Blob, ConstraintInfo *I) {
550 if (ID == CONSTRAINT_EXPRESSION)
551 return decodeRecord(R, I->ConstraintExpr, Blob);
552 return llvm::createStringError(llvm::inconvertibleErrorCode(),
553 "invalid field for ConstraintInfo");
554}
555
556static llvm::Error parseRecord(const Record &R, unsigned ID,
557 llvm::StringRef Blob, VarInfo *I) {
558 switch (ID) {
559 case VAR_USR:
560 return decodeRecord(R, I->USR, Blob);
561 case VAR_NAME:
562 return decodeRecord(R, I->Name, Blob);
563 case VAR_DEFLOCATION:
564 return decodeRecord(R, I->DefLoc, Blob);
565 case VAR_IS_STATIC:
566 return decodeRecord(R, I->IsStatic, Blob);
567 default:
568 return llvm::createStringError(llvm::inconvertibleErrorCode(),
569 "invalid field for VarInfo");
570 }
571}
572
573static llvm::Error parseRecord(const Record &R, unsigned ID, StringRef Blob,
574 FriendInfo *F) {
575 if (ID == FRIEND_IS_CLASS) {
576 return decodeRecord(R, F->IsClass, Blob);
577 }
578 return llvm::createStringError(llvm::inconvertibleErrorCode(),
579 "invalid field for Friend");
580}
581
582template <typename T> static llvm::Expected<CommentInfo *> getCommentInfo(T I) {
583 return llvm::createStringError(llvm::inconvertibleErrorCode(),
584 "invalid type cannot contain CommentInfo");
585}
586
587template <> llvm::Expected<CommentInfo *> getCommentInfo(FunctionInfo *I) {
588 return &I->Description.emplace_back();
589}
590
591template <> llvm::Expected<CommentInfo *> getCommentInfo(NamespaceInfo *I) {
592 return &I->Description.emplace_back();
593}
594
595template <> llvm::Expected<CommentInfo *> getCommentInfo(RecordInfo *I) {
596 return &I->Description.emplace_back();
597}
598
599template <> llvm::Expected<CommentInfo *> getCommentInfo(MemberTypeInfo *I) {
600 return &I->Description.emplace_back();
601}
602
603template <> llvm::Expected<CommentInfo *> getCommentInfo(EnumInfo *I) {
604 return &I->Description.emplace_back();
605}
606
607template <> llvm::Expected<CommentInfo *> getCommentInfo(TypedefInfo *I) {
608 return &I->Description.emplace_back();
609}
610
611template <> llvm::Expected<CommentInfo *> getCommentInfo(EnumValueInfo *I) {
612 return &I->Description.emplace_back();
613}
614
615template <> llvm::Expected<CommentInfo *> getCommentInfo(ConceptInfo *I) {
616 return &I->Description.emplace_back();
617}
618
619template <> Expected<CommentInfo *> getCommentInfo(VarInfo *I) {
620 return &I->Description.emplace_back();
621}
622
623template <> Expected<CommentInfo *> getCommentInfo(FriendInfo *I) {
624 return &I->Description.emplace_back();
625}
626
627// When readSubBlock encounters a TypeInfo sub-block, it calls addTypeInfo on
628// the parent block to set it. The template specializations define what to do
629// for each supported parent block.
630template <typename T, typename TTypeInfo>
631static llvm::Error addTypeInfo(T I, TTypeInfo &&TI) {
632 return llvm::createStringError(llvm::inconvertibleErrorCode(),
633 "invalid type cannot contain TypeInfo");
634}
635
636template <> llvm::Error addTypeInfo(RecordInfo *I, MemberTypeInfo &&T) {
637 I->Members.emplace_back(std::move(T));
638 return llvm::Error::success();
639}
640
641template <> llvm::Error addTypeInfo(BaseRecordInfo *I, MemberTypeInfo &&T) {
642 I->Members.emplace_back(std::move(T));
643 return llvm::Error::success();
644}
645
646template <> llvm::Error addTypeInfo(FunctionInfo *I, TypeInfo &&T) {
647 I->ReturnType = std::move(T);
648 return llvm::Error::success();
649}
650
651template <> llvm::Error addTypeInfo(FunctionInfo *I, FieldTypeInfo &&T) {
652 I->Params.emplace_back(std::move(T));
653 return llvm::Error::success();
654}
655
656template <> llvm::Error addTypeInfo(FriendInfo *I, TypeInfo &&T) {
657 I->ReturnType.emplace(std::move(T));
658 return llvm::Error::success();
659}
660
661template <> llvm::Error addTypeInfo(EnumInfo *I, TypeInfo &&T) {
662 I->BaseType = std::move(T);
663 return llvm::Error::success();
664}
665
666template <> llvm::Error addTypeInfo(TypedefInfo *I, TypeInfo &&T) {
667 I->Underlying = std::move(T);
668 return llvm::Error::success();
669}
670
671template <> llvm::Error addTypeInfo(VarInfo *I, TypeInfo &&T) {
672 I->Type = std::move(T);
673 return llvm::Error::success();
674}
675
676template <typename T>
677static llvm::Error addReference(T I, Reference &&R, FieldId F) {
678 return llvm::createStringError(llvm::inconvertibleErrorCode(),
679 "invalid type cannot contain Reference");
680}
681
682template <> llvm::Error addReference(VarInfo *I, Reference &&R, FieldId F) {
683 switch (F) {
685 I->Namespace.emplace_back(std::move(R));
686 return llvm::Error::success();
687 default:
688 return llvm::createStringError(llvm::inconvertibleErrorCode(),
689 "VarInfo cannot contain this Reference");
690 }
691}
692
693template <> llvm::Error addReference(TypeInfo *I, Reference &&R, FieldId F) {
694 switch (F) {
695 case FieldId::F_type:
696 I->Type = std::move(R);
697 return llvm::Error::success();
698 default:
699 return llvm::createStringError(llvm::inconvertibleErrorCode(),
700 "invalid type cannot contain Reference");
701 }
702}
703
704template <>
706 switch (F) {
707 case FieldId::F_type:
708 I->Type = std::move(R);
709 return llvm::Error::success();
710 default:
711 return llvm::createStringError(llvm::inconvertibleErrorCode(),
712 "invalid type cannot contain Reference");
713 }
714}
715
716template <>
718 switch (F) {
719 case FieldId::F_type:
720 I->Type = std::move(R);
721 return llvm::Error::success();
722 default:
723 return llvm::createStringError(llvm::inconvertibleErrorCode(),
724 "invalid type cannot contain Reference");
725 }
726}
727
728template <> llvm::Error addReference(EnumInfo *I, Reference &&R, FieldId F) {
729 switch (F) {
731 I->Namespace.emplace_back(std::move(R));
732 return llvm::Error::success();
733 default:
734 return llvm::createStringError(llvm::inconvertibleErrorCode(),
735 "invalid type cannot contain Reference");
736 }
737}
738
739template <> llvm::Error addReference(TypedefInfo *I, Reference &&R, FieldId F) {
740 switch (F) {
742 I->Namespace.emplace_back(std::move(R));
743 return llvm::Error::success();
744 default:
745 return llvm::createStringError(llvm::inconvertibleErrorCode(),
746 "invalid type cannot contain Reference");
747 }
748}
749
750template <>
752 switch (F) {
754 I->Namespace.emplace_back(std::move(R));
755 return llvm::Error::success();
757 Reference *NewR = allocatePtr<Reference>(TransientArena, std::move(R));
758 I->Children.Namespaces.push_back(*NewR);
759 return llvm::Error::success();
760 }
762 I->Children.Records.emplace_back(std::move(R));
763 return llvm::Error::success();
764 default:
765 return llvm::createStringError(llvm::inconvertibleErrorCode(),
766 "invalid type cannot contain Reference");
767 }
768}
769
770template <>
772 switch (F) {
774 I->Namespace.emplace_back(std::move(R));
775 return llvm::Error::success();
777 I->Parent = std::move(R);
778 return llvm::Error::success();
779 default:
780 return llvm::createStringError(llvm::inconvertibleErrorCode(),
781 "invalid type cannot contain Reference");
782 }
783}
784
785template <> llvm::Error addReference(RecordInfo *I, Reference &&R, FieldId F) {
786 switch (F) {
788 I->Namespace.emplace_back(std::move(R));
789 return llvm::Error::success();
791 I->Parents.emplace_back(std::move(R));
792 return llvm::Error::success();
794 I->VirtualParents.emplace_back(std::move(R));
795 return llvm::Error::success();
797 I->Children.Records.emplace_back(std::move(R));
798 return llvm::Error::success();
799 default:
800 return llvm::createStringError(llvm::inconvertibleErrorCode(),
801 "invalid type cannot contain Reference");
802 }
803}
804
805template <>
807 if (F == FieldId::F_concept) {
808 I->ConceptRef = std::move(R);
809 return llvm::Error::success();
810 }
811 return llvm::createStringError(
812 llvm::inconvertibleErrorCode(),
813 "ConstraintInfo cannot contain this Reference");
814}
815
816template <>
817llvm::Error addReference(FriendInfo *Friend, Reference &&R, FieldId F) {
818 if (F == FieldId::F_friend) {
819 Friend->Ref = std::move(R);
820 return llvm::Error::success();
821 }
822 return llvm::createStringError(llvm::inconvertibleErrorCode(),
823 "Friend cannot contain this Reference");
824}
825
826template <typename T, typename ChildInfoType>
827static void addChild(T I, ChildInfoType &&R) {
828 ExitOnErr(llvm::createStringError(llvm::inconvertibleErrorCode(),
829 "invalid child type for info"));
830}
831
832// Namespace children:
833template <> void addChild(NamespaceInfo *I, FunctionInfo &&R) {
834 I->Children.Functions.emplace_back(std::move(R));
835}
836template <> void addChild(NamespaceInfo *I, EnumInfo &&R) {
837 I->Children.Enums.emplace_back(std::move(R));
838}
839template <> void addChild(NamespaceInfo *I, TypedefInfo &&R) {
840 I->Children.Typedefs.emplace_back(std::move(R));
841}
842template <> void addChild(NamespaceInfo *I, ConceptInfo &&R) {
843 I->Children.Concepts.emplace_back(std::move(R));
844}
845template <> void addChild(NamespaceInfo *I, VarInfo &&R) {
846 I->Children.Variables.emplace_back(std::move(R));
847}
848
849// Record children:
850template <> void addChild(RecordInfo *I, FunctionInfo &&R) {
851 I->Children.Functions.emplace_back(std::move(R));
852}
853template <> void addChild(RecordInfo *I, EnumInfo &&R) {
854 I->Children.Enums.emplace_back(std::move(R));
855}
856template <> void addChild(RecordInfo *I, TypedefInfo &&R) {
857 I->Children.Typedefs.emplace_back(std::move(R));
858}
859template <> void addChild(RecordInfo *I, FriendInfo &&R) {
860 I->Friends.emplace_back(std::move(R));
861}
862
863// Other types of children:
864template <> void addChild(EnumInfo *I, EnumValueInfo &&R) {
865 I->Members.emplace_back(std::move(R));
866}
867template <> void addChild(RecordInfo *I, BaseRecordInfo &&R) {
868 I->Bases.emplace_back(std::move(R));
869}
870template <> void addChild(BaseRecordInfo *I, FunctionInfo &&R) {
871 I->Children.Functions.emplace_back(std::move(R));
872}
873
874// TemplateParam children. These go into either a TemplateInfo (for template
875// parameters) or TemplateSpecializationInfo (for the specialization's
876// parameters).
877template <typename T> static void addTemplateParam(T I, TemplateParamInfo &&P) {
878 ExitOnErr(
879 llvm::createStringError(llvm::inconvertibleErrorCode(),
880 "invalid container for template parameter"));
881}
883 I->Params.emplace_back(std::move(P));
884}
885template <>
887 I->Params.emplace_back(std::move(P));
888}
889
890// Template info. These apply to either records or functions.
891template <typename T> static void addTemplate(T I, TemplateInfo &&P) {
892 ExitOnErr(llvm::createStringError(llvm::inconvertibleErrorCode(),
893 "invalid container for template info"));
894}
895template <> void addTemplate(RecordInfo *I, TemplateInfo &&P) {
896 I->Template.emplace(std::move(P));
897}
898template <> void addTemplate(FunctionInfo *I, TemplateInfo &&P) {
899 I->Template.emplace(std::move(P));
900}
901template <> void addTemplate(ConceptInfo *I, TemplateInfo &&P) {
902 I->Template = std::move(P);
903}
904template <> void addTemplate(FriendInfo *I, TemplateInfo &&P) {
905 I->Template.emplace(std::move(P));
906}
907template <> void addTemplate(TypedefInfo *I, TemplateInfo &&P) {
908 I->Template.emplace(std::move(P));
909}
910
911// Template specializations go only into template records.
912template <typename T>
914 ExitOnErr(llvm::createStringError(
915 llvm::inconvertibleErrorCode(),
916 "invalid container for template specialization info"));
917}
918template <>
921 I->Specialization.emplace(std::move(TSI));
922}
923
924template <typename T> static void addConstraint(T I, ConstraintInfo &&C) {
925 ExitOnErr(llvm::createStringError(llvm::inconvertibleErrorCode(),
926 "invalid container for constraint info"));
927}
928template <> void addConstraint(TemplateInfo *I, ConstraintInfo &&C) {
929 I->Constraints.emplace_back(std::move(C));
930}
931
932// Read records from bitcode into a given info.
933template <typename T>
934llvm::Error ClangDocBitcodeReader::readRecord(unsigned ID, T I) {
935 Record R;
936 llvm::StringRef Blob;
937 llvm::Expected<unsigned> MaybeRecID = Stream.readRecord(ID, R, &Blob);
938 if (!MaybeRecID)
939 return MaybeRecID.takeError();
940 return parseRecord(R, MaybeRecID.get(), Blob, I);
941}
942
943template <>
944llvm::Error ClangDocBitcodeReader::readRecord(unsigned ID, Reference *I) {
945 llvm::TimeTraceScope("Reducing infos", "readRecord");
946 Record R;
947 llvm::StringRef Blob;
948 llvm::Expected<unsigned> MaybeRecID = Stream.readRecord(ID, R, &Blob);
949 if (!MaybeRecID)
950 return MaybeRecID.takeError();
951 return parseRecord(R, MaybeRecID.get(), Blob, I, CurrentReferenceField);
952}
953
954// Read a block of records into a single info.
955template <typename T>
956llvm::Error ClangDocBitcodeReader::readBlock(unsigned ID, T I) {
957 return parseBlock(
958 ID, I, [](unsigned BlockOrCode) -> llvm::Expected<bool> { return false; },
959 []() -> llvm::Error { return llvm::Error::success(); },
960 [&](unsigned BlockOrCode) -> llvm::Error {
961 return readRecord(BlockOrCode, I);
962 });
963}
964
965template <>
966llvm::Error ClangDocBitcodeReader::readBlock(unsigned ID, FriendInfo *I) {
967 llvm::SmallVector<FieldTypeInfo, 4> LocalParams;
968
969 return parseBlock(
970 ID, I,
971 [&](unsigned BlockOrCode) -> llvm::Expected<bool> {
972 if (BlockOrCode == BI_FIELD_TYPE_BLOCK_ID) {
973 FieldTypeInfo FI;
974 if (auto Err = readBlock(BlockOrCode, &FI))
975 return std::move(Err);
976 LocalParams.push_back(std::move(FI));
977 return true;
978 }
979 return false;
980 },
981 [&]() -> llvm::Error {
982 if (!LocalParams.empty())
984 return llvm::Error::success();
985 },
986 [&](unsigned BlockOrCode) -> llvm::Error {
987 return readRecord(BlockOrCode, I);
988 });
989}
990
991// TODO: fix inconsistentent returning of errors in add callbacks.
992// Once that's fixed, we only need one handleSubBlock.
993template <typename InfoType, typename T, typename Callback>
994llvm::Error ClangDocBitcodeReader::handleSubBlock(unsigned ID, T Parent,
995 Callback Function) {
997 if (auto Err = readBlock(ID, &Info))
998 return Err;
999 Function(Parent, std::move(Info));
1000 return llvm::Error::success();
1001}
1002
1003template <typename InfoType, typename T, typename Callback>
1004llvm::Error ClangDocBitcodeReader::handleTypeSubBlock(unsigned ID, T Parent,
1005 Callback Function) {
1006 InfoType Info;
1007 if (auto Err = readBlock(ID, &Info))
1008 return Err;
1009 if (auto Err = Function(Parent, std::move(Info)))
1010 return Err;
1011 return llvm::Error::success();
1012}
1013
1014template <typename T>
1015llvm::Error ClangDocBitcodeReader::readSubBlock(unsigned ID, T I) {
1016 llvm::TimeTraceScope("Reducing infos", "readSubBlock");
1017
1018 static auto CreateAddFunc = [](auto AddFunc) {
1019 return [AddFunc](auto Parent, auto Child) {
1020 return AddFunc(Parent, std::move(Child));
1021 };
1022 };
1023
1024 switch (ID) {
1025 // Blocks can only have certain types of sub blocks.
1026 case BI_COMMENT_BLOCK_ID: {
1027 auto Comment = getCommentInfo(I);
1028 if (!Comment)
1029 return Comment.takeError();
1030 if (auto Err = readBlock(ID, Comment.get()))
1031 return Err;
1032 return llvm::Error::success();
1033 }
1034 case BI_TYPE_BLOCK_ID: {
1035 return handleTypeSubBlock<TypeInfo>(
1036 ID, I, CreateAddFunc(addTypeInfo<T, TypeInfo>));
1037 }
1039 return handleTypeSubBlock<FieldTypeInfo>(
1040 ID, I, CreateAddFunc(addTypeInfo<T, FieldTypeInfo>));
1041 }
1043 return handleTypeSubBlock<MemberTypeInfo>(
1044 ID, I, CreateAddFunc(addTypeInfo<T, MemberTypeInfo>));
1045 }
1046 case BI_REFERENCE_BLOCK_ID: {
1047 Reference R;
1048 if (auto Err = readBlock(ID, &R))
1049 return Err;
1050 if (auto Err = addReference(I, std::move(R), CurrentReferenceField))
1051 return Err;
1052 return llvm::Error::success();
1053 }
1054 case BI_FUNCTION_BLOCK_ID: {
1055 return handleSubBlock<FunctionInfo>(
1056 ID, I, CreateAddFunc(addChild<T, FunctionInfo>));
1057 }
1059 return handleSubBlock<BaseRecordInfo>(
1060 ID, I, CreateAddFunc(addChild<T, BaseRecordInfo>));
1061 }
1062 case BI_ENUM_BLOCK_ID: {
1063 return handleSubBlock<EnumInfo>(ID, I,
1064 CreateAddFunc(addChild<T, EnumInfo>));
1065 }
1067 return handleSubBlock<EnumValueInfo>(
1068 ID, I, CreateAddFunc(addChild<T, EnumValueInfo>));
1069 }
1070 case BI_TEMPLATE_BLOCK_ID: {
1071 return handleSubBlock<TemplateInfo>(ID, I, CreateAddFunc(addTemplate<T>));
1072 }
1074 return handleSubBlock<TemplateSpecializationInfo>(
1075 ID, I, CreateAddFunc(addTemplateSpecialization<T>));
1076 }
1078 return handleSubBlock<TemplateParamInfo>(
1079 ID, I, CreateAddFunc(addTemplateParam<T>));
1080 }
1081 case BI_TYPEDEF_BLOCK_ID: {
1082 return handleSubBlock<TypedefInfo>(ID, I,
1083 CreateAddFunc(addChild<T, TypedefInfo>));
1084 }
1086 return handleSubBlock<ConstraintInfo>(ID, I,
1087 CreateAddFunc(addConstraint<T>));
1088 }
1089 case BI_CONCEPT_BLOCK_ID: {
1090 return handleSubBlock<ConceptInfo>(ID, I,
1091 CreateAddFunc(addChild<T, ConceptInfo>));
1092 }
1093 case BI_VAR_BLOCK_ID: {
1094 return handleSubBlock<VarInfo>(ID, I, CreateAddFunc(addChild<T, VarInfo>));
1095 }
1096 case BI_FRIEND_BLOCK_ID: {
1097 return handleSubBlock<FriendInfo>(ID, I,
1098 CreateAddFunc(addChild<T, FriendInfo>));
1099 }
1100 default:
1101 return llvm::createStringError(llvm::inconvertibleErrorCode(),
1102 "invalid subblock type");
1103 }
1104}
1105
1106llvm::Expected<ClangDocBitcodeReader::Cursor>
1107ClangDocBitcodeReader::skipUntilRecordOrBlock(unsigned &BlockOrRecordID) {
1108 llvm::TimeTraceScope("Reducing infos", "skipUntilRecordOrBlock");
1109 BlockOrRecordID = 0;
1110
1111 while (!Stream.AtEndOfStream()) {
1112 Expected<unsigned> Code = Stream.ReadCode();
1113 if (!Code)
1114 return Code.takeError();
1115
1116 if (*Code >= static_cast<unsigned>(llvm::bitc::FIRST_APPLICATION_ABBREV)) {
1117 BlockOrRecordID = *Code;
1118 return Cursor::Record;
1119 }
1120 switch (static_cast<llvm::bitc::FixedAbbrevIDs>(*Code)) {
1121 case llvm::bitc::ENTER_SUBBLOCK:
1122 if (Expected<unsigned> MaybeID = Stream.ReadSubBlockID())
1123 BlockOrRecordID = MaybeID.get();
1124 else
1125 return MaybeID.takeError();
1126 return Cursor::BlockBegin;
1127 case llvm::bitc::END_BLOCK:
1128 if (Stream.ReadBlockEnd())
1129 return llvm::createStringError(llvm::inconvertibleErrorCode(),
1130 "error at end of block");
1131 return Cursor::BlockEnd;
1132 case llvm::bitc::DEFINE_ABBREV:
1133 if (llvm::Error Err = Stream.ReadAbbrevRecord())
1134 return std::move(Err);
1135 continue;
1136 case llvm::bitc::UNABBREV_RECORD:
1137 return llvm::createStringError(llvm::inconvertibleErrorCode(),
1138 "found unabbreviated record");
1139 case llvm::bitc::FIRST_APPLICATION_ABBREV:
1140 llvm_unreachable("Unexpected abbrev id.");
1141 }
1142 }
1143 llvm_unreachable("Premature stream end.");
1144}
1145
1146llvm::Error ClangDocBitcodeReader::validateStream() {
1147 if (Stream.AtEndOfStream())
1148 return llvm::createStringError(llvm::inconvertibleErrorCode(),
1149 "premature end of stream");
1150
1151 // Sniff for the signature.
1152 for (int Idx = 0; Idx != 4; ++Idx) {
1153 Expected<llvm::SimpleBitstreamCursor::word_t> MaybeRead = Stream.Read(8);
1154 if (!MaybeRead)
1155 return MaybeRead.takeError();
1156 if (MaybeRead.get() != BitCodeConstants::Signature[Idx])
1157 return llvm::createStringError(llvm::inconvertibleErrorCode(),
1158 "invalid bitcode signature");
1159 }
1160 return llvm::Error::success();
1161}
1162
1163llvm::Error ClangDocBitcodeReader::readBlockInfoBlock() {
1164 llvm::TimeTraceScope("Reducing infos", "readBlockInfoBlock");
1165 Expected<std::optional<llvm::BitstreamBlockInfo>> MaybeBlockInfo =
1166 Stream.ReadBlockInfoBlock();
1167 if (!MaybeBlockInfo)
1168 return MaybeBlockInfo.takeError();
1169 BlockInfo = MaybeBlockInfo.get();
1170 if (!BlockInfo)
1171 return llvm::createStringError(llvm::inconvertibleErrorCode(),
1172 "unable to parse BlockInfoBlock");
1173 Stream.setBlockInfo(&*BlockInfo);
1174 return llvm::Error::success();
1175}
1176
1177template <typename T>
1178llvm::Expected<OwnedPtr<Info>> ClangDocBitcodeReader::createInfo(unsigned ID) {
1179 llvm::TimeTraceScope("Reducing infos", "createInfo");
1181 if (auto Err = readBlock(ID, static_cast<T *>(getPtr(I))))
1182 return std::move(Err);
1183 return OwnedPtr<Info>{std::move(I)};
1184}
1185
1186llvm::Expected<OwnedPtr<Info>>
1187ClangDocBitcodeReader::readBlockToInfo(unsigned ID) {
1188 llvm::TimeTraceScope("Reducing infos", "readBlockToInfo");
1189 switch (ID) {
1191 return createInfo<NamespaceInfo>(ID);
1192 case BI_RECORD_BLOCK_ID:
1193 return createInfo<RecordInfo>(ID);
1194 case BI_ENUM_BLOCK_ID:
1195 return createInfo<EnumInfo>(ID);
1197 return createInfo<TypedefInfo>(ID);
1199 return createInfo<ConceptInfo>(ID);
1201 return createInfo<FunctionInfo>(ID);
1202 case BI_VAR_BLOCK_ID:
1203 return createInfo<VarInfo>(ID);
1204 case BI_FRIEND_BLOCK_ID:
1205 return createInfo<FriendInfo>(ID);
1206 default:
1207 return llvm::createStringError(llvm::inconvertibleErrorCode(),
1208 "cannot create info");
1209 }
1210}
1211
1212// Entry point
1213llvm::Expected<OwningPtrArray<Info>> ClangDocBitcodeReader::readBitcode() {
1215 if (auto Err = validateStream())
1216 return std::move(Err);
1217
1218 // Read the top level blocks.
1219 while (!Stream.AtEndOfStream()) {
1220 Expected<unsigned> MaybeCode = Stream.ReadCode();
1221 if (!MaybeCode)
1222 return MaybeCode.takeError();
1223 if (MaybeCode.get() != llvm::bitc::ENTER_SUBBLOCK)
1224 return llvm::createStringError(llvm::inconvertibleErrorCode(),
1225 "no blocks in input");
1226 Expected<unsigned> MaybeID = Stream.ReadSubBlockID();
1227 if (!MaybeID)
1228 return MaybeID.takeError();
1229 unsigned ID = MaybeID.get();
1230 switch (ID) {
1231 // NamedType and Comment blocks should not appear at the top level
1232 case BI_TYPE_BLOCK_ID:
1237 return llvm::createStringError(llvm::inconvertibleErrorCode(),
1238 "invalid top level block");
1240 case BI_RECORD_BLOCK_ID:
1241 case BI_ENUM_BLOCK_ID:
1244 case BI_VAR_BLOCK_ID:
1245 case BI_FRIEND_BLOCK_ID:
1246 case BI_FUNCTION_BLOCK_ID: {
1247 auto InfoOrErr = readBlockToInfo(ID);
1248 if (!InfoOrErr)
1249 return InfoOrErr.takeError();
1250 Infos.emplace_back(std::move(InfoOrErr.get()));
1251 continue;
1252 }
1254 if (auto Err = readBlock(ID, VersionNumber))
1255 return std::move(Err);
1256 continue;
1257 case llvm::bitc::BLOCKINFO_BLOCK_ID:
1258 if (auto Err = readBlockInfoBlock())
1259 return std::move(Err);
1260 continue;
1261 default:
1262 if (llvm::Error Err = Stream.SkipBlock())
1263 return std::move(Err);
1264 continue;
1265 }
1266 }
1267 return std::move(Infos);
1268}
1269
1270} // namespace doc
1271} // namespace clang
static llvm::ExitOnError ExitOnErr
llvm::Expected< OwningPtrArray< 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
std::unique_ptr< T > OwnedPtr
llvm::ArrayRef< T > allocateArray(llvm::ArrayRef< T > V, llvm::BumpPtrAllocator &Alloc)
static llvm::Error decodeRecord(const Record &R, llvm::SmallVectorImpl< char > &Field, llvm::StringRef Blob)
T * getPtr(const OwnedPtr< T > &O)
static const unsigned VersionNumber
static void addChild(T I, ChildInfoType &&R)
CommentKind stringToCommentKind(llvm::StringRef KindStr)
std::vector< OwnedPtr< T > > OwningPtrArray
static llvm::Error addTypeInfo(T I, TTypeInfo &&TI)
static void addTemplateSpecialization(T I, TemplateSpecializationInfo &&TSI)
static void addTemplate(T I, TemplateInfo &&P)
thread_local llvm::BumpPtrAllocator TransientArena
StringRef internString(const Twine &T)
OwnedPtr< T > allocatePtr(Args &&...args)
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]
llvm::ArrayRef< StringRef > Args
llvm::ArrayRef< StringRef > AttrValues
llvm::ArrayRef< CommentInfo > Children
llvm::ArrayRef< StringRef > AttrKeys
llvm::SmallVector< EnumValueInfo, 4 > Members
std::optional< TypeInfo > BaseType
OwningVec< CommentInfo > Description
Comment description of this field.
std::optional< TypeInfo > ReturnType
llvm::ArrayRef< FieldTypeInfo > Params
std::optional< TemplateInfo > Template
llvm::SmallVector< FieldTypeInfo, 4 > Params
std::optional< TemplateInfo > Template
A base struct for Infos.
OwningVec< CommentInfo > Description
llvm::SmallVector< Reference, 4 > Namespace
OwningVec< CommentInfo > Description
OwningVec< BaseRecordInfo > Bases
llvm::SmallVector< MemberTypeInfo, 4 > Members
std::optional< TemplateInfo > Template
llvm::SmallVector< Reference, 4 > VirtualParents
llvm::SmallVector< Reference, 4 > Parents
OwningVec< FriendInfo > Friends
OwningVec< FunctionInfo > Functions
OwningVec< TypedefInfo > Typedefs
OwningVec< EnumInfo > Enums
OwningVec< Reference > Records
OwningVec< ConceptInfo > Concepts
OwningVec< VarInfo > Variables
llvm::simple_ilist< Reference > Namespaces
llvm::SmallVector< Location, 2 > Loc
std::optional< Location > DefLoc
OwningVec< TemplateParamInfo > Params
OwningVec< ConstraintInfo > Constraints
std::optional< TemplateSpecializationInfo > Specialization
OwningVec< TemplateParamInfo > Params
std::optional< TemplateInfo > Template