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

Provided by KDAB

Privacy Policy
Update your C++ knowledge – Modern C++11/14/17 Training
Find out more

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