1 //===--- DeclPrinter.cpp - Printing implementation for Decl ASTs ----------===//
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 the Decl::print method, which pretty prints the
11 // AST back out to C/Objective-C/C++/Objective-C++ code.
12 //
13 //===----------------------------------------------------------------------===//
14 #include "clang/AST/ASTContext.h"
15 #include "clang/AST/Attr.h"
16 #include "clang/AST/Decl.h"
17 #include "clang/AST/DeclCXX.h"
18 #include "clang/AST/DeclObjC.h"
19 #include "clang/AST/DeclVisitor.h"
20 #include "clang/AST/Expr.h"
21 #include "clang/AST/ExprCXX.h"
22 #include "clang/AST/PrettyPrinter.h"
23 #include "clang/Basic/Module.h"
24 #include "llvm/Support/raw_ostream.h"
25 using namespace clang;
26
27 namespace {
28 class DeclPrinter : public DeclVisitor<DeclPrinter> {
29 raw_ostream &Out;
30 PrintingPolicy Policy;
31 unsigned Indentation;
32 bool PrintInstantiation;
33
Indent()34 raw_ostream& Indent() { return Indent(Indentation); }
35 raw_ostream& Indent(unsigned Indentation);
36 void ProcessDeclGroup(SmallVectorImpl<Decl*>& Decls);
37
38 void Print(AccessSpecifier AS);
39
40 public:
DeclPrinter(raw_ostream & Out,const PrintingPolicy & Policy,unsigned Indentation=0,bool PrintInstantiation=false)41 DeclPrinter(raw_ostream &Out, const PrintingPolicy &Policy,
42 unsigned Indentation = 0, bool PrintInstantiation = false)
43 : Out(Out), Policy(Policy), Indentation(Indentation),
44 PrintInstantiation(PrintInstantiation) { }
45
46 void VisitDeclContext(DeclContext *DC, bool Indent = true);
47
48 void VisitTranslationUnitDecl(TranslationUnitDecl *D);
49 void VisitTypedefDecl(TypedefDecl *D);
50 void VisitTypeAliasDecl(TypeAliasDecl *D);
51 void VisitEnumDecl(EnumDecl *D);
52 void VisitRecordDecl(RecordDecl *D);
53 void VisitEnumConstantDecl(EnumConstantDecl *D);
54 void VisitEmptyDecl(EmptyDecl *D);
55 void VisitFunctionDecl(FunctionDecl *D);
56 void VisitFriendDecl(FriendDecl *D);
57 void VisitFieldDecl(FieldDecl *D);
58 void VisitVarDecl(VarDecl *D);
59 void VisitLabelDecl(LabelDecl *D);
60 void VisitParmVarDecl(ParmVarDecl *D);
61 void VisitFileScopeAsmDecl(FileScopeAsmDecl *D);
62 void VisitImportDecl(ImportDecl *D);
63 void VisitStaticAssertDecl(StaticAssertDecl *D);
64 void VisitNamespaceDecl(NamespaceDecl *D);
65 void VisitUsingDirectiveDecl(UsingDirectiveDecl *D);
66 void VisitNamespaceAliasDecl(NamespaceAliasDecl *D);
67 void VisitCXXRecordDecl(CXXRecordDecl *D);
68 void VisitLinkageSpecDecl(LinkageSpecDecl *D);
69 void VisitTemplateDecl(const TemplateDecl *D);
70 void VisitFunctionTemplateDecl(FunctionTemplateDecl *D);
71 void VisitClassTemplateDecl(ClassTemplateDecl *D);
72 void VisitObjCMethodDecl(ObjCMethodDecl *D);
73 void VisitObjCImplementationDecl(ObjCImplementationDecl *D);
74 void VisitObjCInterfaceDecl(ObjCInterfaceDecl *D);
75 void VisitObjCProtocolDecl(ObjCProtocolDecl *D);
76 void VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D);
77 void VisitObjCCategoryDecl(ObjCCategoryDecl *D);
78 void VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *D);
79 void VisitObjCPropertyDecl(ObjCPropertyDecl *D);
80 void VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D);
81 void VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D);
82 void VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D);
83 void VisitUsingDecl(UsingDecl *D);
84 void VisitUsingShadowDecl(UsingShadowDecl *D);
85 void VisitOMPThreadPrivateDecl(OMPThreadPrivateDecl *D);
86
87 void PrintTemplateParameters(const TemplateParameterList *Params,
88 const TemplateArgumentList *Args = nullptr);
89 void prettyPrintAttributes(Decl *D);
90 void printDeclType(QualType T, StringRef DeclName, bool Pack = false);
91 };
92 }
93
print(raw_ostream & Out,unsigned Indentation,bool PrintInstantiation) const94 void Decl::print(raw_ostream &Out, unsigned Indentation,
95 bool PrintInstantiation) const {
96 print(Out, getASTContext().getPrintingPolicy(), Indentation, PrintInstantiation);
97 }
98
print(raw_ostream & Out,const PrintingPolicy & Policy,unsigned Indentation,bool PrintInstantiation) const99 void Decl::print(raw_ostream &Out, const PrintingPolicy &Policy,
100 unsigned Indentation, bool PrintInstantiation) const {
101 DeclPrinter Printer(Out, Policy, Indentation, PrintInstantiation);
102 Printer.Visit(const_cast<Decl*>(this));
103 }
104
GetBaseType(QualType T)105 static QualType GetBaseType(QualType T) {
106 // FIXME: This should be on the Type class!
107 QualType BaseType = T;
108 while (!BaseType->isSpecifierType()) {
109 if (isa<TypedefType>(BaseType))
110 break;
111 else if (const PointerType* PTy = BaseType->getAs<PointerType>())
112 BaseType = PTy->getPointeeType();
113 else if (const BlockPointerType *BPy = BaseType->getAs<BlockPointerType>())
114 BaseType = BPy->getPointeeType();
115 else if (const ArrayType* ATy = dyn_cast<ArrayType>(BaseType))
116 BaseType = ATy->getElementType();
117 else if (const FunctionType* FTy = BaseType->getAs<FunctionType>())
118 BaseType = FTy->getReturnType();
119 else if (const VectorType *VTy = BaseType->getAs<VectorType>())
120 BaseType = VTy->getElementType();
121 else if (const ReferenceType *RTy = BaseType->getAs<ReferenceType>())
122 BaseType = RTy->getPointeeType();
123 else
124 llvm_unreachable("Unknown declarator!");
125 }
126 return BaseType;
127 }
128
getDeclType(Decl * D)129 static QualType getDeclType(Decl* D) {
130 if (TypedefNameDecl* TDD = dyn_cast<TypedefNameDecl>(D))
131 return TDD->getUnderlyingType();
132 if (ValueDecl* VD = dyn_cast<ValueDecl>(D))
133 return VD->getType();
134 return QualType();
135 }
136
printGroup(Decl ** Begin,unsigned NumDecls,raw_ostream & Out,const PrintingPolicy & Policy,unsigned Indentation)137 void Decl::printGroup(Decl** Begin, unsigned NumDecls,
138 raw_ostream &Out, const PrintingPolicy &Policy,
139 unsigned Indentation) {
140 if (NumDecls == 1) {
141 (*Begin)->print(Out, Policy, Indentation);
142 return;
143 }
144
145 Decl** End = Begin + NumDecls;
146 TagDecl* TD = dyn_cast<TagDecl>(*Begin);
147 if (TD)
148 ++Begin;
149
150 PrintingPolicy SubPolicy(Policy);
151 if (TD && TD->isCompleteDefinition()) {
152 TD->print(Out, Policy, Indentation);
153 Out << " ";
154 SubPolicy.SuppressTag = true;
155 }
156
157 bool isFirst = true;
158 for ( ; Begin != End; ++Begin) {
159 if (isFirst) {
160 SubPolicy.SuppressSpecifiers = false;
161 isFirst = false;
162 } else {
163 if (!isFirst) Out << ", ";
164 SubPolicy.SuppressSpecifiers = true;
165 }
166
167 (*Begin)->print(Out, SubPolicy, Indentation);
168 }
169 }
170
dumpDeclContext() const171 LLVM_DUMP_METHOD void DeclContext::dumpDeclContext() const {
172 // Get the translation unit
173 const DeclContext *DC = this;
174 while (!DC->isTranslationUnit())
175 DC = DC->getParent();
176
177 ASTContext &Ctx = cast<TranslationUnitDecl>(DC)->getASTContext();
178 DeclPrinter Printer(llvm::errs(), Ctx.getPrintingPolicy(), 0);
179 Printer.VisitDeclContext(const_cast<DeclContext *>(this), /*Indent=*/false);
180 }
181
Indent(unsigned Indentation)182 raw_ostream& DeclPrinter::Indent(unsigned Indentation) {
183 for (unsigned i = 0; i != Indentation; ++i)
184 Out << " ";
185 return Out;
186 }
187
prettyPrintAttributes(Decl * D)188 void DeclPrinter::prettyPrintAttributes(Decl *D) {
189 if (Policy.PolishForDeclaration)
190 return;
191
192 if (D->hasAttrs()) {
193 AttrVec &Attrs = D->getAttrs();
194 for (AttrVec::const_iterator i=Attrs.begin(), e=Attrs.end(); i!=e; ++i) {
195 Attr *A = *i;
196 A->printPretty(Out, Policy);
197 }
198 }
199 }
200
printDeclType(QualType T,StringRef DeclName,bool Pack)201 void DeclPrinter::printDeclType(QualType T, StringRef DeclName, bool Pack) {
202 // Normally, a PackExpansionType is written as T[3]... (for instance, as a
203 // template argument), but if it is the type of a declaration, the ellipsis
204 // is placed before the name being declared.
205 if (auto *PET = T->getAs<PackExpansionType>()) {
206 Pack = true;
207 T = PET->getPattern();
208 }
209 T.print(Out, Policy, (Pack ? "..." : "") + DeclName);
210 }
211
ProcessDeclGroup(SmallVectorImpl<Decl * > & Decls)212 void DeclPrinter::ProcessDeclGroup(SmallVectorImpl<Decl*>& Decls) {
213 this->Indent();
214 Decl::printGroup(Decls.data(), Decls.size(), Out, Policy, Indentation);
215 Out << ";\n";
216 Decls.clear();
217
218 }
219
Print(AccessSpecifier AS)220 void DeclPrinter::Print(AccessSpecifier AS) {
221 switch(AS) {
222 case AS_none: llvm_unreachable("No access specifier!");
223 case AS_public: Out << "public"; break;
224 case AS_protected: Out << "protected"; break;
225 case AS_private: Out << "private"; break;
226 }
227 }
228
229 //----------------------------------------------------------------------------
230 // Common C declarations
231 //----------------------------------------------------------------------------
232
VisitDeclContext(DeclContext * DC,bool Indent)233 void DeclPrinter::VisitDeclContext(DeclContext *DC, bool Indent) {
234 if (Policy.TerseOutput)
235 return;
236
237 if (Indent)
238 Indentation += Policy.Indentation;
239
240 SmallVector<Decl*, 2> Decls;
241 for (DeclContext::decl_iterator D = DC->decls_begin(), DEnd = DC->decls_end();
242 D != DEnd; ++D) {
243
244 // Don't print ObjCIvarDecls, as they are printed when visiting the
245 // containing ObjCInterfaceDecl.
246 if (isa<ObjCIvarDecl>(*D))
247 continue;
248
249 // Skip over implicit declarations in pretty-printing mode.
250 if (D->isImplicit())
251 continue;
252
253 // The next bits of code handles stuff like "struct {int x;} a,b"; we're
254 // forced to merge the declarations because there's no other way to
255 // refer to the struct in question. This limited merging is safe without
256 // a bunch of other checks because it only merges declarations directly
257 // referring to the tag, not typedefs.
258 //
259 // Check whether the current declaration should be grouped with a previous
260 // unnamed struct.
261 QualType CurDeclType = getDeclType(*D);
262 if (!Decls.empty() && !CurDeclType.isNull()) {
263 QualType BaseType = GetBaseType(CurDeclType);
264 if (!BaseType.isNull() && isa<ElaboratedType>(BaseType))
265 BaseType = cast<ElaboratedType>(BaseType)->getNamedType();
266 if (!BaseType.isNull() && isa<TagType>(BaseType) &&
267 cast<TagType>(BaseType)->getDecl() == Decls[0]) {
268 Decls.push_back(*D);
269 continue;
270 }
271 }
272
273 // If we have a merged group waiting to be handled, handle it now.
274 if (!Decls.empty())
275 ProcessDeclGroup(Decls);
276
277 // If the current declaration is an unnamed tag type, save it
278 // so we can merge it with the subsequent declaration(s) using it.
279 if (isa<TagDecl>(*D) && !cast<TagDecl>(*D)->getIdentifier()) {
280 Decls.push_back(*D);
281 continue;
282 }
283
284 if (isa<AccessSpecDecl>(*D)) {
285 Indentation -= Policy.Indentation;
286 this->Indent();
287 Print(D->getAccess());
288 Out << ":\n";
289 Indentation += Policy.Indentation;
290 continue;
291 }
292
293 this->Indent();
294 Visit(*D);
295
296 // FIXME: Need to be able to tell the DeclPrinter when
297 const char *Terminator = nullptr;
298 if (isa<OMPThreadPrivateDecl>(*D))
299 Terminator = nullptr;
300 else if (isa<FunctionDecl>(*D) &&
301 cast<FunctionDecl>(*D)->isThisDeclarationADefinition())
302 Terminator = nullptr;
303 else if (isa<ObjCMethodDecl>(*D) && cast<ObjCMethodDecl>(*D)->getBody())
304 Terminator = nullptr;
305 else if (isa<NamespaceDecl>(*D) || isa<LinkageSpecDecl>(*D) ||
306 isa<ObjCImplementationDecl>(*D) ||
307 isa<ObjCInterfaceDecl>(*D) ||
308 isa<ObjCProtocolDecl>(*D) ||
309 isa<ObjCCategoryImplDecl>(*D) ||
310 isa<ObjCCategoryDecl>(*D))
311 Terminator = nullptr;
312 else if (isa<EnumConstantDecl>(*D)) {
313 DeclContext::decl_iterator Next = D;
314 ++Next;
315 if (Next != DEnd)
316 Terminator = ",";
317 } else
318 Terminator = ";";
319
320 if (Terminator)
321 Out << Terminator;
322 Out << "\n";
323 }
324
325 if (!Decls.empty())
326 ProcessDeclGroup(Decls);
327
328 if (Indent)
329 Indentation -= Policy.Indentation;
330 }
331
VisitTranslationUnitDecl(TranslationUnitDecl * D)332 void DeclPrinter::VisitTranslationUnitDecl(TranslationUnitDecl *D) {
333 VisitDeclContext(D, false);
334 }
335
VisitTypedefDecl(TypedefDecl * D)336 void DeclPrinter::VisitTypedefDecl(TypedefDecl *D) {
337 if (!Policy.SuppressSpecifiers) {
338 Out << "typedef ";
339
340 if (D->isModulePrivate())
341 Out << "__module_private__ ";
342 }
343 D->getTypeSourceInfo()->getType().print(Out, Policy, D->getName());
344 prettyPrintAttributes(D);
345 }
346
VisitTypeAliasDecl(TypeAliasDecl * D)347 void DeclPrinter::VisitTypeAliasDecl(TypeAliasDecl *D) {
348 Out << "using " << *D;
349 prettyPrintAttributes(D);
350 Out << " = " << D->getTypeSourceInfo()->getType().getAsString(Policy);
351 }
352
VisitEnumDecl(EnumDecl * D)353 void DeclPrinter::VisitEnumDecl(EnumDecl *D) {
354 if (!Policy.SuppressSpecifiers && D->isModulePrivate())
355 Out << "__module_private__ ";
356 Out << "enum ";
357 if (D->isScoped()) {
358 if (D->isScopedUsingClassTag())
359 Out << "class ";
360 else
361 Out << "struct ";
362 }
363 Out << *D;
364
365 if (D->isFixed())
366 Out << " : " << D->getIntegerType().stream(Policy);
367
368 if (D->isCompleteDefinition()) {
369 Out << " {\n";
370 VisitDeclContext(D);
371 Indent() << "}";
372 }
373 prettyPrintAttributes(D);
374 }
375
VisitRecordDecl(RecordDecl * D)376 void DeclPrinter::VisitRecordDecl(RecordDecl *D) {
377 if (!Policy.SuppressSpecifiers && D->isModulePrivate())
378 Out << "__module_private__ ";
379 Out << D->getKindName();
380
381 prettyPrintAttributes(D);
382
383 if (D->getIdentifier())
384 Out << ' ' << *D;
385
386 if (D->isCompleteDefinition()) {
387 Out << " {\n";
388 VisitDeclContext(D);
389 Indent() << "}";
390 }
391 }
392
VisitEnumConstantDecl(EnumConstantDecl * D)393 void DeclPrinter::VisitEnumConstantDecl(EnumConstantDecl *D) {
394 Out << *D;
395 if (Expr *Init = D->getInitExpr()) {
396 Out << " = ";
397 Init->printPretty(Out, nullptr, Policy, Indentation);
398 }
399 }
400
VisitFunctionDecl(FunctionDecl * D)401 void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
402 CXXConstructorDecl *CDecl = dyn_cast<CXXConstructorDecl>(D);
403 CXXConversionDecl *ConversionDecl = dyn_cast<CXXConversionDecl>(D);
404 if (!Policy.SuppressSpecifiers) {
405 switch (D->getStorageClass()) {
406 case SC_None: break;
407 case SC_Extern: Out << "extern "; break;
408 case SC_Static: Out << "static "; break;
409 case SC_PrivateExtern: Out << "__private_extern__ "; break;
410 case SC_Auto: case SC_Register: case SC_OpenCLWorkGroupLocal:
411 llvm_unreachable("invalid for functions");
412 }
413
414 if (D->isInlineSpecified()) Out << "inline ";
415 if (D->isVirtualAsWritten()) Out << "virtual ";
416 if (D->isModulePrivate()) Out << "__module_private__ ";
417 if (D->isConstexpr() && !D->isExplicitlyDefaulted()) Out << "constexpr ";
418 if ((CDecl && CDecl->isExplicitSpecified()) ||
419 (ConversionDecl && ConversionDecl->isExplicit()))
420 Out << "explicit ";
421 }
422
423 PrintingPolicy SubPolicy(Policy);
424 SubPolicy.SuppressSpecifiers = false;
425 std::string Proto = D->getNameInfo().getAsString();
426
427 QualType Ty = D->getType();
428 while (const ParenType *PT = dyn_cast<ParenType>(Ty)) {
429 Proto = '(' + Proto + ')';
430 Ty = PT->getInnerType();
431 }
432
433 if (const FunctionType *AFT = Ty->getAs<FunctionType>()) {
434 const FunctionProtoType *FT = nullptr;
435 if (D->hasWrittenPrototype())
436 FT = dyn_cast<FunctionProtoType>(AFT);
437
438 Proto += "(";
439 if (FT) {
440 llvm::raw_string_ostream POut(Proto);
441 DeclPrinter ParamPrinter(POut, SubPolicy, Indentation);
442 for (unsigned i = 0, e = D->getNumParams(); i != e; ++i) {
443 if (i) POut << ", ";
444 ParamPrinter.VisitParmVarDecl(D->getParamDecl(i));
445 }
446
447 if (FT->isVariadic()) {
448 if (D->getNumParams()) POut << ", ";
449 POut << "...";
450 }
451 } else if (D->doesThisDeclarationHaveABody() && !D->hasPrototype()) {
452 for (unsigned i = 0, e = D->getNumParams(); i != e; ++i) {
453 if (i)
454 Proto += ", ";
455 Proto += D->getParamDecl(i)->getNameAsString();
456 }
457 }
458
459 Proto += ")";
460
461 if (FT) {
462 if (FT->isConst())
463 Proto += " const";
464 if (FT->isVolatile())
465 Proto += " volatile";
466 if (FT->isRestrict())
467 Proto += " restrict";
468
469 switch (FT->getRefQualifier()) {
470 case RQ_None:
471 break;
472 case RQ_LValue:
473 Proto += " &";
474 break;
475 case RQ_RValue:
476 Proto += " &&";
477 break;
478 }
479 }
480
481 if (FT && FT->hasDynamicExceptionSpec()) {
482 Proto += " throw(";
483 if (FT->getExceptionSpecType() == EST_MSAny)
484 Proto += "...";
485 else
486 for (unsigned I = 0, N = FT->getNumExceptions(); I != N; ++I) {
487 if (I)
488 Proto += ", ";
489
490 Proto += FT->getExceptionType(I).getAsString(SubPolicy);
491 }
492 Proto += ")";
493 } else if (FT && isNoexceptExceptionSpec(FT->getExceptionSpecType())) {
494 Proto += " noexcept";
495 if (FT->getExceptionSpecType() == EST_ComputedNoexcept) {
496 Proto += "(";
497 llvm::raw_string_ostream EOut(Proto);
498 FT->getNoexceptExpr()->printPretty(EOut, nullptr, SubPolicy,
499 Indentation);
500 EOut.flush();
501 Proto += EOut.str();
502 Proto += ")";
503 }
504 }
505
506 if (CDecl) {
507 bool HasInitializerList = false;
508 for (const auto *BMInitializer : CDecl->inits()) {
509 if (BMInitializer->isInClassMemberInitializer())
510 continue;
511
512 if (!HasInitializerList) {
513 Proto += " : ";
514 Out << Proto;
515 Proto.clear();
516 HasInitializerList = true;
517 } else
518 Out << ", ";
519
520 if (BMInitializer->isAnyMemberInitializer()) {
521 FieldDecl *FD = BMInitializer->getAnyMember();
522 Out << *FD;
523 } else {
524 Out << QualType(BMInitializer->getBaseClass(), 0).getAsString(Policy);
525 }
526
527 Out << "(";
528 if (!BMInitializer->getInit()) {
529 // Nothing to print
530 } else {
531 Expr *Init = BMInitializer->getInit();
532 if (ExprWithCleanups *Tmp = dyn_cast<ExprWithCleanups>(Init))
533 Init = Tmp->getSubExpr();
534
535 Init = Init->IgnoreParens();
536
537 Expr *SimpleInit = nullptr;
538 Expr **Args = nullptr;
539 unsigned NumArgs = 0;
540 if (ParenListExpr *ParenList = dyn_cast<ParenListExpr>(Init)) {
541 Args = ParenList->getExprs();
542 NumArgs = ParenList->getNumExprs();
543 } else if (CXXConstructExpr *Construct
544 = dyn_cast<CXXConstructExpr>(Init)) {
545 Args = Construct->getArgs();
546 NumArgs = Construct->getNumArgs();
547 } else
548 SimpleInit = Init;
549
550 if (SimpleInit)
551 SimpleInit->printPretty(Out, nullptr, Policy, Indentation);
552 else {
553 for (unsigned I = 0; I != NumArgs; ++I) {
554 assert(Args[I] != nullptr && "Expected non-null Expr");
555 if (isa<CXXDefaultArgExpr>(Args[I]))
556 break;
557
558 if (I)
559 Out << ", ";
560 Args[I]->printPretty(Out, nullptr, Policy, Indentation);
561 }
562 }
563 }
564 Out << ")";
565 if (BMInitializer->isPackExpansion())
566 Out << "...";
567 }
568 } else if (!ConversionDecl && !isa<CXXDestructorDecl>(D)) {
569 if (FT && FT->hasTrailingReturn()) {
570 Out << "auto " << Proto << " -> ";
571 Proto.clear();
572 }
573 AFT->getReturnType().print(Out, Policy, Proto);
574 Proto.clear();
575 }
576 Out << Proto;
577 } else {
578 Ty.print(Out, Policy, Proto);
579 }
580
581 prettyPrintAttributes(D);
582
583 if (D->isPure())
584 Out << " = 0";
585 else if (D->isDeletedAsWritten())
586 Out << " = delete";
587 else if (D->isExplicitlyDefaulted())
588 Out << " = default";
589 else if (D->doesThisDeclarationHaveABody() && !Policy.TerseOutput) {
590 if (!D->hasPrototype() && D->getNumParams()) {
591 // This is a K&R function definition, so we need to print the
592 // parameters.
593 Out << '\n';
594 DeclPrinter ParamPrinter(Out, SubPolicy, Indentation);
595 Indentation += Policy.Indentation;
596 for (unsigned i = 0, e = D->getNumParams(); i != e; ++i) {
597 Indent();
598 ParamPrinter.VisitParmVarDecl(D->getParamDecl(i));
599 Out << ";\n";
600 }
601 Indentation -= Policy.Indentation;
602 } else
603 Out << ' ';
604
605 if (D->getBody())
606 D->getBody()->printPretty(Out, nullptr, SubPolicy, Indentation);
607 Out << '\n';
608 }
609 }
610
VisitFriendDecl(FriendDecl * D)611 void DeclPrinter::VisitFriendDecl(FriendDecl *D) {
612 if (TypeSourceInfo *TSI = D->getFriendType()) {
613 unsigned NumTPLists = D->getFriendTypeNumTemplateParameterLists();
614 for (unsigned i = 0; i < NumTPLists; ++i)
615 PrintTemplateParameters(D->getFriendTypeTemplateParameterList(i));
616 Out << "friend ";
617 Out << " " << TSI->getType().getAsString(Policy);
618 }
619 else if (FunctionDecl *FD =
620 dyn_cast<FunctionDecl>(D->getFriendDecl())) {
621 Out << "friend ";
622 VisitFunctionDecl(FD);
623 }
624 else if (FunctionTemplateDecl *FTD =
625 dyn_cast<FunctionTemplateDecl>(D->getFriendDecl())) {
626 Out << "friend ";
627 VisitFunctionTemplateDecl(FTD);
628 }
629 else if (ClassTemplateDecl *CTD =
630 dyn_cast<ClassTemplateDecl>(D->getFriendDecl())) {
631 Out << "friend ";
632 VisitRedeclarableTemplateDecl(CTD);
633 }
634 }
635
VisitFieldDecl(FieldDecl * D)636 void DeclPrinter::VisitFieldDecl(FieldDecl *D) {
637 if (!Policy.SuppressSpecifiers && D->isMutable())
638 Out << "mutable ";
639 if (!Policy.SuppressSpecifiers && D->isModulePrivate())
640 Out << "__module_private__ ";
641
642 Out << D->getASTContext().getUnqualifiedObjCPointerType(D->getType()).
643 stream(Policy, D->getName());
644
645 if (D->isBitField()) {
646 Out << " : ";
647 D->getBitWidth()->printPretty(Out, nullptr, Policy, Indentation);
648 }
649
650 Expr *Init = D->getInClassInitializer();
651 if (!Policy.SuppressInitializers && Init) {
652 if (D->getInClassInitStyle() == ICIS_ListInit)
653 Out << " ";
654 else
655 Out << " = ";
656 Init->printPretty(Out, nullptr, Policy, Indentation);
657 }
658 prettyPrintAttributes(D);
659 }
660
VisitLabelDecl(LabelDecl * D)661 void DeclPrinter::VisitLabelDecl(LabelDecl *D) {
662 Out << *D << ":";
663 }
664
VisitVarDecl(VarDecl * D)665 void DeclPrinter::VisitVarDecl(VarDecl *D) {
666 if (!Policy.SuppressSpecifiers) {
667 StorageClass SC = D->getStorageClass();
668 if (SC != SC_None)
669 Out << VarDecl::getStorageClassSpecifierString(SC) << " ";
670
671 switch (D->getTSCSpec()) {
672 case TSCS_unspecified:
673 break;
674 case TSCS___thread:
675 Out << "__thread ";
676 break;
677 case TSCS__Thread_local:
678 Out << "_Thread_local ";
679 break;
680 case TSCS_thread_local:
681 Out << "thread_local ";
682 break;
683 }
684
685 if (D->isModulePrivate())
686 Out << "__module_private__ ";
687 }
688
689 QualType T = D->getTypeSourceInfo()
690 ? D->getTypeSourceInfo()->getType()
691 : D->getASTContext().getUnqualifiedObjCPointerType(D->getType());
692 printDeclType(T, D->getName());
693 Expr *Init = D->getInit();
694 if (!Policy.SuppressInitializers && Init) {
695 bool ImplicitInit = false;
696 if (CXXConstructExpr *Construct =
697 dyn_cast<CXXConstructExpr>(Init->IgnoreImplicit())) {
698 if (D->getInitStyle() == VarDecl::CallInit &&
699 !Construct->isListInitialization()) {
700 ImplicitInit = Construct->getNumArgs() == 0 ||
701 Construct->getArg(0)->isDefaultArgument();
702 }
703 }
704 if (!ImplicitInit) {
705 if ((D->getInitStyle() == VarDecl::CallInit) && !isa<ParenListExpr>(Init))
706 Out << "(";
707 else if (D->getInitStyle() == VarDecl::CInit) {
708 Out << " = ";
709 }
710 Init->printPretty(Out, nullptr, Policy, Indentation);
711 if ((D->getInitStyle() == VarDecl::CallInit) && !isa<ParenListExpr>(Init))
712 Out << ")";
713 }
714 }
715 prettyPrintAttributes(D);
716 }
717
VisitParmVarDecl(ParmVarDecl * D)718 void DeclPrinter::VisitParmVarDecl(ParmVarDecl *D) {
719 VisitVarDecl(D);
720 }
721
VisitFileScopeAsmDecl(FileScopeAsmDecl * D)722 void DeclPrinter::VisitFileScopeAsmDecl(FileScopeAsmDecl *D) {
723 Out << "__asm (";
724 D->getAsmString()->printPretty(Out, nullptr, Policy, Indentation);
725 Out << ")";
726 }
727
VisitImportDecl(ImportDecl * D)728 void DeclPrinter::VisitImportDecl(ImportDecl *D) {
729 Out << "@import " << D->getImportedModule()->getFullModuleName()
730 << ";\n";
731 }
732
VisitStaticAssertDecl(StaticAssertDecl * D)733 void DeclPrinter::VisitStaticAssertDecl(StaticAssertDecl *D) {
734 Out << "static_assert(";
735 D->getAssertExpr()->printPretty(Out, nullptr, Policy, Indentation);
736 Out << ", ";
737 D->getMessage()->printPretty(Out, nullptr, Policy, Indentation);
738 Out << ")";
739 }
740
741 //----------------------------------------------------------------------------
742 // C++ declarations
743 //----------------------------------------------------------------------------
VisitNamespaceDecl(NamespaceDecl * D)744 void DeclPrinter::VisitNamespaceDecl(NamespaceDecl *D) {
745 if (D->isInline())
746 Out << "inline ";
747 Out << "namespace " << *D << " {\n";
748 VisitDeclContext(D);
749 Indent() << "}";
750 }
751
VisitUsingDirectiveDecl(UsingDirectiveDecl * D)752 void DeclPrinter::VisitUsingDirectiveDecl(UsingDirectiveDecl *D) {
753 Out << "using namespace ";
754 if (D->getQualifier())
755 D->getQualifier()->print(Out, Policy);
756 Out << *D->getNominatedNamespaceAsWritten();
757 }
758
VisitNamespaceAliasDecl(NamespaceAliasDecl * D)759 void DeclPrinter::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) {
760 Out << "namespace " << *D << " = ";
761 if (D->getQualifier())
762 D->getQualifier()->print(Out, Policy);
763 Out << *D->getAliasedNamespace();
764 }
765
VisitEmptyDecl(EmptyDecl * D)766 void DeclPrinter::VisitEmptyDecl(EmptyDecl *D) {
767 prettyPrintAttributes(D);
768 }
769
VisitCXXRecordDecl(CXXRecordDecl * D)770 void DeclPrinter::VisitCXXRecordDecl(CXXRecordDecl *D) {
771 if (!Policy.SuppressSpecifiers && D->isModulePrivate())
772 Out << "__module_private__ ";
773 Out << D->getKindName();
774
775 prettyPrintAttributes(D);
776
777 if (D->getIdentifier())
778 Out << ' ' << *D;
779
780 if (D->isCompleteDefinition()) {
781 // Print the base classes
782 if (D->getNumBases()) {
783 Out << " : ";
784 for (CXXRecordDecl::base_class_iterator Base = D->bases_begin(),
785 BaseEnd = D->bases_end(); Base != BaseEnd; ++Base) {
786 if (Base != D->bases_begin())
787 Out << ", ";
788
789 if (Base->isVirtual())
790 Out << "virtual ";
791
792 AccessSpecifier AS = Base->getAccessSpecifierAsWritten();
793 if (AS != AS_none) {
794 Print(AS);
795 Out << " ";
796 }
797 Out << Base->getType().getAsString(Policy);
798
799 if (Base->isPackExpansion())
800 Out << "...";
801 }
802 }
803
804 // Print the class definition
805 // FIXME: Doesn't print access specifiers, e.g., "public:"
806 Out << " {\n";
807 VisitDeclContext(D);
808 Indent() << "}";
809 }
810 }
811
VisitLinkageSpecDecl(LinkageSpecDecl * D)812 void DeclPrinter::VisitLinkageSpecDecl(LinkageSpecDecl *D) {
813 const char *l;
814 if (D->getLanguage() == LinkageSpecDecl::lang_c)
815 l = "C";
816 else {
817 assert(D->getLanguage() == LinkageSpecDecl::lang_cxx &&
818 "unknown language in linkage specification");
819 l = "C++";
820 }
821
822 Out << "extern \"" << l << "\" ";
823 if (D->hasBraces()) {
824 Out << "{\n";
825 VisitDeclContext(D);
826 Indent() << "}";
827 } else
828 Visit(*D->decls_begin());
829 }
830
PrintTemplateParameters(const TemplateParameterList * Params,const TemplateArgumentList * Args)831 void DeclPrinter::PrintTemplateParameters(const TemplateParameterList *Params,
832 const TemplateArgumentList *Args) {
833 assert(Params);
834 assert(!Args || Params->size() == Args->size());
835
836 Out << "template <";
837
838 for (unsigned i = 0, e = Params->size(); i != e; ++i) {
839 if (i != 0)
840 Out << ", ";
841
842 const Decl *Param = Params->getParam(i);
843 if (const TemplateTypeParmDecl *TTP =
844 dyn_cast<TemplateTypeParmDecl>(Param)) {
845
846 if (TTP->wasDeclaredWithTypename())
847 Out << "typename ";
848 else
849 Out << "class ";
850
851 if (TTP->isParameterPack())
852 Out << "...";
853
854 Out << *TTP;
855
856 if (Args) {
857 Out << " = ";
858 Args->get(i).print(Policy, Out);
859 } else if (TTP->hasDefaultArgument()) {
860 Out << " = ";
861 Out << TTP->getDefaultArgument().getAsString(Policy);
862 };
863 } else if (const NonTypeTemplateParmDecl *NTTP =
864 dyn_cast<NonTypeTemplateParmDecl>(Param)) {
865 StringRef Name;
866 if (IdentifierInfo *II = NTTP->getIdentifier())
867 Name = II->getName();
868 printDeclType(NTTP->getType(), Name, NTTP->isParameterPack());
869
870 if (Args) {
871 Out << " = ";
872 Args->get(i).print(Policy, Out);
873 } else if (NTTP->hasDefaultArgument()) {
874 Out << " = ";
875 NTTP->getDefaultArgument()->printPretty(Out, nullptr, Policy,
876 Indentation);
877 }
878 } else if (const TemplateTemplateParmDecl *TTPD =
879 dyn_cast<TemplateTemplateParmDecl>(Param)) {
880 VisitTemplateDecl(TTPD);
881 // FIXME: print the default argument, if present.
882 }
883 }
884
885 Out << "> ";
886 }
887
VisitTemplateDecl(const TemplateDecl * D)888 void DeclPrinter::VisitTemplateDecl(const TemplateDecl *D) {
889 PrintTemplateParameters(D->getTemplateParameters());
890
891 if (const TemplateTemplateParmDecl *TTP =
892 dyn_cast<TemplateTemplateParmDecl>(D)) {
893 Out << "class ";
894 if (TTP->isParameterPack())
895 Out << "...";
896 Out << D->getName();
897 } else {
898 Visit(D->getTemplatedDecl());
899 }
900 }
901
VisitFunctionTemplateDecl(FunctionTemplateDecl * D)902 void DeclPrinter::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
903 if (PrintInstantiation) {
904 TemplateParameterList *Params = D->getTemplateParameters();
905 for (auto *I : D->specializations()) {
906 PrintTemplateParameters(Params, I->getTemplateSpecializationArgs());
907 Visit(I);
908 }
909 }
910
911 return VisitRedeclarableTemplateDecl(D);
912 }
913
VisitClassTemplateDecl(ClassTemplateDecl * D)914 void DeclPrinter::VisitClassTemplateDecl(ClassTemplateDecl *D) {
915 if (PrintInstantiation) {
916 TemplateParameterList *Params = D->getTemplateParameters();
917 for (auto *I : D->specializations()) {
918 PrintTemplateParameters(Params, &I->getTemplateArgs());
919 Visit(I);
920 Out << '\n';
921 }
922 }
923
924 return VisitRedeclarableTemplateDecl(D);
925 }
926
927 //----------------------------------------------------------------------------
928 // Objective-C declarations
929 //----------------------------------------------------------------------------
930
VisitObjCMethodDecl(ObjCMethodDecl * OMD)931 void DeclPrinter::VisitObjCMethodDecl(ObjCMethodDecl *OMD) {
932 if (OMD->isInstanceMethod())
933 Out << "- ";
934 else
935 Out << "+ ";
936 if (!OMD->getReturnType().isNull())
937 Out << '(' << OMD->getASTContext()
938 .getUnqualifiedObjCPointerType(OMD->getReturnType())
939 .getAsString(Policy) << ")";
940
941 std::string name = OMD->getSelector().getAsString();
942 std::string::size_type pos, lastPos = 0;
943 for (const auto *PI : OMD->params()) {
944 // FIXME: selector is missing here!
945 pos = name.find_first_of(':', lastPos);
946 Out << " " << name.substr(lastPos, pos - lastPos);
947 Out << ":(" << PI->getASTContext().getUnqualifiedObjCPointerType(PI->getType()).
948 getAsString(Policy) << ')' << *PI;
949 lastPos = pos + 1;
950 }
951
952 if (OMD->param_begin() == OMD->param_end())
953 Out << " " << name;
954
955 if (OMD->isVariadic())
956 Out << ", ...";
957
958 prettyPrintAttributes(OMD);
959
960 if (OMD->getBody() && !Policy.TerseOutput) {
961 Out << ' ';
962 OMD->getBody()->printPretty(Out, nullptr, Policy);
963 }
964 else if (Policy.PolishForDeclaration)
965 Out << ';';
966 }
967
VisitObjCImplementationDecl(ObjCImplementationDecl * OID)968 void DeclPrinter::VisitObjCImplementationDecl(ObjCImplementationDecl *OID) {
969 std::string I = OID->getNameAsString();
970 ObjCInterfaceDecl *SID = OID->getSuperClass();
971
972 bool eolnOut = false;
973 if (SID)
974 Out << "@implementation " << I << " : " << *SID;
975 else
976 Out << "@implementation " << I;
977
978 if (OID->ivar_size() > 0) {
979 Out << "{\n";
980 eolnOut = true;
981 Indentation += Policy.Indentation;
982 for (const auto *I : OID->ivars()) {
983 Indent() << I->getASTContext().getUnqualifiedObjCPointerType(I->getType()).
984 getAsString(Policy) << ' ' << *I << ";\n";
985 }
986 Indentation -= Policy.Indentation;
987 Out << "}\n";
988 }
989 else if (SID || (OID->decls_begin() != OID->decls_end())) {
990 Out << "\n";
991 eolnOut = true;
992 }
993 VisitDeclContext(OID, false);
994 if (!eolnOut)
995 Out << "\n";
996 Out << "@end";
997 }
998
VisitObjCInterfaceDecl(ObjCInterfaceDecl * OID)999 void DeclPrinter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *OID) {
1000 std::string I = OID->getNameAsString();
1001 ObjCInterfaceDecl *SID = OID->getSuperClass();
1002
1003 if (!OID->isThisDeclarationADefinition()) {
1004 Out << "@class " << I << ";";
1005 return;
1006 }
1007 bool eolnOut = false;
1008 if (SID)
1009 Out << "@interface " << I << " : " << *SID;
1010 else
1011 Out << "@interface " << I;
1012
1013 // Protocols?
1014 const ObjCList<ObjCProtocolDecl> &Protocols = OID->getReferencedProtocols();
1015 if (!Protocols.empty()) {
1016 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
1017 E = Protocols.end(); I != E; ++I)
1018 Out << (I == Protocols.begin() ? '<' : ',') << **I;
1019 Out << "> ";
1020 }
1021
1022 if (OID->ivar_size() > 0) {
1023 Out << "{\n";
1024 eolnOut = true;
1025 Indentation += Policy.Indentation;
1026 for (const auto *I : OID->ivars()) {
1027 Indent() << I->getASTContext()
1028 .getUnqualifiedObjCPointerType(I->getType())
1029 .getAsString(Policy) << ' ' << *I << ";\n";
1030 }
1031 Indentation -= Policy.Indentation;
1032 Out << "}\n";
1033 }
1034 else if (SID || (OID->decls_begin() != OID->decls_end())) {
1035 Out << "\n";
1036 eolnOut = true;
1037 }
1038
1039 VisitDeclContext(OID, false);
1040 if (!eolnOut)
1041 Out << "\n";
1042 Out << "@end";
1043 // FIXME: implement the rest...
1044 }
1045
VisitObjCProtocolDecl(ObjCProtocolDecl * PID)1046 void DeclPrinter::VisitObjCProtocolDecl(ObjCProtocolDecl *PID) {
1047 if (!PID->isThisDeclarationADefinition()) {
1048 Out << "@protocol " << *PID << ";\n";
1049 return;
1050 }
1051 // Protocols?
1052 const ObjCList<ObjCProtocolDecl> &Protocols = PID->getReferencedProtocols();
1053 if (!Protocols.empty()) {
1054 Out << "@protocol " << *PID;
1055 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
1056 E = Protocols.end(); I != E; ++I)
1057 Out << (I == Protocols.begin() ? '<' : ',') << **I;
1058 Out << ">\n";
1059 } else
1060 Out << "@protocol " << *PID << '\n';
1061 VisitDeclContext(PID, false);
1062 Out << "@end";
1063 }
1064
VisitObjCCategoryImplDecl(ObjCCategoryImplDecl * PID)1065 void DeclPrinter::VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *PID) {
1066 Out << "@implementation " << *PID->getClassInterface() << '(' << *PID <<")\n";
1067
1068 VisitDeclContext(PID, false);
1069 Out << "@end";
1070 // FIXME: implement the rest...
1071 }
1072
VisitObjCCategoryDecl(ObjCCategoryDecl * PID)1073 void DeclPrinter::VisitObjCCategoryDecl(ObjCCategoryDecl *PID) {
1074 Out << "@interface " << *PID->getClassInterface() << '(' << *PID << ")\n";
1075 if (PID->ivar_size() > 0) {
1076 Out << "{\n";
1077 Indentation += Policy.Indentation;
1078 for (const auto *I : PID->ivars())
1079 Indent() << I->getASTContext().getUnqualifiedObjCPointerType(I->getType()).
1080 getAsString(Policy) << ' ' << *I << ";\n";
1081 Indentation -= Policy.Indentation;
1082 Out << "}\n";
1083 }
1084
1085 VisitDeclContext(PID, false);
1086 Out << "@end";
1087
1088 // FIXME: implement the rest...
1089 }
1090
VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl * AID)1091 void DeclPrinter::VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *AID) {
1092 Out << "@compatibility_alias " << *AID
1093 << ' ' << *AID->getClassInterface() << ";\n";
1094 }
1095
1096 /// PrintObjCPropertyDecl - print a property declaration.
1097 ///
VisitObjCPropertyDecl(ObjCPropertyDecl * PDecl)1098 void DeclPrinter::VisitObjCPropertyDecl(ObjCPropertyDecl *PDecl) {
1099 if (PDecl->getPropertyImplementation() == ObjCPropertyDecl::Required)
1100 Out << "@required\n";
1101 else if (PDecl->getPropertyImplementation() == ObjCPropertyDecl::Optional)
1102 Out << "@optional\n";
1103
1104 Out << "@property";
1105 if (PDecl->getPropertyAttributes() != ObjCPropertyDecl::OBJC_PR_noattr) {
1106 bool first = true;
1107 Out << " (";
1108 if (PDecl->getPropertyAttributes() &
1109 ObjCPropertyDecl::OBJC_PR_readonly) {
1110 Out << (first ? ' ' : ',') << "readonly";
1111 first = false;
1112 }
1113
1114 if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_getter) {
1115 Out << (first ? ' ' : ',') << "getter = ";
1116 PDecl->getGetterName().print(Out);
1117 first = false;
1118 }
1119 if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_setter) {
1120 Out << (first ? ' ' : ',') << "setter = ";
1121 PDecl->getSetterName().print(Out);
1122 first = false;
1123 }
1124
1125 if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_assign) {
1126 Out << (first ? ' ' : ',') << "assign";
1127 first = false;
1128 }
1129
1130 if (PDecl->getPropertyAttributes() &
1131 ObjCPropertyDecl::OBJC_PR_readwrite) {
1132 Out << (first ? ' ' : ',') << "readwrite";
1133 first = false;
1134 }
1135
1136 if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_retain) {
1137 Out << (first ? ' ' : ',') << "retain";
1138 first = false;
1139 }
1140
1141 if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_strong) {
1142 Out << (first ? ' ' : ',') << "strong";
1143 first = false;
1144 }
1145
1146 if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_copy) {
1147 Out << (first ? ' ' : ',') << "copy";
1148 first = false;
1149 }
1150
1151 if (PDecl->getPropertyAttributes() &
1152 ObjCPropertyDecl::OBJC_PR_nonatomic) {
1153 Out << (first ? ' ' : ',') << "nonatomic";
1154 first = false;
1155 }
1156 if (PDecl->getPropertyAttributes() &
1157 ObjCPropertyDecl::OBJC_PR_atomic) {
1158 Out << (first ? ' ' : ',') << "atomic";
1159 first = false;
1160 }
1161
1162 (void) first; // Silence dead store warning due to idiomatic code.
1163 Out << " )";
1164 }
1165 Out << ' ' << PDecl->getASTContext().getUnqualifiedObjCPointerType(PDecl->getType()).
1166 getAsString(Policy) << ' ' << *PDecl;
1167 if (Policy.PolishForDeclaration)
1168 Out << ';';
1169 }
1170
VisitObjCPropertyImplDecl(ObjCPropertyImplDecl * PID)1171 void DeclPrinter::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *PID) {
1172 if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize)
1173 Out << "@synthesize ";
1174 else
1175 Out << "@dynamic ";
1176 Out << *PID->getPropertyDecl();
1177 if (PID->getPropertyIvarDecl())
1178 Out << '=' << *PID->getPropertyIvarDecl();
1179 }
1180
VisitUsingDecl(UsingDecl * D)1181 void DeclPrinter::VisitUsingDecl(UsingDecl *D) {
1182 if (!D->isAccessDeclaration())
1183 Out << "using ";
1184 if (D->hasTypename())
1185 Out << "typename ";
1186 D->getQualifier()->print(Out, Policy);
1187 Out << *D;
1188 }
1189
1190 void
VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl * D)1191 DeclPrinter::VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D) {
1192 Out << "using typename ";
1193 D->getQualifier()->print(Out, Policy);
1194 Out << D->getDeclName();
1195 }
1196
VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl * D)1197 void DeclPrinter::VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D) {
1198 if (!D->isAccessDeclaration())
1199 Out << "using ";
1200 D->getQualifier()->print(Out, Policy);
1201 Out << D->getName();
1202 }
1203
VisitUsingShadowDecl(UsingShadowDecl * D)1204 void DeclPrinter::VisitUsingShadowDecl(UsingShadowDecl *D) {
1205 // ignore
1206 }
1207
VisitOMPThreadPrivateDecl(OMPThreadPrivateDecl * D)1208 void DeclPrinter::VisitOMPThreadPrivateDecl(OMPThreadPrivateDecl *D) {
1209 Out << "#pragma omp threadprivate";
1210 if (!D->varlist_empty()) {
1211 for (OMPThreadPrivateDecl::varlist_iterator I = D->varlist_begin(),
1212 E = D->varlist_end();
1213 I != E; ++I) {
1214 Out << (I == D->varlist_begin() ? '(' : ',');
1215 NamedDecl *ND = cast<NamedDecl>(cast<DeclRefExpr>(*I)->getDecl());
1216 ND->printQualifiedName(Out);
1217 }
1218 Out << ")";
1219 }
1220 }
1221
1222