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