clang-tools  14.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/ADT/IndexedMap.h"
11 #include "llvm/ADT/Optional.h"
12 #include "llvm/Support/Error.h"
13 #include "llvm/Support/raw_ostream.h"
14 
15 namespace clang {
16 namespace doc {
17 
18 using Record = llvm::SmallVector<uint64_t, 1024>;
19 
20 llvm::Error decodeRecord(const Record &R, llvm::SmallVectorImpl<char> &Field,
21  llvm::StringRef Blob) {
22  Field.assign(Blob.begin(), Blob.end());
23  return llvm::Error::success();
24 }
25 
26 llvm::Error decodeRecord(const Record &R, SymbolID &Field,
27  llvm::StringRef Blob) {
29  return llvm::createStringError(llvm::inconvertibleErrorCode(),
30  "incorrect USR size");
31 
32  // First position in the record is the length of the following array, so we
33  // copy the following elements to the field.
34  for (int I = 0, E = R[0]; I < E; ++I)
35  Field[I] = R[I + 1];
36  return llvm::Error::success();
37 }
38 
39 llvm::Error decodeRecord(const Record &R, bool &Field, llvm::StringRef Blob) {
40  Field = R[0] != 0;
41  return llvm::Error::success();
42 }
43 
44 llvm::Error decodeRecord(const Record &R, int &Field, llvm::StringRef Blob) {
45  if (R[0] > INT_MAX)
46  return llvm::createStringError(llvm::inconvertibleErrorCode(),
47  "integer too large to parse");
48  Field = (int)R[0];
49  return llvm::Error::success();
50 }
51 
52 llvm::Error decodeRecord(const Record &R, AccessSpecifier &Field,
53  llvm::StringRef Blob) {
54  switch (R[0]) {
55  case AS_public:
56  case AS_private:
57  case AS_protected:
58  case AS_none:
59  Field = (AccessSpecifier)R[0];
60  return llvm::Error::success();
61  default:
62  return llvm::createStringError(llvm::inconvertibleErrorCode(),
63  "invalid value for AccessSpecifier");
64  }
65 }
66 
67 llvm::Error decodeRecord(const Record &R, TagTypeKind &Field,
68  llvm::StringRef Blob) {
69  switch (R[0]) {
70  case TTK_Struct:
71  case TTK_Interface:
72  case TTK_Union:
73  case TTK_Class:
74  case TTK_Enum:
75  Field = (TagTypeKind)R[0];
76  return llvm::Error::success();
77  default:
78  return llvm::createStringError(llvm::inconvertibleErrorCode(),
79  "invalid value for TagTypeKind");
80  }
81 }
82 
83 llvm::Error decodeRecord(const Record &R, llvm::Optional<Location> &Field,
84  llvm::StringRef Blob) {
85  if (R[0] > INT_MAX)
86  return llvm::createStringError(llvm::inconvertibleErrorCode(),
87  "integer too large to parse");
88  Field.emplace((int)R[0], Blob, (bool)R[1]);
89  return llvm::Error::success();
90 }
91 
92 llvm::Error decodeRecord(const Record &R, InfoType &Field,
93  llvm::StringRef Blob) {
94  switch (auto IT = static_cast<InfoType>(R[0])) {
99  case InfoType::IT_enum:
100  Field = IT;
101  return llvm::Error::success();
102  }
103  return llvm::createStringError(llvm::inconvertibleErrorCode(),
104  "invalid value for InfoType");
105 }
106 
107 llvm::Error decodeRecord(const Record &R, FieldId &Field,
108  llvm::StringRef Blob) {
109  switch (auto F = static_cast<FieldId>(R[0])) {
111  case FieldId::F_parent:
112  case FieldId::F_vparent:
113  case FieldId::F_type:
116  case FieldId::F_default:
117  Field = F;
118  return llvm::Error::success();
119  }
120  return llvm::createStringError(llvm::inconvertibleErrorCode(),
121  "invalid value for FieldId");
122 }
123 
124 llvm::Error decodeRecord(const Record &R,
125  llvm::SmallVectorImpl<llvm::SmallString<16>> &Field,
126  llvm::StringRef Blob) {
127  Field.push_back(Blob);
128  return llvm::Error::success();
129 }
130 
131 llvm::Error decodeRecord(const Record &R,
132  llvm::SmallVectorImpl<Location> &Field,
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((int)R[0], Blob, (bool)R[1]);
138  return llvm::Error::success();
139 }
140 
141 llvm::Error parseRecord(const Record &R, unsigned ID, llvm::StringRef Blob,
142  const unsigned VersionNo) {
143  if (ID == VERSION && R[0] == VersionNo)
144  return llvm::Error::success();
145  return llvm::createStringError(llvm::inconvertibleErrorCode(),
146  "mismatched bitcode version number");
147 }
148 
149 llvm::Error parseRecord(const Record &R, unsigned ID, llvm::StringRef Blob,
150  NamespaceInfo *I) {
151  switch (ID) {
152  case NAMESPACE_USR:
153  return decodeRecord(R, I->USR, Blob);
154  case NAMESPACE_NAME:
155  return decodeRecord(R, I->Name, Blob);
156  case NAMESPACE_PATH:
157  return decodeRecord(R, I->Path, Blob);
158  default:
159  return llvm::createStringError(llvm::inconvertibleErrorCode(),
160  "invalid field for NamespaceInfo");
161  }
162 }
163 
164 llvm::Error parseRecord(const Record &R, unsigned ID, llvm::StringRef Blob,
165  RecordInfo *I) {
166  switch (ID) {
167  case RECORD_USR:
168  return decodeRecord(R, I->USR, Blob);
169  case RECORD_NAME:
170  return decodeRecord(R, I->Name, Blob);
171  case RECORD_PATH:
172  return decodeRecord(R, I->Path, Blob);
173  case RECORD_DEFLOCATION:
174  return decodeRecord(R, I->DefLoc, Blob);
175  case RECORD_LOCATION:
176  return decodeRecord(R, I->Loc, Blob);
177  case RECORD_TAG_TYPE:
178  return decodeRecord(R, I->TagType, Blob);
179  case RECORD_IS_TYPE_DEF:
180  return decodeRecord(R, I->IsTypeDef, Blob);
181  default:
182  return llvm::createStringError(llvm::inconvertibleErrorCode(),
183  "invalid field for RecordInfo");
184  }
185 }
186 
187 llvm::Error parseRecord(const Record &R, unsigned ID, llvm::StringRef Blob,
188  BaseRecordInfo *I) {
189  switch (ID) {
190  case BASE_RECORD_USR:
191  return decodeRecord(R, I->USR, Blob);
192  case BASE_RECORD_NAME:
193  return decodeRecord(R, I->Name, Blob);
194  case BASE_RECORD_PATH:
195  return decodeRecord(R, I->Path, Blob);
197  return decodeRecord(R, I->TagType, Blob);
199  return decodeRecord(R, I->IsVirtual, Blob);
200  case BASE_RECORD_ACCESS:
201  return decodeRecord(R, I->Access, Blob);
203  return decodeRecord(R, I->IsParent, Blob);
204  default:
205  return llvm::createStringError(llvm::inconvertibleErrorCode(),
206  "invalid field for BaseRecordInfo");
207  }
208 }
209 
210 llvm::Error parseRecord(const Record &R, unsigned ID, llvm::StringRef Blob,
211  EnumInfo *I) {
212  switch (ID) {
213  case ENUM_USR:
214  return decodeRecord(R, I->USR, Blob);
215  case ENUM_NAME:
216  return decodeRecord(R, I->Name, Blob);
217  case ENUM_DEFLOCATION:
218  return decodeRecord(R, I->DefLoc, Blob);
219  case ENUM_LOCATION:
220  return decodeRecord(R, I->Loc, Blob);
221  case ENUM_MEMBER:
222  return decodeRecord(R, I->Members, Blob);
223  case ENUM_SCOPED:
224  return decodeRecord(R, I->Scoped, Blob);
225  default:
226  return llvm::createStringError(llvm::inconvertibleErrorCode(),
227  "invalid field for EnumInfo");
228  }
229 }
230 
231 llvm::Error parseRecord(const Record &R, unsigned ID, llvm::StringRef Blob,
232  FunctionInfo *I) {
233  switch (ID) {
234  case FUNCTION_USR:
235  return decodeRecord(R, I->USR, Blob);
236  case FUNCTION_NAME:
237  return decodeRecord(R, I->Name, Blob);
239  return decodeRecord(R, I->DefLoc, Blob);
240  case FUNCTION_LOCATION:
241  return decodeRecord(R, I->Loc, Blob);
242  case FUNCTION_ACCESS:
243  return decodeRecord(R, I->Access, Blob);
244  case FUNCTION_IS_METHOD:
245  return decodeRecord(R, I->IsMethod, Blob);
246  default:
247  return llvm::createStringError(llvm::inconvertibleErrorCode(),
248  "invalid field for FunctionInfo");
249  }
250 }
251 
252 llvm::Error parseRecord(const Record &R, unsigned ID, llvm::StringRef Blob,
253  TypeInfo *I) {
254  return llvm::Error::success();
255 }
256 
257 llvm::Error parseRecord(const Record &R, unsigned ID, llvm::StringRef Blob,
258  FieldTypeInfo *I) {
259  switch (ID) {
260  case FIELD_TYPE_NAME:
261  return decodeRecord(R, I->Name, Blob);
262  default:
263  return llvm::createStringError(llvm::inconvertibleErrorCode(),
264  "invalid field for TypeInfo");
265  }
266 }
267 
268 llvm::Error parseRecord(const Record &R, unsigned ID, llvm::StringRef Blob,
269  MemberTypeInfo *I) {
270  switch (ID) {
271  case MEMBER_TYPE_NAME:
272  return decodeRecord(R, I->Name, Blob);
273  case MEMBER_TYPE_ACCESS:
274  return decodeRecord(R, I->Access, Blob);
275  default:
276  return llvm::createStringError(llvm::inconvertibleErrorCode(),
277  "invalid field for MemberTypeInfo");
278  }
279 }
280 
281 llvm::Error parseRecord(const Record &R, unsigned ID, llvm::StringRef Blob,
282  CommentInfo *I) {
283  switch (ID) {
284  case COMMENT_KIND:
285  return decodeRecord(R, I->Kind, Blob);
286  case COMMENT_TEXT:
287  return decodeRecord(R, I->Text, Blob);
288  case COMMENT_NAME:
289  return decodeRecord(R, I->Name, Blob);
290  case COMMENT_DIRECTION:
291  return decodeRecord(R, I->Direction, Blob);
292  case COMMENT_PARAMNAME:
293  return decodeRecord(R, I->ParamName, Blob);
294  case COMMENT_CLOSENAME:
295  return decodeRecord(R, I->CloseName, Blob);
296  case COMMENT_ATTRKEY:
297  return decodeRecord(R, I->AttrKeys, Blob);
298  case COMMENT_ATTRVAL:
299  return decodeRecord(R, I->AttrValues, Blob);
300  case COMMENT_ARG:
301  return decodeRecord(R, I->Args, Blob);
302  case COMMENT_SELFCLOSING:
303  return decodeRecord(R, I->SelfClosing, Blob);
304  case COMMENT_EXPLICIT:
305  return decodeRecord(R, I->Explicit, Blob);
306  default:
307  return llvm::createStringError(llvm::inconvertibleErrorCode(),
308  "invalid field for CommentInfo");
309  }
310 }
311 
312 llvm::Error parseRecord(const Record &R, unsigned ID, llvm::StringRef Blob,
313  Reference *I, FieldId &F) {
314  switch (ID) {
315  case REFERENCE_USR:
316  return decodeRecord(R, I->USR, Blob);
317  case REFERENCE_NAME:
318  return decodeRecord(R, I->Name, Blob);
319  case REFERENCE_TYPE:
320  return decodeRecord(R, I->RefType, Blob);
321  case REFERENCE_PATH:
322  return decodeRecord(R, I->Path, Blob);
324  return decodeRecord(R, I->IsInGlobalNamespace, Blob);
325  case REFERENCE_FIELD:
326  return decodeRecord(R, F, Blob);
327  default:
328  return llvm::createStringError(llvm::inconvertibleErrorCode(),
329  "invalid field for Reference");
330  }
331 }
332 
333 template <typename T> llvm::Expected<CommentInfo *> getCommentInfo(T I) {
334  return llvm::createStringError(llvm::inconvertibleErrorCode(),
335  "invalid type cannot contain CommentInfo");
336 }
337 
338 template <> llvm::Expected<CommentInfo *> getCommentInfo(FunctionInfo *I) {
339  I->Description.emplace_back();
340  return &I->Description.back();
341 }
342 
343 template <> llvm::Expected<CommentInfo *> getCommentInfo(NamespaceInfo *I) {
344  I->Description.emplace_back();
345  return &I->Description.back();
346 }
347 
348 template <> llvm::Expected<CommentInfo *> getCommentInfo(RecordInfo *I) {
349  I->Description.emplace_back();
350  return &I->Description.back();
351 }
352 
353 template <> llvm::Expected<CommentInfo *> getCommentInfo(EnumInfo *I) {
354  I->Description.emplace_back();
355  return &I->Description.back();
356 }
357 
358 template <> llvm::Expected<CommentInfo *> getCommentInfo(CommentInfo *I) {
359  I->Children.emplace_back(std::make_unique<CommentInfo>());
360  return I->Children.back().get();
361 }
362 
363 template <>
364 llvm::Expected<CommentInfo *> getCommentInfo(std::unique_ptr<CommentInfo> &I) {
365  return getCommentInfo(I.get());
366 }
367 
368 template <typename T, typename TTypeInfo>
369 llvm::Error addTypeInfo(T I, TTypeInfo &&TI) {
370  return llvm::createStringError(llvm::inconvertibleErrorCode(),
371  "invalid type cannot contain TypeInfo");
372 }
373 
374 template <> llvm::Error addTypeInfo(RecordInfo *I, MemberTypeInfo &&T) {
375  I->Members.emplace_back(std::move(T));
376  return llvm::Error::success();
377 }
378 
379 template <> llvm::Error addTypeInfo(BaseRecordInfo *I, MemberTypeInfo &&T) {
380  I->Members.emplace_back(std::move(T));
381  return llvm::Error::success();
382 }
383 
384 template <> llvm::Error addTypeInfo(FunctionInfo *I, TypeInfo &&T) {
385  I->ReturnType = std::move(T);
386  return llvm::Error::success();
387 }
388 
389 template <> llvm::Error addTypeInfo(FunctionInfo *I, FieldTypeInfo &&T) {
390  I->Params.emplace_back(std::move(T));
391  return llvm::Error::success();
392 }
393 
394 template <typename T> llvm::Error addReference(T I, Reference &&R, FieldId F) {
395  return llvm::createStringError(llvm::inconvertibleErrorCode(),
396  "invalid type cannot contain Reference");
397 }
398 
399 template <> llvm::Error addReference(TypeInfo *I, Reference &&R, FieldId F) {
400  switch (F) {
401  case FieldId::F_type:
402  I->Type = std::move(R);
403  return llvm::Error::success();
404  default:
405  return llvm::createStringError(llvm::inconvertibleErrorCode(),
406  "invalid type cannot contain Reference");
407  }
408 }
409 
410 template <>
411 llvm::Error addReference(FieldTypeInfo *I, Reference &&R, FieldId F) {
412  switch (F) {
413  case FieldId::F_type:
414  I->Type = std::move(R);
415  return llvm::Error::success();
416  default:
417  return llvm::createStringError(llvm::inconvertibleErrorCode(),
418  "invalid type cannot contain Reference");
419  }
420 }
421 
422 template <>
423 llvm::Error addReference(MemberTypeInfo *I, Reference &&R, FieldId F) {
424  switch (F) {
425  case FieldId::F_type:
426  I->Type = std::move(R);
427  return llvm::Error::success();
428  default:
429  return llvm::createStringError(llvm::inconvertibleErrorCode(),
430  "invalid type cannot contain Reference");
431  }
432 }
433 
434 template <> llvm::Error addReference(EnumInfo *I, Reference &&R, FieldId F) {
435  switch (F) {
437  I->Namespace.emplace_back(std::move(R));
438  return llvm::Error::success();
439  default:
440  return llvm::createStringError(llvm::inconvertibleErrorCode(),
441  "invalid type cannot contain Reference");
442  }
443 }
444 
445 template <>
446 llvm::Error addReference(NamespaceInfo *I, Reference &&R, FieldId F) {
447  switch (F) {
449  I->Namespace.emplace_back(std::move(R));
450  return llvm::Error::success();
452  I->ChildNamespaces.emplace_back(std::move(R));
453  return llvm::Error::success();
455  I->ChildRecords.emplace_back(std::move(R));
456  return llvm::Error::success();
457  default:
458  return llvm::createStringError(llvm::inconvertibleErrorCode(),
459  "invalid type cannot contain Reference");
460  }
461 }
462 
463 template <>
464 llvm::Error addReference(FunctionInfo *I, Reference &&R, FieldId F) {
465  switch (F) {
467  I->Namespace.emplace_back(std::move(R));
468  return llvm::Error::success();
469  case FieldId::F_parent:
470  I->Parent = std::move(R);
471  return llvm::Error::success();
472  default:
473  return llvm::createStringError(llvm::inconvertibleErrorCode(),
474  "invalid type cannot contain Reference");
475  }
476 }
477 
478 template <> llvm::Error addReference(RecordInfo *I, Reference &&R, FieldId F) {
479  switch (F) {
481  I->Namespace.emplace_back(std::move(R));
482  return llvm::Error::success();
483  case FieldId::F_parent:
484  I->Parents.emplace_back(std::move(R));
485  return llvm::Error::success();
486  case FieldId::F_vparent:
487  I->VirtualParents.emplace_back(std::move(R));
488  return llvm::Error::success();
490  I->ChildRecords.emplace_back(std::move(R));
491  return llvm::Error::success();
492  default:
493  return llvm::createStringError(llvm::inconvertibleErrorCode(),
494  "invalid type cannot contain Reference");
495  }
496 }
497 
498 template <typename T, typename ChildInfoType>
499 void addChild(T I, ChildInfoType &&R) {
500  llvm::errs() << "invalid child type for info";
501  exit(1);
502 }
503 
504 template <> void addChild(NamespaceInfo *I, FunctionInfo &&R) {
505  I->ChildFunctions.emplace_back(std::move(R));
506 }
507 
508 template <> void addChild(NamespaceInfo *I, EnumInfo &&R) {
509  I->ChildEnums.emplace_back(std::move(R));
510 }
511 
512 template <> void addChild(RecordInfo *I, FunctionInfo &&R) {
513  I->ChildFunctions.emplace_back(std::move(R));
514 }
515 
516 template <> void addChild(RecordInfo *I, EnumInfo &&R) {
517  I->ChildEnums.emplace_back(std::move(R));
518 }
519 
520 template <> void addChild(RecordInfo *I, BaseRecordInfo &&R) {
521  I->Bases.emplace_back(std::move(R));
522 }
523 
524 template <> void addChild(BaseRecordInfo *I, FunctionInfo &&R) {
525  I->ChildFunctions.emplace_back(std::move(R));
526 }
527 
528 // Read records from bitcode into a given info.
529 template <typename T>
530 llvm::Error ClangDocBitcodeReader::readRecord(unsigned ID, T I) {
531  Record R;
532  llvm::StringRef Blob;
533  llvm::Expected<unsigned> MaybeRecID = Stream.readRecord(ID, R, &Blob);
534  if (!MaybeRecID)
535  return MaybeRecID.takeError();
536  return parseRecord(R, MaybeRecID.get(), Blob, I);
537 }
538 
539 template <>
540 llvm::Error ClangDocBitcodeReader::readRecord(unsigned ID, Reference *I) {
541  Record R;
542  llvm::StringRef Blob;
543  llvm::Expected<unsigned> MaybeRecID = Stream.readRecord(ID, R, &Blob);
544  if (!MaybeRecID)
545  return MaybeRecID.takeError();
546  return parseRecord(R, MaybeRecID.get(), Blob, I, CurrentReferenceField);
547 }
548 
549 // Read a block of records into a single info.
550 template <typename T>
551 llvm::Error ClangDocBitcodeReader::readBlock(unsigned ID, T I) {
552  if (llvm::Error Err = Stream.EnterSubBlock(ID))
553  return Err;
554 
555  while (true) {
556  unsigned BlockOrCode = 0;
557  Cursor Res = skipUntilRecordOrBlock(BlockOrCode);
558 
559  switch (Res) {
560  case Cursor::BadBlock:
561  return llvm::createStringError(llvm::inconvertibleErrorCode(),
562  "bad block found");
563  case Cursor::BlockEnd:
564  return llvm::Error::success();
565  case Cursor::BlockBegin:
566  if (llvm::Error Err = readSubBlock(BlockOrCode, I)) {
567  if (llvm::Error Skipped = Stream.SkipBlock())
568  return joinErrors(std::move(Err), std::move(Skipped));
569  return Err;
570  }
571  continue;
572  case Cursor::Record:
573  break;
574  }
575  if (auto Err = readRecord(BlockOrCode, I))
576  return Err;
577  }
578 }
579 
580 template <typename T>
581 llvm::Error ClangDocBitcodeReader::readSubBlock(unsigned ID, T I) {
582  switch (ID) {
583  // Blocks can only have Comment, Reference, TypeInfo, FunctionInfo, or
584  // EnumInfo subblocks
585  case BI_COMMENT_BLOCK_ID: {
586  auto Comment = getCommentInfo(I);
587  if (!Comment)
588  return Comment.takeError();
589  if (auto Err = readBlock(ID, Comment.get()))
590  return Err;
591  return llvm::Error::success();
592  }
593  case BI_TYPE_BLOCK_ID: {
594  TypeInfo TI;
595  if (auto Err = readBlock(ID, &TI))
596  return Err;
597  if (auto Err = addTypeInfo(I, std::move(TI)))
598  return Err;
599  return llvm::Error::success();
600  }
601  case BI_FIELD_TYPE_BLOCK_ID: {
602  FieldTypeInfo TI;
603  if (auto Err = readBlock(ID, &TI))
604  return Err;
605  if (auto Err = addTypeInfo(I, std::move(TI)))
606  return Err;
607  return llvm::Error::success();
608  }
610  MemberTypeInfo TI;
611  if (auto Err = readBlock(ID, &TI))
612  return Err;
613  if (auto Err = addTypeInfo(I, std::move(TI)))
614  return Err;
615  return llvm::Error::success();
616  }
617  case BI_REFERENCE_BLOCK_ID: {
618  Reference R;
619  if (auto Err = readBlock(ID, &R))
620  return Err;
621  if (auto Err = addReference(I, std::move(R), CurrentReferenceField))
622  return Err;
623  return llvm::Error::success();
624  }
625  case BI_FUNCTION_BLOCK_ID: {
626  FunctionInfo F;
627  if (auto Err = readBlock(ID, &F))
628  return Err;
629  addChild(I, std::move(F));
630  return llvm::Error::success();
631  }
633  BaseRecordInfo BR;
634  if (auto Err = readBlock(ID, &BR))
635  return Err;
636  addChild(I, std::move(BR));
637  return llvm::Error::success();
638  }
639  case BI_ENUM_BLOCK_ID: {
640  EnumInfo E;
641  if (auto Err = readBlock(ID, &E))
642  return Err;
643  addChild(I, std::move(E));
644  return llvm::Error::success();
645  }
646  default:
647  return llvm::createStringError(llvm::inconvertibleErrorCode(),
648  "invalid subblock type");
649  }
650 }
651 
652 ClangDocBitcodeReader::Cursor
653 ClangDocBitcodeReader::skipUntilRecordOrBlock(unsigned &BlockOrRecordID) {
654  BlockOrRecordID = 0;
655 
656  while (!Stream.AtEndOfStream()) {
657  Expected<unsigned> MaybeCode = Stream.ReadCode();
658  if (!MaybeCode) {
659  // FIXME this drops the error on the floor.
660  consumeError(MaybeCode.takeError());
661  return Cursor::BadBlock;
662  }
663 
664  unsigned Code = MaybeCode.get();
665  if (Code >= static_cast<unsigned>(llvm::bitc::FIRST_APPLICATION_ABBREV)) {
666  BlockOrRecordID = Code;
667  return Cursor::Record;
668  }
669  switch (static_cast<llvm::bitc::FixedAbbrevIDs>(Code)) {
670  case llvm::bitc::ENTER_SUBBLOCK:
671  if (Expected<unsigned> MaybeID = Stream.ReadSubBlockID())
672  BlockOrRecordID = MaybeID.get();
673  else {
674  // FIXME this drops the error on the floor.
675  consumeError(MaybeID.takeError());
676  }
677  return Cursor::BlockBegin;
678  case llvm::bitc::END_BLOCK:
679  if (Stream.ReadBlockEnd())
680  return Cursor::BadBlock;
681  return Cursor::BlockEnd;
682  case llvm::bitc::DEFINE_ABBREV:
683  if (llvm::Error Err = Stream.ReadAbbrevRecord()) {
684  // FIXME this drops the error on the floor.
685  consumeError(std::move(Err));
686  }
687  continue;
688  case llvm::bitc::UNABBREV_RECORD:
689  return Cursor::BadBlock;
690  case llvm::bitc::FIRST_APPLICATION_ABBREV:
691  llvm_unreachable("Unexpected abbrev id.");
692  }
693  }
694  llvm_unreachable("Premature stream end.");
695 }
696 
697 llvm::Error ClangDocBitcodeReader::validateStream() {
698  if (Stream.AtEndOfStream())
699  return llvm::createStringError(llvm::inconvertibleErrorCode(),
700  "premature end of stream");
701 
702  // Sniff for the signature.
703  for (int Idx = 0; Idx != 4; ++Idx) {
704  Expected<llvm::SimpleBitstreamCursor::word_t> MaybeRead = Stream.Read(8);
705  if (!MaybeRead)
706  return MaybeRead.takeError();
707  else if (MaybeRead.get() != BitCodeConstants::Signature[Idx])
708  return llvm::createStringError(llvm::inconvertibleErrorCode(),
709  "invalid bitcode signature");
710  }
711  return llvm::Error::success();
712 }
713 
714 llvm::Error ClangDocBitcodeReader::readBlockInfoBlock() {
715  Expected<Optional<llvm::BitstreamBlockInfo>> MaybeBlockInfo =
716  Stream.ReadBlockInfoBlock();
717  if (!MaybeBlockInfo)
718  return MaybeBlockInfo.takeError();
719  else
720  BlockInfo = MaybeBlockInfo.get();
721  if (!BlockInfo)
722  return llvm::createStringError(llvm::inconvertibleErrorCode(),
723  "unable to parse BlockInfoBlock");
724  Stream.setBlockInfo(&*BlockInfo);
725  return llvm::Error::success();
726 }
727 
728 template <typename T>
729 llvm::Expected<std::unique_ptr<Info>>
730 ClangDocBitcodeReader::createInfo(unsigned ID) {
731  std::unique_ptr<Info> I = std::make_unique<T>();
732  if (auto Err = readBlock(ID, static_cast<T *>(I.get())))
733  return std::move(Err);
734  return std::unique_ptr<Info>{std::move(I)};
735 }
736 
737 llvm::Expected<std::unique_ptr<Info>>
738 ClangDocBitcodeReader::readBlockToInfo(unsigned ID) {
739  switch (ID) {
741  return createInfo<NamespaceInfo>(ID);
742  case BI_RECORD_BLOCK_ID:
743  return createInfo<RecordInfo>(ID);
744  case BI_ENUM_BLOCK_ID:
745  return createInfo<EnumInfo>(ID);
747  return createInfo<FunctionInfo>(ID);
748  default:
749  return llvm::createStringError(llvm::inconvertibleErrorCode(),
750  "cannot create info");
751  }
752 }
753 
754 // Entry point
755 llvm::Expected<std::vector<std::unique_ptr<Info>>>
757  std::vector<std::unique_ptr<Info>> Infos;
758  if (auto Err = validateStream())
759  return std::move(Err);
760 
761  // Read the top level blocks.
762  while (!Stream.AtEndOfStream()) {
763  Expected<unsigned> MaybeCode = Stream.ReadCode();
764  if (!MaybeCode)
765  return MaybeCode.takeError();
766  if (MaybeCode.get() != llvm::bitc::ENTER_SUBBLOCK)
767  return llvm::createStringError(llvm::inconvertibleErrorCode(),
768  "no blocks in input");
769  Expected<unsigned> MaybeID = Stream.ReadSubBlockID();
770  if (!MaybeID)
771  return MaybeID.takeError();
772  unsigned ID = MaybeID.get();
773  switch (ID) {
774  // NamedType and Comment blocks should not appear at the top level
775  case BI_TYPE_BLOCK_ID:
778  case BI_COMMENT_BLOCK_ID:
780  return llvm::createStringError(llvm::inconvertibleErrorCode(),
781  "invalid top level block");
783  case BI_RECORD_BLOCK_ID:
784  case BI_ENUM_BLOCK_ID:
785  case BI_FUNCTION_BLOCK_ID: {
786  auto InfoOrErr = readBlockToInfo(ID);
787  if (!InfoOrErr)
788  return InfoOrErr.takeError();
789  Infos.emplace_back(std::move(InfoOrErr.get()));
790  continue;
791  }
792  case BI_VERSION_BLOCK_ID:
793  if (auto Err = readBlock(ID, VersionNumber))
794  return std::move(Err);
795  continue;
796  case llvm::bitc::BLOCKINFO_BLOCK_ID:
797  if (auto Err = readBlockInfoBlock())
798  return std::move(Err);
799  continue;
800  default:
801  if (llvm::Error Err = Stream.SkipBlock()) {
802  // FIXME this drops the error on the floor.
803  consumeError(std::move(Err));
804  }
805  continue;
806  }
807  }
808  return std::move(Infos);
809 }
810 
811 } // namespace doc
812 } // namespace clang
clang::doc::FieldId::F_type
@ F_type
clang::doc::BI_VERSION_BLOCK_ID
@ BI_VERSION_BLOCK_ID
Definition: BitcodeWriter.h:54
clang::doc::FieldId::F_child_record
@ F_child_record
clang::doc::BaseRecordInfo::Access
AccessSpecifier Access
Definition: Representation.h:384
clang::doc::FieldId::F_default
@ F_default
clang::doc::RecordInfo::IsTypeDef
bool IsTypeDef
Definition: Representation.h:352
clang::doc::Info::Description
std::vector< CommentInfo > Description
Definition: Representation.h:262
clang::doc::ENUM_MEMBER
@ ENUM_MEMBER
Definition: BitcodeWriter.h:100
clang::doc::NamespaceInfo::ChildEnums
std::vector< EnumInfo > ChildEnums
Definition: Representation.h:300
clang::doc::BI_FUNCTION_BLOCK_ID
@ BI_FUNCTION_BLOCK_ID
Definition: BitcodeWriter.h:62
E
const Expr * E
Definition: AvoidBindCheck.cpp:88
clang::doc::InfoType::IT_enum
@ IT_enum
clang::doc::NamespaceInfo::ChildFunctions
std::vector< FunctionInfo > ChildFunctions
Definition: Representation.h:299
clang::doc::FUNCTION_DEFLOCATION
@ FUNCTION_DEFLOCATION
Definition: BitcodeWriter.h:75
clang::doc::Info::Name
SmallString< 16 > Name
Definition: Representation.h:259
clang::doc::parseRecord
llvm::Error parseRecord(const Record &R, unsigned ID, llvm::StringRef Blob, const unsigned VersionNo)
Definition: BitcodeReader.cpp:141
clang::doc::RECORD_IS_TYPE_DEF
@ RECORD_IS_TYPE_DEF
Definition: BitcodeWriter.h:108
clang::doc::InfoType::IT_namespace
@ IT_namespace
clang::doc::COMMENT_CLOSENAME
@ COMMENT_CLOSENAME
Definition: BitcodeWriter.h:84
clang::doc::FunctionInfo
Definition: Representation.h:319
clang::doc::COMMENT_NAME
@ COMMENT_NAME
Definition: BitcodeWriter.h:81
clang::doc::Reference::Path
llvm::SmallString< 128 > Path
Definition: Representation.h:151
clang::doc::FieldTypeInfo::Name
SmallString< 16 > Name
Definition: Representation.h:187
clang::doc::InfoType
InfoType
Definition: Representation.h:37
clang::doc::NamespaceInfo::ChildNamespaces
std::vector< Reference > ChildNamespaces
Definition: Representation.h:297
clang::doc::RECORD_LOCATION
@ RECORD_LOCATION
Definition: BitcodeWriter.h:106
clang::doc::COMMENT_PARAMNAME
@ COMMENT_PARAMNAME
Definition: BitcodeWriter.h:83
clang::doc::CommentInfo
Definition: Representation.h:46
clang::doc::FieldId::F_child_namespace
@ F_child_namespace
clang::doc::BI_BASE_RECORD_BLOCK_ID
@ BI_BASE_RECORD_BLOCK_ID
Definition: BitcodeWriter.h:61
clang::doc::Reference::Name
SmallString< 16 > Name
Definition: Representation.h:145
clang::doc::ENUM_NAME
@ ENUM_NAME
Definition: BitcodeWriter.h:97
clang::doc::COMMENT_EXPLICIT
@ COMMENT_EXPLICIT
Definition: BitcodeWriter.h:86
clang::doc::BI_MEMBER_TYPE_BLOCK_ID
@ BI_MEMBER_TYPE_BLOCK_ID
Definition: BitcodeWriter.h:59
clang::doc::InfoType::IT_function
@ IT_function
clang::doc::EnumInfo
Definition: Representation.h:390
clang::doc::REFERENCE_IS_IN_GLOBAL_NAMESPACE
@ REFERENCE_IS_IN_GLOBAL_NAMESPACE
Definition: BitcodeWriter.h:120
clang::doc::CommentInfo::CloseName
SmallString< 16 > CloseName
Definition: Representation.h:101
clang::doc::decodeRecord
llvm::Error decodeRecord(const Record &R, llvm::SmallVectorImpl< char > &Field, llvm::StringRef Blob)
Definition: BitcodeReader.cpp:20
clang::doc::addChild
void addChild(T I, ChildInfoType &&R)
Definition: BitcodeReader.cpp:499
clang::doc::CommentInfo::Kind
SmallString< 16 > Kind
Definition: Representation.h:92
clang::doc::ENUM_USR
@ ENUM_USR
Definition: BitcodeWriter.h:96
clang::doc::BASE_RECORD_PATH
@ BASE_RECORD_PATH
Definition: BitcodeWriter.h:111
clang::doc::CommentInfo::Direction
SmallString< 8 > Direction
Definition: Representation.h:99
clang::doc::CommentInfo::Explicit
bool Explicit
Definition: Representation.h:103
clang::doc::RecordInfo::VirtualParents
llvm::SmallVector< Reference, 4 > VirtualParents
Definition: Representation.h:359
clang::doc::RECORD_PATH
@ RECORD_PATH
Definition: BitcodeWriter.h:104
clang::doc::CommentInfo::Name
SmallString< 16 > Name
Definition: Representation.h:98
clang::doc::NAMESPACE_USR
@ NAMESPACE_USR
Definition: BitcodeWriter.h:93
clang::doc::BitCodeConstants::USRHashSize
static constexpr int USRHashSize
Definition: BitcodeWriter.h:48
clang::doc::BaseRecordInfo
Definition: Representation.h:373
clang::doc::RecordInfo::Members
llvm::SmallVector< MemberTypeInfo, 4 > Members
Definition: Representation.h:354
clang::doc::ENUM_SCOPED
@ ENUM_SCOPED
Definition: BitcodeWriter.h:101
clang::doc::REFERENCE_PATH
@ REFERENCE_PATH
Definition: BitcodeWriter.h:119
clang::doc::FieldId::F_namespace
@ F_namespace
clang::doc::RecordInfo::Bases
std::vector< BaseRecordInfo > Bases
Definition: Representation.h:362
clang::doc::CommentInfo::ParamName
SmallString< 16 > ParamName
Definition: Representation.h:100
clang::doc::MEMBER_TYPE_ACCESS
@ MEMBER_TYPE_ACCESS
Definition: BitcodeWriter.h:92
clang::doc::Info::Path
llvm::SmallString< 128 > Path
Definition: Representation.h:263
clang::doc::CommentInfo::Children
std::vector< std::unique_ptr< CommentInfo > > Children
Definition: Representation.h:112
clang::doc::InfoType::IT_record
@ IT_record
clang::doc::CommentInfo::AttrKeys
llvm::SmallVector< SmallString< 16 >, 4 > AttrKeys
Definition: Representation.h:106
clang::doc::FunctionInfo::Parent
Reference Parent
Definition: Representation.h:326
clang::doc::getCommentInfo
llvm::Expected< CommentInfo * > getCommentInfo(T I)
Definition: BitcodeReader.cpp:333
TypeInfo
QualType TypeInfo
Definition: ExtractFunction.cpp:338
Code
std::string Code
Definition: FindTargetTests.cpp:67
clang::doc::BASE_RECORD_IS_PARENT
@ BASE_RECORD_IS_PARENT
Definition: BitcodeWriter.h:115
clang::doc::EnumInfo::Members
llvm::SmallVector< SmallString< 16 >, 4 > Members
Definition: Representation.h:398
clang::doc::addReference
llvm::Error addReference(T I, Reference &&R, FieldId F)
Definition: BitcodeReader.cpp:394
clang::doc::FUNCTION_USR
@ FUNCTION_USR
Definition: BitcodeWriter.h:73
clang::doc::NAMESPACE_PATH
@ NAMESPACE_PATH
Definition: BitcodeWriter.h:95
clang::doc::FieldId::F_vparent
@ F_vparent
clang::doc::CommentInfo::Text
SmallString< 64 > Text
Definition: Representation.h:97
clang::doc::BASE_RECORD_USR
@ BASE_RECORD_USR
Definition: BitcodeWriter.h:109
clang::doc::SymbolInfo::Loc
llvm::SmallVector< Location, 2 > Loc
Definition: Representation.h:314
clang::doc::COMMENT_DIRECTION
@ COMMENT_DIRECTION
Definition: BitcodeWriter.h:82
clang::doc::RecordInfo::Parents
llvm::SmallVector< Reference, 4 > Parents
Definition: Representation.h:355
clang::doc::MemberTypeInfo::Access
AccessSpecifier Access
Definition: Representation.h:212
clang::doc::RECORD_USR
@ RECORD_USR
Definition: BitcodeWriter.h:102
clang::doc::BaseRecordInfo::IsVirtual
bool IsVirtual
Definition: Representation.h:381
clang::doc::Reference::IsInGlobalNamespace
bool IsInGlobalNamespace
Definition: Representation.h:154
clang::doc::REFERENCE_FIELD
@ REFERENCE_FIELD
Definition: BitcodeWriter.h:121
clang::doc::REFERENCE_NAME
@ REFERENCE_NAME
Definition: BitcodeWriter.h:117
clang::clangd::RefKind::Reference
@ Reference
clang::doc::Info::USR
SymbolID USR
Definition: Representation.h:256
clang::doc::FunctionInfo::Access
AccessSpecifier Access
Definition: Representation.h:333
clang::doc::FunctionInfo::Params
llvm::SmallVector< FieldTypeInfo, 4 > Params
Definition: Representation.h:328
clang::doc::RECORD_NAME
@ RECORD_NAME
Definition: BitcodeWriter.h:103
clang::doc::InfoType::IT_default
@ IT_default
clang::doc::SymbolID
std::array< uint8_t, 20 > SymbolID
Definition: Representation.h:30
clang::doc::REFERENCE_USR
@ REFERENCE_USR
Definition: BitcodeWriter.h:116
clang::doc::RecordInfo
Definition: Representation.h:339
clang::doc::BitCodeConstants::Signature
static constexpr unsigned char Signature[4]
Definition: BitcodeWriter.h:47
clang::doc::ENUM_LOCATION
@ ENUM_LOCATION
Definition: BitcodeWriter.h:99
clang::doc::BASE_RECORD_IS_VIRTUAL
@ BASE_RECORD_IS_VIRTUAL
Definition: BitcodeWriter.h:113
clang::doc::BaseRecordInfo::IsParent
bool IsParent
Definition: Representation.h:385
clang::doc::BASE_RECORD_TAG_TYPE
@ BASE_RECORD_TAG_TYPE
Definition: BitcodeWriter.h:112
clang::doc::TypeInfo::Type
Reference Type
Definition: Representation.h:169
clang::doc::BI_COMMENT_BLOCK_ID
@ BI_COMMENT_BLOCK_ID
Definition: BitcodeWriter.h:63
clang::doc::addTypeInfo
llvm::Error addTypeInfo(T I, TTypeInfo &&TI)
Definition: BitcodeReader.cpp:369
clang::doc::BASE_RECORD_ACCESS
@ BASE_RECORD_ACCESS
Definition: BitcodeWriter.h:114
clang::doc::RecordInfo::ChildRecords
std::vector< Reference > ChildRecords
Definition: Representation.h:368
clang::doc::COMMENT_SELFCLOSING
@ COMMENT_SELFCLOSING
Definition: BitcodeWriter.h:85
clang::doc::Reference::USR
SymbolID USR
Definition: Representation.h:144
clang::doc::Reference
Definition: Representation.h:115
clang::doc::BI_RECORD_BLOCK_ID
@ BI_RECORD_BLOCK_ID
Definition: BitcodeWriter.h:60
clang::doc::BI_REFERENCE_BLOCK_ID
@ BI_REFERENCE_BLOCK_ID
Definition: BitcodeWriter.h:64
clang::doc::REFERENCE_TYPE
@ REFERENCE_TYPE
Definition: BitcodeWriter.h:118
clang::doc::FIELD_TYPE_NAME
@ FIELD_TYPE_NAME
Definition: BitcodeWriter.h:90
clang::doc::ENUM_DEFLOCATION
@ ENUM_DEFLOCATION
Definition: BitcodeWriter.h:98
clang::doc::VERSION
@ VERSION
Definition: BitcodeWriter.h:72
ID
static char ID
Definition: Logger.cpp:74
clang::doc::Reference::RefType
InfoType RefType
Definition: Representation.h:146
clang::doc::VersionNumber
static const unsigned VersionNumber
Definition: BitcodeWriter.h:33
clang::doc::FUNCTION_LOCATION
@ FUNCTION_LOCATION
Definition: BitcodeWriter.h:76
clang::doc::BI_FIELD_TYPE_BLOCK_ID
@ BI_FIELD_TYPE_BLOCK_ID
Definition: BitcodeWriter.h:58
clang::doc::COMMENT_ATTRVAL
@ COMMENT_ATTRVAL
Definition: BitcodeWriter.h:88
clang::doc::CommentInfo::SelfClosing
bool SelfClosing
Definition: Representation.h:102
clang::doc::RecordInfo::ChildFunctions
std::vector< FunctionInfo > ChildFunctions
Definition: Representation.h:369
clang::doc::MEMBER_TYPE_NAME
@ MEMBER_TYPE_NAME
Definition: BitcodeWriter.h:91
clang::doc::FunctionInfo::ReturnType
TypeInfo ReturnType
Definition: Representation.h:327
clang::doc::BASE_RECORD_NAME
@ BASE_RECORD_NAME
Definition: BitcodeWriter.h:110
clang::doc::COMMENT_TEXT
@ COMMENT_TEXT
Definition: BitcodeWriter.h:80
clang
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
Definition: ApplyReplacements.h:27
clang::doc::NamespaceInfo
Definition: Representation.h:283
clang::doc::FieldId::F_parent
@ F_parent
clang::doc::RECORD_TAG_TYPE
@ RECORD_TAG_TYPE
Definition: BitcodeWriter.h:107
clang::doc::FUNCTION_NAME
@ FUNCTION_NAME
Definition: BitcodeWriter.h:74
clang::doc::NamespaceInfo::ChildRecords
std::vector< Reference > ChildRecords
Definition: Representation.h:298
clang::doc::COMMENT_ATTRKEY
@ COMMENT_ATTRKEY
Definition: BitcodeWriter.h:87
clang::doc::Record
llvm::SmallVector< uint64_t, 1024 > Record
Definition: BitcodeReader.cpp:18
clang::doc::RecordInfo::TagType
TagTypeKind TagType
Definition: Representation.h:349
clang::doc::TypeInfo
Definition: Representation.h:158
clang::doc::CommentInfo::AttrValues
llvm::SmallVector< SmallString< 16 >, 4 > AttrValues
Definition: Representation.h:108
clang::doc::BI_NAMESPACE_BLOCK_ID
@ BI_NAMESPACE_BLOCK_ID
Definition: BitcodeWriter.h:55
clang::doc::RECORD_DEFLOCATION
@ RECORD_DEFLOCATION
Definition: BitcodeWriter.h:105
clang::doc::CommentInfo::Args
llvm::SmallVector< SmallString< 16 >, 4 > Args
Definition: Representation.h:110
clang::doc::ClangDocBitcodeReader::readBitcode
llvm::Expected< std::vector< std::unique_ptr< Info > > > readBitcode()
Definition: BitcodeReader.cpp:756
clang::doc::COMMENT_KIND
@ COMMENT_KIND
Definition: BitcodeWriter.h:79
clang::doc::COMMENT_ARG
@ COMMENT_ARG
Definition: BitcodeWriter.h:89
clang::doc::RecordInfo::ChildEnums
std::vector< EnumInfo > ChildEnums
Definition: Representation.h:370
BitcodeReader.h
clang::doc::SymbolInfo::DefLoc
llvm::Optional< Location > DefLoc
Definition: Representation.h:313
clang::doc::FieldTypeInfo
Definition: Representation.h:173
clang::doc::FUNCTION_IS_METHOD
@ FUNCTION_IS_METHOD
Definition: BitcodeWriter.h:78
clang::doc::MemberTypeInfo
Definition: Representation.h:191
clang::doc::BI_TYPE_BLOCK_ID
@ BI_TYPE_BLOCK_ID
Definition: BitcodeWriter.h:57
clang::doc::Info::Namespace
llvm::SmallVector< Reference, 4 > Namespace
Definition: Representation.h:261
clang::doc::BI_ENUM_BLOCK_ID
@ BI_ENUM_BLOCK_ID
Definition: BitcodeWriter.h:56
clang::doc::FieldId
FieldId
Definition: BitcodeWriter.h:130
clang::doc::EnumInfo::Scoped
bool Scoped
Definition: Representation.h:396
clang::doc::FUNCTION_ACCESS
@ FUNCTION_ACCESS
Definition: BitcodeWriter.h:77
clang::doc::FunctionInfo::IsMethod
bool IsMethod
Definition: Representation.h:325
clang::doc::NAMESPACE_NAME
@ NAMESPACE_NAME
Definition: BitcodeWriter.h:94