blob: 01a79b44d98b5ad8cf160dd0eca3da9972a86ef0 [file] [log] [blame]
Douglas Gregorc34897d2009-04-09 22:27:44 +00001//===--- PCHReader.cpp - Precompiled Headers Reader -------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file defines the PCHReader class, which reads a precompiled header.
11//
12//===----------------------------------------------------------------------===//
13#include "clang/Frontend/PCHReader.h"
14#include "clang/Frontend/PCHBitCodes.h"
15#include "clang/AST/ASTContext.h"
16#include "clang/AST/Decl.h"
17#include "clang/AST/Type.h"
Douglas Gregorab1cef72009-04-10 03:52:48 +000018#include "clang/Lex/Preprocessor.h"
19#include "clang/Basic/SourceManager.h"
20#include "clang/Basic/FileManager.h"
Douglas Gregorc34897d2009-04-09 22:27:44 +000021#include "llvm/Bitcode/BitstreamReader.h"
22#include "llvm/Support/Compiler.h"
23#include "llvm/Support/MemoryBuffer.h"
24#include <algorithm>
25#include <cstdio>
26
27using namespace clang;
28
29//===----------------------------------------------------------------------===//
30// Declaration deserialization
31//===----------------------------------------------------------------------===//
32namespace {
33 class VISIBILITY_HIDDEN PCHDeclReader {
34 PCHReader &Reader;
35 const PCHReader::RecordData &Record;
36 unsigned &Idx;
37
38 public:
39 PCHDeclReader(PCHReader &Reader, const PCHReader::RecordData &Record,
40 unsigned &Idx)
41 : Reader(Reader), Record(Record), Idx(Idx) { }
42
43 void VisitDecl(Decl *D);
44 void VisitTranslationUnitDecl(TranslationUnitDecl *TU);
45 void VisitNamedDecl(NamedDecl *ND);
46 void VisitTypeDecl(TypeDecl *TD);
47 void VisitTypedefDecl(TypedefDecl *TD);
48 void VisitValueDecl(ValueDecl *VD);
49 void VisitVarDecl(VarDecl *VD);
50
51 std::pair<uint64_t, uint64_t> VisitDeclContext(DeclContext *DC);
52 };
53}
54
55void PCHDeclReader::VisitDecl(Decl *D) {
56 D->setDeclContext(cast_or_null<DeclContext>(Reader.GetDecl(Record[Idx++])));
57 D->setLexicalDeclContext(
58 cast_or_null<DeclContext>(Reader.GetDecl(Record[Idx++])));
59 D->setLocation(SourceLocation::getFromRawEncoding(Record[Idx++]));
60 D->setInvalidDecl(Record[Idx++]);
61 // FIXME: hasAttrs
62 D->setImplicit(Record[Idx++]);
63 D->setAccess((AccessSpecifier)Record[Idx++]);
64}
65
66void PCHDeclReader::VisitTranslationUnitDecl(TranslationUnitDecl *TU) {
67 VisitDecl(TU);
68}
69
70void PCHDeclReader::VisitNamedDecl(NamedDecl *ND) {
71 VisitDecl(ND);
72 ND->setDeclName(Reader.ReadDeclarationName(Record, Idx));
73}
74
75void PCHDeclReader::VisitTypeDecl(TypeDecl *TD) {
76 VisitNamedDecl(TD);
77 // FIXME: circular dependencies here?
78 TD->setTypeForDecl(Reader.GetType(Record[Idx++]).getTypePtr());
79}
80
81void PCHDeclReader::VisitTypedefDecl(TypedefDecl *TD) {
82 VisitTypeDecl(TD);
83 TD->setUnderlyingType(Reader.GetType(Record[Idx++]));
84}
85
86void PCHDeclReader::VisitValueDecl(ValueDecl *VD) {
87 VisitNamedDecl(VD);
88 VD->setType(Reader.GetType(Record[Idx++]));
89}
90
91void PCHDeclReader::VisitVarDecl(VarDecl *VD) {
92 VisitValueDecl(VD);
93 VD->setStorageClass((VarDecl::StorageClass)Record[Idx++]);
94 VD->setThreadSpecified(Record[Idx++]);
95 VD->setCXXDirectInitializer(Record[Idx++]);
96 VD->setDeclaredInCondition(Record[Idx++]);
97 VD->setPreviousDeclaration(
98 cast_or_null<VarDecl>(Reader.GetDecl(Record[Idx++])));
99 VD->setTypeSpecStartLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
100}
101
102std::pair<uint64_t, uint64_t>
103PCHDeclReader::VisitDeclContext(DeclContext *DC) {
104 uint64_t LexicalOffset = Record[Idx++];
105 uint64_t VisibleOffset = 0;
106 if (DC->getPrimaryContext() == DC)
107 VisibleOffset = Record[Idx++];
108 return std::make_pair(LexicalOffset, VisibleOffset);
109}
110
111// FIXME: use the diagnostics machinery
112static bool Error(const char *Str) {
113 std::fprintf(stderr, "%s\n", Str);
114 return true;
115}
116
Douglas Gregorab1cef72009-04-10 03:52:48 +0000117/// \brief Read the source manager block
118bool PCHReader::ReadSourceManagerBlock() {
119 using namespace SrcMgr;
120 if (Stream.EnterSubBlock(pch::SOURCE_MANAGER_BLOCK_ID))
121 return Error("Malformed source manager block record");
122
123 SourceManager &SourceMgr = Context.getSourceManager();
124 RecordData Record;
125 while (true) {
126 unsigned Code = Stream.ReadCode();
127 if (Code == llvm::bitc::END_BLOCK) {
128 if (Stream.ReadBlockEnd())
129 return Error("Error at end of Source Manager block");
130 return false;
131 }
132
133 if (Code == llvm::bitc::ENTER_SUBBLOCK) {
134 // No known subblocks, always skip them.
135 Stream.ReadSubBlockID();
136 if (Stream.SkipBlock())
137 return Error("Malformed block record");
138 continue;
139 }
140
141 if (Code == llvm::bitc::DEFINE_ABBREV) {
142 Stream.ReadAbbrevRecord();
143 continue;
144 }
145
146 // Read a record.
147 const char *BlobStart;
148 unsigned BlobLen;
149 Record.clear();
150 switch (Stream.ReadRecord(Code, Record, &BlobStart, &BlobLen)) {
151 default: // Default behavior: ignore.
152 break;
153
154 case pch::SM_SLOC_FILE_ENTRY: {
155 // FIXME: We would really like to delay the creation of this
156 // FileEntry until it is actually required, e.g., when producing
157 // a diagnostic with a source location in this file.
158 const FileEntry *File
159 = PP.getFileManager().getFile(BlobStart, BlobStart + BlobLen);
160 // FIXME: Error recovery if file cannot be found.
161 SourceMgr.createFileID(File,
162 SourceLocation::getFromRawEncoding(Record[1]),
163 (CharacteristicKind)Record[2]);
164 break;
165 }
166
167 case pch::SM_SLOC_BUFFER_ENTRY: {
168 const char *Name = BlobStart;
169 unsigned Code = Stream.ReadCode();
170 Record.clear();
171 unsigned RecCode = Stream.ReadRecord(Code, Record, &BlobStart, &BlobLen);
172 assert(RecCode == pch::SM_SLOC_BUFFER_BLOB && "Ill-formed PCH file");
173 SourceMgr.createFileIDForMemBuffer(
174 llvm::MemoryBuffer::getMemBuffer(BlobStart, BlobStart + BlobLen - 1,
175 Name));
176 break;
177 }
178
179 case pch::SM_SLOC_INSTANTIATION_ENTRY: {
180 SourceLocation SpellingLoc
181 = SourceLocation::getFromRawEncoding(Record[1]);
182 SourceMgr.createInstantiationLoc(
183 SpellingLoc,
184 SourceLocation::getFromRawEncoding(Record[2]),
185 SourceLocation::getFromRawEncoding(Record[3]),
186 Lexer::MeasureTokenLength(SpellingLoc,
187 SourceMgr));
188 break;
189 }
190
191 }
192 }
193}
194
Douglas Gregorc34897d2009-04-09 22:27:44 +0000195/// \brief Read the type-offsets block.
196bool PCHReader::ReadTypeOffsets() {
197 if (Stream.EnterSubBlock(pch::TYPE_OFFSETS_BLOCK_ID))
198 return Error("Malformed block record");
199
200 RecordData Record;
201 while (true) {
202 unsigned Code = Stream.ReadCode();
203 if (Code == llvm::bitc::END_BLOCK) {
204 if (Stream.ReadBlockEnd())
205 return Error("Error at end of TYPE_OFFSETS block");
206 return false;
207 }
208
209 if (Code == llvm::bitc::ENTER_SUBBLOCK) {
210 // No known subblocks, always skip them.
211 Stream.ReadSubBlockID();
212 if (Stream.SkipBlock())
213 return Error("Malformed block record");
214 continue;
215 }
216
217 if (Code == llvm::bitc::DEFINE_ABBREV) {
218 Stream.ReadAbbrevRecord();
219 continue;
220 }
221
222 // Read a record.
223 Record.clear();
224 switch (Stream.ReadRecord(Code, Record)) {
225 default: // Default behavior: ignore.
226 break;
227 case pch::TYPE_OFFSET:
228 if (!TypeOffsets.empty())
229 return Error("Duplicate TYPE_OFFSETS block");
230 TypeOffsets.swap(Record);
231 TypeAlreadyLoaded.resize(TypeOffsets.size(), false);
232 break;
233 }
234 }
235}
236
237/// \brief Read the decl-offsets block.
238bool PCHReader::ReadDeclOffsets() {
239 if (Stream.EnterSubBlock(pch::DECL_OFFSETS_BLOCK_ID))
240 return Error("Malformed block record");
241
242 RecordData Record;
243 while (true) {
244 unsigned Code = Stream.ReadCode();
245 if (Code == llvm::bitc::END_BLOCK) {
246 if (Stream.ReadBlockEnd())
247 return Error("Error at end of DECL_OFFSETS block");
248 return false;
249 }
250
251 if (Code == llvm::bitc::ENTER_SUBBLOCK) {
252 // No known subblocks, always skip them.
253 Stream.ReadSubBlockID();
254 if (Stream.SkipBlock())
255 return Error("Malformed block record");
256 continue;
257 }
258
259 if (Code == llvm::bitc::DEFINE_ABBREV) {
260 Stream.ReadAbbrevRecord();
261 continue;
262 }
263
264 // Read a record.
265 Record.clear();
266 switch (Stream.ReadRecord(Code, Record)) {
267 default: // Default behavior: ignore.
268 break;
269 case pch::DECL_OFFSET:
270 if (!DeclOffsets.empty())
271 return Error("Duplicate DECL_OFFSETS block");
272 DeclOffsets.swap(Record);
273 DeclAlreadyLoaded.resize(DeclOffsets.size(), false);
274 break;
275 }
276 }
277}
278
279bool PCHReader::ReadPCHBlock() {
280 if (Stream.EnterSubBlock(pch::PCH_BLOCK_ID))
281 return Error("Malformed block record");
282
283 // Read all of the records and blocks for the PCH file.
284 while (!Stream.AtEndOfStream()) {
285 unsigned Code = Stream.ReadCode();
286 if (Code == llvm::bitc::END_BLOCK) {
287 if (Stream.ReadBlockEnd())
288 return Error("Error at end of module block");
289 return false;
290 }
291
292 if (Code == llvm::bitc::ENTER_SUBBLOCK) {
293 switch (Stream.ReadSubBlockID()) {
294 case pch::DECLS_BLOCK_ID: // Skip decls block (lazily loaded)
295 case pch::TYPES_BLOCK_ID: // Skip types block (lazily loaded)
296 default: // Skip unknown content.
297 if (Stream.SkipBlock())
298 return Error("Malformed block record");
299 break;
300
Douglas Gregorab1cef72009-04-10 03:52:48 +0000301 case pch::SOURCE_MANAGER_BLOCK_ID:
302 if (ReadSourceManagerBlock())
303 return Error("Malformed source manager block");
304 break;
Douglas Gregorc34897d2009-04-09 22:27:44 +0000305
306 case pch::TYPE_OFFSETS_BLOCK_ID:
307 if (ReadTypeOffsets())
308 return Error("Malformed type-offsets block");
309 break;
310
311 case pch::DECL_OFFSETS_BLOCK_ID:
312 if (ReadDeclOffsets())
313 return Error("Malformed decl-offsets block");
314 break;
315 }
316 }
317 }
318
319 return Error("Premature end of bitstream");
320}
321
322PCHReader::~PCHReader() { }
323
324bool PCHReader::ReadPCH(const std::string &FileName) {
325 // Open the PCH file.
326 std::string ErrStr;
327 Buffer.reset(llvm::MemoryBuffer::getFile(FileName.c_str(), &ErrStr));
328 if (!Buffer)
329 return Error(ErrStr.c_str());
330
331 // Initialize the stream
332 Stream.init((const unsigned char *)Buffer->getBufferStart(),
333 (const unsigned char *)Buffer->getBufferEnd());
334
335 // Sniff for the signature.
336 if (Stream.Read(8) != 'C' ||
337 Stream.Read(8) != 'P' ||
338 Stream.Read(8) != 'C' ||
339 Stream.Read(8) != 'H')
340 return Error("Not a PCH file");
341
342 // We expect a number of well-defined blocks, though we don't necessarily
343 // need to understand them all.
344 while (!Stream.AtEndOfStream()) {
345 unsigned Code = Stream.ReadCode();
346
347 if (Code != llvm::bitc::ENTER_SUBBLOCK)
348 return Error("Invalid record at top-level");
349
350 unsigned BlockID = Stream.ReadSubBlockID();
351
352 // We only know the PCH subblock ID.
353 switch (BlockID) {
354 case llvm::bitc::BLOCKINFO_BLOCK_ID:
355 if (Stream.ReadBlockInfoBlock())
356 return Error("Malformed BlockInfoBlock");
357 break;
358 case pch::PCH_BLOCK_ID:
359 if (ReadPCHBlock())
360 return true;
361 break;
362 default:
363 if (Stream.SkipBlock())
364 return Error("Malformed block record");
365 break;
366 }
367 }
368
369 // Load the translation unit declaration
370 ReadDeclRecord(DeclOffsets[0], 0);
371
372 return false;
373}
374
375/// \brief Read and return the type at the given offset.
376///
377/// This routine actually reads the record corresponding to the type
378/// at the given offset in the bitstream. It is a helper routine for
379/// GetType, which deals with reading type IDs.
380QualType PCHReader::ReadTypeRecord(uint64_t Offset) {
381 Stream.JumpToBit(Offset);
382 RecordData Record;
383 unsigned Code = Stream.ReadCode();
384 switch ((pch::TypeCode)Stream.ReadRecord(Code, Record)) {
385 case pch::TYPE_FIXED_WIDTH_INT: {
386 assert(Record.size() == 2 && "Incorrect encoding of fixed-width int type");
387 return Context.getFixedWidthIntType(Record[0], Record[1]);
388 }
389
390 case pch::TYPE_COMPLEX: {
391 assert(Record.size() == 1 && "Incorrect encoding of complex type");
392 QualType ElemType = GetType(Record[0]);
393 return Context.getComplexType(ElemType);
394 }
395
396 case pch::TYPE_POINTER: {
397 assert(Record.size() == 1 && "Incorrect encoding of pointer type");
398 QualType PointeeType = GetType(Record[0]);
399 return Context.getPointerType(PointeeType);
400 }
401
402 case pch::TYPE_BLOCK_POINTER: {
403 assert(Record.size() == 1 && "Incorrect encoding of block pointer type");
404 QualType PointeeType = GetType(Record[0]);
405 return Context.getBlockPointerType(PointeeType);
406 }
407
408 case pch::TYPE_LVALUE_REFERENCE: {
409 assert(Record.size() == 1 && "Incorrect encoding of lvalue reference type");
410 QualType PointeeType = GetType(Record[0]);
411 return Context.getLValueReferenceType(PointeeType);
412 }
413
414 case pch::TYPE_RVALUE_REFERENCE: {
415 assert(Record.size() == 1 && "Incorrect encoding of rvalue reference type");
416 QualType PointeeType = GetType(Record[0]);
417 return Context.getRValueReferenceType(PointeeType);
418 }
419
420 case pch::TYPE_MEMBER_POINTER: {
421 assert(Record.size() == 1 && "Incorrect encoding of member pointer type");
422 QualType PointeeType = GetType(Record[0]);
423 QualType ClassType = GetType(Record[1]);
424 return Context.getMemberPointerType(PointeeType, ClassType.getTypePtr());
425 }
426
427 // FIXME: Several other kinds of types to deserialize here!
428 default:
429 assert("Unable to deserialize this type");
430 break;
431 }
432
433 // Suppress a GCC warning
434 return QualType();
435}
436
437/// \brief Note that we have loaded the declaration with the given
438/// Index.
439///
440/// This routine notes that this declaration has already been loaded,
441/// so that future GetDecl calls will return this declaration rather
442/// than trying to load a new declaration.
443inline void PCHReader::LoadedDecl(unsigned Index, Decl *D) {
444 assert(!DeclAlreadyLoaded[Index] && "Decl loaded twice?");
445 DeclAlreadyLoaded[Index] = true;
446 DeclOffsets[Index] = reinterpret_cast<uint64_t>(D);
447}
448
449/// \brief Read the declaration at the given offset from the PCH file.
450Decl *PCHReader::ReadDeclRecord(uint64_t Offset, unsigned Index) {
451 Decl *D = 0;
452 Stream.JumpToBit(Offset);
453 RecordData Record;
454 unsigned Code = Stream.ReadCode();
455 unsigned Idx = 0;
456 PCHDeclReader Reader(*this, Record, Idx);
457 switch ((pch::DeclCode)Stream.ReadRecord(Code, Record)) {
458 case pch::DECL_TRANSLATION_UNIT:
459 assert(Index == 0 && "Translation unit must be at index 0");
460 Reader.VisitTranslationUnitDecl(Context.getTranslationUnitDecl());
461 D = Context.getTranslationUnitDecl();
462 LoadedDecl(Index, D);
463 break;
464
465 case pch::DECL_TYPEDEF: {
466 TypedefDecl *Typedef = TypedefDecl::Create(Context, 0, SourceLocation(),
467 0, QualType());
468 LoadedDecl(Index, Typedef);
469 Reader.VisitTypedefDecl(Typedef);
470 D = Typedef;
471 break;
472 }
473
474 case pch::DECL_VAR: {
475 VarDecl *Var = VarDecl::Create(Context, 0, SourceLocation(), 0, QualType(),
476 VarDecl::None, SourceLocation());
477 LoadedDecl(Index, Var);
478 Reader.VisitVarDecl(Var);
479 D = Var;
480 break;
481 }
482
483 default:
484 assert(false && "Cannot de-serialize this kind of declaration");
485 break;
486 }
487
488 // If this declaration is also a declaration context, get the
489 // offsets for its tables of lexical and visible declarations.
490 if (DeclContext *DC = dyn_cast<DeclContext>(D)) {
491 std::pair<uint64_t, uint64_t> Offsets = Reader.VisitDeclContext(DC);
492 if (Offsets.first || Offsets.second) {
493 DC->setHasExternalLexicalStorage(Offsets.first != 0);
494 DC->setHasExternalVisibleStorage(Offsets.second != 0);
495 DeclContextOffsets[DC] = Offsets;
496 }
497 }
498 assert(Idx == Record.size());
499
500 return D;
501}
502
503QualType PCHReader::GetType(unsigned ID) {
504 unsigned Quals = ID & 0x07;
505 unsigned Index = ID >> 3;
506
507 if (Index < pch::NUM_PREDEF_TYPE_IDS) {
508 QualType T;
509 switch ((pch::PredefinedTypeIDs)Index) {
510 case pch::PREDEF_TYPE_NULL_ID: return QualType();
511 case pch::PREDEF_TYPE_VOID_ID: T = Context.VoidTy; break;
512 case pch::PREDEF_TYPE_BOOL_ID: T = Context.BoolTy; break;
513
514 case pch::PREDEF_TYPE_CHAR_U_ID:
515 case pch::PREDEF_TYPE_CHAR_S_ID:
516 // FIXME: Check that the signedness of CharTy is correct!
517 T = Context.CharTy;
518 break;
519
520 case pch::PREDEF_TYPE_UCHAR_ID: T = Context.UnsignedCharTy; break;
521 case pch::PREDEF_TYPE_USHORT_ID: T = Context.UnsignedShortTy; break;
522 case pch::PREDEF_TYPE_UINT_ID: T = Context.UnsignedIntTy; break;
523 case pch::PREDEF_TYPE_ULONG_ID: T = Context.UnsignedLongTy; break;
524 case pch::PREDEF_TYPE_ULONGLONG_ID: T = Context.UnsignedLongLongTy; break;
525 case pch::PREDEF_TYPE_SCHAR_ID: T = Context.SignedCharTy; break;
526 case pch::PREDEF_TYPE_WCHAR_ID: T = Context.WCharTy; break;
527 case pch::PREDEF_TYPE_SHORT_ID: T = Context.ShortTy; break;
528 case pch::PREDEF_TYPE_INT_ID: T = Context.IntTy; break;
529 case pch::PREDEF_TYPE_LONG_ID: T = Context.LongTy; break;
530 case pch::PREDEF_TYPE_LONGLONG_ID: T = Context.LongLongTy; break;
531 case pch::PREDEF_TYPE_FLOAT_ID: T = Context.FloatTy; break;
532 case pch::PREDEF_TYPE_DOUBLE_ID: T = Context.DoubleTy; break;
533 case pch::PREDEF_TYPE_LONGDOUBLE_ID: T = Context.LongDoubleTy; break;
534 case pch::PREDEF_TYPE_OVERLOAD_ID: T = Context.OverloadTy; break;
535 case pch::PREDEF_TYPE_DEPENDENT_ID: T = Context.DependentTy; break;
536 }
537
538 assert(!T.isNull() && "Unknown predefined type");
539 return T.getQualifiedType(Quals);
540 }
541
542 Index -= pch::NUM_PREDEF_TYPE_IDS;
543 if (!TypeAlreadyLoaded[Index]) {
544 // Load the type from the PCH file.
545 TypeOffsets[Index] = reinterpret_cast<uint64_t>(
546 ReadTypeRecord(TypeOffsets[Index]).getTypePtr());
547 TypeAlreadyLoaded[Index] = true;
548 }
549
550 return QualType(reinterpret_cast<Type *>(TypeOffsets[Index]), Quals);
551}
552
553Decl *PCHReader::GetDecl(unsigned ID) {
554 if (ID == 0)
555 return 0;
556
557 unsigned Index = ID - 1;
558 if (DeclAlreadyLoaded[Index])
559 return reinterpret_cast<Decl *>(DeclOffsets[Index]);
560
561 // Load the declaration from the PCH file.
562 return ReadDeclRecord(DeclOffsets[Index], Index);
563}
564
565bool PCHReader::ReadDeclsLexicallyInContext(DeclContext *DC,
566 llvm::SmallVectorImpl<unsigned> &Decls) {
567 assert(DC->hasExternalLexicalStorage() &&
568 "DeclContext has no lexical decls in storage");
569 uint64_t Offset = DeclContextOffsets[DC].first;
570 assert(Offset && "DeclContext has no lexical decls in storage");
571
572 // Load the record containing all of the declarations lexically in
573 // this context.
574 Stream.JumpToBit(Offset);
575 RecordData Record;
576 unsigned Code = Stream.ReadCode();
577 unsigned RecCode = Stream.ReadRecord(Code, Record);
578 assert(RecCode == pch::DECL_CONTEXT_LEXICAL && "Expected lexical block");
579
580 // Load all of the declaration IDs
581 Decls.clear();
582 Decls.insert(Decls.end(), Record.begin(), Record.end());
583 return false;
584}
585
586bool PCHReader::ReadDeclsVisibleInContext(DeclContext *DC,
587 llvm::SmallVectorImpl<VisibleDeclaration> & Decls) {
588 assert(DC->hasExternalVisibleStorage() &&
589 "DeclContext has no visible decls in storage");
590 uint64_t Offset = DeclContextOffsets[DC].second;
591 assert(Offset && "DeclContext has no visible decls in storage");
592
593 // Load the record containing all of the declarations visible in
594 // this context.
595 Stream.JumpToBit(Offset);
596 RecordData Record;
597 unsigned Code = Stream.ReadCode();
598 unsigned RecCode = Stream.ReadRecord(Code, Record);
599 assert(RecCode == pch::DECL_CONTEXT_VISIBLE && "Expected visible block");
600 if (Record.size() == 0)
601 return false;
602
603 Decls.clear();
604
605 unsigned Idx = 0;
606 // llvm::SmallVector<uintptr_t, 16> DeclIDs;
607 while (Idx < Record.size()) {
608 Decls.push_back(VisibleDeclaration());
609 Decls.back().Name = ReadDeclarationName(Record, Idx);
610
611 // FIXME: Don't actually read anything here!
612 unsigned Size = Record[Idx++];
613 llvm::SmallVector<unsigned, 4> & LoadedDecls
614 = Decls.back().Declarations;
615 LoadedDecls.reserve(Size);
616 for (unsigned I = 0; I < Size; ++I)
617 LoadedDecls.push_back(Record[Idx++]);
618 }
619
620 return false;
621}
622
623void PCHReader::PrintStats() {
624 std::fprintf(stderr, "*** PCH Statistics:\n");
625
626 unsigned NumTypesLoaded = std::count(TypeAlreadyLoaded.begin(),
627 TypeAlreadyLoaded.end(),
628 true);
629 unsigned NumDeclsLoaded = std::count(DeclAlreadyLoaded.begin(),
630 DeclAlreadyLoaded.end(),
631 true);
632 std::fprintf(stderr, " %u/%u types read (%f%%)\n",
633 NumTypesLoaded, (unsigned)TypeAlreadyLoaded.size(),
634 ((float)NumTypesLoaded/(float)TypeAlreadyLoaded.size() * 100));
635 std::fprintf(stderr, " %u/%u declarations read (%f%%)\n",
636 NumDeclsLoaded, (unsigned)DeclAlreadyLoaded.size(),
637 ((float)NumDeclsLoaded/(float)DeclAlreadyLoaded.size() * 100));
638 std::fprintf(stderr, "\n");
639}
640
641const IdentifierInfo *PCHReader::GetIdentifierInfo(const RecordData &Record,
642 unsigned &Idx) {
643 // FIXME: we need unique IDs for identifiers.
644 std::string Str;
645 unsigned Length = Record[Idx++];
646 Str.resize(Length);
647 for (unsigned I = 0; I != Length; ++I)
648 Str[I] = Record[Idx++];
649 return &Context.Idents.get(Str);
650}
651
652DeclarationName
653PCHReader::ReadDeclarationName(const RecordData &Record, unsigned &Idx) {
654 DeclarationName::NameKind Kind = (DeclarationName::NameKind)Record[Idx++];
655 switch (Kind) {
656 case DeclarationName::Identifier:
657 return DeclarationName(GetIdentifierInfo(Record, Idx));
658
659 case DeclarationName::ObjCZeroArgSelector:
660 case DeclarationName::ObjCOneArgSelector:
661 case DeclarationName::ObjCMultiArgSelector:
662 assert(false && "Unable to de-serialize Objective-C selectors");
663 break;
664
665 case DeclarationName::CXXConstructorName:
666 return Context.DeclarationNames.getCXXConstructorName(
667 GetType(Record[Idx++]));
668
669 case DeclarationName::CXXDestructorName:
670 return Context.DeclarationNames.getCXXDestructorName(
671 GetType(Record[Idx++]));
672
673 case DeclarationName::CXXConversionFunctionName:
674 return Context.DeclarationNames.getCXXConversionFunctionName(
675 GetType(Record[Idx++]));
676
677 case DeclarationName::CXXOperatorName:
678 return Context.DeclarationNames.getCXXOperatorName(
679 (OverloadedOperatorKind)Record[Idx++]);
680
681 case DeclarationName::CXXUsingDirective:
682 return DeclarationName::getUsingDirectiveName();
683 }
684
685 // Required to silence GCC warning
686 return DeclarationName();
687}