 |
|
 |
|
| Files: |
1 |
|
Branches Taken: |
77.3% |
102 / 132 |
| Generated: |
2010-02-10 01:31 |
|
Branches Executed: |
98.5% |
130 / 132 |
| |
|
Line Coverage: |
91.6% |
339 / 370 |
| |
 |
|
 |
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/ADT/Twine.h"
18 : #include "llvm/Bitcode/BitstreamWriter.h"
19 : #include "llvm/Support/ErrorHandling.h"
20 : using namespace clang;
21 :
22 : //===----------------------------------------------------------------------===//
23 : // Declaration serialization
24 : //===----------------------------------------------------------------------===//
25 :
26 : namespace {
27 : class PCHDeclWriter : public DeclVisitor<PCHDeclWriter, void> {
28 :
29 : PCHWriter &Writer;
30 : ASTContext &Context;
31 : PCHWriter::RecordData &Record;
32 :
33 : public:
34 : pch::DeclCode Code;
35 : unsigned AbbrevToUse;
36 :
37 : PCHDeclWriter(PCHWriter &Writer, ASTContext &Context,
38 602: PCHWriter::RecordData &Record)
39 602: : Writer(Writer), Context(Context), Record(Record) {
40 602: }
41 :
42 : void VisitDecl(Decl *D);
43 : void VisitTranslationUnitDecl(TranslationUnitDecl *D);
44 : void VisitNamedDecl(NamedDecl *D);
45 : void VisitTypeDecl(TypeDecl *D);
46 : void VisitTypedefDecl(TypedefDecl *D);
47 : void VisitTagDecl(TagDecl *D);
48 : void VisitEnumDecl(EnumDecl *D);
49 : void VisitRecordDecl(RecordDecl *D);
50 : void VisitValueDecl(ValueDecl *D);
51 : void VisitEnumConstantDecl(EnumConstantDecl *D);
52 : void VisitDeclaratorDecl(DeclaratorDecl *D);
53 : void VisitFunctionDecl(FunctionDecl *D);
54 : void VisitFieldDecl(FieldDecl *D);
55 : void VisitVarDecl(VarDecl *D);
56 : void VisitImplicitParamDecl(ImplicitParamDecl *D);
57 : void VisitParmVarDecl(ParmVarDecl *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 :
80 602: void PCHDeclWriter::VisitDecl(Decl *D) {
81 602: Writer.AddDeclRef(cast_or_null<Decl>(D->getDeclContext()), Record);
82 602: Writer.AddDeclRef(cast_or_null<Decl>(D->getLexicalDeclContext()), Record);
83 602: Writer.AddSourceLocation(D->getLocation(), Record);
84 602: Record.push_back(D->isInvalidDecl());
85 602: Record.push_back(D->hasAttrs());
86 602: Record.push_back(D->isImplicit());
87 602: Record.push_back(D->isUsed());
88 602: Record.push_back(D->getAccess());
89 602: Record.push_back(D->getPCHLevel());
90 602: }
91 :
92 44: void PCHDeclWriter::VisitTranslationUnitDecl(TranslationUnitDecl *D) {
93 44: VisitDecl(D);
94 44: Code = pch::DECL_TRANSLATION_UNIT;
95 44: }
96 :
97 550: void PCHDeclWriter::VisitNamedDecl(NamedDecl *D) {
98 550: VisitDecl(D);
99 550: Writer.AddDeclarationName(D->getDeclName(), Record);
100 550: }
101 :
102 191: void PCHDeclWriter::VisitTypeDecl(TypeDecl *D) {
103 191: VisitNamedDecl(D);
104 191: Writer.AddTypeRef(QualType(D->getTypeForDecl(), 0), Record);
105 191: }
106 :
107 156: void PCHDeclWriter::VisitTypedefDecl(TypedefDecl *D) {
108 156: VisitTypeDecl(D);
109 156: Writer.AddTypeSourceInfo(D->getTypeSourceInfo(), Record);
110 156: Code = pch::DECL_TYPEDEF;
111 156: }
112 :
113 35: void PCHDeclWriter::VisitTagDecl(TagDecl *D) {
114 35: VisitTypeDecl(D);
115 35: Writer.AddDeclRef(D->getPreviousDeclaration(), Record);
116 35: Record.push_back((unsigned)D->getTagKind()); // FIXME: stable encoding
117 35: Record.push_back(D->isDefinition());
118 35: Record.push_back(D->isDefinedInDeclarator());
119 35: Writer.AddDeclRef(D->getTypedefForAnonDecl(), Record);
120 35: Writer.AddSourceLocation(D->getRBraceLoc(), Record);
121 35: Writer.AddSourceLocation(D->getTagKeywordLoc(), Record);
122 35: }
123 :
124 5: void PCHDeclWriter::VisitEnumDecl(EnumDecl *D) {
125 5: VisitTagDecl(D);
126 5: Writer.AddTypeRef(D->getIntegerType(), Record);
127 5: Writer.AddTypeRef(D->getPromotionType(), Record);
128 : // FIXME: C++ InstantiatedFrom
129 5: Code = pch::DECL_ENUM;
130 5: }
131 :
132 30: void PCHDeclWriter::VisitRecordDecl(RecordDecl *D) {
133 30: VisitTagDecl(D);
134 30: Record.push_back(D->hasFlexibleArrayMember());
135 30: Record.push_back(D->isAnonymousStructOrUnion());
136 30: Record.push_back(D->hasObjectMember());
137 30: Code = pch::DECL_RECORD;
138 30: }
139 :
140 294: void PCHDeclWriter::VisitValueDecl(ValueDecl *D) {
141 294: VisitNamedDecl(D);
142 294: Writer.AddTypeRef(D->getType(), Record);
143 294: }
144 :
145 10: void PCHDeclWriter::VisitEnumConstantDecl(EnumConstantDecl *D) {
146 10: VisitValueDecl(D);
2: branch 1 taken
8: branch 2 taken
147 10: Record.push_back(D->getInitExpr()? 1 : 0);
2: branch 1 taken
8: branch 2 taken
148 10: if (D->getInitExpr())
149 2: Writer.AddStmt(D->getInitExpr());
150 10: Writer.AddAPSInt(D->getInitVal(), Record);
151 10: Code = pch::DECL_ENUM_CONSTANT;
152 10: }
153 :
154 284: void PCHDeclWriter::VisitDeclaratorDecl(DeclaratorDecl *D) {
155 284: VisitValueDecl(D);
156 284: Writer.AddTypeSourceInfo(D->getTypeSourceInfo(), Record);
157 284: }
158 :
159 64: void PCHDeclWriter::VisitFunctionDecl(FunctionDecl *D) {
160 64: VisitDeclaratorDecl(D);
161 64: Record.push_back(D->isThisDeclarationADefinition());
27: branch 1 taken
37: branch 2 taken
162 64: if (D->isThisDeclarationADefinition())
163 27: Writer.AddStmt(D->getBody());
164 64: Writer.AddDeclRef(D->getPreviousDeclaration(), Record);
165 64: Record.push_back(D->getStorageClass()); // FIXME: stable encoding
166 64: Record.push_back(D->isInlineSpecified());
167 64: Record.push_back(D->isVirtualAsWritten());
168 64: Record.push_back(D->isPure());
169 64: Record.push_back(D->hasInheritedPrototype());
170 64: Record.push_back(D->hasWrittenPrototype());
171 64: Record.push_back(D->isDeleted());
172 64: Record.push_back(D->isTrivial());
173 64: Record.push_back(D->isCopyAssignment());
174 64: Record.push_back(D->hasImplicitReturnZero());
175 64: Writer.AddSourceLocation(D->getLocEnd(), Record);
176 : // FIXME: C++ TemplateOrInstantiation
177 64: Record.push_back(D->param_size());
60: branch 2 taken
64: branch 3 taken
178 124: for (FunctionDecl::param_iterator P = D->param_begin(), PEnd = D->param_end();
179 : P != PEnd; ++P)
180 60: Writer.AddDeclRef(*P, Record);
181 64: Code = pch::DECL_FUNCTION;
182 64: }
183 :
184 29: void PCHDeclWriter::VisitObjCMethodDecl(ObjCMethodDecl *D) {
185 29: VisitNamedDecl(D);
186 : // FIXME: convert to LazyStmtPtr?
187 : // Unlike C/C++, method bodies will never be in header files.
188 29: Record.push_back(D->getBody() != 0);
3: branch 1 taken
26: branch 2 taken
189 29: if (D->getBody() != 0) {
190 3: Writer.AddStmt(D->getBody());
191 3: Writer.AddDeclRef(D->getSelfDecl(), Record);
192 3: Writer.AddDeclRef(D->getCmdDecl(), Record);
193 : }
194 29: Record.push_back(D->isInstanceMethod());
195 29: Record.push_back(D->isVariadic());
196 29: Record.push_back(D->isSynthesized());
197 : // FIXME: stable encoding for @required/@optional
198 29: Record.push_back(D->getImplementationControl());
199 : // FIXME: stable encoding for in/out/inout/bycopy/byref/oneway
200 29: Record.push_back(D->getObjCDeclQualifier());
201 29: Writer.AddTypeRef(D->getResultType(), Record);
202 29: Writer.AddSourceLocation(D->getLocEnd(), Record);
203 29: Record.push_back(D->param_size());
8: branch 1 taken
29: branch 2 taken
204 66: for (ObjCMethodDecl::param_iterator P = D->param_begin(),
205 29: PEnd = D->param_end(); P != PEnd; ++P)
206 8: Writer.AddDeclRef(*P, Record);
207 29: Code = pch::DECL_OBJC_METHOD;
208 29: }
209 :
210 34: void PCHDeclWriter::VisitObjCContainerDecl(ObjCContainerDecl *D) {
211 34: VisitNamedDecl(D);
212 34: SourceRange R = D->getAtEndRange();
213 34: Writer.AddSourceLocation(R.getBegin(), Record);
214 34: Writer.AddSourceLocation(R.getEnd(), Record);
215 : // Abstract class (no need to define a stable pch::DECL code).
216 34: }
217 :
218 25: void PCHDeclWriter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) {
219 25: VisitObjCContainerDecl(D);
220 25: Writer.AddTypeRef(QualType(D->getTypeForDecl(), 0), Record);
221 25: Writer.AddDeclRef(D->getSuperClass(), Record);
222 25: Record.push_back(D->protocol_size());
2: branch 1 taken
25: branch 2 taken
223 52: for (ObjCInterfaceDecl::protocol_iterator P = D->protocol_begin(),
224 25: PEnd = D->protocol_end();
225 : P != PEnd; ++P)
226 2: Writer.AddDeclRef(*P, Record);
2: branch 1 taken
25: branch 2 taken
227 52: for (ObjCInterfaceDecl::protocol_loc_iterator PL = D->protocol_loc_begin(),
228 25: PLEnd = D->protocol_loc_end();
229 : PL != PLEnd; ++PL)
230 2: Writer.AddSourceLocation(*PL, Record);
231 25: Record.push_back(D->ivar_size());
4: branch 1 taken
25: branch 2 taken
232 54: for (ObjCInterfaceDecl::ivar_iterator I = D->ivar_begin(),
233 25: IEnd = D->ivar_end(); I != IEnd; ++I)
234 4: Writer.AddDeclRef(*I, Record);
235 25: Writer.AddDeclRef(D->getCategoryList(), Record);
236 25: Record.push_back(D->isForwardDecl());
237 25: Record.push_back(D->isImplicitInterfaceDecl());
238 25: Writer.AddSourceLocation(D->getClassLoc(), Record);
239 25: Writer.AddSourceLocation(D->getSuperClassLoc(), Record);
240 25: Writer.AddSourceLocation(D->getLocEnd(), Record);
241 25: Code = pch::DECL_OBJC_INTERFACE;
242 25: }
243 :
244 4: void PCHDeclWriter::VisitObjCIvarDecl(ObjCIvarDecl *D) {
245 4: VisitFieldDecl(D);
246 : // FIXME: stable encoding for @public/@private/@protected/@package
247 4: Record.push_back(D->getAccessControl());
248 4: Code = pch::DECL_OBJC_IVAR;
249 4: }
250 :
251 5: void PCHDeclWriter::VisitObjCProtocolDecl(ObjCProtocolDecl *D) {
252 5: VisitObjCContainerDecl(D);
253 5: Record.push_back(D->isForwardDecl());
254 5: Writer.AddSourceLocation(D->getLocEnd(), Record);
255 5: Record.push_back(D->protocol_size());
2: branch 0 taken
5: branch 1 taken
256 7: for (ObjCProtocolDecl::protocol_iterator
257 5: I = D->protocol_begin(), IEnd = D->protocol_end(); I != IEnd; ++I)
258 2: Writer.AddDeclRef(*I, Record);
2: branch 1 taken
5: branch 2 taken
259 12: for (ObjCProtocolDecl::protocol_loc_iterator PL = D->protocol_loc_begin(),
260 5: PLEnd = D->protocol_loc_end();
261 : PL != PLEnd; ++PL)
262 2: Writer.AddSourceLocation(*PL, Record);
263 5: Code = pch::DECL_OBJC_PROTOCOL;
264 5: }
265 :
266 0: void PCHDeclWriter::VisitObjCAtDefsFieldDecl(ObjCAtDefsFieldDecl *D) {
267 0: VisitFieldDecl(D);
268 0: Code = pch::DECL_OBJC_AT_DEFS_FIELD;
269 0: }
270 :
271 4: void PCHDeclWriter::VisitObjCClassDecl(ObjCClassDecl *D) {
272 4: VisitDecl(D);
273 4: Record.push_back(D->size());
4: branch 2 taken
4: branch 3 taken
274 8: for (ObjCClassDecl::iterator I = D->begin(), IEnd = D->end(); I != IEnd; ++I)
275 4: Writer.AddDeclRef(I->getInterface(), Record);
4: branch 2 taken
4: branch 3 taken
276 8: for (ObjCClassDecl::iterator I = D->begin(), IEnd = D->end(); I != IEnd; ++I)
277 4: Writer.AddSourceLocation(I->getLocation(), Record);
278 4: Code = pch::DECL_OBJC_CLASS;
279 4: }
280 :
281 1: void PCHDeclWriter::VisitObjCForwardProtocolDecl(ObjCForwardProtocolDecl *D) {
282 1: VisitDecl(D);
283 1: Record.push_back(D->protocol_size());
1: branch 0 taken
1: branch 1 taken
284 2: for (ObjCForwardProtocolDecl::protocol_iterator
285 1: I = D->protocol_begin(), IEnd = D->protocol_end(); I != IEnd; ++I)
286 1: Writer.AddDeclRef(*I, Record);
1: branch 0 taken
1: branch 1 taken
287 2: for (ObjCForwardProtocolDecl::protocol_loc_iterator
288 1: PL = D->protocol_loc_begin(), PLEnd = D->protocol_loc_end();
289 : PL != PLEnd; ++PL)
290 1: Writer.AddSourceLocation(*PL, Record);
291 1: Code = pch::DECL_OBJC_FORWARD_PROTOCOL;
292 1: }
293 :
294 2: void PCHDeclWriter::VisitObjCCategoryDecl(ObjCCategoryDecl *D) {
295 2: VisitObjCContainerDecl(D);
296 2: Writer.AddDeclRef(D->getClassInterface(), Record);
297 2: Record.push_back(D->protocol_size());
0: branch 0 not taken
2: branch 1 taken
298 2: for (ObjCCategoryDecl::protocol_iterator
299 2: I = D->protocol_begin(), IEnd = D->protocol_end(); I != IEnd; ++I)
300 0: Writer.AddDeclRef(*I, Record);
0: branch 0 not taken
2: branch 1 taken
301 2: for (ObjCCategoryDecl::protocol_loc_iterator
302 2: PL = D->protocol_loc_begin(), PLEnd = D->protocol_loc_end();
303 : PL != PLEnd; ++PL)
304 0: Writer.AddSourceLocation(*PL, Record);
305 2: Writer.AddDeclRef(D->getNextClassCategory(), Record);
306 2: Writer.AddSourceLocation(D->getAtLoc(), Record);
307 2: Writer.AddSourceLocation(D->getCategoryNameLoc(), Record);
308 2: Code = pch::DECL_OBJC_CATEGORY;
309 2: }
310 :
311 0: void PCHDeclWriter::VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *D) {
312 0: VisitNamedDecl(D);
313 0: Writer.AddDeclRef(D->getClassInterface(), Record);
314 0: Code = pch::DECL_OBJC_COMPATIBLE_ALIAS;
315 0: }
316 :
317 2: void PCHDeclWriter::VisitObjCPropertyDecl(ObjCPropertyDecl *D) {
318 2: VisitNamedDecl(D);
319 2: Writer.AddSourceLocation(D->getAtLoc(), Record);
320 2: Writer.AddTypeRef(D->getType(), Record);
321 : // FIXME: stable encoding
322 2: Record.push_back((unsigned)D->getPropertyAttributes());
323 : // FIXME: stable encoding
324 2: Record.push_back((unsigned)D->getPropertyImplementation());
325 2: Writer.AddDeclarationName(D->getGetterName(), Record);
326 2: Writer.AddDeclarationName(D->getSetterName(), Record);
327 2: Writer.AddDeclRef(D->getGetterMethodDecl(), Record);
328 2: Writer.AddDeclRef(D->getSetterMethodDecl(), Record);
329 2: Writer.AddDeclRef(D->getPropertyIvarDecl(), Record);
330 2: Code = pch::DECL_OBJC_PROPERTY;
331 2: }
332 :
333 2: void PCHDeclWriter::VisitObjCImplDecl(ObjCImplDecl *D) {
334 2: VisitObjCContainerDecl(D);
335 2: Writer.AddDeclRef(D->getClassInterface(), Record);
336 : // Abstract class (no need to define a stable pch::DECL code).
337 2: }
338 :
339 0: void PCHDeclWriter::VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D) {
340 0: VisitObjCImplDecl(D);
341 0: Writer.AddIdentifierRef(D->getIdentifier(), Record);
342 0: Code = pch::DECL_OBJC_CATEGORY_IMPL;
343 0: }
344 :
345 2: void PCHDeclWriter::VisitObjCImplementationDecl(ObjCImplementationDecl *D) {
346 2: VisitObjCImplDecl(D);
347 2: Writer.AddDeclRef(D->getSuperClass(), Record);
348 2: Code = pch::DECL_OBJC_IMPLEMENTATION;
349 2: }
350 :
351 0: void PCHDeclWriter::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D) {
352 0: VisitDecl(D);
353 0: Writer.AddSourceLocation(D->getLocStart(), Record);
354 0: Writer.AddDeclRef(D->getPropertyDecl(), Record);
355 0: Writer.AddDeclRef(D->getPropertyIvarDecl(), Record);
356 0: Code = pch::DECL_OBJC_PROPERTY_IMPL;
357 0: }
358 :
359 51: void PCHDeclWriter::VisitFieldDecl(FieldDecl *D) {
360 51: VisitDeclaratorDecl(D);
361 51: Record.push_back(D->isMutable());
1: branch 1 taken
50: branch 2 taken
362 51: Record.push_back(D->getBitWidth()? 1 : 0);
1: branch 1 taken
50: branch 2 taken
363 51: if (D->getBitWidth())
364 1: Writer.AddStmt(D->getBitWidth());
365 51: Code = pch::DECL_FIELD;
366 51: }
367 :
368 169: void PCHDeclWriter::VisitVarDecl(VarDecl *D) {
369 169: VisitDeclaratorDecl(D);
370 169: Record.push_back(D->getStorageClass()); // FIXME: stable encoding
371 169: Record.push_back(D->isThreadSpecified());
372 169: Record.push_back(D->hasCXXDirectInitializer());
373 169: Record.push_back(D->isDeclaredInCondition());
374 169: Writer.AddDeclRef(D->getPreviousDeclaration(), Record);
28: branch 1 taken
141: branch 2 taken
375 169: Record.push_back(D->getInit()? 1 : 0);
28: branch 1 taken
141: branch 2 taken
376 169: if (D->getInit())
377 28: Writer.AddStmt(D->getInit());
378 169: Code = pch::DECL_VAR;
379 169: }
380 :
381 6: void PCHDeclWriter::VisitImplicitParamDecl(ImplicitParamDecl *D) {
382 6: VisitVarDecl(D);
383 6: Code = pch::DECL_IMPLICIT_PARAM;
384 6: }
385 :
386 80: void PCHDeclWriter::VisitParmVarDecl(ParmVarDecl *D) {
387 80: VisitVarDecl(D);
388 80: Record.push_back(D->getObjCDeclQualifier()); // FIXME: stable encoding
389 80: Code = pch::DECL_PARM_VAR;
390 :
391 :
392 : // If the assumptions about the DECL_PARM_VAR abbrev are true, use it. Here
393 : // we dynamically check for the properties that we optimize for, but don't
394 : // know are true of all PARM_VAR_DECLs.
13: branch 1 taken
67: branch 2 taken
13: branch 4 taken
0: branch 5 not taken
13: branch 7 taken
0: branch 8 not taken
13: branch 10 taken
0: branch 11 not taken
13: branch 13 taken
0: branch 14 not taken
13: branch 16 taken
0: branch 17 not taken
13: branch 19 taken
0: branch 20 not taken
13: branch 22 taken
0: branch 23 not taken
13: branch 25 taken
0: branch 26 not taken
13: branch 27 taken
67: branch 28 taken
395 80: if (!D->getTypeSourceInfo() &&
396 : !D->hasAttrs() &&
397 : !D->isImplicit() &&
398 : !D->isUsed() &&
399 : D->getAccess() == AS_none &&
400 : D->getPCHLevel() == 0 &&
401 : D->getStorageClass() == 0 &&
402 : !D->hasCXXDirectInitializer() && // Can params have this ever?
403 : D->getObjCDeclQualifier() == 0)
404 13: AbbrevToUse = Writer.getParmVarDeclAbbrev();
405 :
406 : // Check things we know are true of *every* PARM_VAR_DECL, which is more than
407 : // just us assuming it.
80: branch 1 taken
0: branch 2 not taken
408 80: assert(!D->isInvalidDecl() && "Shouldn't emit invalid decls");
80: branch 1 taken
0: branch 2 not taken
409 80: assert(!D->isThreadSpecified() && "PARM_VAR_DECL can't be __thread");
80: branch 1 taken
0: branch 2 not taken
410 80: assert(D->getAccess() == AS_none && "PARM_VAR_DECL can't be public/private");
80: branch 1 taken
0: branch 2 not taken
411 80: assert(!D->isDeclaredInCondition() && "PARM_VAR_DECL can't be in condition");
80: branch 1 taken
0: branch 2 not taken
412 80: assert(D->getPreviousDeclaration() == 0 && "PARM_VAR_DECL can't be redecl");
80: branch 1 taken
0: branch 2 not taken
413 80: assert(D->getInit() == 0 && "PARM_VAR_DECL never has init");
414 80: }
415 :
416 1: void PCHDeclWriter::VisitFileScopeAsmDecl(FileScopeAsmDecl *D) {
417 1: VisitDecl(D);
418 1: Writer.AddStmt(D->getAsmString());
419 1: Code = pch::DECL_FILE_SCOPE_ASM;
420 1: }
421 :
422 2: void PCHDeclWriter::VisitBlockDecl(BlockDecl *D) {
423 2: VisitDecl(D);
424 2: Writer.AddStmt(D->getBody());
425 2: Record.push_back(D->param_size());
4: branch 2 taken
2: branch 3 taken
426 6: for (FunctionDecl::param_iterator P = D->param_begin(), PEnd = D->param_end();
427 : P != PEnd; ++P)
428 4: Writer.AddDeclRef(*P, Record);
429 2: Code = pch::DECL_BLOCK;
430 2: }
431 :
432 : /// \brief Emit the DeclContext part of a declaration context decl.
433 : ///
434 : /// \param LexicalOffset the offset at which the DECL_CONTEXT_LEXICAL
435 : /// block for this declaration context is stored. May be 0 to indicate
436 : /// that there are no declarations stored within this context.
437 : ///
438 : /// \param VisibleOffset the offset at which the DECL_CONTEXT_VISIBLE
439 : /// block for this declaration context is stored. May be 0 to indicate
440 : /// that there are no declarations visible from this context. Note
441 : /// that this value will not be emitted for non-primary declaration
442 : /// contexts.
443 : void PCHDeclWriter::VisitDeclContext(DeclContext *DC, uint64_t LexicalOffset,
444 208: uint64_t VisibleOffset) {
445 208: Record.push_back(LexicalOffset);
446 208: Record.push_back(VisibleOffset);
447 208: }
448 :
449 :
450 : //===----------------------------------------------------------------------===//
451 : // PCHWriter Implementation
452 : //===----------------------------------------------------------------------===//
453 :
454 44: void PCHWriter::WriteDeclsBlockAbbrevs() {
455 : using namespace llvm;
456 : // Abbreviation for DECL_PARM_VAR.
457 44: BitCodeAbbrev *Abv = new BitCodeAbbrev();
458 44: Abv->Add(BitCodeAbbrevOp(pch::DECL_PARM_VAR));
459 :
460 : // Decl
461 44: Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // DeclContext
462 44: Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // LexicalDeclContext
463 44: Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Location
464 44: Abv->Add(BitCodeAbbrevOp(0)); // isInvalidDecl (!?)
465 44: Abv->Add(BitCodeAbbrevOp(0)); // HasAttrs
466 44: Abv->Add(BitCodeAbbrevOp(0)); // isImplicit
467 44: Abv->Add(BitCodeAbbrevOp(0)); // isUsed
468 44: Abv->Add(BitCodeAbbrevOp(AS_none)); // C++ AccessSpecifier
469 44: Abv->Add(BitCodeAbbrevOp(0)); // PCH level
470 :
471 : // NamedDecl
472 44: Abv->Add(BitCodeAbbrevOp(0)); // NameKind = Identifier
473 44: Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Name
474 : // ValueDecl
475 44: Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type
476 : // DeclaratorDecl
477 44: Abv->Add(BitCodeAbbrevOp(pch::PREDEF_TYPE_NULL_ID)); // InfoType
478 : // VarDecl
479 44: Abv->Add(BitCodeAbbrevOp(0)); // StorageClass
480 44: Abv->Add(BitCodeAbbrevOp(0)); // isThreadSpecified
481 44: Abv->Add(BitCodeAbbrevOp(0)); // hasCXXDirectInitializer
482 44: Abv->Add(BitCodeAbbrevOp(0)); // isDeclaredInCondition
483 44: Abv->Add(BitCodeAbbrevOp(0)); // PrevDecl
484 44: Abv->Add(BitCodeAbbrevOp(0)); // HasInit
485 : // ParmVarDecl
486 44: Abv->Add(BitCodeAbbrevOp(0)); // ObjCDeclQualifier
487 :
488 44: ParmVarDeclAbbrev = Stream.EmitAbbrev(Abv);
489 44: }
490 :
491 : /// isRequiredDecl - Check if this is a "required" Decl, which must be seen by
492 : /// consumers of the AST.
493 : ///
494 : /// Such decls will always be deserialized from the PCH file, so we would like
495 : /// this to be as restrictive as possible. Currently the predicate is driven by
496 : /// code generation requirements, if other clients have a different notion of
497 : /// what is "required" then we may have to consider an alternate scheme where
498 : /// clients can iterate over the top-level decls and get information on them,
499 : /// without necessary deserializing them. We could explicitly require such
500 : /// clients to use a separate API call to "realize" the decl. This should be
501 : /// relatively painless since they would presumably only do it for top-level
502 : /// decls.
503 : //
504 : // FIXME: This predicate is essentially IRgen's predicate to determine whether a
505 : // declaration can be deferred. Merge them somehow.
506 602: static bool isRequiredDecl(const Decl *D, ASTContext &Context) {
507 : // File scoped assembly must be seen.
1: branch 1 taken
601: branch 2 taken
508 602: if (isa<FileScopeAsmDecl>(D))
509 1: return true;
510 :
511 : // Otherwise if this isn't a function or a file scoped variable it doesn't
512 : // need to be seen.
169: branch 1 taken
432: branch 2 taken
513 601: if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
114: branch 1 taken
55: branch 2 taken
514 169: if (!VD->isFileVarDecl())
515 114: return false;
368: branch 1 taken
64: branch 2 taken
516 432: } else if (!isa<FunctionDecl>(D))
517 368: return false;
518 :
519 : // Aliases and used decls must be seen.
119: branch 1 taken
0: branch 2 not taken
0: branch 4 not taken
119: branch 5 taken
0: branch 6 not taken
119: branch 7 taken
520 119: if (D->hasAttr<AliasAttr>() || D->hasAttr<UsedAttr>())
521 0: return true;
522 :
64: branch 1 taken
55: branch 2 taken
523 119: if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
524 : // Forward declarations don't need to be seen.
37: branch 1 taken
27: branch 2 taken
525 64: if (!FD->isThisDeclarationADefinition())
526 37: return false;
527 :
528 : // Constructors and destructors must be seen.
27: branch 1 taken
0: branch 2 not taken
0: branch 4 not taken
27: branch 5 taken
0: branch 6 not taken
27: branch 7 taken
529 27: if (FD->hasAttr<ConstructorAttr>() || FD->hasAttr<DestructorAttr>())
530 0: return true;
531 :
532 : // Otherwise, this is required unless it is static.
533 : //
534 : // FIXME: Inlines.
535 27: return FD->getStorageClass() != FunctionDecl::Static;
536 : } else {
537 55: const VarDecl *VD = cast<VarDecl>(D);
538 :
539 : // In C++, this doesn't need to be seen if it is marked "extern".
5: branch 1 taken
50: branch 2 taken
3: branch 4 taken
2: branch 5 taken
3: branch 7 taken
0: branch 8 not taken
0: branch 10 not taken
3: branch 11 taken
0: branch 12 not taken
55: branch 13 taken
540 55: if (Context.getLangOptions().CPlusPlus && !VD->getInit() &&
541 : (VD->getStorageClass() == VarDecl::Extern ||
542 : VD->isExternC()))
543 0: return false;
544 :
545 : // In C, this doesn't need to be seen unless it is a definition.
50: branch 1 taken
5: branch 2 taken
40: branch 4 taken
10: branch 5 taken
40: branch 6 taken
15: branch 7 taken
546 55: if (!Context.getLangOptions().CPlusPlus && !VD->getInit())
547 40: return false;
548 :
549 : // Otherwise, this is required unless it is static.
550 15: return VD->getStorageClass() != VarDecl::Static;
551 : }
552 : }
553 :
554 602: void PCHWriter::WriteDecl(ASTContext &Context, Decl *D) {
555 602: RecordData Record;
556 602: PCHDeclWriter W(*this, Context, Record);
557 :
558 : // If this declaration is also a DeclContext, write blocks for the
559 : // declarations that lexically stored inside its context and those
560 : // declarations that are visible from its context. These blocks
561 : // are written before the declaration itself so that we can put
562 : // their offsets into the record for the declaration.
563 602: uint64_t LexicalOffset = 0;
564 602: uint64_t VisibleOffset = 0;
565 602: DeclContext *DC = dyn_cast<DeclContext>(D);
208: branch 0 taken
394: branch 1 taken
566 602: if (DC) {
567 208: LexicalOffset = WriteDeclContextLexicalBlock(Context, DC);
568 208: VisibleOffset = WriteDeclContextVisibleBlock(Context, DC);
569 : }
570 :
571 : // Determine the ID for this declaration
572 602: pch::DeclID &ID = DeclIDs[D];
0: branch 0 not taken
602: branch 1 taken
573 602: if (ID == 0)
574 0: ID = DeclIDs.size();
575 :
576 602: unsigned Index = ID - 1;
577 :
578 : // Record the offset for this declaration
602: branch 1 taken
0: branch 2 not taken
579 602: if (DeclOffsets.size() == Index)
580 602: DeclOffsets.push_back(Stream.GetCurrentBitNo());
0: branch 1 not taken
0: branch 2 not taken
581 0: else if (DeclOffsets.size() < Index) {
582 0: DeclOffsets.resize(Index+1);
583 0: DeclOffsets[Index] = Stream.GetCurrentBitNo();
584 : }
585 :
586 : // Build and emit a record for this declaration
587 602: Record.clear();
588 602: W.Code = (pch::DeclCode)0;
589 602: W.AbbrevToUse = 0;
590 602: W.Visit(D);
208: branch 0 taken
394: branch 1 taken
591 602: if (DC) W.VisitDeclContext(DC, LexicalOffset, VisibleOffset);
592 :
0: branch 0 not taken
602: branch 1 taken
593 602: if (!W.Code)
594 : llvm::llvm_report_error(llvm::StringRef("unexpected declaration kind '") +
595 0: D->getDeclKindName() + "'");
596 602: Stream.EmitRecord(W.Code, Record, W.AbbrevToUse);
597 :
598 : // If the declaration had any attributes, write them now.
7: branch 1 taken
595: branch 2 taken
599 602: if (D->hasAttrs())
600 7: WriteAttributeRecord(D->getAttrs());
601 :
602 : // Flush any expressions that were written as part of this declaration.
603 602: FlushStmts();
604 :
605 : // Note "external" declarations so that we can add them to a record in the
606 : // PCH file later.
607 : //
608 : // FIXME: This should be renamed, the predicate is much more complicated.
42: branch 1 taken
560: branch 2 taken
609 602: if (isRequiredDecl(D, Context))
610 42: ExternalDefinitions.push_back(Index + 1);
611 602: }
Generated: 2010-02-10 01:31 by zcov