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