blob: e2cf3d8ce5dd554903b7da1629df153c922b061e [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"
17#include "llvm/Bitcode/BitstreamWriter.h"
18using namespace clang;
19
20//===----------------------------------------------------------------------===//
21// Declaration serialization
22//===----------------------------------------------------------------------===//
23
24namespace {
25 class PCHDeclWriter : public DeclVisitor<PCHDeclWriter, void> {
26
27 PCHWriter &Writer;
28 ASTContext &Context;
29 PCHWriter::RecordData &Record;
30
31 public:
32 pch::DeclCode Code;
33
34 PCHDeclWriter(PCHWriter &Writer, ASTContext &Context,
35 PCHWriter::RecordData &Record)
36 : Writer(Writer), Context(Context), Record(Record) { }
37
38 void VisitDecl(Decl *D);
39 void VisitTranslationUnitDecl(TranslationUnitDecl *D);
40 void VisitNamedDecl(NamedDecl *D);
41 void VisitTypeDecl(TypeDecl *D);
42 void VisitTypedefDecl(TypedefDecl *D);
43 void VisitTagDecl(TagDecl *D);
44 void VisitEnumDecl(EnumDecl *D);
45 void VisitRecordDecl(RecordDecl *D);
46 void VisitValueDecl(ValueDecl *D);
47 void VisitEnumConstantDecl(EnumConstantDecl *D);
48 void VisitFunctionDecl(FunctionDecl *D);
49 void VisitFieldDecl(FieldDecl *D);
50 void VisitVarDecl(VarDecl *D);
51 void VisitImplicitParamDecl(ImplicitParamDecl *D);
52 void VisitParmVarDecl(ParmVarDecl *D);
53 void VisitOriginalParmVarDecl(OriginalParmVarDecl *D);
54 void VisitFileScopeAsmDecl(FileScopeAsmDecl *D);
55 void VisitBlockDecl(BlockDecl *D);
56 void VisitDeclContext(DeclContext *DC, uint64_t LexicalOffset,
57 uint64_t VisibleOffset);
58 void VisitObjCMethodDecl(ObjCMethodDecl *D);
59 void VisitObjCContainerDecl(ObjCContainerDecl *D);
60 void VisitObjCInterfaceDecl(ObjCInterfaceDecl *D);
61 void VisitObjCIvarDecl(ObjCIvarDecl *D);
62 void VisitObjCProtocolDecl(ObjCProtocolDecl *D);
63 void VisitObjCAtDefsFieldDecl(ObjCAtDefsFieldDecl *D);
64 void VisitObjCClassDecl(ObjCClassDecl *D);
65 void VisitObjCForwardProtocolDecl(ObjCForwardProtocolDecl *D);
66 void VisitObjCCategoryDecl(ObjCCategoryDecl *D);
67 void VisitObjCImplDecl(ObjCImplDecl *D);
68 void VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D);
69 void VisitObjCImplementationDecl(ObjCImplementationDecl *D);
70 void VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *D);
71 void VisitObjCPropertyDecl(ObjCPropertyDecl *D);
72 void VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D);
73 };
74}
75
76void PCHDeclWriter::VisitDecl(Decl *D) {
77 Writer.AddDeclRef(cast_or_null<Decl>(D->getDeclContext()), Record);
78 Writer.AddDeclRef(cast_or_null<Decl>(D->getLexicalDeclContext()), Record);
79 Writer.AddSourceLocation(D->getLocation(), Record);
80 Record.push_back(D->isInvalidDecl());
81 Record.push_back(D->hasAttrs());
82 Record.push_back(D->isImplicit());
83 Record.push_back(D->getAccess());
84}
85
86void PCHDeclWriter::VisitTranslationUnitDecl(TranslationUnitDecl *D) {
87 VisitDecl(D);
88 Code = pch::DECL_TRANSLATION_UNIT;
89}
90
91void PCHDeclWriter::VisitNamedDecl(NamedDecl *D) {
92 VisitDecl(D);
93 Writer.AddDeclarationName(D->getDeclName(), Record);
94}
95
96void PCHDeclWriter::VisitTypeDecl(TypeDecl *D) {
97 VisitNamedDecl(D);
98 Writer.AddTypeRef(QualType(D->getTypeForDecl(), 0), Record);
99}
100
101void PCHDeclWriter::VisitTypedefDecl(TypedefDecl *D) {
102 VisitTypeDecl(D);
103 Writer.AddTypeRef(D->getUnderlyingType(), Record);
104 Code = pch::DECL_TYPEDEF;
105}
106
107void PCHDeclWriter::VisitTagDecl(TagDecl *D) {
108 VisitTypeDecl(D);
109 Record.push_back((unsigned)D->getTagKind()); // FIXME: stable encoding
110 Record.push_back(D->isDefinition());
111 Writer.AddDeclRef(D->getTypedefForAnonDecl(), Record);
112}
113
114void PCHDeclWriter::VisitEnumDecl(EnumDecl *D) {
115 VisitTagDecl(D);
116 Writer.AddTypeRef(D->getIntegerType(), Record);
117 Code = pch::DECL_ENUM;
118}
119
120void PCHDeclWriter::VisitRecordDecl(RecordDecl *D) {
121 VisitTagDecl(D);
122 Record.push_back(D->hasFlexibleArrayMember());
123 Record.push_back(D->isAnonymousStructOrUnion());
124 Code = pch::DECL_RECORD;
125}
126
127void PCHDeclWriter::VisitValueDecl(ValueDecl *D) {
128 VisitNamedDecl(D);
129 Writer.AddTypeRef(D->getType(), Record);
130}
131
132void PCHDeclWriter::VisitEnumConstantDecl(EnumConstantDecl *D) {
133 VisitValueDecl(D);
134 Record.push_back(D->getInitExpr()? 1 : 0);
135 if (D->getInitExpr())
136 Writer.AddStmt(D->getInitExpr());
137 Writer.AddAPSInt(D->getInitVal(), Record);
138 Code = pch::DECL_ENUM_CONSTANT;
139}
140
141void PCHDeclWriter::VisitFunctionDecl(FunctionDecl *D) {
142 VisitValueDecl(D);
143 Record.push_back(D->isThisDeclarationADefinition());
144 if (D->isThisDeclarationADefinition())
145 Writer.AddStmt(D->getBody(Context));
146 Writer.AddDeclRef(D->getPreviousDeclaration(), Record);
147 Record.push_back(D->getStorageClass()); // FIXME: stable encoding
148 Record.push_back(D->isInline());
149 Record.push_back(D->isC99InlineDefinition());
150 Record.push_back(D->isVirtual());
151 Record.push_back(D->isPure());
152 Record.push_back(D->inheritedPrototype());
153 Record.push_back(D->hasPrototype() && !D->inheritedPrototype());
154 Record.push_back(D->isDeleted());
155 Writer.AddSourceLocation(D->getTypeSpecStartLoc(), Record);
156 Record.push_back(D->param_size());
157 for (FunctionDecl::param_iterator P = D->param_begin(), PEnd = D->param_end();
158 P != PEnd; ++P)
159 Writer.AddDeclRef(*P, Record);
160 Code = pch::DECL_FUNCTION;
161}
162
163void PCHDeclWriter::VisitObjCMethodDecl(ObjCMethodDecl *D) {
164 VisitNamedDecl(D);
165 // FIXME: convert to LazyStmtPtr?
166 // Unlike C/C++, method bodies will never be in header files.
167 Record.push_back(D->getBody() != 0);
168 if (D->getBody() != 0) {
169 Writer.AddStmt(D->getBody(Context));
170 Writer.AddDeclRef(D->getSelfDecl(), Record);
171 Writer.AddDeclRef(D->getCmdDecl(), Record);
172 }
173 Record.push_back(D->isInstanceMethod());
174 Record.push_back(D->isVariadic());
175 Record.push_back(D->isSynthesized());
176 // FIXME: stable encoding for @required/@optional
177 Record.push_back(D->getImplementationControl());
178 // FIXME: stable encoding for in/out/inout/bycopy/byref/oneway
179 Record.push_back(D->getObjCDeclQualifier());
180 Writer.AddTypeRef(D->getResultType(), Record);
181 Writer.AddSourceLocation(D->getLocEnd(), Record);
182 Record.push_back(D->param_size());
183 for (ObjCMethodDecl::param_iterator P = D->param_begin(),
184 PEnd = D->param_end(); P != PEnd; ++P)
185 Writer.AddDeclRef(*P, Record);
186 Code = pch::DECL_OBJC_METHOD;
187}
188
189void PCHDeclWriter::VisitObjCContainerDecl(ObjCContainerDecl *D) {
190 VisitNamedDecl(D);
191 Writer.AddSourceLocation(D->getAtEndLoc(), Record);
192 // Abstract class (no need to define a stable pch::DECL code).
193}
194
195void PCHDeclWriter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) {
196 VisitObjCContainerDecl(D);
197 Writer.AddTypeRef(QualType(D->getTypeForDecl(), 0), Record);
198 Writer.AddDeclRef(D->getSuperClass(), Record);
199 Record.push_back(D->protocol_size());
200 for (ObjCInterfaceDecl::protocol_iterator P = D->protocol_begin(),
201 PEnd = D->protocol_end();
202 P != PEnd; ++P)
203 Writer.AddDeclRef(*P, Record);
204 Record.push_back(D->ivar_size());
205 for (ObjCInterfaceDecl::ivar_iterator I = D->ivar_begin(),
206 IEnd = D->ivar_end(); I != IEnd; ++I)
207 Writer.AddDeclRef(*I, Record);
208 Writer.AddDeclRef(D->getCategoryList(), Record);
209 Record.push_back(D->isForwardDecl());
210 Record.push_back(D->isImplicitInterfaceDecl());
211 Writer.AddSourceLocation(D->getClassLoc(), Record);
212 Writer.AddSourceLocation(D->getSuperClassLoc(), Record);
213 Writer.AddSourceLocation(D->getLocEnd(), Record);
214 Code = pch::DECL_OBJC_INTERFACE;
215}
216
217void PCHDeclWriter::VisitObjCIvarDecl(ObjCIvarDecl *D) {
218 VisitFieldDecl(D);
219 // FIXME: stable encoding for @public/@private/@protected/@package
220 Record.push_back(D->getAccessControl());
221 Code = pch::DECL_OBJC_IVAR;
222}
223
224void PCHDeclWriter::VisitObjCProtocolDecl(ObjCProtocolDecl *D) {
225 VisitObjCContainerDecl(D);
226 Record.push_back(D->isForwardDecl());
227 Writer.AddSourceLocation(D->getLocEnd(), Record);
228 Record.push_back(D->protocol_size());
229 for (ObjCProtocolDecl::protocol_iterator
230 I = D->protocol_begin(), IEnd = D->protocol_end(); I != IEnd; ++I)
231 Writer.AddDeclRef(*I, Record);
232 Code = pch::DECL_OBJC_PROTOCOL;
233}
234
235void PCHDeclWriter::VisitObjCAtDefsFieldDecl(ObjCAtDefsFieldDecl *D) {
236 VisitFieldDecl(D);
237 Code = pch::DECL_OBJC_AT_DEFS_FIELD;
238}
239
240void PCHDeclWriter::VisitObjCClassDecl(ObjCClassDecl *D) {
241 VisitDecl(D);
242 Record.push_back(D->size());
243 for (ObjCClassDecl::iterator I = D->begin(), IEnd = D->end(); I != IEnd; ++I)
244 Writer.AddDeclRef(*I, Record);
245 Code = pch::DECL_OBJC_CLASS;
246}
247
248void PCHDeclWriter::VisitObjCForwardProtocolDecl(ObjCForwardProtocolDecl *D) {
249 VisitDecl(D);
250 Record.push_back(D->protocol_size());
251 for (ObjCProtocolDecl::protocol_iterator
252 I = D->protocol_begin(), IEnd = D->protocol_end(); I != IEnd; ++I)
253 Writer.AddDeclRef(*I, Record);
254 Code = pch::DECL_OBJC_FORWARD_PROTOCOL;
255}
256
257void PCHDeclWriter::VisitObjCCategoryDecl(ObjCCategoryDecl *D) {
258 VisitObjCContainerDecl(D);
259 Writer.AddDeclRef(D->getClassInterface(), Record);
260 Record.push_back(D->protocol_size());
261 for (ObjCProtocolDecl::protocol_iterator
262 I = D->protocol_begin(), IEnd = D->protocol_end(); I != IEnd; ++I)
263 Writer.AddDeclRef(*I, Record);
264 Writer.AddDeclRef(D->getNextClassCategory(), Record);
265 Writer.AddSourceLocation(D->getLocEnd(), Record);
266 Code = pch::DECL_OBJC_CATEGORY;
267}
268
269void PCHDeclWriter::VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *D) {
270 VisitNamedDecl(D);
271 Writer.AddDeclRef(D->getClassInterface(), Record);
272 Code = pch::DECL_OBJC_COMPATIBLE_ALIAS;
273}
274
275void PCHDeclWriter::VisitObjCPropertyDecl(ObjCPropertyDecl *D) {
276 VisitNamedDecl(D);
277 Writer.AddTypeRef(D->getType(), Record);
278 // FIXME: stable encoding
279 Record.push_back((unsigned)D->getPropertyAttributes());
280 // FIXME: stable encoding
281 Record.push_back((unsigned)D->getPropertyImplementation());
282 Writer.AddDeclarationName(D->getGetterName(), Record);
283 Writer.AddDeclarationName(D->getSetterName(), Record);
284 Writer.AddDeclRef(D->getGetterMethodDecl(), Record);
285 Writer.AddDeclRef(D->getSetterMethodDecl(), Record);
286 Writer.AddDeclRef(D->getPropertyIvarDecl(), Record);
287 Code = pch::DECL_OBJC_PROPERTY;
288}
289
290void PCHDeclWriter::VisitObjCImplDecl(ObjCImplDecl *D) {
291 VisitNamedDecl(D);
292 Writer.AddDeclRef(D->getClassInterface(), Record);
293 Writer.AddSourceLocation(D->getLocEnd(), Record);
294 // Abstract class (no need to define a stable pch::DECL code).
295}
296
297void PCHDeclWriter::VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D) {
298 VisitObjCImplDecl(D);
299 Writer.AddIdentifierRef(D->getIdentifier(), Record);
300 Code = pch::DECL_OBJC_CATEGORY_IMPL;
301}
302
303void PCHDeclWriter::VisitObjCImplementationDecl(ObjCImplementationDecl *D) {
304 VisitObjCImplDecl(D);
305 Writer.AddDeclRef(D->getSuperClass(), Record);
306 Code = pch::DECL_OBJC_IMPLEMENTATION;
307}
308
309void PCHDeclWriter::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D) {
310 VisitDecl(D);
311 Writer.AddSourceLocation(D->getLocStart(), Record);
312 Writer.AddDeclRef(D->getPropertyDecl(), Record);
313 Writer.AddDeclRef(D->getPropertyIvarDecl(), Record);
314 Code = pch::DECL_OBJC_PROPERTY_IMPL;
315}
316
317void PCHDeclWriter::VisitFieldDecl(FieldDecl *D) {
318 VisitValueDecl(D);
319 Record.push_back(D->isMutable());
320 Record.push_back(D->getBitWidth()? 1 : 0);
321 if (D->getBitWidth())
322 Writer.AddStmt(D->getBitWidth());
323 Code = pch::DECL_FIELD;
324}
325
326void PCHDeclWriter::VisitVarDecl(VarDecl *D) {
327 VisitValueDecl(D);
328 Record.push_back(D->getStorageClass()); // FIXME: stable encoding
329 Record.push_back(D->isThreadSpecified());
330 Record.push_back(D->hasCXXDirectInitializer());
331 Record.push_back(D->isDeclaredInCondition());
332 Writer.AddDeclRef(D->getPreviousDeclaration(), Record);
333 Writer.AddSourceLocation(D->getTypeSpecStartLoc(), Record);
334 Record.push_back(D->getInit()? 1 : 0);
335 if (D->getInit())
336 Writer.AddStmt(D->getInit());
337 Code = pch::DECL_VAR;
338}
339
340void PCHDeclWriter::VisitImplicitParamDecl(ImplicitParamDecl *D) {
341 VisitVarDecl(D);
342 Code = pch::DECL_IMPLICIT_PARAM;
343}
344
345void PCHDeclWriter::VisitParmVarDecl(ParmVarDecl *D) {
346 VisitVarDecl(D);
347 Record.push_back(D->getObjCDeclQualifier()); // FIXME: stable encoding
348 // FIXME: emit default argument (C++)
349 // FIXME: why isn't the "default argument" just stored as the initializer
350 // in VarDecl?
351 Code = pch::DECL_PARM_VAR;
352}
353
354void PCHDeclWriter::VisitOriginalParmVarDecl(OriginalParmVarDecl *D) {
355 VisitParmVarDecl(D);
356 Writer.AddTypeRef(D->getOriginalType(), Record);
357 Code = pch::DECL_ORIGINAL_PARM_VAR;
358}
359
360void PCHDeclWriter::VisitFileScopeAsmDecl(FileScopeAsmDecl *D) {
361 VisitDecl(D);
362 Writer.AddStmt(D->getAsmString());
363 Code = pch::DECL_FILE_SCOPE_ASM;
364}
365
366void PCHDeclWriter::VisitBlockDecl(BlockDecl *D) {
367 VisitDecl(D);
368 Writer.AddStmt(D->getBody());
369 Record.push_back(D->param_size());
370 for (FunctionDecl::param_iterator P = D->param_begin(), PEnd = D->param_end();
371 P != PEnd; ++P)
372 Writer.AddDeclRef(*P, Record);
373 Code = pch::DECL_BLOCK;
374}
375
376/// \brief Emit the DeclContext part of a declaration context decl.
377///
378/// \param LexicalOffset the offset at which the DECL_CONTEXT_LEXICAL
379/// block for this declaration context is stored. May be 0 to indicate
380/// that there are no declarations stored within this context.
381///
382/// \param VisibleOffset the offset at which the DECL_CONTEXT_VISIBLE
383/// block for this declaration context is stored. May be 0 to indicate
384/// that there are no declarations visible from this context. Note
385/// that this value will not be emitted for non-primary declaration
386/// contexts.
387void PCHDeclWriter::VisitDeclContext(DeclContext *DC, uint64_t LexicalOffset,
388 uint64_t VisibleOffset) {
389 Record.push_back(LexicalOffset);
390 Record.push_back(VisibleOffset);
391}
392
393
394//===----------------------------------------------------------------------===//
395// PCHWriter Implementation
396//===----------------------------------------------------------------------===//
397
398/// \brief Write a block containing all of the declarations.
399void PCHWriter::WriteDeclsBlock(ASTContext &Context) {
400 // Enter the declarations block.
401 Stream.EnterSubblock(pch::DECLS_BLOCK_ID, 2);
402
403 // Emit all of the declarations.
404 RecordData Record;
405 PCHDeclWriter W(*this, Context, Record);
406 while (!DeclsToEmit.empty()) {
407 // Pull the next declaration off the queue
408 Decl *D = DeclsToEmit.front();
409 DeclsToEmit.pop();
410
411 // If this declaration is also a DeclContext, write blocks for the
412 // declarations that lexically stored inside its context and those
413 // declarations that are visible from its context. These blocks
414 // are written before the declaration itself so that we can put
415 // their offsets into the record for the declaration.
416 uint64_t LexicalOffset = 0;
417 uint64_t VisibleOffset = 0;
418 DeclContext *DC = dyn_cast<DeclContext>(D);
419 if (DC) {
420 LexicalOffset = WriteDeclContextLexicalBlock(Context, DC);
421 VisibleOffset = WriteDeclContextVisibleBlock(Context, DC);
422 }
423
424 // Determine the ID for this declaration
425 pch::DeclID ID = DeclIDs[D];
426 if (ID == 0)
427 ID = DeclIDs.size();
428
429 unsigned Index = ID - 1;
430
431 // Record the offset for this declaration
432 if (DeclOffsets.size() == Index)
433 DeclOffsets.push_back(Stream.GetCurrentBitNo());
434 else if (DeclOffsets.size() < Index) {
435 DeclOffsets.resize(Index+1);
436 DeclOffsets[Index] = Stream.GetCurrentBitNo();
437 }
438
439 // Build and emit a record for this declaration
440 Record.clear();
441 W.Code = (pch::DeclCode)0;
442 W.Visit(D);
443 if (DC) W.VisitDeclContext(DC, LexicalOffset, VisibleOffset);
444
445 if (!W.Code) {
446 fprintf(stderr, "Cannot serialize declaration of kind %s\n",
447 D->getDeclKindName());
448 assert(false && "Unhandled declaration kind while generating PCH");
449 exit(-1);
450 }
451 Stream.EmitRecord(W.Code, Record);
452
453 // If the declaration had any attributes, write them now.
454 if (D->hasAttrs())
455 WriteAttributeRecord(D->getAttrs());
456
457 // Flush any expressions that were written as part of this declaration.
458 FlushStmts();
459
460 // Note external declarations so that we can add them to a record
461 // in the PCH file later.
462 if (isa<FileScopeAsmDecl>(D))
463 ExternalDefinitions.push_back(ID);
464 }
465
466 // Exit the declarations block
467 Stream.ExitBlock();
468}