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(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(Out, nullptr, Policy, Indentation, "\n",
391 &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(Out, nullptr, Policy, Indentation, "\n",
401 &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);
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(D, 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(Out, Policy, 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(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(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(Out, nullptr, Policy, Indentation, "\n", &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(EOut, nullptr, Policy, Indentation, "\n",
628 &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, 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(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(EOut, nullptr, SubPolicy,
792 Indentation, "\n", &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(Out, nullptr, SubPolicy, Indentation,
820 "\n", &Context);
821 }
822 } else {
823 Ty.print(OS&: Out, Policy, PlaceHolder: Proto);
824 }
825
826 prettyPrintAttributes(D, 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(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(D->getType()).
898 stream(Policy, D->getName(), Indentation);
899
900 if (D->isBitField()) {
901 Out << " : ";
902 D->getBitWidth()->printPretty(Out, nullptr, Policy, Indentation, "\n",
903 &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(Out, nullptr, Policy, Indentation, "\n", &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, 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(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, 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(Out, nullptr, SubPolicy, Indentation, "\n", &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(Out, nullptr, Policy, Indentation, "\n",
1010 &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(Out, nullptr, Policy, Indentation, "\n",
1027 &Context);
1028 if (Expr *E = D->getMessage()) {
1029 Out << ", ";
1030 E->printPretty(Out, nullptr, Policy, Indentation, "\n", &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(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, AttrPosAsWritten::Left))
1079 Out << ' ';
1080
1081 if (D->getIdentifier()) {
1082 if (auto *NNS = D->getQualifier())
1083 NNS->print(Out, Policy);
1084 Out << *D;
1085
1086 if (auto S = dyn_cast<ClassTemplateSpecializationDecl>(Val: D)) {
1087 ArrayRef<TemplateArgument> Args = S->getTemplateArgs().asArray();
1088 if (!Policy.PrintCanonicalTypes)
1089 if (const auto* TSI = S->getTypeAsWritten())
1090 if (const auto *TST =
1091 dyn_cast<TemplateSpecializationType>(Val: TSI->getType()))
1092 Args = TST->template_arguments();
1093 printTemplateArguments(
1094 Args, S->getSpecializedTemplate()->getTemplateParameters());
1095 }
1096 }
1097
1098 prettyPrintAttributes(D, 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(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(D);
1152 Indent() << "}";
1153 } else
1154 Visit(*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>(Param)) {
1180 VisitTemplateTypeParmDecl(TTP: TTP);
1181 } else if (auto NTTP = dyn_cast<NonTypeTemplateParmDecl>(Param)) {
1182 VisitNonTypeTemplateParmDecl(NTTP: NTTP);
1183 } else if (auto TTPD = dyn_cast<TemplateTemplateParmDecl>(Param)) {
1184 VisitTemplateDecl(D: TTPD);
1185 // FIXME: print the default argument, if present.
1186 }
1187 }
1188
1189 Out << '>';
1190 if (!OmitTemplateKW)
1191 Out << ' ';
1192}
1193
1194void DeclPrinter::printTemplateArguments(ArrayRef<TemplateArgument> Args,
1195 const TemplateParameterList *Params) {
1196 Out << "<";
1197 for (size_t I = 0, E = Args.size(); I < E; ++I) {
1198 if (I)
1199 Out << ", ";
1200 if (!Params)
1201 Args[I].print(Policy, Out, /*IncludeType*/ true);
1202 else
1203 Args[I].print(Policy, Out,
1204 IncludeType: TemplateParameterList::shouldIncludeTypeForArgument(
1205 Policy, TPL: Params, Idx: I));
1206 }
1207 Out << ">";
1208}
1209
1210void DeclPrinter::printTemplateArguments(ArrayRef<TemplateArgumentLoc> Args,
1211 const TemplateParameterList *Params) {
1212 Out << "<";
1213 for (size_t I = 0, E = Args.size(); I < E; ++I) {
1214 if (I)
1215 Out << ", ";
1216 if (!Params)
1217 Args[I].getArgument().print(Policy, Out, /*IncludeType*/ true);
1218 else
1219 Args[I].getArgument().print(
1220 Policy, Out,
1221 IncludeType: TemplateParameterList::shouldIncludeTypeForArgument(Policy, TPL: Params,
1222 Idx: I));
1223 }
1224 Out << ">";
1225}
1226
1227void DeclPrinter::VisitTemplateDecl(const TemplateDecl *D) {
1228 printTemplateParameters(Params: D->getTemplateParameters());
1229
1230 if (const TemplateTemplateParmDecl *TTP =
1231 dyn_cast<TemplateTemplateParmDecl>(Val: D)) {
1232 if (TTP->wasDeclaredWithTypename())
1233 Out << "typename";
1234 else
1235 Out << "class";
1236
1237 if (TTP->isParameterPack())
1238 Out << " ...";
1239 else if (TTP->getDeclName())
1240 Out << ' ';
1241
1242 if (TTP->getDeclName()) {
1243 if (Policy.CleanUglifiedParameters && TTP->getIdentifier())
1244 Out << TTP->getIdentifier()->deuglifiedName();
1245 else
1246 Out << TTP->getDeclName();
1247 }
1248 } else if (auto *TD = D->getTemplatedDecl())
1249 Visit(TD);
1250 else if (const auto *Concept = dyn_cast<ConceptDecl>(Val: D)) {
1251 Out << "concept " << Concept->getName() << " = " ;
1252 Concept->getConstraintExpr()->printPretty(Out, nullptr, Policy, Indentation,
1253 "\n", &Context);
1254 }
1255}
1256
1257void DeclPrinter::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
1258 prettyPrintPragmas(D->getTemplatedDecl());
1259 // Print any leading template parameter lists.
1260 if (const FunctionDecl *FD = D->getTemplatedDecl()) {
1261 for (unsigned I = 0, NumTemplateParams = FD->getNumTemplateParameterLists();
1262 I < NumTemplateParams; ++I)
1263 printTemplateParameters(Params: FD->getTemplateParameterList(I));
1264 }
1265 VisitRedeclarableTemplateDecl(D);
1266 // Declare target attribute is special one, natural spelling for the pragma
1267 // assumes "ending" construct so print it here.
1268 if (D->getTemplatedDecl()->hasAttr<OMPDeclareTargetDeclAttr>())
1269 Out << "#pragma omp end declare target\n";
1270
1271 // Never print "instantiations" for deduction guides (they don't really
1272 // have them).
1273 if (PrintInstantiation &&
1274 !isa<CXXDeductionGuideDecl>(Val: D->getTemplatedDecl())) {
1275 FunctionDecl *PrevDecl = D->getTemplatedDecl();
1276 const FunctionDecl *Def;
1277 if (PrevDecl->isDefined(Definition&: Def) && Def != PrevDecl)
1278 return;
1279 for (auto *I : D->specializations())
1280 if (I->getTemplateSpecializationKind() == TSK_ImplicitInstantiation) {
1281 if (!PrevDecl->isThisDeclarationADefinition())
1282 Out << ";\n";
1283 Indent();
1284 prettyPrintPragmas(I);
1285 Visit(I);
1286 }
1287 }
1288}
1289
1290void DeclPrinter::VisitClassTemplateDecl(ClassTemplateDecl *D) {
1291 VisitRedeclarableTemplateDecl(D);
1292
1293 if (PrintInstantiation) {
1294 for (auto *I : D->specializations())
1295 if (I->getSpecializationKind() == TSK_ImplicitInstantiation) {
1296 if (D->isThisDeclarationADefinition())
1297 Out << ";";
1298 Out << "\n";
1299 Indent();
1300 Visit(I);
1301 }
1302 }
1303}
1304
1305void DeclPrinter::VisitClassTemplateSpecializationDecl(
1306 ClassTemplateSpecializationDecl *D) {
1307 Out << "template<> ";
1308 VisitCXXRecordDecl(D);
1309}
1310
1311void DeclPrinter::VisitClassTemplatePartialSpecializationDecl(
1312 ClassTemplatePartialSpecializationDecl *D) {
1313 printTemplateParameters(Params: D->getTemplateParameters());
1314 VisitCXXRecordDecl(D);
1315}
1316
1317//----------------------------------------------------------------------------
1318// Objective-C declarations
1319//----------------------------------------------------------------------------
1320
1321void DeclPrinter::PrintObjCMethodType(ASTContext &Ctx,
1322 Decl::ObjCDeclQualifier Quals,
1323 QualType T) {
1324 Out << '(';
1325 if (Quals & Decl::ObjCDeclQualifier::OBJC_TQ_In)
1326 Out << "in ";
1327 if (Quals & Decl::ObjCDeclQualifier::OBJC_TQ_Inout)
1328 Out << "inout ";
1329 if (Quals & Decl::ObjCDeclQualifier::OBJC_TQ_Out)
1330 Out << "out ";
1331 if (Quals & Decl::ObjCDeclQualifier::OBJC_TQ_Bycopy)
1332 Out << "bycopy ";
1333 if (Quals & Decl::ObjCDeclQualifier::OBJC_TQ_Byref)
1334 Out << "byref ";
1335 if (Quals & Decl::ObjCDeclQualifier::OBJC_TQ_Oneway)
1336 Out << "oneway ";
1337 if (Quals & Decl::ObjCDeclQualifier::OBJC_TQ_CSNullability) {
1338 if (auto nullability = AttributedType::stripOuterNullability(T))
1339 Out << getNullabilitySpelling(kind: *nullability, isContextSensitive: true) << ' ';
1340 }
1341
1342 Out << Ctx.getUnqualifiedObjCPointerType(type: T).getAsString(Policy);
1343 Out << ')';
1344}
1345
1346void DeclPrinter::PrintObjCTypeParams(ObjCTypeParamList *Params) {
1347 Out << "<";
1348 unsigned First = true;
1349 for (auto *Param : *Params) {
1350 if (First) {
1351 First = false;
1352 } else {
1353 Out << ", ";
1354 }
1355
1356 switch (Param->getVariance()) {
1357 case ObjCTypeParamVariance::Invariant:
1358 break;
1359
1360 case ObjCTypeParamVariance::Covariant:
1361 Out << "__covariant ";
1362 break;
1363
1364 case ObjCTypeParamVariance::Contravariant:
1365 Out << "__contravariant ";
1366 break;
1367 }
1368
1369 Out << Param->getDeclName();
1370
1371 if (Param->hasExplicitBound()) {
1372 Out << " : " << Param->getUnderlyingType().getAsString(Policy);
1373 }
1374 }
1375 Out << ">";
1376}
1377
1378void DeclPrinter::VisitObjCMethodDecl(ObjCMethodDecl *OMD) {
1379 if (OMD->isInstanceMethod())
1380 Out << "- ";
1381 else
1382 Out << "+ ";
1383 if (!OMD->getReturnType().isNull()) {
1384 PrintObjCMethodType(Ctx&: OMD->getASTContext(), Quals: OMD->getObjCDeclQualifier(),
1385 T: OMD->getReturnType());
1386 }
1387
1388 std::string name = OMD->getSelector().getAsString();
1389 std::string::size_type pos, lastPos = 0;
1390 for (const auto *PI : OMD->parameters()) {
1391 // FIXME: selector is missing here!
1392 pos = name.find_first_of(c: ':', pos: lastPos);
1393 if (lastPos != 0)
1394 Out << " ";
1395 Out << name.substr(pos: lastPos, n: pos - lastPos) << ':';
1396 PrintObjCMethodType(Ctx&: OMD->getASTContext(),
1397 Quals: PI->getObjCDeclQualifier(),
1398 T: PI->getType());
1399 Out << *PI;
1400 lastPos = pos + 1;
1401 }
1402
1403 if (OMD->param_begin() == OMD->param_end())
1404 Out << name;
1405
1406 if (OMD->isVariadic())
1407 Out << ", ...";
1408
1409 prettyPrintAttributes(OMD);
1410
1411 if (OMD->getBody() && !Policy.TerseOutput) {
1412 Out << ' ';
1413 OMD->getBody()->printPretty(OS&: Out, Helper: nullptr, Policy, Indentation, NewlineSymbol: "\n",
1414 Context: &Context);
1415 }
1416 else if (Policy.PolishForDeclaration)
1417 Out << ';';
1418}
1419
1420void DeclPrinter::VisitObjCImplementationDecl(ObjCImplementationDecl *OID) {
1421 std::string I = OID->getNameAsString();
1422 ObjCInterfaceDecl *SID = OID->getSuperClass();
1423
1424 bool eolnOut = false;
1425 if (SID)
1426 Out << "@implementation " << I << " : " << *SID;
1427 else
1428 Out << "@implementation " << I;
1429
1430 if (OID->ivar_size() > 0) {
1431 Out << "{\n";
1432 eolnOut = true;
1433 Indentation += Policy.Indentation;
1434 for (const auto *I : OID->ivars()) {
1435 Indent() << I->getASTContext().getUnqualifiedObjCPointerType(I->getType()).
1436 getAsString(Policy) << ' ' << *I << ";\n";
1437 }
1438 Indentation -= Policy.Indentation;
1439 Out << "}\n";
1440 }
1441 else if (SID || (OID->decls_begin() != OID->decls_end())) {
1442 Out << "\n";
1443 eolnOut = true;
1444 }
1445 VisitDeclContext(OID, false);
1446 if (!eolnOut)
1447 Out << "\n";
1448 Out << "@end";
1449}
1450
1451void DeclPrinter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *OID) {
1452 std::string I = OID->getNameAsString();
1453 ObjCInterfaceDecl *SID = OID->getSuperClass();
1454
1455 if (!OID->isThisDeclarationADefinition()) {
1456 Out << "@class " << I;
1457
1458 if (auto TypeParams = OID->getTypeParamListAsWritten()) {
1459 PrintObjCTypeParams(Params: TypeParams);
1460 }
1461
1462 Out << ";";
1463 return;
1464 }
1465 bool eolnOut = false;
1466 if (OID->hasAttrs()) {
1467 prettyPrintAttributes(OID);
1468 Out << "\n";
1469 }
1470
1471 Out << "@interface " << I;
1472
1473 if (auto TypeParams = OID->getTypeParamListAsWritten()) {
1474 PrintObjCTypeParams(Params: TypeParams);
1475 }
1476
1477 if (SID)
1478 Out << " : " << QualType(OID->getSuperClassType(), 0).getAsString(Policy);
1479
1480 // Protocols?
1481 const ObjCList<ObjCProtocolDecl> &Protocols = OID->getReferencedProtocols();
1482 if (!Protocols.empty()) {
1483 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
1484 E = Protocols.end(); I != E; ++I)
1485 Out << (I == Protocols.begin() ? '<' : ',') << **I;
1486 Out << "> ";
1487 }
1488
1489 if (OID->ivar_size() > 0) {
1490 Out << "{\n";
1491 eolnOut = true;
1492 Indentation += Policy.Indentation;
1493 for (const auto *I : OID->ivars()) {
1494 Indent() << I->getASTContext()
1495 .getUnqualifiedObjCPointerType(I->getType())
1496 .getAsString(Policy) << ' ' << *I << ";\n";
1497 }
1498 Indentation -= Policy.Indentation;
1499 Out << "}\n";
1500 }
1501 else if (SID || (OID->decls_begin() != OID->decls_end())) {
1502 Out << "\n";
1503 eolnOut = true;
1504 }
1505
1506 VisitDeclContext(OID, false);
1507 if (!eolnOut)
1508 Out << "\n";
1509 Out << "@end";
1510 // FIXME: implement the rest...
1511}
1512
1513void DeclPrinter::VisitObjCProtocolDecl(ObjCProtocolDecl *PID) {
1514 if (!PID->isThisDeclarationADefinition()) {
1515 Out << "@protocol " << *PID << ";\n";
1516 return;
1517 }
1518 // Protocols?
1519 const ObjCList<ObjCProtocolDecl> &Protocols = PID->getReferencedProtocols();
1520 if (!Protocols.empty()) {
1521 Out << "@protocol " << *PID;
1522 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
1523 E = Protocols.end(); I != E; ++I)
1524 Out << (I == Protocols.begin() ? '<' : ',') << **I;
1525 Out << ">\n";
1526 } else
1527 Out << "@protocol " << *PID << '\n';
1528 VisitDeclContext(PID, false);
1529 Out << "@end";
1530}
1531
1532void DeclPrinter::VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *PID) {
1533 Out << "@implementation ";
1534 if (const auto *CID = PID->getClassInterface())
1535 Out << *CID;
1536 else
1537 Out << "<<error-type>>";
1538 Out << '(' << *PID << ")\n";
1539
1540 VisitDeclContext(PID, false);
1541 Out << "@end";
1542 // FIXME: implement the rest...
1543}
1544
1545void DeclPrinter::VisitObjCCategoryDecl(ObjCCategoryDecl *PID) {
1546 Out << "@interface ";
1547 if (const auto *CID = PID->getClassInterface())
1548 Out << *CID;
1549 else
1550 Out << "<<error-type>>";
1551 if (auto TypeParams = PID->getTypeParamList()) {
1552 PrintObjCTypeParams(Params: TypeParams);
1553 }
1554 Out << "(" << *PID << ")\n";
1555 if (PID->ivar_size() > 0) {
1556 Out << "{\n";
1557 Indentation += Policy.Indentation;
1558 for (const auto *I : PID->ivars())
1559 Indent() << I->getASTContext().getUnqualifiedObjCPointerType(I->getType()).
1560 getAsString(Policy) << ' ' << *I << ";\n";
1561 Indentation -= Policy.Indentation;
1562 Out << "}\n";
1563 }
1564
1565 VisitDeclContext(PID, false);
1566 Out << "@end";
1567
1568 // FIXME: implement the rest...
1569}
1570
1571void DeclPrinter::VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *AID) {
1572 Out << "@compatibility_alias " << *AID
1573 << ' ' << *AID->getClassInterface() << ";\n";
1574}
1575
1576/// PrintObjCPropertyDecl - print a property declaration.
1577///
1578/// Print attributes in the following order:
1579/// - class
1580/// - nonatomic | atomic
1581/// - assign | retain | strong | copy | weak | unsafe_unretained
1582/// - readwrite | readonly
1583/// - getter & setter
1584/// - nullability
1585void DeclPrinter::VisitObjCPropertyDecl(ObjCPropertyDecl *PDecl) {
1586 if (PDecl->getPropertyImplementation() == ObjCPropertyDecl::Required)
1587 Out << "@required\n";
1588 else if (PDecl->getPropertyImplementation() == ObjCPropertyDecl::Optional)
1589 Out << "@optional\n";
1590
1591 QualType T = PDecl->getType();
1592
1593 Out << "@property";
1594 if (PDecl->getPropertyAttributes() != ObjCPropertyAttribute::kind_noattr) {
1595 bool first = true;
1596 Out << "(";
1597 if (PDecl->getPropertyAttributes() & ObjCPropertyAttribute::kind_class) {
1598 Out << (first ? "" : ", ") << "class";
1599 first = false;
1600 }
1601
1602 if (PDecl->getPropertyAttributes() & ObjCPropertyAttribute::kind_direct) {
1603 Out << (first ? "" : ", ") << "direct";
1604 first = false;
1605 }
1606
1607 if (PDecl->getPropertyAttributes() &
1608 ObjCPropertyAttribute::kind_nonatomic) {
1609 Out << (first ? "" : ", ") << "nonatomic";
1610 first = false;
1611 }
1612 if (PDecl->getPropertyAttributes() & ObjCPropertyAttribute::kind_atomic) {
1613 Out << (first ? "" : ", ") << "atomic";
1614 first = false;
1615 }
1616
1617 if (PDecl->getPropertyAttributes() & ObjCPropertyAttribute::kind_assign) {
1618 Out << (first ? "" : ", ") << "assign";
1619 first = false;
1620 }
1621 if (PDecl->getPropertyAttributes() & ObjCPropertyAttribute::kind_retain) {
1622 Out << (first ? "" : ", ") << "retain";
1623 first = false;
1624 }
1625
1626 if (PDecl->getPropertyAttributes() & ObjCPropertyAttribute::kind_strong) {
1627 Out << (first ? "" : ", ") << "strong";
1628 first = false;
1629 }
1630 if (PDecl->getPropertyAttributes() & ObjCPropertyAttribute::kind_copy) {
1631 Out << (first ? "" : ", ") << "copy";
1632 first = false;
1633 }
1634 if (PDecl->getPropertyAttributes() & ObjCPropertyAttribute::kind_weak) {
1635 Out << (first ? "" : ", ") << "weak";
1636 first = false;
1637 }
1638 if (PDecl->getPropertyAttributes() &
1639 ObjCPropertyAttribute::kind_unsafe_unretained) {
1640 Out << (first ? "" : ", ") << "unsafe_unretained";
1641 first = false;
1642 }
1643
1644 if (PDecl->getPropertyAttributes() &
1645 ObjCPropertyAttribute::kind_readwrite) {
1646 Out << (first ? "" : ", ") << "readwrite";
1647 first = false;
1648 }
1649 if (PDecl->getPropertyAttributes() & ObjCPropertyAttribute::kind_readonly) {
1650 Out << (first ? "" : ", ") << "readonly";
1651 first = false;
1652 }
1653
1654 if (PDecl->getPropertyAttributes() & ObjCPropertyAttribute::kind_getter) {
1655 Out << (first ? "" : ", ") << "getter = ";
1656 PDecl->getGetterName().print(OS&: Out);
1657 first = false;
1658 }
1659 if (PDecl->getPropertyAttributes() & ObjCPropertyAttribute::kind_setter) {
1660 Out << (first ? "" : ", ") << "setter = ";
1661 PDecl->getSetterName().print(OS&: Out);
1662 first = false;
1663 }
1664
1665 if (PDecl->getPropertyAttributes() &
1666 ObjCPropertyAttribute::kind_nullability) {
1667 if (auto nullability = AttributedType::stripOuterNullability(T)) {
1668 if (*nullability == NullabilityKind::Unspecified &&
1669 (PDecl->getPropertyAttributes() &
1670 ObjCPropertyAttribute::kind_null_resettable)) {
1671 Out << (first ? "" : ", ") << "null_resettable";
1672 } else {
1673 Out << (first ? "" : ", ")
1674 << getNullabilitySpelling(kind: *nullability, isContextSensitive: true);
1675 }
1676 first = false;
1677 }
1678 }
1679
1680 (void) first; // Silence dead store warning due to idiomatic code.
1681 Out << ")";
1682 }
1683 std::string TypeStr = PDecl->getASTContext().getUnqualifiedObjCPointerType(T).
1684 getAsString(Policy);
1685 Out << ' ' << TypeStr;
1686 if (!StringRef(TypeStr).ends_with(Suffix: "*"))
1687 Out << ' ';
1688 Out << *PDecl;
1689 if (Policy.PolishForDeclaration)
1690 Out << ';';
1691}
1692
1693void DeclPrinter::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *PID) {
1694 if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize)
1695 Out << "@synthesize ";
1696 else
1697 Out << "@dynamic ";
1698 Out << *PID->getPropertyDecl();
1699 if (PID->getPropertyIvarDecl())
1700 Out << '=' << *PID->getPropertyIvarDecl();
1701}
1702
1703void DeclPrinter::VisitUsingDecl(UsingDecl *D) {
1704 if (!D->isAccessDeclaration())
1705 Out << "using ";
1706 if (D->hasTypename())
1707 Out << "typename ";
1708 D->getQualifier()->print(OS&: Out, Policy);
1709
1710 // Use the correct record name when the using declaration is used for
1711 // inheriting constructors.
1712 for (const auto *Shadow : D->shadows()) {
1713 if (const auto *ConstructorShadow =
1714 dyn_cast<ConstructorUsingShadowDecl>(Shadow)) {
1715 assert(Shadow->getDeclContext() == ConstructorShadow->getDeclContext());
1716 Out << *ConstructorShadow->getNominatedBaseClass();
1717 return;
1718 }
1719 }
1720 Out << *D;
1721}
1722
1723void DeclPrinter::VisitUsingEnumDecl(UsingEnumDecl *D) {
1724 Out << "using enum " << D->getEnumDecl();
1725}
1726
1727void
1728DeclPrinter::VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D) {
1729 Out << "using typename ";
1730 D->getQualifier()->print(OS&: Out, Policy);
1731 Out << D->getDeclName();
1732}
1733
1734void DeclPrinter::VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D) {
1735 if (!D->isAccessDeclaration())
1736 Out << "using ";
1737 D->getQualifier()->print(OS&: Out, Policy);
1738 Out << D->getDeclName();
1739}
1740
1741void DeclPrinter::VisitUsingShadowDecl(UsingShadowDecl *D) {
1742 // ignore
1743}
1744
1745void DeclPrinter::VisitOMPThreadPrivateDecl(OMPThreadPrivateDecl *D) {
1746 Out << "#pragma omp threadprivate";
1747 if (!D->varlist_empty()) {
1748 for (OMPThreadPrivateDecl::varlist_iterator I = D->varlist_begin(),
1749 E = D->varlist_end();
1750 I != E; ++I) {
1751 Out << (I == D->varlist_begin() ? '(' : ',');
1752 NamedDecl *ND = cast<DeclRefExpr>(Val: *I)->getDecl();
1753 ND->printQualifiedName(OS&: Out);
1754 }
1755 Out << ")";
1756 }
1757}
1758
1759void DeclPrinter::VisitHLSLBufferDecl(HLSLBufferDecl *D) {
1760 if (D->isCBuffer())
1761 Out << "cbuffer ";
1762 else
1763 Out << "tbuffer ";
1764
1765 Out << *D;
1766
1767 prettyPrintAttributes(D);
1768
1769 Out << " {\n";
1770 VisitDeclContext(D);
1771 Indent() << "}";
1772}
1773
1774void DeclPrinter::VisitOMPAllocateDecl(OMPAllocateDecl *D) {
1775 Out << "#pragma omp allocate";
1776 if (!D->varlist_empty()) {
1777 for (OMPAllocateDecl::varlist_iterator I = D->varlist_begin(),
1778 E = D->varlist_end();
1779 I != E; ++I) {
1780 Out << (I == D->varlist_begin() ? '(' : ',');
1781 NamedDecl *ND = cast<DeclRefExpr>(Val: *I)->getDecl();
1782 ND->printQualifiedName(OS&: Out);
1783 }
1784 Out << ")";
1785 }
1786 if (!D->clauselist_empty()) {
1787 OMPClausePrinter Printer(Out, Policy);
1788 for (OMPClause *C : D->clauselists()) {
1789 Out << " ";
1790 Printer.Visit(C);
1791 }
1792 }
1793}
1794
1795void DeclPrinter::VisitOMPRequiresDecl(OMPRequiresDecl *D) {
1796 Out << "#pragma omp requires ";
1797 if (!D->clauselist_empty()) {
1798 OMPClausePrinter Printer(Out, Policy);
1799 for (auto I = D->clauselist_begin(), E = D->clauselist_end(); I != E; ++I)
1800 Printer.Visit(*I);
1801 }
1802}
1803
1804void DeclPrinter::VisitOMPDeclareReductionDecl(OMPDeclareReductionDecl *D) {
1805 if (!D->isInvalidDecl()) {
1806 Out << "#pragma omp declare reduction (";
1807 if (D->getDeclName().getNameKind() == DeclarationName::CXXOperatorName) {
1808 const char *OpName =
1809 getOperatorSpelling(D->getDeclName().getCXXOverloadedOperator());
1810 assert(OpName && "not an overloaded operator");
1811 Out << OpName;
1812 } else {
1813 assert(D->getDeclName().isIdentifier());
1814 D->printName(Out, Policy);
1815 }
1816 Out << " : ";
1817 D->getType().print(Out, Policy);
1818 Out << " : ";
1819 D->getCombiner()->printPretty(Out, nullptr, Policy, 0, "\n", &Context);
1820 Out << ")";
1821 if (auto *Init = D->getInitializer()) {
1822 Out << " initializer(";
1823 switch (D->getInitializerKind()) {
1824 case OMPDeclareReductionInitKind::Direct:
1825 Out << "omp_priv(";
1826 break;
1827 case OMPDeclareReductionInitKind::Copy:
1828 Out << "omp_priv = ";
1829 break;
1830 case OMPDeclareReductionInitKind::Call:
1831 break;
1832 }
1833 Init->printPretty(Out, nullptr, Policy, 0, "\n", &Context);
1834 if (D->getInitializerKind() == OMPDeclareReductionInitKind::Direct)
1835 Out << ")";
1836 Out << ")";
1837 }
1838 }
1839}
1840
1841void DeclPrinter::VisitOMPDeclareMapperDecl(OMPDeclareMapperDecl *D) {
1842 if (!D->isInvalidDecl()) {
1843 Out << "#pragma omp declare mapper (";
1844 D->printName(Out, Policy);
1845 Out << " : ";
1846 D->getType().print(Out, Policy);
1847 Out << " ";
1848 Out << D->getVarName();
1849 Out << ")";
1850 if (!D->clauselist_empty()) {
1851 OMPClausePrinter Printer(Out, Policy);
1852 for (auto *C : D->clauselists()) {
1853 Out << " ";
1854 Printer.Visit(C);
1855 }
1856 }
1857 }
1858}
1859
1860void DeclPrinter::VisitOMPCapturedExprDecl(OMPCapturedExprDecl *D) {
1861 D->getInit()->printPretty(Out, nullptr, Policy, Indentation, "\n", &Context);
1862}
1863
1864void DeclPrinter::VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *TTP) {
1865 if (const TypeConstraint *TC = TTP->getTypeConstraint())
1866 TC->print(OS&: Out, Policy);
1867 else if (TTP->wasDeclaredWithTypename())
1868 Out << "typename";
1869 else
1870 Out << "class";
1871
1872 if (TTP->isParameterPack())
1873 Out << " ...";
1874 else if (TTP->getDeclName())
1875 Out << ' ';
1876
1877 if (TTP->getDeclName()) {
1878 if (Policy.CleanUglifiedParameters && TTP->getIdentifier())
1879 Out << TTP->getIdentifier()->deuglifiedName();
1880 else
1881 Out << TTP->getDeclName();
1882 }
1883
1884 if (TTP->hasDefaultArgument()) {
1885 Out << " = ";
1886 Out << TTP->getDefaultArgument().getAsString(Policy);
1887 }
1888}
1889
1890void DeclPrinter::VisitNonTypeTemplateParmDecl(
1891 const NonTypeTemplateParmDecl *NTTP) {
1892 StringRef Name;
1893 if (IdentifierInfo *II = NTTP->getIdentifier())
1894 Name =
1895 Policy.CleanUglifiedParameters ? II->deuglifiedName() : II->getName();
1896 printDeclType(T: NTTP->getType(), DeclName: Name, Pack: NTTP->isParameterPack());
1897
1898 if (NTTP->hasDefaultArgument()) {
1899 Out << " = ";
1900 NTTP->getDefaultArgument()->printPretty(Out, nullptr, Policy, Indentation,
1901 "\n", &Context);
1902 }
1903}
1904

source code of clang/lib/AST/DeclPrinter.cpp