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