blob: 96c383b49f31f88bb37ac94f6c45156225082ff7 [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 Gregor631f6c62009-04-14 00:24:19 +000015#include "clang/AST/ASTConsumer.h"
Douglas Gregorc34897d2009-04-09 22:27:44 +000016#include "clang/AST/ASTContext.h"
17#include "clang/AST/Decl.h"
Douglas Gregor631f6c62009-04-14 00:24:19 +000018#include "clang/AST/DeclGroup.h"
Douglas Gregorc10f86f2009-04-14 21:18:50 +000019#include "clang/AST/Expr.h"
20#include "clang/AST/StmtVisitor.h"
Douglas Gregorc34897d2009-04-09 22:27:44 +000021#include "clang/AST/Type.h"
Chris Lattnerdb1c81b2009-04-10 21:41:48 +000022#include "clang/Lex/MacroInfo.h"
Douglas Gregorab1cef72009-04-10 03:52:48 +000023#include "clang/Lex/Preprocessor.h"
24#include "clang/Basic/SourceManager.h"
Douglas Gregor635f97f2009-04-13 16:31:14 +000025#include "clang/Basic/SourceManagerInternals.h"
Douglas Gregorab1cef72009-04-10 03:52:48 +000026#include "clang/Basic/FileManager.h"
Douglas Gregorb5887f32009-04-10 21:16:55 +000027#include "clang/Basic/TargetInfo.h"
Douglas Gregorc34897d2009-04-09 22:27:44 +000028#include "llvm/Bitcode/BitstreamReader.h"
29#include "llvm/Support/Compiler.h"
30#include "llvm/Support/MemoryBuffer.h"
31#include <algorithm>
32#include <cstdio>
33
34using namespace clang;
35
36//===----------------------------------------------------------------------===//
37// Declaration deserialization
38//===----------------------------------------------------------------------===//
39namespace {
40 class VISIBILITY_HIDDEN PCHDeclReader {
41 PCHReader &Reader;
42 const PCHReader::RecordData &Record;
43 unsigned &Idx;
44
45 public:
46 PCHDeclReader(PCHReader &Reader, const PCHReader::RecordData &Record,
47 unsigned &Idx)
48 : Reader(Reader), Record(Record), Idx(Idx) { }
49
50 void VisitDecl(Decl *D);
51 void VisitTranslationUnitDecl(TranslationUnitDecl *TU);
52 void VisitNamedDecl(NamedDecl *ND);
53 void VisitTypeDecl(TypeDecl *TD);
54 void VisitTypedefDecl(TypedefDecl *TD);
Douglas Gregor47f1b2c2009-04-13 18:14:40 +000055 void VisitTagDecl(TagDecl *TD);
56 void VisitEnumDecl(EnumDecl *ED);
Douglas Gregor982365e2009-04-13 21:20:57 +000057 void VisitRecordDecl(RecordDecl *RD);
Douglas Gregorc34897d2009-04-09 22:27:44 +000058 void VisitValueDecl(ValueDecl *VD);
Douglas Gregor47f1b2c2009-04-13 18:14:40 +000059 void VisitEnumConstantDecl(EnumConstantDecl *ECD);
Douglas Gregor23ce3a52009-04-13 22:18:37 +000060 void VisitFunctionDecl(FunctionDecl *FD);
Douglas Gregor982365e2009-04-13 21:20:57 +000061 void VisitFieldDecl(FieldDecl *FD);
Douglas Gregorc34897d2009-04-09 22:27:44 +000062 void VisitVarDecl(VarDecl *VD);
Douglas Gregor23ce3a52009-04-13 22:18:37 +000063 void VisitParmVarDecl(ParmVarDecl *PD);
64 void VisitOriginalParmVarDecl(OriginalParmVarDecl *PD);
Douglas Gregor2a491792009-04-13 22:49:25 +000065 void VisitFileScopeAsmDecl(FileScopeAsmDecl *AD);
66 void VisitBlockDecl(BlockDecl *BD);
Douglas Gregorc34897d2009-04-09 22:27:44 +000067 std::pair<uint64_t, uint64_t> VisitDeclContext(DeclContext *DC);
68 };
69}
70
71void PCHDeclReader::VisitDecl(Decl *D) {
72 D->setDeclContext(cast_or_null<DeclContext>(Reader.GetDecl(Record[Idx++])));
73 D->setLexicalDeclContext(
74 cast_or_null<DeclContext>(Reader.GetDecl(Record[Idx++])));
75 D->setLocation(SourceLocation::getFromRawEncoding(Record[Idx++]));
76 D->setInvalidDecl(Record[Idx++]);
77 // FIXME: hasAttrs
78 D->setImplicit(Record[Idx++]);
79 D->setAccess((AccessSpecifier)Record[Idx++]);
80}
81
82void PCHDeclReader::VisitTranslationUnitDecl(TranslationUnitDecl *TU) {
83 VisitDecl(TU);
84}
85
86void PCHDeclReader::VisitNamedDecl(NamedDecl *ND) {
87 VisitDecl(ND);
88 ND->setDeclName(Reader.ReadDeclarationName(Record, Idx));
89}
90
91void PCHDeclReader::VisitTypeDecl(TypeDecl *TD) {
92 VisitNamedDecl(TD);
Douglas Gregorc34897d2009-04-09 22:27:44 +000093 TD->setTypeForDecl(Reader.GetType(Record[Idx++]).getTypePtr());
94}
95
96void PCHDeclReader::VisitTypedefDecl(TypedefDecl *TD) {
Douglas Gregor88fd09d2009-04-13 20:46:52 +000097 // Note that we cannot use VisitTypeDecl here, because we need to
98 // set the underlying type of the typedef *before* we try to read
99 // the type associated with the TypedefDecl.
100 VisitNamedDecl(TD);
101 TD->setUnderlyingType(Reader.GetType(Record[Idx + 1]));
102 TD->setTypeForDecl(Reader.GetType(Record[Idx]).getTypePtr());
103 Idx += 2;
Douglas Gregorc34897d2009-04-09 22:27:44 +0000104}
105
Douglas Gregor47f1b2c2009-04-13 18:14:40 +0000106void PCHDeclReader::VisitTagDecl(TagDecl *TD) {
107 VisitTypeDecl(TD);
108 TD->setTagKind((TagDecl::TagKind)Record[Idx++]);
109 TD->setDefinition(Record[Idx++]);
110 TD->setTypedefForAnonDecl(
111 cast_or_null<TypedefDecl>(Reader.GetDecl(Record[Idx++])));
112}
113
114void PCHDeclReader::VisitEnumDecl(EnumDecl *ED) {
115 VisitTagDecl(ED);
116 ED->setIntegerType(Reader.GetType(Record[Idx++]));
117}
118
Douglas Gregor982365e2009-04-13 21:20:57 +0000119void PCHDeclReader::VisitRecordDecl(RecordDecl *RD) {
120 VisitTagDecl(RD);
121 RD->setHasFlexibleArrayMember(Record[Idx++]);
122 RD->setAnonymousStructOrUnion(Record[Idx++]);
123}
124
Douglas Gregorc34897d2009-04-09 22:27:44 +0000125void PCHDeclReader::VisitValueDecl(ValueDecl *VD) {
126 VisitNamedDecl(VD);
127 VD->setType(Reader.GetType(Record[Idx++]));
128}
129
Douglas Gregor47f1b2c2009-04-13 18:14:40 +0000130void PCHDeclReader::VisitEnumConstantDecl(EnumConstantDecl *ECD) {
131 VisitValueDecl(ECD);
Douglas Gregorc10f86f2009-04-14 21:18:50 +0000132 if (Record[Idx++])
133 ECD->setInitExpr(Reader.ReadExpr());
Douglas Gregor47f1b2c2009-04-13 18:14:40 +0000134 ECD->setInitVal(Reader.ReadAPSInt(Record, Idx));
135}
136
Douglas Gregor23ce3a52009-04-13 22:18:37 +0000137void PCHDeclReader::VisitFunctionDecl(FunctionDecl *FD) {
138 VisitValueDecl(FD);
139 // FIXME: function body
140 FD->setPreviousDeclaration(
141 cast_or_null<FunctionDecl>(Reader.GetDecl(Record[Idx++])));
142 FD->setStorageClass((FunctionDecl::StorageClass)Record[Idx++]);
143 FD->setInline(Record[Idx++]);
144 FD->setVirtual(Record[Idx++]);
145 FD->setPure(Record[Idx++]);
146 FD->setInheritedPrototype(Record[Idx++]);
147 FD->setHasPrototype(Record[Idx++]);
148 FD->setDeleted(Record[Idx++]);
149 FD->setTypeSpecStartLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
150 unsigned NumParams = Record[Idx++];
151 llvm::SmallVector<ParmVarDecl *, 16> Params;
152 Params.reserve(NumParams);
153 for (unsigned I = 0; I != NumParams; ++I)
154 Params.push_back(cast<ParmVarDecl>(Reader.GetDecl(Record[Idx++])));
155 FD->setParams(Reader.getContext(), &Params[0], NumParams);
156}
157
Douglas Gregor982365e2009-04-13 21:20:57 +0000158void PCHDeclReader::VisitFieldDecl(FieldDecl *FD) {
159 VisitValueDecl(FD);
160 FD->setMutable(Record[Idx++]);
Douglas Gregorc10f86f2009-04-14 21:18:50 +0000161 if (Record[Idx++])
162 FD->setBitWidth(Reader.ReadExpr());
Douglas Gregor982365e2009-04-13 21:20:57 +0000163}
164
Douglas Gregorc34897d2009-04-09 22:27:44 +0000165void PCHDeclReader::VisitVarDecl(VarDecl *VD) {
166 VisitValueDecl(VD);
167 VD->setStorageClass((VarDecl::StorageClass)Record[Idx++]);
168 VD->setThreadSpecified(Record[Idx++]);
169 VD->setCXXDirectInitializer(Record[Idx++]);
170 VD->setDeclaredInCondition(Record[Idx++]);
171 VD->setPreviousDeclaration(
172 cast_or_null<VarDecl>(Reader.GetDecl(Record[Idx++])));
173 VD->setTypeSpecStartLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
Douglas Gregorc10f86f2009-04-14 21:18:50 +0000174 if (Record[Idx++])
175 VD->setInit(Reader.ReadExpr());
Douglas Gregorc34897d2009-04-09 22:27:44 +0000176}
177
Douglas Gregor23ce3a52009-04-13 22:18:37 +0000178void PCHDeclReader::VisitParmVarDecl(ParmVarDecl *PD) {
179 VisitVarDecl(PD);
180 PD->setObjCDeclQualifier((Decl::ObjCDeclQualifier)Record[Idx++]);
181 // FIXME: default argument
182}
183
184void PCHDeclReader::VisitOriginalParmVarDecl(OriginalParmVarDecl *PD) {
185 VisitParmVarDecl(PD);
186 PD->setOriginalType(Reader.GetType(Record[Idx++]));
187}
188
Douglas Gregor2a491792009-04-13 22:49:25 +0000189void PCHDeclReader::VisitFileScopeAsmDecl(FileScopeAsmDecl *AD) {
190 VisitDecl(AD);
191 // FIXME: read asm string
192}
193
194void PCHDeclReader::VisitBlockDecl(BlockDecl *BD) {
195 VisitDecl(BD);
196 unsigned NumParams = Record[Idx++];
197 llvm::SmallVector<ParmVarDecl *, 16> Params;
198 Params.reserve(NumParams);
199 for (unsigned I = 0; I != NumParams; ++I)
200 Params.push_back(cast<ParmVarDecl>(Reader.GetDecl(Record[Idx++])));
201 BD->setParams(Reader.getContext(), &Params[0], NumParams);
202}
203
Douglas Gregorc34897d2009-04-09 22:27:44 +0000204std::pair<uint64_t, uint64_t>
205PCHDeclReader::VisitDeclContext(DeclContext *DC) {
206 uint64_t LexicalOffset = Record[Idx++];
207 uint64_t VisibleOffset = 0;
208 if (DC->getPrimaryContext() == DC)
209 VisibleOffset = Record[Idx++];
210 return std::make_pair(LexicalOffset, VisibleOffset);
211}
212
Douglas Gregorc10f86f2009-04-14 21:18:50 +0000213//===----------------------------------------------------------------------===//
214// Statement/expression deserialization
215//===----------------------------------------------------------------------===//
216namespace {
217 class VISIBILITY_HIDDEN PCHStmtReader
Douglas Gregora151ba42009-04-14 23:32:43 +0000218 : public StmtVisitor<PCHStmtReader, unsigned> {
Douglas Gregorc10f86f2009-04-14 21:18:50 +0000219 PCHReader &Reader;
220 const PCHReader::RecordData &Record;
221 unsigned &Idx;
Douglas Gregora151ba42009-04-14 23:32:43 +0000222 llvm::SmallVectorImpl<Expr *> &ExprStack;
Douglas Gregorc10f86f2009-04-14 21:18:50 +0000223
224 public:
225 PCHStmtReader(PCHReader &Reader, const PCHReader::RecordData &Record,
Douglas Gregora151ba42009-04-14 23:32:43 +0000226 unsigned &Idx, llvm::SmallVectorImpl<Expr *> &ExprStack)
227 : Reader(Reader), Record(Record), Idx(Idx), ExprStack(ExprStack) { }
Douglas Gregorc10f86f2009-04-14 21:18:50 +0000228
Douglas Gregora151ba42009-04-14 23:32:43 +0000229 // Each of the Visit* functions reads in part of the expression
230 // from the given record and the current expression stack, then
231 // return the total number of operands that it read from the
232 // expression stack.
233
234 unsigned VisitExpr(Expr *E);
235 unsigned VisitPredefinedExpr(PredefinedExpr *E);
236 unsigned VisitDeclRefExpr(DeclRefExpr *E);
237 unsigned VisitIntegerLiteral(IntegerLiteral *E);
238 unsigned VisitFloatingLiteral(FloatingLiteral *E);
239 unsigned VisitCharacterLiteral(CharacterLiteral *E);
Douglas Gregor4ea0b1f2009-04-14 23:59:37 +0000240 unsigned VisitParenExpr(ParenExpr *E);
Douglas Gregor12d74052009-04-15 15:58:59 +0000241 unsigned VisitUnaryOperator(UnaryOperator *E);
242 unsigned VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E);
Douglas Gregora151ba42009-04-14 23:32:43 +0000243 unsigned VisitCastExpr(CastExpr *E);
Douglas Gregorc75d0cb2009-04-15 00:25:59 +0000244 unsigned VisitBinaryOperator(BinaryOperator *E);
Douglas Gregora151ba42009-04-14 23:32:43 +0000245 unsigned VisitImplicitCastExpr(ImplicitCastExpr *E);
Douglas Gregorc75d0cb2009-04-15 00:25:59 +0000246 unsigned VisitExplicitCastExpr(ExplicitCastExpr *E);
247 unsigned VisitCStyleCastExpr(CStyleCastExpr *E);
Douglas Gregorc10f86f2009-04-14 21:18:50 +0000248 };
249}
250
Douglas Gregora151ba42009-04-14 23:32:43 +0000251unsigned PCHStmtReader::VisitExpr(Expr *E) {
Douglas Gregorc10f86f2009-04-14 21:18:50 +0000252 E->setType(Reader.GetType(Record[Idx++]));
253 E->setTypeDependent(Record[Idx++]);
254 E->setValueDependent(Record[Idx++]);
Douglas Gregora151ba42009-04-14 23:32:43 +0000255 return 0;
Douglas Gregorc10f86f2009-04-14 21:18:50 +0000256}
257
Douglas Gregora151ba42009-04-14 23:32:43 +0000258unsigned PCHStmtReader::VisitPredefinedExpr(PredefinedExpr *E) {
Douglas Gregore2f37202009-04-14 21:55:33 +0000259 VisitExpr(E);
260 E->setLocation(SourceLocation::getFromRawEncoding(Record[Idx++]));
261 E->setIdentType((PredefinedExpr::IdentType)Record[Idx++]);
Douglas Gregora151ba42009-04-14 23:32:43 +0000262 return 0;
Douglas Gregore2f37202009-04-14 21:55:33 +0000263}
264
Douglas Gregora151ba42009-04-14 23:32:43 +0000265unsigned PCHStmtReader::VisitDeclRefExpr(DeclRefExpr *E) {
Douglas Gregorc10f86f2009-04-14 21:18:50 +0000266 VisitExpr(E);
267 E->setDecl(cast<NamedDecl>(Reader.GetDecl(Record[Idx++])));
268 E->setLocation(SourceLocation::getFromRawEncoding(Record[Idx++]));
Douglas Gregora151ba42009-04-14 23:32:43 +0000269 return 0;
Douglas Gregorc10f86f2009-04-14 21:18:50 +0000270}
271
Douglas Gregora151ba42009-04-14 23:32:43 +0000272unsigned PCHStmtReader::VisitIntegerLiteral(IntegerLiteral *E) {
Douglas Gregorc10f86f2009-04-14 21:18:50 +0000273 VisitExpr(E);
274 E->setLocation(SourceLocation::getFromRawEncoding(Record[Idx++]));
275 E->setValue(Reader.ReadAPInt(Record, Idx));
Douglas Gregora151ba42009-04-14 23:32:43 +0000276 return 0;
Douglas Gregorc10f86f2009-04-14 21:18:50 +0000277}
278
Douglas Gregora151ba42009-04-14 23:32:43 +0000279unsigned PCHStmtReader::VisitFloatingLiteral(FloatingLiteral *E) {
Douglas Gregore2f37202009-04-14 21:55:33 +0000280 VisitExpr(E);
281 E->setValue(Reader.ReadAPFloat(Record, Idx));
282 E->setExact(Record[Idx++]);
283 E->setLocation(SourceLocation::getFromRawEncoding(Record[Idx++]));
Douglas Gregora151ba42009-04-14 23:32:43 +0000284 return 0;
Douglas Gregore2f37202009-04-14 21:55:33 +0000285}
286
Douglas Gregora151ba42009-04-14 23:32:43 +0000287unsigned PCHStmtReader::VisitCharacterLiteral(CharacterLiteral *E) {
Douglas Gregorc10f86f2009-04-14 21:18:50 +0000288 VisitExpr(E);
289 E->setValue(Record[Idx++]);
290 E->setLocation(SourceLocation::getFromRawEncoding(Record[Idx++]));
291 E->setWide(Record[Idx++]);
Douglas Gregora151ba42009-04-14 23:32:43 +0000292 return 0;
293}
294
Douglas Gregor4ea0b1f2009-04-14 23:59:37 +0000295unsigned PCHStmtReader::VisitParenExpr(ParenExpr *E) {
296 VisitExpr(E);
297 E->setLParen(SourceLocation::getFromRawEncoding(Record[Idx++]));
298 E->setRParen(SourceLocation::getFromRawEncoding(Record[Idx++]));
299 E->setSubExpr(ExprStack.back());
300 return 1;
301}
302
Douglas Gregor12d74052009-04-15 15:58:59 +0000303unsigned PCHStmtReader::VisitUnaryOperator(UnaryOperator *E) {
304 VisitExpr(E);
305 E->setSubExpr(ExprStack.back());
306 E->setOpcode((UnaryOperator::Opcode)Record[Idx++]);
307 E->setOperatorLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
308 return 1;
309}
310
311unsigned PCHStmtReader::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E) {
312 VisitExpr(E);
313 E->setSizeof(Record[Idx++]);
314 if (Record[Idx] == 0) {
315 E->setArgument(ExprStack.back());
316 ++Idx;
317 } else {
318 E->setArgument(Reader.GetType(Record[Idx++]));
319 }
320 E->setOperatorLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
321 E->setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
322 return E->isArgumentType()? 0 : 1;
323}
324
Douglas Gregora151ba42009-04-14 23:32:43 +0000325unsigned PCHStmtReader::VisitCastExpr(CastExpr *E) {
326 VisitExpr(E);
327 E->setSubExpr(ExprStack.back());
328 return 1;
329}
330
Douglas Gregorc75d0cb2009-04-15 00:25:59 +0000331unsigned PCHStmtReader::VisitBinaryOperator(BinaryOperator *E) {
332 VisitExpr(E);
333 E->setLHS(ExprStack.end()[-2]);
334 E->setRHS(ExprStack.end()[-1]);
335 E->setOpcode((BinaryOperator::Opcode)Record[Idx++]);
336 E->setOperatorLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
337 return 2;
338}
339
Douglas Gregora151ba42009-04-14 23:32:43 +0000340unsigned PCHStmtReader::VisitImplicitCastExpr(ImplicitCastExpr *E) {
341 VisitCastExpr(E);
342 E->setLvalueCast(Record[Idx++]);
343 return 1;
Douglas Gregorc10f86f2009-04-14 21:18:50 +0000344}
345
Douglas Gregorc75d0cb2009-04-15 00:25:59 +0000346unsigned PCHStmtReader::VisitExplicitCastExpr(ExplicitCastExpr *E) {
347 VisitCastExpr(E);
348 E->setTypeAsWritten(Reader.GetType(Record[Idx++]));
349 return 1;
350}
351
352unsigned PCHStmtReader::VisitCStyleCastExpr(CStyleCastExpr *E) {
353 VisitExplicitCastExpr(E);
354 E->setLParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
355 E->setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
356 return 1;
357}
358
Douglas Gregorc34897d2009-04-09 22:27:44 +0000359// FIXME: use the diagnostics machinery
360static bool Error(const char *Str) {
361 std::fprintf(stderr, "%s\n", Str);
362 return true;
363}
364
Douglas Gregorb3a04c82009-04-10 23:10:45 +0000365/// \brief Check the contents of the predefines buffer against the
366/// contents of the predefines buffer used to build the PCH file.
367///
368/// The contents of the two predefines buffers should be the same. If
369/// not, then some command-line option changed the preprocessor state
370/// and we must reject the PCH file.
371///
372/// \param PCHPredef The start of the predefines buffer in the PCH
373/// file.
374///
375/// \param PCHPredefLen The length of the predefines buffer in the PCH
376/// file.
377///
378/// \param PCHBufferID The FileID for the PCH predefines buffer.
379///
380/// \returns true if there was a mismatch (in which case the PCH file
381/// should be ignored), or false otherwise.
382bool PCHReader::CheckPredefinesBuffer(const char *PCHPredef,
383 unsigned PCHPredefLen,
384 FileID PCHBufferID) {
385 const char *Predef = PP.getPredefines().c_str();
386 unsigned PredefLen = PP.getPredefines().size();
387
388 // If the two predefines buffers compare equal, we're done!.
389 if (PredefLen == PCHPredefLen &&
390 strncmp(Predef, PCHPredef, PCHPredefLen) == 0)
391 return false;
392
393 // The predefines buffers are different. Produce a reasonable
394 // diagnostic showing where they are different.
395
396 // The source locations (potentially in the two different predefines
397 // buffers)
398 SourceLocation Loc1, Loc2;
399 SourceManager &SourceMgr = PP.getSourceManager();
400
401 // Create a source buffer for our predefines string, so
402 // that we can build a diagnostic that points into that
403 // source buffer.
404 FileID BufferID;
405 if (Predef && Predef[0]) {
406 llvm::MemoryBuffer *Buffer
407 = llvm::MemoryBuffer::getMemBuffer(Predef, Predef + PredefLen,
408 "<built-in>");
409 BufferID = SourceMgr.createFileIDForMemBuffer(Buffer);
410 }
411
412 unsigned MinLen = std::min(PredefLen, PCHPredefLen);
413 std::pair<const char *, const char *> Locations
414 = std::mismatch(Predef, Predef + MinLen, PCHPredef);
415
416 if (Locations.first != Predef + MinLen) {
417 // We found the location in the two buffers where there is a
418 // difference. Form source locations to point there (in both
419 // buffers).
420 unsigned Offset = Locations.first - Predef;
421 Loc1 = SourceMgr.getLocForStartOfFile(BufferID)
422 .getFileLocWithOffset(Offset);
423 Loc2 = SourceMgr.getLocForStartOfFile(PCHBufferID)
424 .getFileLocWithOffset(Offset);
425 } else if (PredefLen > PCHPredefLen) {
426 Loc1 = SourceMgr.getLocForStartOfFile(BufferID)
427 .getFileLocWithOffset(MinLen);
428 } else {
429 Loc1 = SourceMgr.getLocForStartOfFile(PCHBufferID)
430 .getFileLocWithOffset(MinLen);
431 }
432
433 Diag(Loc1, diag::warn_pch_preprocessor);
434 if (Loc2.isValid())
435 Diag(Loc2, diag::note_predef_in_pch);
436 Diag(diag::note_ignoring_pch) << FileName;
437 return true;
438}
439
Douglas Gregor635f97f2009-04-13 16:31:14 +0000440/// \brief Read the line table in the source manager block.
441/// \returns true if ther was an error.
442static bool ParseLineTable(SourceManager &SourceMgr,
443 llvm::SmallVectorImpl<uint64_t> &Record) {
444 unsigned Idx = 0;
445 LineTableInfo &LineTable = SourceMgr.getLineTable();
446
447 // Parse the file names
Douglas Gregor183ad602009-04-13 17:12:42 +0000448 std::map<int, int> FileIDs;
449 for (int I = 0, N = Record[Idx++]; I != N; ++I) {
Douglas Gregor635f97f2009-04-13 16:31:14 +0000450 // Extract the file name
451 unsigned FilenameLen = Record[Idx++];
452 std::string Filename(&Record[Idx], &Record[Idx] + FilenameLen);
453 Idx += FilenameLen;
Douglas Gregor183ad602009-04-13 17:12:42 +0000454 FileIDs[I] = LineTable.getLineTableFilenameID(Filename.c_str(),
455 Filename.size());
Douglas Gregor635f97f2009-04-13 16:31:14 +0000456 }
457
458 // Parse the line entries
459 std::vector<LineEntry> Entries;
460 while (Idx < Record.size()) {
Douglas Gregor183ad602009-04-13 17:12:42 +0000461 int FID = FileIDs[Record[Idx++]];
Douglas Gregor635f97f2009-04-13 16:31:14 +0000462
463 // Extract the line entries
464 unsigned NumEntries = Record[Idx++];
465 Entries.clear();
466 Entries.reserve(NumEntries);
467 for (unsigned I = 0; I != NumEntries; ++I) {
468 unsigned FileOffset = Record[Idx++];
469 unsigned LineNo = Record[Idx++];
470 int FilenameID = Record[Idx++];
471 SrcMgr::CharacteristicKind FileKind
472 = (SrcMgr::CharacteristicKind)Record[Idx++];
473 unsigned IncludeOffset = Record[Idx++];
474 Entries.push_back(LineEntry::get(FileOffset, LineNo, FilenameID,
475 FileKind, IncludeOffset));
476 }
477 LineTable.AddEntry(FID, Entries);
478 }
479
480 return false;
481}
482
Douglas Gregorab1cef72009-04-10 03:52:48 +0000483/// \brief Read the source manager block
Douglas Gregorb3a04c82009-04-10 23:10:45 +0000484PCHReader::PCHReadResult PCHReader::ReadSourceManagerBlock() {
Douglas Gregorab1cef72009-04-10 03:52:48 +0000485 using namespace SrcMgr;
Douglas Gregorb3a04c82009-04-10 23:10:45 +0000486 if (Stream.EnterSubBlock(pch::SOURCE_MANAGER_BLOCK_ID)) {
487 Error("Malformed source manager block record");
488 return Failure;
489 }
Douglas Gregorab1cef72009-04-10 03:52:48 +0000490
491 SourceManager &SourceMgr = Context.getSourceManager();
492 RecordData Record;
493 while (true) {
494 unsigned Code = Stream.ReadCode();
495 if (Code == llvm::bitc::END_BLOCK) {
Douglas Gregorb3a04c82009-04-10 23:10:45 +0000496 if (Stream.ReadBlockEnd()) {
497 Error("Error at end of Source Manager block");
498 return Failure;
499 }
500
501 return Success;
Douglas Gregorab1cef72009-04-10 03:52:48 +0000502 }
503
504 if (Code == llvm::bitc::ENTER_SUBBLOCK) {
505 // No known subblocks, always skip them.
506 Stream.ReadSubBlockID();
Douglas Gregorb3a04c82009-04-10 23:10:45 +0000507 if (Stream.SkipBlock()) {
508 Error("Malformed block record");
509 return Failure;
510 }
Douglas Gregorab1cef72009-04-10 03:52:48 +0000511 continue;
512 }
513
514 if (Code == llvm::bitc::DEFINE_ABBREV) {
515 Stream.ReadAbbrevRecord();
516 continue;
517 }
518
519 // Read a record.
520 const char *BlobStart;
521 unsigned BlobLen;
522 Record.clear();
523 switch (Stream.ReadRecord(Code, Record, &BlobStart, &BlobLen)) {
524 default: // Default behavior: ignore.
525 break;
526
527 case pch::SM_SLOC_FILE_ENTRY: {
528 // FIXME: We would really like to delay the creation of this
529 // FileEntry until it is actually required, e.g., when producing
530 // a diagnostic with a source location in this file.
531 const FileEntry *File
532 = PP.getFileManager().getFile(BlobStart, BlobStart + BlobLen);
533 // FIXME: Error recovery if file cannot be found.
Douglas Gregor635f97f2009-04-13 16:31:14 +0000534 FileID ID = SourceMgr.createFileID(File,
535 SourceLocation::getFromRawEncoding(Record[1]),
536 (CharacteristicKind)Record[2]);
537 if (Record[3])
538 const_cast<SrcMgr::FileInfo&>(SourceMgr.getSLocEntry(ID).getFile())
539 .setHasLineDirectives();
Douglas Gregorab1cef72009-04-10 03:52:48 +0000540 break;
541 }
542
543 case pch::SM_SLOC_BUFFER_ENTRY: {
544 const char *Name = BlobStart;
545 unsigned Code = Stream.ReadCode();
546 Record.clear();
547 unsigned RecCode = Stream.ReadRecord(Code, Record, &BlobStart, &BlobLen);
548 assert(RecCode == pch::SM_SLOC_BUFFER_BLOB && "Ill-formed PCH file");
Douglas Gregorb3a04c82009-04-10 23:10:45 +0000549 llvm::MemoryBuffer *Buffer
550 = llvm::MemoryBuffer::getMemBuffer(BlobStart,
551 BlobStart + BlobLen - 1,
552 Name);
553 FileID BufferID = SourceMgr.createFileIDForMemBuffer(Buffer);
554
555 if (strcmp(Name, "<built-in>") == 0
556 && CheckPredefinesBuffer(BlobStart, BlobLen - 1, BufferID))
557 return IgnorePCH;
Douglas Gregorab1cef72009-04-10 03:52:48 +0000558 break;
559 }
560
561 case pch::SM_SLOC_INSTANTIATION_ENTRY: {
562 SourceLocation SpellingLoc
563 = SourceLocation::getFromRawEncoding(Record[1]);
564 SourceMgr.createInstantiationLoc(
565 SpellingLoc,
566 SourceLocation::getFromRawEncoding(Record[2]),
567 SourceLocation::getFromRawEncoding(Record[3]),
568 Lexer::MeasureTokenLength(SpellingLoc,
Chris Lattnere1be6022009-04-14 23:22:57 +0000569 SourceMgr,
570 PP.getLangOptions()));
Douglas Gregorab1cef72009-04-10 03:52:48 +0000571 break;
572 }
573
Chris Lattnere1be6022009-04-14 23:22:57 +0000574 case pch::SM_LINE_TABLE:
Douglas Gregor635f97f2009-04-13 16:31:14 +0000575 if (ParseLineTable(SourceMgr, Record))
576 return Failure;
Chris Lattnere1be6022009-04-14 23:22:57 +0000577 break;
Douglas Gregorab1cef72009-04-10 03:52:48 +0000578 }
579 }
580}
581
Chris Lattnerdb1c81b2009-04-10 21:41:48 +0000582bool PCHReader::ReadPreprocessorBlock() {
583 if (Stream.EnterSubBlock(pch::PREPROCESSOR_BLOCK_ID))
584 return Error("Malformed preprocessor block record");
585
Chris Lattnerdb1c81b2009-04-10 21:41:48 +0000586 RecordData Record;
587 llvm::SmallVector<IdentifierInfo*, 16> MacroArgs;
588 MacroInfo *LastMacro = 0;
589
590 while (true) {
591 unsigned Code = Stream.ReadCode();
592 switch (Code) {
593 case llvm::bitc::END_BLOCK:
594 if (Stream.ReadBlockEnd())
595 return Error("Error at end of preprocessor block");
596 return false;
597
598 case llvm::bitc::ENTER_SUBBLOCK:
599 // No known subblocks, always skip them.
600 Stream.ReadSubBlockID();
601 if (Stream.SkipBlock())
602 return Error("Malformed block record");
603 continue;
604
605 case llvm::bitc::DEFINE_ABBREV:
606 Stream.ReadAbbrevRecord();
607 continue;
608 default: break;
609 }
610
611 // Read a record.
612 Record.clear();
613 pch::PreprocessorRecordTypes RecType =
614 (pch::PreprocessorRecordTypes)Stream.ReadRecord(Code, Record);
615 switch (RecType) {
616 default: // Default behavior: ignore unknown records.
617 break;
Chris Lattner4b21c202009-04-13 01:29:17 +0000618 case pch::PP_COUNTER_VALUE:
619 if (!Record.empty())
620 PP.setCounterValue(Record[0]);
621 break;
622
Chris Lattnerdb1c81b2009-04-10 21:41:48 +0000623 case pch::PP_MACRO_OBJECT_LIKE:
624 case pch::PP_MACRO_FUNCTION_LIKE: {
Chris Lattner29241862009-04-11 21:15:38 +0000625 IdentifierInfo *II = DecodeIdentifierInfo(Record[0]);
626 if (II == 0)
627 return Error("Macro must have a name");
Chris Lattnerdb1c81b2009-04-10 21:41:48 +0000628 SourceLocation Loc = SourceLocation::getFromRawEncoding(Record[1]);
629 bool isUsed = Record[2];
630
631 MacroInfo *MI = PP.AllocateMacroInfo(Loc);
632 MI->setIsUsed(isUsed);
633
634 if (RecType == pch::PP_MACRO_FUNCTION_LIKE) {
635 // Decode function-like macro info.
636 bool isC99VarArgs = Record[3];
637 bool isGNUVarArgs = Record[4];
638 MacroArgs.clear();
639 unsigned NumArgs = Record[5];
640 for (unsigned i = 0; i != NumArgs; ++i)
Chris Lattner29241862009-04-11 21:15:38 +0000641 MacroArgs.push_back(DecodeIdentifierInfo(Record[6+i]));
Chris Lattnerdb1c81b2009-04-10 21:41:48 +0000642
643 // Install function-like macro info.
644 MI->setIsFunctionLike();
645 if (isC99VarArgs) MI->setIsC99Varargs();
646 if (isGNUVarArgs) MI->setIsGNUVarargs();
647 MI->setArgumentList(&MacroArgs[0], MacroArgs.size(),
648 PP.getPreprocessorAllocator());
649 }
650
651 // Finally, install the macro.
Chris Lattnerdb1c81b2009-04-10 21:41:48 +0000652 PP.setMacroInfo(II, MI);
Chris Lattnerdb1c81b2009-04-10 21:41:48 +0000653
654 // Remember that we saw this macro last so that we add the tokens that
655 // form its body to it.
656 LastMacro = MI;
657 break;
658 }
659
660 case pch::PP_TOKEN: {
661 // If we see a TOKEN before a PP_MACRO_*, then the file is eroneous, just
662 // pretend we didn't see this.
663 if (LastMacro == 0) break;
664
665 Token Tok;
666 Tok.startToken();
667 Tok.setLocation(SourceLocation::getFromRawEncoding(Record[0]));
668 Tok.setLength(Record[1]);
Chris Lattner29241862009-04-11 21:15:38 +0000669 if (IdentifierInfo *II = DecodeIdentifierInfo(Record[2]))
670 Tok.setIdentifierInfo(II);
Chris Lattnerdb1c81b2009-04-10 21:41:48 +0000671 Tok.setKind((tok::TokenKind)Record[3]);
672 Tok.setFlag((Token::TokenFlags)Record[4]);
673 LastMacro->AddTokenToBody(Tok);
674 break;
675 }
676 }
677 }
678}
679
Douglas Gregor179cfb12009-04-10 20:39:37 +0000680PCHReader::PCHReadResult PCHReader::ReadPCHBlock() {
681 if (Stream.EnterSubBlock(pch::PCH_BLOCK_ID)) {
682 Error("Malformed block record");
683 return Failure;
684 }
Douglas Gregorc34897d2009-04-09 22:27:44 +0000685
Chris Lattner29241862009-04-11 21:15:38 +0000686 uint64_t PreprocessorBlockBit = 0;
687
Douglas Gregorc34897d2009-04-09 22:27:44 +0000688 // Read all of the records and blocks for the PCH file.
Douglas Gregorac8f2802009-04-10 17:25:41 +0000689 RecordData Record;
Douglas Gregorc34897d2009-04-09 22:27:44 +0000690 while (!Stream.AtEndOfStream()) {
691 unsigned Code = Stream.ReadCode();
692 if (Code == llvm::bitc::END_BLOCK) {
Chris Lattner29241862009-04-11 21:15:38 +0000693 // If we saw the preprocessor block, read it now.
694 if (PreprocessorBlockBit) {
695 uint64_t SavedPos = Stream.GetCurrentBitNo();
696 Stream.JumpToBit(PreprocessorBlockBit);
697 if (ReadPreprocessorBlock()) {
698 Error("Malformed preprocessor block");
699 return Failure;
700 }
701 Stream.JumpToBit(SavedPos);
702 }
703
Douglas Gregor179cfb12009-04-10 20:39:37 +0000704 if (Stream.ReadBlockEnd()) {
705 Error("Error at end of module block");
706 return Failure;
707 }
Chris Lattner29241862009-04-11 21:15:38 +0000708
Douglas Gregor179cfb12009-04-10 20:39:37 +0000709 return Success;
Douglas Gregorc34897d2009-04-09 22:27:44 +0000710 }
711
712 if (Code == llvm::bitc::ENTER_SUBBLOCK) {
713 switch (Stream.ReadSubBlockID()) {
714 case pch::DECLS_BLOCK_ID: // Skip decls block (lazily loaded)
715 case pch::TYPES_BLOCK_ID: // Skip types block (lazily loaded)
716 default: // Skip unknown content.
Douglas Gregor179cfb12009-04-10 20:39:37 +0000717 if (Stream.SkipBlock()) {
718 Error("Malformed block record");
719 return Failure;
720 }
Douglas Gregorc34897d2009-04-09 22:27:44 +0000721 break;
722
Chris Lattner29241862009-04-11 21:15:38 +0000723 case pch::PREPROCESSOR_BLOCK_ID:
724 // Skip the preprocessor block for now, but remember where it is. We
725 // want to read it in after the identifier table.
726 if (PreprocessorBlockBit) {
727 Error("Multiple preprocessor blocks found.");
728 return Failure;
729 }
730 PreprocessorBlockBit = Stream.GetCurrentBitNo();
731 if (Stream.SkipBlock()) {
732 Error("Malformed block record");
733 return Failure;
734 }
735 break;
736
Douglas Gregorab1cef72009-04-10 03:52:48 +0000737 case pch::SOURCE_MANAGER_BLOCK_ID:
Douglas Gregorb3a04c82009-04-10 23:10:45 +0000738 switch (ReadSourceManagerBlock()) {
739 case Success:
740 break;
741
742 case Failure:
Douglas Gregor179cfb12009-04-10 20:39:37 +0000743 Error("Malformed source manager block");
744 return Failure;
Douglas Gregorb3a04c82009-04-10 23:10:45 +0000745
746 case IgnorePCH:
747 return IgnorePCH;
Douglas Gregor179cfb12009-04-10 20:39:37 +0000748 }
Douglas Gregorab1cef72009-04-10 03:52:48 +0000749 break;
Douglas Gregorc34897d2009-04-09 22:27:44 +0000750 }
Douglas Gregorac8f2802009-04-10 17:25:41 +0000751 continue;
752 }
753
754 if (Code == llvm::bitc::DEFINE_ABBREV) {
755 Stream.ReadAbbrevRecord();
756 continue;
757 }
758
759 // Read and process a record.
760 Record.clear();
Douglas Gregorb5887f32009-04-10 21:16:55 +0000761 const char *BlobStart = 0;
762 unsigned BlobLen = 0;
763 switch ((pch::PCHRecordTypes)Stream.ReadRecord(Code, Record,
764 &BlobStart, &BlobLen)) {
Douglas Gregorac8f2802009-04-10 17:25:41 +0000765 default: // Default behavior: ignore.
766 break;
767
768 case pch::TYPE_OFFSET:
Douglas Gregor179cfb12009-04-10 20:39:37 +0000769 if (!TypeOffsets.empty()) {
770 Error("Duplicate TYPE_OFFSET record in PCH file");
771 return Failure;
772 }
Douglas Gregorac8f2802009-04-10 17:25:41 +0000773 TypeOffsets.swap(Record);
774 TypeAlreadyLoaded.resize(TypeOffsets.size(), false);
775 break;
776
777 case pch::DECL_OFFSET:
Douglas Gregor179cfb12009-04-10 20:39:37 +0000778 if (!DeclOffsets.empty()) {
779 Error("Duplicate DECL_OFFSET record in PCH file");
780 return Failure;
781 }
Douglas Gregorac8f2802009-04-10 17:25:41 +0000782 DeclOffsets.swap(Record);
783 DeclAlreadyLoaded.resize(DeclOffsets.size(), false);
784 break;
Douglas Gregor179cfb12009-04-10 20:39:37 +0000785
786 case pch::LANGUAGE_OPTIONS:
787 if (ParseLanguageOptions(Record))
788 return IgnorePCH;
789 break;
Douglas Gregorb5887f32009-04-10 21:16:55 +0000790
Douglas Gregor7a224cf2009-04-11 00:14:32 +0000791 case pch::TARGET_TRIPLE: {
Douglas Gregorb5887f32009-04-10 21:16:55 +0000792 std::string TargetTriple(BlobStart, BlobLen);
793 if (TargetTriple != Context.Target.getTargetTriple()) {
794 Diag(diag::warn_pch_target_triple)
795 << TargetTriple << Context.Target.getTargetTriple();
796 Diag(diag::note_ignoring_pch) << FileName;
797 return IgnorePCH;
798 }
799 break;
Douglas Gregorc34897d2009-04-09 22:27:44 +0000800 }
Douglas Gregor7a224cf2009-04-11 00:14:32 +0000801
802 case pch::IDENTIFIER_TABLE:
803 IdentifierTable = BlobStart;
804 break;
805
806 case pch::IDENTIFIER_OFFSET:
807 if (!IdentifierData.empty()) {
808 Error("Duplicate IDENTIFIER_OFFSET record in PCH file");
809 return Failure;
810 }
811 IdentifierData.swap(Record);
812#ifndef NDEBUG
813 for (unsigned I = 0, N = IdentifierData.size(); I != N; ++I) {
814 if ((IdentifierData[I] & 0x01) == 0) {
815 Error("Malformed identifier table in the precompiled header");
816 return Failure;
817 }
818 }
819#endif
820 break;
Douglas Gregor631f6c62009-04-14 00:24:19 +0000821
822 case pch::EXTERNAL_DEFINITIONS:
823 if (!ExternalDefinitions.empty()) {
824 Error("Duplicate EXTERNAL_DEFINITIONS record in PCH file");
825 return Failure;
826 }
827 ExternalDefinitions.swap(Record);
828 break;
Douglas Gregor7a224cf2009-04-11 00:14:32 +0000829 }
Douglas Gregorc34897d2009-04-09 22:27:44 +0000830 }
831
Douglas Gregor179cfb12009-04-10 20:39:37 +0000832 Error("Premature end of bitstream");
833 return Failure;
Douglas Gregorc34897d2009-04-09 22:27:44 +0000834}
835
Douglas Gregorb3a04c82009-04-10 23:10:45 +0000836PCHReader::PCHReadResult PCHReader::ReadPCH(const std::string &FileName) {
Douglas Gregor179cfb12009-04-10 20:39:37 +0000837 // Set the PCH file name.
838 this->FileName = FileName;
839
Douglas Gregorc34897d2009-04-09 22:27:44 +0000840 // Open the PCH file.
841 std::string ErrStr;
842 Buffer.reset(llvm::MemoryBuffer::getFile(FileName.c_str(), &ErrStr));
Douglas Gregorb3a04c82009-04-10 23:10:45 +0000843 if (!Buffer) {
844 Error(ErrStr.c_str());
845 return IgnorePCH;
846 }
Douglas Gregorc34897d2009-04-09 22:27:44 +0000847
848 // Initialize the stream
849 Stream.init((const unsigned char *)Buffer->getBufferStart(),
850 (const unsigned char *)Buffer->getBufferEnd());
851
852 // Sniff for the signature.
853 if (Stream.Read(8) != 'C' ||
854 Stream.Read(8) != 'P' ||
855 Stream.Read(8) != 'C' ||
Douglas Gregorb3a04c82009-04-10 23:10:45 +0000856 Stream.Read(8) != 'H') {
857 Error("Not a PCH file");
858 return IgnorePCH;
859 }
Douglas Gregorc34897d2009-04-09 22:27:44 +0000860
861 // We expect a number of well-defined blocks, though we don't necessarily
862 // need to understand them all.
863 while (!Stream.AtEndOfStream()) {
864 unsigned Code = Stream.ReadCode();
865
Douglas Gregorb3a04c82009-04-10 23:10:45 +0000866 if (Code != llvm::bitc::ENTER_SUBBLOCK) {
867 Error("Invalid record at top-level");
868 return Failure;
869 }
Douglas Gregorc34897d2009-04-09 22:27:44 +0000870
871 unsigned BlockID = Stream.ReadSubBlockID();
872
873 // We only know the PCH subblock ID.
874 switch (BlockID) {
875 case llvm::bitc::BLOCKINFO_BLOCK_ID:
Douglas Gregorb3a04c82009-04-10 23:10:45 +0000876 if (Stream.ReadBlockInfoBlock()) {
877 Error("Malformed BlockInfoBlock");
878 return Failure;
879 }
Douglas Gregorc34897d2009-04-09 22:27:44 +0000880 break;
881 case pch::PCH_BLOCK_ID:
Douglas Gregor179cfb12009-04-10 20:39:37 +0000882 switch (ReadPCHBlock()) {
883 case Success:
884 break;
885
886 case Failure:
Douglas Gregorb3a04c82009-04-10 23:10:45 +0000887 return Failure;
Douglas Gregor179cfb12009-04-10 20:39:37 +0000888
889 case IgnorePCH:
Douglas Gregorb5887f32009-04-10 21:16:55 +0000890 // FIXME: We could consider reading through to the end of this
891 // PCH block, skipping subblocks, to see if there are other
892 // PCH blocks elsewhere.
Douglas Gregorb3a04c82009-04-10 23:10:45 +0000893 return IgnorePCH;
Douglas Gregor179cfb12009-04-10 20:39:37 +0000894 }
Douglas Gregorc34897d2009-04-09 22:27:44 +0000895 break;
896 default:
Douglas Gregorb3a04c82009-04-10 23:10:45 +0000897 if (Stream.SkipBlock()) {
898 Error("Malformed block record");
899 return Failure;
900 }
Douglas Gregorc34897d2009-04-09 22:27:44 +0000901 break;
902 }
903 }
904
905 // Load the translation unit declaration
906 ReadDeclRecord(DeclOffsets[0], 0);
907
Douglas Gregorb3a04c82009-04-10 23:10:45 +0000908 return Success;
Douglas Gregorc34897d2009-04-09 22:27:44 +0000909}
910
Douglas Gregorc10f86f2009-04-14 21:18:50 +0000911namespace {
912 /// \brief Helper class that saves the current stream position and
913 /// then restores it when destroyed.
914 struct VISIBILITY_HIDDEN SavedStreamPosition {
915 explicit SavedStreamPosition(llvm::BitstreamReader &Stream)
Douglas Gregor6dc849b2009-04-15 04:54:29 +0000916 : Stream(Stream), Offset(Stream.GetCurrentBitNo()) { }
Douglas Gregorc10f86f2009-04-14 21:18:50 +0000917
918 ~SavedStreamPosition() {
Douglas Gregor6dc849b2009-04-15 04:54:29 +0000919 Stream.JumpToBit(Offset);
Douglas Gregorc10f86f2009-04-14 21:18:50 +0000920 }
921
922 private:
923 llvm::BitstreamReader &Stream;
924 uint64_t Offset;
Douglas Gregorc10f86f2009-04-14 21:18:50 +0000925 };
926}
927
Douglas Gregor179cfb12009-04-10 20:39:37 +0000928/// \brief Parse the record that corresponds to a LangOptions data
929/// structure.
930///
931/// This routine compares the language options used to generate the
932/// PCH file against the language options set for the current
933/// compilation. For each option, we classify differences between the
934/// two compiler states as either "benign" or "important". Benign
935/// differences don't matter, and we accept them without complaint
936/// (and without modifying the language options). Differences between
937/// the states for important options cause the PCH file to be
938/// unusable, so we emit a warning and return true to indicate that
939/// there was an error.
940///
941/// \returns true if the PCH file is unacceptable, false otherwise.
942bool PCHReader::ParseLanguageOptions(
943 const llvm::SmallVectorImpl<uint64_t> &Record) {
944 const LangOptions &LangOpts = Context.getLangOptions();
945#define PARSE_LANGOPT_BENIGN(Option) ++Idx
946#define PARSE_LANGOPT_IMPORTANT(Option, DiagID) \
947 if (Record[Idx] != LangOpts.Option) { \
948 Diag(DiagID) << (unsigned)Record[Idx] << LangOpts.Option; \
949 Diag(diag::note_ignoring_pch) << FileName; \
950 return true; \
951 } \
952 ++Idx
953
954 unsigned Idx = 0;
955 PARSE_LANGOPT_BENIGN(Trigraphs);
956 PARSE_LANGOPT_BENIGN(BCPLComment);
957 PARSE_LANGOPT_BENIGN(DollarIdents);
958 PARSE_LANGOPT_BENIGN(AsmPreprocessor);
959 PARSE_LANGOPT_IMPORTANT(GNUMode, diag::warn_pch_gnu_extensions);
960 PARSE_LANGOPT_BENIGN(ImplicitInt);
961 PARSE_LANGOPT_BENIGN(Digraphs);
962 PARSE_LANGOPT_BENIGN(HexFloats);
963 PARSE_LANGOPT_IMPORTANT(C99, diag::warn_pch_c99);
964 PARSE_LANGOPT_IMPORTANT(Microsoft, diag::warn_pch_microsoft_extensions);
965 PARSE_LANGOPT_IMPORTANT(CPlusPlus, diag::warn_pch_cplusplus);
966 PARSE_LANGOPT_IMPORTANT(CPlusPlus0x, diag::warn_pch_cplusplus0x);
967 PARSE_LANGOPT_IMPORTANT(NoExtensions, diag::warn_pch_extensions);
968 PARSE_LANGOPT_BENIGN(CXXOperatorName);
969 PARSE_LANGOPT_IMPORTANT(ObjC1, diag::warn_pch_objective_c);
970 PARSE_LANGOPT_IMPORTANT(ObjC2, diag::warn_pch_objective_c2);
971 PARSE_LANGOPT_IMPORTANT(ObjCNonFragileABI, diag::warn_pch_nonfragile_abi);
972 PARSE_LANGOPT_BENIGN(PascalStrings);
973 PARSE_LANGOPT_BENIGN(Boolean);
974 PARSE_LANGOPT_BENIGN(WritableStrings);
975 PARSE_LANGOPT_IMPORTANT(LaxVectorConversions,
976 diag::warn_pch_lax_vector_conversions);
977 PARSE_LANGOPT_IMPORTANT(Exceptions, diag::warn_pch_exceptions);
978 PARSE_LANGOPT_IMPORTANT(NeXTRuntime, diag::warn_pch_objc_runtime);
979 PARSE_LANGOPT_IMPORTANT(Freestanding, diag::warn_pch_freestanding);
980 PARSE_LANGOPT_IMPORTANT(NoBuiltin, diag::warn_pch_builtins);
981 PARSE_LANGOPT_IMPORTANT(ThreadsafeStatics,
982 diag::warn_pch_thread_safe_statics);
983 PARSE_LANGOPT_IMPORTANT(Blocks, diag::warn_pch_blocks);
984 PARSE_LANGOPT_BENIGN(EmitAllDecls);
985 PARSE_LANGOPT_IMPORTANT(MathErrno, diag::warn_pch_math_errno);
986 PARSE_LANGOPT_IMPORTANT(OverflowChecking, diag::warn_pch_overflow_checking);
987 PARSE_LANGOPT_IMPORTANT(HeinousExtensions,
988 diag::warn_pch_heinous_extensions);
989 // FIXME: Most of the options below are benign if the macro wasn't
990 // used. Unfortunately, this means that a PCH compiled without
991 // optimization can't be used with optimization turned on, even
992 // though the only thing that changes is whether __OPTIMIZE__ was
993 // defined... but if __OPTIMIZE__ never showed up in the header, it
994 // doesn't matter. We could consider making this some special kind
995 // of check.
996 PARSE_LANGOPT_IMPORTANT(Optimize, diag::warn_pch_optimize);
997 PARSE_LANGOPT_IMPORTANT(OptimizeSize, diag::warn_pch_optimize_size);
998 PARSE_LANGOPT_IMPORTANT(Static, diag::warn_pch_static);
999 PARSE_LANGOPT_IMPORTANT(PICLevel, diag::warn_pch_pic_level);
1000 PARSE_LANGOPT_IMPORTANT(GNUInline, diag::warn_pch_gnu_inline);
1001 PARSE_LANGOPT_IMPORTANT(NoInline, diag::warn_pch_no_inline);
1002 if ((LangOpts.getGCMode() != 0) != (Record[Idx] != 0)) {
1003 Diag(diag::warn_pch_gc_mode)
1004 << (unsigned)Record[Idx] << LangOpts.getGCMode();
1005 Diag(diag::note_ignoring_pch) << FileName;
1006 return true;
1007 }
1008 ++Idx;
1009 PARSE_LANGOPT_BENIGN(getVisibilityMode());
1010 PARSE_LANGOPT_BENIGN(InstantiationDepth);
1011#undef PARSE_LANGOPT_IRRELEVANT
1012#undef PARSE_LANGOPT_BENIGN
1013
1014 return false;
1015}
1016
Douglas Gregorc34897d2009-04-09 22:27:44 +00001017/// \brief Read and return the type at the given offset.
1018///
1019/// This routine actually reads the record corresponding to the type
1020/// at the given offset in the bitstream. It is a helper routine for
1021/// GetType, which deals with reading type IDs.
1022QualType PCHReader::ReadTypeRecord(uint64_t Offset) {
Douglas Gregorc10f86f2009-04-14 21:18:50 +00001023 // Keep track of where we are in the stream, then jump back there
1024 // after reading this type.
1025 SavedStreamPosition SavedPosition(Stream);
1026
Douglas Gregorc34897d2009-04-09 22:27:44 +00001027 Stream.JumpToBit(Offset);
1028 RecordData Record;
1029 unsigned Code = Stream.ReadCode();
1030 switch ((pch::TypeCode)Stream.ReadRecord(Code, Record)) {
Douglas Gregor88fd09d2009-04-13 20:46:52 +00001031 case pch::TYPE_EXT_QUAL:
1032 // FIXME: Deserialize ExtQualType
1033 assert(false && "Cannot deserialize qualified types yet");
1034 return QualType();
1035
Douglas Gregorc34897d2009-04-09 22:27:44 +00001036 case pch::TYPE_FIXED_WIDTH_INT: {
1037 assert(Record.size() == 2 && "Incorrect encoding of fixed-width int type");
1038 return Context.getFixedWidthIntType(Record[0], Record[1]);
1039 }
1040
1041 case pch::TYPE_COMPLEX: {
1042 assert(Record.size() == 1 && "Incorrect encoding of complex type");
1043 QualType ElemType = GetType(Record[0]);
1044 return Context.getComplexType(ElemType);
1045 }
1046
1047 case pch::TYPE_POINTER: {
1048 assert(Record.size() == 1 && "Incorrect encoding of pointer type");
1049 QualType PointeeType = GetType(Record[0]);
1050 return Context.getPointerType(PointeeType);
1051 }
1052
1053 case pch::TYPE_BLOCK_POINTER: {
1054 assert(Record.size() == 1 && "Incorrect encoding of block pointer type");
1055 QualType PointeeType = GetType(Record[0]);
1056 return Context.getBlockPointerType(PointeeType);
1057 }
1058
1059 case pch::TYPE_LVALUE_REFERENCE: {
1060 assert(Record.size() == 1 && "Incorrect encoding of lvalue reference type");
1061 QualType PointeeType = GetType(Record[0]);
1062 return Context.getLValueReferenceType(PointeeType);
1063 }
1064
1065 case pch::TYPE_RVALUE_REFERENCE: {
1066 assert(Record.size() == 1 && "Incorrect encoding of rvalue reference type");
1067 QualType PointeeType = GetType(Record[0]);
1068 return Context.getRValueReferenceType(PointeeType);
1069 }
1070
1071 case pch::TYPE_MEMBER_POINTER: {
1072 assert(Record.size() == 1 && "Incorrect encoding of member pointer type");
1073 QualType PointeeType = GetType(Record[0]);
1074 QualType ClassType = GetType(Record[1]);
1075 return Context.getMemberPointerType(PointeeType, ClassType.getTypePtr());
1076 }
1077
Douglas Gregor88fd09d2009-04-13 20:46:52 +00001078 case pch::TYPE_CONSTANT_ARRAY: {
1079 QualType ElementType = GetType(Record[0]);
1080 ArrayType::ArraySizeModifier ASM = (ArrayType::ArraySizeModifier)Record[1];
1081 unsigned IndexTypeQuals = Record[2];
1082 unsigned Idx = 3;
1083 llvm::APInt Size = ReadAPInt(Record, Idx);
1084 return Context.getConstantArrayType(ElementType, Size, ASM, IndexTypeQuals);
1085 }
1086
1087 case pch::TYPE_INCOMPLETE_ARRAY: {
1088 QualType ElementType = GetType(Record[0]);
1089 ArrayType::ArraySizeModifier ASM = (ArrayType::ArraySizeModifier)Record[1];
1090 unsigned IndexTypeQuals = Record[2];
1091 return Context.getIncompleteArrayType(ElementType, ASM, IndexTypeQuals);
1092 }
1093
1094 case pch::TYPE_VARIABLE_ARRAY: {
Douglas Gregorc10f86f2009-04-14 21:18:50 +00001095 QualType ElementType = GetType(Record[0]);
1096 ArrayType::ArraySizeModifier ASM = (ArrayType::ArraySizeModifier)Record[1];
1097 unsigned IndexTypeQuals = Record[2];
1098 return Context.getVariableArrayType(ElementType, ReadExpr(),
1099 ASM, IndexTypeQuals);
Douglas Gregor88fd09d2009-04-13 20:46:52 +00001100 }
1101
1102 case pch::TYPE_VECTOR: {
1103 if (Record.size() != 2) {
1104 Error("Incorrect encoding of vector type in PCH file");
1105 return QualType();
1106 }
1107
1108 QualType ElementType = GetType(Record[0]);
1109 unsigned NumElements = Record[1];
1110 return Context.getVectorType(ElementType, NumElements);
1111 }
1112
1113 case pch::TYPE_EXT_VECTOR: {
1114 if (Record.size() != 2) {
1115 Error("Incorrect encoding of extended vector type in PCH file");
1116 return QualType();
1117 }
1118
1119 QualType ElementType = GetType(Record[0]);
1120 unsigned NumElements = Record[1];
1121 return Context.getExtVectorType(ElementType, NumElements);
1122 }
1123
1124 case pch::TYPE_FUNCTION_NO_PROTO: {
1125 if (Record.size() != 1) {
1126 Error("Incorrect encoding of no-proto function type");
1127 return QualType();
1128 }
1129 QualType ResultType = GetType(Record[0]);
1130 return Context.getFunctionNoProtoType(ResultType);
1131 }
1132
1133 case pch::TYPE_FUNCTION_PROTO: {
1134 QualType ResultType = GetType(Record[0]);
1135 unsigned Idx = 1;
1136 unsigned NumParams = Record[Idx++];
1137 llvm::SmallVector<QualType, 16> ParamTypes;
1138 for (unsigned I = 0; I != NumParams; ++I)
1139 ParamTypes.push_back(GetType(Record[Idx++]));
1140 bool isVariadic = Record[Idx++];
1141 unsigned Quals = Record[Idx++];
1142 return Context.getFunctionType(ResultType, &ParamTypes[0], NumParams,
1143 isVariadic, Quals);
1144 }
1145
1146 case pch::TYPE_TYPEDEF:
1147 assert(Record.size() == 1 && "Incorrect encoding of typedef type");
1148 return Context.getTypeDeclType(cast<TypedefDecl>(GetDecl(Record[0])));
1149
1150 case pch::TYPE_TYPEOF_EXPR:
Douglas Gregorc10f86f2009-04-14 21:18:50 +00001151 return Context.getTypeOfExprType(ReadExpr());
Douglas Gregor88fd09d2009-04-13 20:46:52 +00001152
1153 case pch::TYPE_TYPEOF: {
1154 if (Record.size() != 1) {
1155 Error("Incorrect encoding of typeof(type) in PCH file");
1156 return QualType();
1157 }
1158 QualType UnderlyingType = GetType(Record[0]);
1159 return Context.getTypeOfType(UnderlyingType);
1160 }
1161
1162 case pch::TYPE_RECORD:
Douglas Gregor982365e2009-04-13 21:20:57 +00001163 assert(Record.size() == 1 && "Incorrect encoding of record type");
1164 return Context.getTypeDeclType(cast<RecordDecl>(GetDecl(Record[0])));
Douglas Gregor88fd09d2009-04-13 20:46:52 +00001165
Douglas Gregor47f1b2c2009-04-13 18:14:40 +00001166 case pch::TYPE_ENUM:
1167 assert(Record.size() == 1 && "Incorrect encoding of enum type");
1168 return Context.getTypeDeclType(cast<EnumDecl>(GetDecl(Record[0])));
1169
Douglas Gregor88fd09d2009-04-13 20:46:52 +00001170 case pch::TYPE_OBJC_INTERFACE:
1171 // FIXME: Deserialize ObjCInterfaceType
1172 assert(false && "Cannot de-serialize ObjC interface types yet");
1173 return QualType();
1174
1175 case pch::TYPE_OBJC_QUALIFIED_INTERFACE:
1176 // FIXME: Deserialize ObjCQualifiedInterfaceType
1177 assert(false && "Cannot de-serialize ObjC qualified interface types yet");
1178 return QualType();
1179
1180 case pch::TYPE_OBJC_QUALIFIED_ID:
1181 // FIXME: Deserialize ObjCQualifiedIdType
1182 assert(false && "Cannot de-serialize ObjC qualified id types yet");
1183 return QualType();
1184
1185 case pch::TYPE_OBJC_QUALIFIED_CLASS:
1186 // FIXME: Deserialize ObjCQualifiedClassType
1187 assert(false && "Cannot de-serialize ObjC qualified class types yet");
1188 return QualType();
Douglas Gregorc34897d2009-04-09 22:27:44 +00001189 }
1190
1191 // Suppress a GCC warning
1192 return QualType();
1193}
1194
1195/// \brief Note that we have loaded the declaration with the given
1196/// Index.
1197///
1198/// This routine notes that this declaration has already been loaded,
1199/// so that future GetDecl calls will return this declaration rather
1200/// than trying to load a new declaration.
1201inline void PCHReader::LoadedDecl(unsigned Index, Decl *D) {
1202 assert(!DeclAlreadyLoaded[Index] && "Decl loaded twice?");
1203 DeclAlreadyLoaded[Index] = true;
1204 DeclOffsets[Index] = reinterpret_cast<uint64_t>(D);
1205}
1206
1207/// \brief Read the declaration at the given offset from the PCH file.
1208Decl *PCHReader::ReadDeclRecord(uint64_t Offset, unsigned Index) {
Douglas Gregorc10f86f2009-04-14 21:18:50 +00001209 // Keep track of where we are in the stream, then jump back there
1210 // after reading this declaration.
1211 SavedStreamPosition SavedPosition(Stream);
1212
Douglas Gregorc34897d2009-04-09 22:27:44 +00001213 Decl *D = 0;
1214 Stream.JumpToBit(Offset);
1215 RecordData Record;
1216 unsigned Code = Stream.ReadCode();
1217 unsigned Idx = 0;
1218 PCHDeclReader Reader(*this, Record, Idx);
Douglas Gregorc10f86f2009-04-14 21:18:50 +00001219
Douglas Gregorc34897d2009-04-09 22:27:44 +00001220 switch ((pch::DeclCode)Stream.ReadRecord(Code, Record)) {
1221 case pch::DECL_TRANSLATION_UNIT:
1222 assert(Index == 0 && "Translation unit must be at index 0");
1223 Reader.VisitTranslationUnitDecl(Context.getTranslationUnitDecl());
1224 D = Context.getTranslationUnitDecl();
1225 LoadedDecl(Index, D);
1226 break;
1227
1228 case pch::DECL_TYPEDEF: {
1229 TypedefDecl *Typedef = TypedefDecl::Create(Context, 0, SourceLocation(),
1230 0, QualType());
1231 LoadedDecl(Index, Typedef);
1232 Reader.VisitTypedefDecl(Typedef);
1233 D = Typedef;
1234 break;
1235 }
1236
Douglas Gregor47f1b2c2009-04-13 18:14:40 +00001237 case pch::DECL_ENUM: {
1238 EnumDecl *Enum = EnumDecl::Create(Context, 0, SourceLocation(), 0, 0);
1239 LoadedDecl(Index, Enum);
1240 Reader.VisitEnumDecl(Enum);
1241 D = Enum;
1242 break;
1243 }
1244
Douglas Gregor982365e2009-04-13 21:20:57 +00001245 case pch::DECL_RECORD: {
1246 RecordDecl *Record = RecordDecl::Create(Context, TagDecl::TK_struct,
1247 0, SourceLocation(), 0, 0);
1248 LoadedDecl(Index, Record);
1249 Reader.VisitRecordDecl(Record);
1250 D = Record;
1251 break;
1252 }
1253
Douglas Gregor47f1b2c2009-04-13 18:14:40 +00001254 case pch::DECL_ENUM_CONSTANT: {
1255 EnumConstantDecl *ECD = EnumConstantDecl::Create(Context, 0,
1256 SourceLocation(), 0,
1257 QualType(), 0,
1258 llvm::APSInt());
1259 LoadedDecl(Index, ECD);
1260 Reader.VisitEnumConstantDecl(ECD);
1261 D = ECD;
1262 break;
1263 }
Douglas Gregor23ce3a52009-04-13 22:18:37 +00001264
1265 case pch::DECL_FUNCTION: {
1266 FunctionDecl *Function = FunctionDecl::Create(Context, 0, SourceLocation(),
1267 DeclarationName(),
1268 QualType());
1269 LoadedDecl(Index, Function);
1270 Reader.VisitFunctionDecl(Function);
1271 D = Function;
1272 break;
1273 }
Douglas Gregor47f1b2c2009-04-13 18:14:40 +00001274
Douglas Gregor982365e2009-04-13 21:20:57 +00001275 case pch::DECL_FIELD: {
1276 FieldDecl *Field = FieldDecl::Create(Context, 0, SourceLocation(), 0,
1277 QualType(), 0, false);
1278 LoadedDecl(Index, Field);
1279 Reader.VisitFieldDecl(Field);
1280 D = Field;
1281 break;
1282 }
1283
Douglas Gregorc34897d2009-04-09 22:27:44 +00001284 case pch::DECL_VAR: {
1285 VarDecl *Var = VarDecl::Create(Context, 0, SourceLocation(), 0, QualType(),
1286 VarDecl::None, SourceLocation());
1287 LoadedDecl(Index, Var);
1288 Reader.VisitVarDecl(Var);
1289 D = Var;
1290 break;
1291 }
1292
Douglas Gregor23ce3a52009-04-13 22:18:37 +00001293 case pch::DECL_PARM_VAR: {
1294 ParmVarDecl *Parm = ParmVarDecl::Create(Context, 0, SourceLocation(), 0,
1295 QualType(), VarDecl::None, 0);
1296 LoadedDecl(Index, Parm);
1297 Reader.VisitParmVarDecl(Parm);
1298 D = Parm;
1299 break;
1300 }
1301
1302 case pch::DECL_ORIGINAL_PARM_VAR: {
1303 OriginalParmVarDecl *Parm
1304 = OriginalParmVarDecl::Create(Context, 0, SourceLocation(), 0,
1305 QualType(), QualType(), VarDecl::None,
1306 0);
1307 LoadedDecl(Index, Parm);
1308 Reader.VisitOriginalParmVarDecl(Parm);
1309 D = Parm;
1310 break;
1311 }
1312
Douglas Gregor2a491792009-04-13 22:49:25 +00001313 case pch::DECL_FILE_SCOPE_ASM: {
1314 FileScopeAsmDecl *Asm = FileScopeAsmDecl::Create(Context, 0,
1315 SourceLocation(), 0);
1316 LoadedDecl(Index, Asm);
1317 Reader.VisitFileScopeAsmDecl(Asm);
1318 D = Asm;
1319 break;
1320 }
1321
1322 case pch::DECL_BLOCK: {
1323 BlockDecl *Block = BlockDecl::Create(Context, 0, SourceLocation());
1324 LoadedDecl(Index, Block);
1325 Reader.VisitBlockDecl(Block);
1326 D = Block;
1327 break;
1328 }
1329
Douglas Gregorc34897d2009-04-09 22:27:44 +00001330 default:
1331 assert(false && "Cannot de-serialize this kind of declaration");
1332 break;
1333 }
1334
1335 // If this declaration is also a declaration context, get the
1336 // offsets for its tables of lexical and visible declarations.
1337 if (DeclContext *DC = dyn_cast<DeclContext>(D)) {
1338 std::pair<uint64_t, uint64_t> Offsets = Reader.VisitDeclContext(DC);
1339 if (Offsets.first || Offsets.second) {
1340 DC->setHasExternalLexicalStorage(Offsets.first != 0);
1341 DC->setHasExternalVisibleStorage(Offsets.second != 0);
1342 DeclContextOffsets[DC] = Offsets;
1343 }
1344 }
1345 assert(Idx == Record.size());
1346
1347 return D;
1348}
1349
Douglas Gregorac8f2802009-04-10 17:25:41 +00001350QualType PCHReader::GetType(pch::TypeID ID) {
Douglas Gregorc34897d2009-04-09 22:27:44 +00001351 unsigned Quals = ID & 0x07;
1352 unsigned Index = ID >> 3;
1353
1354 if (Index < pch::NUM_PREDEF_TYPE_IDS) {
1355 QualType T;
1356 switch ((pch::PredefinedTypeIDs)Index) {
1357 case pch::PREDEF_TYPE_NULL_ID: return QualType();
1358 case pch::PREDEF_TYPE_VOID_ID: T = Context.VoidTy; break;
1359 case pch::PREDEF_TYPE_BOOL_ID: T = Context.BoolTy; break;
1360
1361 case pch::PREDEF_TYPE_CHAR_U_ID:
1362 case pch::PREDEF_TYPE_CHAR_S_ID:
1363 // FIXME: Check that the signedness of CharTy is correct!
1364 T = Context.CharTy;
1365 break;
1366
1367 case pch::PREDEF_TYPE_UCHAR_ID: T = Context.UnsignedCharTy; break;
1368 case pch::PREDEF_TYPE_USHORT_ID: T = Context.UnsignedShortTy; break;
1369 case pch::PREDEF_TYPE_UINT_ID: T = Context.UnsignedIntTy; break;
1370 case pch::PREDEF_TYPE_ULONG_ID: T = Context.UnsignedLongTy; break;
1371 case pch::PREDEF_TYPE_ULONGLONG_ID: T = Context.UnsignedLongLongTy; break;
1372 case pch::PREDEF_TYPE_SCHAR_ID: T = Context.SignedCharTy; break;
1373 case pch::PREDEF_TYPE_WCHAR_ID: T = Context.WCharTy; break;
1374 case pch::PREDEF_TYPE_SHORT_ID: T = Context.ShortTy; break;
1375 case pch::PREDEF_TYPE_INT_ID: T = Context.IntTy; break;
1376 case pch::PREDEF_TYPE_LONG_ID: T = Context.LongTy; break;
1377 case pch::PREDEF_TYPE_LONGLONG_ID: T = Context.LongLongTy; break;
1378 case pch::PREDEF_TYPE_FLOAT_ID: T = Context.FloatTy; break;
1379 case pch::PREDEF_TYPE_DOUBLE_ID: T = Context.DoubleTy; break;
1380 case pch::PREDEF_TYPE_LONGDOUBLE_ID: T = Context.LongDoubleTy; break;
1381 case pch::PREDEF_TYPE_OVERLOAD_ID: T = Context.OverloadTy; break;
1382 case pch::PREDEF_TYPE_DEPENDENT_ID: T = Context.DependentTy; break;
1383 }
1384
1385 assert(!T.isNull() && "Unknown predefined type");
1386 return T.getQualifiedType(Quals);
1387 }
1388
1389 Index -= pch::NUM_PREDEF_TYPE_IDS;
1390 if (!TypeAlreadyLoaded[Index]) {
1391 // Load the type from the PCH file.
1392 TypeOffsets[Index] = reinterpret_cast<uint64_t>(
1393 ReadTypeRecord(TypeOffsets[Index]).getTypePtr());
1394 TypeAlreadyLoaded[Index] = true;
1395 }
1396
1397 return QualType(reinterpret_cast<Type *>(TypeOffsets[Index]), Quals);
1398}
1399
Douglas Gregorac8f2802009-04-10 17:25:41 +00001400Decl *PCHReader::GetDecl(pch::DeclID ID) {
Douglas Gregorc34897d2009-04-09 22:27:44 +00001401 if (ID == 0)
1402 return 0;
1403
1404 unsigned Index = ID - 1;
1405 if (DeclAlreadyLoaded[Index])
1406 return reinterpret_cast<Decl *>(DeclOffsets[Index]);
1407
1408 // Load the declaration from the PCH file.
1409 return ReadDeclRecord(DeclOffsets[Index], Index);
1410}
1411
1412bool PCHReader::ReadDeclsLexicallyInContext(DeclContext *DC,
Douglas Gregorac8f2802009-04-10 17:25:41 +00001413 llvm::SmallVectorImpl<pch::DeclID> &Decls) {
Douglas Gregorc34897d2009-04-09 22:27:44 +00001414 assert(DC->hasExternalLexicalStorage() &&
1415 "DeclContext has no lexical decls in storage");
1416 uint64_t Offset = DeclContextOffsets[DC].first;
1417 assert(Offset && "DeclContext has no lexical decls in storage");
1418
Douglas Gregorc10f86f2009-04-14 21:18:50 +00001419 // Keep track of where we are in the stream, then jump back there
1420 // after reading this context.
1421 SavedStreamPosition SavedPosition(Stream);
1422
Douglas Gregorc34897d2009-04-09 22:27:44 +00001423 // Load the record containing all of the declarations lexically in
1424 // this context.
1425 Stream.JumpToBit(Offset);
1426 RecordData Record;
1427 unsigned Code = Stream.ReadCode();
1428 unsigned RecCode = Stream.ReadRecord(Code, Record);
1429 assert(RecCode == pch::DECL_CONTEXT_LEXICAL && "Expected lexical block");
1430
1431 // Load all of the declaration IDs
1432 Decls.clear();
1433 Decls.insert(Decls.end(), Record.begin(), Record.end());
1434 return false;
1435}
1436
1437bool PCHReader::ReadDeclsVisibleInContext(DeclContext *DC,
1438 llvm::SmallVectorImpl<VisibleDeclaration> & Decls) {
1439 assert(DC->hasExternalVisibleStorage() &&
1440 "DeclContext has no visible decls in storage");
1441 uint64_t Offset = DeclContextOffsets[DC].second;
1442 assert(Offset && "DeclContext has no visible decls in storage");
1443
Douglas Gregorc10f86f2009-04-14 21:18:50 +00001444 // Keep track of where we are in the stream, then jump back there
1445 // after reading this context.
1446 SavedStreamPosition SavedPosition(Stream);
1447
Douglas Gregorc34897d2009-04-09 22:27:44 +00001448 // Load the record containing all of the declarations visible in
1449 // this context.
1450 Stream.JumpToBit(Offset);
1451 RecordData Record;
1452 unsigned Code = Stream.ReadCode();
1453 unsigned RecCode = Stream.ReadRecord(Code, Record);
1454 assert(RecCode == pch::DECL_CONTEXT_VISIBLE && "Expected visible block");
1455 if (Record.size() == 0)
1456 return false;
1457
1458 Decls.clear();
1459
1460 unsigned Idx = 0;
Douglas Gregorc34897d2009-04-09 22:27:44 +00001461 while (Idx < Record.size()) {
1462 Decls.push_back(VisibleDeclaration());
1463 Decls.back().Name = ReadDeclarationName(Record, Idx);
1464
Douglas Gregorc34897d2009-04-09 22:27:44 +00001465 unsigned Size = Record[Idx++];
1466 llvm::SmallVector<unsigned, 4> & LoadedDecls
1467 = Decls.back().Declarations;
1468 LoadedDecls.reserve(Size);
1469 for (unsigned I = 0; I < Size; ++I)
1470 LoadedDecls.push_back(Record[Idx++]);
1471 }
1472
1473 return false;
1474}
1475
Douglas Gregor631f6c62009-04-14 00:24:19 +00001476void PCHReader::StartTranslationUnit(ASTConsumer *Consumer) {
1477 if (!Consumer)
1478 return;
1479
1480 for (unsigned I = 0, N = ExternalDefinitions.size(); I != N; ++I) {
1481 Decl *D = GetDecl(ExternalDefinitions[I]);
1482 DeclGroupRef DG(D);
1483 Consumer->HandleTopLevelDecl(DG);
1484 }
1485}
1486
Douglas Gregorc34897d2009-04-09 22:27:44 +00001487void PCHReader::PrintStats() {
1488 std::fprintf(stderr, "*** PCH Statistics:\n");
1489
1490 unsigned NumTypesLoaded = std::count(TypeAlreadyLoaded.begin(),
1491 TypeAlreadyLoaded.end(),
1492 true);
1493 unsigned NumDeclsLoaded = std::count(DeclAlreadyLoaded.begin(),
1494 DeclAlreadyLoaded.end(),
1495 true);
Douglas Gregor9cf47422009-04-13 20:50:16 +00001496 unsigned NumIdentifiersLoaded = 0;
1497 for (unsigned I = 0; I < IdentifierData.size(); ++I) {
1498 if ((IdentifierData[I] & 0x01) == 0)
1499 ++NumIdentifiersLoaded;
1500 }
1501
Douglas Gregorc34897d2009-04-09 22:27:44 +00001502 std::fprintf(stderr, " %u/%u types read (%f%%)\n",
1503 NumTypesLoaded, (unsigned)TypeAlreadyLoaded.size(),
Douglas Gregor9cf47422009-04-13 20:50:16 +00001504 ((float)NumTypesLoaded/TypeAlreadyLoaded.size() * 100));
Douglas Gregorc34897d2009-04-09 22:27:44 +00001505 std::fprintf(stderr, " %u/%u declarations read (%f%%)\n",
1506 NumDeclsLoaded, (unsigned)DeclAlreadyLoaded.size(),
Douglas Gregor9cf47422009-04-13 20:50:16 +00001507 ((float)NumDeclsLoaded/DeclAlreadyLoaded.size() * 100));
1508 std::fprintf(stderr, " %u/%u identifiers read (%f%%)\n",
1509 NumIdentifiersLoaded, (unsigned)IdentifierData.size(),
1510 ((float)NumIdentifiersLoaded/IdentifierData.size() * 100));
Douglas Gregorc34897d2009-04-09 22:27:44 +00001511 std::fprintf(stderr, "\n");
1512}
1513
Chris Lattner29241862009-04-11 21:15:38 +00001514IdentifierInfo *PCHReader::DecodeIdentifierInfo(unsigned ID) {
Douglas Gregor7a224cf2009-04-11 00:14:32 +00001515 if (ID == 0)
1516 return 0;
Chris Lattner29241862009-04-11 21:15:38 +00001517
Douglas Gregor7a224cf2009-04-11 00:14:32 +00001518 if (!IdentifierTable || IdentifierData.empty()) {
1519 Error("No identifier table in PCH file");
1520 return 0;
1521 }
Chris Lattner29241862009-04-11 21:15:38 +00001522
Douglas Gregor7a224cf2009-04-11 00:14:32 +00001523 if (IdentifierData[ID - 1] & 0x01) {
1524 uint64_t Offset = IdentifierData[ID - 1];
1525 IdentifierData[ID - 1] = reinterpret_cast<uint64_t>(
Chris Lattner29241862009-04-11 21:15:38 +00001526 &Context.Idents.get(IdentifierTable + Offset));
Douglas Gregor7a224cf2009-04-11 00:14:32 +00001527 }
Chris Lattner29241862009-04-11 21:15:38 +00001528
1529 return reinterpret_cast<IdentifierInfo *>(IdentifierData[ID - 1]);
Douglas Gregorc34897d2009-04-09 22:27:44 +00001530}
1531
1532DeclarationName
1533PCHReader::ReadDeclarationName(const RecordData &Record, unsigned &Idx) {
1534 DeclarationName::NameKind Kind = (DeclarationName::NameKind)Record[Idx++];
1535 switch (Kind) {
1536 case DeclarationName::Identifier:
1537 return DeclarationName(GetIdentifierInfo(Record, Idx));
1538
1539 case DeclarationName::ObjCZeroArgSelector:
1540 case DeclarationName::ObjCOneArgSelector:
1541 case DeclarationName::ObjCMultiArgSelector:
1542 assert(false && "Unable to de-serialize Objective-C selectors");
1543 break;
1544
1545 case DeclarationName::CXXConstructorName:
1546 return Context.DeclarationNames.getCXXConstructorName(
1547 GetType(Record[Idx++]));
1548
1549 case DeclarationName::CXXDestructorName:
1550 return Context.DeclarationNames.getCXXDestructorName(
1551 GetType(Record[Idx++]));
1552
1553 case DeclarationName::CXXConversionFunctionName:
1554 return Context.DeclarationNames.getCXXConversionFunctionName(
1555 GetType(Record[Idx++]));
1556
1557 case DeclarationName::CXXOperatorName:
1558 return Context.DeclarationNames.getCXXOperatorName(
1559 (OverloadedOperatorKind)Record[Idx++]);
1560
1561 case DeclarationName::CXXUsingDirective:
1562 return DeclarationName::getUsingDirectiveName();
1563 }
1564
1565 // Required to silence GCC warning
1566 return DeclarationName();
1567}
Douglas Gregor179cfb12009-04-10 20:39:37 +00001568
Douglas Gregor47f1b2c2009-04-13 18:14:40 +00001569/// \brief Read an integral value
1570llvm::APInt PCHReader::ReadAPInt(const RecordData &Record, unsigned &Idx) {
1571 unsigned BitWidth = Record[Idx++];
1572 unsigned NumWords = llvm::APInt::getNumWords(BitWidth);
1573 llvm::APInt Result(BitWidth, NumWords, &Record[Idx]);
1574 Idx += NumWords;
1575 return Result;
1576}
1577
1578/// \brief Read a signed integral value
1579llvm::APSInt PCHReader::ReadAPSInt(const RecordData &Record, unsigned &Idx) {
1580 bool isUnsigned = Record[Idx++];
1581 return llvm::APSInt(ReadAPInt(Record, Idx), isUnsigned);
1582}
1583
Douglas Gregore2f37202009-04-14 21:55:33 +00001584/// \brief Read a floating-point value
1585llvm::APFloat PCHReader::ReadAPFloat(const RecordData &Record, unsigned &Idx) {
1586 // FIXME: is this really correct?
1587 return llvm::APFloat(ReadAPInt(Record, Idx));
1588}
1589
Douglas Gregorc10f86f2009-04-14 21:18:50 +00001590Expr *PCHReader::ReadExpr() {
Douglas Gregora151ba42009-04-14 23:32:43 +00001591 // Within the bitstream, expressions are stored in Reverse Polish
1592 // Notation, with each of the subexpressions preceding the
1593 // expression they are stored in. To evaluate expressions, we
1594 // continue reading expressions and placing them on the stack, with
1595 // expressions having operands removing those operands from the
1596 // stack. Evaluation terminates when we see a EXPR_STOP record, and
1597 // the single remaining expression on the stack is our result.
Douglas Gregorc10f86f2009-04-14 21:18:50 +00001598 RecordData Record;
Douglas Gregora151ba42009-04-14 23:32:43 +00001599 unsigned Idx;
1600 llvm::SmallVector<Expr *, 16> ExprStack;
1601 PCHStmtReader Reader(*this, Record, Idx, ExprStack);
Douglas Gregorc10f86f2009-04-14 21:18:50 +00001602 Stmt::EmptyShell Empty;
1603
Douglas Gregora151ba42009-04-14 23:32:43 +00001604 while (true) {
1605 unsigned Code = Stream.ReadCode();
1606 if (Code == llvm::bitc::END_BLOCK) {
1607 if (Stream.ReadBlockEnd()) {
1608 Error("Error at end of Source Manager block");
1609 return 0;
1610 }
1611 break;
1612 }
Douglas Gregorc10f86f2009-04-14 21:18:50 +00001613
Douglas Gregora151ba42009-04-14 23:32:43 +00001614 if (Code == llvm::bitc::ENTER_SUBBLOCK) {
1615 // No known subblocks, always skip them.
1616 Stream.ReadSubBlockID();
1617 if (Stream.SkipBlock()) {
1618 Error("Malformed block record");
1619 return 0;
1620 }
1621 continue;
1622 }
Douglas Gregore2f37202009-04-14 21:55:33 +00001623
Douglas Gregora151ba42009-04-14 23:32:43 +00001624 if (Code == llvm::bitc::DEFINE_ABBREV) {
1625 Stream.ReadAbbrevRecord();
1626 continue;
1627 }
Douglas Gregorc10f86f2009-04-14 21:18:50 +00001628
Douglas Gregora151ba42009-04-14 23:32:43 +00001629 Expr *E = 0;
1630 Idx = 0;
1631 Record.clear();
1632 bool Finished = false;
1633 switch ((pch::StmtCode)Stream.ReadRecord(Code, Record)) {
1634 case pch::EXPR_STOP:
1635 Finished = true;
1636 break;
Douglas Gregorc10f86f2009-04-14 21:18:50 +00001637
Douglas Gregora151ba42009-04-14 23:32:43 +00001638 case pch::EXPR_NULL:
1639 E = 0;
1640 break;
Douglas Gregorc10f86f2009-04-14 21:18:50 +00001641
Douglas Gregora151ba42009-04-14 23:32:43 +00001642 case pch::EXPR_PREDEFINED:
1643 // FIXME: untested (until we can serialize function bodies).
1644 E = new (Context) PredefinedExpr(Empty);
1645 break;
1646
1647 case pch::EXPR_DECL_REF:
1648 E = new (Context) DeclRefExpr(Empty);
1649 break;
1650
1651 case pch::EXPR_INTEGER_LITERAL:
1652 E = new (Context) IntegerLiteral(Empty);
1653 break;
1654
1655 case pch::EXPR_FLOATING_LITERAL:
1656 E = new (Context) FloatingLiteral(Empty);
1657 break;
1658
1659 case pch::EXPR_CHARACTER_LITERAL:
1660 E = new (Context) CharacterLiteral(Empty);
1661 break;
1662
Douglas Gregor4ea0b1f2009-04-14 23:59:37 +00001663 case pch::EXPR_PAREN:
1664 E = new (Context) ParenExpr(Empty);
1665 break;
1666
Douglas Gregor12d74052009-04-15 15:58:59 +00001667 case pch::EXPR_UNARY_OPERATOR:
1668 E = new (Context) UnaryOperator(Empty);
1669 break;
1670
1671 case pch::EXPR_SIZEOF_ALIGN_OF:
1672 E = new (Context) SizeOfAlignOfExpr(Empty);
1673 break;
1674
Douglas Gregorc75d0cb2009-04-15 00:25:59 +00001675 case pch::EXPR_BINARY_OPERATOR:
1676 E = new (Context) BinaryOperator(Empty);
1677 break;
1678
Douglas Gregora151ba42009-04-14 23:32:43 +00001679 case pch::EXPR_IMPLICIT_CAST:
1680 E = new (Context) ImplicitCastExpr(Empty);
1681 break;
Douglas Gregorc75d0cb2009-04-15 00:25:59 +00001682
1683 case pch::EXPR_CSTYLE_CAST:
1684 E = new (Context) CStyleCastExpr(Empty);
1685 break;
Douglas Gregora151ba42009-04-14 23:32:43 +00001686 }
1687
1688 // We hit an EXPR_STOP, so we're done with this expression.
1689 if (Finished)
1690 break;
1691
1692 if (E) {
1693 unsigned NumSubExprs = Reader.Visit(E);
1694 while (NumSubExprs > 0) {
1695 ExprStack.pop_back();
1696 --NumSubExprs;
1697 }
1698 }
1699
1700 assert(Idx == Record.size() && "Invalid deserialization of expression");
1701 ExprStack.push_back(E);
Douglas Gregorc10f86f2009-04-14 21:18:50 +00001702 }
Douglas Gregora151ba42009-04-14 23:32:43 +00001703 assert(ExprStack.size() == 1 && "Extra expressions on stack!");
1704 return ExprStack.back();
Douglas Gregorc10f86f2009-04-14 21:18:50 +00001705}
1706
Douglas Gregor179cfb12009-04-10 20:39:37 +00001707DiagnosticBuilder PCHReader::Diag(unsigned DiagID) {
Douglas Gregorb3a04c82009-04-10 23:10:45 +00001708 return Diag(SourceLocation(), DiagID);
1709}
1710
1711DiagnosticBuilder PCHReader::Diag(SourceLocation Loc, unsigned DiagID) {
1712 return PP.getDiagnostics().Report(FullSourceLoc(Loc,
Douglas Gregor179cfb12009-04-10 20:39:37 +00001713 Context.getSourceManager()),
1714 DiagID);
1715}