1//===--- DeclPrinter.cpp - Printing implementation for Decl ASTs ----------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file implements the Decl::print method, which pretty prints the
10// AST back out to C/Objective-C/C++/Objective-C++ code.
11//
12//===----------------------------------------------------------------------===//
13#include "clang/AST/ASTContext.h"
14#include "clang/AST/Attr.h"
15#include "clang/AST/Decl.h"
16#include "clang/AST/DeclCXX.h"
17#include "clang/AST/DeclObjC.h"
18#include "clang/AST/DeclTemplate.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 "clang/Basic/SourceManager.h"
25#include "llvm/Support/raw_ostream.h"
26using namespace clang;
27
28namespace {
29 class DeclPrinter : public DeclVisitor<DeclPrinter> {
30 raw_ostream &Out;
31 PrintingPolicy Policy;
32 const ASTContext &Context;
33 unsigned Indentation;
34 bool PrintInstantiation;
35
36 raw_ostream& Indent() { return Indent(Indentation); }
37 raw_ostream& Indent(unsigned Indentation);
38 void ProcessDeclGroup(SmallVectorImpl<Decl*>& Decls);
39
40 void Print(AccessSpecifier AS);
41 void PrintConstructorInitializers(CXXConstructorDecl *CDecl,
42 std::string &Proto);
43
44 /// Print an Objective-C method type in parentheses.
45 ///
46 /// \param Quals The Objective-C declaration qualifiers.
47 /// \param T The type to print.
48 void PrintObjCMethodType(ASTContext &Ctx, Decl::ObjCDeclQualifier Quals,
49 QualType T);
50
51 void PrintObjCTypeParams(ObjCTypeParamList *Params);
52
53 public:
54 DeclPrinter(raw_ostream &Out, const PrintingPolicy &Policy,
55 const ASTContext &Context, unsigned Indentation = 0,
56 bool PrintInstantiation = false)
57 : Out(Out), Policy(Policy), Context(Context), Indentation(Indentation),
58 PrintInstantiation(PrintInstantiation) {}
59
60 void VisitDeclContext(DeclContext *DC, bool Indent = true);
61
62 void VisitTranslationUnitDecl(TranslationUnitDecl *D);
63 void VisitTypedefDecl(TypedefDecl *D);
64 void VisitTypeAliasDecl(TypeAliasDecl *D);
65 void VisitEnumDecl(EnumDecl *D);
66 void VisitRecordDecl(RecordDecl *D);
67 void VisitEnumConstantDecl(EnumConstantDecl *D);
68 void VisitEmptyDecl(EmptyDecl *D);
69 void VisitFunctionDecl(FunctionDecl *D);
70 void VisitFriendDecl(FriendDecl *D);
71 void VisitFieldDecl(FieldDecl *D);
72 void VisitVarDecl(VarDecl *D);
73 void VisitLabelDecl(LabelDecl *D);
74 void VisitParmVarDecl(ParmVarDecl *D);
75 void VisitFileScopeAsmDecl(FileScopeAsmDecl *D);
76 void VisitTopLevelStmtDecl(TopLevelStmtDecl *D);
77 void VisitImportDecl(ImportDecl *D);
78 void VisitStaticAssertDecl(StaticAssertDecl *D);
79 void VisitNamespaceDecl(NamespaceDecl *D);
80 void VisitUsingDirectiveDecl(UsingDirectiveDecl *D);
81 void VisitNamespaceAliasDecl(NamespaceAliasDecl *D);
82 void VisitCXXRecordDecl(CXXRecordDecl *D);
83 void VisitLinkageSpecDecl(LinkageSpecDecl *D);
84 void VisitTemplateDecl(const TemplateDecl *D);
85 void VisitFunctionTemplateDecl(FunctionTemplateDecl *D);
86 void VisitClassTemplateDecl(ClassTemplateDecl *D);
87 void VisitClassTemplateSpecializationDecl(
88 ClassTemplateSpecializationDecl *D);
89 void VisitClassTemplatePartialSpecializationDecl(
90 ClassTemplatePartialSpecializationDecl *D);
91 void VisitObjCMethodDecl(ObjCMethodDecl *D);
92 void VisitObjCImplementationDecl(ObjCImplementationDecl *D);
93 void VisitObjCInterfaceDecl(ObjCInterfaceDecl *D);
94 void VisitObjCProtocolDecl(ObjCProtocolDecl *D);
95 void VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D);
96 void VisitObjCCategoryDecl(ObjCCategoryDecl *D);
97 void VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *D);
98 void VisitObjCPropertyDecl(ObjCPropertyDecl *D);
99 void VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D);
100 void VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D);
101 void VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D);
102 void VisitUsingDecl(UsingDecl *D);
103 void VisitUsingEnumDecl(UsingEnumDecl *D);
104 void VisitUsingShadowDecl(UsingShadowDecl *D);
105 void VisitOMPThreadPrivateDecl(OMPThreadPrivateDecl *D);
106 void VisitOMPAllocateDecl(OMPAllocateDecl *D);
107 void VisitOMPRequiresDecl(OMPRequiresDecl *D);
108 void VisitOMPDeclareReductionDecl(OMPDeclareReductionDecl *D);
109 void VisitOMPDeclareMapperDecl(OMPDeclareMapperDecl *D);
110 void VisitOMPCapturedExprDecl(OMPCapturedExprDecl *D);
111 void VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *TTP);
112 void VisitNonTypeTemplateParmDecl(const NonTypeTemplateParmDecl *NTTP);
113 void VisitHLSLBufferDecl(HLSLBufferDecl *D);
114
115 void printTemplateParameters(const TemplateParameterList *Params,
116 bool OmitTemplateKW = false);
117 void printTemplateArguments(llvm::ArrayRef<TemplateArgument> Args,
118 const TemplateParameterList *Params);
119 void printTemplateArguments(llvm::ArrayRef<TemplateArgumentLoc> Args,
120 const TemplateParameterList *Params);
121 enum class AttrPosAsWritten { Default = 0, Left, Right };
122 bool
123 prettyPrintAttributes(const Decl *D,
124 AttrPosAsWritten Pos = AttrPosAsWritten::Default);
125 void prettyPrintPragmas(Decl *D);
126 void printDeclType(QualType T, StringRef DeclName, bool Pack = false);
127 };
128}
129
130void Decl::print(raw_ostream &Out, unsigned Indentation,
131 bool PrintInstantiation) const {
132 print(Out, Policy: getASTContext().getPrintingPolicy(), Indentation, PrintInstantiation);
133}
134
135void Decl::print(raw_ostream &Out, const PrintingPolicy &Policy,
136 unsigned Indentation, bool PrintInstantiation) const {
137 DeclPrinter Printer(Out, Policy, getASTContext(), Indentation,
138 PrintInstantiation);
139 Printer.Visit(D: const_cast<Decl*>(this));
140}
141
142void TemplateParameterList::print(raw_ostream &Out, const ASTContext &Context,
143 bool OmitTemplateKW) const {
144 print(Out, Context, Policy: Context.getPrintingPolicy(), OmitTemplateKW);
145}
146
147void TemplateParameterList::print(raw_ostream &Out, const ASTContext &Context,
148 const PrintingPolicy &Policy,
149 bool OmitTemplateKW) const {
150 DeclPrinter Printer(Out, Policy, Context);
151 Printer.printTemplateParameters(Params: this, OmitTemplateKW);
152}
153
154static QualType GetBaseType(QualType T) {
155 // FIXME: This should be on the Type class!
156 QualType BaseType = T;
157 while (!BaseType->isSpecifierType()) {
158 if (const PointerType *PTy = BaseType->getAs<PointerType>())
159 BaseType = PTy->getPointeeType();
160 else if (const ObjCObjectPointerType *OPT =
161 BaseType->getAs<ObjCObjectPointerType>())
162 BaseType = OPT->getPointeeType();
163 else if (const BlockPointerType *BPy = BaseType->getAs<BlockPointerType>())
164 BaseType = BPy->getPointeeType();
165 else if (const ArrayType *ATy = dyn_cast<ArrayType>(Val&: BaseType))
166 BaseType = ATy->getElementType();
167 else if (const FunctionType *FTy = BaseType->getAs<FunctionType>())
168 BaseType = FTy->getReturnType();
169 else if (const VectorType *VTy = BaseType->getAs<VectorType>())
170 BaseType = VTy->getElementType();
171 else if (const ReferenceType *RTy = BaseType->getAs<ReferenceType>())
172 BaseType = RTy->getPointeeType();
173 else if (const AutoType *ATy = BaseType->getAs<AutoType>())
174 BaseType = ATy->getDeducedType();
175 else if (const ParenType *PTy = BaseType->getAs<ParenType>())
176 BaseType = PTy->desugar();
177 else
178 // This must be a syntax error.
179 break;
180 }
181 return BaseType;
182}
183
184static QualType getDeclType(Decl* D) {
185 if (TypedefNameDecl* TDD = dyn_cast<TypedefNameDecl>(Val: D))
186 return TDD->getUnderlyingType();
187 if (ValueDecl* VD = dyn_cast<ValueDecl>(Val: D))
188 return VD->getType();
189 return QualType();
190}
191
192void Decl::printGroup(Decl** Begin, unsigned NumDecls,
193 raw_ostream &Out, const PrintingPolicy &Policy,
194 unsigned Indentation) {
195 if (NumDecls == 1) {
196 (*Begin)->print(Out, Policy, Indentation);
197 return;
198 }
199
200 Decl** End = Begin + NumDecls;
201 TagDecl* TD = dyn_cast<TagDecl>(Val: *Begin);
202 if (TD)
203 ++Begin;
204
205 PrintingPolicy SubPolicy(Policy);
206
207 bool isFirst = true;
208 for ( ; Begin != End; ++Begin) {
209 if (isFirst) {
210 if(TD)
211 SubPolicy.IncludeTagDefinition = true;
212 SubPolicy.SuppressSpecifiers = false;
213 isFirst = false;
214 } else {
215 if (!isFirst) Out << ", ";
216 SubPolicy.IncludeTagDefinition = false;
217 SubPolicy.SuppressSpecifiers = true;
218 }
219
220 (*Begin)->print(Out, Policy: SubPolicy, Indentation);
221 }
222}
223
224LLVM_DUMP_METHOD void DeclContext::dumpDeclContext() const {
225 // Get the translation unit
226 const DeclContext *DC = this;
227 while (!DC->isTranslationUnit())
228 DC = DC->getParent();
229
230 ASTContext &Ctx = cast<TranslationUnitDecl>(Val: DC)->getASTContext();
231 DeclPrinter Printer(llvm::errs(), Ctx.getPrintingPolicy(), Ctx, 0);
232 Printer.VisitDeclContext(DC: const_cast<DeclContext *>(this), /*Indent=*/false);
233}
234
235raw_ostream& DeclPrinter::Indent(unsigned Indentation) {
236 for (unsigned i = 0; i != Indentation; ++i)
237 Out << " ";
238 return Out;
239}
240
241static DeclPrinter::AttrPosAsWritten getPosAsWritten(const Attr *A,
242 const Decl *D) {
243 SourceLocation ALoc = A->getLoc();
244 SourceLocation DLoc = D->getLocation();
245 const ASTContext &C = D->getASTContext();
246 if (ALoc.isInvalid() || DLoc.isInvalid())
247 return DeclPrinter::AttrPosAsWritten::Left;
248
249 if (C.getSourceManager().isBeforeInTranslationUnit(LHS: ALoc, RHS: DLoc))
250 return DeclPrinter::AttrPosAsWritten::Left;
251
252 return DeclPrinter::AttrPosAsWritten::Right;
253}
254
255// returns true if an attribute was printed.
256bool DeclPrinter::prettyPrintAttributes(const Decl *D,
257 AttrPosAsWritten Pos /*=Default*/) {
258 bool hasPrinted = false;
259
260 if (D->hasAttrs()) {
261 const AttrVec &Attrs = D->getAttrs();
262 for (auto *A : Attrs) {
263 if (A->isInherited() || A->isImplicit())
264 continue;
265 // Print out the keyword attributes, they aren't regular attributes.
266 if (Policy.PolishForDeclaration && !A->isKeywordAttribute())
267 continue;
268 switch (A->getKind()) {
269#define ATTR(X)
270#define PRAGMA_SPELLING_ATTR(X) case attr::X:
271#include "clang/Basic/AttrList.inc"
272 break;
273 default:
274 AttrPosAsWritten APos = getPosAsWritten(A, D);
275 assert(APos != AttrPosAsWritten::Default &&
276 "Default not a valid for an attribute location");
277 if (Pos == AttrPosAsWritten::Default || Pos == APos) {
278 if (Pos != AttrPosAsWritten::Left)
279 Out << ' ';
280 A->printPretty(OS&: Out, Policy);
281 hasPrinted = true;
282 if (Pos == AttrPosAsWritten::Left)
283 Out << ' ';
284 }
285 break;
286 }
287 }
288 }
289 return hasPrinted;
290}
291
292void DeclPrinter::prettyPrintPragmas(Decl *D) {
293 if (Policy.PolishForDeclaration)
294 return;
295
296 if (D->hasAttrs()) {
297 AttrVec &Attrs = D->getAttrs();
298 for (auto *A : Attrs) {
299 switch (A->getKind()) {
300#define ATTR(X)
301#define PRAGMA_SPELLING_ATTR(X) case attr::X:
302#include "clang/Basic/AttrList.inc"
303 A->printPretty(OS&: Out, Policy);
304 Indent();
305 break;
306 default:
307 break;
308 }
309 }
310 }
311}
312
313void DeclPrinter::printDeclType(QualType T, StringRef DeclName, bool Pack) {
314 // Normally, a PackExpansionType is written as T[3]... (for instance, as a
315 // template argument), but if it is the type of a declaration, the ellipsis
316 // is placed before the name being declared.
317 if (auto *PET = T->getAs<PackExpansionType>()) {
318 Pack = true;
319 T = PET->getPattern();
320 }
321 T.print(OS&: Out, Policy, PlaceHolder: (Pack ? "..." : "") + DeclName, Indentation);
322}
323
324void DeclPrinter::ProcessDeclGroup(SmallVectorImpl<Decl*>& Decls) {
325 this->Indent();
326 Decl::printGroup(Begin: Decls.data(), NumDecls: Decls.size(), Out, Policy, Indentation);
327 Out << ";\n";
328 Decls.clear();
329
330}
331
332void DeclPrinter::Print(AccessSpecifier AS) {
333 const auto AccessSpelling = getAccessSpelling(AS);
334 if (AccessSpelling.empty())
335 llvm_unreachable("No access specifier!");
336 Out << AccessSpelling;
337}
338
339void DeclPrinter::PrintConstructorInitializers(CXXConstructorDecl *CDecl,
340 std::string &Proto) {
341 bool HasInitializerList = false;
342 for (const auto *BMInitializer : CDecl->inits()) {
343 if (BMInitializer->isInClassMemberInitializer())
344 continue;
345 if (!BMInitializer->isWritten())
346 continue;
347
348 if (!HasInitializerList) {
349 Proto += " : ";
350 Out << Proto;
351 Proto.clear();
352 HasInitializerList = true;
353 } else
354 Out << ", ";
355
356 if (BMInitializer->isAnyMemberInitializer()) {
357 FieldDecl *FD = BMInitializer->getAnyMember();
358 Out << *FD;
359 } else if (BMInitializer->isDelegatingInitializer()) {
360 Out << CDecl->getNameAsString();
361 } else {
362 Out << QualType(BMInitializer->getBaseClass(), 0).getAsString(Policy);
363 }
364
365 if (Expr *Init = BMInitializer->getInit()) {
366 bool OutParens = !isa<InitListExpr>(Val: Init);
367
368 if (OutParens)
369 Out << "(";
370
371 if (ExprWithCleanups *Tmp = dyn_cast<ExprWithCleanups>(Val: Init))
372 Init = Tmp->getSubExpr();
373
374 Init = Init->IgnoreParens();
375
376 Expr *SimpleInit = nullptr;
377 Expr **Args = nullptr;
378 unsigned NumArgs = 0;
379 if (ParenListExpr *ParenList = dyn_cast<ParenListExpr>(Val: Init)) {
380 Args = ParenList->getExprs();
381 NumArgs = ParenList->getNumExprs();
382 } else if (CXXConstructExpr *Construct =
383 dyn_cast<CXXConstructExpr>(Val: Init)) {
384 Args = Construct->getArgs();
385 NumArgs = Construct->getNumArgs();
386 } else
387 SimpleInit = Init;
388
389 if (SimpleInit)
390 SimpleInit->printPretty(OS&: Out, Helper: nullptr, Policy, Indentation, NewlineSymbol: "\n",
391 Context: &Context);
392 else {
393 for (unsigned I = 0; I != NumArgs; ++I) {
394 assert(Args[I] != nullptr && "Expected non-null Expr");
395 if (isa<CXXDefaultArgExpr>(Val: Args[I]))
396 break;
397
398 if (I)
399 Out << ", ";
400 Args[I]->printPretty(OS&: Out, Helper: nullptr, Policy, Indentation, NewlineSymbol: "\n",
401 Context: &Context);
402 }
403 }
404
405 if (OutParens)
406 Out << ")";
407 } else {
408 Out << "()";
409 }
410
411 if (BMInitializer->isPackExpansion())
412 Out << "...";
413 }
414}
415
416//----------------------------------------------------------------------------
417// Common C declarations
418//----------------------------------------------------------------------------
419
420void DeclPrinter::VisitDeclContext(DeclContext *DC, bool Indent) {
421 if (Policy.TerseOutput)
422 return;
423
424 if (Indent)
425 Indentation += Policy.Indentation;
426
427 SmallVector<Decl*, 2> Decls;
428 for (DeclContext::decl_iterator D = DC->decls_begin(), DEnd = DC->decls_end();
429 D != DEnd; ++D) {
430
431 // Don't print ObjCIvarDecls, as they are printed when visiting the
432 // containing ObjCInterfaceDecl.
433 if (isa<ObjCIvarDecl>(Val: *D))
434 continue;
435
436 // Skip over implicit declarations in pretty-printing mode.
437 if (D->isImplicit())
438 continue;
439
440 // Don't print implicit specializations, as they are printed when visiting
441 // corresponding templates.
442 if (auto FD = dyn_cast<FunctionDecl>(Val: *D))
443 if (FD->getTemplateSpecializationKind() == TSK_ImplicitInstantiation &&
444 !isa<ClassTemplateSpecializationDecl>(Val: DC))
445 continue;
446
447 // The next bits of code handle stuff like "struct {int x;} a,b"; we're
448 // forced to merge the declarations because there's no other way to
449 // refer to the struct in question. When that struct is named instead, we
450 // also need to merge to avoid splitting off a stand-alone struct
451 // declaration that produces the warning ext_no_declarators in some
452 // contexts.
453 //
454 // This limited merging is safe without a bunch of other checks because it
455 // only merges declarations directly referring to the tag, not typedefs.
456 //
457 // Check whether the current declaration should be grouped with a previous
458 // non-free-standing tag declaration.
459 QualType CurDeclType = getDeclType(D: *D);
460 if (!Decls.empty() && !CurDeclType.isNull()) {
461 QualType BaseType = GetBaseType(T: CurDeclType);
462 if (!BaseType.isNull() && isa<ElaboratedType>(Val: BaseType) &&
463 cast<ElaboratedType>(Val&: BaseType)->getOwnedTagDecl() == Decls[0]) {
464 Decls.push_back(Elt: *D);
465 continue;
466 }
467 }
468
469 // If we have a merged group waiting to be handled, handle it now.
470 if (!Decls.empty())
471 ProcessDeclGroup(Decls);
472
473 // If the current declaration is not a free standing declaration, save it
474 // so we can merge it with the subsequent declaration(s) using it.
475 if (isa<TagDecl>(Val: *D) && !cast<TagDecl>(Val: *D)->isFreeStanding()) {
476 Decls.push_back(Elt: *D);
477 continue;
478 }
479
480 if (isa<AccessSpecDecl>(Val: *D)) {
481 Indentation -= Policy.Indentation;
482 this->Indent();
483 Print(AS: D->getAccess());
484 Out << ":\n";
485 Indentation += Policy.Indentation;
486 continue;
487 }
488
489 this->Indent();
490 Visit(D: *D);
491
492 // FIXME: Need to be able to tell the DeclPrinter when
493 const char *Terminator = nullptr;
494 if (isa<OMPThreadPrivateDecl>(Val: *D) || isa<OMPDeclareReductionDecl>(Val: *D) ||
495 isa<OMPDeclareMapperDecl>(Val: *D) || isa<OMPRequiresDecl>(Val: *D) ||
496 isa<OMPAllocateDecl>(Val: *D))
497 Terminator = nullptr;
498 else if (isa<ObjCMethodDecl>(Val: *D) && cast<ObjCMethodDecl>(Val: *D)->hasBody())
499 Terminator = nullptr;
500 else if (auto FD = dyn_cast<FunctionDecl>(Val: *D)) {
501 if (FD->doesThisDeclarationHaveABody() && !FD->isDefaulted())
502 Terminator = nullptr;
503 else
504 Terminator = ";";
505 } else if (auto TD = dyn_cast<FunctionTemplateDecl>(Val: *D)) {
506 if (TD->getTemplatedDecl()->doesThisDeclarationHaveABody())
507 Terminator = nullptr;
508 else
509 Terminator = ";";
510 } else if (isa<NamespaceDecl, LinkageSpecDecl, ObjCImplementationDecl,
511 ObjCInterfaceDecl, ObjCProtocolDecl, ObjCCategoryImplDecl,
512 ObjCCategoryDecl, HLSLBufferDecl>(Val: *D))
513 Terminator = nullptr;
514 else if (isa<EnumConstantDecl>(Val: *D)) {
515 DeclContext::decl_iterator Next = D;
516 ++Next;
517 if (Next != DEnd)
518 Terminator = ",";
519 } else
520 Terminator = ";";
521
522 if (Terminator)
523 Out << Terminator;
524 if (!Policy.TerseOutput &&
525 ((isa<FunctionDecl>(Val: *D) &&
526 cast<FunctionDecl>(Val: *D)->doesThisDeclarationHaveABody()) ||
527 (isa<FunctionTemplateDecl>(Val: *D) &&
528 cast<FunctionTemplateDecl>(Val: *D)->getTemplatedDecl()->doesThisDeclarationHaveABody())))
529 ; // StmtPrinter already added '\n' after CompoundStmt.
530 else
531 Out << "\n";
532
533 // Declare target attribute is special one, natural spelling for the pragma
534 // assumes "ending" construct so print it here.
535 if (D->hasAttr<OMPDeclareTargetDeclAttr>())
536 Out << "#pragma omp end declare target\n";
537 }
538
539 if (!Decls.empty())
540 ProcessDeclGroup(Decls);
541
542 if (Indent)
543 Indentation -= Policy.Indentation;
544}
545
546void DeclPrinter::VisitTranslationUnitDecl(TranslationUnitDecl *D) {
547 VisitDeclContext(DC: D, Indent: false);
548}
549
550void DeclPrinter::VisitTypedefDecl(TypedefDecl *D) {
551 if (!Policy.SuppressSpecifiers) {
552 Out << "typedef ";
553
554 if (D->isModulePrivate())
555 Out << "__module_private__ ";
556 }
557 QualType Ty = D->getTypeSourceInfo()->getType();
558 Ty.print(OS&: Out, Policy, PlaceHolder: D->getName(), Indentation);
559 prettyPrintAttributes(D);
560}
561
562void DeclPrinter::VisitTypeAliasDecl(TypeAliasDecl *D) {
563 Out << "using " << *D;
564 prettyPrintAttributes(D);
565 Out << " = " << D->getTypeSourceInfo()->getType().getAsString(Policy);
566}
567
568void DeclPrinter::VisitEnumDecl(EnumDecl *D) {
569 if (!Policy.SuppressSpecifiers && D->isModulePrivate())
570 Out << "__module_private__ ";
571 Out << "enum";
572 if (D->isScoped()) {
573 if (D->isScopedUsingClassTag())
574 Out << " class";
575 else
576 Out << " struct";
577 }
578
579 prettyPrintAttributes(D);
580
581 if (D->getDeclName())
582 Out << ' ' << D->getDeclName();
583
584 if (D->isFixed())
585 Out << " : " << D->getIntegerType().stream(Policy);
586
587 if (D->isCompleteDefinition()) {
588 Out << " {\n";
589 VisitDeclContext(DC: D);
590 Indent() << "}";
591 }
592}
593
594void DeclPrinter::VisitRecordDecl(RecordDecl *D) {
595 if (!Policy.SuppressSpecifiers && D->isModulePrivate())
596 Out << "__module_private__ ";
597 Out << D->getKindName();
598
599 prettyPrintAttributes(D);
600
601 if (D->getIdentifier())
602 Out << ' ' << *D;
603
604 if (D->isCompleteDefinition()) {
605 Out << " {\n";
606 VisitDeclContext(DC: D);
607 Indent() << "}";
608 }
609}
610
611void DeclPrinter::VisitEnumConstantDecl(EnumConstantDecl *D) {
612 Out << *D;
613 prettyPrintAttributes(D);
614 if (Expr *Init = D->getInitExpr()) {
615 Out << " = ";
616 Init->printPretty(OS&: Out, Helper: nullptr, Policy, Indentation, NewlineSymbol: "\n", Context: &Context);
617 }
618}
619
620static void printExplicitSpecifier(ExplicitSpecifier ES, llvm::raw_ostream &Out,
621 PrintingPolicy &Policy, unsigned Indentation,
622 const ASTContext &Context) {
623 std::string Proto = "explicit";
624 llvm::raw_string_ostream EOut(Proto);
625 if (ES.getExpr()) {
626 EOut << "(";
627 ES.getExpr()->printPretty(OS&: EOut, Helper: nullptr, Policy, Indentation, NewlineSymbol: "\n",
628 Context: &Context);
629 EOut << ")";
630 }
631 EOut << " ";
632 EOut.flush();
633 Out << Proto;
634}
635
636static void MaybePrintTagKeywordIfSupressingScopes(PrintingPolicy &Policy,
637 QualType T,
638 llvm::raw_ostream &Out) {
639 StringRef prefix = T->isClassType() ? "class "
640 : T->isStructureType() ? "struct "
641 : T->isUnionType() ? "union "
642 : "";
643 Out << prefix;
644}
645
646void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
647 if (!D->getDescribedFunctionTemplate() &&
648 !D->isFunctionTemplateSpecialization()) {
649 prettyPrintPragmas(D);
650 prettyPrintAttributes(D, Pos: AttrPosAsWritten::Left);
651 }
652
653 if (D->isFunctionTemplateSpecialization())
654 Out << "template<> ";
655 else if (!D->getDescribedFunctionTemplate()) {
656 for (unsigned I = 0, NumTemplateParams = D->getNumTemplateParameterLists();
657 I < NumTemplateParams; ++I)
658 printTemplateParameters(Params: D->getTemplateParameterList(index: I));
659 }
660
661 CXXConstructorDecl *CDecl = dyn_cast<CXXConstructorDecl>(Val: D);
662 CXXConversionDecl *ConversionDecl = dyn_cast<CXXConversionDecl>(Val: D);
663 CXXDeductionGuideDecl *GuideDecl = dyn_cast<CXXDeductionGuideDecl>(Val: D);
664 if (!Policy.SuppressSpecifiers) {
665 switch (D->getStorageClass()) {
666 case SC_None: break;
667 case SC_Extern: Out << "extern "; break;
668 case SC_Static: Out << "static "; break;
669 case SC_PrivateExtern: Out << "__private_extern__ "; break;
670 case SC_Auto: case SC_Register:
671 llvm_unreachable("invalid for functions");
672 }
673
674 if (D->isInlineSpecified()) Out << "inline ";
675 if (D->isVirtualAsWritten()) Out << "virtual ";
676 if (D->isModulePrivate()) Out << "__module_private__ ";
677 if (D->isConstexprSpecified() && !D->isExplicitlyDefaulted())
678 Out << "constexpr ";
679 if (D->isConsteval()) Out << "consteval ";
680 else if (D->isImmediateFunction())
681 Out << "immediate ";
682 ExplicitSpecifier ExplicitSpec = ExplicitSpecifier::getFromDecl(Function: D);
683 if (ExplicitSpec.isSpecified())
684 printExplicitSpecifier(ES: ExplicitSpec, Out, Policy, Indentation, Context);
685 }
686
687 PrintingPolicy SubPolicy(Policy);
688 SubPolicy.SuppressSpecifiers = false;
689 std::string Proto;
690
691 if (Policy.FullyQualifiedName) {
692 Proto += D->getQualifiedNameAsString();
693 } else {
694 llvm::raw_string_ostream OS(Proto);
695 if (!Policy.SuppressScope) {
696 if (const NestedNameSpecifier *NS = D->getQualifier()) {
697 NS->print(OS, Policy);
698 }
699 }
700 D->getNameInfo().printName(OS, Policy);
701 }
702
703 if (GuideDecl)
704 Proto = GuideDecl->getDeducedTemplate()->getDeclName().getAsString();
705 if (D->isFunctionTemplateSpecialization()) {
706 llvm::raw_string_ostream POut(Proto);
707 DeclPrinter TArgPrinter(POut, SubPolicy, Context, Indentation);
708 const auto *TArgAsWritten = D->getTemplateSpecializationArgsAsWritten();
709 if (TArgAsWritten && !Policy.PrintCanonicalTypes)
710 TArgPrinter.printTemplateArguments(Args: TArgAsWritten->arguments(), Params: nullptr);
711 else if (const TemplateArgumentList *TArgs =
712 D->getTemplateSpecializationArgs())
713 TArgPrinter.printTemplateArguments(Args: TArgs->asArray(), Params: nullptr);
714 }
715
716 QualType Ty = D->getType();
717 while (const ParenType *PT = dyn_cast<ParenType>(Val&: Ty)) {
718 Proto = '(' + Proto + ')';
719 Ty = PT->getInnerType();
720 }
721
722 if (const FunctionType *AFT = Ty->getAs<FunctionType>()) {
723 const FunctionProtoType *FT = nullptr;
724 if (D->hasWrittenPrototype())
725 FT = dyn_cast<FunctionProtoType>(Val: AFT);
726
727 Proto += "(";
728 if (FT) {
729 llvm::raw_string_ostream POut(Proto);
730 DeclPrinter ParamPrinter(POut, SubPolicy, Context, Indentation);
731 for (unsigned i = 0, e = D->getNumParams(); i != e; ++i) {
732 if (i) POut << ", ";
733 ParamPrinter.VisitParmVarDecl(D: D->getParamDecl(i));
734 }
735
736 if (FT->isVariadic()) {
737 if (D->getNumParams()) POut << ", ";
738 POut << "...";
739 } else if (!D->getNumParams() && !Context.getLangOpts().CPlusPlus) {
740 // The function has a prototype, so it needs to retain the prototype
741 // in C.
742 POut << "void";
743 }
744 } else if (D->doesThisDeclarationHaveABody() && !D->hasPrototype()) {
745 for (unsigned i = 0, e = D->getNumParams(); i != e; ++i) {
746 if (i)
747 Proto += ", ";
748 Proto += D->getParamDecl(i)->getNameAsString();
749 }
750 }
751
752 Proto += ")";
753
754 if (FT) {
755 if (FT->isConst())
756 Proto += " const";
757 if (FT->isVolatile())
758 Proto += " volatile";
759 if (FT->isRestrict())
760 Proto += " restrict";
761
762 switch (FT->getRefQualifier()) {
763 case RQ_None:
764 break;
765 case RQ_LValue:
766 Proto += " &";
767 break;
768 case RQ_RValue:
769 Proto += " &&";
770 break;
771 }
772 }
773
774 if (FT && FT->hasDynamicExceptionSpec()) {
775 Proto += " throw(";
776 if (FT->getExceptionSpecType() == EST_MSAny)
777 Proto += "...";
778 else
779 for (unsigned I = 0, N = FT->getNumExceptions(); I != N; ++I) {
780 if (I)
781 Proto += ", ";
782
783 Proto += FT->getExceptionType(i: I).getAsString(Policy: SubPolicy);
784 }
785 Proto += ")";
786 } else if (FT && isNoexceptExceptionSpec(ESpecType: FT->getExceptionSpecType())) {
787 Proto += " noexcept";
788 if (isComputedNoexcept(ESpecType: FT->getExceptionSpecType())) {
789 Proto += "(";
790 llvm::raw_string_ostream EOut(Proto);
791 FT->getNoexceptExpr()->printPretty(OS&: EOut, Helper: nullptr, Policy: SubPolicy,
792 Indentation, NewlineSymbol: "\n", Context: &Context);
793 EOut.flush();
794 Proto += ")";
795 }
796 }
797
798 if (CDecl) {
799 if (!Policy.TerseOutput)
800 PrintConstructorInitializers(CDecl, Proto);
801 } else if (!ConversionDecl && !isa<CXXDestructorDecl>(Val: D)) {
802 if (FT && FT->hasTrailingReturn()) {
803 if (!GuideDecl)
804 Out << "auto ";
805 Out << Proto << " -> ";
806 Proto.clear();
807 }
808 if (!Policy.SuppressTagKeyword && Policy.SuppressScope &&
809 !Policy.SuppressUnwrittenScope)
810 MaybePrintTagKeywordIfSupressingScopes(Policy, T: AFT->getReturnType(),
811 Out);
812 AFT->getReturnType().print(OS&: Out, Policy, PlaceHolder: Proto);
813 Proto.clear();
814 }
815 Out << Proto;
816
817 if (Expr *TrailingRequiresClause = D->getTrailingRequiresClause()) {
818 Out << " requires ";
819 TrailingRequiresClause->printPretty(OS&: Out, Helper: nullptr, Policy: SubPolicy, Indentation,
820 NewlineSymbol: "\n", Context: &Context);
821 }
822 } else {
823 Ty.print(OS&: Out, Policy, PlaceHolder: Proto);
824 }
825
826 prettyPrintAttributes(D, Pos: AttrPosAsWritten::Right);
827
828 if (D->isPureVirtual())
829 Out << " = 0";
830 else if (D->isDeletedAsWritten()) {
831 Out << " = delete";
832 if (const StringLiteral *M = D->getDeletedMessage()) {
833 Out << "(";
834 M->outputString(OS&: Out);
835 Out << ")";
836 }
837 } else if (D->isExplicitlyDefaulted())
838 Out << " = default";
839 else if (D->doesThisDeclarationHaveABody()) {
840 if (!Policy.TerseOutput) {
841 if (!D->hasPrototype() && D->getNumParams()) {
842 // This is a K&R function definition, so we need to print the
843 // parameters.
844 Out << '\n';
845 DeclPrinter ParamPrinter(Out, SubPolicy, Context, Indentation);
846 Indentation += Policy.Indentation;
847 for (unsigned i = 0, e = D->getNumParams(); i != e; ++i) {
848 Indent();
849 ParamPrinter.VisitParmVarDecl(D: D->getParamDecl(i));
850 Out << ";\n";
851 }
852 Indentation -= Policy.Indentation;
853 }
854
855 if (D->getBody())
856 D->getBody()->printPrettyControlled(OS&: Out, Helper: nullptr, Policy: SubPolicy, Indentation, NewlineSymbol: "\n",
857 Context: &Context);
858 } else {
859 if (!Policy.TerseOutput && isa<CXXConstructorDecl>(Val: *D))
860 Out << " {}";
861 }
862 }
863}
864
865void DeclPrinter::VisitFriendDecl(FriendDecl *D) {
866 if (TypeSourceInfo *TSI = D->getFriendType()) {
867 unsigned NumTPLists = D->getFriendTypeNumTemplateParameterLists();
868 for (unsigned i = 0; i < NumTPLists; ++i)
869 printTemplateParameters(Params: D->getFriendTypeTemplateParameterList(N: i));
870 Out << "friend ";
871 Out << " " << TSI->getType().getAsString(Policy);
872 }
873 else if (FunctionDecl *FD =
874 dyn_cast<FunctionDecl>(Val: D->getFriendDecl())) {
875 Out << "friend ";
876 VisitFunctionDecl(D: FD);
877 }
878 else if (FunctionTemplateDecl *FTD =
879 dyn_cast<FunctionTemplateDecl>(Val: D->getFriendDecl())) {
880 Out << "friend ";
881 VisitFunctionTemplateDecl(D: FTD);
882 }
883 else if (ClassTemplateDecl *CTD =
884 dyn_cast<ClassTemplateDecl>(Val: D->getFriendDecl())) {
885 Out << "friend ";
886 VisitRedeclarableTemplateDecl(D: CTD);
887 }
888}
889
890void DeclPrinter::VisitFieldDecl(FieldDecl *D) {
891 // FIXME: add printing of pragma attributes if required.
892 if (!Policy.SuppressSpecifiers && D->isMutable())
893 Out << "mutable ";
894 if (!Policy.SuppressSpecifiers && D->isModulePrivate())
895 Out << "__module_private__ ";
896
897 Out << D->getASTContext().getUnqualifiedObjCPointerType(type: D->getType()).
898 stream(Policy, PlaceHolder: D->getName(), Indentation);
899
900 if (D->isBitField()) {
901 Out << " : ";
902 D->getBitWidth()->printPretty(OS&: Out, Helper: nullptr, Policy, Indentation, NewlineSymbol: "\n",
903 Context: &Context);
904 }
905
906 Expr *Init = D->getInClassInitializer();
907 if (!Policy.SuppressInitializers && Init) {
908 if (D->getInClassInitStyle() == ICIS_ListInit)
909 Out << " ";
910 else
911 Out << " = ";
912 Init->printPretty(OS&: Out, Helper: nullptr, Policy, Indentation, NewlineSymbol: "\n", Context: &Context);
913 }
914 prettyPrintAttributes(D);
915}
916
917void DeclPrinter::VisitLabelDecl(LabelDecl *D) {
918 Out << *D << ":";
919}
920
921void DeclPrinter::VisitVarDecl(VarDecl *D) {
922 prettyPrintPragmas(D);
923
924 prettyPrintAttributes(D, Pos: AttrPosAsWritten::Left);
925
926 if (const auto *Param = dyn_cast<ParmVarDecl>(Val: D);
927 Param && Param->isExplicitObjectParameter())
928 Out << "this ";
929
930 QualType T = D->getTypeSourceInfo()
931 ? D->getTypeSourceInfo()->getType()
932 : D->getASTContext().getUnqualifiedObjCPointerType(type: D->getType());
933
934 if (!Policy.SuppressSpecifiers) {
935 StorageClass SC = D->getStorageClass();
936 if (SC != SC_None)
937 Out << VarDecl::getStorageClassSpecifierString(SC) << " ";
938
939 switch (D->getTSCSpec()) {
940 case TSCS_unspecified:
941 break;
942 case TSCS___thread:
943 Out << "__thread ";
944 break;
945 case TSCS__Thread_local:
946 Out << "_Thread_local ";
947 break;
948 case TSCS_thread_local:
949 Out << "thread_local ";
950 break;
951 }
952
953 if (D->isModulePrivate())
954 Out << "__module_private__ ";
955
956 if (D->isConstexpr()) {
957 Out << "constexpr ";
958 T.removeLocalConst();
959 }
960 }
961
962 if (!Policy.SuppressTagKeyword && Policy.SuppressScope &&
963 !Policy.SuppressUnwrittenScope)
964 MaybePrintTagKeywordIfSupressingScopes(Policy, T, Out);
965
966 printDeclType(T, DeclName: (isa<ParmVarDecl>(Val: D) && Policy.CleanUglifiedParameters &&
967 D->getIdentifier())
968 ? D->getIdentifier()->deuglifiedName()
969 : D->getName());
970
971 prettyPrintAttributes(D, Pos: AttrPosAsWritten::Right);
972
973 Expr *Init = D->getInit();
974 if (!Policy.SuppressInitializers && Init) {
975 bool ImplicitInit = false;
976 if (D->isCXXForRangeDecl()) {
977 // FIXME: We should print the range expression instead.
978 ImplicitInit = true;
979 } else if (CXXConstructExpr *Construct =
980 dyn_cast<CXXConstructExpr>(Val: Init->IgnoreImplicit())) {
981 if (D->getInitStyle() == VarDecl::CallInit &&
982 !Construct->isListInitialization()) {
983 ImplicitInit = Construct->getNumArgs() == 0 ||
984 Construct->getArg(Arg: 0)->isDefaultArgument();
985 }
986 }
987 if (!ImplicitInit) {
988 if ((D->getInitStyle() == VarDecl::CallInit) && !isa<ParenListExpr>(Val: Init))
989 Out << "(";
990 else if (D->getInitStyle() == VarDecl::CInit) {
991 Out << " = ";
992 }
993 PrintingPolicy SubPolicy(Policy);
994 SubPolicy.SuppressSpecifiers = false;
995 SubPolicy.IncludeTagDefinition = false;
996 Init->printPretty(OS&: Out, Helper: nullptr, Policy: SubPolicy, Indentation, NewlineSymbol: "\n", Context: &Context);
997 if ((D->getInitStyle() == VarDecl::CallInit) && !isa<ParenListExpr>(Val: Init))
998 Out << ")";
999 }
1000 }
1001}
1002
1003void DeclPrinter::VisitParmVarDecl(ParmVarDecl *D) {
1004 VisitVarDecl(D);
1005}
1006
1007void DeclPrinter::VisitFileScopeAsmDecl(FileScopeAsmDecl *D) {
1008 Out << "__asm (";
1009 D->getAsmString()->printPretty(OS&: Out, Helper: nullptr, Policy, Indentation, NewlineSymbol: "\n",
1010 Context: &Context);
1011 Out << ")";
1012}
1013
1014void DeclPrinter::VisitTopLevelStmtDecl(TopLevelStmtDecl *D) {
1015 assert(D->getStmt());
1016 D->getStmt()->printPretty(OS&: Out, Helper: nullptr, Policy, Indentation, NewlineSymbol: "\n", Context: &Context);
1017}
1018
1019void DeclPrinter::VisitImportDecl(ImportDecl *D) {
1020 Out << "@import " << D->getImportedModule()->getFullModuleName()
1021 << ";\n";
1022}
1023
1024void DeclPrinter::VisitStaticAssertDecl(StaticAssertDecl *D) {
1025 Out << "static_assert(";
1026 D->getAssertExpr()->printPretty(OS&: Out, Helper: nullptr, Policy, Indentation, NewlineSymbol: "\n",
1027 Context: &Context);
1028 if (Expr *E = D->getMessage()) {
1029 Out << ", ";
1030 E->printPretty(OS&: Out, Helper: nullptr, Policy, Indentation, NewlineSymbol: "\n", Context: &Context);
1031 }
1032 Out << ")";
1033}
1034
1035//----------------------------------------------------------------------------
1036// C++ declarations
1037//----------------------------------------------------------------------------
1038void DeclPrinter::VisitNamespaceDecl(NamespaceDecl *D) {
1039 if (D->isInline())
1040 Out << "inline ";
1041
1042 Out << "namespace ";
1043 if (D->getDeclName())
1044 Out << D->getDeclName() << ' ';
1045 Out << "{\n";
1046
1047 VisitDeclContext(DC: D);
1048 Indent() << "}";
1049}
1050
1051void DeclPrinter::VisitUsingDirectiveDecl(UsingDirectiveDecl *D) {
1052 Out << "using namespace ";
1053 if (D->getQualifier())
1054 D->getQualifier()->print(OS&: Out, Policy);
1055 Out << *D->getNominatedNamespaceAsWritten();
1056}
1057
1058void DeclPrinter::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) {
1059 Out << "namespace " << *D << " = ";
1060 if (D->getQualifier())
1061 D->getQualifier()->print(OS&: Out, Policy);
1062 Out << *D->getAliasedNamespace();
1063}
1064
1065void DeclPrinter::VisitEmptyDecl(EmptyDecl *D) {
1066 prettyPrintAttributes(D);
1067}
1068
1069void DeclPrinter::VisitCXXRecordDecl(CXXRecordDecl *D) {
1070 // FIXME: add printing of pragma attributes if required.
1071 if (!Policy.SuppressSpecifiers && D->isModulePrivate())
1072 Out << "__module_private__ ";
1073
1074 Out << D->getKindName() << ' ';
1075
1076 // FIXME: Move before printing the decl kind to match the behavior of the
1077 // attribute printing for variables and function where they are printed first.
1078 if (prettyPrintAttributes(D, Pos: AttrPosAsWritten::Left))
1079 Out << ' ';
1080
1081 if (D->getIdentifier()) {
1082 if (auto *NNS = D->getQualifier())
1083 NNS->print(OS&: Out, Policy);
1084 Out << *D;
1085
1086 if (auto *S = dyn_cast<ClassTemplateSpecializationDecl>(Val: D)) {
1087 const TemplateParameterList *TParams =
1088 S->getSpecializedTemplate()->getTemplateParameters();
1089 const ASTTemplateArgumentListInfo *TArgAsWritten =
1090 S->getTemplateArgsAsWritten();
1091 if (TArgAsWritten && !Policy.PrintCanonicalTypes)
1092 printTemplateArguments(Args: TArgAsWritten->arguments(), Params: TParams);
1093 else
1094 printTemplateArguments(Args: S->getTemplateArgs().asArray(), Params: TParams);
1095 }
1096 }
1097
1098 prettyPrintAttributes(D, Pos: AttrPosAsWritten::Right);
1099
1100 if (D->isCompleteDefinition()) {
1101 Out << ' ';
1102 // Print the base classes
1103 if (D->getNumBases()) {
1104 Out << ": ";
1105 for (CXXRecordDecl::base_class_iterator Base = D->bases_begin(),
1106 BaseEnd = D->bases_end(); Base != BaseEnd; ++Base) {
1107 if (Base != D->bases_begin())
1108 Out << ", ";
1109
1110 if (Base->isVirtual())
1111 Out << "virtual ";
1112
1113 AccessSpecifier AS = Base->getAccessSpecifierAsWritten();
1114 if (AS != AS_none) {
1115 Print(AS);
1116 Out << " ";
1117 }
1118 Out << Base->getType().getAsString(Policy);
1119
1120 if (Base->isPackExpansion())
1121 Out << "...";
1122 }
1123 Out << ' ';
1124 }
1125
1126 // Print the class definition
1127 // FIXME: Doesn't print access specifiers, e.g., "public:"
1128 if (Policy.TerseOutput) {
1129 Out << "{}";
1130 } else {
1131 Out << "{\n";
1132 VisitDeclContext(DC: D);
1133 Indent() << "}";
1134 }
1135 }
1136}
1137
1138void DeclPrinter::VisitLinkageSpecDecl(LinkageSpecDecl *D) {
1139 const char *l;
1140 if (D->getLanguage() == LinkageSpecLanguageIDs::C)
1141 l = "C";
1142 else {
1143 assert(D->getLanguage() == LinkageSpecLanguageIDs::CXX &&
1144 "unknown language in linkage specification");
1145 l = "C++";
1146 }
1147
1148 Out << "extern \"" << l << "\" ";
1149 if (D->hasBraces()) {
1150 Out << "{\n";
1151 VisitDeclContext(DC: D);
1152 Indent() << "}";
1153 } else
1154 Visit(D: *D->decls_begin());
1155}
1156
1157void DeclPrinter::printTemplateParameters(const TemplateParameterList *Params,
1158 bool OmitTemplateKW) {
1159 assert(Params);
1160
1161 // Don't print invented template parameter lists.
1162 if (!Params->empty() && Params->getParam(Idx: 0)->isImplicit())
1163 return;
1164
1165 if (!OmitTemplateKW)
1166 Out << "template ";
1167 Out << '<';
1168
1169 bool NeedComma = false;
1170 for (const Decl *Param : *Params) {
1171 if (Param->isImplicit())
1172 continue;
1173
1174 if (NeedComma)
1175 Out << ", ";
1176 else
1177 NeedComma = true;
1178
1179 if (const auto *TTP = dyn_cast<TemplateTypeParmDecl>(Val: Param)) {
1180 VisitTemplateTypeParmDecl(TTP);
1181 } else if (auto NTTP = dyn_cast<NonTypeTemplateParmDecl>(Val: Param)) {
1182 VisitNonTypeTemplateParmDecl(NTTP);
1183 } else if (auto TTPD = dyn_cast<TemplateTemplateParmDecl>(Val: Param)) {
1184 VisitTemplateDecl(D: TTPD);
1185 // FIXME: print the default argument, if present.
1186 }
1187 }
1188
1189 Out << '>';
1190
1191 if (const Expr *RequiresClause = Params->getRequiresClause()) {
1192 Out << " requires ";
1193 RequiresClause->printPretty(OS&: Out, Helper: nullptr, Policy, Indentation, NewlineSymbol: "\n",
1194 Context: &Context);
1195 }
1196
1197 if (!OmitTemplateKW)
1198 Out << ' ';
1199}
1200
1201void DeclPrinter::printTemplateArguments(ArrayRef<TemplateArgument> Args,
1202 const TemplateParameterList *Params) {
1203 Out << "<";
1204 for (size_t I = 0, E = Args.size(); I < E; ++I) {
1205 if (I)
1206 Out << ", ";
1207 if (!Params)
1208 Args[I].print(Policy, Out, /*IncludeType*/ true);
1209 else
1210 Args[I].print(Policy, Out,
1211 IncludeType: TemplateParameterList::shouldIncludeTypeForArgument(
1212 Policy, TPL: Params, Idx: I));
1213 }
1214 Out << ">";
1215}
1216
1217void DeclPrinter::printTemplateArguments(ArrayRef<TemplateArgumentLoc> Args,
1218 const TemplateParameterList *Params) {
1219 Out << "<";
1220 for (size_t I = 0, E = Args.size(); I < E; ++I) {
1221 if (I)
1222 Out << ", ";
1223 if (!Params)
1224 Args[I].getArgument().print(Policy, Out, /*IncludeType*/ true);
1225 else
1226 Args[I].getArgument().print(
1227 Policy, Out,
1228 IncludeType: TemplateParameterList::shouldIncludeTypeForArgument(Policy, TPL: Params,
1229 Idx: I));
1230 }
1231 Out << ">";
1232}
1233
1234void DeclPrinter::VisitTemplateDecl(const TemplateDecl *D) {
1235 printTemplateParameters(Params: D->getTemplateParameters());
1236
1237 if (const TemplateTemplateParmDecl *TTP =
1238 dyn_cast<TemplateTemplateParmDecl>(Val: D)) {
1239 if (TTP->wasDeclaredWithTypename())
1240 Out << "typename";
1241 else
1242 Out << "class";
1243
1244 if (TTP->isParameterPack())
1245 Out << " ...";
1246 else if (TTP->getDeclName())
1247 Out << ' ';
1248
1249 if (TTP->getDeclName()) {
1250 if (Policy.CleanUglifiedParameters && TTP->getIdentifier())
1251 Out << TTP->getIdentifier()->deuglifiedName();
1252 else
1253 Out << TTP->getDeclName();
1254 }
1255 } else if (auto *TD = D->getTemplatedDecl())
1256 Visit(D: TD);
1257 else if (const auto *Concept = dyn_cast<ConceptDecl>(Val: D)) {
1258 Out << "concept " << Concept->getName() << " = " ;
1259 Concept->getConstraintExpr()->printPretty(OS&: Out, Helper: nullptr, Policy, Indentation,
1260 NewlineSymbol: "\n", Context: &Context);
1261 }
1262}
1263
1264void DeclPrinter::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
1265 prettyPrintPragmas(D: D->getTemplatedDecl());
1266 // Print any leading template parameter lists.
1267 if (const FunctionDecl *FD = D->getTemplatedDecl()) {
1268 for (unsigned I = 0, NumTemplateParams = FD->getNumTemplateParameterLists();
1269 I < NumTemplateParams; ++I)
1270 printTemplateParameters(Params: FD->getTemplateParameterList(index: I));
1271 }
1272 VisitRedeclarableTemplateDecl(D);
1273 // Declare target attribute is special one, natural spelling for the pragma
1274 // assumes "ending" construct so print it here.
1275 if (D->getTemplatedDecl()->hasAttr<OMPDeclareTargetDeclAttr>())
1276 Out << "#pragma omp end declare target\n";
1277
1278 // Never print "instantiations" for deduction guides (they don't really
1279 // have them).
1280 if (PrintInstantiation &&
1281 !isa<CXXDeductionGuideDecl>(Val: D->getTemplatedDecl())) {
1282 FunctionDecl *PrevDecl = D->getTemplatedDecl();
1283 const FunctionDecl *Def;
1284 if (PrevDecl->isDefined(Definition&: Def) && Def != PrevDecl)
1285 return;
1286 for (auto *I : D->specializations())
1287 if (I->getTemplateSpecializationKind() == TSK_ImplicitInstantiation) {
1288 if (!PrevDecl->isThisDeclarationADefinition())
1289 Out << ";\n";
1290 Indent();
1291 prettyPrintPragmas(D: I);
1292 Visit(D: I);
1293 }
1294 }
1295}
1296
1297void DeclPrinter::VisitClassTemplateDecl(ClassTemplateDecl *D) {
1298 VisitRedeclarableTemplateDecl(D);
1299
1300 if (PrintInstantiation) {
1301 for (auto *I : D->specializations())
1302 if (I->getSpecializationKind() == TSK_ImplicitInstantiation) {
1303 if (D->isThisDeclarationADefinition())
1304 Out << ";";
1305 Out << "\n";
1306 Indent();
1307 Visit(D: I);
1308 }
1309 }
1310}
1311
1312void DeclPrinter::VisitClassTemplateSpecializationDecl(
1313 ClassTemplateSpecializationDecl *D) {
1314 Out << "template<> ";
1315 VisitCXXRecordDecl(D);
1316}
1317
1318void DeclPrinter::VisitClassTemplatePartialSpecializationDecl(
1319 ClassTemplatePartialSpecializationDecl *D) {
1320 printTemplateParameters(Params: D->getTemplateParameters());
1321 VisitCXXRecordDecl(D);
1322}
1323
1324//----------------------------------------------------------------------------
1325// Objective-C declarations
1326//----------------------------------------------------------------------------
1327
1328void DeclPrinter::PrintObjCMethodType(ASTContext &Ctx,
1329 Decl::ObjCDeclQualifier Quals,
1330 QualType T) {
1331 Out << '(';
1332 if (Quals & Decl::ObjCDeclQualifier::OBJC_TQ_In)
1333 Out << "in ";
1334 if (Quals & Decl::ObjCDeclQualifier::OBJC_TQ_Inout)
1335 Out << "inout ";
1336 if (Quals & Decl::ObjCDeclQualifier::OBJC_TQ_Out)
1337 Out << "out ";
1338 if (Quals & Decl::ObjCDeclQualifier::OBJC_TQ_Bycopy)
1339 Out << "bycopy ";
1340 if (Quals & Decl::ObjCDeclQualifier::OBJC_TQ_Byref)
1341 Out << "byref ";
1342 if (Quals & Decl::ObjCDeclQualifier::OBJC_TQ_Oneway)
1343 Out << "oneway ";
1344 if (Quals & Decl::ObjCDeclQualifier::OBJC_TQ_CSNullability) {
1345 if (auto nullability = AttributedType::stripOuterNullability(T))
1346 Out << getNullabilitySpelling(kind: *nullability, isContextSensitive: true) << ' ';
1347 }
1348
1349 Out << Ctx.getUnqualifiedObjCPointerType(type: T).getAsString(Policy);
1350 Out << ')';
1351}
1352
1353void DeclPrinter::PrintObjCTypeParams(ObjCTypeParamList *Params) {
1354 Out << "<";
1355 unsigned First = true;
1356 for (auto *Param : *Params) {
1357 if (First) {
1358 First = false;
1359 } else {
1360 Out << ", ";
1361 }
1362
1363 switch (Param->getVariance()) {
1364 case ObjCTypeParamVariance::Invariant:
1365 break;
1366
1367 case ObjCTypeParamVariance::Covariant:
1368 Out << "__covariant ";
1369 break;
1370
1371 case ObjCTypeParamVariance::Contravariant:
1372 Out << "__contravariant ";
1373 break;
1374 }
1375
1376 Out << Param->getDeclName();
1377
1378 if (Param->hasExplicitBound()) {
1379 Out << " : " << Param->getUnderlyingType().getAsString(Policy);
1380 }
1381 }
1382 Out << ">";
1383}
1384
1385void DeclPrinter::VisitObjCMethodDecl(ObjCMethodDecl *OMD) {
1386 if (OMD->isInstanceMethod())
1387 Out << "- ";
1388 else
1389 Out << "+ ";
1390 if (!OMD->getReturnType().isNull()) {
1391 PrintObjCMethodType(Ctx&: OMD->getASTContext(), Quals: OMD->getObjCDeclQualifier(),
1392 T: OMD->getReturnType());
1393 }
1394
1395 std::string name = OMD->getSelector().getAsString();
1396 std::string::size_type pos, lastPos = 0;
1397 for (const auto *PI : OMD->parameters()) {
1398 // FIXME: selector is missing here!
1399 pos = name.find_first_of(c: ':', pos: lastPos);
1400 if (lastPos != 0)
1401 Out << " ";
1402 Out << name.substr(pos: lastPos, n: pos - lastPos) << ':';
1403 PrintObjCMethodType(Ctx&: OMD->getASTContext(),
1404 Quals: PI->getObjCDeclQualifier(),
1405 T: PI->getType());
1406 Out << *PI;
1407 lastPos = pos + 1;
1408 }
1409
1410 if (OMD->param_begin() == OMD->param_end())
1411 Out << name;
1412
1413 if (OMD->isVariadic())
1414 Out << ", ...";
1415
1416 prettyPrintAttributes(D: OMD);
1417
1418 if (OMD->getBody() && !Policy.TerseOutput) {
1419 Out << ' ';
1420 OMD->getBody()->printPretty(OS&: Out, Helper: nullptr, Policy, Indentation, NewlineSymbol: "\n",
1421 Context: &Context);
1422 }
1423 else if (Policy.PolishForDeclaration)
1424 Out << ';';
1425}
1426
1427void DeclPrinter::VisitObjCImplementationDecl(ObjCImplementationDecl *OID) {
1428 std::string I = OID->getNameAsString();
1429 ObjCInterfaceDecl *SID = OID->getSuperClass();
1430
1431 bool eolnOut = false;
1432 if (SID)
1433 Out << "@implementation " << I << " : " << *SID;
1434 else
1435 Out << "@implementation " << I;
1436
1437 if (OID->ivar_size() > 0) {
1438 Out << "{\n";
1439 eolnOut = true;
1440 Indentation += Policy.Indentation;
1441 for (const auto *I : OID->ivars()) {
1442 Indent() << I->getASTContext().getUnqualifiedObjCPointerType(type: I->getType()).
1443 getAsString(Policy) << ' ' << *I << ";\n";
1444 }
1445 Indentation -= Policy.Indentation;
1446 Out << "}\n";
1447 }
1448 else if (SID || (OID->decls_begin() != OID->decls_end())) {
1449 Out << "\n";
1450 eolnOut = true;
1451 }
1452 VisitDeclContext(DC: OID, Indent: false);
1453 if (!eolnOut)
1454 Out << "\n";
1455 Out << "@end";
1456}
1457
1458void DeclPrinter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *OID) {
1459 std::string I = OID->getNameAsString();
1460 ObjCInterfaceDecl *SID = OID->getSuperClass();
1461
1462 if (!OID->isThisDeclarationADefinition()) {
1463 Out << "@class " << I;
1464
1465 if (auto TypeParams = OID->getTypeParamListAsWritten()) {
1466 PrintObjCTypeParams(Params: TypeParams);
1467 }
1468
1469 Out << ";";
1470 return;
1471 }
1472 bool eolnOut = false;
1473 if (OID->hasAttrs()) {
1474 prettyPrintAttributes(D: OID);
1475 Out << "\n";
1476 }
1477
1478 Out << "@interface " << I;
1479
1480 if (auto TypeParams = OID->getTypeParamListAsWritten()) {
1481 PrintObjCTypeParams(Params: TypeParams);
1482 }
1483
1484 if (SID)
1485 Out << " : " << QualType(OID->getSuperClassType(), 0).getAsString(Policy);
1486
1487 // Protocols?
1488 const ObjCList<ObjCProtocolDecl> &Protocols = OID->getReferencedProtocols();
1489 if (!Protocols.empty()) {
1490 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
1491 E = Protocols.end(); I != E; ++I)
1492 Out << (I == Protocols.begin() ? '<' : ',') << **I;
1493 Out << "> ";
1494 }
1495
1496 if (OID->ivar_size() > 0) {
1497 Out << "{\n";
1498 eolnOut = true;
1499 Indentation += Policy.Indentation;
1500 for (const auto *I : OID->ivars()) {
1501 Indent() << I->getASTContext()
1502 .getUnqualifiedObjCPointerType(type: I->getType())
1503 .getAsString(Policy) << ' ' << *I << ";\n";
1504 }
1505 Indentation -= Policy.Indentation;
1506 Out << "}\n";
1507 }
1508 else if (SID || (OID->decls_begin() != OID->decls_end())) {
1509 Out << "\n";
1510 eolnOut = true;
1511 }
1512
1513 VisitDeclContext(DC: OID, Indent: false);
1514 if (!eolnOut)
1515 Out << "\n";
1516 Out << "@end";
1517 // FIXME: implement the rest...
1518}
1519
1520void DeclPrinter::VisitObjCProtocolDecl(ObjCProtocolDecl *PID) {
1521 if (!PID->isThisDeclarationADefinition()) {
1522 Out << "@protocol " << *PID << ";\n";
1523 return;
1524 }
1525 // Protocols?
1526 const ObjCList<ObjCProtocolDecl> &Protocols = PID->getReferencedProtocols();
1527 if (!Protocols.empty()) {
1528 Out << "@protocol " << *PID;
1529 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
1530 E = Protocols.end(); I != E; ++I)
1531 Out << (I == Protocols.begin() ? '<' : ',') << **I;
1532 Out << ">\n";
1533 } else
1534 Out << "@protocol " << *PID << '\n';
1535 VisitDeclContext(DC: PID, Indent: false);
1536 Out << "@end";
1537}
1538
1539void DeclPrinter::VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *PID) {
1540 Out << "@implementation ";
1541 if (const auto *CID = PID->getClassInterface())
1542 Out << *CID;
1543 else
1544 Out << "<<error-type>>";
1545 Out << '(' << *PID << ")\n";
1546
1547 VisitDeclContext(DC: PID, Indent: false);
1548 Out << "@end";
1549 // FIXME: implement the rest...
1550}
1551
1552void DeclPrinter::VisitObjCCategoryDecl(ObjCCategoryDecl *PID) {
1553 Out << "@interface ";
1554 if (const auto *CID = PID->getClassInterface())
1555 Out << *CID;
1556 else
1557 Out << "<<error-type>>";
1558 if (auto TypeParams = PID->getTypeParamList()) {
1559 PrintObjCTypeParams(Params: TypeParams);
1560 }
1561 Out << "(" << *PID << ")\n";
1562 if (PID->ivar_size() > 0) {
1563 Out << "{\n";
1564 Indentation += Policy.Indentation;
1565 for (const auto *I : PID->ivars())
1566 Indent() << I->getASTContext().getUnqualifiedObjCPointerType(type: I->getType()).
1567 getAsString(Policy) << ' ' << *I << ";\n";
1568 Indentation -= Policy.Indentation;
1569 Out << "}\n";
1570 }
1571
1572 VisitDeclContext(DC: PID, Indent: false);
1573 Out << "@end";
1574
1575 // FIXME: implement the rest...
1576}
1577
1578void DeclPrinter::VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *AID) {
1579 Out << "@compatibility_alias " << *AID
1580 << ' ' << *AID->getClassInterface() << ";\n";
1581}
1582
1583/// PrintObjCPropertyDecl - print a property declaration.
1584///
1585/// Print attributes in the following order:
1586/// - class
1587/// - nonatomic | atomic
1588/// - assign | retain | strong | copy | weak | unsafe_unretained
1589/// - readwrite | readonly
1590/// - getter & setter
1591/// - nullability
1592void DeclPrinter::VisitObjCPropertyDecl(ObjCPropertyDecl *PDecl) {
1593 if (PDecl->getPropertyImplementation() == ObjCPropertyDecl::Required)
1594 Out << "@required\n";
1595 else if (PDecl->getPropertyImplementation() == ObjCPropertyDecl::Optional)
1596 Out << "@optional\n";
1597
1598 QualType T = PDecl->getType();
1599
1600 Out << "@property";
1601 if (PDecl->getPropertyAttributes() != ObjCPropertyAttribute::kind_noattr) {
1602 bool first = true;
1603 Out << "(";
1604 if (PDecl->getPropertyAttributes() & ObjCPropertyAttribute::kind_class) {
1605 Out << (first ? "" : ", ") << "class";
1606 first = false;
1607 }
1608
1609 if (PDecl->getPropertyAttributes() & ObjCPropertyAttribute::kind_direct) {
1610 Out << (first ? "" : ", ") << "direct";
1611 first = false;
1612 }
1613
1614 if (PDecl->getPropertyAttributes() &
1615 ObjCPropertyAttribute::kind_nonatomic) {
1616 Out << (first ? "" : ", ") << "nonatomic";
1617 first = false;
1618 }
1619 if (PDecl->getPropertyAttributes() & ObjCPropertyAttribute::kind_atomic) {
1620 Out << (first ? "" : ", ") << "atomic";
1621 first = false;
1622 }
1623
1624 if (PDecl->getPropertyAttributes() & ObjCPropertyAttribute::kind_assign) {
1625 Out << (first ? "" : ", ") << "assign";
1626 first = false;
1627 }
1628 if (PDecl->getPropertyAttributes() & ObjCPropertyAttribute::kind_retain) {
1629 Out << (first ? "" : ", ") << "retain";
1630 first = false;
1631 }
1632
1633 if (PDecl->getPropertyAttributes() & ObjCPropertyAttribute::kind_strong) {
1634 Out << (first ? "" : ", ") << "strong";
1635 first = false;
1636 }
1637 if (PDecl->getPropertyAttributes() & ObjCPropertyAttribute::kind_copy) {
1638 Out << (first ? "" : ", ") << "copy";
1639 first = false;
1640 }
1641 if (PDecl->getPropertyAttributes() & ObjCPropertyAttribute::kind_weak) {
1642 Out << (first ? "" : ", ") << "weak";
1643 first = false;
1644 }
1645 if (PDecl->getPropertyAttributes() &
1646 ObjCPropertyAttribute::kind_unsafe_unretained) {
1647 Out << (first ? "" : ", ") << "unsafe_unretained";
1648 first = false;
1649 }
1650
1651 if (PDecl->getPropertyAttributes() &
1652 ObjCPropertyAttribute::kind_readwrite) {
1653 Out << (first ? "" : ", ") << "readwrite";
1654 first = false;
1655 }
1656 if (PDecl->getPropertyAttributes() & ObjCPropertyAttribute::kind_readonly) {
1657 Out << (first ? "" : ", ") << "readonly";
1658 first = false;
1659 }
1660
1661 if (PDecl->getPropertyAttributes() & ObjCPropertyAttribute::kind_getter) {
1662 Out << (first ? "" : ", ") << "getter = ";
1663 PDecl->getGetterName().print(OS&: Out);
1664 first = false;
1665 }
1666 if (PDecl->getPropertyAttributes() & ObjCPropertyAttribute::kind_setter) {
1667 Out << (first ? "" : ", ") << "setter = ";
1668 PDecl->getSetterName().print(OS&: Out);
1669 first = false;
1670 }
1671
1672 if (PDecl->getPropertyAttributes() &
1673 ObjCPropertyAttribute::kind_nullability) {
1674 if (auto nullability = AttributedType::stripOuterNullability(T)) {
1675 if (*nullability == NullabilityKind::Unspecified &&
1676 (PDecl->getPropertyAttributes() &
1677 ObjCPropertyAttribute::kind_null_resettable)) {
1678 Out << (first ? "" : ", ") << "null_resettable";
1679 } else {
1680 Out << (first ? "" : ", ")
1681 << getNullabilitySpelling(kind: *nullability, isContextSensitive: true);
1682 }
1683 first = false;
1684 }
1685 }
1686
1687 (void) first; // Silence dead store warning due to idiomatic code.
1688 Out << ")";
1689 }
1690 std::string TypeStr = PDecl->getASTContext().getUnqualifiedObjCPointerType(type: T).
1691 getAsString(Policy);
1692 Out << ' ' << TypeStr;
1693 if (!StringRef(TypeStr).ends_with(Suffix: "*"))
1694 Out << ' ';
1695 Out << *PDecl;
1696 if (Policy.PolishForDeclaration)
1697 Out << ';';
1698}
1699
1700void DeclPrinter::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *PID) {
1701 if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize)
1702 Out << "@synthesize ";
1703 else
1704 Out << "@dynamic ";
1705 Out << *PID->getPropertyDecl();
1706 if (PID->getPropertyIvarDecl())
1707 Out << '=' << *PID->getPropertyIvarDecl();
1708}
1709
1710void DeclPrinter::VisitUsingDecl(UsingDecl *D) {
1711 if (!D->isAccessDeclaration())
1712 Out << "using ";
1713 if (D->hasTypename())
1714 Out << "typename ";
1715 D->getQualifier()->print(OS&: Out, Policy);
1716
1717 // Use the correct record name when the using declaration is used for
1718 // inheriting constructors.
1719 for (const auto *Shadow : D->shadows()) {
1720 if (const auto *ConstructorShadow =
1721 dyn_cast<ConstructorUsingShadowDecl>(Val: Shadow)) {
1722 assert(Shadow->getDeclContext() == ConstructorShadow->getDeclContext());
1723 Out << *ConstructorShadow->getNominatedBaseClass();
1724 return;
1725 }
1726 }
1727 Out << *D;
1728}
1729
1730void DeclPrinter::VisitUsingEnumDecl(UsingEnumDecl *D) {
1731 Out << "using enum " << D->getEnumDecl();
1732}
1733
1734void
1735DeclPrinter::VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D) {
1736 Out << "using typename ";
1737 D->getQualifier()->print(OS&: Out, Policy);
1738 Out << D->getDeclName();
1739}
1740
1741void DeclPrinter::VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D) {
1742 if (!D->isAccessDeclaration())
1743 Out << "using ";
1744 D->getQualifier()->print(OS&: Out, Policy);
1745 Out << D->getDeclName();
1746}
1747
1748void DeclPrinter::VisitUsingShadowDecl(UsingShadowDecl *D) {
1749 // ignore
1750}
1751
1752void DeclPrinter::VisitOMPThreadPrivateDecl(OMPThreadPrivateDecl *D) {
1753 Out << "#pragma omp threadprivate";
1754 if (!D->varlist_empty()) {
1755 for (OMPThreadPrivateDecl::varlist_iterator I = D->varlist_begin(),
1756 E = D->varlist_end();
1757 I != E; ++I) {
1758 Out << (I == D->varlist_begin() ? '(' : ',');
1759 NamedDecl *ND = cast<DeclRefExpr>(Val: *I)->getDecl();
1760 ND->printQualifiedName(OS&: Out);
1761 }
1762 Out << ")";
1763 }
1764}
1765
1766void DeclPrinter::VisitHLSLBufferDecl(HLSLBufferDecl *D) {
1767 if (D->isCBuffer())
1768 Out << "cbuffer ";
1769 else
1770 Out << "tbuffer ";
1771
1772 Out << *D;
1773
1774 prettyPrintAttributes(D);
1775
1776 Out << " {\n";
1777 VisitDeclContext(DC: D);
1778 Indent() << "}";
1779}
1780
1781void DeclPrinter::VisitOMPAllocateDecl(OMPAllocateDecl *D) {
1782 Out << "#pragma omp allocate";
1783 if (!D->varlist_empty()) {
1784 for (OMPAllocateDecl::varlist_iterator I = D->varlist_begin(),
1785 E = D->varlist_end();
1786 I != E; ++I) {
1787 Out << (I == D->varlist_begin() ? '(' : ',');
1788 NamedDecl *ND = cast<DeclRefExpr>(Val: *I)->getDecl();
1789 ND->printQualifiedName(OS&: Out);
1790 }
1791 Out << ")";
1792 }
1793 if (!D->clauselist_empty()) {
1794 OMPClausePrinter Printer(Out, Policy);
1795 for (OMPClause *C : D->clauselists()) {
1796 Out << " ";
1797 Printer.Visit(S: C);
1798 }
1799 }
1800}
1801
1802void DeclPrinter::VisitOMPRequiresDecl(OMPRequiresDecl *D) {
1803 Out << "#pragma omp requires ";
1804 if (!D->clauselist_empty()) {
1805 OMPClausePrinter Printer(Out, Policy);
1806 for (auto I = D->clauselist_begin(), E = D->clauselist_end(); I != E; ++I)
1807 Printer.Visit(S: *I);
1808 }
1809}
1810
1811void DeclPrinter::VisitOMPDeclareReductionDecl(OMPDeclareReductionDecl *D) {
1812 if (!D->isInvalidDecl()) {
1813 Out << "#pragma omp declare reduction (";
1814 if (D->getDeclName().getNameKind() == DeclarationName::CXXOperatorName) {
1815 const char *OpName =
1816 getOperatorSpelling(Operator: D->getDeclName().getCXXOverloadedOperator());
1817 assert(OpName && "not an overloaded operator");
1818 Out << OpName;
1819 } else {
1820 assert(D->getDeclName().isIdentifier());
1821 D->printName(OS&: Out, Policy);
1822 }
1823 Out << " : ";
1824 D->getType().print(OS&: Out, Policy);
1825 Out << " : ";
1826 D->getCombiner()->printPretty(OS&: Out, Helper: nullptr, Policy, Indentation: 0, NewlineSymbol: "\n", Context: &Context);
1827 Out << ")";
1828 if (auto *Init = D->getInitializer()) {
1829 Out << " initializer(";
1830 switch (D->getInitializerKind()) {
1831 case OMPDeclareReductionInitKind::Direct:
1832 Out << "omp_priv(";
1833 break;
1834 case OMPDeclareReductionInitKind::Copy:
1835 Out << "omp_priv = ";
1836 break;
1837 case OMPDeclareReductionInitKind::Call:
1838 break;
1839 }
1840 Init->printPretty(OS&: Out, Helper: nullptr, Policy, Indentation: 0, NewlineSymbol: "\n", Context: &Context);
1841 if (D->getInitializerKind() == OMPDeclareReductionInitKind::Direct)
1842 Out << ")";
1843 Out << ")";
1844 }
1845 }
1846}
1847
1848void DeclPrinter::VisitOMPDeclareMapperDecl(OMPDeclareMapperDecl *D) {
1849 if (!D->isInvalidDecl()) {
1850 Out << "#pragma omp declare mapper (";
1851 D->printName(OS&: Out, Policy);
1852 Out << " : ";
1853 D->getType().print(OS&: Out, Policy);
1854 Out << " ";
1855 Out << D->getVarName();
1856 Out << ")";
1857 if (!D->clauselist_empty()) {
1858 OMPClausePrinter Printer(Out, Policy);
1859 for (auto *C : D->clauselists()) {
1860 Out << " ";
1861 Printer.Visit(S: C);
1862 }
1863 }
1864 }
1865}
1866
1867void DeclPrinter::VisitOMPCapturedExprDecl(OMPCapturedExprDecl *D) {
1868 D->getInit()->printPretty(OS&: Out, Helper: nullptr, Policy, Indentation, NewlineSymbol: "\n", Context: &Context);
1869}
1870
1871void DeclPrinter::VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *TTP) {
1872 if (const TypeConstraint *TC = TTP->getTypeConstraint())
1873 TC->print(OS&: Out, Policy);
1874 else if (TTP->wasDeclaredWithTypename())
1875 Out << "typename";
1876 else
1877 Out << "class";
1878
1879 if (TTP->isParameterPack())
1880 Out << " ...";
1881 else if (TTP->getDeclName())
1882 Out << ' ';
1883
1884 if (TTP->getDeclName()) {
1885 if (Policy.CleanUglifiedParameters && TTP->getIdentifier())
1886 Out << TTP->getIdentifier()->deuglifiedName();
1887 else
1888 Out << TTP->getDeclName();
1889 }
1890
1891 if (TTP->hasDefaultArgument()) {
1892 Out << " = ";
1893 TTP->getDefaultArgument().getArgument().print(Policy, Out,
1894 /*IncludeType=*/false);
1895 }
1896}
1897
1898void DeclPrinter::VisitNonTypeTemplateParmDecl(
1899 const NonTypeTemplateParmDecl *NTTP) {
1900 StringRef Name;
1901 if (IdentifierInfo *II = NTTP->getIdentifier())
1902 Name =
1903 Policy.CleanUglifiedParameters ? II->deuglifiedName() : II->getName();
1904 printDeclType(T: NTTP->getType(), DeclName: Name, Pack: NTTP->isParameterPack());
1905
1906 if (NTTP->hasDefaultArgument()) {
1907 Out << " = ";
1908 NTTP->getDefaultArgument().getArgument().print(Policy, Out,
1909 /*IncludeType=*/false);
1910 }
1911}
1912