blob: a5e29dcdcd416c8f76225ee2188b3b27fe282db7 [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"
Douglas Gregor179cfb12009-04-10 20:39:37 +000014#include "clang/Frontend/FrontendDiagnostic.h"
Douglas Gregorc34897d2009-04-09 22:27:44 +000015#include "clang/AST/ASTContext.h"
16#include "clang/AST/Decl.h"
17#include "clang/AST/Type.h"
Chris Lattnerdb1c81b2009-04-10 21:41:48 +000018#include "clang/Lex/MacroInfo.h"
Douglas Gregorab1cef72009-04-10 03:52:48 +000019#include "clang/Lex/Preprocessor.h"
20#include "clang/Basic/SourceManager.h"
Douglas Gregor635f97f2009-04-13 16:31:14 +000021#include "clang/Basic/SourceManagerInternals.h"
Douglas Gregorab1cef72009-04-10 03:52:48 +000022#include "clang/Basic/FileManager.h"
Douglas Gregorb5887f32009-04-10 21:16:55 +000023#include "clang/Basic/TargetInfo.h"
Douglas Gregorc34897d2009-04-09 22:27:44 +000024#include "llvm/Bitcode/BitstreamReader.h"
25#include "llvm/Support/Compiler.h"
26#include "llvm/Support/MemoryBuffer.h"
27#include <algorithm>
28#include <cstdio>
29
30using namespace clang;
31
32//===----------------------------------------------------------------------===//
33// Declaration deserialization
34//===----------------------------------------------------------------------===//
35namespace {
36 class VISIBILITY_HIDDEN PCHDeclReader {
37 PCHReader &Reader;
38 const PCHReader::RecordData &Record;
39 unsigned &Idx;
40
41 public:
42 PCHDeclReader(PCHReader &Reader, const PCHReader::RecordData &Record,
43 unsigned &Idx)
44 : Reader(Reader), Record(Record), Idx(Idx) { }
45
46 void VisitDecl(Decl *D);
47 void VisitTranslationUnitDecl(TranslationUnitDecl *TU);
48 void VisitNamedDecl(NamedDecl *ND);
49 void VisitTypeDecl(TypeDecl *TD);
50 void VisitTypedefDecl(TypedefDecl *TD);
Douglas Gregor47f1b2c2009-04-13 18:14:40 +000051 void VisitTagDecl(TagDecl *TD);
52 void VisitEnumDecl(EnumDecl *ED);
Douglas Gregor982365e2009-04-13 21:20:57 +000053 void VisitRecordDecl(RecordDecl *RD);
Douglas Gregorc34897d2009-04-09 22:27:44 +000054 void VisitValueDecl(ValueDecl *VD);
Douglas Gregor47f1b2c2009-04-13 18:14:40 +000055 void VisitEnumConstantDecl(EnumConstantDecl *ECD);
Douglas Gregor23ce3a52009-04-13 22:18:37 +000056 void VisitFunctionDecl(FunctionDecl *FD);
Douglas Gregor982365e2009-04-13 21:20:57 +000057 void VisitFieldDecl(FieldDecl *FD);
Douglas Gregorc34897d2009-04-09 22:27:44 +000058 void VisitVarDecl(VarDecl *VD);
Douglas Gregor23ce3a52009-04-13 22:18:37 +000059 void VisitParmVarDecl(ParmVarDecl *PD);
60 void VisitOriginalParmVarDecl(OriginalParmVarDecl *PD);
Douglas Gregorc34897d2009-04-09 22:27:44 +000061
62 std::pair<uint64_t, uint64_t> VisitDeclContext(DeclContext *DC);
63 };
64}
65
66void PCHDeclReader::VisitDecl(Decl *D) {
67 D->setDeclContext(cast_or_null<DeclContext>(Reader.GetDecl(Record[Idx++])));
68 D->setLexicalDeclContext(
69 cast_or_null<DeclContext>(Reader.GetDecl(Record[Idx++])));
70 D->setLocation(SourceLocation::getFromRawEncoding(Record[Idx++]));
71 D->setInvalidDecl(Record[Idx++]);
72 // FIXME: hasAttrs
73 D->setImplicit(Record[Idx++]);
74 D->setAccess((AccessSpecifier)Record[Idx++]);
75}
76
77void PCHDeclReader::VisitTranslationUnitDecl(TranslationUnitDecl *TU) {
78 VisitDecl(TU);
79}
80
81void PCHDeclReader::VisitNamedDecl(NamedDecl *ND) {
82 VisitDecl(ND);
83 ND->setDeclName(Reader.ReadDeclarationName(Record, Idx));
84}
85
86void PCHDeclReader::VisitTypeDecl(TypeDecl *TD) {
87 VisitNamedDecl(TD);
Douglas Gregorc34897d2009-04-09 22:27:44 +000088 TD->setTypeForDecl(Reader.GetType(Record[Idx++]).getTypePtr());
89}
90
91void PCHDeclReader::VisitTypedefDecl(TypedefDecl *TD) {
Douglas Gregor88fd09d2009-04-13 20:46:52 +000092 // Note that we cannot use VisitTypeDecl here, because we need to
93 // set the underlying type of the typedef *before* we try to read
94 // the type associated with the TypedefDecl.
95 VisitNamedDecl(TD);
96 TD->setUnderlyingType(Reader.GetType(Record[Idx + 1]));
97 TD->setTypeForDecl(Reader.GetType(Record[Idx]).getTypePtr());
98 Idx += 2;
Douglas Gregorc34897d2009-04-09 22:27:44 +000099}
100
Douglas Gregor47f1b2c2009-04-13 18:14:40 +0000101void PCHDeclReader::VisitTagDecl(TagDecl *TD) {
102 VisitTypeDecl(TD);
103 TD->setTagKind((TagDecl::TagKind)Record[Idx++]);
104 TD->setDefinition(Record[Idx++]);
105 TD->setTypedefForAnonDecl(
106 cast_or_null<TypedefDecl>(Reader.GetDecl(Record[Idx++])));
107}
108
109void PCHDeclReader::VisitEnumDecl(EnumDecl *ED) {
110 VisitTagDecl(ED);
111 ED->setIntegerType(Reader.GetType(Record[Idx++]));
112}
113
Douglas Gregor982365e2009-04-13 21:20:57 +0000114void PCHDeclReader::VisitRecordDecl(RecordDecl *RD) {
115 VisitTagDecl(RD);
116 RD->setHasFlexibleArrayMember(Record[Idx++]);
117 RD->setAnonymousStructOrUnion(Record[Idx++]);
118}
119
Douglas Gregorc34897d2009-04-09 22:27:44 +0000120void PCHDeclReader::VisitValueDecl(ValueDecl *VD) {
121 VisitNamedDecl(VD);
122 VD->setType(Reader.GetType(Record[Idx++]));
123}
124
Douglas Gregor47f1b2c2009-04-13 18:14:40 +0000125void PCHDeclReader::VisitEnumConstantDecl(EnumConstantDecl *ECD) {
126 VisitValueDecl(ECD);
Douglas Gregor982365e2009-04-13 21:20:57 +0000127 // FIXME: read the initialization expression
Douglas Gregor47f1b2c2009-04-13 18:14:40 +0000128 ECD->setInitVal(Reader.ReadAPSInt(Record, Idx));
129}
130
Douglas Gregor23ce3a52009-04-13 22:18:37 +0000131void PCHDeclReader::VisitFunctionDecl(FunctionDecl *FD) {
132 VisitValueDecl(FD);
133 // FIXME: function body
134 FD->setPreviousDeclaration(
135 cast_or_null<FunctionDecl>(Reader.GetDecl(Record[Idx++])));
136 FD->setStorageClass((FunctionDecl::StorageClass)Record[Idx++]);
137 FD->setInline(Record[Idx++]);
138 FD->setVirtual(Record[Idx++]);
139 FD->setPure(Record[Idx++]);
140 FD->setInheritedPrototype(Record[Idx++]);
141 FD->setHasPrototype(Record[Idx++]);
142 FD->setDeleted(Record[Idx++]);
143 FD->setTypeSpecStartLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
144 unsigned NumParams = Record[Idx++];
145 llvm::SmallVector<ParmVarDecl *, 16> Params;
146 Params.reserve(NumParams);
147 for (unsigned I = 0; I != NumParams; ++I)
148 Params.push_back(cast<ParmVarDecl>(Reader.GetDecl(Record[Idx++])));
149 FD->setParams(Reader.getContext(), &Params[0], NumParams);
150}
151
Douglas Gregor982365e2009-04-13 21:20:57 +0000152void PCHDeclReader::VisitFieldDecl(FieldDecl *FD) {
153 VisitValueDecl(FD);
154 FD->setMutable(Record[Idx++]);
155 // FIXME: Read the bit width.
156}
157
Douglas Gregorc34897d2009-04-09 22:27:44 +0000158void PCHDeclReader::VisitVarDecl(VarDecl *VD) {
159 VisitValueDecl(VD);
160 VD->setStorageClass((VarDecl::StorageClass)Record[Idx++]);
161 VD->setThreadSpecified(Record[Idx++]);
162 VD->setCXXDirectInitializer(Record[Idx++]);
163 VD->setDeclaredInCondition(Record[Idx++]);
164 VD->setPreviousDeclaration(
165 cast_or_null<VarDecl>(Reader.GetDecl(Record[Idx++])));
166 VD->setTypeSpecStartLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
167}
168
Douglas Gregor23ce3a52009-04-13 22:18:37 +0000169void PCHDeclReader::VisitParmVarDecl(ParmVarDecl *PD) {
170 VisitVarDecl(PD);
171 PD->setObjCDeclQualifier((Decl::ObjCDeclQualifier)Record[Idx++]);
172 // FIXME: default argument
173}
174
175void PCHDeclReader::VisitOriginalParmVarDecl(OriginalParmVarDecl *PD) {
176 VisitParmVarDecl(PD);
177 PD->setOriginalType(Reader.GetType(Record[Idx++]));
178}
179
Douglas Gregorc34897d2009-04-09 22:27:44 +0000180std::pair<uint64_t, uint64_t>
181PCHDeclReader::VisitDeclContext(DeclContext *DC) {
182 uint64_t LexicalOffset = Record[Idx++];
183 uint64_t VisibleOffset = 0;
184 if (DC->getPrimaryContext() == DC)
185 VisibleOffset = Record[Idx++];
186 return std::make_pair(LexicalOffset, VisibleOffset);
187}
188
189// FIXME: use the diagnostics machinery
190static bool Error(const char *Str) {
191 std::fprintf(stderr, "%s\n", Str);
192 return true;
193}
194
Douglas Gregorb3a04c82009-04-10 23:10:45 +0000195/// \brief Check the contents of the predefines buffer against the
196/// contents of the predefines buffer used to build the PCH file.
197///
198/// The contents of the two predefines buffers should be the same. If
199/// not, then some command-line option changed the preprocessor state
200/// and we must reject the PCH file.
201///
202/// \param PCHPredef The start of the predefines buffer in the PCH
203/// file.
204///
205/// \param PCHPredefLen The length of the predefines buffer in the PCH
206/// file.
207///
208/// \param PCHBufferID The FileID for the PCH predefines buffer.
209///
210/// \returns true if there was a mismatch (in which case the PCH file
211/// should be ignored), or false otherwise.
212bool PCHReader::CheckPredefinesBuffer(const char *PCHPredef,
213 unsigned PCHPredefLen,
214 FileID PCHBufferID) {
215 const char *Predef = PP.getPredefines().c_str();
216 unsigned PredefLen = PP.getPredefines().size();
217
218 // If the two predefines buffers compare equal, we're done!.
219 if (PredefLen == PCHPredefLen &&
220 strncmp(Predef, PCHPredef, PCHPredefLen) == 0)
221 return false;
222
223 // The predefines buffers are different. Produce a reasonable
224 // diagnostic showing where they are different.
225
226 // The source locations (potentially in the two different predefines
227 // buffers)
228 SourceLocation Loc1, Loc2;
229 SourceManager &SourceMgr = PP.getSourceManager();
230
231 // Create a source buffer for our predefines string, so
232 // that we can build a diagnostic that points into that
233 // source buffer.
234 FileID BufferID;
235 if (Predef && Predef[0]) {
236 llvm::MemoryBuffer *Buffer
237 = llvm::MemoryBuffer::getMemBuffer(Predef, Predef + PredefLen,
238 "<built-in>");
239 BufferID = SourceMgr.createFileIDForMemBuffer(Buffer);
240 }
241
242 unsigned MinLen = std::min(PredefLen, PCHPredefLen);
243 std::pair<const char *, const char *> Locations
244 = std::mismatch(Predef, Predef + MinLen, PCHPredef);
245
246 if (Locations.first != Predef + MinLen) {
247 // We found the location in the two buffers where there is a
248 // difference. Form source locations to point there (in both
249 // buffers).
250 unsigned Offset = Locations.first - Predef;
251 Loc1 = SourceMgr.getLocForStartOfFile(BufferID)
252 .getFileLocWithOffset(Offset);
253 Loc2 = SourceMgr.getLocForStartOfFile(PCHBufferID)
254 .getFileLocWithOffset(Offset);
255 } else if (PredefLen > PCHPredefLen) {
256 Loc1 = SourceMgr.getLocForStartOfFile(BufferID)
257 .getFileLocWithOffset(MinLen);
258 } else {
259 Loc1 = SourceMgr.getLocForStartOfFile(PCHBufferID)
260 .getFileLocWithOffset(MinLen);
261 }
262
263 Diag(Loc1, diag::warn_pch_preprocessor);
264 if (Loc2.isValid())
265 Diag(Loc2, diag::note_predef_in_pch);
266 Diag(diag::note_ignoring_pch) << FileName;
267 return true;
268}
269
Douglas Gregor635f97f2009-04-13 16:31:14 +0000270/// \brief Read the line table in the source manager block.
271/// \returns true if ther was an error.
272static bool ParseLineTable(SourceManager &SourceMgr,
273 llvm::SmallVectorImpl<uint64_t> &Record) {
274 unsigned Idx = 0;
275 LineTableInfo &LineTable = SourceMgr.getLineTable();
276
277 // Parse the file names
Douglas Gregor183ad602009-04-13 17:12:42 +0000278 std::map<int, int> FileIDs;
279 for (int I = 0, N = Record[Idx++]; I != N; ++I) {
Douglas Gregor635f97f2009-04-13 16:31:14 +0000280 // Extract the file name
281 unsigned FilenameLen = Record[Idx++];
282 std::string Filename(&Record[Idx], &Record[Idx] + FilenameLen);
283 Idx += FilenameLen;
Douglas Gregor183ad602009-04-13 17:12:42 +0000284 FileIDs[I] = LineTable.getLineTableFilenameID(Filename.c_str(),
285 Filename.size());
Douglas Gregor635f97f2009-04-13 16:31:14 +0000286 }
287
288 // Parse the line entries
289 std::vector<LineEntry> Entries;
290 while (Idx < Record.size()) {
Douglas Gregor183ad602009-04-13 17:12:42 +0000291 int FID = FileIDs[Record[Idx++]];
Douglas Gregor635f97f2009-04-13 16:31:14 +0000292
293 // Extract the line entries
294 unsigned NumEntries = Record[Idx++];
295 Entries.clear();
296 Entries.reserve(NumEntries);
297 for (unsigned I = 0; I != NumEntries; ++I) {
298 unsigned FileOffset = Record[Idx++];
299 unsigned LineNo = Record[Idx++];
300 int FilenameID = Record[Idx++];
301 SrcMgr::CharacteristicKind FileKind
302 = (SrcMgr::CharacteristicKind)Record[Idx++];
303 unsigned IncludeOffset = Record[Idx++];
304 Entries.push_back(LineEntry::get(FileOffset, LineNo, FilenameID,
305 FileKind, IncludeOffset));
306 }
307 LineTable.AddEntry(FID, Entries);
308 }
309
310 return false;
311}
312
Douglas Gregorab1cef72009-04-10 03:52:48 +0000313/// \brief Read the source manager block
Douglas Gregorb3a04c82009-04-10 23:10:45 +0000314PCHReader::PCHReadResult PCHReader::ReadSourceManagerBlock() {
Douglas Gregorab1cef72009-04-10 03:52:48 +0000315 using namespace SrcMgr;
Douglas Gregorb3a04c82009-04-10 23:10:45 +0000316 if (Stream.EnterSubBlock(pch::SOURCE_MANAGER_BLOCK_ID)) {
317 Error("Malformed source manager block record");
318 return Failure;
319 }
Douglas Gregorab1cef72009-04-10 03:52:48 +0000320
321 SourceManager &SourceMgr = Context.getSourceManager();
322 RecordData Record;
323 while (true) {
324 unsigned Code = Stream.ReadCode();
325 if (Code == llvm::bitc::END_BLOCK) {
Douglas Gregorb3a04c82009-04-10 23:10:45 +0000326 if (Stream.ReadBlockEnd()) {
327 Error("Error at end of Source Manager block");
328 return Failure;
329 }
330
331 return Success;
Douglas Gregorab1cef72009-04-10 03:52:48 +0000332 }
333
334 if (Code == llvm::bitc::ENTER_SUBBLOCK) {
335 // No known subblocks, always skip them.
336 Stream.ReadSubBlockID();
Douglas Gregorb3a04c82009-04-10 23:10:45 +0000337 if (Stream.SkipBlock()) {
338 Error("Malformed block record");
339 return Failure;
340 }
Douglas Gregorab1cef72009-04-10 03:52:48 +0000341 continue;
342 }
343
344 if (Code == llvm::bitc::DEFINE_ABBREV) {
345 Stream.ReadAbbrevRecord();
346 continue;
347 }
348
349 // Read a record.
350 const char *BlobStart;
351 unsigned BlobLen;
352 Record.clear();
353 switch (Stream.ReadRecord(Code, Record, &BlobStart, &BlobLen)) {
354 default: // Default behavior: ignore.
355 break;
356
357 case pch::SM_SLOC_FILE_ENTRY: {
358 // FIXME: We would really like to delay the creation of this
359 // FileEntry until it is actually required, e.g., when producing
360 // a diagnostic with a source location in this file.
361 const FileEntry *File
362 = PP.getFileManager().getFile(BlobStart, BlobStart + BlobLen);
363 // FIXME: Error recovery if file cannot be found.
Douglas Gregor635f97f2009-04-13 16:31:14 +0000364 FileID ID = SourceMgr.createFileID(File,
365 SourceLocation::getFromRawEncoding(Record[1]),
366 (CharacteristicKind)Record[2]);
367 if (Record[3])
368 const_cast<SrcMgr::FileInfo&>(SourceMgr.getSLocEntry(ID).getFile())
369 .setHasLineDirectives();
Douglas Gregorab1cef72009-04-10 03:52:48 +0000370 break;
371 }
372
373 case pch::SM_SLOC_BUFFER_ENTRY: {
374 const char *Name = BlobStart;
375 unsigned Code = Stream.ReadCode();
376 Record.clear();
377 unsigned RecCode = Stream.ReadRecord(Code, Record, &BlobStart, &BlobLen);
378 assert(RecCode == pch::SM_SLOC_BUFFER_BLOB && "Ill-formed PCH file");
Douglas Gregorb3a04c82009-04-10 23:10:45 +0000379 llvm::MemoryBuffer *Buffer
380 = llvm::MemoryBuffer::getMemBuffer(BlobStart,
381 BlobStart + BlobLen - 1,
382 Name);
383 FileID BufferID = SourceMgr.createFileIDForMemBuffer(Buffer);
384
385 if (strcmp(Name, "<built-in>") == 0
386 && CheckPredefinesBuffer(BlobStart, BlobLen - 1, BufferID))
387 return IgnorePCH;
Douglas Gregorab1cef72009-04-10 03:52:48 +0000388 break;
389 }
390
391 case pch::SM_SLOC_INSTANTIATION_ENTRY: {
392 SourceLocation SpellingLoc
393 = SourceLocation::getFromRawEncoding(Record[1]);
394 SourceMgr.createInstantiationLoc(
395 SpellingLoc,
396 SourceLocation::getFromRawEncoding(Record[2]),
397 SourceLocation::getFromRawEncoding(Record[3]),
398 Lexer::MeasureTokenLength(SpellingLoc,
399 SourceMgr));
400 break;
401 }
402
Douglas Gregor635f97f2009-04-13 16:31:14 +0000403 case pch::SM_LINE_TABLE: {
404 if (ParseLineTable(SourceMgr, Record))
405 return Failure;
406 }
Douglas Gregorab1cef72009-04-10 03:52:48 +0000407 }
408 }
409}
410
Chris Lattnerdb1c81b2009-04-10 21:41:48 +0000411bool PCHReader::ReadPreprocessorBlock() {
412 if (Stream.EnterSubBlock(pch::PREPROCESSOR_BLOCK_ID))
413 return Error("Malformed preprocessor block record");
414
Chris Lattnerdb1c81b2009-04-10 21:41:48 +0000415 RecordData Record;
416 llvm::SmallVector<IdentifierInfo*, 16> MacroArgs;
417 MacroInfo *LastMacro = 0;
418
419 while (true) {
420 unsigned Code = Stream.ReadCode();
421 switch (Code) {
422 case llvm::bitc::END_BLOCK:
423 if (Stream.ReadBlockEnd())
424 return Error("Error at end of preprocessor block");
425 return false;
426
427 case llvm::bitc::ENTER_SUBBLOCK:
428 // No known subblocks, always skip them.
429 Stream.ReadSubBlockID();
430 if (Stream.SkipBlock())
431 return Error("Malformed block record");
432 continue;
433
434 case llvm::bitc::DEFINE_ABBREV:
435 Stream.ReadAbbrevRecord();
436 continue;
437 default: break;
438 }
439
440 // Read a record.
441 Record.clear();
442 pch::PreprocessorRecordTypes RecType =
443 (pch::PreprocessorRecordTypes)Stream.ReadRecord(Code, Record);
444 switch (RecType) {
445 default: // Default behavior: ignore unknown records.
446 break;
Chris Lattner4b21c202009-04-13 01:29:17 +0000447 case pch::PP_COUNTER_VALUE:
448 if (!Record.empty())
449 PP.setCounterValue(Record[0]);
450 break;
451
Chris Lattnerdb1c81b2009-04-10 21:41:48 +0000452 case pch::PP_MACRO_OBJECT_LIKE:
453 case pch::PP_MACRO_FUNCTION_LIKE: {
Chris Lattner29241862009-04-11 21:15:38 +0000454 IdentifierInfo *II = DecodeIdentifierInfo(Record[0]);
455 if (II == 0)
456 return Error("Macro must have a name");
Chris Lattnerdb1c81b2009-04-10 21:41:48 +0000457 SourceLocation Loc = SourceLocation::getFromRawEncoding(Record[1]);
458 bool isUsed = Record[2];
459
460 MacroInfo *MI = PP.AllocateMacroInfo(Loc);
461 MI->setIsUsed(isUsed);
462
463 if (RecType == pch::PP_MACRO_FUNCTION_LIKE) {
464 // Decode function-like macro info.
465 bool isC99VarArgs = Record[3];
466 bool isGNUVarArgs = Record[4];
467 MacroArgs.clear();
468 unsigned NumArgs = Record[5];
469 for (unsigned i = 0; i != NumArgs; ++i)
Chris Lattner29241862009-04-11 21:15:38 +0000470 MacroArgs.push_back(DecodeIdentifierInfo(Record[6+i]));
Chris Lattnerdb1c81b2009-04-10 21:41:48 +0000471
472 // Install function-like macro info.
473 MI->setIsFunctionLike();
474 if (isC99VarArgs) MI->setIsC99Varargs();
475 if (isGNUVarArgs) MI->setIsGNUVarargs();
476 MI->setArgumentList(&MacroArgs[0], MacroArgs.size(),
477 PP.getPreprocessorAllocator());
478 }
479
480 // Finally, install the macro.
Chris Lattnerdb1c81b2009-04-10 21:41:48 +0000481 PP.setMacroInfo(II, MI);
Chris Lattnerdb1c81b2009-04-10 21:41:48 +0000482
483 // Remember that we saw this macro last so that we add the tokens that
484 // form its body to it.
485 LastMacro = MI;
486 break;
487 }
488
489 case pch::PP_TOKEN: {
490 // If we see a TOKEN before a PP_MACRO_*, then the file is eroneous, just
491 // pretend we didn't see this.
492 if (LastMacro == 0) break;
493
494 Token Tok;
495 Tok.startToken();
496 Tok.setLocation(SourceLocation::getFromRawEncoding(Record[0]));
497 Tok.setLength(Record[1]);
Chris Lattner29241862009-04-11 21:15:38 +0000498 if (IdentifierInfo *II = DecodeIdentifierInfo(Record[2]))
499 Tok.setIdentifierInfo(II);
Chris Lattnerdb1c81b2009-04-10 21:41:48 +0000500 Tok.setKind((tok::TokenKind)Record[3]);
501 Tok.setFlag((Token::TokenFlags)Record[4]);
502 LastMacro->AddTokenToBody(Tok);
503 break;
504 }
505 }
506 }
507}
508
Douglas Gregor179cfb12009-04-10 20:39:37 +0000509PCHReader::PCHReadResult PCHReader::ReadPCHBlock() {
510 if (Stream.EnterSubBlock(pch::PCH_BLOCK_ID)) {
511 Error("Malformed block record");
512 return Failure;
513 }
Douglas Gregorc34897d2009-04-09 22:27:44 +0000514
Chris Lattner29241862009-04-11 21:15:38 +0000515 uint64_t PreprocessorBlockBit = 0;
516
Douglas Gregorc34897d2009-04-09 22:27:44 +0000517 // Read all of the records and blocks for the PCH file.
Douglas Gregorac8f2802009-04-10 17:25:41 +0000518 RecordData Record;
Douglas Gregorc34897d2009-04-09 22:27:44 +0000519 while (!Stream.AtEndOfStream()) {
520 unsigned Code = Stream.ReadCode();
521 if (Code == llvm::bitc::END_BLOCK) {
Chris Lattner29241862009-04-11 21:15:38 +0000522 // If we saw the preprocessor block, read it now.
523 if (PreprocessorBlockBit) {
524 uint64_t SavedPos = Stream.GetCurrentBitNo();
525 Stream.JumpToBit(PreprocessorBlockBit);
526 if (ReadPreprocessorBlock()) {
527 Error("Malformed preprocessor block");
528 return Failure;
529 }
530 Stream.JumpToBit(SavedPos);
531 }
532
Douglas Gregor179cfb12009-04-10 20:39:37 +0000533 if (Stream.ReadBlockEnd()) {
534 Error("Error at end of module block");
535 return Failure;
536 }
Chris Lattner29241862009-04-11 21:15:38 +0000537
Douglas Gregor179cfb12009-04-10 20:39:37 +0000538 return Success;
Douglas Gregorc34897d2009-04-09 22:27:44 +0000539 }
540
541 if (Code == llvm::bitc::ENTER_SUBBLOCK) {
542 switch (Stream.ReadSubBlockID()) {
543 case pch::DECLS_BLOCK_ID: // Skip decls block (lazily loaded)
544 case pch::TYPES_BLOCK_ID: // Skip types block (lazily loaded)
545 default: // Skip unknown content.
Douglas Gregor179cfb12009-04-10 20:39:37 +0000546 if (Stream.SkipBlock()) {
547 Error("Malformed block record");
548 return Failure;
549 }
Douglas Gregorc34897d2009-04-09 22:27:44 +0000550 break;
551
Chris Lattner29241862009-04-11 21:15:38 +0000552 case pch::PREPROCESSOR_BLOCK_ID:
553 // Skip the preprocessor block for now, but remember where it is. We
554 // want to read it in after the identifier table.
555 if (PreprocessorBlockBit) {
556 Error("Multiple preprocessor blocks found.");
557 return Failure;
558 }
559 PreprocessorBlockBit = Stream.GetCurrentBitNo();
560 if (Stream.SkipBlock()) {
561 Error("Malformed block record");
562 return Failure;
563 }
564 break;
565
Douglas Gregorab1cef72009-04-10 03:52:48 +0000566 case pch::SOURCE_MANAGER_BLOCK_ID:
Douglas Gregorb3a04c82009-04-10 23:10:45 +0000567 switch (ReadSourceManagerBlock()) {
568 case Success:
569 break;
570
571 case Failure:
Douglas Gregor179cfb12009-04-10 20:39:37 +0000572 Error("Malformed source manager block");
573 return Failure;
Douglas Gregorb3a04c82009-04-10 23:10:45 +0000574
575 case IgnorePCH:
576 return IgnorePCH;
Douglas Gregor179cfb12009-04-10 20:39:37 +0000577 }
Douglas Gregorab1cef72009-04-10 03:52:48 +0000578 break;
Douglas Gregorc34897d2009-04-09 22:27:44 +0000579 }
Douglas Gregorac8f2802009-04-10 17:25:41 +0000580 continue;
581 }
582
583 if (Code == llvm::bitc::DEFINE_ABBREV) {
584 Stream.ReadAbbrevRecord();
585 continue;
586 }
587
588 // Read and process a record.
589 Record.clear();
Douglas Gregorb5887f32009-04-10 21:16:55 +0000590 const char *BlobStart = 0;
591 unsigned BlobLen = 0;
592 switch ((pch::PCHRecordTypes)Stream.ReadRecord(Code, Record,
593 &BlobStart, &BlobLen)) {
Douglas Gregorac8f2802009-04-10 17:25:41 +0000594 default: // Default behavior: ignore.
595 break;
596
597 case pch::TYPE_OFFSET:
Douglas Gregor179cfb12009-04-10 20:39:37 +0000598 if (!TypeOffsets.empty()) {
599 Error("Duplicate TYPE_OFFSET record in PCH file");
600 return Failure;
601 }
Douglas Gregorac8f2802009-04-10 17:25:41 +0000602 TypeOffsets.swap(Record);
603 TypeAlreadyLoaded.resize(TypeOffsets.size(), false);
604 break;
605
606 case pch::DECL_OFFSET:
Douglas Gregor179cfb12009-04-10 20:39:37 +0000607 if (!DeclOffsets.empty()) {
608 Error("Duplicate DECL_OFFSET record in PCH file");
609 return Failure;
610 }
Douglas Gregorac8f2802009-04-10 17:25:41 +0000611 DeclOffsets.swap(Record);
612 DeclAlreadyLoaded.resize(DeclOffsets.size(), false);
613 break;
Douglas Gregor179cfb12009-04-10 20:39:37 +0000614
615 case pch::LANGUAGE_OPTIONS:
616 if (ParseLanguageOptions(Record))
617 return IgnorePCH;
618 break;
Douglas Gregorb5887f32009-04-10 21:16:55 +0000619
Douglas Gregor7a224cf2009-04-11 00:14:32 +0000620 case pch::TARGET_TRIPLE: {
Douglas Gregorb5887f32009-04-10 21:16:55 +0000621 std::string TargetTriple(BlobStart, BlobLen);
622 if (TargetTriple != Context.Target.getTargetTriple()) {
623 Diag(diag::warn_pch_target_triple)
624 << TargetTriple << Context.Target.getTargetTriple();
625 Diag(diag::note_ignoring_pch) << FileName;
626 return IgnorePCH;
627 }
628 break;
Douglas Gregorc34897d2009-04-09 22:27:44 +0000629 }
Douglas Gregor7a224cf2009-04-11 00:14:32 +0000630
631 case pch::IDENTIFIER_TABLE:
632 IdentifierTable = BlobStart;
633 break;
634
635 case pch::IDENTIFIER_OFFSET:
636 if (!IdentifierData.empty()) {
637 Error("Duplicate IDENTIFIER_OFFSET record in PCH file");
638 return Failure;
639 }
640 IdentifierData.swap(Record);
641#ifndef NDEBUG
642 for (unsigned I = 0, N = IdentifierData.size(); I != N; ++I) {
643 if ((IdentifierData[I] & 0x01) == 0) {
644 Error("Malformed identifier table in the precompiled header");
645 return Failure;
646 }
647 }
648#endif
649 break;
650 }
Douglas Gregorc34897d2009-04-09 22:27:44 +0000651 }
652
Douglas Gregor179cfb12009-04-10 20:39:37 +0000653 Error("Premature end of bitstream");
654 return Failure;
Douglas Gregorc34897d2009-04-09 22:27:44 +0000655}
656
Douglas Gregorb3a04c82009-04-10 23:10:45 +0000657PCHReader::PCHReadResult PCHReader::ReadPCH(const std::string &FileName) {
Douglas Gregor179cfb12009-04-10 20:39:37 +0000658 // Set the PCH file name.
659 this->FileName = FileName;
660
Douglas Gregorc34897d2009-04-09 22:27:44 +0000661 // Open the PCH file.
662 std::string ErrStr;
663 Buffer.reset(llvm::MemoryBuffer::getFile(FileName.c_str(), &ErrStr));
Douglas Gregorb3a04c82009-04-10 23:10:45 +0000664 if (!Buffer) {
665 Error(ErrStr.c_str());
666 return IgnorePCH;
667 }
Douglas Gregorc34897d2009-04-09 22:27:44 +0000668
669 // Initialize the stream
670 Stream.init((const unsigned char *)Buffer->getBufferStart(),
671 (const unsigned char *)Buffer->getBufferEnd());
672
673 // Sniff for the signature.
674 if (Stream.Read(8) != 'C' ||
675 Stream.Read(8) != 'P' ||
676 Stream.Read(8) != 'C' ||
Douglas Gregorb3a04c82009-04-10 23:10:45 +0000677 Stream.Read(8) != 'H') {
678 Error("Not a PCH file");
679 return IgnorePCH;
680 }
Douglas Gregorc34897d2009-04-09 22:27:44 +0000681
682 // We expect a number of well-defined blocks, though we don't necessarily
683 // need to understand them all.
684 while (!Stream.AtEndOfStream()) {
685 unsigned Code = Stream.ReadCode();
686
Douglas Gregorb3a04c82009-04-10 23:10:45 +0000687 if (Code != llvm::bitc::ENTER_SUBBLOCK) {
688 Error("Invalid record at top-level");
689 return Failure;
690 }
Douglas Gregorc34897d2009-04-09 22:27:44 +0000691
692 unsigned BlockID = Stream.ReadSubBlockID();
693
694 // We only know the PCH subblock ID.
695 switch (BlockID) {
696 case llvm::bitc::BLOCKINFO_BLOCK_ID:
Douglas Gregorb3a04c82009-04-10 23:10:45 +0000697 if (Stream.ReadBlockInfoBlock()) {
698 Error("Malformed BlockInfoBlock");
699 return Failure;
700 }
Douglas Gregorc34897d2009-04-09 22:27:44 +0000701 break;
702 case pch::PCH_BLOCK_ID:
Douglas Gregor179cfb12009-04-10 20:39:37 +0000703 switch (ReadPCHBlock()) {
704 case Success:
705 break;
706
707 case Failure:
Douglas Gregorb3a04c82009-04-10 23:10:45 +0000708 return Failure;
Douglas Gregor179cfb12009-04-10 20:39:37 +0000709
710 case IgnorePCH:
Douglas Gregorb5887f32009-04-10 21:16:55 +0000711 // FIXME: We could consider reading through to the end of this
712 // PCH block, skipping subblocks, to see if there are other
713 // PCH blocks elsewhere.
Douglas Gregorb3a04c82009-04-10 23:10:45 +0000714 return IgnorePCH;
Douglas Gregor179cfb12009-04-10 20:39:37 +0000715 }
Douglas Gregorc34897d2009-04-09 22:27:44 +0000716 break;
717 default:
Douglas Gregorb3a04c82009-04-10 23:10:45 +0000718 if (Stream.SkipBlock()) {
719 Error("Malformed block record");
720 return Failure;
721 }
Douglas Gregorc34897d2009-04-09 22:27:44 +0000722 break;
723 }
724 }
725
726 // Load the translation unit declaration
727 ReadDeclRecord(DeclOffsets[0], 0);
728
Douglas Gregorb3a04c82009-04-10 23:10:45 +0000729 return Success;
Douglas Gregorc34897d2009-04-09 22:27:44 +0000730}
731
Douglas Gregor179cfb12009-04-10 20:39:37 +0000732/// \brief Parse the record that corresponds to a LangOptions data
733/// structure.
734///
735/// This routine compares the language options used to generate the
736/// PCH file against the language options set for the current
737/// compilation. For each option, we classify differences between the
738/// two compiler states as either "benign" or "important". Benign
739/// differences don't matter, and we accept them without complaint
740/// (and without modifying the language options). Differences between
741/// the states for important options cause the PCH file to be
742/// unusable, so we emit a warning and return true to indicate that
743/// there was an error.
744///
745/// \returns true if the PCH file is unacceptable, false otherwise.
746bool PCHReader::ParseLanguageOptions(
747 const llvm::SmallVectorImpl<uint64_t> &Record) {
748 const LangOptions &LangOpts = Context.getLangOptions();
749#define PARSE_LANGOPT_BENIGN(Option) ++Idx
750#define PARSE_LANGOPT_IMPORTANT(Option, DiagID) \
751 if (Record[Idx] != LangOpts.Option) { \
752 Diag(DiagID) << (unsigned)Record[Idx] << LangOpts.Option; \
753 Diag(diag::note_ignoring_pch) << FileName; \
754 return true; \
755 } \
756 ++Idx
757
758 unsigned Idx = 0;
759 PARSE_LANGOPT_BENIGN(Trigraphs);
760 PARSE_LANGOPT_BENIGN(BCPLComment);
761 PARSE_LANGOPT_BENIGN(DollarIdents);
762 PARSE_LANGOPT_BENIGN(AsmPreprocessor);
763 PARSE_LANGOPT_IMPORTANT(GNUMode, diag::warn_pch_gnu_extensions);
764 PARSE_LANGOPT_BENIGN(ImplicitInt);
765 PARSE_LANGOPT_BENIGN(Digraphs);
766 PARSE_LANGOPT_BENIGN(HexFloats);
767 PARSE_LANGOPT_IMPORTANT(C99, diag::warn_pch_c99);
768 PARSE_LANGOPT_IMPORTANT(Microsoft, diag::warn_pch_microsoft_extensions);
769 PARSE_LANGOPT_IMPORTANT(CPlusPlus, diag::warn_pch_cplusplus);
770 PARSE_LANGOPT_IMPORTANT(CPlusPlus0x, diag::warn_pch_cplusplus0x);
771 PARSE_LANGOPT_IMPORTANT(NoExtensions, diag::warn_pch_extensions);
772 PARSE_LANGOPT_BENIGN(CXXOperatorName);
773 PARSE_LANGOPT_IMPORTANT(ObjC1, diag::warn_pch_objective_c);
774 PARSE_LANGOPT_IMPORTANT(ObjC2, diag::warn_pch_objective_c2);
775 PARSE_LANGOPT_IMPORTANT(ObjCNonFragileABI, diag::warn_pch_nonfragile_abi);
776 PARSE_LANGOPT_BENIGN(PascalStrings);
777 PARSE_LANGOPT_BENIGN(Boolean);
778 PARSE_LANGOPT_BENIGN(WritableStrings);
779 PARSE_LANGOPT_IMPORTANT(LaxVectorConversions,
780 diag::warn_pch_lax_vector_conversions);
781 PARSE_LANGOPT_IMPORTANT(Exceptions, diag::warn_pch_exceptions);
782 PARSE_LANGOPT_IMPORTANT(NeXTRuntime, diag::warn_pch_objc_runtime);
783 PARSE_LANGOPT_IMPORTANT(Freestanding, diag::warn_pch_freestanding);
784 PARSE_LANGOPT_IMPORTANT(NoBuiltin, diag::warn_pch_builtins);
785 PARSE_LANGOPT_IMPORTANT(ThreadsafeStatics,
786 diag::warn_pch_thread_safe_statics);
787 PARSE_LANGOPT_IMPORTANT(Blocks, diag::warn_pch_blocks);
788 PARSE_LANGOPT_BENIGN(EmitAllDecls);
789 PARSE_LANGOPT_IMPORTANT(MathErrno, diag::warn_pch_math_errno);
790 PARSE_LANGOPT_IMPORTANT(OverflowChecking, diag::warn_pch_overflow_checking);
791 PARSE_LANGOPT_IMPORTANT(HeinousExtensions,
792 diag::warn_pch_heinous_extensions);
793 // FIXME: Most of the options below are benign if the macro wasn't
794 // used. Unfortunately, this means that a PCH compiled without
795 // optimization can't be used with optimization turned on, even
796 // though the only thing that changes is whether __OPTIMIZE__ was
797 // defined... but if __OPTIMIZE__ never showed up in the header, it
798 // doesn't matter. We could consider making this some special kind
799 // of check.
800 PARSE_LANGOPT_IMPORTANT(Optimize, diag::warn_pch_optimize);
801 PARSE_LANGOPT_IMPORTANT(OptimizeSize, diag::warn_pch_optimize_size);
802 PARSE_LANGOPT_IMPORTANT(Static, diag::warn_pch_static);
803 PARSE_LANGOPT_IMPORTANT(PICLevel, diag::warn_pch_pic_level);
804 PARSE_LANGOPT_IMPORTANT(GNUInline, diag::warn_pch_gnu_inline);
805 PARSE_LANGOPT_IMPORTANT(NoInline, diag::warn_pch_no_inline);
806 if ((LangOpts.getGCMode() != 0) != (Record[Idx] != 0)) {
807 Diag(diag::warn_pch_gc_mode)
808 << (unsigned)Record[Idx] << LangOpts.getGCMode();
809 Diag(diag::note_ignoring_pch) << FileName;
810 return true;
811 }
812 ++Idx;
813 PARSE_LANGOPT_BENIGN(getVisibilityMode());
814 PARSE_LANGOPT_BENIGN(InstantiationDepth);
815#undef PARSE_LANGOPT_IRRELEVANT
816#undef PARSE_LANGOPT_BENIGN
817
818 return false;
819}
820
Douglas Gregorc34897d2009-04-09 22:27:44 +0000821/// \brief Read and return the type at the given offset.
822///
823/// This routine actually reads the record corresponding to the type
824/// at the given offset in the bitstream. It is a helper routine for
825/// GetType, which deals with reading type IDs.
826QualType PCHReader::ReadTypeRecord(uint64_t Offset) {
827 Stream.JumpToBit(Offset);
828 RecordData Record;
829 unsigned Code = Stream.ReadCode();
830 switch ((pch::TypeCode)Stream.ReadRecord(Code, Record)) {
Douglas Gregor88fd09d2009-04-13 20:46:52 +0000831 case pch::TYPE_EXT_QUAL:
832 // FIXME: Deserialize ExtQualType
833 assert(false && "Cannot deserialize qualified types yet");
834 return QualType();
835
Douglas Gregorc34897d2009-04-09 22:27:44 +0000836 case pch::TYPE_FIXED_WIDTH_INT: {
837 assert(Record.size() == 2 && "Incorrect encoding of fixed-width int type");
838 return Context.getFixedWidthIntType(Record[0], Record[1]);
839 }
840
841 case pch::TYPE_COMPLEX: {
842 assert(Record.size() == 1 && "Incorrect encoding of complex type");
843 QualType ElemType = GetType(Record[0]);
844 return Context.getComplexType(ElemType);
845 }
846
847 case pch::TYPE_POINTER: {
848 assert(Record.size() == 1 && "Incorrect encoding of pointer type");
849 QualType PointeeType = GetType(Record[0]);
850 return Context.getPointerType(PointeeType);
851 }
852
853 case pch::TYPE_BLOCK_POINTER: {
854 assert(Record.size() == 1 && "Incorrect encoding of block pointer type");
855 QualType PointeeType = GetType(Record[0]);
856 return Context.getBlockPointerType(PointeeType);
857 }
858
859 case pch::TYPE_LVALUE_REFERENCE: {
860 assert(Record.size() == 1 && "Incorrect encoding of lvalue reference type");
861 QualType PointeeType = GetType(Record[0]);
862 return Context.getLValueReferenceType(PointeeType);
863 }
864
865 case pch::TYPE_RVALUE_REFERENCE: {
866 assert(Record.size() == 1 && "Incorrect encoding of rvalue reference type");
867 QualType PointeeType = GetType(Record[0]);
868 return Context.getRValueReferenceType(PointeeType);
869 }
870
871 case pch::TYPE_MEMBER_POINTER: {
872 assert(Record.size() == 1 && "Incorrect encoding of member pointer type");
873 QualType PointeeType = GetType(Record[0]);
874 QualType ClassType = GetType(Record[1]);
875 return Context.getMemberPointerType(PointeeType, ClassType.getTypePtr());
876 }
877
Douglas Gregor88fd09d2009-04-13 20:46:52 +0000878 case pch::TYPE_CONSTANT_ARRAY: {
879 QualType ElementType = GetType(Record[0]);
880 ArrayType::ArraySizeModifier ASM = (ArrayType::ArraySizeModifier)Record[1];
881 unsigned IndexTypeQuals = Record[2];
882 unsigned Idx = 3;
883 llvm::APInt Size = ReadAPInt(Record, Idx);
884 return Context.getConstantArrayType(ElementType, Size, ASM, IndexTypeQuals);
885 }
886
887 case pch::TYPE_INCOMPLETE_ARRAY: {
888 QualType ElementType = GetType(Record[0]);
889 ArrayType::ArraySizeModifier ASM = (ArrayType::ArraySizeModifier)Record[1];
890 unsigned IndexTypeQuals = Record[2];
891 return Context.getIncompleteArrayType(ElementType, ASM, IndexTypeQuals);
892 }
893
894 case pch::TYPE_VARIABLE_ARRAY: {
895 // FIXME: implement this
896 assert(false && "Unable to de-serialize variable-length array type");
897 return QualType();
898 }
899
900 case pch::TYPE_VECTOR: {
901 if (Record.size() != 2) {
902 Error("Incorrect encoding of vector type in PCH file");
903 return QualType();
904 }
905
906 QualType ElementType = GetType(Record[0]);
907 unsigned NumElements = Record[1];
908 return Context.getVectorType(ElementType, NumElements);
909 }
910
911 case pch::TYPE_EXT_VECTOR: {
912 if (Record.size() != 2) {
913 Error("Incorrect encoding of extended vector type in PCH file");
914 return QualType();
915 }
916
917 QualType ElementType = GetType(Record[0]);
918 unsigned NumElements = Record[1];
919 return Context.getExtVectorType(ElementType, NumElements);
920 }
921
922 case pch::TYPE_FUNCTION_NO_PROTO: {
923 if (Record.size() != 1) {
924 Error("Incorrect encoding of no-proto function type");
925 return QualType();
926 }
927 QualType ResultType = GetType(Record[0]);
928 return Context.getFunctionNoProtoType(ResultType);
929 }
930
931 case pch::TYPE_FUNCTION_PROTO: {
932 QualType ResultType = GetType(Record[0]);
933 unsigned Idx = 1;
934 unsigned NumParams = Record[Idx++];
935 llvm::SmallVector<QualType, 16> ParamTypes;
936 for (unsigned I = 0; I != NumParams; ++I)
937 ParamTypes.push_back(GetType(Record[Idx++]));
938 bool isVariadic = Record[Idx++];
939 unsigned Quals = Record[Idx++];
940 return Context.getFunctionType(ResultType, &ParamTypes[0], NumParams,
941 isVariadic, Quals);
942 }
943
944 case pch::TYPE_TYPEDEF:
945 assert(Record.size() == 1 && "Incorrect encoding of typedef type");
946 return Context.getTypeDeclType(cast<TypedefDecl>(GetDecl(Record[0])));
947
948 case pch::TYPE_TYPEOF_EXPR:
949 // FIXME: Deserialize TypeOfExprType
950 assert(false && "Cannot de-serialize typeof(expr) from a PCH file");
951 return QualType();
952
953 case pch::TYPE_TYPEOF: {
954 if (Record.size() != 1) {
955 Error("Incorrect encoding of typeof(type) in PCH file");
956 return QualType();
957 }
958 QualType UnderlyingType = GetType(Record[0]);
959 return Context.getTypeOfType(UnderlyingType);
960 }
961
962 case pch::TYPE_RECORD:
Douglas Gregor982365e2009-04-13 21:20:57 +0000963 assert(Record.size() == 1 && "Incorrect encoding of record type");
964 return Context.getTypeDeclType(cast<RecordDecl>(GetDecl(Record[0])));
Douglas Gregor88fd09d2009-04-13 20:46:52 +0000965
Douglas Gregor47f1b2c2009-04-13 18:14:40 +0000966 case pch::TYPE_ENUM:
967 assert(Record.size() == 1 && "Incorrect encoding of enum type");
968 return Context.getTypeDeclType(cast<EnumDecl>(GetDecl(Record[0])));
969
Douglas Gregor88fd09d2009-04-13 20:46:52 +0000970 case pch::TYPE_OBJC_INTERFACE:
971 // FIXME: Deserialize ObjCInterfaceType
972 assert(false && "Cannot de-serialize ObjC interface types yet");
973 return QualType();
974
975 case pch::TYPE_OBJC_QUALIFIED_INTERFACE:
976 // FIXME: Deserialize ObjCQualifiedInterfaceType
977 assert(false && "Cannot de-serialize ObjC qualified interface types yet");
978 return QualType();
979
980 case pch::TYPE_OBJC_QUALIFIED_ID:
981 // FIXME: Deserialize ObjCQualifiedIdType
982 assert(false && "Cannot de-serialize ObjC qualified id types yet");
983 return QualType();
984
985 case pch::TYPE_OBJC_QUALIFIED_CLASS:
986 // FIXME: Deserialize ObjCQualifiedClassType
987 assert(false && "Cannot de-serialize ObjC qualified class types yet");
988 return QualType();
Douglas Gregorc34897d2009-04-09 22:27:44 +0000989 }
990
991 // Suppress a GCC warning
992 return QualType();
993}
994
995/// \brief Note that we have loaded the declaration with the given
996/// Index.
997///
998/// This routine notes that this declaration has already been loaded,
999/// so that future GetDecl calls will return this declaration rather
1000/// than trying to load a new declaration.
1001inline void PCHReader::LoadedDecl(unsigned Index, Decl *D) {
1002 assert(!DeclAlreadyLoaded[Index] && "Decl loaded twice?");
1003 DeclAlreadyLoaded[Index] = true;
1004 DeclOffsets[Index] = reinterpret_cast<uint64_t>(D);
1005}
1006
1007/// \brief Read the declaration at the given offset from the PCH file.
1008Decl *PCHReader::ReadDeclRecord(uint64_t Offset, unsigned Index) {
1009 Decl *D = 0;
1010 Stream.JumpToBit(Offset);
1011 RecordData Record;
1012 unsigned Code = Stream.ReadCode();
1013 unsigned Idx = 0;
1014 PCHDeclReader Reader(*this, Record, Idx);
1015 switch ((pch::DeclCode)Stream.ReadRecord(Code, Record)) {
1016 case pch::DECL_TRANSLATION_UNIT:
1017 assert(Index == 0 && "Translation unit must be at index 0");
1018 Reader.VisitTranslationUnitDecl(Context.getTranslationUnitDecl());
1019 D = Context.getTranslationUnitDecl();
1020 LoadedDecl(Index, D);
1021 break;
1022
1023 case pch::DECL_TYPEDEF: {
1024 TypedefDecl *Typedef = TypedefDecl::Create(Context, 0, SourceLocation(),
1025 0, QualType());
1026 LoadedDecl(Index, Typedef);
1027 Reader.VisitTypedefDecl(Typedef);
1028 D = Typedef;
1029 break;
1030 }
1031
Douglas Gregor47f1b2c2009-04-13 18:14:40 +00001032 case pch::DECL_ENUM: {
1033 EnumDecl *Enum = EnumDecl::Create(Context, 0, SourceLocation(), 0, 0);
1034 LoadedDecl(Index, Enum);
1035 Reader.VisitEnumDecl(Enum);
1036 D = Enum;
1037 break;
1038 }
1039
Douglas Gregor982365e2009-04-13 21:20:57 +00001040 case pch::DECL_RECORD: {
1041 RecordDecl *Record = RecordDecl::Create(Context, TagDecl::TK_struct,
1042 0, SourceLocation(), 0, 0);
1043 LoadedDecl(Index, Record);
1044 Reader.VisitRecordDecl(Record);
1045 D = Record;
1046 break;
1047 }
1048
Douglas Gregor47f1b2c2009-04-13 18:14:40 +00001049 case pch::DECL_ENUM_CONSTANT: {
1050 EnumConstantDecl *ECD = EnumConstantDecl::Create(Context, 0,
1051 SourceLocation(), 0,
1052 QualType(), 0,
1053 llvm::APSInt());
1054 LoadedDecl(Index, ECD);
1055 Reader.VisitEnumConstantDecl(ECD);
1056 D = ECD;
1057 break;
1058 }
Douglas Gregor23ce3a52009-04-13 22:18:37 +00001059
1060 case pch::DECL_FUNCTION: {
1061 FunctionDecl *Function = FunctionDecl::Create(Context, 0, SourceLocation(),
1062 DeclarationName(),
1063 QualType());
1064 LoadedDecl(Index, Function);
1065 Reader.VisitFunctionDecl(Function);
1066 D = Function;
1067 break;
1068 }
Douglas Gregor47f1b2c2009-04-13 18:14:40 +00001069
Douglas Gregor982365e2009-04-13 21:20:57 +00001070 case pch::DECL_FIELD: {
1071 FieldDecl *Field = FieldDecl::Create(Context, 0, SourceLocation(), 0,
1072 QualType(), 0, false);
1073 LoadedDecl(Index, Field);
1074 Reader.VisitFieldDecl(Field);
1075 D = Field;
1076 break;
1077 }
1078
Douglas Gregorc34897d2009-04-09 22:27:44 +00001079 case pch::DECL_VAR: {
1080 VarDecl *Var = VarDecl::Create(Context, 0, SourceLocation(), 0, QualType(),
1081 VarDecl::None, SourceLocation());
1082 LoadedDecl(Index, Var);
1083 Reader.VisitVarDecl(Var);
1084 D = Var;
1085 break;
1086 }
1087
Douglas Gregor23ce3a52009-04-13 22:18:37 +00001088 case pch::DECL_PARM_VAR: {
1089 ParmVarDecl *Parm = ParmVarDecl::Create(Context, 0, SourceLocation(), 0,
1090 QualType(), VarDecl::None, 0);
1091 LoadedDecl(Index, Parm);
1092 Reader.VisitParmVarDecl(Parm);
1093 D = Parm;
1094 break;
1095 }
1096
1097 case pch::DECL_ORIGINAL_PARM_VAR: {
1098 OriginalParmVarDecl *Parm
1099 = OriginalParmVarDecl::Create(Context, 0, SourceLocation(), 0,
1100 QualType(), QualType(), VarDecl::None,
1101 0);
1102 LoadedDecl(Index, Parm);
1103 Reader.VisitOriginalParmVarDecl(Parm);
1104 D = Parm;
1105 break;
1106 }
1107
Douglas Gregorc34897d2009-04-09 22:27:44 +00001108 default:
1109 assert(false && "Cannot de-serialize this kind of declaration");
1110 break;
1111 }
1112
1113 // If this declaration is also a declaration context, get the
1114 // offsets for its tables of lexical and visible declarations.
1115 if (DeclContext *DC = dyn_cast<DeclContext>(D)) {
1116 std::pair<uint64_t, uint64_t> Offsets = Reader.VisitDeclContext(DC);
1117 if (Offsets.first || Offsets.second) {
1118 DC->setHasExternalLexicalStorage(Offsets.first != 0);
1119 DC->setHasExternalVisibleStorage(Offsets.second != 0);
1120 DeclContextOffsets[DC] = Offsets;
1121 }
1122 }
1123 assert(Idx == Record.size());
1124
1125 return D;
1126}
1127
Douglas Gregorac8f2802009-04-10 17:25:41 +00001128QualType PCHReader::GetType(pch::TypeID ID) {
Douglas Gregorc34897d2009-04-09 22:27:44 +00001129 unsigned Quals = ID & 0x07;
1130 unsigned Index = ID >> 3;
1131
1132 if (Index < pch::NUM_PREDEF_TYPE_IDS) {
1133 QualType T;
1134 switch ((pch::PredefinedTypeIDs)Index) {
1135 case pch::PREDEF_TYPE_NULL_ID: return QualType();
1136 case pch::PREDEF_TYPE_VOID_ID: T = Context.VoidTy; break;
1137 case pch::PREDEF_TYPE_BOOL_ID: T = Context.BoolTy; break;
1138
1139 case pch::PREDEF_TYPE_CHAR_U_ID:
1140 case pch::PREDEF_TYPE_CHAR_S_ID:
1141 // FIXME: Check that the signedness of CharTy is correct!
1142 T = Context.CharTy;
1143 break;
1144
1145 case pch::PREDEF_TYPE_UCHAR_ID: T = Context.UnsignedCharTy; break;
1146 case pch::PREDEF_TYPE_USHORT_ID: T = Context.UnsignedShortTy; break;
1147 case pch::PREDEF_TYPE_UINT_ID: T = Context.UnsignedIntTy; break;
1148 case pch::PREDEF_TYPE_ULONG_ID: T = Context.UnsignedLongTy; break;
1149 case pch::PREDEF_TYPE_ULONGLONG_ID: T = Context.UnsignedLongLongTy; break;
1150 case pch::PREDEF_TYPE_SCHAR_ID: T = Context.SignedCharTy; break;
1151 case pch::PREDEF_TYPE_WCHAR_ID: T = Context.WCharTy; break;
1152 case pch::PREDEF_TYPE_SHORT_ID: T = Context.ShortTy; break;
1153 case pch::PREDEF_TYPE_INT_ID: T = Context.IntTy; break;
1154 case pch::PREDEF_TYPE_LONG_ID: T = Context.LongTy; break;
1155 case pch::PREDEF_TYPE_LONGLONG_ID: T = Context.LongLongTy; break;
1156 case pch::PREDEF_TYPE_FLOAT_ID: T = Context.FloatTy; break;
1157 case pch::PREDEF_TYPE_DOUBLE_ID: T = Context.DoubleTy; break;
1158 case pch::PREDEF_TYPE_LONGDOUBLE_ID: T = Context.LongDoubleTy; break;
1159 case pch::PREDEF_TYPE_OVERLOAD_ID: T = Context.OverloadTy; break;
1160 case pch::PREDEF_TYPE_DEPENDENT_ID: T = Context.DependentTy; break;
1161 }
1162
1163 assert(!T.isNull() && "Unknown predefined type");
1164 return T.getQualifiedType(Quals);
1165 }
1166
1167 Index -= pch::NUM_PREDEF_TYPE_IDS;
1168 if (!TypeAlreadyLoaded[Index]) {
1169 // Load the type from the PCH file.
1170 TypeOffsets[Index] = reinterpret_cast<uint64_t>(
1171 ReadTypeRecord(TypeOffsets[Index]).getTypePtr());
1172 TypeAlreadyLoaded[Index] = true;
1173 }
1174
1175 return QualType(reinterpret_cast<Type *>(TypeOffsets[Index]), Quals);
1176}
1177
Douglas Gregorac8f2802009-04-10 17:25:41 +00001178Decl *PCHReader::GetDecl(pch::DeclID ID) {
Douglas Gregorc34897d2009-04-09 22:27:44 +00001179 if (ID == 0)
1180 return 0;
1181
1182 unsigned Index = ID - 1;
1183 if (DeclAlreadyLoaded[Index])
1184 return reinterpret_cast<Decl *>(DeclOffsets[Index]);
1185
1186 // Load the declaration from the PCH file.
1187 return ReadDeclRecord(DeclOffsets[Index], Index);
1188}
1189
1190bool PCHReader::ReadDeclsLexicallyInContext(DeclContext *DC,
Douglas Gregorac8f2802009-04-10 17:25:41 +00001191 llvm::SmallVectorImpl<pch::DeclID> &Decls) {
Douglas Gregorc34897d2009-04-09 22:27:44 +00001192 assert(DC->hasExternalLexicalStorage() &&
1193 "DeclContext has no lexical decls in storage");
1194 uint64_t Offset = DeclContextOffsets[DC].first;
1195 assert(Offset && "DeclContext has no lexical decls in storage");
1196
1197 // Load the record containing all of the declarations lexically in
1198 // this context.
1199 Stream.JumpToBit(Offset);
1200 RecordData Record;
1201 unsigned Code = Stream.ReadCode();
1202 unsigned RecCode = Stream.ReadRecord(Code, Record);
1203 assert(RecCode == pch::DECL_CONTEXT_LEXICAL && "Expected lexical block");
1204
1205 // Load all of the declaration IDs
1206 Decls.clear();
1207 Decls.insert(Decls.end(), Record.begin(), Record.end());
1208 return false;
1209}
1210
1211bool PCHReader::ReadDeclsVisibleInContext(DeclContext *DC,
1212 llvm::SmallVectorImpl<VisibleDeclaration> & Decls) {
1213 assert(DC->hasExternalVisibleStorage() &&
1214 "DeclContext has no visible decls in storage");
1215 uint64_t Offset = DeclContextOffsets[DC].second;
1216 assert(Offset && "DeclContext has no visible decls in storage");
1217
1218 // Load the record containing all of the declarations visible in
1219 // this context.
1220 Stream.JumpToBit(Offset);
1221 RecordData Record;
1222 unsigned Code = Stream.ReadCode();
1223 unsigned RecCode = Stream.ReadRecord(Code, Record);
1224 assert(RecCode == pch::DECL_CONTEXT_VISIBLE && "Expected visible block");
1225 if (Record.size() == 0)
1226 return false;
1227
1228 Decls.clear();
1229
1230 unsigned Idx = 0;
Douglas Gregorc34897d2009-04-09 22:27:44 +00001231 while (Idx < Record.size()) {
1232 Decls.push_back(VisibleDeclaration());
1233 Decls.back().Name = ReadDeclarationName(Record, Idx);
1234
Douglas Gregorc34897d2009-04-09 22:27:44 +00001235 unsigned Size = Record[Idx++];
1236 llvm::SmallVector<unsigned, 4> & LoadedDecls
1237 = Decls.back().Declarations;
1238 LoadedDecls.reserve(Size);
1239 for (unsigned I = 0; I < Size; ++I)
1240 LoadedDecls.push_back(Record[Idx++]);
1241 }
1242
1243 return false;
1244}
1245
1246void PCHReader::PrintStats() {
1247 std::fprintf(stderr, "*** PCH Statistics:\n");
1248
1249 unsigned NumTypesLoaded = std::count(TypeAlreadyLoaded.begin(),
1250 TypeAlreadyLoaded.end(),
1251 true);
1252 unsigned NumDeclsLoaded = std::count(DeclAlreadyLoaded.begin(),
1253 DeclAlreadyLoaded.end(),
1254 true);
Douglas Gregor9cf47422009-04-13 20:50:16 +00001255 unsigned NumIdentifiersLoaded = 0;
1256 for (unsigned I = 0; I < IdentifierData.size(); ++I) {
1257 if ((IdentifierData[I] & 0x01) == 0)
1258 ++NumIdentifiersLoaded;
1259 }
1260
Douglas Gregorc34897d2009-04-09 22:27:44 +00001261 std::fprintf(stderr, " %u/%u types read (%f%%)\n",
1262 NumTypesLoaded, (unsigned)TypeAlreadyLoaded.size(),
Douglas Gregor9cf47422009-04-13 20:50:16 +00001263 ((float)NumTypesLoaded/TypeAlreadyLoaded.size() * 100));
Douglas Gregorc34897d2009-04-09 22:27:44 +00001264 std::fprintf(stderr, " %u/%u declarations read (%f%%)\n",
1265 NumDeclsLoaded, (unsigned)DeclAlreadyLoaded.size(),
Douglas Gregor9cf47422009-04-13 20:50:16 +00001266 ((float)NumDeclsLoaded/DeclAlreadyLoaded.size() * 100));
1267 std::fprintf(stderr, " %u/%u identifiers read (%f%%)\n",
1268 NumIdentifiersLoaded, (unsigned)IdentifierData.size(),
1269 ((float)NumIdentifiersLoaded/IdentifierData.size() * 100));
Douglas Gregorc34897d2009-04-09 22:27:44 +00001270 std::fprintf(stderr, "\n");
1271}
1272
Chris Lattner29241862009-04-11 21:15:38 +00001273IdentifierInfo *PCHReader::DecodeIdentifierInfo(unsigned ID) {
Douglas Gregor7a224cf2009-04-11 00:14:32 +00001274 if (ID == 0)
1275 return 0;
Chris Lattner29241862009-04-11 21:15:38 +00001276
Douglas Gregor7a224cf2009-04-11 00:14:32 +00001277 if (!IdentifierTable || IdentifierData.empty()) {
1278 Error("No identifier table in PCH file");
1279 return 0;
1280 }
Chris Lattner29241862009-04-11 21:15:38 +00001281
Douglas Gregor7a224cf2009-04-11 00:14:32 +00001282 if (IdentifierData[ID - 1] & 0x01) {
1283 uint64_t Offset = IdentifierData[ID - 1];
1284 IdentifierData[ID - 1] = reinterpret_cast<uint64_t>(
Chris Lattner29241862009-04-11 21:15:38 +00001285 &Context.Idents.get(IdentifierTable + Offset));
Douglas Gregor7a224cf2009-04-11 00:14:32 +00001286 }
Chris Lattner29241862009-04-11 21:15:38 +00001287
1288 return reinterpret_cast<IdentifierInfo *>(IdentifierData[ID - 1]);
Douglas Gregorc34897d2009-04-09 22:27:44 +00001289}
1290
1291DeclarationName
1292PCHReader::ReadDeclarationName(const RecordData &Record, unsigned &Idx) {
1293 DeclarationName::NameKind Kind = (DeclarationName::NameKind)Record[Idx++];
1294 switch (Kind) {
1295 case DeclarationName::Identifier:
1296 return DeclarationName(GetIdentifierInfo(Record, Idx));
1297
1298 case DeclarationName::ObjCZeroArgSelector:
1299 case DeclarationName::ObjCOneArgSelector:
1300 case DeclarationName::ObjCMultiArgSelector:
1301 assert(false && "Unable to de-serialize Objective-C selectors");
1302 break;
1303
1304 case DeclarationName::CXXConstructorName:
1305 return Context.DeclarationNames.getCXXConstructorName(
1306 GetType(Record[Idx++]));
1307
1308 case DeclarationName::CXXDestructorName:
1309 return Context.DeclarationNames.getCXXDestructorName(
1310 GetType(Record[Idx++]));
1311
1312 case DeclarationName::CXXConversionFunctionName:
1313 return Context.DeclarationNames.getCXXConversionFunctionName(
1314 GetType(Record[Idx++]));
1315
1316 case DeclarationName::CXXOperatorName:
1317 return Context.DeclarationNames.getCXXOperatorName(
1318 (OverloadedOperatorKind)Record[Idx++]);
1319
1320 case DeclarationName::CXXUsingDirective:
1321 return DeclarationName::getUsingDirectiveName();
1322 }
1323
1324 // Required to silence GCC warning
1325 return DeclarationName();
1326}
Douglas Gregor179cfb12009-04-10 20:39:37 +00001327
Douglas Gregor47f1b2c2009-04-13 18:14:40 +00001328/// \brief Read an integral value
1329llvm::APInt PCHReader::ReadAPInt(const RecordData &Record, unsigned &Idx) {
1330 unsigned BitWidth = Record[Idx++];
1331 unsigned NumWords = llvm::APInt::getNumWords(BitWidth);
1332 llvm::APInt Result(BitWidth, NumWords, &Record[Idx]);
1333 Idx += NumWords;
1334 return Result;
1335}
1336
1337/// \brief Read a signed integral value
1338llvm::APSInt PCHReader::ReadAPSInt(const RecordData &Record, unsigned &Idx) {
1339 bool isUnsigned = Record[Idx++];
1340 return llvm::APSInt(ReadAPInt(Record, Idx), isUnsigned);
1341}
1342
Douglas Gregor179cfb12009-04-10 20:39:37 +00001343DiagnosticBuilder PCHReader::Diag(unsigned DiagID) {
Douglas Gregorb3a04c82009-04-10 23:10:45 +00001344 return Diag(SourceLocation(), DiagID);
1345}
1346
1347DiagnosticBuilder PCHReader::Diag(SourceLocation Loc, unsigned DiagID) {
1348 return PP.getDiagnostics().Report(FullSourceLoc(Loc,
Douglas Gregor179cfb12009-04-10 20:39:37 +00001349 Context.getSourceManager()),
1350 DiagID);
1351}