blob: ff8795ca6403fc7428d4c7ad5dfc7080fce91f9d [file] [log] [blame]
Douglas Gregor2cf26342009-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//===----------------------------------------------------------------------===//
Chris Lattner4c6f9522009-04-27 05:14:47 +000013
Douglas Gregor2cf26342009-04-09 22:27:44 +000014#include "clang/Frontend/PCHReader.h"
Douglas Gregor0a0428e2009-04-10 20:39:37 +000015#include "clang/Frontend/FrontendDiagnostic.h"
Douglas Gregor668c1a42009-04-21 22:25:48 +000016#include "../Sema/Sema.h" // FIXME: move Sema headers elsewhere
Douglas Gregorfdd01722009-04-14 00:24:19 +000017#include "clang/AST/ASTConsumer.h"
Douglas Gregor2cf26342009-04-09 22:27:44 +000018#include "clang/AST/ASTContext.h"
Douglas Gregor0b748912009-04-14 21:18:50 +000019#include "clang/AST/Expr.h"
Douglas Gregor2cf26342009-04-09 22:27:44 +000020#include "clang/AST/Type.h"
Chris Lattner42d42b52009-04-10 21:41:48 +000021#include "clang/Lex/MacroInfo.h"
Douglas Gregor14f79002009-04-10 03:52:48 +000022#include "clang/Lex/Preprocessor.h"
Steve Naroff83d63c72009-04-24 20:03:17 +000023#include "clang/Lex/HeaderSearch.h"
Douglas Gregor668c1a42009-04-21 22:25:48 +000024#include "clang/Basic/OnDiskHashTable.h"
Douglas Gregor14f79002009-04-10 03:52:48 +000025#include "clang/Basic/SourceManager.h"
Douglas Gregorbd945002009-04-13 16:31:14 +000026#include "clang/Basic/SourceManagerInternals.h"
Douglas Gregor14f79002009-04-10 03:52:48 +000027#include "clang/Basic/FileManager.h"
Douglas Gregor2bec0412009-04-10 21:16:55 +000028#include "clang/Basic/TargetInfo.h"
Douglas Gregor2cf26342009-04-09 22:27:44 +000029#include "llvm/Bitcode/BitstreamReader.h"
30#include "llvm/Support/Compiler.h"
31#include "llvm/Support/MemoryBuffer.h"
32#include <algorithm>
33#include <cstdio>
Douglas Gregor2cf26342009-04-09 22:27:44 +000034using namespace clang;
35
36//===----------------------------------------------------------------------===//
Douglas Gregor668c1a42009-04-21 22:25:48 +000037// PCH reader implementation
38//===----------------------------------------------------------------------===//
39
Chris Lattner4c6f9522009-04-27 05:14:47 +000040PCHReader::PCHReader(Preprocessor &PP, ASTContext &Context)
41 : SemaObj(0), PP(PP), Context(Context), Consumer(0),
42 IdentifierTableData(0), IdentifierLookupTable(0),
43 IdentifierOffsets(0),
44 MethodPoolLookupTable(0), MethodPoolLookupTableData(0),
45 TotalSelectorsInMethodPool(0), SelectorOffsets(0),
Douglas Gregor7f94b0b2009-04-27 06:38:32 +000046 TotalNumSelectors(0), NumSLocEntriesRead(0), NumStatementsRead(0),
47 NumMacrosRead(0), NumMethodPoolSelectorsRead(0), NumMethodPoolMisses(0),
Chris Lattner4c6f9522009-04-27 05:14:47 +000048 NumLexicalDeclContextsRead(0), NumVisibleDeclContextsRead(0) { }
49
50PCHReader::~PCHReader() {}
51
Chris Lattnerda930612009-04-27 05:58:23 +000052Expr *PCHReader::ReadDeclExpr() {
53 return dyn_cast_or_null<Expr>(ReadStmt(DeclsCursor));
54}
55
56Expr *PCHReader::ReadTypeExpr() {
Chris Lattner52e97d12009-04-27 05:41:06 +000057 return dyn_cast_or_null<Expr>(ReadStmt(Stream));
Chris Lattner4c6f9522009-04-27 05:14:47 +000058}
59
60
Douglas Gregor668c1a42009-04-21 22:25:48 +000061namespace {
Douglas Gregorf0aaf7a2009-04-24 21:10:55 +000062class VISIBILITY_HIDDEN PCHMethodPoolLookupTrait {
63 PCHReader &Reader;
64
65public:
66 typedef std::pair<ObjCMethodList, ObjCMethodList> data_type;
67
68 typedef Selector external_key_type;
69 typedef external_key_type internal_key_type;
70
71 explicit PCHMethodPoolLookupTrait(PCHReader &Reader) : Reader(Reader) { }
72
73 static bool EqualKey(const internal_key_type& a,
74 const internal_key_type& b) {
75 return a == b;
76 }
77
78 static unsigned ComputeHash(Selector Sel) {
79 unsigned N = Sel.getNumArgs();
80 if (N == 0)
81 ++N;
82 unsigned R = 5381;
83 for (unsigned I = 0; I != N; ++I)
84 if (IdentifierInfo *II = Sel.getIdentifierInfoForSlot(I))
85 R = clang::BernsteinHashPartial(II->getName(), II->getLength(), R);
86 return R;
87 }
88
89 // This hopefully will just get inlined and removed by the optimizer.
90 static const internal_key_type&
91 GetInternalKey(const external_key_type& x) { return x; }
92
93 static std::pair<unsigned, unsigned>
94 ReadKeyDataLength(const unsigned char*& d) {
95 using namespace clang::io;
96 unsigned KeyLen = ReadUnalignedLE16(d);
97 unsigned DataLen = ReadUnalignedLE16(d);
98 return std::make_pair(KeyLen, DataLen);
99 }
100
Douglas Gregor83941df2009-04-25 17:48:32 +0000101 internal_key_type ReadKey(const unsigned char* d, unsigned) {
Douglas Gregorf0aaf7a2009-04-24 21:10:55 +0000102 using namespace clang::io;
103 SelectorTable &SelTable = Reader.getContext().Selectors;
104 unsigned N = ReadUnalignedLE16(d);
105 IdentifierInfo *FirstII
106 = Reader.DecodeIdentifierInfo(ReadUnalignedLE32(d));
107 if (N == 0)
108 return SelTable.getNullarySelector(FirstII);
109 else if (N == 1)
110 return SelTable.getUnarySelector(FirstII);
111
112 llvm::SmallVector<IdentifierInfo *, 16> Args;
113 Args.push_back(FirstII);
114 for (unsigned I = 1; I != N; ++I)
115 Args.push_back(Reader.DecodeIdentifierInfo(ReadUnalignedLE32(d)));
116
117 return SelTable.getSelector(N, &Args[0]);
118 }
119
120 data_type ReadData(Selector, const unsigned char* d, unsigned DataLen) {
121 using namespace clang::io;
122 unsigned NumInstanceMethods = ReadUnalignedLE16(d);
123 unsigned NumFactoryMethods = ReadUnalignedLE16(d);
124
125 data_type Result;
126
127 // Load instance methods
128 ObjCMethodList *Prev = 0;
129 for (unsigned I = 0; I != NumInstanceMethods; ++I) {
130 ObjCMethodDecl *Method
131 = cast<ObjCMethodDecl>(Reader.GetDecl(ReadUnalignedLE32(d)));
132 if (!Result.first.Method) {
133 // This is the first method, which is the easy case.
134 Result.first.Method = Method;
135 Prev = &Result.first;
136 continue;
137 }
138
139 Prev->Next = new ObjCMethodList(Method, 0);
140 Prev = Prev->Next;
141 }
142
143 // Load factory methods
144 Prev = 0;
145 for (unsigned I = 0; I != NumFactoryMethods; ++I) {
146 ObjCMethodDecl *Method
147 = cast<ObjCMethodDecl>(Reader.GetDecl(ReadUnalignedLE32(d)));
148 if (!Result.second.Method) {
149 // This is the first method, which is the easy case.
150 Result.second.Method = Method;
151 Prev = &Result.second;
152 continue;
153 }
154
155 Prev->Next = new ObjCMethodList(Method, 0);
156 Prev = Prev->Next;
157 }
158
159 return Result;
160 }
161};
162
163} // end anonymous namespace
164
165/// \brief The on-disk hash table used for the global method pool.
166typedef OnDiskChainedHashTable<PCHMethodPoolLookupTrait>
167 PCHMethodPoolLookupTable;
168
169namespace {
Douglas Gregor668c1a42009-04-21 22:25:48 +0000170class VISIBILITY_HIDDEN PCHIdentifierLookupTrait {
171 PCHReader &Reader;
172
173 // If we know the IdentifierInfo in advance, it is here and we will
174 // not build a new one. Used when deserializing information about an
175 // identifier that was constructed before the PCH file was read.
176 IdentifierInfo *KnownII;
177
178public:
179 typedef IdentifierInfo * data_type;
180
181 typedef const std::pair<const char*, unsigned> external_key_type;
182
183 typedef external_key_type internal_key_type;
184
185 explicit PCHIdentifierLookupTrait(PCHReader &Reader, IdentifierInfo *II = 0)
186 : Reader(Reader), KnownII(II) { }
187
188 static bool EqualKey(const internal_key_type& a,
189 const internal_key_type& b) {
190 return (a.second == b.second) ? memcmp(a.first, b.first, a.second) == 0
191 : false;
192 }
193
194 static unsigned ComputeHash(const internal_key_type& a) {
195 return BernsteinHash(a.first, a.second);
196 }
197
198 // This hopefully will just get inlined and removed by the optimizer.
199 static const internal_key_type&
200 GetInternalKey(const external_key_type& x) { return x; }
201
202 static std::pair<unsigned, unsigned>
203 ReadKeyDataLength(const unsigned char*& d) {
204 using namespace clang::io;
Douglas Gregor5f8e3302009-04-25 20:26:24 +0000205 unsigned DataLen = ReadUnalignedLE16(d);
Douglas Gregord6595a42009-04-25 21:04:17 +0000206 unsigned KeyLen = ReadUnalignedLE16(d);
Douglas Gregor668c1a42009-04-21 22:25:48 +0000207 return std::make_pair(KeyLen, DataLen);
208 }
209
210 static std::pair<const char*, unsigned>
211 ReadKey(const unsigned char* d, unsigned n) {
212 assert(n >= 2 && d[n-1] == '\0');
213 return std::make_pair((const char*) d, n-1);
214 }
215
216 IdentifierInfo *ReadData(const internal_key_type& k,
217 const unsigned char* d,
218 unsigned DataLen) {
219 using namespace clang::io;
Douglas Gregor6cfc1a82009-04-22 21:15:06 +0000220 uint32_t Bits = ReadUnalignedLE32(d);
Douglas Gregor2deaea32009-04-22 18:49:13 +0000221 bool CPlusPlusOperatorKeyword = Bits & 0x01;
222 Bits >>= 1;
223 bool Poisoned = Bits & 0x01;
224 Bits >>= 1;
225 bool ExtensionToken = Bits & 0x01;
226 Bits >>= 1;
227 bool hasMacroDefinition = Bits & 0x01;
228 Bits >>= 1;
229 unsigned ObjCOrBuiltinID = Bits & 0x3FF;
230 Bits >>= 10;
231 unsigned TokenID = Bits & 0xFF;
232 Bits >>= 8;
233
Douglas Gregor668c1a42009-04-21 22:25:48 +0000234 pch::IdentID ID = ReadUnalignedLE32(d);
Douglas Gregor2deaea32009-04-22 18:49:13 +0000235 assert(Bits == 0 && "Extra bits in the identifier?");
Douglas Gregor668c1a42009-04-21 22:25:48 +0000236 DataLen -= 8;
237
238 // Build the IdentifierInfo itself and link the identifier ID with
239 // the new IdentifierInfo.
240 IdentifierInfo *II = KnownII;
241 if (!II)
Douglas Gregor5f8e3302009-04-25 20:26:24 +0000242 II = &Reader.getIdentifierTable().CreateIdentifierInfo(
243 k.first, k.first + k.second);
Douglas Gregor668c1a42009-04-21 22:25:48 +0000244 Reader.SetIdentifierInfo(ID, II);
245
Douglas Gregor2deaea32009-04-22 18:49:13 +0000246 // Set or check the various bits in the IdentifierInfo structure.
247 // FIXME: Load token IDs lazily, too?
248 assert((unsigned)II->getTokenID() == TokenID &&
249 "Incorrect token ID loaded");
250 (void)TokenID;
251 II->setObjCOrBuiltinID(ObjCOrBuiltinID);
252 assert(II->isExtensionToken() == ExtensionToken &&
253 "Incorrect extension token flag");
254 (void)ExtensionToken;
255 II->setIsPoisoned(Poisoned);
256 assert(II->isCPlusPlusOperatorKeyword() == CPlusPlusOperatorKeyword &&
257 "Incorrect C++ operator keyword flag");
258 (void)CPlusPlusOperatorKeyword;
259
Douglas Gregor37e26842009-04-21 23:56:24 +0000260 // If this identifier is a macro, deserialize the macro
261 // definition.
262 if (hasMacroDefinition) {
263 uint32_t Offset = ReadUnalignedLE64(d);
264 Reader.ReadMacroRecord(Offset);
265 DataLen -= 8;
266 }
Douglas Gregor668c1a42009-04-21 22:25:48 +0000267
268 // Read all of the declarations visible at global scope with this
269 // name.
270 Sema *SemaObj = Reader.getSema();
271 while (DataLen > 0) {
272 NamedDecl *D = cast<NamedDecl>(Reader.GetDecl(ReadUnalignedLE32(d)));
Douglas Gregor668c1a42009-04-21 22:25:48 +0000273 if (SemaObj) {
274 // Introduce this declaration into the translation-unit scope
275 // and add it to the declaration chain for this identifier, so
276 // that (unqualified) name lookup will find it.
277 SemaObj->TUScope->AddDecl(Action::DeclPtrTy::make(D));
278 SemaObj->IdResolver.AddDeclToIdentifierChain(II, D);
279 } else {
280 // Queue this declaration so that it will be added to the
281 // translation unit scope and identifier's declaration chain
282 // once a Sema object is known.
Douglas Gregor6cfc1a82009-04-22 21:15:06 +0000283 Reader.PreloadedDecls.push_back(D);
Douglas Gregor668c1a42009-04-21 22:25:48 +0000284 }
285
286 DataLen -= 4;
287 }
288 return II;
289 }
290};
291
292} // end anonymous namespace
293
294/// \brief The on-disk hash table used to contain information about
295/// all of the identifiers in the program.
296typedef OnDiskChainedHashTable<PCHIdentifierLookupTrait>
297 PCHIdentifierLookupTable;
298
Douglas Gregor2cf26342009-04-09 22:27:44 +0000299// FIXME: use the diagnostics machinery
300static bool Error(const char *Str) {
301 std::fprintf(stderr, "%s\n", Str);
302 return true;
303}
304
Douglas Gregore1d918e2009-04-10 23:10:45 +0000305/// \brief Check the contents of the predefines buffer against the
306/// contents of the predefines buffer used to build the PCH file.
307///
308/// The contents of the two predefines buffers should be the same. If
309/// not, then some command-line option changed the preprocessor state
310/// and we must reject the PCH file.
311///
312/// \param PCHPredef The start of the predefines buffer in the PCH
313/// file.
314///
315/// \param PCHPredefLen The length of the predefines buffer in the PCH
316/// file.
317///
318/// \param PCHBufferID The FileID for the PCH predefines buffer.
319///
320/// \returns true if there was a mismatch (in which case the PCH file
321/// should be ignored), or false otherwise.
322bool PCHReader::CheckPredefinesBuffer(const char *PCHPredef,
323 unsigned PCHPredefLen,
324 FileID PCHBufferID) {
325 const char *Predef = PP.getPredefines().c_str();
326 unsigned PredefLen = PP.getPredefines().size();
327
328 // If the two predefines buffers compare equal, we're done!.
329 if (PredefLen == PCHPredefLen &&
330 strncmp(Predef, PCHPredef, PCHPredefLen) == 0)
331 return false;
332
333 // The predefines buffers are different. Produce a reasonable
334 // diagnostic showing where they are different.
335
336 // The source locations (potentially in the two different predefines
337 // buffers)
338 SourceLocation Loc1, Loc2;
339 SourceManager &SourceMgr = PP.getSourceManager();
340
341 // Create a source buffer for our predefines string, so
342 // that we can build a diagnostic that points into that
343 // source buffer.
344 FileID BufferID;
345 if (Predef && Predef[0]) {
346 llvm::MemoryBuffer *Buffer
347 = llvm::MemoryBuffer::getMemBuffer(Predef, Predef + PredefLen,
348 "<built-in>");
349 BufferID = SourceMgr.createFileIDForMemBuffer(Buffer);
350 }
351
352 unsigned MinLen = std::min(PredefLen, PCHPredefLen);
353 std::pair<const char *, const char *> Locations
354 = std::mismatch(Predef, Predef + MinLen, PCHPredef);
355
356 if (Locations.first != Predef + MinLen) {
357 // We found the location in the two buffers where there is a
358 // difference. Form source locations to point there (in both
359 // buffers).
360 unsigned Offset = Locations.first - Predef;
361 Loc1 = SourceMgr.getLocForStartOfFile(BufferID)
362 .getFileLocWithOffset(Offset);
363 Loc2 = SourceMgr.getLocForStartOfFile(PCHBufferID)
364 .getFileLocWithOffset(Offset);
365 } else if (PredefLen > PCHPredefLen) {
366 Loc1 = SourceMgr.getLocForStartOfFile(BufferID)
367 .getFileLocWithOffset(MinLen);
368 } else {
369 Loc1 = SourceMgr.getLocForStartOfFile(PCHBufferID)
370 .getFileLocWithOffset(MinLen);
371 }
372
373 Diag(Loc1, diag::warn_pch_preprocessor);
374 if (Loc2.isValid())
375 Diag(Loc2, diag::note_predef_in_pch);
376 Diag(diag::note_ignoring_pch) << FileName;
377 return true;
378}
379
Douglas Gregorbd945002009-04-13 16:31:14 +0000380/// \brief Read the line table in the source manager block.
381/// \returns true if ther was an error.
382static bool ParseLineTable(SourceManager &SourceMgr,
383 llvm::SmallVectorImpl<uint64_t> &Record) {
384 unsigned Idx = 0;
385 LineTableInfo &LineTable = SourceMgr.getLineTable();
386
387 // Parse the file names
Douglas Gregorff0a9872009-04-13 17:12:42 +0000388 std::map<int, int> FileIDs;
389 for (int I = 0, N = Record[Idx++]; I != N; ++I) {
Douglas Gregorbd945002009-04-13 16:31:14 +0000390 // Extract the file name
391 unsigned FilenameLen = Record[Idx++];
392 std::string Filename(&Record[Idx], &Record[Idx] + FilenameLen);
393 Idx += FilenameLen;
Douglas Gregorff0a9872009-04-13 17:12:42 +0000394 FileIDs[I] = LineTable.getLineTableFilenameID(Filename.c_str(),
395 Filename.size());
Douglas Gregorbd945002009-04-13 16:31:14 +0000396 }
397
398 // Parse the line entries
399 std::vector<LineEntry> Entries;
400 while (Idx < Record.size()) {
Douglas Gregorff0a9872009-04-13 17:12:42 +0000401 int FID = FileIDs[Record[Idx++]];
Douglas Gregorbd945002009-04-13 16:31:14 +0000402
403 // Extract the line entries
404 unsigned NumEntries = Record[Idx++];
405 Entries.clear();
406 Entries.reserve(NumEntries);
407 for (unsigned I = 0; I != NumEntries; ++I) {
408 unsigned FileOffset = Record[Idx++];
409 unsigned LineNo = Record[Idx++];
410 int FilenameID = Record[Idx++];
411 SrcMgr::CharacteristicKind FileKind
412 = (SrcMgr::CharacteristicKind)Record[Idx++];
413 unsigned IncludeOffset = Record[Idx++];
414 Entries.push_back(LineEntry::get(FileOffset, LineNo, FilenameID,
415 FileKind, IncludeOffset));
416 }
417 LineTable.AddEntry(FID, Entries);
418 }
419
420 return false;
421}
422
Douglas Gregor14f79002009-04-10 03:52:48 +0000423/// \brief Read the source manager block
Douglas Gregore1d918e2009-04-10 23:10:45 +0000424PCHReader::PCHReadResult PCHReader::ReadSourceManagerBlock() {
Douglas Gregor14f79002009-04-10 03:52:48 +0000425 using namespace SrcMgr;
Douglas Gregor7f94b0b2009-04-27 06:38:32 +0000426
427 // Set the source-location entry cursor to the current position in
428 // the stream. This cursor will be used to read the contents of the
429 // source manager block initially, and then lazily read
430 // source-location entries as needed.
431 SLocEntryCursor = Stream;
432
433 // The stream itself is going to skip over the source manager block.
434 if (Stream.SkipBlock()) {
435 Error("Malformed block record");
436 return Failure;
437 }
438
439 // Enter the source manager block.
440 if (SLocEntryCursor.EnterSubBlock(pch::SOURCE_MANAGER_BLOCK_ID)) {
Douglas Gregore1d918e2009-04-10 23:10:45 +0000441 Error("Malformed source manager block record");
442 return Failure;
443 }
Douglas Gregor14f79002009-04-10 03:52:48 +0000444
445 SourceManager &SourceMgr = Context.getSourceManager();
446 RecordData Record;
Douglas Gregor2eafc1b2009-04-26 00:07:37 +0000447 unsigned NumHeaderInfos = 0;
Douglas Gregor14f79002009-04-10 03:52:48 +0000448 while (true) {
Douglas Gregor7f94b0b2009-04-27 06:38:32 +0000449 unsigned Code = SLocEntryCursor.ReadCode();
Douglas Gregor14f79002009-04-10 03:52:48 +0000450 if (Code == llvm::bitc::END_BLOCK) {
Douglas Gregor7f94b0b2009-04-27 06:38:32 +0000451 if (SLocEntryCursor.ReadBlockEnd()) {
Douglas Gregore1d918e2009-04-10 23:10:45 +0000452 Error("Error at end of Source Manager block");
453 return Failure;
454 }
Douglas Gregore1d918e2009-04-10 23:10:45 +0000455 return Success;
Douglas Gregor14f79002009-04-10 03:52:48 +0000456 }
457
458 if (Code == llvm::bitc::ENTER_SUBBLOCK) {
459 // No known subblocks, always skip them.
Douglas Gregor7f94b0b2009-04-27 06:38:32 +0000460 SLocEntryCursor.ReadSubBlockID();
461 if (SLocEntryCursor.SkipBlock()) {
Douglas Gregore1d918e2009-04-10 23:10:45 +0000462 Error("Malformed block record");
463 return Failure;
464 }
Douglas Gregor14f79002009-04-10 03:52:48 +0000465 continue;
466 }
467
468 if (Code == llvm::bitc::DEFINE_ABBREV) {
Douglas Gregor7f94b0b2009-04-27 06:38:32 +0000469 SLocEntryCursor.ReadAbbrevRecord();
Douglas Gregor14f79002009-04-10 03:52:48 +0000470 continue;
471 }
472
473 // Read a record.
474 const char *BlobStart;
475 unsigned BlobLen;
476 Record.clear();
Douglas Gregor7f94b0b2009-04-27 06:38:32 +0000477 switch (SLocEntryCursor.ReadRecord(Code, Record, &BlobStart, &BlobLen)) {
Douglas Gregor14f79002009-04-10 03:52:48 +0000478 default: // Default behavior: ignore.
479 break;
480
Chris Lattner2c78b872009-04-14 23:22:57 +0000481 case pch::SM_LINE_TABLE:
Douglas Gregorbd945002009-04-13 16:31:14 +0000482 if (ParseLineTable(SourceMgr, Record))
483 return Failure;
Chris Lattner2c78b872009-04-14 23:22:57 +0000484 break;
Douglas Gregor2eafc1b2009-04-26 00:07:37 +0000485
486 case pch::SM_HEADER_FILE_INFO: {
487 HeaderFileInfo HFI;
488 HFI.isImport = Record[0];
489 HFI.DirInfo = Record[1];
490 HFI.NumIncludes = Record[2];
491 HFI.ControllingMacroID = Record[3];
492 PP.getHeaderSearchInfo().setHeaderFileInfoForUID(HFI, NumHeaderInfos++);
493 break;
494 }
Douglas Gregor7f94b0b2009-04-27 06:38:32 +0000495
496 case pch::SM_SLOC_FILE_ENTRY:
497 case pch::SM_SLOC_BUFFER_ENTRY:
498 case pch::SM_SLOC_INSTANTIATION_ENTRY:
499 // Once we hit one of the source location entries, we're done.
500 return Success;
Douglas Gregor14f79002009-04-10 03:52:48 +0000501 }
502 }
503}
504
Douglas Gregor7f94b0b2009-04-27 06:38:32 +0000505/// \brief Read in the source location entry with the given ID.
506PCHReader::PCHReadResult PCHReader::ReadSLocEntryRecord(unsigned ID) {
507 if (ID == 0)
508 return Success;
509
510 if (ID > TotalNumSLocEntries) {
511 Error("source location entry ID out-of-range for PCH file");
512 return Failure;
513 }
514
515 ++NumSLocEntriesRead;
516 SLocEntryCursor.JumpToBit(SLocOffsets[ID - 1]);
517 unsigned Code = SLocEntryCursor.ReadCode();
518 if (Code == llvm::bitc::END_BLOCK ||
519 Code == llvm::bitc::ENTER_SUBBLOCK ||
520 Code == llvm::bitc::DEFINE_ABBREV) {
521 Error("incorrectly-formatted source location entry in PCH file");
522 return Failure;
523 }
524
525 SourceManager &SourceMgr = Context.getSourceManager();
526 RecordData Record;
527 const char *BlobStart;
528 unsigned BlobLen;
529 switch (SLocEntryCursor.ReadRecord(Code, Record, &BlobStart, &BlobLen)) {
530 default:
531 Error("incorrectly-formatted source location entry in PCH file");
532 return Failure;
533
534 case pch::SM_SLOC_FILE_ENTRY: {
535 const FileEntry *File
536 = PP.getFileManager().getFile(BlobStart, BlobStart + BlobLen);
537 // FIXME: Error recovery if file cannot be found.
538 FileID FID = SourceMgr.createFileID(File,
539 SourceLocation::getFromRawEncoding(Record[1]),
540 (SrcMgr::CharacteristicKind)Record[2],
541 ID, Record[0]);
542 if (Record[3])
543 const_cast<SrcMgr::FileInfo&>(SourceMgr.getSLocEntry(FID).getFile())
544 .setHasLineDirectives();
545
546 break;
547 }
548
549 case pch::SM_SLOC_BUFFER_ENTRY: {
550 const char *Name = BlobStart;
551 unsigned Offset = Record[0];
552 unsigned Code = SLocEntryCursor.ReadCode();
553 Record.clear();
554 unsigned RecCode
555 = SLocEntryCursor.ReadRecord(Code, Record, &BlobStart, &BlobLen);
556 assert(RecCode == pch::SM_SLOC_BUFFER_BLOB && "Ill-formed PCH file");
557 (void)RecCode;
558 llvm::MemoryBuffer *Buffer
559 = llvm::MemoryBuffer::getMemBuffer(BlobStart,
560 BlobStart + BlobLen - 1,
561 Name);
562 FileID BufferID = SourceMgr.createFileIDForMemBuffer(Buffer, ID, Offset);
563
564 if (strcmp(Name, "<built-in>") == 0
565 && CheckPredefinesBuffer(BlobStart, BlobLen - 1, BufferID))
566 return IgnorePCH;
567
568 break;
569 }
570
571 case pch::SM_SLOC_INSTANTIATION_ENTRY: {
572 SourceLocation SpellingLoc
573 = SourceLocation::getFromRawEncoding(Record[1]);
574 SourceMgr.createInstantiationLoc(SpellingLoc,
575 SourceLocation::getFromRawEncoding(Record[2]),
576 SourceLocation::getFromRawEncoding(Record[3]),
577 Record[4],
578 ID,
579 Record[0]);
580 break;
581 }
582 }
583
584 return Success;
585}
586
Chris Lattner6367f6d2009-04-27 01:05:14 +0000587/// ReadBlockAbbrevs - Enter a subblock of the specified BlockID with the
588/// specified cursor. Read the abbreviations that are at the top of the block
589/// and then leave the cursor pointing into the block.
590bool PCHReader::ReadBlockAbbrevs(llvm::BitstreamCursor &Cursor,
591 unsigned BlockID) {
592 if (Cursor.EnterSubBlock(BlockID)) {
593 Error("Malformed block record");
594 return Failure;
595 }
596
Chris Lattner6367f6d2009-04-27 01:05:14 +0000597 while (true) {
598 unsigned Code = Cursor.ReadCode();
599
600 // We expect all abbrevs to be at the start of the block.
601 if (Code != llvm::bitc::DEFINE_ABBREV)
602 return false;
603 Cursor.ReadAbbrevRecord();
604 }
605}
606
Douglas Gregor37e26842009-04-21 23:56:24 +0000607void PCHReader::ReadMacroRecord(uint64_t Offset) {
608 // Keep track of where we are in the stream, then jump back there
609 // after reading this macro.
610 SavedStreamPosition SavedPosition(Stream);
611
612 Stream.JumpToBit(Offset);
613 RecordData Record;
614 llvm::SmallVector<IdentifierInfo*, 16> MacroArgs;
615 MacroInfo *Macro = 0;
Steve Naroff83d63c72009-04-24 20:03:17 +0000616
Douglas Gregor37e26842009-04-21 23:56:24 +0000617 while (true) {
618 unsigned Code = Stream.ReadCode();
619 switch (Code) {
620 case llvm::bitc::END_BLOCK:
621 return;
622
623 case llvm::bitc::ENTER_SUBBLOCK:
624 // No known subblocks, always skip them.
625 Stream.ReadSubBlockID();
626 if (Stream.SkipBlock()) {
627 Error("Malformed block record");
628 return;
629 }
630 continue;
631
632 case llvm::bitc::DEFINE_ABBREV:
633 Stream.ReadAbbrevRecord();
634 continue;
635 default: break;
636 }
637
638 // Read a record.
639 Record.clear();
640 pch::PreprocessorRecordTypes RecType =
641 (pch::PreprocessorRecordTypes)Stream.ReadRecord(Code, Record);
642 switch (RecType) {
Douglas Gregor37e26842009-04-21 23:56:24 +0000643 case pch::PP_MACRO_OBJECT_LIKE:
644 case pch::PP_MACRO_FUNCTION_LIKE: {
645 // If we already have a macro, that means that we've hit the end
646 // of the definition of the macro we were looking for. We're
647 // done.
648 if (Macro)
649 return;
650
651 IdentifierInfo *II = DecodeIdentifierInfo(Record[0]);
652 if (II == 0) {
653 Error("Macro must have a name");
654 return;
655 }
656 SourceLocation Loc = SourceLocation::getFromRawEncoding(Record[1]);
657 bool isUsed = Record[2];
658
659 MacroInfo *MI = PP.AllocateMacroInfo(Loc);
660 MI->setIsUsed(isUsed);
661
662 if (RecType == pch::PP_MACRO_FUNCTION_LIKE) {
663 // Decode function-like macro info.
664 bool isC99VarArgs = Record[3];
665 bool isGNUVarArgs = Record[4];
666 MacroArgs.clear();
667 unsigned NumArgs = Record[5];
668 for (unsigned i = 0; i != NumArgs; ++i)
669 MacroArgs.push_back(DecodeIdentifierInfo(Record[6+i]));
670
671 // Install function-like macro info.
672 MI->setIsFunctionLike();
673 if (isC99VarArgs) MI->setIsC99Varargs();
674 if (isGNUVarArgs) MI->setIsGNUVarargs();
675 MI->setArgumentList(&MacroArgs[0], MacroArgs.size(),
676 PP.getPreprocessorAllocator());
677 }
678
679 // Finally, install the macro.
680 PP.setMacroInfo(II, MI);
681
682 // Remember that we saw this macro last so that we add the tokens that
683 // form its body to it.
684 Macro = MI;
685 ++NumMacrosRead;
686 break;
687 }
688
689 case pch::PP_TOKEN: {
690 // If we see a TOKEN before a PP_MACRO_*, then the file is
691 // erroneous, just pretend we didn't see this.
692 if (Macro == 0) break;
693
694 Token Tok;
695 Tok.startToken();
696 Tok.setLocation(SourceLocation::getFromRawEncoding(Record[0]));
697 Tok.setLength(Record[1]);
698 if (IdentifierInfo *II = DecodeIdentifierInfo(Record[2]))
699 Tok.setIdentifierInfo(II);
700 Tok.setKind((tok::TokenKind)Record[3]);
701 Tok.setFlag((Token::TokenFlags)Record[4]);
702 Macro->AddTokenToBody(Tok);
703 break;
704 }
Steve Naroff83d63c72009-04-24 20:03:17 +0000705 }
Douglas Gregor37e26842009-04-21 23:56:24 +0000706 }
707}
708
Douglas Gregor668c1a42009-04-21 22:25:48 +0000709PCHReader::PCHReadResult
Douglas Gregor2eafc1b2009-04-26 00:07:37 +0000710PCHReader::ReadPCHBlock() {
Douglas Gregor0a0428e2009-04-10 20:39:37 +0000711 if (Stream.EnterSubBlock(pch::PCH_BLOCK_ID)) {
712 Error("Malformed block record");
713 return Failure;
714 }
Douglas Gregor2cf26342009-04-09 22:27:44 +0000715
716 // Read all of the records and blocks for the PCH file.
Douglas Gregor8038d512009-04-10 17:25:41 +0000717 RecordData Record;
Douglas Gregor2cf26342009-04-09 22:27:44 +0000718 while (!Stream.AtEndOfStream()) {
719 unsigned Code = Stream.ReadCode();
720 if (Code == llvm::bitc::END_BLOCK) {
Douglas Gregor0a0428e2009-04-10 20:39:37 +0000721 if (Stream.ReadBlockEnd()) {
722 Error("Error at end of module block");
723 return Failure;
724 }
Chris Lattner7356a312009-04-11 21:15:38 +0000725
Douglas Gregor0a0428e2009-04-10 20:39:37 +0000726 return Success;
Douglas Gregor2cf26342009-04-09 22:27:44 +0000727 }
728
729 if (Code == llvm::bitc::ENTER_SUBBLOCK) {
730 switch (Stream.ReadSubBlockID()) {
Douglas Gregor2cf26342009-04-09 22:27:44 +0000731 case pch::TYPES_BLOCK_ID: // Skip types block (lazily loaded)
732 default: // Skip unknown content.
Douglas Gregor0a0428e2009-04-10 20:39:37 +0000733 if (Stream.SkipBlock()) {
734 Error("Malformed block record");
735 return Failure;
736 }
Douglas Gregor2cf26342009-04-09 22:27:44 +0000737 break;
738
Chris Lattner6367f6d2009-04-27 01:05:14 +0000739 case pch::DECLS_BLOCK_ID:
740 // We lazily load the decls block, but we want to set up the
741 // DeclsCursor cursor to point into it. Clone our current bitcode
742 // cursor to it, enter the block and read the abbrevs in that block.
743 // With the main cursor, we just skip over it.
744 DeclsCursor = Stream;
745 if (Stream.SkipBlock() || // Skip with the main cursor.
746 // Read the abbrevs.
747 ReadBlockAbbrevs(DeclsCursor, pch::DECLS_BLOCK_ID)) {
748 Error("Malformed block record");
749 return Failure;
750 }
751 break;
752
Chris Lattner7356a312009-04-11 21:15:38 +0000753 case pch::PREPROCESSOR_BLOCK_ID:
Chris Lattner7356a312009-04-11 21:15:38 +0000754 if (Stream.SkipBlock()) {
755 Error("Malformed block record");
756 return Failure;
757 }
758 break;
Steve Naroff90cd1bb2009-04-23 10:39:46 +0000759
Douglas Gregor14f79002009-04-10 03:52:48 +0000760 case pch::SOURCE_MANAGER_BLOCK_ID:
Douglas Gregore1d918e2009-04-10 23:10:45 +0000761 switch (ReadSourceManagerBlock()) {
762 case Success:
763 break;
764
765 case Failure:
Douglas Gregor0a0428e2009-04-10 20:39:37 +0000766 Error("Malformed source manager block");
767 return Failure;
Douglas Gregore1d918e2009-04-10 23:10:45 +0000768
769 case IgnorePCH:
770 return IgnorePCH;
Douglas Gregor0a0428e2009-04-10 20:39:37 +0000771 }
Douglas Gregor14f79002009-04-10 03:52:48 +0000772 break;
Douglas Gregor2cf26342009-04-09 22:27:44 +0000773 }
Douglas Gregor8038d512009-04-10 17:25:41 +0000774 continue;
775 }
776
777 if (Code == llvm::bitc::DEFINE_ABBREV) {
778 Stream.ReadAbbrevRecord();
779 continue;
780 }
781
782 // Read and process a record.
783 Record.clear();
Douglas Gregor2bec0412009-04-10 21:16:55 +0000784 const char *BlobStart = 0;
785 unsigned BlobLen = 0;
786 switch ((pch::PCHRecordTypes)Stream.ReadRecord(Code, Record,
787 &BlobStart, &BlobLen)) {
Douglas Gregor8038d512009-04-10 17:25:41 +0000788 default: // Default behavior: ignore.
789 break;
790
791 case pch::TYPE_OFFSET:
Douglas Gregor8f5dc7f2009-04-25 18:35:21 +0000792 if (!TypesLoaded.empty()) {
Douglas Gregor0a0428e2009-04-10 20:39:37 +0000793 Error("Duplicate TYPE_OFFSET record in PCH file");
794 return Failure;
795 }
Douglas Gregor8f5dc7f2009-04-25 18:35:21 +0000796 TypeOffsets = (const uint64_t *)BlobStart;
797 TypesLoaded.resize(Record[0]);
Douglas Gregor8038d512009-04-10 17:25:41 +0000798 break;
799
800 case pch::DECL_OFFSET:
Douglas Gregor8f5dc7f2009-04-25 18:35:21 +0000801 if (!DeclsLoaded.empty()) {
Douglas Gregor0a0428e2009-04-10 20:39:37 +0000802 Error("Duplicate DECL_OFFSET record in PCH file");
803 return Failure;
804 }
Douglas Gregor8f5dc7f2009-04-25 18:35:21 +0000805 DeclOffsets = (const uint64_t *)BlobStart;
806 DeclsLoaded.resize(Record[0]);
Douglas Gregor8038d512009-04-10 17:25:41 +0000807 break;
Douglas Gregor0a0428e2009-04-10 20:39:37 +0000808
809 case pch::LANGUAGE_OPTIONS:
810 if (ParseLanguageOptions(Record))
811 return IgnorePCH;
812 break;
Douglas Gregor2bec0412009-04-10 21:16:55 +0000813
Douglas Gregorafaf3082009-04-11 00:14:32 +0000814 case pch::TARGET_TRIPLE: {
Douglas Gregor2bec0412009-04-10 21:16:55 +0000815 std::string TargetTriple(BlobStart, BlobLen);
816 if (TargetTriple != Context.Target.getTargetTriple()) {
817 Diag(diag::warn_pch_target_triple)
818 << TargetTriple << Context.Target.getTargetTriple();
819 Diag(diag::note_ignoring_pch) << FileName;
820 return IgnorePCH;
821 }
822 break;
Douglas Gregor2cf26342009-04-09 22:27:44 +0000823 }
Douglas Gregorafaf3082009-04-11 00:14:32 +0000824
825 case pch::IDENTIFIER_TABLE:
Douglas Gregor668c1a42009-04-21 22:25:48 +0000826 IdentifierTableData = BlobStart;
Douglas Gregor2b3a5a82009-04-25 19:10:14 +0000827 if (Record[0]) {
828 IdentifierLookupTable
829 = PCHIdentifierLookupTable::Create(
Douglas Gregor668c1a42009-04-21 22:25:48 +0000830 (const unsigned char *)IdentifierTableData + Record[0],
831 (const unsigned char *)IdentifierTableData,
832 PCHIdentifierLookupTrait(*this));
Douglas Gregor2b3a5a82009-04-25 19:10:14 +0000833 PP.getIdentifierTable().setExternalIdentifierLookup(this);
834 }
Douglas Gregorafaf3082009-04-11 00:14:32 +0000835 break;
836
837 case pch::IDENTIFIER_OFFSET:
Douglas Gregor2b3a5a82009-04-25 19:10:14 +0000838 if (!IdentifiersLoaded.empty()) {
Douglas Gregorafaf3082009-04-11 00:14:32 +0000839 Error("Duplicate IDENTIFIER_OFFSET record in PCH file");
840 return Failure;
841 }
Douglas Gregor2b3a5a82009-04-25 19:10:14 +0000842 IdentifierOffsets = (const uint32_t *)BlobStart;
843 IdentifiersLoaded.resize(Record[0]);
Douglas Gregor8c5a7602009-04-25 23:30:02 +0000844 PP.getHeaderSearchInfo().SetExternalLookup(this);
Douglas Gregorafaf3082009-04-11 00:14:32 +0000845 break;
Douglas Gregorfdd01722009-04-14 00:24:19 +0000846
847 case pch::EXTERNAL_DEFINITIONS:
848 if (!ExternalDefinitions.empty()) {
849 Error("Duplicate EXTERNAL_DEFINITIONS record in PCH file");
850 return Failure;
851 }
852 ExternalDefinitions.swap(Record);
853 break;
Douglas Gregor3e1af842009-04-17 22:13:46 +0000854
Douglas Gregorad1de002009-04-18 05:55:16 +0000855 case pch::SPECIAL_TYPES:
856 SpecialTypes.swap(Record);
857 break;
858
Douglas Gregor3e1af842009-04-17 22:13:46 +0000859 case pch::STATISTICS:
860 TotalNumStatements = Record[0];
Douglas Gregor37e26842009-04-21 23:56:24 +0000861 TotalNumMacros = Record[1];
Douglas Gregor25123082009-04-22 22:34:57 +0000862 TotalLexicalDeclContexts = Record[2];
863 TotalVisibleDeclContexts = Record[3];
Douglas Gregor3e1af842009-04-17 22:13:46 +0000864 break;
Douglas Gregor7f94b0b2009-04-27 06:38:32 +0000865
Douglas Gregor4c0e86b2009-04-22 22:02:47 +0000866 case pch::TENTATIVE_DEFINITIONS:
867 if (!TentativeDefinitions.empty()) {
868 Error("Duplicate TENTATIVE_DEFINITIONS record in PCH file");
869 return Failure;
870 }
871 TentativeDefinitions.swap(Record);
872 break;
Douglas Gregor14c22f22009-04-22 22:18:58 +0000873
874 case pch::LOCALLY_SCOPED_EXTERNAL_DECLS:
875 if (!LocallyScopedExternalDecls.empty()) {
876 Error("Duplicate LOCALLY_SCOPED_EXTERNAL_DECLS record in PCH file");
877 return Failure;
878 }
879 LocallyScopedExternalDecls.swap(Record);
880 break;
Douglas Gregorf0aaf7a2009-04-24 21:10:55 +0000881
Douglas Gregor83941df2009-04-25 17:48:32 +0000882 case pch::SELECTOR_OFFSETS:
883 SelectorOffsets = (const uint32_t *)BlobStart;
884 TotalNumSelectors = Record[0];
885 SelectorsLoaded.resize(TotalNumSelectors);
886 break;
887
Douglas Gregorf0aaf7a2009-04-24 21:10:55 +0000888 case pch::METHOD_POOL:
Douglas Gregor83941df2009-04-25 17:48:32 +0000889 MethodPoolLookupTableData = (const unsigned char *)BlobStart;
890 if (Record[0])
891 MethodPoolLookupTable
892 = PCHMethodPoolLookupTable::Create(
893 MethodPoolLookupTableData + Record[0],
894 MethodPoolLookupTableData,
Douglas Gregorf0aaf7a2009-04-24 21:10:55 +0000895 PCHMethodPoolLookupTrait(*this));
Douglas Gregor83941df2009-04-25 17:48:32 +0000896 TotalSelectorsInMethodPool = Record[1];
Douglas Gregorf0aaf7a2009-04-24 21:10:55 +0000897 break;
Douglas Gregor2eafc1b2009-04-26 00:07:37 +0000898
899 case pch::PP_COUNTER_VALUE:
900 if (!Record.empty())
901 PP.setCounterValue(Record[0]);
902 break;
Douglas Gregor7f94b0b2009-04-27 06:38:32 +0000903
904 case pch::SOURCE_LOCATION_OFFSETS:
905 SLocOffsets = (const uint64_t *)BlobStart;
906 TotalNumSLocEntries = Record[0];
907 PP.getSourceManager().PreallocateSLocEntries(this,
908 TotalNumSLocEntries,
909 Record[1]);
910 break;
911
912 case pch::SOURCE_LOCATION_PRELOADS:
913 for (unsigned I = 0, N = Record.size(); I != N; ++I) {
914 PCHReadResult Result = ReadSLocEntryRecord(Record[I]);
915 if (Result != Success)
916 return Result;
917 }
918 break;
Douglas Gregorafaf3082009-04-11 00:14:32 +0000919 }
Douglas Gregor2cf26342009-04-09 22:27:44 +0000920 }
Douglas Gregor0a0428e2009-04-10 20:39:37 +0000921 Error("Premature end of bitstream");
922 return Failure;
Douglas Gregor2cf26342009-04-09 22:27:44 +0000923}
924
Douglas Gregore1d918e2009-04-10 23:10:45 +0000925PCHReader::PCHReadResult PCHReader::ReadPCH(const std::string &FileName) {
Douglas Gregor0a0428e2009-04-10 20:39:37 +0000926 // Set the PCH file name.
927 this->FileName = FileName;
928
Douglas Gregor2cf26342009-04-09 22:27:44 +0000929 // Open the PCH file.
930 std::string ErrStr;
931 Buffer.reset(llvm::MemoryBuffer::getFile(FileName.c_str(), &ErrStr));
Douglas Gregore1d918e2009-04-10 23:10:45 +0000932 if (!Buffer) {
933 Error(ErrStr.c_str());
934 return IgnorePCH;
935 }
Douglas Gregor2cf26342009-04-09 22:27:44 +0000936
937 // Initialize the stream
Chris Lattnerb9fa9172009-04-26 20:59:20 +0000938 StreamFile.init((const unsigned char *)Buffer->getBufferStart(),
939 (const unsigned char *)Buffer->getBufferEnd());
940 Stream.init(StreamFile);
Douglas Gregor2cf26342009-04-09 22:27:44 +0000941
942 // Sniff for the signature.
943 if (Stream.Read(8) != 'C' ||
944 Stream.Read(8) != 'P' ||
945 Stream.Read(8) != 'C' ||
Douglas Gregore1d918e2009-04-10 23:10:45 +0000946 Stream.Read(8) != 'H') {
947 Error("Not a PCH file");
948 return IgnorePCH;
949 }
Douglas Gregor2cf26342009-04-09 22:27:44 +0000950
Douglas Gregor2cf26342009-04-09 22:27:44 +0000951 while (!Stream.AtEndOfStream()) {
952 unsigned Code = Stream.ReadCode();
953
Douglas Gregore1d918e2009-04-10 23:10:45 +0000954 if (Code != llvm::bitc::ENTER_SUBBLOCK) {
955 Error("Invalid record at top-level");
956 return Failure;
957 }
Douglas Gregor2cf26342009-04-09 22:27:44 +0000958
959 unsigned BlockID = Stream.ReadSubBlockID();
Douglas Gregor668c1a42009-04-21 22:25:48 +0000960
Douglas Gregor2cf26342009-04-09 22:27:44 +0000961 // We only know the PCH subblock ID.
962 switch (BlockID) {
963 case llvm::bitc::BLOCKINFO_BLOCK_ID:
Douglas Gregore1d918e2009-04-10 23:10:45 +0000964 if (Stream.ReadBlockInfoBlock()) {
965 Error("Malformed BlockInfoBlock");
966 return Failure;
967 }
Douglas Gregor2cf26342009-04-09 22:27:44 +0000968 break;
969 case pch::PCH_BLOCK_ID:
Douglas Gregor2eafc1b2009-04-26 00:07:37 +0000970 switch (ReadPCHBlock()) {
Douglas Gregor0a0428e2009-04-10 20:39:37 +0000971 case Success:
972 break;
973
974 case Failure:
Douglas Gregore1d918e2009-04-10 23:10:45 +0000975 return Failure;
Douglas Gregor0a0428e2009-04-10 20:39:37 +0000976
977 case IgnorePCH:
Douglas Gregor2bec0412009-04-10 21:16:55 +0000978 // FIXME: We could consider reading through to the end of this
979 // PCH block, skipping subblocks, to see if there are other
980 // PCH blocks elsewhere.
Douglas Gregore1d918e2009-04-10 23:10:45 +0000981 return IgnorePCH;
Douglas Gregor0a0428e2009-04-10 20:39:37 +0000982 }
Douglas Gregor2cf26342009-04-09 22:27:44 +0000983 break;
984 default:
Douglas Gregore1d918e2009-04-10 23:10:45 +0000985 if (Stream.SkipBlock()) {
986 Error("Malformed block record");
987 return Failure;
988 }
Douglas Gregor2cf26342009-04-09 22:27:44 +0000989 break;
990 }
991 }
992
993 // Load the translation unit declaration
994 ReadDeclRecord(DeclOffsets[0], 0);
995
Douglas Gregor668c1a42009-04-21 22:25:48 +0000996 // Initialization of builtins and library builtins occurs before the
997 // PCH file is read, so there may be some identifiers that were
998 // loaded into the IdentifierTable before we intercepted the
999 // creation of identifiers. Iterate through the list of known
1000 // identifiers and determine whether we have to establish
1001 // preprocessor definitions or top-level identifier declaration
1002 // chains for those identifiers.
1003 //
1004 // We copy the IdentifierInfo pointers to a small vector first,
1005 // since de-serializing declarations or macro definitions can add
1006 // new entries into the identifier table, invalidating the
1007 // iterators.
1008 llvm::SmallVector<IdentifierInfo *, 128> Identifiers;
1009 for (IdentifierTable::iterator Id = PP.getIdentifierTable().begin(),
1010 IdEnd = PP.getIdentifierTable().end();
1011 Id != IdEnd; ++Id)
1012 Identifiers.push_back(Id->second);
1013 PCHIdentifierLookupTable *IdTable
1014 = (PCHIdentifierLookupTable *)IdentifierLookupTable;
1015 for (unsigned I = 0, N = Identifiers.size(); I != N; ++I) {
1016 IdentifierInfo *II = Identifiers[I];
1017 // Look in the on-disk hash table for an entry for
1018 PCHIdentifierLookupTrait Info(*this, II);
1019 std::pair<const char*, unsigned> Key(II->getName(), II->getLength());
1020 PCHIdentifierLookupTable::iterator Pos = IdTable->find(Key, &Info);
1021 if (Pos == IdTable->end())
1022 continue;
1023
1024 // Dereferencing the iterator has the effect of populating the
1025 // IdentifierInfo node with the various declarations it needs.
1026 (void)*Pos;
1027 }
1028
Douglas Gregorad1de002009-04-18 05:55:16 +00001029 // Load the special types.
1030 Context.setBuiltinVaListType(
1031 GetType(SpecialTypes[pch::SPECIAL_TYPE_BUILTIN_VA_LIST]));
Douglas Gregor319ac892009-04-23 22:29:11 +00001032 if (unsigned Id = SpecialTypes[pch::SPECIAL_TYPE_OBJC_ID])
1033 Context.setObjCIdType(GetType(Id));
1034 if (unsigned Sel = SpecialTypes[pch::SPECIAL_TYPE_OBJC_SELECTOR])
1035 Context.setObjCSelType(GetType(Sel));
1036 if (unsigned Proto = SpecialTypes[pch::SPECIAL_TYPE_OBJC_PROTOCOL])
1037 Context.setObjCProtoType(GetType(Proto));
1038 if (unsigned Class = SpecialTypes[pch::SPECIAL_TYPE_OBJC_CLASS])
1039 Context.setObjCClassType(GetType(Class));
1040 if (unsigned String = SpecialTypes[pch::SPECIAL_TYPE_CF_CONSTANT_STRING])
1041 Context.setCFConstantStringType(GetType(String));
1042 if (unsigned FastEnum
1043 = SpecialTypes[pch::SPECIAL_TYPE_OBJC_FAST_ENUMERATION_STATE])
1044 Context.setObjCFastEnumerationStateType(GetType(FastEnum));
Douglas Gregor0b748912009-04-14 21:18:50 +00001045
Douglas Gregor668c1a42009-04-21 22:25:48 +00001046 return Success;
Douglas Gregor0b748912009-04-14 21:18:50 +00001047}
1048
Douglas Gregor0a0428e2009-04-10 20:39:37 +00001049/// \brief Parse the record that corresponds to a LangOptions data
1050/// structure.
1051///
1052/// This routine compares the language options used to generate the
1053/// PCH file against the language options set for the current
1054/// compilation. For each option, we classify differences between the
1055/// two compiler states as either "benign" or "important". Benign
1056/// differences don't matter, and we accept them without complaint
1057/// (and without modifying the language options). Differences between
1058/// the states for important options cause the PCH file to be
1059/// unusable, so we emit a warning and return true to indicate that
1060/// there was an error.
1061///
1062/// \returns true if the PCH file is unacceptable, false otherwise.
1063bool PCHReader::ParseLanguageOptions(
1064 const llvm::SmallVectorImpl<uint64_t> &Record) {
1065 const LangOptions &LangOpts = Context.getLangOptions();
1066#define PARSE_LANGOPT_BENIGN(Option) ++Idx
1067#define PARSE_LANGOPT_IMPORTANT(Option, DiagID) \
1068 if (Record[Idx] != LangOpts.Option) { \
1069 Diag(DiagID) << (unsigned)Record[Idx] << LangOpts.Option; \
1070 Diag(diag::note_ignoring_pch) << FileName; \
1071 return true; \
1072 } \
1073 ++Idx
1074
1075 unsigned Idx = 0;
1076 PARSE_LANGOPT_BENIGN(Trigraphs);
1077 PARSE_LANGOPT_BENIGN(BCPLComment);
1078 PARSE_LANGOPT_BENIGN(DollarIdents);
1079 PARSE_LANGOPT_BENIGN(AsmPreprocessor);
1080 PARSE_LANGOPT_IMPORTANT(GNUMode, diag::warn_pch_gnu_extensions);
1081 PARSE_LANGOPT_BENIGN(ImplicitInt);
1082 PARSE_LANGOPT_BENIGN(Digraphs);
1083 PARSE_LANGOPT_BENIGN(HexFloats);
1084 PARSE_LANGOPT_IMPORTANT(C99, diag::warn_pch_c99);
1085 PARSE_LANGOPT_IMPORTANT(Microsoft, diag::warn_pch_microsoft_extensions);
1086 PARSE_LANGOPT_IMPORTANT(CPlusPlus, diag::warn_pch_cplusplus);
1087 PARSE_LANGOPT_IMPORTANT(CPlusPlus0x, diag::warn_pch_cplusplus0x);
1088 PARSE_LANGOPT_IMPORTANT(NoExtensions, diag::warn_pch_extensions);
1089 PARSE_LANGOPT_BENIGN(CXXOperatorName);
1090 PARSE_LANGOPT_IMPORTANT(ObjC1, diag::warn_pch_objective_c);
1091 PARSE_LANGOPT_IMPORTANT(ObjC2, diag::warn_pch_objective_c2);
1092 PARSE_LANGOPT_IMPORTANT(ObjCNonFragileABI, diag::warn_pch_nonfragile_abi);
1093 PARSE_LANGOPT_BENIGN(PascalStrings);
1094 PARSE_LANGOPT_BENIGN(Boolean);
1095 PARSE_LANGOPT_BENIGN(WritableStrings);
1096 PARSE_LANGOPT_IMPORTANT(LaxVectorConversions,
1097 diag::warn_pch_lax_vector_conversions);
1098 PARSE_LANGOPT_IMPORTANT(Exceptions, diag::warn_pch_exceptions);
1099 PARSE_LANGOPT_IMPORTANT(NeXTRuntime, diag::warn_pch_objc_runtime);
1100 PARSE_LANGOPT_IMPORTANT(Freestanding, diag::warn_pch_freestanding);
1101 PARSE_LANGOPT_IMPORTANT(NoBuiltin, diag::warn_pch_builtins);
1102 PARSE_LANGOPT_IMPORTANT(ThreadsafeStatics,
1103 diag::warn_pch_thread_safe_statics);
1104 PARSE_LANGOPT_IMPORTANT(Blocks, diag::warn_pch_blocks);
1105 PARSE_LANGOPT_BENIGN(EmitAllDecls);
1106 PARSE_LANGOPT_IMPORTANT(MathErrno, diag::warn_pch_math_errno);
1107 PARSE_LANGOPT_IMPORTANT(OverflowChecking, diag::warn_pch_overflow_checking);
1108 PARSE_LANGOPT_IMPORTANT(HeinousExtensions,
1109 diag::warn_pch_heinous_extensions);
1110 // FIXME: Most of the options below are benign if the macro wasn't
1111 // used. Unfortunately, this means that a PCH compiled without
1112 // optimization can't be used with optimization turned on, even
1113 // though the only thing that changes is whether __OPTIMIZE__ was
1114 // defined... but if __OPTIMIZE__ never showed up in the header, it
1115 // doesn't matter. We could consider making this some special kind
1116 // of check.
1117 PARSE_LANGOPT_IMPORTANT(Optimize, diag::warn_pch_optimize);
1118 PARSE_LANGOPT_IMPORTANT(OptimizeSize, diag::warn_pch_optimize_size);
1119 PARSE_LANGOPT_IMPORTANT(Static, diag::warn_pch_static);
1120 PARSE_LANGOPT_IMPORTANT(PICLevel, diag::warn_pch_pic_level);
1121 PARSE_LANGOPT_IMPORTANT(GNUInline, diag::warn_pch_gnu_inline);
1122 PARSE_LANGOPT_IMPORTANT(NoInline, diag::warn_pch_no_inline);
1123 if ((LangOpts.getGCMode() != 0) != (Record[Idx] != 0)) {
1124 Diag(diag::warn_pch_gc_mode)
1125 << (unsigned)Record[Idx] << LangOpts.getGCMode();
1126 Diag(diag::note_ignoring_pch) << FileName;
1127 return true;
1128 }
1129 ++Idx;
1130 PARSE_LANGOPT_BENIGN(getVisibilityMode());
1131 PARSE_LANGOPT_BENIGN(InstantiationDepth);
1132#undef PARSE_LANGOPT_IRRELEVANT
1133#undef PARSE_LANGOPT_BENIGN
1134
1135 return false;
1136}
1137
Douglas Gregor2cf26342009-04-09 22:27:44 +00001138/// \brief Read and return the type at the given offset.
1139///
1140/// This routine actually reads the record corresponding to the type
1141/// at the given offset in the bitstream. It is a helper routine for
1142/// GetType, which deals with reading type IDs.
1143QualType PCHReader::ReadTypeRecord(uint64_t Offset) {
Douglas Gregor0b748912009-04-14 21:18:50 +00001144 // Keep track of where we are in the stream, then jump back there
1145 // after reading this type.
1146 SavedStreamPosition SavedPosition(Stream);
1147
Douglas Gregor2cf26342009-04-09 22:27:44 +00001148 Stream.JumpToBit(Offset);
1149 RecordData Record;
1150 unsigned Code = Stream.ReadCode();
1151 switch ((pch::TypeCode)Stream.ReadRecord(Code, Record)) {
Douglas Gregor6d473962009-04-15 22:00:08 +00001152 case pch::TYPE_EXT_QUAL: {
1153 assert(Record.size() == 3 &&
1154 "Incorrect encoding of extended qualifier type");
1155 QualType Base = GetType(Record[0]);
1156 QualType::GCAttrTypes GCAttr = (QualType::GCAttrTypes)Record[1];
1157 unsigned AddressSpace = Record[2];
1158
1159 QualType T = Base;
1160 if (GCAttr != QualType::GCNone)
1161 T = Context.getObjCGCQualType(T, GCAttr);
1162 if (AddressSpace)
1163 T = Context.getAddrSpaceQualType(T, AddressSpace);
1164 return T;
1165 }
Douglas Gregorb4e715b2009-04-13 20:46:52 +00001166
Douglas Gregor2cf26342009-04-09 22:27:44 +00001167 case pch::TYPE_FIXED_WIDTH_INT: {
1168 assert(Record.size() == 2 && "Incorrect encoding of fixed-width int type");
1169 return Context.getFixedWidthIntType(Record[0], Record[1]);
1170 }
1171
1172 case pch::TYPE_COMPLEX: {
1173 assert(Record.size() == 1 && "Incorrect encoding of complex type");
1174 QualType ElemType = GetType(Record[0]);
1175 return Context.getComplexType(ElemType);
1176 }
1177
1178 case pch::TYPE_POINTER: {
1179 assert(Record.size() == 1 && "Incorrect encoding of pointer type");
1180 QualType PointeeType = GetType(Record[0]);
1181 return Context.getPointerType(PointeeType);
1182 }
1183
1184 case pch::TYPE_BLOCK_POINTER: {
1185 assert(Record.size() == 1 && "Incorrect encoding of block pointer type");
1186 QualType PointeeType = GetType(Record[0]);
1187 return Context.getBlockPointerType(PointeeType);
1188 }
1189
1190 case pch::TYPE_LVALUE_REFERENCE: {
1191 assert(Record.size() == 1 && "Incorrect encoding of lvalue reference type");
1192 QualType PointeeType = GetType(Record[0]);
1193 return Context.getLValueReferenceType(PointeeType);
1194 }
1195
1196 case pch::TYPE_RVALUE_REFERENCE: {
1197 assert(Record.size() == 1 && "Incorrect encoding of rvalue reference type");
1198 QualType PointeeType = GetType(Record[0]);
1199 return Context.getRValueReferenceType(PointeeType);
1200 }
1201
1202 case pch::TYPE_MEMBER_POINTER: {
1203 assert(Record.size() == 1 && "Incorrect encoding of member pointer type");
1204 QualType PointeeType = GetType(Record[0]);
1205 QualType ClassType = GetType(Record[1]);
1206 return Context.getMemberPointerType(PointeeType, ClassType.getTypePtr());
1207 }
1208
Douglas Gregorb4e715b2009-04-13 20:46:52 +00001209 case pch::TYPE_CONSTANT_ARRAY: {
1210 QualType ElementType = GetType(Record[0]);
1211 ArrayType::ArraySizeModifier ASM = (ArrayType::ArraySizeModifier)Record[1];
1212 unsigned IndexTypeQuals = Record[2];
1213 unsigned Idx = 3;
1214 llvm::APInt Size = ReadAPInt(Record, Idx);
1215 return Context.getConstantArrayType(ElementType, Size, ASM, IndexTypeQuals);
1216 }
1217
1218 case pch::TYPE_INCOMPLETE_ARRAY: {
1219 QualType ElementType = GetType(Record[0]);
1220 ArrayType::ArraySizeModifier ASM = (ArrayType::ArraySizeModifier)Record[1];
1221 unsigned IndexTypeQuals = Record[2];
1222 return Context.getIncompleteArrayType(ElementType, ASM, IndexTypeQuals);
1223 }
1224
1225 case pch::TYPE_VARIABLE_ARRAY: {
Douglas Gregor0b748912009-04-14 21:18:50 +00001226 QualType ElementType = GetType(Record[0]);
1227 ArrayType::ArraySizeModifier ASM = (ArrayType::ArraySizeModifier)Record[1];
1228 unsigned IndexTypeQuals = Record[2];
Chris Lattnerda930612009-04-27 05:58:23 +00001229 return Context.getVariableArrayType(ElementType, ReadTypeExpr(),
Douglas Gregor0b748912009-04-14 21:18:50 +00001230 ASM, IndexTypeQuals);
Douglas Gregorb4e715b2009-04-13 20:46:52 +00001231 }
1232
1233 case pch::TYPE_VECTOR: {
1234 if (Record.size() != 2) {
1235 Error("Incorrect encoding of vector type in PCH file");
1236 return QualType();
1237 }
1238
1239 QualType ElementType = GetType(Record[0]);
1240 unsigned NumElements = Record[1];
1241 return Context.getVectorType(ElementType, NumElements);
1242 }
1243
1244 case pch::TYPE_EXT_VECTOR: {
1245 if (Record.size() != 2) {
1246 Error("Incorrect encoding of extended vector type in PCH file");
1247 return QualType();
1248 }
1249
1250 QualType ElementType = GetType(Record[0]);
1251 unsigned NumElements = Record[1];
1252 return Context.getExtVectorType(ElementType, NumElements);
1253 }
1254
1255 case pch::TYPE_FUNCTION_NO_PROTO: {
1256 if (Record.size() != 1) {
1257 Error("Incorrect encoding of no-proto function type");
1258 return QualType();
1259 }
1260 QualType ResultType = GetType(Record[0]);
1261 return Context.getFunctionNoProtoType(ResultType);
1262 }
1263
1264 case pch::TYPE_FUNCTION_PROTO: {
1265 QualType ResultType = GetType(Record[0]);
1266 unsigned Idx = 1;
1267 unsigned NumParams = Record[Idx++];
1268 llvm::SmallVector<QualType, 16> ParamTypes;
1269 for (unsigned I = 0; I != NumParams; ++I)
1270 ParamTypes.push_back(GetType(Record[Idx++]));
1271 bool isVariadic = Record[Idx++];
1272 unsigned Quals = Record[Idx++];
1273 return Context.getFunctionType(ResultType, &ParamTypes[0], NumParams,
1274 isVariadic, Quals);
1275 }
1276
1277 case pch::TYPE_TYPEDEF:
1278 assert(Record.size() == 1 && "Incorrect encoding of typedef type");
1279 return Context.getTypeDeclType(cast<TypedefDecl>(GetDecl(Record[0])));
1280
1281 case pch::TYPE_TYPEOF_EXPR:
Chris Lattnerda930612009-04-27 05:58:23 +00001282 return Context.getTypeOfExprType(ReadTypeExpr());
Douglas Gregorb4e715b2009-04-13 20:46:52 +00001283
1284 case pch::TYPE_TYPEOF: {
1285 if (Record.size() != 1) {
1286 Error("Incorrect encoding of typeof(type) in PCH file");
1287 return QualType();
1288 }
1289 QualType UnderlyingType = GetType(Record[0]);
1290 return Context.getTypeOfType(UnderlyingType);
1291 }
1292
1293 case pch::TYPE_RECORD:
Douglas Gregor8c700062009-04-13 21:20:57 +00001294 assert(Record.size() == 1 && "Incorrect encoding of record type");
1295 return Context.getTypeDeclType(cast<RecordDecl>(GetDecl(Record[0])));
Douglas Gregorb4e715b2009-04-13 20:46:52 +00001296
Douglas Gregor0a2b45e2009-04-13 18:14:40 +00001297 case pch::TYPE_ENUM:
1298 assert(Record.size() == 1 && "Incorrect encoding of enum type");
1299 return Context.getTypeDeclType(cast<EnumDecl>(GetDecl(Record[0])));
1300
Douglas Gregorb4e715b2009-04-13 20:46:52 +00001301 case pch::TYPE_OBJC_INTERFACE:
Chris Lattner4dcf151a2009-04-22 05:57:30 +00001302 assert(Record.size() == 1 && "Incorrect encoding of objc interface type");
1303 return Context.getObjCInterfaceType(
1304 cast<ObjCInterfaceDecl>(GetDecl(Record[0])));
Douglas Gregorb4e715b2009-04-13 20:46:52 +00001305
Chris Lattnerc6fa4452009-04-22 06:45:28 +00001306 case pch::TYPE_OBJC_QUALIFIED_INTERFACE: {
1307 unsigned Idx = 0;
1308 ObjCInterfaceDecl *ItfD = cast<ObjCInterfaceDecl>(GetDecl(Record[Idx++]));
1309 unsigned NumProtos = Record[Idx++];
1310 llvm::SmallVector<ObjCProtocolDecl*, 4> Protos;
1311 for (unsigned I = 0; I != NumProtos; ++I)
1312 Protos.push_back(cast<ObjCProtocolDecl>(GetDecl(Record[Idx++])));
1313 return Context.getObjCQualifiedInterfaceType(ItfD, &Protos[0], NumProtos);
1314 }
Douglas Gregorb4e715b2009-04-13 20:46:52 +00001315
Chris Lattnerd7a3fcd2009-04-22 06:40:03 +00001316 case pch::TYPE_OBJC_QUALIFIED_ID: {
1317 unsigned Idx = 0;
1318 unsigned NumProtos = Record[Idx++];
1319 llvm::SmallVector<ObjCProtocolDecl*, 4> Protos;
1320 for (unsigned I = 0; I != NumProtos; ++I)
1321 Protos.push_back(cast<ObjCProtocolDecl>(GetDecl(Record[Idx++])));
1322 return Context.getObjCQualifiedIdType(&Protos[0], NumProtos);
1323 }
Douglas Gregor2cf26342009-04-09 22:27:44 +00001324 }
Douglas Gregor2cf26342009-04-09 22:27:44 +00001325 // Suppress a GCC warning
1326 return QualType();
1327}
1328
Douglas Gregor2cf26342009-04-09 22:27:44 +00001329
Douglas Gregor8038d512009-04-10 17:25:41 +00001330QualType PCHReader::GetType(pch::TypeID ID) {
Douglas Gregor2cf26342009-04-09 22:27:44 +00001331 unsigned Quals = ID & 0x07;
1332 unsigned Index = ID >> 3;
1333
1334 if (Index < pch::NUM_PREDEF_TYPE_IDS) {
1335 QualType T;
1336 switch ((pch::PredefinedTypeIDs)Index) {
1337 case pch::PREDEF_TYPE_NULL_ID: return QualType();
1338 case pch::PREDEF_TYPE_VOID_ID: T = Context.VoidTy; break;
1339 case pch::PREDEF_TYPE_BOOL_ID: T = Context.BoolTy; break;
1340
1341 case pch::PREDEF_TYPE_CHAR_U_ID:
1342 case pch::PREDEF_TYPE_CHAR_S_ID:
1343 // FIXME: Check that the signedness of CharTy is correct!
1344 T = Context.CharTy;
1345 break;
1346
1347 case pch::PREDEF_TYPE_UCHAR_ID: T = Context.UnsignedCharTy; break;
1348 case pch::PREDEF_TYPE_USHORT_ID: T = Context.UnsignedShortTy; break;
1349 case pch::PREDEF_TYPE_UINT_ID: T = Context.UnsignedIntTy; break;
1350 case pch::PREDEF_TYPE_ULONG_ID: T = Context.UnsignedLongTy; break;
1351 case pch::PREDEF_TYPE_ULONGLONG_ID: T = Context.UnsignedLongLongTy; break;
1352 case pch::PREDEF_TYPE_SCHAR_ID: T = Context.SignedCharTy; break;
1353 case pch::PREDEF_TYPE_WCHAR_ID: T = Context.WCharTy; break;
1354 case pch::PREDEF_TYPE_SHORT_ID: T = Context.ShortTy; break;
1355 case pch::PREDEF_TYPE_INT_ID: T = Context.IntTy; break;
1356 case pch::PREDEF_TYPE_LONG_ID: T = Context.LongTy; break;
1357 case pch::PREDEF_TYPE_LONGLONG_ID: T = Context.LongLongTy; break;
1358 case pch::PREDEF_TYPE_FLOAT_ID: T = Context.FloatTy; break;
1359 case pch::PREDEF_TYPE_DOUBLE_ID: T = Context.DoubleTy; break;
1360 case pch::PREDEF_TYPE_LONGDOUBLE_ID: T = Context.LongDoubleTy; break;
1361 case pch::PREDEF_TYPE_OVERLOAD_ID: T = Context.OverloadTy; break;
1362 case pch::PREDEF_TYPE_DEPENDENT_ID: T = Context.DependentTy; break;
1363 }
1364
1365 assert(!T.isNull() && "Unknown predefined type");
1366 return T.getQualifiedType(Quals);
1367 }
1368
1369 Index -= pch::NUM_PREDEF_TYPE_IDS;
Douglas Gregor366809a2009-04-26 03:49:13 +00001370 assert(Index < TypesLoaded.size() && "Type index out-of-range");
Douglas Gregor8f5dc7f2009-04-25 18:35:21 +00001371 if (!TypesLoaded[Index])
1372 TypesLoaded[Index] = ReadTypeRecord(TypeOffsets[Index]).getTypePtr();
Douglas Gregor2cf26342009-04-09 22:27:44 +00001373
Douglas Gregor8f5dc7f2009-04-25 18:35:21 +00001374 return QualType(TypesLoaded[Index], Quals);
Douglas Gregor2cf26342009-04-09 22:27:44 +00001375}
1376
Douglas Gregor8038d512009-04-10 17:25:41 +00001377Decl *PCHReader::GetDecl(pch::DeclID ID) {
Douglas Gregor2cf26342009-04-09 22:27:44 +00001378 if (ID == 0)
1379 return 0;
1380
Douglas Gregor8f5dc7f2009-04-25 18:35:21 +00001381 if (ID > DeclsLoaded.size()) {
1382 Error("Declaration ID out-of-range for PCH file");
1383 return 0;
1384 }
Douglas Gregor2cf26342009-04-09 22:27:44 +00001385
Douglas Gregor8f5dc7f2009-04-25 18:35:21 +00001386 unsigned Index = ID - 1;
1387 if (!DeclsLoaded[Index])
1388 ReadDeclRecord(DeclOffsets[Index], Index);
1389
1390 return DeclsLoaded[Index];
Douglas Gregor2cf26342009-04-09 22:27:44 +00001391}
1392
Chris Lattner887e2b32009-04-27 05:46:25 +00001393/// \brief Resolve the offset of a statement into a statement.
1394///
1395/// This operation will read a new statement from the external
1396/// source each time it is called, and is meant to be used via a
1397/// LazyOffsetPtr (which is used by Decls for the body of functions, etc).
1398Stmt *PCHReader::GetDeclStmt(uint64_t Offset) {
Chris Lattnerda930612009-04-27 05:58:23 +00001399 // Since we know tha this statement is part of a decl, make sure to use the
1400 // decl cursor to read it.
1401 DeclsCursor.JumpToBit(Offset);
1402 return ReadStmt(DeclsCursor);
Douglas Gregor250fc9c2009-04-18 00:07:54 +00001403}
1404
Douglas Gregor2cf26342009-04-09 22:27:44 +00001405bool PCHReader::ReadDeclsLexicallyInContext(DeclContext *DC,
Douglas Gregor8038d512009-04-10 17:25:41 +00001406 llvm::SmallVectorImpl<pch::DeclID> &Decls) {
Douglas Gregor2cf26342009-04-09 22:27:44 +00001407 assert(DC->hasExternalLexicalStorage() &&
1408 "DeclContext has no lexical decls in storage");
1409 uint64_t Offset = DeclContextOffsets[DC].first;
1410 assert(Offset && "DeclContext has no lexical decls in storage");
1411
Douglas Gregor0b748912009-04-14 21:18:50 +00001412 // Keep track of where we are in the stream, then jump back there
1413 // after reading this context.
1414 SavedStreamPosition SavedPosition(Stream);
1415
Douglas Gregor2cf26342009-04-09 22:27:44 +00001416 // Load the record containing all of the declarations lexically in
1417 // this context.
1418 Stream.JumpToBit(Offset);
1419 RecordData Record;
1420 unsigned Code = Stream.ReadCode();
1421 unsigned RecCode = Stream.ReadRecord(Code, Record);
Douglas Gregor6a2bfb22009-04-15 18:43:11 +00001422 (void)RecCode;
Douglas Gregor2cf26342009-04-09 22:27:44 +00001423 assert(RecCode == pch::DECL_CONTEXT_LEXICAL && "Expected lexical block");
1424
1425 // Load all of the declaration IDs
1426 Decls.clear();
1427 Decls.insert(Decls.end(), Record.begin(), Record.end());
Douglas Gregor25123082009-04-22 22:34:57 +00001428 ++NumLexicalDeclContextsRead;
Douglas Gregor2cf26342009-04-09 22:27:44 +00001429 return false;
1430}
1431
1432bool PCHReader::ReadDeclsVisibleInContext(DeclContext *DC,
1433 llvm::SmallVectorImpl<VisibleDeclaration> & Decls) {
1434 assert(DC->hasExternalVisibleStorage() &&
1435 "DeclContext has no visible decls in storage");
1436 uint64_t Offset = DeclContextOffsets[DC].second;
1437 assert(Offset && "DeclContext has no visible decls in storage");
1438
Douglas Gregor0b748912009-04-14 21:18:50 +00001439 // Keep track of where we are in the stream, then jump back there
1440 // after reading this context.
1441 SavedStreamPosition SavedPosition(Stream);
1442
Douglas Gregor2cf26342009-04-09 22:27:44 +00001443 // Load the record containing all of the declarations visible in
1444 // this context.
1445 Stream.JumpToBit(Offset);
1446 RecordData Record;
1447 unsigned Code = Stream.ReadCode();
1448 unsigned RecCode = Stream.ReadRecord(Code, Record);
Douglas Gregor6a2bfb22009-04-15 18:43:11 +00001449 (void)RecCode;
Douglas Gregor2cf26342009-04-09 22:27:44 +00001450 assert(RecCode == pch::DECL_CONTEXT_VISIBLE && "Expected visible block");
1451 if (Record.size() == 0)
1452 return false;
1453
1454 Decls.clear();
1455
1456 unsigned Idx = 0;
Douglas Gregor2cf26342009-04-09 22:27:44 +00001457 while (Idx < Record.size()) {
1458 Decls.push_back(VisibleDeclaration());
1459 Decls.back().Name = ReadDeclarationName(Record, Idx);
1460
Douglas Gregor2cf26342009-04-09 22:27:44 +00001461 unsigned Size = Record[Idx++];
1462 llvm::SmallVector<unsigned, 4> & LoadedDecls
1463 = Decls.back().Declarations;
1464 LoadedDecls.reserve(Size);
1465 for (unsigned I = 0; I < Size; ++I)
1466 LoadedDecls.push_back(Record[Idx++]);
1467 }
1468
Douglas Gregor25123082009-04-22 22:34:57 +00001469 ++NumVisibleDeclContextsRead;
Douglas Gregor2cf26342009-04-09 22:27:44 +00001470 return false;
1471}
1472
Douglas Gregorfdd01722009-04-14 00:24:19 +00001473void PCHReader::StartTranslationUnit(ASTConsumer *Consumer) {
Douglas Gregor0af2ca42009-04-22 19:09:20 +00001474 this->Consumer = Consumer;
1475
Douglas Gregorfdd01722009-04-14 00:24:19 +00001476 if (!Consumer)
1477 return;
1478
1479 for (unsigned I = 0, N = ExternalDefinitions.size(); I != N; ++I) {
1480 Decl *D = GetDecl(ExternalDefinitions[I]);
1481 DeclGroupRef DG(D);
1482 Consumer->HandleTopLevelDecl(DG);
1483 }
Douglas Gregorc62a2fe2009-04-25 00:41:30 +00001484
1485 for (unsigned I = 0, N = InterestingDecls.size(); I != N; ++I) {
1486 DeclGroupRef DG(InterestingDecls[I]);
1487 Consumer->HandleTopLevelDecl(DG);
1488 }
Douglas Gregorfdd01722009-04-14 00:24:19 +00001489}
1490
Douglas Gregor2cf26342009-04-09 22:27:44 +00001491void PCHReader::PrintStats() {
1492 std::fprintf(stderr, "*** PCH Statistics:\n");
1493
Douglas Gregor2b3a5a82009-04-25 19:10:14 +00001494 unsigned NumTypesLoaded
1495 = TypesLoaded.size() - std::count(TypesLoaded.begin(), TypesLoaded.end(),
1496 (Type *)0);
1497 unsigned NumDeclsLoaded
1498 = DeclsLoaded.size() - std::count(DeclsLoaded.begin(), DeclsLoaded.end(),
1499 (Decl *)0);
1500 unsigned NumIdentifiersLoaded
1501 = IdentifiersLoaded.size() - std::count(IdentifiersLoaded.begin(),
1502 IdentifiersLoaded.end(),
1503 (IdentifierInfo *)0);
1504 unsigned NumSelectorsLoaded
1505 = SelectorsLoaded.size() - std::count(SelectorsLoaded.begin(),
1506 SelectorsLoaded.end(),
1507 Selector());
Douglas Gregor2d41cc12009-04-13 20:50:16 +00001508
Douglas Gregor7f94b0b2009-04-27 06:38:32 +00001509 if (TotalNumSLocEntries)
1510 std::fprintf(stderr, " %u/%u source location entries read (%f%%)\n",
1511 NumSLocEntriesRead, TotalNumSLocEntries,
1512 ((float)NumSLocEntriesRead/TotalNumSLocEntries * 100));
Douglas Gregor8f5dc7f2009-04-25 18:35:21 +00001513 if (!TypesLoaded.empty())
Douglas Gregor83941df2009-04-25 17:48:32 +00001514 std::fprintf(stderr, " %u/%u types read (%f%%)\n",
Douglas Gregor8f5dc7f2009-04-25 18:35:21 +00001515 NumTypesLoaded, (unsigned)TypesLoaded.size(),
1516 ((float)NumTypesLoaded/TypesLoaded.size() * 100));
1517 if (!DeclsLoaded.empty())
Douglas Gregor83941df2009-04-25 17:48:32 +00001518 std::fprintf(stderr, " %u/%u declarations read (%f%%)\n",
Douglas Gregor8f5dc7f2009-04-25 18:35:21 +00001519 NumDeclsLoaded, (unsigned)DeclsLoaded.size(),
1520 ((float)NumDeclsLoaded/DeclsLoaded.size() * 100));
Douglas Gregor2b3a5a82009-04-25 19:10:14 +00001521 if (!IdentifiersLoaded.empty())
Douglas Gregor83941df2009-04-25 17:48:32 +00001522 std::fprintf(stderr, " %u/%u identifiers read (%f%%)\n",
Douglas Gregor2b3a5a82009-04-25 19:10:14 +00001523 NumIdentifiersLoaded, (unsigned)IdentifiersLoaded.size(),
1524 ((float)NumIdentifiersLoaded/IdentifiersLoaded.size() * 100));
Douglas Gregor83941df2009-04-25 17:48:32 +00001525 if (TotalNumSelectors)
1526 std::fprintf(stderr, " %u/%u selectors read (%f%%)\n",
1527 NumSelectorsLoaded, TotalNumSelectors,
1528 ((float)NumSelectorsLoaded/TotalNumSelectors * 100));
1529 if (TotalNumStatements)
1530 std::fprintf(stderr, " %u/%u statements read (%f%%)\n",
1531 NumStatementsRead, TotalNumStatements,
1532 ((float)NumStatementsRead/TotalNumStatements * 100));
1533 if (TotalNumMacros)
1534 std::fprintf(stderr, " %u/%u macros read (%f%%)\n",
1535 NumMacrosRead, TotalNumMacros,
1536 ((float)NumMacrosRead/TotalNumMacros * 100));
1537 if (TotalLexicalDeclContexts)
1538 std::fprintf(stderr, " %u/%u lexical declcontexts read (%f%%)\n",
1539 NumLexicalDeclContextsRead, TotalLexicalDeclContexts,
1540 ((float)NumLexicalDeclContextsRead/TotalLexicalDeclContexts
1541 * 100));
1542 if (TotalVisibleDeclContexts)
1543 std::fprintf(stderr, " %u/%u visible declcontexts read (%f%%)\n",
1544 NumVisibleDeclContextsRead, TotalVisibleDeclContexts,
1545 ((float)NumVisibleDeclContextsRead/TotalVisibleDeclContexts
1546 * 100));
1547 if (TotalSelectorsInMethodPool) {
1548 std::fprintf(stderr, " %u/%u method pool entries read (%f%%)\n",
1549 NumMethodPoolSelectorsRead, TotalSelectorsInMethodPool,
1550 ((float)NumMethodPoolSelectorsRead/TotalSelectorsInMethodPool
1551 * 100));
1552 std::fprintf(stderr, " %u method pool misses\n", NumMethodPoolMisses);
1553 }
Douglas Gregor2cf26342009-04-09 22:27:44 +00001554 std::fprintf(stderr, "\n");
1555}
1556
Douglas Gregor668c1a42009-04-21 22:25:48 +00001557void PCHReader::InitializeSema(Sema &S) {
1558 SemaObj = &S;
Douglas Gregorf0aaf7a2009-04-24 21:10:55 +00001559 S.ExternalSource = this;
1560
Douglas Gregor6cfc1a82009-04-22 21:15:06 +00001561 // Makes sure any declarations that were deserialized "too early"
1562 // still get added to the identifier's declaration chains.
1563 for (unsigned I = 0, N = PreloadedDecls.size(); I != N; ++I) {
1564 SemaObj->TUScope->AddDecl(Action::DeclPtrTy::make(PreloadedDecls[I]));
1565 SemaObj->IdResolver.AddDecl(PreloadedDecls[I]);
Douglas Gregor668c1a42009-04-21 22:25:48 +00001566 }
Douglas Gregor6cfc1a82009-04-22 21:15:06 +00001567 PreloadedDecls.clear();
Douglas Gregor4c0e86b2009-04-22 22:02:47 +00001568
1569 // If there were any tentative definitions, deserialize them and add
1570 // them to Sema's table of tentative definitions.
1571 for (unsigned I = 0, N = TentativeDefinitions.size(); I != N; ++I) {
1572 VarDecl *Var = cast<VarDecl>(GetDecl(TentativeDefinitions[I]));
1573 SemaObj->TentativeDefinitions[Var->getDeclName()] = Var;
1574 }
Douglas Gregor14c22f22009-04-22 22:18:58 +00001575
1576 // If there were any locally-scoped external declarations,
1577 // deserialize them and add them to Sema's table of locally-scoped
1578 // external declarations.
1579 for (unsigned I = 0, N = LocallyScopedExternalDecls.size(); I != N; ++I) {
1580 NamedDecl *D = cast<NamedDecl>(GetDecl(LocallyScopedExternalDecls[I]));
1581 SemaObj->LocallyScopedExternalDecls[D->getDeclName()] = D;
1582 }
Douglas Gregor668c1a42009-04-21 22:25:48 +00001583}
1584
1585IdentifierInfo* PCHReader::get(const char *NameStart, const char *NameEnd) {
1586 // Try to find this name within our on-disk hash table
1587 PCHIdentifierLookupTable *IdTable
1588 = (PCHIdentifierLookupTable *)IdentifierLookupTable;
1589 std::pair<const char*, unsigned> Key(NameStart, NameEnd - NameStart);
1590 PCHIdentifierLookupTable::iterator Pos = IdTable->find(Key);
1591 if (Pos == IdTable->end())
1592 return 0;
1593
1594 // Dereferencing the iterator has the effect of building the
1595 // IdentifierInfo node and populating it with the various
1596 // declarations it needs.
1597 return *Pos;
1598}
1599
Douglas Gregorf0aaf7a2009-04-24 21:10:55 +00001600std::pair<ObjCMethodList, ObjCMethodList>
1601PCHReader::ReadMethodPool(Selector Sel) {
1602 if (!MethodPoolLookupTable)
1603 return std::pair<ObjCMethodList, ObjCMethodList>();
1604
1605 // Try to find this selector within our on-disk hash table.
1606 PCHMethodPoolLookupTable *PoolTable
1607 = (PCHMethodPoolLookupTable*)MethodPoolLookupTable;
1608 PCHMethodPoolLookupTable::iterator Pos = PoolTable->find(Sel);
Douglas Gregor83941df2009-04-25 17:48:32 +00001609 if (Pos == PoolTable->end()) {
1610 ++NumMethodPoolMisses;
Douglas Gregorf0aaf7a2009-04-24 21:10:55 +00001611 return std::pair<ObjCMethodList, ObjCMethodList>();;
Douglas Gregor83941df2009-04-25 17:48:32 +00001612 }
Douglas Gregorf0aaf7a2009-04-24 21:10:55 +00001613
Douglas Gregor83941df2009-04-25 17:48:32 +00001614 ++NumMethodPoolSelectorsRead;
Douglas Gregorf0aaf7a2009-04-24 21:10:55 +00001615 return *Pos;
1616}
1617
Douglas Gregor2b3a5a82009-04-25 19:10:14 +00001618void PCHReader::SetIdentifierInfo(unsigned ID, IdentifierInfo *II) {
Douglas Gregor668c1a42009-04-21 22:25:48 +00001619 assert(ID && "Non-zero identifier ID required");
Douglas Gregor2b3a5a82009-04-25 19:10:14 +00001620 assert(ID <= IdentifiersLoaded.size() && "Identifier ID out of range");
1621 IdentifiersLoaded[ID - 1] = II;
Douglas Gregor668c1a42009-04-21 22:25:48 +00001622}
1623
Chris Lattner7356a312009-04-11 21:15:38 +00001624IdentifierInfo *PCHReader::DecodeIdentifierInfo(unsigned ID) {
Douglas Gregorafaf3082009-04-11 00:14:32 +00001625 if (ID == 0)
1626 return 0;
Chris Lattner7356a312009-04-11 21:15:38 +00001627
Douglas Gregor2b3a5a82009-04-25 19:10:14 +00001628 if (!IdentifierTableData || IdentifiersLoaded.empty()) {
Douglas Gregorafaf3082009-04-11 00:14:32 +00001629 Error("No identifier table in PCH file");
1630 return 0;
1631 }
Chris Lattner7356a312009-04-11 21:15:38 +00001632
Douglas Gregor2b3a5a82009-04-25 19:10:14 +00001633 if (!IdentifiersLoaded[ID - 1]) {
1634 uint32_t Offset = IdentifierOffsets[ID - 1];
Douglas Gregor17e1c5e2009-04-25 21:21:38 +00001635 const char *Str = IdentifierTableData + Offset;
Douglas Gregord6595a42009-04-25 21:04:17 +00001636
1637 // If there is an identifier lookup table, but the offset of this
1638 // string is after the identifier table itself, then we know that
1639 // this string is not in the on-disk hash table. Therefore,
1640 // disable lookup into the hash table when looking for this
1641 // identifier.
1642 PCHIdentifierLookupTable *IdTable
1643 = (PCHIdentifierLookupTable *)IdentifierLookupTable;
Douglas Gregor17e1c5e2009-04-25 21:21:38 +00001644 if (!IdTable ||
1645 Offset >= uint32_t(IdTable->getBuckets() - IdTable->getBase())) {
1646 // Turn off lookup into the on-disk hash table. We know that
1647 // this identifier is not there.
1648 if (IdTable)
1649 PP.getIdentifierTable().setExternalIdentifierLookup(0);
Douglas Gregord6595a42009-04-25 21:04:17 +00001650
Douglas Gregor17e1c5e2009-04-25 21:21:38 +00001651 // All of the strings in the PCH file are preceded by a 16-bit
1652 // length. Extract that 16-bit length to avoid having to execute
1653 // strlen().
1654 const char *StrLenPtr = Str - 2;
1655 unsigned StrLen = (((unsigned) StrLenPtr[0])
1656 | (((unsigned) StrLenPtr[1]) << 8)) - 1;
1657 IdentifiersLoaded[ID - 1] = &Context.Idents.get(Str, Str + StrLen);
Douglas Gregord6595a42009-04-25 21:04:17 +00001658
Douglas Gregor17e1c5e2009-04-25 21:21:38 +00001659 // Turn on lookup into the on-disk hash table, if we have an
1660 // on-disk hash table.
1661 if (IdTable)
1662 PP.getIdentifierTable().setExternalIdentifierLookup(this);
1663 } else {
1664 // The identifier is a key in our on-disk hash table. Since we
1665 // know where the hash table entry starts, just read in this
1666 // (key, value) pair.
1667 PCHIdentifierLookupTrait Trait(const_cast<PCHReader &>(*this));
1668 const unsigned char *Pos = (const unsigned char *)Str - 4;
1669 std::pair<unsigned, unsigned> KeyDataLengths
1670 = Trait.ReadKeyDataLength(Pos);
Douglas Gregord6595a42009-04-25 21:04:17 +00001671
Douglas Gregor17e1c5e2009-04-25 21:21:38 +00001672 PCHIdentifierLookupTrait::internal_key_type InternalKey
1673 = Trait.ReadKey(Pos, KeyDataLengths.first);
1674 Pos = (const unsigned char *)Str + KeyDataLengths.first;
1675 IdentifiersLoaded[ID - 1] = Trait.ReadData(InternalKey, Pos,
1676 KeyDataLengths.second);
1677 }
Douglas Gregorafaf3082009-04-11 00:14:32 +00001678 }
Chris Lattner7356a312009-04-11 21:15:38 +00001679
Douglas Gregor2b3a5a82009-04-25 19:10:14 +00001680 return IdentifiersLoaded[ID - 1];
Douglas Gregor2cf26342009-04-09 22:27:44 +00001681}
1682
Douglas Gregor7f94b0b2009-04-27 06:38:32 +00001683void PCHReader::ReadSLocEntry(unsigned ID) {
1684 ReadSLocEntryRecord(ID);
1685}
1686
Steve Naroff90cd1bb2009-04-23 10:39:46 +00001687Selector PCHReader::DecodeSelector(unsigned ID) {
1688 if (ID == 0)
1689 return Selector();
1690
Douglas Gregor83941df2009-04-25 17:48:32 +00001691 if (!MethodPoolLookupTableData) {
Steve Naroff90cd1bb2009-04-23 10:39:46 +00001692 Error("No selector table in PCH file");
1693 return Selector();
1694 }
Douglas Gregor83941df2009-04-25 17:48:32 +00001695
1696 if (ID > TotalNumSelectors) {
Steve Naroff90cd1bb2009-04-23 10:39:46 +00001697 Error("Selector ID out of range");
1698 return Selector();
1699 }
Douglas Gregor83941df2009-04-25 17:48:32 +00001700
1701 unsigned Index = ID - 1;
1702 if (SelectorsLoaded[Index].getAsOpaquePtr() == 0) {
1703 // Load this selector from the selector table.
1704 // FIXME: endianness portability issues with SelectorOffsets table
1705 PCHMethodPoolLookupTrait Trait(*this);
1706 SelectorsLoaded[Index]
1707 = Trait.ReadKey(MethodPoolLookupTableData + SelectorOffsets[Index], 0);
1708 }
1709
1710 return SelectorsLoaded[Index];
Steve Naroff90cd1bb2009-04-23 10:39:46 +00001711}
1712
Douglas Gregor2cf26342009-04-09 22:27:44 +00001713DeclarationName
1714PCHReader::ReadDeclarationName(const RecordData &Record, unsigned &Idx) {
1715 DeclarationName::NameKind Kind = (DeclarationName::NameKind)Record[Idx++];
1716 switch (Kind) {
1717 case DeclarationName::Identifier:
1718 return DeclarationName(GetIdentifierInfo(Record, Idx));
1719
1720 case DeclarationName::ObjCZeroArgSelector:
1721 case DeclarationName::ObjCOneArgSelector:
1722 case DeclarationName::ObjCMultiArgSelector:
Steve Naroffa7503a72009-04-23 15:15:40 +00001723 return DeclarationName(GetSelector(Record, Idx));
Douglas Gregor2cf26342009-04-09 22:27:44 +00001724
1725 case DeclarationName::CXXConstructorName:
1726 return Context.DeclarationNames.getCXXConstructorName(
1727 GetType(Record[Idx++]));
1728
1729 case DeclarationName::CXXDestructorName:
1730 return Context.DeclarationNames.getCXXDestructorName(
1731 GetType(Record[Idx++]));
1732
1733 case DeclarationName::CXXConversionFunctionName:
1734 return Context.DeclarationNames.getCXXConversionFunctionName(
1735 GetType(Record[Idx++]));
1736
1737 case DeclarationName::CXXOperatorName:
1738 return Context.DeclarationNames.getCXXOperatorName(
1739 (OverloadedOperatorKind)Record[Idx++]);
1740
1741 case DeclarationName::CXXUsingDirective:
1742 return DeclarationName::getUsingDirectiveName();
1743 }
1744
1745 // Required to silence GCC warning
1746 return DeclarationName();
1747}
Douglas Gregor0a0428e2009-04-10 20:39:37 +00001748
Douglas Gregor0a2b45e2009-04-13 18:14:40 +00001749/// \brief Read an integral value
1750llvm::APInt PCHReader::ReadAPInt(const RecordData &Record, unsigned &Idx) {
1751 unsigned BitWidth = Record[Idx++];
1752 unsigned NumWords = llvm::APInt::getNumWords(BitWidth);
1753 llvm::APInt Result(BitWidth, NumWords, &Record[Idx]);
1754 Idx += NumWords;
1755 return Result;
1756}
1757
1758/// \brief Read a signed integral value
1759llvm::APSInt PCHReader::ReadAPSInt(const RecordData &Record, unsigned &Idx) {
1760 bool isUnsigned = Record[Idx++];
1761 return llvm::APSInt(ReadAPInt(Record, Idx), isUnsigned);
1762}
1763
Douglas Gregor17fc2232009-04-14 21:55:33 +00001764/// \brief Read a floating-point value
1765llvm::APFloat PCHReader::ReadAPFloat(const RecordData &Record, unsigned &Idx) {
Douglas Gregor17fc2232009-04-14 21:55:33 +00001766 return llvm::APFloat(ReadAPInt(Record, Idx));
1767}
1768
Douglas Gregor68a2eb02009-04-15 21:30:51 +00001769// \brief Read a string
1770std::string PCHReader::ReadString(const RecordData &Record, unsigned &Idx) {
1771 unsigned Len = Record[Idx++];
1772 std::string Result(&Record[Idx], &Record[Idx] + Len);
1773 Idx += Len;
1774 return Result;
1775}
1776
Douglas Gregor0a0428e2009-04-10 20:39:37 +00001777DiagnosticBuilder PCHReader::Diag(unsigned DiagID) {
Douglas Gregore1d918e2009-04-10 23:10:45 +00001778 return Diag(SourceLocation(), DiagID);
1779}
1780
1781DiagnosticBuilder PCHReader::Diag(SourceLocation Loc, unsigned DiagID) {
1782 return PP.getDiagnostics().Report(FullSourceLoc(Loc,
Douglas Gregor0a0428e2009-04-10 20:39:37 +00001783 Context.getSourceManager()),
1784 DiagID);
1785}
Douglas Gregor025452f2009-04-17 00:04:06 +00001786
Douglas Gregor668c1a42009-04-21 22:25:48 +00001787/// \brief Retrieve the identifier table associated with the
1788/// preprocessor.
1789IdentifierTable &PCHReader::getIdentifierTable() {
1790 return PP.getIdentifierTable();
1791}
1792
Douglas Gregor025452f2009-04-17 00:04:06 +00001793/// \brief Record that the given ID maps to the given switch-case
1794/// statement.
1795void PCHReader::RecordSwitchCaseID(SwitchCase *SC, unsigned ID) {
1796 assert(SwitchCaseStmts[ID] == 0 && "Already have a SwitchCase with this ID");
1797 SwitchCaseStmts[ID] = SC;
1798}
1799
1800/// \brief Retrieve the switch-case statement with the given ID.
1801SwitchCase *PCHReader::getSwitchCaseWithID(unsigned ID) {
1802 assert(SwitchCaseStmts[ID] != 0 && "No SwitchCase with this ID");
1803 return SwitchCaseStmts[ID];
1804}
Douglas Gregor1de05fe2009-04-17 18:18:49 +00001805
1806/// \brief Record that the given label statement has been
1807/// deserialized and has the given ID.
1808void PCHReader::RecordLabelStmt(LabelStmt *S, unsigned ID) {
1809 assert(LabelStmts.find(ID) == LabelStmts.end() &&
1810 "Deserialized label twice");
1811 LabelStmts[ID] = S;
1812
1813 // If we've already seen any goto statements that point to this
1814 // label, resolve them now.
1815 typedef std::multimap<unsigned, GotoStmt *>::iterator GotoIter;
1816 std::pair<GotoIter, GotoIter> Gotos = UnresolvedGotoStmts.equal_range(ID);
1817 for (GotoIter Goto = Gotos.first; Goto != Gotos.second; ++Goto)
1818 Goto->second->setLabel(S);
1819 UnresolvedGotoStmts.erase(Gotos.first, Gotos.second);
Douglas Gregor7d5c2f22009-04-17 18:58:21 +00001820
1821 // If we've already seen any address-label statements that point to
1822 // this label, resolve them now.
1823 typedef std::multimap<unsigned, AddrLabelExpr *>::iterator AddrLabelIter;
1824 std::pair<AddrLabelIter, AddrLabelIter> AddrLabels
1825 = UnresolvedAddrLabelExprs.equal_range(ID);
1826 for (AddrLabelIter AddrLabel = AddrLabels.first;
1827 AddrLabel != AddrLabels.second; ++AddrLabel)
1828 AddrLabel->second->setLabel(S);
1829 UnresolvedAddrLabelExprs.erase(AddrLabels.first, AddrLabels.second);
Douglas Gregor1de05fe2009-04-17 18:18:49 +00001830}
1831
1832/// \brief Set the label of the given statement to the label
1833/// identified by ID.
1834///
1835/// Depending on the order in which the label and other statements
1836/// referencing that label occur, this operation may complete
1837/// immediately (updating the statement) or it may queue the
1838/// statement to be back-patched later.
1839void PCHReader::SetLabelOf(GotoStmt *S, unsigned ID) {
1840 std::map<unsigned, LabelStmt *>::iterator Label = LabelStmts.find(ID);
1841 if (Label != LabelStmts.end()) {
1842 // We've already seen this label, so set the label of the goto and
1843 // we're done.
1844 S->setLabel(Label->second);
1845 } else {
1846 // We haven't seen this label yet, so add this goto to the set of
1847 // unresolved goto statements.
1848 UnresolvedGotoStmts.insert(std::make_pair(ID, S));
1849 }
1850}
Douglas Gregor7d5c2f22009-04-17 18:58:21 +00001851
1852/// \brief Set the label of the given expression to the label
1853/// identified by ID.
1854///
1855/// Depending on the order in which the label and other statements
1856/// referencing that label occur, this operation may complete
1857/// immediately (updating the statement) or it may queue the
1858/// statement to be back-patched later.
1859void PCHReader::SetLabelOf(AddrLabelExpr *S, unsigned ID) {
1860 std::map<unsigned, LabelStmt *>::iterator Label = LabelStmts.find(ID);
1861 if (Label != LabelStmts.end()) {
1862 // We've already seen this label, so set the label of the
1863 // label-address expression and we're done.
1864 S->setLabel(Label->second);
1865 } else {
1866 // We haven't seen this label yet, so add this label-address
1867 // expression to the set of unresolved label-address expressions.
1868 UnresolvedAddrLabelExprs.insert(std::make_pair(ID, S));
1869 }
1870}