blob: 4af13a012ab38c9b33e6fdacc1977269de0cf98a [file] [log] [blame]
Chris Lattner12b1c762009-04-27 06:16:06 +00001//===--- PCHWriterDecl.cpp - Declaration Serialization --------------------===//
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 implements serialization for Declarations.
11//
12//===----------------------------------------------------------------------===//
13
14#include "clang/Frontend/PCHWriter.h"
15#include "clang/AST/DeclVisitor.h"
16#include "clang/AST/Expr.h"
Argyrios Kyrtzidisd4a7e542009-08-19 01:28:35 +000017#include "clang/AST/TypeLoc.h"
Chris Lattner12b1c762009-04-27 06:16:06 +000018#include "llvm/Bitcode/BitstreamWriter.h"
19using namespace clang;
20
21//===----------------------------------------------------------------------===//
22// Declaration serialization
23//===----------------------------------------------------------------------===//
24
25namespace {
26 class PCHDeclWriter : public DeclVisitor<PCHDeclWriter, void> {
27
28 PCHWriter &Writer;
29 ASTContext &Context;
30 PCHWriter::RecordData &Record;
31
32 public:
33 pch::DeclCode Code;
Chris Lattnerea5ce472009-04-27 07:35:58 +000034 unsigned AbbrevToUse;
Chris Lattner12b1c762009-04-27 06:16:06 +000035
36 PCHDeclWriter(PCHWriter &Writer, ASTContext &Context,
37 PCHWriter::RecordData &Record)
Chris Lattnerea5ce472009-04-27 07:35:58 +000038 : Writer(Writer), Context(Context), Record(Record) {
39 }
Chris Lattner12b1c762009-04-27 06:16:06 +000040
41 void VisitDecl(Decl *D);
42 void VisitTranslationUnitDecl(TranslationUnitDecl *D);
43 void VisitNamedDecl(NamedDecl *D);
44 void VisitTypeDecl(TypeDecl *D);
45 void VisitTypedefDecl(TypedefDecl *D);
46 void VisitTagDecl(TagDecl *D);
47 void VisitEnumDecl(EnumDecl *D);
48 void VisitRecordDecl(RecordDecl *D);
49 void VisitValueDecl(ValueDecl *D);
50 void VisitEnumConstantDecl(EnumConstantDecl *D);
Argyrios Kyrtzidisd4a7e542009-08-19 01:28:35 +000051 void VisitDeclaratorDecl(DeclaratorDecl *D);
Chris Lattner12b1c762009-04-27 06:16:06 +000052 void VisitFunctionDecl(FunctionDecl *D);
53 void VisitFieldDecl(FieldDecl *D);
54 void VisitVarDecl(VarDecl *D);
55 void VisitImplicitParamDecl(ImplicitParamDecl *D);
56 void VisitParmVarDecl(ParmVarDecl *D);
57 void VisitOriginalParmVarDecl(OriginalParmVarDecl *D);
58 void VisitFileScopeAsmDecl(FileScopeAsmDecl *D);
59 void VisitBlockDecl(BlockDecl *D);
60 void VisitDeclContext(DeclContext *DC, uint64_t LexicalOffset,
61 uint64_t VisibleOffset);
62 void VisitObjCMethodDecl(ObjCMethodDecl *D);
63 void VisitObjCContainerDecl(ObjCContainerDecl *D);
64 void VisitObjCInterfaceDecl(ObjCInterfaceDecl *D);
65 void VisitObjCIvarDecl(ObjCIvarDecl *D);
66 void VisitObjCProtocolDecl(ObjCProtocolDecl *D);
67 void VisitObjCAtDefsFieldDecl(ObjCAtDefsFieldDecl *D);
68 void VisitObjCClassDecl(ObjCClassDecl *D);
69 void VisitObjCForwardProtocolDecl(ObjCForwardProtocolDecl *D);
70 void VisitObjCCategoryDecl(ObjCCategoryDecl *D);
71 void VisitObjCImplDecl(ObjCImplDecl *D);
72 void VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D);
73 void VisitObjCImplementationDecl(ObjCImplementationDecl *D);
74 void VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *D);
75 void VisitObjCPropertyDecl(ObjCPropertyDecl *D);
76 void VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D);
77 };
78}
79
80void PCHDeclWriter::VisitDecl(Decl *D) {
81 Writer.AddDeclRef(cast_or_null<Decl>(D->getDeclContext()), Record);
82 Writer.AddDeclRef(cast_or_null<Decl>(D->getLexicalDeclContext()), Record);
83 Writer.AddSourceLocation(D->getLocation(), Record);
84 Record.push_back(D->isInvalidDecl());
85 Record.push_back(D->hasAttrs());
86 Record.push_back(D->isImplicit());
Douglas Gregore0762c92009-06-19 23:52:42 +000087 Record.push_back(D->isUsed());
Chris Lattner12b1c762009-04-27 06:16:06 +000088 Record.push_back(D->getAccess());
89}
90
91void PCHDeclWriter::VisitTranslationUnitDecl(TranslationUnitDecl *D) {
92 VisitDecl(D);
93 Code = pch::DECL_TRANSLATION_UNIT;
94}
95
96void PCHDeclWriter::VisitNamedDecl(NamedDecl *D) {
97 VisitDecl(D);
98 Writer.AddDeclarationName(D->getDeclName(), Record);
99}
100
101void PCHDeclWriter::VisitTypeDecl(TypeDecl *D) {
102 VisitNamedDecl(D);
103 Writer.AddTypeRef(QualType(D->getTypeForDecl(), 0), Record);
104}
105
106void PCHDeclWriter::VisitTypedefDecl(TypedefDecl *D) {
107 VisitTypeDecl(D);
108 Writer.AddTypeRef(D->getUnderlyingType(), Record);
109 Code = pch::DECL_TYPEDEF;
110}
111
112void PCHDeclWriter::VisitTagDecl(TagDecl *D) {
113 VisitTypeDecl(D);
Douglas Gregor8e9e9ef2009-07-29 23:36:44 +0000114 Writer.AddDeclRef(D->getPreviousDeclaration(), Record);
Chris Lattner12b1c762009-04-27 06:16:06 +0000115 Record.push_back((unsigned)D->getTagKind()); // FIXME: stable encoding
116 Record.push_back(D->isDefinition());
117 Writer.AddDeclRef(D->getTypedefForAnonDecl(), Record);
Argyrios Kyrtzidisad93a742009-07-14 03:18:02 +0000118 Writer.AddSourceLocation(D->getRBraceLoc(), Record);
Douglas Gregor741dd9a2009-07-21 14:46:17 +0000119 Writer.AddSourceLocation(D->getTagKeywordLoc(), Record);
Chris Lattner12b1c762009-04-27 06:16:06 +0000120}
121
122void PCHDeclWriter::VisitEnumDecl(EnumDecl *D) {
123 VisitTagDecl(D);
124 Writer.AddTypeRef(D->getIntegerType(), Record);
Douglas Gregor8dbc3c62009-05-27 17:20:35 +0000125 // FIXME: C++ InstantiatedFrom
Chris Lattner12b1c762009-04-27 06:16:06 +0000126 Code = pch::DECL_ENUM;
127}
128
129void PCHDeclWriter::VisitRecordDecl(RecordDecl *D) {
130 VisitTagDecl(D);
131 Record.push_back(D->hasFlexibleArrayMember());
132 Record.push_back(D->isAnonymousStructOrUnion());
Fariborz Jahanian643b7df2009-07-08 16:37:44 +0000133 Record.push_back(D->hasObjectMember());
Chris Lattner12b1c762009-04-27 06:16:06 +0000134 Code = pch::DECL_RECORD;
135}
136
137void PCHDeclWriter::VisitValueDecl(ValueDecl *D) {
138 VisitNamedDecl(D);
139 Writer.AddTypeRef(D->getType(), Record);
140}
141
142void PCHDeclWriter::VisitEnumConstantDecl(EnumConstantDecl *D) {
143 VisitValueDecl(D);
144 Record.push_back(D->getInitExpr()? 1 : 0);
145 if (D->getInitExpr())
146 Writer.AddStmt(D->getInitExpr());
147 Writer.AddAPSInt(D->getInitVal(), Record);
148 Code = pch::DECL_ENUM_CONSTANT;
149}
Argyrios Kyrtzidisd4a7e542009-08-19 01:28:35 +0000150namespace {
151
152class TypeLocWriter : public TypeLocVisitor<TypeLocWriter> {
153 PCHWriter &Writer;
154 PCHWriter::RecordData &Record;
155
156public:
157 TypeLocWriter(PCHWriter &Writer, PCHWriter::RecordData &Record)
158 : Writer(Writer), Record(Record) { }
159
160#define ABSTRACT_TYPELOC(CLASS)
161#define TYPELOC(CLASS, PARENT, TYPE) \
162 void Visit##CLASS(CLASS TyLoc);
163#include "clang/AST/TypeLocNodes.def"
164
165 void VisitTypeLoc(TypeLoc TyLoc) {
166 assert(0 && "A type loc wrapper was not handled!");
167 }
168};
169
170}
171
172void TypeLocWriter::VisitDefaultTypeSpecLoc(DefaultTypeSpecLoc TyLoc) {
173 Writer.AddSourceLocation(TyLoc.getStartLoc(), Record);
174}
175void TypeLocWriter::VisitTypedefLoc(TypedefLoc TyLoc) {
176 Writer.AddSourceLocation(TyLoc.getNameLoc(), Record);
177}
178void TypeLocWriter::VisitPointerLoc(PointerLoc TyLoc) {
179 Writer.AddSourceLocation(TyLoc.getStarLoc(), Record);
180}
181void TypeLocWriter::VisitBlockPointerLoc(BlockPointerLoc TyLoc) {
182 Writer.AddSourceLocation(TyLoc.getCaretLoc(), Record);
183}
184void TypeLocWriter::VisitMemberPointerLoc(MemberPointerLoc TyLoc) {
185 Writer.AddSourceLocation(TyLoc.getStarLoc(), Record);
186}
187void TypeLocWriter::VisitReferenceLoc(ReferenceLoc TyLoc) {
188 Writer.AddSourceLocation(TyLoc.getAmpLoc(), Record);
189}
190void TypeLocWriter::VisitFunctionLoc(FunctionLoc TyLoc) {
191 Writer.AddSourceLocation(TyLoc.getLParenLoc(), Record);
192 Writer.AddSourceLocation(TyLoc.getRParenLoc(), Record);
193 for (unsigned i = 0, e = TyLoc.getNumArgs(); i != e; ++i)
194 Writer.AddDeclRef(TyLoc.getArg(i), Record);
195}
196void TypeLocWriter::VisitArrayLoc(ArrayLoc TyLoc) {
197 Writer.AddSourceLocation(TyLoc.getLBracketLoc(), Record);
198 Writer.AddSourceLocation(TyLoc.getRBracketLoc(), Record);
199 Record.push_back(TyLoc.getSizeExpr() ? 1 : 0);
200 if (TyLoc.getSizeExpr())
201 Writer.AddStmt(TyLoc.getSizeExpr());
202}
203
204void PCHDeclWriter::VisitDeclaratorDecl(DeclaratorDecl *D) {
205 VisitValueDecl(D);
206 DeclaratorInfo *DInfo = D->getDeclaratorInfo();
207 if (DInfo == 0) {
208 Writer.AddTypeRef(QualType(), Record);
209 return;
210 }
211
212 Writer.AddTypeRef(DInfo->getTypeLoc().getSourceType(), Record);
213 TypeLocWriter TLW(Writer, Record);
214 for (TypeLoc TL = DInfo->getTypeLoc(); !TL.isNull(); TL = TL.getNextTypeLoc())
215 TLW.Visit(TL);
216}
Chris Lattner12b1c762009-04-27 06:16:06 +0000217
218void PCHDeclWriter::VisitFunctionDecl(FunctionDecl *D) {
Argyrios Kyrtzidisd4a7e542009-08-19 01:28:35 +0000219 VisitDeclaratorDecl(D);
Chris Lattner12b1c762009-04-27 06:16:06 +0000220 Record.push_back(D->isThisDeclarationADefinition());
221 if (D->isThisDeclarationADefinition())
Argyrios Kyrtzidis6fb0aee2009-06-30 02:35:26 +0000222 Writer.AddStmt(D->getBody());
Chris Lattner12b1c762009-04-27 06:16:06 +0000223 Writer.AddDeclRef(D->getPreviousDeclaration(), Record);
224 Record.push_back(D->getStorageClass()); // FIXME: stable encoding
225 Record.push_back(D->isInline());
226 Record.push_back(D->isC99InlineDefinition());
Anders Carlsson77b7f1d2009-05-14 22:15:41 +0000227 Record.push_back(D->isVirtualAsWritten());
Chris Lattner12b1c762009-04-27 06:16:06 +0000228 Record.push_back(D->isPure());
Anders Carlssona75e8532009-05-14 21:46:00 +0000229 Record.push_back(D->hasInheritedPrototype());
230 Record.push_back(D->hasWrittenPrototype());
Chris Lattner12b1c762009-04-27 06:16:06 +0000231 Record.push_back(D->isDeleted());
232 Writer.AddSourceLocation(D->getTypeSpecStartLoc(), Record);
Argyrios Kyrtzidis8cff90e2009-06-20 08:09:34 +0000233 Writer.AddSourceLocation(D->getLocEnd(), Record);
Douglas Gregor1eee0e72009-05-14 21:06:31 +0000234 // FIXME: C++ TemplateOrInstantiation
Chris Lattner12b1c762009-04-27 06:16:06 +0000235 Record.push_back(D->param_size());
236 for (FunctionDecl::param_iterator P = D->param_begin(), PEnd = D->param_end();
237 P != PEnd; ++P)
238 Writer.AddDeclRef(*P, Record);
239 Code = pch::DECL_FUNCTION;
240}
241
242void PCHDeclWriter::VisitObjCMethodDecl(ObjCMethodDecl *D) {
243 VisitNamedDecl(D);
244 // FIXME: convert to LazyStmtPtr?
245 // Unlike C/C++, method bodies will never be in header files.
246 Record.push_back(D->getBody() != 0);
247 if (D->getBody() != 0) {
Argyrios Kyrtzidis6fb0aee2009-06-30 02:35:26 +0000248 Writer.AddStmt(D->getBody());
Chris Lattner12b1c762009-04-27 06:16:06 +0000249 Writer.AddDeclRef(D->getSelfDecl(), Record);
250 Writer.AddDeclRef(D->getCmdDecl(), Record);
251 }
252 Record.push_back(D->isInstanceMethod());
253 Record.push_back(D->isVariadic());
254 Record.push_back(D->isSynthesized());
255 // FIXME: stable encoding for @required/@optional
256 Record.push_back(D->getImplementationControl());
257 // FIXME: stable encoding for in/out/inout/bycopy/byref/oneway
258 Record.push_back(D->getObjCDeclQualifier());
259 Writer.AddTypeRef(D->getResultType(), Record);
260 Writer.AddSourceLocation(D->getLocEnd(), Record);
261 Record.push_back(D->param_size());
262 for (ObjCMethodDecl::param_iterator P = D->param_begin(),
263 PEnd = D->param_end(); P != PEnd; ++P)
264 Writer.AddDeclRef(*P, Record);
265 Code = pch::DECL_OBJC_METHOD;
266}
267
268void PCHDeclWriter::VisitObjCContainerDecl(ObjCContainerDecl *D) {
269 VisitNamedDecl(D);
270 Writer.AddSourceLocation(D->getAtEndLoc(), Record);
271 // Abstract class (no need to define a stable pch::DECL code).
272}
273
274void PCHDeclWriter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) {
275 VisitObjCContainerDecl(D);
276 Writer.AddTypeRef(QualType(D->getTypeForDecl(), 0), Record);
277 Writer.AddDeclRef(D->getSuperClass(), Record);
278 Record.push_back(D->protocol_size());
279 for (ObjCInterfaceDecl::protocol_iterator P = D->protocol_begin(),
280 PEnd = D->protocol_end();
281 P != PEnd; ++P)
282 Writer.AddDeclRef(*P, Record);
283 Record.push_back(D->ivar_size());
284 for (ObjCInterfaceDecl::ivar_iterator I = D->ivar_begin(),
285 IEnd = D->ivar_end(); I != IEnd; ++I)
286 Writer.AddDeclRef(*I, Record);
287 Writer.AddDeclRef(D->getCategoryList(), Record);
288 Record.push_back(D->isForwardDecl());
289 Record.push_back(D->isImplicitInterfaceDecl());
290 Writer.AddSourceLocation(D->getClassLoc(), Record);
291 Writer.AddSourceLocation(D->getSuperClassLoc(), Record);
292 Writer.AddSourceLocation(D->getLocEnd(), Record);
293 Code = pch::DECL_OBJC_INTERFACE;
294}
295
296void PCHDeclWriter::VisitObjCIvarDecl(ObjCIvarDecl *D) {
297 VisitFieldDecl(D);
298 // FIXME: stable encoding for @public/@private/@protected/@package
299 Record.push_back(D->getAccessControl());
300 Code = pch::DECL_OBJC_IVAR;
301}
302
303void PCHDeclWriter::VisitObjCProtocolDecl(ObjCProtocolDecl *D) {
304 VisitObjCContainerDecl(D);
305 Record.push_back(D->isForwardDecl());
306 Writer.AddSourceLocation(D->getLocEnd(), Record);
307 Record.push_back(D->protocol_size());
308 for (ObjCProtocolDecl::protocol_iterator
309 I = D->protocol_begin(), IEnd = D->protocol_end(); I != IEnd; ++I)
310 Writer.AddDeclRef(*I, Record);
311 Code = pch::DECL_OBJC_PROTOCOL;
312}
313
314void PCHDeclWriter::VisitObjCAtDefsFieldDecl(ObjCAtDefsFieldDecl *D) {
315 VisitFieldDecl(D);
316 Code = pch::DECL_OBJC_AT_DEFS_FIELD;
317}
318
319void PCHDeclWriter::VisitObjCClassDecl(ObjCClassDecl *D) {
320 VisitDecl(D);
321 Record.push_back(D->size());
322 for (ObjCClassDecl::iterator I = D->begin(), IEnd = D->end(); I != IEnd; ++I)
323 Writer.AddDeclRef(*I, Record);
324 Code = pch::DECL_OBJC_CLASS;
325}
326
327void PCHDeclWriter::VisitObjCForwardProtocolDecl(ObjCForwardProtocolDecl *D) {
328 VisitDecl(D);
329 Record.push_back(D->protocol_size());
330 for (ObjCProtocolDecl::protocol_iterator
331 I = D->protocol_begin(), IEnd = D->protocol_end(); I != IEnd; ++I)
332 Writer.AddDeclRef(*I, Record);
333 Code = pch::DECL_OBJC_FORWARD_PROTOCOL;
334}
335
336void PCHDeclWriter::VisitObjCCategoryDecl(ObjCCategoryDecl *D) {
337 VisitObjCContainerDecl(D);
338 Writer.AddDeclRef(D->getClassInterface(), Record);
339 Record.push_back(D->protocol_size());
340 for (ObjCProtocolDecl::protocol_iterator
341 I = D->protocol_begin(), IEnd = D->protocol_end(); I != IEnd; ++I)
342 Writer.AddDeclRef(*I, Record);
343 Writer.AddDeclRef(D->getNextClassCategory(), Record);
344 Writer.AddSourceLocation(D->getLocEnd(), Record);
345 Code = pch::DECL_OBJC_CATEGORY;
346}
347
348void PCHDeclWriter::VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *D) {
349 VisitNamedDecl(D);
350 Writer.AddDeclRef(D->getClassInterface(), Record);
351 Code = pch::DECL_OBJC_COMPATIBLE_ALIAS;
352}
353
354void PCHDeclWriter::VisitObjCPropertyDecl(ObjCPropertyDecl *D) {
355 VisitNamedDecl(D);
356 Writer.AddTypeRef(D->getType(), Record);
357 // FIXME: stable encoding
358 Record.push_back((unsigned)D->getPropertyAttributes());
359 // FIXME: stable encoding
360 Record.push_back((unsigned)D->getPropertyImplementation());
361 Writer.AddDeclarationName(D->getGetterName(), Record);
362 Writer.AddDeclarationName(D->getSetterName(), Record);
363 Writer.AddDeclRef(D->getGetterMethodDecl(), Record);
364 Writer.AddDeclRef(D->getSetterMethodDecl(), Record);
365 Writer.AddDeclRef(D->getPropertyIvarDecl(), Record);
366 Code = pch::DECL_OBJC_PROPERTY;
367}
368
369void PCHDeclWriter::VisitObjCImplDecl(ObjCImplDecl *D) {
Argyrios Kyrtzidisaecae622009-07-27 19:04:32 +0000370 VisitObjCContainerDecl(D);
Chris Lattner12b1c762009-04-27 06:16:06 +0000371 Writer.AddDeclRef(D->getClassInterface(), Record);
Chris Lattner12b1c762009-04-27 06:16:06 +0000372 // Abstract class (no need to define a stable pch::DECL code).
373}
374
375void PCHDeclWriter::VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D) {
376 VisitObjCImplDecl(D);
377 Writer.AddIdentifierRef(D->getIdentifier(), Record);
378 Code = pch::DECL_OBJC_CATEGORY_IMPL;
379}
380
381void PCHDeclWriter::VisitObjCImplementationDecl(ObjCImplementationDecl *D) {
382 VisitObjCImplDecl(D);
383 Writer.AddDeclRef(D->getSuperClass(), Record);
384 Code = pch::DECL_OBJC_IMPLEMENTATION;
385}
386
387void PCHDeclWriter::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D) {
388 VisitDecl(D);
389 Writer.AddSourceLocation(D->getLocStart(), Record);
390 Writer.AddDeclRef(D->getPropertyDecl(), Record);
391 Writer.AddDeclRef(D->getPropertyIvarDecl(), Record);
392 Code = pch::DECL_OBJC_PROPERTY_IMPL;
393}
394
395void PCHDeclWriter::VisitFieldDecl(FieldDecl *D) {
Argyrios Kyrtzidisd4a7e542009-08-19 01:28:35 +0000396 VisitDeclaratorDecl(D);
Chris Lattner12b1c762009-04-27 06:16:06 +0000397 Record.push_back(D->isMutable());
Steve Naroffea218b82009-07-14 14:58:18 +0000398 Writer.AddSourceLocation(D->getTypeSpecStartLoc(), Record);
Chris Lattner12b1c762009-04-27 06:16:06 +0000399 Record.push_back(D->getBitWidth()? 1 : 0);
400 if (D->getBitWidth())
401 Writer.AddStmt(D->getBitWidth());
402 Code = pch::DECL_FIELD;
403}
404
405void PCHDeclWriter::VisitVarDecl(VarDecl *D) {
Argyrios Kyrtzidisd4a7e542009-08-19 01:28:35 +0000406 VisitDeclaratorDecl(D);
Chris Lattner12b1c762009-04-27 06:16:06 +0000407 Record.push_back(D->getStorageClass()); // FIXME: stable encoding
408 Record.push_back(D->isThreadSpecified());
409 Record.push_back(D->hasCXXDirectInitializer());
410 Record.push_back(D->isDeclaredInCondition());
411 Writer.AddDeclRef(D->getPreviousDeclaration(), Record);
412 Writer.AddSourceLocation(D->getTypeSpecStartLoc(), Record);
413 Record.push_back(D->getInit()? 1 : 0);
414 if (D->getInit())
415 Writer.AddStmt(D->getInit());
416 Code = pch::DECL_VAR;
417}
418
419void PCHDeclWriter::VisitImplicitParamDecl(ImplicitParamDecl *D) {
420 VisitVarDecl(D);
421 Code = pch::DECL_IMPLICIT_PARAM;
422}
423
424void PCHDeclWriter::VisitParmVarDecl(ParmVarDecl *D) {
425 VisitVarDecl(D);
426 Record.push_back(D->getObjCDeclQualifier()); // FIXME: stable encoding
Chris Lattner12b1c762009-04-27 06:16:06 +0000427 Code = pch::DECL_PARM_VAR;
Chris Lattnerea5ce472009-04-27 07:35:58 +0000428
429
430 // If the assumptions about the DECL_PARM_VAR abbrev are true, use it. Here
431 // we dynamically check for the properties that we optimize for, but don't
432 // know are true of all PARM_VAR_DECLs.
Argyrios Kyrtzidisd4a7e542009-08-19 01:28:35 +0000433 if (!D->getDeclaratorInfo() &&
434 !D->hasAttrs() &&
Chris Lattnerea5ce472009-04-27 07:35:58 +0000435 !D->isImplicit() &&
Douglas Gregore0762c92009-06-19 23:52:42 +0000436 !D->isUsed() &&
Chris Lattnerea5ce472009-04-27 07:35:58 +0000437 D->getAccess() == AS_none &&
438 D->getStorageClass() == 0 &&
439 !D->hasCXXDirectInitializer() && // Can params have this ever?
440 D->getObjCDeclQualifier() == 0)
441 AbbrevToUse = Writer.getParmVarDeclAbbrev();
442
443 // Check things we know are true of *every* PARM_VAR_DECL, which is more than
444 // just us assuming it.
445 assert(!D->isInvalidDecl() && "Shouldn't emit invalid decls");
446 assert(!D->isThreadSpecified() && "PARM_VAR_DECL can't be __thread");
447 assert(D->getAccess() == AS_none && "PARM_VAR_DECL can't be public/private");
448 assert(!D->isDeclaredInCondition() && "PARM_VAR_DECL can't be in condition");
449 assert(D->getPreviousDeclaration() == 0 && "PARM_VAR_DECL can't be redecl");
450 assert(D->getInit() == 0 && "PARM_VAR_DECL never has init");
Chris Lattner12b1c762009-04-27 06:16:06 +0000451}
452
453void PCHDeclWriter::VisitOriginalParmVarDecl(OriginalParmVarDecl *D) {
454 VisitParmVarDecl(D);
455 Writer.AddTypeRef(D->getOriginalType(), Record);
456 Code = pch::DECL_ORIGINAL_PARM_VAR;
Chris Lattnerea5ce472009-04-27 07:35:58 +0000457 AbbrevToUse = 0;
Chris Lattner12b1c762009-04-27 06:16:06 +0000458}
459
460void PCHDeclWriter::VisitFileScopeAsmDecl(FileScopeAsmDecl *D) {
461 VisitDecl(D);
462 Writer.AddStmt(D->getAsmString());
463 Code = pch::DECL_FILE_SCOPE_ASM;
464}
465
466void PCHDeclWriter::VisitBlockDecl(BlockDecl *D) {
467 VisitDecl(D);
468 Writer.AddStmt(D->getBody());
469 Record.push_back(D->param_size());
470 for (FunctionDecl::param_iterator P = D->param_begin(), PEnd = D->param_end();
471 P != PEnd; ++P)
472 Writer.AddDeclRef(*P, Record);
473 Code = pch::DECL_BLOCK;
474}
475
476/// \brief Emit the DeclContext part of a declaration context decl.
477///
478/// \param LexicalOffset the offset at which the DECL_CONTEXT_LEXICAL
479/// block for this declaration context is stored. May be 0 to indicate
480/// that there are no declarations stored within this context.
481///
482/// \param VisibleOffset the offset at which the DECL_CONTEXT_VISIBLE
483/// block for this declaration context is stored. May be 0 to indicate
484/// that there are no declarations visible from this context. Note
485/// that this value will not be emitted for non-primary declaration
486/// contexts.
487void PCHDeclWriter::VisitDeclContext(DeclContext *DC, uint64_t LexicalOffset,
488 uint64_t VisibleOffset) {
489 Record.push_back(LexicalOffset);
490 Record.push_back(VisibleOffset);
491}
492
493
494//===----------------------------------------------------------------------===//
495// PCHWriter Implementation
496//===----------------------------------------------------------------------===//
497
Chris Lattnerea5ce472009-04-27 07:35:58 +0000498void PCHWriter::WriteDeclsBlockAbbrevs() {
499 using namespace llvm;
500 // Abbreviation for DECL_PARM_VAR.
501 BitCodeAbbrev *Abv = new BitCodeAbbrev();
502 Abv->Add(BitCodeAbbrevOp(pch::DECL_PARM_VAR));
503
504 // Decl
505 Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // DeclContext
506 Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // LexicalDeclContext
507 Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Location
508 Abv->Add(BitCodeAbbrevOp(0)); // isInvalidDecl (!?)
509 Abv->Add(BitCodeAbbrevOp(0)); // HasAttrs
510 Abv->Add(BitCodeAbbrevOp(0)); // isImplicit
Douglas Gregore0762c92009-06-19 23:52:42 +0000511 Abv->Add(BitCodeAbbrevOp(0)); // isUsed
Chris Lattnerea5ce472009-04-27 07:35:58 +0000512 Abv->Add(BitCodeAbbrevOp(AS_none)); // C++ AccessSpecifier
513
514 // NamedDecl
515 Abv->Add(BitCodeAbbrevOp(0)); // NameKind = Identifier
516 Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Name
517 // ValueDecl
518 Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type
Argyrios Kyrtzidisd4a7e542009-08-19 01:28:35 +0000519 // DeclaratorDecl
520 Abv->Add(BitCodeAbbrevOp(pch::PREDEF_TYPE_NULL_ID)); // InfoType
Chris Lattnerea5ce472009-04-27 07:35:58 +0000521 // VarDecl
522 Abv->Add(BitCodeAbbrevOp(0)); // StorageClass
523 Abv->Add(BitCodeAbbrevOp(0)); // isThreadSpecified
524 Abv->Add(BitCodeAbbrevOp(0)); // hasCXXDirectInitializer
525 Abv->Add(BitCodeAbbrevOp(0)); // isDeclaredInCondition
526 Abv->Add(BitCodeAbbrevOp(0)); // PrevDecl
527 Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // TypeSpecStartLoc
528 Abv->Add(BitCodeAbbrevOp(0)); // HasInit
529 // ParmVarDecl
530 Abv->Add(BitCodeAbbrevOp(0)); // ObjCDeclQualifier
531
532 ParmVarDeclAbbrev = Stream.EmitAbbrev(Abv);
533}
534
Chris Lattner12b1c762009-04-27 06:16:06 +0000535/// \brief Write a block containing all of the declarations.
536void PCHWriter::WriteDeclsBlock(ASTContext &Context) {
537 // Enter the declarations block.
Chris Lattnerea5ce472009-04-27 07:35:58 +0000538 Stream.EnterSubblock(pch::DECLS_BLOCK_ID, 3);
Chris Lattner12b1c762009-04-27 06:16:06 +0000539
Chris Lattnerea5ce472009-04-27 07:35:58 +0000540 // Output the abbreviations that we will use in this block.
541 WriteDeclsBlockAbbrevs();
542
Chris Lattner12b1c762009-04-27 06:16:06 +0000543 // Emit all of the declarations.
544 RecordData Record;
545 PCHDeclWriter W(*this, Context, Record);
546 while (!DeclsToEmit.empty()) {
547 // Pull the next declaration off the queue
548 Decl *D = DeclsToEmit.front();
549 DeclsToEmit.pop();
550
551 // If this declaration is also a DeclContext, write blocks for the
552 // declarations that lexically stored inside its context and those
553 // declarations that are visible from its context. These blocks
554 // are written before the declaration itself so that we can put
555 // their offsets into the record for the declaration.
556 uint64_t LexicalOffset = 0;
557 uint64_t VisibleOffset = 0;
558 DeclContext *DC = dyn_cast<DeclContext>(D);
559 if (DC) {
560 LexicalOffset = WriteDeclContextLexicalBlock(Context, DC);
561 VisibleOffset = WriteDeclContextVisibleBlock(Context, DC);
562 }
563
564 // Determine the ID for this declaration
Zhongxing Xu44dfc982009-06-01 00:50:23 +0000565 pch::DeclID &ID = DeclIDs[D];
Chris Lattner12b1c762009-04-27 06:16:06 +0000566 if (ID == 0)
567 ID = DeclIDs.size();
568
569 unsigned Index = ID - 1;
570
571 // Record the offset for this declaration
572 if (DeclOffsets.size() == Index)
573 DeclOffsets.push_back(Stream.GetCurrentBitNo());
574 else if (DeclOffsets.size() < Index) {
575 DeclOffsets.resize(Index+1);
576 DeclOffsets[Index] = Stream.GetCurrentBitNo();
577 }
578
579 // Build and emit a record for this declaration
580 Record.clear();
581 W.Code = (pch::DeclCode)0;
Chris Lattnerea5ce472009-04-27 07:35:58 +0000582 W.AbbrevToUse = 0;
Chris Lattner12b1c762009-04-27 06:16:06 +0000583 W.Visit(D);
584 if (DC) W.VisitDeclContext(DC, LexicalOffset, VisibleOffset);
585
586 if (!W.Code) {
587 fprintf(stderr, "Cannot serialize declaration of kind %s\n",
588 D->getDeclKindName());
589 assert(false && "Unhandled declaration kind while generating PCH");
590 exit(-1);
591 }
Chris Lattnerea5ce472009-04-27 07:35:58 +0000592 Stream.EmitRecord(W.Code, Record, W.AbbrevToUse);
593
Chris Lattner12b1c762009-04-27 06:16:06 +0000594 // If the declaration had any attributes, write them now.
595 if (D->hasAttrs())
Argyrios Kyrtzidis40b598e2009-06-30 02:34:44 +0000596 WriteAttributeRecord(D->getAttrs());
Chris Lattner12b1c762009-04-27 06:16:06 +0000597
598 // Flush any expressions that were written as part of this declaration.
599 FlushStmts();
600
601 // Note external declarations so that we can add them to a record
602 // in the PCH file later.
603 if (isa<FileScopeAsmDecl>(D))
604 ExternalDefinitions.push_back(ID);
605 }
606
607 // Exit the declarations block
608 Stream.ExitBlock();
609}