blob: 328ed841ce51c6cb8d2cc3e98847e6de219e7b64 [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 Gregor2a491792009-04-13 22:49:25 +000061 void VisitFileScopeAsmDecl(FileScopeAsmDecl *AD);
62 void VisitBlockDecl(BlockDecl *BD);
Douglas Gregorc34897d2009-04-09 22:27:44 +000063 std::pair<uint64_t, uint64_t> VisitDeclContext(DeclContext *DC);
64 };
65}
66
67void PCHDeclReader::VisitDecl(Decl *D) {
68 D->setDeclContext(cast_or_null<DeclContext>(Reader.GetDecl(Record[Idx++])));
69 D->setLexicalDeclContext(
70 cast_or_null<DeclContext>(Reader.GetDecl(Record[Idx++])));
71 D->setLocation(SourceLocation::getFromRawEncoding(Record[Idx++]));
72 D->setInvalidDecl(Record[Idx++]);
73 // FIXME: hasAttrs
74 D->setImplicit(Record[Idx++]);
75 D->setAccess((AccessSpecifier)Record[Idx++]);
76}
77
78void PCHDeclReader::VisitTranslationUnitDecl(TranslationUnitDecl *TU) {
79 VisitDecl(TU);
80}
81
82void PCHDeclReader::VisitNamedDecl(NamedDecl *ND) {
83 VisitDecl(ND);
84 ND->setDeclName(Reader.ReadDeclarationName(Record, Idx));
85}
86
87void PCHDeclReader::VisitTypeDecl(TypeDecl *TD) {
88 VisitNamedDecl(TD);
Douglas Gregorc34897d2009-04-09 22:27:44 +000089 TD->setTypeForDecl(Reader.GetType(Record[Idx++]).getTypePtr());
90}
91
92void PCHDeclReader::VisitTypedefDecl(TypedefDecl *TD) {
Douglas Gregor88fd09d2009-04-13 20:46:52 +000093 // Note that we cannot use VisitTypeDecl here, because we need to
94 // set the underlying type of the typedef *before* we try to read
95 // the type associated with the TypedefDecl.
96 VisitNamedDecl(TD);
97 TD->setUnderlyingType(Reader.GetType(Record[Idx + 1]));
98 TD->setTypeForDecl(Reader.GetType(Record[Idx]).getTypePtr());
99 Idx += 2;
Douglas Gregorc34897d2009-04-09 22:27:44 +0000100}
101
Douglas Gregor47f1b2c2009-04-13 18:14:40 +0000102void PCHDeclReader::VisitTagDecl(TagDecl *TD) {
103 VisitTypeDecl(TD);
104 TD->setTagKind((TagDecl::TagKind)Record[Idx++]);
105 TD->setDefinition(Record[Idx++]);
106 TD->setTypedefForAnonDecl(
107 cast_or_null<TypedefDecl>(Reader.GetDecl(Record[Idx++])));
108}
109
110void PCHDeclReader::VisitEnumDecl(EnumDecl *ED) {
111 VisitTagDecl(ED);
112 ED->setIntegerType(Reader.GetType(Record[Idx++]));
113}
114
Douglas Gregor982365e2009-04-13 21:20:57 +0000115void PCHDeclReader::VisitRecordDecl(RecordDecl *RD) {
116 VisitTagDecl(RD);
117 RD->setHasFlexibleArrayMember(Record[Idx++]);
118 RD->setAnonymousStructOrUnion(Record[Idx++]);
119}
120
Douglas Gregorc34897d2009-04-09 22:27:44 +0000121void PCHDeclReader::VisitValueDecl(ValueDecl *VD) {
122 VisitNamedDecl(VD);
123 VD->setType(Reader.GetType(Record[Idx++]));
124}
125
Douglas Gregor47f1b2c2009-04-13 18:14:40 +0000126void PCHDeclReader::VisitEnumConstantDecl(EnumConstantDecl *ECD) {
127 VisitValueDecl(ECD);
Douglas Gregor982365e2009-04-13 21:20:57 +0000128 // FIXME: read the initialization expression
Douglas Gregor47f1b2c2009-04-13 18:14:40 +0000129 ECD->setInitVal(Reader.ReadAPSInt(Record, Idx));
130}
131
Douglas Gregor23ce3a52009-04-13 22:18:37 +0000132void PCHDeclReader::VisitFunctionDecl(FunctionDecl *FD) {
133 VisitValueDecl(FD);
134 // FIXME: function body
135 FD->setPreviousDeclaration(
136 cast_or_null<FunctionDecl>(Reader.GetDecl(Record[Idx++])));
137 FD->setStorageClass((FunctionDecl::StorageClass)Record[Idx++]);
138 FD->setInline(Record[Idx++]);
139 FD->setVirtual(Record[Idx++]);
140 FD->setPure(Record[Idx++]);
141 FD->setInheritedPrototype(Record[Idx++]);
142 FD->setHasPrototype(Record[Idx++]);
143 FD->setDeleted(Record[Idx++]);
144 FD->setTypeSpecStartLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
145 unsigned NumParams = Record[Idx++];
146 llvm::SmallVector<ParmVarDecl *, 16> Params;
147 Params.reserve(NumParams);
148 for (unsigned I = 0; I != NumParams; ++I)
149 Params.push_back(cast<ParmVarDecl>(Reader.GetDecl(Record[Idx++])));
150 FD->setParams(Reader.getContext(), &Params[0], NumParams);
151}
152
Douglas Gregor982365e2009-04-13 21:20:57 +0000153void PCHDeclReader::VisitFieldDecl(FieldDecl *FD) {
154 VisitValueDecl(FD);
155 FD->setMutable(Record[Idx++]);
156 // FIXME: Read the bit width.
157}
158
Douglas Gregorc34897d2009-04-09 22:27:44 +0000159void PCHDeclReader::VisitVarDecl(VarDecl *VD) {
160 VisitValueDecl(VD);
161 VD->setStorageClass((VarDecl::StorageClass)Record[Idx++]);
162 VD->setThreadSpecified(Record[Idx++]);
163 VD->setCXXDirectInitializer(Record[Idx++]);
164 VD->setDeclaredInCondition(Record[Idx++]);
165 VD->setPreviousDeclaration(
166 cast_or_null<VarDecl>(Reader.GetDecl(Record[Idx++])));
167 VD->setTypeSpecStartLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
168}
169
Douglas Gregor23ce3a52009-04-13 22:18:37 +0000170void PCHDeclReader::VisitParmVarDecl(ParmVarDecl *PD) {
171 VisitVarDecl(PD);
172 PD->setObjCDeclQualifier((Decl::ObjCDeclQualifier)Record[Idx++]);
173 // FIXME: default argument
174}
175
176void PCHDeclReader::VisitOriginalParmVarDecl(OriginalParmVarDecl *PD) {
177 VisitParmVarDecl(PD);
178 PD->setOriginalType(Reader.GetType(Record[Idx++]));
179}
180
Douglas Gregor2a491792009-04-13 22:49:25 +0000181void PCHDeclReader::VisitFileScopeAsmDecl(FileScopeAsmDecl *AD) {
182 VisitDecl(AD);
183 // FIXME: read asm string
184}
185
186void PCHDeclReader::VisitBlockDecl(BlockDecl *BD) {
187 VisitDecl(BD);
188 unsigned NumParams = Record[Idx++];
189 llvm::SmallVector<ParmVarDecl *, 16> Params;
190 Params.reserve(NumParams);
191 for (unsigned I = 0; I != NumParams; ++I)
192 Params.push_back(cast<ParmVarDecl>(Reader.GetDecl(Record[Idx++])));
193 BD->setParams(Reader.getContext(), &Params[0], NumParams);
194}
195
Douglas Gregorc34897d2009-04-09 22:27:44 +0000196std::pair<uint64_t, uint64_t>
197PCHDeclReader::VisitDeclContext(DeclContext *DC) {
198 uint64_t LexicalOffset = Record[Idx++];
199 uint64_t VisibleOffset = 0;
200 if (DC->getPrimaryContext() == DC)
201 VisibleOffset = Record[Idx++];
202 return std::make_pair(LexicalOffset, VisibleOffset);
203}
204
205// FIXME: use the diagnostics machinery
206static bool Error(const char *Str) {
207 std::fprintf(stderr, "%s\n", Str);
208 return true;
209}
210
Douglas Gregorb3a04c82009-04-10 23:10:45 +0000211/// \brief Check the contents of the predefines buffer against the
212/// contents of the predefines buffer used to build the PCH file.
213///
214/// The contents of the two predefines buffers should be the same. If
215/// not, then some command-line option changed the preprocessor state
216/// and we must reject the PCH file.
217///
218/// \param PCHPredef The start of the predefines buffer in the PCH
219/// file.
220///
221/// \param PCHPredefLen The length of the predefines buffer in the PCH
222/// file.
223///
224/// \param PCHBufferID The FileID for the PCH predefines buffer.
225///
226/// \returns true if there was a mismatch (in which case the PCH file
227/// should be ignored), or false otherwise.
228bool PCHReader::CheckPredefinesBuffer(const char *PCHPredef,
229 unsigned PCHPredefLen,
230 FileID PCHBufferID) {
231 const char *Predef = PP.getPredefines().c_str();
232 unsigned PredefLen = PP.getPredefines().size();
233
234 // If the two predefines buffers compare equal, we're done!.
235 if (PredefLen == PCHPredefLen &&
236 strncmp(Predef, PCHPredef, PCHPredefLen) == 0)
237 return false;
238
239 // The predefines buffers are different. Produce a reasonable
240 // diagnostic showing where they are different.
241
242 // The source locations (potentially in the two different predefines
243 // buffers)
244 SourceLocation Loc1, Loc2;
245 SourceManager &SourceMgr = PP.getSourceManager();
246
247 // Create a source buffer for our predefines string, so
248 // that we can build a diagnostic that points into that
249 // source buffer.
250 FileID BufferID;
251 if (Predef && Predef[0]) {
252 llvm::MemoryBuffer *Buffer
253 = llvm::MemoryBuffer::getMemBuffer(Predef, Predef + PredefLen,
254 "<built-in>");
255 BufferID = SourceMgr.createFileIDForMemBuffer(Buffer);
256 }
257
258 unsigned MinLen = std::min(PredefLen, PCHPredefLen);
259 std::pair<const char *, const char *> Locations
260 = std::mismatch(Predef, Predef + MinLen, PCHPredef);
261
262 if (Locations.first != Predef + MinLen) {
263 // We found the location in the two buffers where there is a
264 // difference. Form source locations to point there (in both
265 // buffers).
266 unsigned Offset = Locations.first - Predef;
267 Loc1 = SourceMgr.getLocForStartOfFile(BufferID)
268 .getFileLocWithOffset(Offset);
269 Loc2 = SourceMgr.getLocForStartOfFile(PCHBufferID)
270 .getFileLocWithOffset(Offset);
271 } else if (PredefLen > PCHPredefLen) {
272 Loc1 = SourceMgr.getLocForStartOfFile(BufferID)
273 .getFileLocWithOffset(MinLen);
274 } else {
275 Loc1 = SourceMgr.getLocForStartOfFile(PCHBufferID)
276 .getFileLocWithOffset(MinLen);
277 }
278
279 Diag(Loc1, diag::warn_pch_preprocessor);
280 if (Loc2.isValid())
281 Diag(Loc2, diag::note_predef_in_pch);
282 Diag(diag::note_ignoring_pch) << FileName;
283 return true;
284}
285
Douglas Gregor635f97f2009-04-13 16:31:14 +0000286/// \brief Read the line table in the source manager block.
287/// \returns true if ther was an error.
288static bool ParseLineTable(SourceManager &SourceMgr,
289 llvm::SmallVectorImpl<uint64_t> &Record) {
290 unsigned Idx = 0;
291 LineTableInfo &LineTable = SourceMgr.getLineTable();
292
293 // Parse the file names
Douglas Gregor183ad602009-04-13 17:12:42 +0000294 std::map<int, int> FileIDs;
295 for (int I = 0, N = Record[Idx++]; I != N; ++I) {
Douglas Gregor635f97f2009-04-13 16:31:14 +0000296 // Extract the file name
297 unsigned FilenameLen = Record[Idx++];
298 std::string Filename(&Record[Idx], &Record[Idx] + FilenameLen);
299 Idx += FilenameLen;
Douglas Gregor183ad602009-04-13 17:12:42 +0000300 FileIDs[I] = LineTable.getLineTableFilenameID(Filename.c_str(),
301 Filename.size());
Douglas Gregor635f97f2009-04-13 16:31:14 +0000302 }
303
304 // Parse the line entries
305 std::vector<LineEntry> Entries;
306 while (Idx < Record.size()) {
Douglas Gregor183ad602009-04-13 17:12:42 +0000307 int FID = FileIDs[Record[Idx++]];
Douglas Gregor635f97f2009-04-13 16:31:14 +0000308
309 // Extract the line entries
310 unsigned NumEntries = Record[Idx++];
311 Entries.clear();
312 Entries.reserve(NumEntries);
313 for (unsigned I = 0; I != NumEntries; ++I) {
314 unsigned FileOffset = Record[Idx++];
315 unsigned LineNo = Record[Idx++];
316 int FilenameID = Record[Idx++];
317 SrcMgr::CharacteristicKind FileKind
318 = (SrcMgr::CharacteristicKind)Record[Idx++];
319 unsigned IncludeOffset = Record[Idx++];
320 Entries.push_back(LineEntry::get(FileOffset, LineNo, FilenameID,
321 FileKind, IncludeOffset));
322 }
323 LineTable.AddEntry(FID, Entries);
324 }
325
326 return false;
327}
328
Douglas Gregorab1cef72009-04-10 03:52:48 +0000329/// \brief Read the source manager block
Douglas Gregorb3a04c82009-04-10 23:10:45 +0000330PCHReader::PCHReadResult PCHReader::ReadSourceManagerBlock() {
Douglas Gregorab1cef72009-04-10 03:52:48 +0000331 using namespace SrcMgr;
Douglas Gregorb3a04c82009-04-10 23:10:45 +0000332 if (Stream.EnterSubBlock(pch::SOURCE_MANAGER_BLOCK_ID)) {
333 Error("Malformed source manager block record");
334 return Failure;
335 }
Douglas Gregorab1cef72009-04-10 03:52:48 +0000336
337 SourceManager &SourceMgr = Context.getSourceManager();
338 RecordData Record;
339 while (true) {
340 unsigned Code = Stream.ReadCode();
341 if (Code == llvm::bitc::END_BLOCK) {
Douglas Gregorb3a04c82009-04-10 23:10:45 +0000342 if (Stream.ReadBlockEnd()) {
343 Error("Error at end of Source Manager block");
344 return Failure;
345 }
346
347 return Success;
Douglas Gregorab1cef72009-04-10 03:52:48 +0000348 }
349
350 if (Code == llvm::bitc::ENTER_SUBBLOCK) {
351 // No known subblocks, always skip them.
352 Stream.ReadSubBlockID();
Douglas Gregorb3a04c82009-04-10 23:10:45 +0000353 if (Stream.SkipBlock()) {
354 Error("Malformed block record");
355 return Failure;
356 }
Douglas Gregorab1cef72009-04-10 03:52:48 +0000357 continue;
358 }
359
360 if (Code == llvm::bitc::DEFINE_ABBREV) {
361 Stream.ReadAbbrevRecord();
362 continue;
363 }
364
365 // Read a record.
366 const char *BlobStart;
367 unsigned BlobLen;
368 Record.clear();
369 switch (Stream.ReadRecord(Code, Record, &BlobStart, &BlobLen)) {
370 default: // Default behavior: ignore.
371 break;
372
373 case pch::SM_SLOC_FILE_ENTRY: {
374 // FIXME: We would really like to delay the creation of this
375 // FileEntry until it is actually required, e.g., when producing
376 // a diagnostic with a source location in this file.
377 const FileEntry *File
378 = PP.getFileManager().getFile(BlobStart, BlobStart + BlobLen);
379 // FIXME: Error recovery if file cannot be found.
Douglas Gregor635f97f2009-04-13 16:31:14 +0000380 FileID ID = SourceMgr.createFileID(File,
381 SourceLocation::getFromRawEncoding(Record[1]),
382 (CharacteristicKind)Record[2]);
383 if (Record[3])
384 const_cast<SrcMgr::FileInfo&>(SourceMgr.getSLocEntry(ID).getFile())
385 .setHasLineDirectives();
Douglas Gregorab1cef72009-04-10 03:52:48 +0000386 break;
387 }
388
389 case pch::SM_SLOC_BUFFER_ENTRY: {
390 const char *Name = BlobStart;
391 unsigned Code = Stream.ReadCode();
392 Record.clear();
393 unsigned RecCode = Stream.ReadRecord(Code, Record, &BlobStart, &BlobLen);
394 assert(RecCode == pch::SM_SLOC_BUFFER_BLOB && "Ill-formed PCH file");
Douglas Gregorb3a04c82009-04-10 23:10:45 +0000395 llvm::MemoryBuffer *Buffer
396 = llvm::MemoryBuffer::getMemBuffer(BlobStart,
397 BlobStart + BlobLen - 1,
398 Name);
399 FileID BufferID = SourceMgr.createFileIDForMemBuffer(Buffer);
400
401 if (strcmp(Name, "<built-in>") == 0
402 && CheckPredefinesBuffer(BlobStart, BlobLen - 1, BufferID))
403 return IgnorePCH;
Douglas Gregorab1cef72009-04-10 03:52:48 +0000404 break;
405 }
406
407 case pch::SM_SLOC_INSTANTIATION_ENTRY: {
408 SourceLocation SpellingLoc
409 = SourceLocation::getFromRawEncoding(Record[1]);
410 SourceMgr.createInstantiationLoc(
411 SpellingLoc,
412 SourceLocation::getFromRawEncoding(Record[2]),
413 SourceLocation::getFromRawEncoding(Record[3]),
414 Lexer::MeasureTokenLength(SpellingLoc,
415 SourceMgr));
416 break;
417 }
418
Douglas Gregor635f97f2009-04-13 16:31:14 +0000419 case pch::SM_LINE_TABLE: {
420 if (ParseLineTable(SourceMgr, Record))
421 return Failure;
422 }
Douglas Gregorab1cef72009-04-10 03:52:48 +0000423 }
424 }
425}
426
Chris Lattnerdb1c81b2009-04-10 21:41:48 +0000427bool PCHReader::ReadPreprocessorBlock() {
428 if (Stream.EnterSubBlock(pch::PREPROCESSOR_BLOCK_ID))
429 return Error("Malformed preprocessor block record");
430
Chris Lattnerdb1c81b2009-04-10 21:41:48 +0000431 RecordData Record;
432 llvm::SmallVector<IdentifierInfo*, 16> MacroArgs;
433 MacroInfo *LastMacro = 0;
434
435 while (true) {
436 unsigned Code = Stream.ReadCode();
437 switch (Code) {
438 case llvm::bitc::END_BLOCK:
439 if (Stream.ReadBlockEnd())
440 return Error("Error at end of preprocessor block");
441 return false;
442
443 case llvm::bitc::ENTER_SUBBLOCK:
444 // No known subblocks, always skip them.
445 Stream.ReadSubBlockID();
446 if (Stream.SkipBlock())
447 return Error("Malformed block record");
448 continue;
449
450 case llvm::bitc::DEFINE_ABBREV:
451 Stream.ReadAbbrevRecord();
452 continue;
453 default: break;
454 }
455
456 // Read a record.
457 Record.clear();
458 pch::PreprocessorRecordTypes RecType =
459 (pch::PreprocessorRecordTypes)Stream.ReadRecord(Code, Record);
460 switch (RecType) {
461 default: // Default behavior: ignore unknown records.
462 break;
Chris Lattner4b21c202009-04-13 01:29:17 +0000463 case pch::PP_COUNTER_VALUE:
464 if (!Record.empty())
465 PP.setCounterValue(Record[0]);
466 break;
467
Chris Lattnerdb1c81b2009-04-10 21:41:48 +0000468 case pch::PP_MACRO_OBJECT_LIKE:
469 case pch::PP_MACRO_FUNCTION_LIKE: {
Chris Lattner29241862009-04-11 21:15:38 +0000470 IdentifierInfo *II = DecodeIdentifierInfo(Record[0]);
471 if (II == 0)
472 return Error("Macro must have a name");
Chris Lattnerdb1c81b2009-04-10 21:41:48 +0000473 SourceLocation Loc = SourceLocation::getFromRawEncoding(Record[1]);
474 bool isUsed = Record[2];
475
476 MacroInfo *MI = PP.AllocateMacroInfo(Loc);
477 MI->setIsUsed(isUsed);
478
479 if (RecType == pch::PP_MACRO_FUNCTION_LIKE) {
480 // Decode function-like macro info.
481 bool isC99VarArgs = Record[3];
482 bool isGNUVarArgs = Record[4];
483 MacroArgs.clear();
484 unsigned NumArgs = Record[5];
485 for (unsigned i = 0; i != NumArgs; ++i)
Chris Lattner29241862009-04-11 21:15:38 +0000486 MacroArgs.push_back(DecodeIdentifierInfo(Record[6+i]));
Chris Lattnerdb1c81b2009-04-10 21:41:48 +0000487
488 // Install function-like macro info.
489 MI->setIsFunctionLike();
490 if (isC99VarArgs) MI->setIsC99Varargs();
491 if (isGNUVarArgs) MI->setIsGNUVarargs();
492 MI->setArgumentList(&MacroArgs[0], MacroArgs.size(),
493 PP.getPreprocessorAllocator());
494 }
495
496 // Finally, install the macro.
Chris Lattnerdb1c81b2009-04-10 21:41:48 +0000497 PP.setMacroInfo(II, MI);
Chris Lattnerdb1c81b2009-04-10 21:41:48 +0000498
499 // Remember that we saw this macro last so that we add the tokens that
500 // form its body to it.
501 LastMacro = MI;
502 break;
503 }
504
505 case pch::PP_TOKEN: {
506 // If we see a TOKEN before a PP_MACRO_*, then the file is eroneous, just
507 // pretend we didn't see this.
508 if (LastMacro == 0) break;
509
510 Token Tok;
511 Tok.startToken();
512 Tok.setLocation(SourceLocation::getFromRawEncoding(Record[0]));
513 Tok.setLength(Record[1]);
Chris Lattner29241862009-04-11 21:15:38 +0000514 if (IdentifierInfo *II = DecodeIdentifierInfo(Record[2]))
515 Tok.setIdentifierInfo(II);
Chris Lattnerdb1c81b2009-04-10 21:41:48 +0000516 Tok.setKind((tok::TokenKind)Record[3]);
517 Tok.setFlag((Token::TokenFlags)Record[4]);
518 LastMacro->AddTokenToBody(Tok);
519 break;
520 }
521 }
522 }
523}
524
Douglas Gregor179cfb12009-04-10 20:39:37 +0000525PCHReader::PCHReadResult PCHReader::ReadPCHBlock() {
526 if (Stream.EnterSubBlock(pch::PCH_BLOCK_ID)) {
527 Error("Malformed block record");
528 return Failure;
529 }
Douglas Gregorc34897d2009-04-09 22:27:44 +0000530
Chris Lattner29241862009-04-11 21:15:38 +0000531 uint64_t PreprocessorBlockBit = 0;
532
Douglas Gregorc34897d2009-04-09 22:27:44 +0000533 // Read all of the records and blocks for the PCH file.
Douglas Gregorac8f2802009-04-10 17:25:41 +0000534 RecordData Record;
Douglas Gregorc34897d2009-04-09 22:27:44 +0000535 while (!Stream.AtEndOfStream()) {
536 unsigned Code = Stream.ReadCode();
537 if (Code == llvm::bitc::END_BLOCK) {
Chris Lattner29241862009-04-11 21:15:38 +0000538 // If we saw the preprocessor block, read it now.
539 if (PreprocessorBlockBit) {
540 uint64_t SavedPos = Stream.GetCurrentBitNo();
541 Stream.JumpToBit(PreprocessorBlockBit);
542 if (ReadPreprocessorBlock()) {
543 Error("Malformed preprocessor block");
544 return Failure;
545 }
546 Stream.JumpToBit(SavedPos);
547 }
548
Douglas Gregor179cfb12009-04-10 20:39:37 +0000549 if (Stream.ReadBlockEnd()) {
550 Error("Error at end of module block");
551 return Failure;
552 }
Chris Lattner29241862009-04-11 21:15:38 +0000553
Douglas Gregor179cfb12009-04-10 20:39:37 +0000554 return Success;
Douglas Gregorc34897d2009-04-09 22:27:44 +0000555 }
556
557 if (Code == llvm::bitc::ENTER_SUBBLOCK) {
558 switch (Stream.ReadSubBlockID()) {
559 case pch::DECLS_BLOCK_ID: // Skip decls block (lazily loaded)
560 case pch::TYPES_BLOCK_ID: // Skip types block (lazily loaded)
561 default: // Skip unknown content.
Douglas Gregor179cfb12009-04-10 20:39:37 +0000562 if (Stream.SkipBlock()) {
563 Error("Malformed block record");
564 return Failure;
565 }
Douglas Gregorc34897d2009-04-09 22:27:44 +0000566 break;
567
Chris Lattner29241862009-04-11 21:15:38 +0000568 case pch::PREPROCESSOR_BLOCK_ID:
569 // Skip the preprocessor block for now, but remember where it is. We
570 // want to read it in after the identifier table.
571 if (PreprocessorBlockBit) {
572 Error("Multiple preprocessor blocks found.");
573 return Failure;
574 }
575 PreprocessorBlockBit = Stream.GetCurrentBitNo();
576 if (Stream.SkipBlock()) {
577 Error("Malformed block record");
578 return Failure;
579 }
580 break;
581
Douglas Gregorab1cef72009-04-10 03:52:48 +0000582 case pch::SOURCE_MANAGER_BLOCK_ID:
Douglas Gregorb3a04c82009-04-10 23:10:45 +0000583 switch (ReadSourceManagerBlock()) {
584 case Success:
585 break;
586
587 case Failure:
Douglas Gregor179cfb12009-04-10 20:39:37 +0000588 Error("Malformed source manager block");
589 return Failure;
Douglas Gregorb3a04c82009-04-10 23:10:45 +0000590
591 case IgnorePCH:
592 return IgnorePCH;
Douglas Gregor179cfb12009-04-10 20:39:37 +0000593 }
Douglas Gregorab1cef72009-04-10 03:52:48 +0000594 break;
Douglas Gregorc34897d2009-04-09 22:27:44 +0000595 }
Douglas Gregorac8f2802009-04-10 17:25:41 +0000596 continue;
597 }
598
599 if (Code == llvm::bitc::DEFINE_ABBREV) {
600 Stream.ReadAbbrevRecord();
601 continue;
602 }
603
604 // Read and process a record.
605 Record.clear();
Douglas Gregorb5887f32009-04-10 21:16:55 +0000606 const char *BlobStart = 0;
607 unsigned BlobLen = 0;
608 switch ((pch::PCHRecordTypes)Stream.ReadRecord(Code, Record,
609 &BlobStart, &BlobLen)) {
Douglas Gregorac8f2802009-04-10 17:25:41 +0000610 default: // Default behavior: ignore.
611 break;
612
613 case pch::TYPE_OFFSET:
Douglas Gregor179cfb12009-04-10 20:39:37 +0000614 if (!TypeOffsets.empty()) {
615 Error("Duplicate TYPE_OFFSET record in PCH file");
616 return Failure;
617 }
Douglas Gregorac8f2802009-04-10 17:25:41 +0000618 TypeOffsets.swap(Record);
619 TypeAlreadyLoaded.resize(TypeOffsets.size(), false);
620 break;
621
622 case pch::DECL_OFFSET:
Douglas Gregor179cfb12009-04-10 20:39:37 +0000623 if (!DeclOffsets.empty()) {
624 Error("Duplicate DECL_OFFSET record in PCH file");
625 return Failure;
626 }
Douglas Gregorac8f2802009-04-10 17:25:41 +0000627 DeclOffsets.swap(Record);
628 DeclAlreadyLoaded.resize(DeclOffsets.size(), false);
629 break;
Douglas Gregor179cfb12009-04-10 20:39:37 +0000630
631 case pch::LANGUAGE_OPTIONS:
632 if (ParseLanguageOptions(Record))
633 return IgnorePCH;
634 break;
Douglas Gregorb5887f32009-04-10 21:16:55 +0000635
Douglas Gregor7a224cf2009-04-11 00:14:32 +0000636 case pch::TARGET_TRIPLE: {
Douglas Gregorb5887f32009-04-10 21:16:55 +0000637 std::string TargetTriple(BlobStart, BlobLen);
638 if (TargetTriple != Context.Target.getTargetTriple()) {
639 Diag(diag::warn_pch_target_triple)
640 << TargetTriple << Context.Target.getTargetTriple();
641 Diag(diag::note_ignoring_pch) << FileName;
642 return IgnorePCH;
643 }
644 break;
Douglas Gregorc34897d2009-04-09 22:27:44 +0000645 }
Douglas Gregor7a224cf2009-04-11 00:14:32 +0000646
647 case pch::IDENTIFIER_TABLE:
648 IdentifierTable = BlobStart;
649 break;
650
651 case pch::IDENTIFIER_OFFSET:
652 if (!IdentifierData.empty()) {
653 Error("Duplicate IDENTIFIER_OFFSET record in PCH file");
654 return Failure;
655 }
656 IdentifierData.swap(Record);
657#ifndef NDEBUG
658 for (unsigned I = 0, N = IdentifierData.size(); I != N; ++I) {
659 if ((IdentifierData[I] & 0x01) == 0) {
660 Error("Malformed identifier table in the precompiled header");
661 return Failure;
662 }
663 }
664#endif
665 break;
666 }
Douglas Gregorc34897d2009-04-09 22:27:44 +0000667 }
668
Douglas Gregor179cfb12009-04-10 20:39:37 +0000669 Error("Premature end of bitstream");
670 return Failure;
Douglas Gregorc34897d2009-04-09 22:27:44 +0000671}
672
Douglas Gregorb3a04c82009-04-10 23:10:45 +0000673PCHReader::PCHReadResult PCHReader::ReadPCH(const std::string &FileName) {
Douglas Gregor179cfb12009-04-10 20:39:37 +0000674 // Set the PCH file name.
675 this->FileName = FileName;
676
Douglas Gregorc34897d2009-04-09 22:27:44 +0000677 // Open the PCH file.
678 std::string ErrStr;
679 Buffer.reset(llvm::MemoryBuffer::getFile(FileName.c_str(), &ErrStr));
Douglas Gregorb3a04c82009-04-10 23:10:45 +0000680 if (!Buffer) {
681 Error(ErrStr.c_str());
682 return IgnorePCH;
683 }
Douglas Gregorc34897d2009-04-09 22:27:44 +0000684
685 // Initialize the stream
686 Stream.init((const unsigned char *)Buffer->getBufferStart(),
687 (const unsigned char *)Buffer->getBufferEnd());
688
689 // Sniff for the signature.
690 if (Stream.Read(8) != 'C' ||
691 Stream.Read(8) != 'P' ||
692 Stream.Read(8) != 'C' ||
Douglas Gregorb3a04c82009-04-10 23:10:45 +0000693 Stream.Read(8) != 'H') {
694 Error("Not a PCH file");
695 return IgnorePCH;
696 }
Douglas Gregorc34897d2009-04-09 22:27:44 +0000697
698 // We expect a number of well-defined blocks, though we don't necessarily
699 // need to understand them all.
700 while (!Stream.AtEndOfStream()) {
701 unsigned Code = Stream.ReadCode();
702
Douglas Gregorb3a04c82009-04-10 23:10:45 +0000703 if (Code != llvm::bitc::ENTER_SUBBLOCK) {
704 Error("Invalid record at top-level");
705 return Failure;
706 }
Douglas Gregorc34897d2009-04-09 22:27:44 +0000707
708 unsigned BlockID = Stream.ReadSubBlockID();
709
710 // We only know the PCH subblock ID.
711 switch (BlockID) {
712 case llvm::bitc::BLOCKINFO_BLOCK_ID:
Douglas Gregorb3a04c82009-04-10 23:10:45 +0000713 if (Stream.ReadBlockInfoBlock()) {
714 Error("Malformed BlockInfoBlock");
715 return Failure;
716 }
Douglas Gregorc34897d2009-04-09 22:27:44 +0000717 break;
718 case pch::PCH_BLOCK_ID:
Douglas Gregor179cfb12009-04-10 20:39:37 +0000719 switch (ReadPCHBlock()) {
720 case Success:
721 break;
722
723 case Failure:
Douglas Gregorb3a04c82009-04-10 23:10:45 +0000724 return Failure;
Douglas Gregor179cfb12009-04-10 20:39:37 +0000725
726 case IgnorePCH:
Douglas Gregorb5887f32009-04-10 21:16:55 +0000727 // FIXME: We could consider reading through to the end of this
728 // PCH block, skipping subblocks, to see if there are other
729 // PCH blocks elsewhere.
Douglas Gregorb3a04c82009-04-10 23:10:45 +0000730 return IgnorePCH;
Douglas Gregor179cfb12009-04-10 20:39:37 +0000731 }
Douglas Gregorc34897d2009-04-09 22:27:44 +0000732 break;
733 default:
Douglas Gregorb3a04c82009-04-10 23:10:45 +0000734 if (Stream.SkipBlock()) {
735 Error("Malformed block record");
736 return Failure;
737 }
Douglas Gregorc34897d2009-04-09 22:27:44 +0000738 break;
739 }
740 }
741
742 // Load the translation unit declaration
743 ReadDeclRecord(DeclOffsets[0], 0);
744
Douglas Gregorb3a04c82009-04-10 23:10:45 +0000745 return Success;
Douglas Gregorc34897d2009-04-09 22:27:44 +0000746}
747
Douglas Gregor179cfb12009-04-10 20:39:37 +0000748/// \brief Parse the record that corresponds to a LangOptions data
749/// structure.
750///
751/// This routine compares the language options used to generate the
752/// PCH file against the language options set for the current
753/// compilation. For each option, we classify differences between the
754/// two compiler states as either "benign" or "important". Benign
755/// differences don't matter, and we accept them without complaint
756/// (and without modifying the language options). Differences between
757/// the states for important options cause the PCH file to be
758/// unusable, so we emit a warning and return true to indicate that
759/// there was an error.
760///
761/// \returns true if the PCH file is unacceptable, false otherwise.
762bool PCHReader::ParseLanguageOptions(
763 const llvm::SmallVectorImpl<uint64_t> &Record) {
764 const LangOptions &LangOpts = Context.getLangOptions();
765#define PARSE_LANGOPT_BENIGN(Option) ++Idx
766#define PARSE_LANGOPT_IMPORTANT(Option, DiagID) \
767 if (Record[Idx] != LangOpts.Option) { \
768 Diag(DiagID) << (unsigned)Record[Idx] << LangOpts.Option; \
769 Diag(diag::note_ignoring_pch) << FileName; \
770 return true; \
771 } \
772 ++Idx
773
774 unsigned Idx = 0;
775 PARSE_LANGOPT_BENIGN(Trigraphs);
776 PARSE_LANGOPT_BENIGN(BCPLComment);
777 PARSE_LANGOPT_BENIGN(DollarIdents);
778 PARSE_LANGOPT_BENIGN(AsmPreprocessor);
779 PARSE_LANGOPT_IMPORTANT(GNUMode, diag::warn_pch_gnu_extensions);
780 PARSE_LANGOPT_BENIGN(ImplicitInt);
781 PARSE_LANGOPT_BENIGN(Digraphs);
782 PARSE_LANGOPT_BENIGN(HexFloats);
783 PARSE_LANGOPT_IMPORTANT(C99, diag::warn_pch_c99);
784 PARSE_LANGOPT_IMPORTANT(Microsoft, diag::warn_pch_microsoft_extensions);
785 PARSE_LANGOPT_IMPORTANT(CPlusPlus, diag::warn_pch_cplusplus);
786 PARSE_LANGOPT_IMPORTANT(CPlusPlus0x, diag::warn_pch_cplusplus0x);
787 PARSE_LANGOPT_IMPORTANT(NoExtensions, diag::warn_pch_extensions);
788 PARSE_LANGOPT_BENIGN(CXXOperatorName);
789 PARSE_LANGOPT_IMPORTANT(ObjC1, diag::warn_pch_objective_c);
790 PARSE_LANGOPT_IMPORTANT(ObjC2, diag::warn_pch_objective_c2);
791 PARSE_LANGOPT_IMPORTANT(ObjCNonFragileABI, diag::warn_pch_nonfragile_abi);
792 PARSE_LANGOPT_BENIGN(PascalStrings);
793 PARSE_LANGOPT_BENIGN(Boolean);
794 PARSE_LANGOPT_BENIGN(WritableStrings);
795 PARSE_LANGOPT_IMPORTANT(LaxVectorConversions,
796 diag::warn_pch_lax_vector_conversions);
797 PARSE_LANGOPT_IMPORTANT(Exceptions, diag::warn_pch_exceptions);
798 PARSE_LANGOPT_IMPORTANT(NeXTRuntime, diag::warn_pch_objc_runtime);
799 PARSE_LANGOPT_IMPORTANT(Freestanding, diag::warn_pch_freestanding);
800 PARSE_LANGOPT_IMPORTANT(NoBuiltin, diag::warn_pch_builtins);
801 PARSE_LANGOPT_IMPORTANT(ThreadsafeStatics,
802 diag::warn_pch_thread_safe_statics);
803 PARSE_LANGOPT_IMPORTANT(Blocks, diag::warn_pch_blocks);
804 PARSE_LANGOPT_BENIGN(EmitAllDecls);
805 PARSE_LANGOPT_IMPORTANT(MathErrno, diag::warn_pch_math_errno);
806 PARSE_LANGOPT_IMPORTANT(OverflowChecking, diag::warn_pch_overflow_checking);
807 PARSE_LANGOPT_IMPORTANT(HeinousExtensions,
808 diag::warn_pch_heinous_extensions);
809 // FIXME: Most of the options below are benign if the macro wasn't
810 // used. Unfortunately, this means that a PCH compiled without
811 // optimization can't be used with optimization turned on, even
812 // though the only thing that changes is whether __OPTIMIZE__ was
813 // defined... but if __OPTIMIZE__ never showed up in the header, it
814 // doesn't matter. We could consider making this some special kind
815 // of check.
816 PARSE_LANGOPT_IMPORTANT(Optimize, diag::warn_pch_optimize);
817 PARSE_LANGOPT_IMPORTANT(OptimizeSize, diag::warn_pch_optimize_size);
818 PARSE_LANGOPT_IMPORTANT(Static, diag::warn_pch_static);
819 PARSE_LANGOPT_IMPORTANT(PICLevel, diag::warn_pch_pic_level);
820 PARSE_LANGOPT_IMPORTANT(GNUInline, diag::warn_pch_gnu_inline);
821 PARSE_LANGOPT_IMPORTANT(NoInline, diag::warn_pch_no_inline);
822 if ((LangOpts.getGCMode() != 0) != (Record[Idx] != 0)) {
823 Diag(diag::warn_pch_gc_mode)
824 << (unsigned)Record[Idx] << LangOpts.getGCMode();
825 Diag(diag::note_ignoring_pch) << FileName;
826 return true;
827 }
828 ++Idx;
829 PARSE_LANGOPT_BENIGN(getVisibilityMode());
830 PARSE_LANGOPT_BENIGN(InstantiationDepth);
831#undef PARSE_LANGOPT_IRRELEVANT
832#undef PARSE_LANGOPT_BENIGN
833
834 return false;
835}
836
Douglas Gregorc34897d2009-04-09 22:27:44 +0000837/// \brief Read and return the type at the given offset.
838///
839/// This routine actually reads the record corresponding to the type
840/// at the given offset in the bitstream. It is a helper routine for
841/// GetType, which deals with reading type IDs.
842QualType PCHReader::ReadTypeRecord(uint64_t Offset) {
843 Stream.JumpToBit(Offset);
844 RecordData Record;
845 unsigned Code = Stream.ReadCode();
846 switch ((pch::TypeCode)Stream.ReadRecord(Code, Record)) {
Douglas Gregor88fd09d2009-04-13 20:46:52 +0000847 case pch::TYPE_EXT_QUAL:
848 // FIXME: Deserialize ExtQualType
849 assert(false && "Cannot deserialize qualified types yet");
850 return QualType();
851
Douglas Gregorc34897d2009-04-09 22:27:44 +0000852 case pch::TYPE_FIXED_WIDTH_INT: {
853 assert(Record.size() == 2 && "Incorrect encoding of fixed-width int type");
854 return Context.getFixedWidthIntType(Record[0], Record[1]);
855 }
856
857 case pch::TYPE_COMPLEX: {
858 assert(Record.size() == 1 && "Incorrect encoding of complex type");
859 QualType ElemType = GetType(Record[0]);
860 return Context.getComplexType(ElemType);
861 }
862
863 case pch::TYPE_POINTER: {
864 assert(Record.size() == 1 && "Incorrect encoding of pointer type");
865 QualType PointeeType = GetType(Record[0]);
866 return Context.getPointerType(PointeeType);
867 }
868
869 case pch::TYPE_BLOCK_POINTER: {
870 assert(Record.size() == 1 && "Incorrect encoding of block pointer type");
871 QualType PointeeType = GetType(Record[0]);
872 return Context.getBlockPointerType(PointeeType);
873 }
874
875 case pch::TYPE_LVALUE_REFERENCE: {
876 assert(Record.size() == 1 && "Incorrect encoding of lvalue reference type");
877 QualType PointeeType = GetType(Record[0]);
878 return Context.getLValueReferenceType(PointeeType);
879 }
880
881 case pch::TYPE_RVALUE_REFERENCE: {
882 assert(Record.size() == 1 && "Incorrect encoding of rvalue reference type");
883 QualType PointeeType = GetType(Record[0]);
884 return Context.getRValueReferenceType(PointeeType);
885 }
886
887 case pch::TYPE_MEMBER_POINTER: {
888 assert(Record.size() == 1 && "Incorrect encoding of member pointer type");
889 QualType PointeeType = GetType(Record[0]);
890 QualType ClassType = GetType(Record[1]);
891 return Context.getMemberPointerType(PointeeType, ClassType.getTypePtr());
892 }
893
Douglas Gregor88fd09d2009-04-13 20:46:52 +0000894 case pch::TYPE_CONSTANT_ARRAY: {
895 QualType ElementType = GetType(Record[0]);
896 ArrayType::ArraySizeModifier ASM = (ArrayType::ArraySizeModifier)Record[1];
897 unsigned IndexTypeQuals = Record[2];
898 unsigned Idx = 3;
899 llvm::APInt Size = ReadAPInt(Record, Idx);
900 return Context.getConstantArrayType(ElementType, Size, ASM, IndexTypeQuals);
901 }
902
903 case pch::TYPE_INCOMPLETE_ARRAY: {
904 QualType ElementType = GetType(Record[0]);
905 ArrayType::ArraySizeModifier ASM = (ArrayType::ArraySizeModifier)Record[1];
906 unsigned IndexTypeQuals = Record[2];
907 return Context.getIncompleteArrayType(ElementType, ASM, IndexTypeQuals);
908 }
909
910 case pch::TYPE_VARIABLE_ARRAY: {
911 // FIXME: implement this
912 assert(false && "Unable to de-serialize variable-length array type");
913 return QualType();
914 }
915
916 case pch::TYPE_VECTOR: {
917 if (Record.size() != 2) {
918 Error("Incorrect encoding of vector type in PCH file");
919 return QualType();
920 }
921
922 QualType ElementType = GetType(Record[0]);
923 unsigned NumElements = Record[1];
924 return Context.getVectorType(ElementType, NumElements);
925 }
926
927 case pch::TYPE_EXT_VECTOR: {
928 if (Record.size() != 2) {
929 Error("Incorrect encoding of extended vector type in PCH file");
930 return QualType();
931 }
932
933 QualType ElementType = GetType(Record[0]);
934 unsigned NumElements = Record[1];
935 return Context.getExtVectorType(ElementType, NumElements);
936 }
937
938 case pch::TYPE_FUNCTION_NO_PROTO: {
939 if (Record.size() != 1) {
940 Error("Incorrect encoding of no-proto function type");
941 return QualType();
942 }
943 QualType ResultType = GetType(Record[0]);
944 return Context.getFunctionNoProtoType(ResultType);
945 }
946
947 case pch::TYPE_FUNCTION_PROTO: {
948 QualType ResultType = GetType(Record[0]);
949 unsigned Idx = 1;
950 unsigned NumParams = Record[Idx++];
951 llvm::SmallVector<QualType, 16> ParamTypes;
952 for (unsigned I = 0; I != NumParams; ++I)
953 ParamTypes.push_back(GetType(Record[Idx++]));
954 bool isVariadic = Record[Idx++];
955 unsigned Quals = Record[Idx++];
956 return Context.getFunctionType(ResultType, &ParamTypes[0], NumParams,
957 isVariadic, Quals);
958 }
959
960 case pch::TYPE_TYPEDEF:
961 assert(Record.size() == 1 && "Incorrect encoding of typedef type");
962 return Context.getTypeDeclType(cast<TypedefDecl>(GetDecl(Record[0])));
963
964 case pch::TYPE_TYPEOF_EXPR:
965 // FIXME: Deserialize TypeOfExprType
966 assert(false && "Cannot de-serialize typeof(expr) from a PCH file");
967 return QualType();
968
969 case pch::TYPE_TYPEOF: {
970 if (Record.size() != 1) {
971 Error("Incorrect encoding of typeof(type) in PCH file");
972 return QualType();
973 }
974 QualType UnderlyingType = GetType(Record[0]);
975 return Context.getTypeOfType(UnderlyingType);
976 }
977
978 case pch::TYPE_RECORD:
Douglas Gregor982365e2009-04-13 21:20:57 +0000979 assert(Record.size() == 1 && "Incorrect encoding of record type");
980 return Context.getTypeDeclType(cast<RecordDecl>(GetDecl(Record[0])));
Douglas Gregor88fd09d2009-04-13 20:46:52 +0000981
Douglas Gregor47f1b2c2009-04-13 18:14:40 +0000982 case pch::TYPE_ENUM:
983 assert(Record.size() == 1 && "Incorrect encoding of enum type");
984 return Context.getTypeDeclType(cast<EnumDecl>(GetDecl(Record[0])));
985
Douglas Gregor88fd09d2009-04-13 20:46:52 +0000986 case pch::TYPE_OBJC_INTERFACE:
987 // FIXME: Deserialize ObjCInterfaceType
988 assert(false && "Cannot de-serialize ObjC interface types yet");
989 return QualType();
990
991 case pch::TYPE_OBJC_QUALIFIED_INTERFACE:
992 // FIXME: Deserialize ObjCQualifiedInterfaceType
993 assert(false && "Cannot de-serialize ObjC qualified interface types yet");
994 return QualType();
995
996 case pch::TYPE_OBJC_QUALIFIED_ID:
997 // FIXME: Deserialize ObjCQualifiedIdType
998 assert(false && "Cannot de-serialize ObjC qualified id types yet");
999 return QualType();
1000
1001 case pch::TYPE_OBJC_QUALIFIED_CLASS:
1002 // FIXME: Deserialize ObjCQualifiedClassType
1003 assert(false && "Cannot de-serialize ObjC qualified class types yet");
1004 return QualType();
Douglas Gregorc34897d2009-04-09 22:27:44 +00001005 }
1006
1007 // Suppress a GCC warning
1008 return QualType();
1009}
1010
1011/// \brief Note that we have loaded the declaration with the given
1012/// Index.
1013///
1014/// This routine notes that this declaration has already been loaded,
1015/// so that future GetDecl calls will return this declaration rather
1016/// than trying to load a new declaration.
1017inline void PCHReader::LoadedDecl(unsigned Index, Decl *D) {
1018 assert(!DeclAlreadyLoaded[Index] && "Decl loaded twice?");
1019 DeclAlreadyLoaded[Index] = true;
1020 DeclOffsets[Index] = reinterpret_cast<uint64_t>(D);
1021}
1022
1023/// \brief Read the declaration at the given offset from the PCH file.
1024Decl *PCHReader::ReadDeclRecord(uint64_t Offset, unsigned Index) {
1025 Decl *D = 0;
1026 Stream.JumpToBit(Offset);
1027 RecordData Record;
1028 unsigned Code = Stream.ReadCode();
1029 unsigned Idx = 0;
1030 PCHDeclReader Reader(*this, Record, Idx);
1031 switch ((pch::DeclCode)Stream.ReadRecord(Code, Record)) {
1032 case pch::DECL_TRANSLATION_UNIT:
1033 assert(Index == 0 && "Translation unit must be at index 0");
1034 Reader.VisitTranslationUnitDecl(Context.getTranslationUnitDecl());
1035 D = Context.getTranslationUnitDecl();
1036 LoadedDecl(Index, D);
1037 break;
1038
1039 case pch::DECL_TYPEDEF: {
1040 TypedefDecl *Typedef = TypedefDecl::Create(Context, 0, SourceLocation(),
1041 0, QualType());
1042 LoadedDecl(Index, Typedef);
1043 Reader.VisitTypedefDecl(Typedef);
1044 D = Typedef;
1045 break;
1046 }
1047
Douglas Gregor47f1b2c2009-04-13 18:14:40 +00001048 case pch::DECL_ENUM: {
1049 EnumDecl *Enum = EnumDecl::Create(Context, 0, SourceLocation(), 0, 0);
1050 LoadedDecl(Index, Enum);
1051 Reader.VisitEnumDecl(Enum);
1052 D = Enum;
1053 break;
1054 }
1055
Douglas Gregor982365e2009-04-13 21:20:57 +00001056 case pch::DECL_RECORD: {
1057 RecordDecl *Record = RecordDecl::Create(Context, TagDecl::TK_struct,
1058 0, SourceLocation(), 0, 0);
1059 LoadedDecl(Index, Record);
1060 Reader.VisitRecordDecl(Record);
1061 D = Record;
1062 break;
1063 }
1064
Douglas Gregor47f1b2c2009-04-13 18:14:40 +00001065 case pch::DECL_ENUM_CONSTANT: {
1066 EnumConstantDecl *ECD = EnumConstantDecl::Create(Context, 0,
1067 SourceLocation(), 0,
1068 QualType(), 0,
1069 llvm::APSInt());
1070 LoadedDecl(Index, ECD);
1071 Reader.VisitEnumConstantDecl(ECD);
1072 D = ECD;
1073 break;
1074 }
Douglas Gregor23ce3a52009-04-13 22:18:37 +00001075
1076 case pch::DECL_FUNCTION: {
1077 FunctionDecl *Function = FunctionDecl::Create(Context, 0, SourceLocation(),
1078 DeclarationName(),
1079 QualType());
1080 LoadedDecl(Index, Function);
1081 Reader.VisitFunctionDecl(Function);
1082 D = Function;
1083 break;
1084 }
Douglas Gregor47f1b2c2009-04-13 18:14:40 +00001085
Douglas Gregor982365e2009-04-13 21:20:57 +00001086 case pch::DECL_FIELD: {
1087 FieldDecl *Field = FieldDecl::Create(Context, 0, SourceLocation(), 0,
1088 QualType(), 0, false);
1089 LoadedDecl(Index, Field);
1090 Reader.VisitFieldDecl(Field);
1091 D = Field;
1092 break;
1093 }
1094
Douglas Gregorc34897d2009-04-09 22:27:44 +00001095 case pch::DECL_VAR: {
1096 VarDecl *Var = VarDecl::Create(Context, 0, SourceLocation(), 0, QualType(),
1097 VarDecl::None, SourceLocation());
1098 LoadedDecl(Index, Var);
1099 Reader.VisitVarDecl(Var);
1100 D = Var;
1101 break;
1102 }
1103
Douglas Gregor23ce3a52009-04-13 22:18:37 +00001104 case pch::DECL_PARM_VAR: {
1105 ParmVarDecl *Parm = ParmVarDecl::Create(Context, 0, SourceLocation(), 0,
1106 QualType(), VarDecl::None, 0);
1107 LoadedDecl(Index, Parm);
1108 Reader.VisitParmVarDecl(Parm);
1109 D = Parm;
1110 break;
1111 }
1112
1113 case pch::DECL_ORIGINAL_PARM_VAR: {
1114 OriginalParmVarDecl *Parm
1115 = OriginalParmVarDecl::Create(Context, 0, SourceLocation(), 0,
1116 QualType(), QualType(), VarDecl::None,
1117 0);
1118 LoadedDecl(Index, Parm);
1119 Reader.VisitOriginalParmVarDecl(Parm);
1120 D = Parm;
1121 break;
1122 }
1123
Douglas Gregor2a491792009-04-13 22:49:25 +00001124 case pch::DECL_FILE_SCOPE_ASM: {
1125 FileScopeAsmDecl *Asm = FileScopeAsmDecl::Create(Context, 0,
1126 SourceLocation(), 0);
1127 LoadedDecl(Index, Asm);
1128 Reader.VisitFileScopeAsmDecl(Asm);
1129 D = Asm;
1130 break;
1131 }
1132
1133 case pch::DECL_BLOCK: {
1134 BlockDecl *Block = BlockDecl::Create(Context, 0, SourceLocation());
1135 LoadedDecl(Index, Block);
1136 Reader.VisitBlockDecl(Block);
1137 D = Block;
1138 break;
1139 }
1140
Douglas Gregorc34897d2009-04-09 22:27:44 +00001141 default:
1142 assert(false && "Cannot de-serialize this kind of declaration");
1143 break;
1144 }
1145
1146 // If this declaration is also a declaration context, get the
1147 // offsets for its tables of lexical and visible declarations.
1148 if (DeclContext *DC = dyn_cast<DeclContext>(D)) {
1149 std::pair<uint64_t, uint64_t> Offsets = Reader.VisitDeclContext(DC);
1150 if (Offsets.first || Offsets.second) {
1151 DC->setHasExternalLexicalStorage(Offsets.first != 0);
1152 DC->setHasExternalVisibleStorage(Offsets.second != 0);
1153 DeclContextOffsets[DC] = Offsets;
1154 }
1155 }
1156 assert(Idx == Record.size());
1157
1158 return D;
1159}
1160
Douglas Gregorac8f2802009-04-10 17:25:41 +00001161QualType PCHReader::GetType(pch::TypeID ID) {
Douglas Gregorc34897d2009-04-09 22:27:44 +00001162 unsigned Quals = ID & 0x07;
1163 unsigned Index = ID >> 3;
1164
1165 if (Index < pch::NUM_PREDEF_TYPE_IDS) {
1166 QualType T;
1167 switch ((pch::PredefinedTypeIDs)Index) {
1168 case pch::PREDEF_TYPE_NULL_ID: return QualType();
1169 case pch::PREDEF_TYPE_VOID_ID: T = Context.VoidTy; break;
1170 case pch::PREDEF_TYPE_BOOL_ID: T = Context.BoolTy; break;
1171
1172 case pch::PREDEF_TYPE_CHAR_U_ID:
1173 case pch::PREDEF_TYPE_CHAR_S_ID:
1174 // FIXME: Check that the signedness of CharTy is correct!
1175 T = Context.CharTy;
1176 break;
1177
1178 case pch::PREDEF_TYPE_UCHAR_ID: T = Context.UnsignedCharTy; break;
1179 case pch::PREDEF_TYPE_USHORT_ID: T = Context.UnsignedShortTy; break;
1180 case pch::PREDEF_TYPE_UINT_ID: T = Context.UnsignedIntTy; break;
1181 case pch::PREDEF_TYPE_ULONG_ID: T = Context.UnsignedLongTy; break;
1182 case pch::PREDEF_TYPE_ULONGLONG_ID: T = Context.UnsignedLongLongTy; break;
1183 case pch::PREDEF_TYPE_SCHAR_ID: T = Context.SignedCharTy; break;
1184 case pch::PREDEF_TYPE_WCHAR_ID: T = Context.WCharTy; break;
1185 case pch::PREDEF_TYPE_SHORT_ID: T = Context.ShortTy; break;
1186 case pch::PREDEF_TYPE_INT_ID: T = Context.IntTy; break;
1187 case pch::PREDEF_TYPE_LONG_ID: T = Context.LongTy; break;
1188 case pch::PREDEF_TYPE_LONGLONG_ID: T = Context.LongLongTy; break;
1189 case pch::PREDEF_TYPE_FLOAT_ID: T = Context.FloatTy; break;
1190 case pch::PREDEF_TYPE_DOUBLE_ID: T = Context.DoubleTy; break;
1191 case pch::PREDEF_TYPE_LONGDOUBLE_ID: T = Context.LongDoubleTy; break;
1192 case pch::PREDEF_TYPE_OVERLOAD_ID: T = Context.OverloadTy; break;
1193 case pch::PREDEF_TYPE_DEPENDENT_ID: T = Context.DependentTy; break;
1194 }
1195
1196 assert(!T.isNull() && "Unknown predefined type");
1197 return T.getQualifiedType(Quals);
1198 }
1199
1200 Index -= pch::NUM_PREDEF_TYPE_IDS;
1201 if (!TypeAlreadyLoaded[Index]) {
1202 // Load the type from the PCH file.
1203 TypeOffsets[Index] = reinterpret_cast<uint64_t>(
1204 ReadTypeRecord(TypeOffsets[Index]).getTypePtr());
1205 TypeAlreadyLoaded[Index] = true;
1206 }
1207
1208 return QualType(reinterpret_cast<Type *>(TypeOffsets[Index]), Quals);
1209}
1210
Douglas Gregorac8f2802009-04-10 17:25:41 +00001211Decl *PCHReader::GetDecl(pch::DeclID ID) {
Douglas Gregorc34897d2009-04-09 22:27:44 +00001212 if (ID == 0)
1213 return 0;
1214
1215 unsigned Index = ID - 1;
1216 if (DeclAlreadyLoaded[Index])
1217 return reinterpret_cast<Decl *>(DeclOffsets[Index]);
1218
1219 // Load the declaration from the PCH file.
1220 return ReadDeclRecord(DeclOffsets[Index], Index);
1221}
1222
1223bool PCHReader::ReadDeclsLexicallyInContext(DeclContext *DC,
Douglas Gregorac8f2802009-04-10 17:25:41 +00001224 llvm::SmallVectorImpl<pch::DeclID> &Decls) {
Douglas Gregorc34897d2009-04-09 22:27:44 +00001225 assert(DC->hasExternalLexicalStorage() &&
1226 "DeclContext has no lexical decls in storage");
1227 uint64_t Offset = DeclContextOffsets[DC].first;
1228 assert(Offset && "DeclContext has no lexical decls in storage");
1229
1230 // Load the record containing all of the declarations lexically in
1231 // this context.
1232 Stream.JumpToBit(Offset);
1233 RecordData Record;
1234 unsigned Code = Stream.ReadCode();
1235 unsigned RecCode = Stream.ReadRecord(Code, Record);
1236 assert(RecCode == pch::DECL_CONTEXT_LEXICAL && "Expected lexical block");
1237
1238 // Load all of the declaration IDs
1239 Decls.clear();
1240 Decls.insert(Decls.end(), Record.begin(), Record.end());
1241 return false;
1242}
1243
1244bool PCHReader::ReadDeclsVisibleInContext(DeclContext *DC,
1245 llvm::SmallVectorImpl<VisibleDeclaration> & Decls) {
1246 assert(DC->hasExternalVisibleStorage() &&
1247 "DeclContext has no visible decls in storage");
1248 uint64_t Offset = DeclContextOffsets[DC].second;
1249 assert(Offset && "DeclContext has no visible decls in storage");
1250
1251 // Load the record containing all of the declarations visible in
1252 // this context.
1253 Stream.JumpToBit(Offset);
1254 RecordData Record;
1255 unsigned Code = Stream.ReadCode();
1256 unsigned RecCode = Stream.ReadRecord(Code, Record);
1257 assert(RecCode == pch::DECL_CONTEXT_VISIBLE && "Expected visible block");
1258 if (Record.size() == 0)
1259 return false;
1260
1261 Decls.clear();
1262
1263 unsigned Idx = 0;
Douglas Gregorc34897d2009-04-09 22:27:44 +00001264 while (Idx < Record.size()) {
1265 Decls.push_back(VisibleDeclaration());
1266 Decls.back().Name = ReadDeclarationName(Record, Idx);
1267
Douglas Gregorc34897d2009-04-09 22:27:44 +00001268 unsigned Size = Record[Idx++];
1269 llvm::SmallVector<unsigned, 4> & LoadedDecls
1270 = Decls.back().Declarations;
1271 LoadedDecls.reserve(Size);
1272 for (unsigned I = 0; I < Size; ++I)
1273 LoadedDecls.push_back(Record[Idx++]);
1274 }
1275
1276 return false;
1277}
1278
1279void PCHReader::PrintStats() {
1280 std::fprintf(stderr, "*** PCH Statistics:\n");
1281
1282 unsigned NumTypesLoaded = std::count(TypeAlreadyLoaded.begin(),
1283 TypeAlreadyLoaded.end(),
1284 true);
1285 unsigned NumDeclsLoaded = std::count(DeclAlreadyLoaded.begin(),
1286 DeclAlreadyLoaded.end(),
1287 true);
Douglas Gregor9cf47422009-04-13 20:50:16 +00001288 unsigned NumIdentifiersLoaded = 0;
1289 for (unsigned I = 0; I < IdentifierData.size(); ++I) {
1290 if ((IdentifierData[I] & 0x01) == 0)
1291 ++NumIdentifiersLoaded;
1292 }
1293
Douglas Gregorc34897d2009-04-09 22:27:44 +00001294 std::fprintf(stderr, " %u/%u types read (%f%%)\n",
1295 NumTypesLoaded, (unsigned)TypeAlreadyLoaded.size(),
Douglas Gregor9cf47422009-04-13 20:50:16 +00001296 ((float)NumTypesLoaded/TypeAlreadyLoaded.size() * 100));
Douglas Gregorc34897d2009-04-09 22:27:44 +00001297 std::fprintf(stderr, " %u/%u declarations read (%f%%)\n",
1298 NumDeclsLoaded, (unsigned)DeclAlreadyLoaded.size(),
Douglas Gregor9cf47422009-04-13 20:50:16 +00001299 ((float)NumDeclsLoaded/DeclAlreadyLoaded.size() * 100));
1300 std::fprintf(stderr, " %u/%u identifiers read (%f%%)\n",
1301 NumIdentifiersLoaded, (unsigned)IdentifierData.size(),
1302 ((float)NumIdentifiersLoaded/IdentifierData.size() * 100));
Douglas Gregorc34897d2009-04-09 22:27:44 +00001303 std::fprintf(stderr, "\n");
1304}
1305
Chris Lattner29241862009-04-11 21:15:38 +00001306IdentifierInfo *PCHReader::DecodeIdentifierInfo(unsigned ID) {
Douglas Gregor7a224cf2009-04-11 00:14:32 +00001307 if (ID == 0)
1308 return 0;
Chris Lattner29241862009-04-11 21:15:38 +00001309
Douglas Gregor7a224cf2009-04-11 00:14:32 +00001310 if (!IdentifierTable || IdentifierData.empty()) {
1311 Error("No identifier table in PCH file");
1312 return 0;
1313 }
Chris Lattner29241862009-04-11 21:15:38 +00001314
Douglas Gregor7a224cf2009-04-11 00:14:32 +00001315 if (IdentifierData[ID - 1] & 0x01) {
1316 uint64_t Offset = IdentifierData[ID - 1];
1317 IdentifierData[ID - 1] = reinterpret_cast<uint64_t>(
Chris Lattner29241862009-04-11 21:15:38 +00001318 &Context.Idents.get(IdentifierTable + Offset));
Douglas Gregor7a224cf2009-04-11 00:14:32 +00001319 }
Chris Lattner29241862009-04-11 21:15:38 +00001320
1321 return reinterpret_cast<IdentifierInfo *>(IdentifierData[ID - 1]);
Douglas Gregorc34897d2009-04-09 22:27:44 +00001322}
1323
1324DeclarationName
1325PCHReader::ReadDeclarationName(const RecordData &Record, unsigned &Idx) {
1326 DeclarationName::NameKind Kind = (DeclarationName::NameKind)Record[Idx++];
1327 switch (Kind) {
1328 case DeclarationName::Identifier:
1329 return DeclarationName(GetIdentifierInfo(Record, Idx));
1330
1331 case DeclarationName::ObjCZeroArgSelector:
1332 case DeclarationName::ObjCOneArgSelector:
1333 case DeclarationName::ObjCMultiArgSelector:
1334 assert(false && "Unable to de-serialize Objective-C selectors");
1335 break;
1336
1337 case DeclarationName::CXXConstructorName:
1338 return Context.DeclarationNames.getCXXConstructorName(
1339 GetType(Record[Idx++]));
1340
1341 case DeclarationName::CXXDestructorName:
1342 return Context.DeclarationNames.getCXXDestructorName(
1343 GetType(Record[Idx++]));
1344
1345 case DeclarationName::CXXConversionFunctionName:
1346 return Context.DeclarationNames.getCXXConversionFunctionName(
1347 GetType(Record[Idx++]));
1348
1349 case DeclarationName::CXXOperatorName:
1350 return Context.DeclarationNames.getCXXOperatorName(
1351 (OverloadedOperatorKind)Record[Idx++]);
1352
1353 case DeclarationName::CXXUsingDirective:
1354 return DeclarationName::getUsingDirectiveName();
1355 }
1356
1357 // Required to silence GCC warning
1358 return DeclarationName();
1359}
Douglas Gregor179cfb12009-04-10 20:39:37 +00001360
Douglas Gregor47f1b2c2009-04-13 18:14:40 +00001361/// \brief Read an integral value
1362llvm::APInt PCHReader::ReadAPInt(const RecordData &Record, unsigned &Idx) {
1363 unsigned BitWidth = Record[Idx++];
1364 unsigned NumWords = llvm::APInt::getNumWords(BitWidth);
1365 llvm::APInt Result(BitWidth, NumWords, &Record[Idx]);
1366 Idx += NumWords;
1367 return Result;
1368}
1369
1370/// \brief Read a signed integral value
1371llvm::APSInt PCHReader::ReadAPSInt(const RecordData &Record, unsigned &Idx) {
1372 bool isUnsigned = Record[Idx++];
1373 return llvm::APSInt(ReadAPInt(Record, Idx), isUnsigned);
1374}
1375
Douglas Gregor179cfb12009-04-10 20:39:37 +00001376DiagnosticBuilder PCHReader::Diag(unsigned DiagID) {
Douglas Gregorb3a04c82009-04-10 23:10:45 +00001377 return Diag(SourceLocation(), DiagID);
1378}
1379
1380DiagnosticBuilder PCHReader::Diag(SourceLocation Loc, unsigned DiagID) {
1381 return PP.getDiagnostics().Report(FullSourceLoc(Loc,
Douglas Gregor179cfb12009-04-10 20:39:37 +00001382 Context.getSourceManager()),
1383 DiagID);
1384}