1 //===--- DeclPrinter.cpp - Printing implementation for Decl ASTs ----------===//
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
7 //===----------------------------------------------------------------------===//
9 // This file implements the Decl::print method, which pretty prints the
10 // AST back out to C/Objective-C/C++/Objective-C++ code.
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 "llvm/Support/raw_ostream.h"
25 using namespace clang
;
28 class DeclPrinter
: public DeclVisitor
<DeclPrinter
> {
30 PrintingPolicy Policy
;
31 const ASTContext
&Context
;
33 bool PrintInstantiation
;
35 raw_ostream
& Indent() { return Indent(Indentation
); }
36 raw_ostream
& Indent(unsigned Indentation
);
37 void ProcessDeclGroup(SmallVectorImpl
<Decl
*>& Decls
);
39 void Print(AccessSpecifier AS
);
40 void PrintConstructorInitializers(CXXConstructorDecl
*CDecl
,
43 /// Print an Objective-C method type in parentheses.
45 /// \param Quals The Objective-C declaration qualifiers.
46 /// \param T The type to print.
47 void PrintObjCMethodType(ASTContext
&Ctx
, Decl::ObjCDeclQualifier Quals
,
50 void PrintObjCTypeParams(ObjCTypeParamList
*Params
);
53 DeclPrinter(raw_ostream
&Out
, const PrintingPolicy
&Policy
,
54 const ASTContext
&Context
, unsigned Indentation
= 0,
55 bool PrintInstantiation
= false)
56 : Out(Out
), Policy(Policy
), Context(Context
), Indentation(Indentation
),
57 PrintInstantiation(PrintInstantiation
) {}
59 void VisitDeclContext(DeclContext
*DC
, bool Indent
= true);
61 void VisitTranslationUnitDecl(TranslationUnitDecl
*D
);
62 void VisitTypedefDecl(TypedefDecl
*D
);
63 void VisitTypeAliasDecl(TypeAliasDecl
*D
);
64 void VisitEnumDecl(EnumDecl
*D
);
65 void VisitRecordDecl(RecordDecl
*D
);
66 void VisitEnumConstantDecl(EnumConstantDecl
*D
);
67 void VisitEmptyDecl(EmptyDecl
*D
);
68 void VisitFunctionDecl(FunctionDecl
*D
);
69 void VisitFriendDecl(FriendDecl
*D
);
70 void VisitFieldDecl(FieldDecl
*D
);
71 void VisitVarDecl(VarDecl
*D
);
72 void VisitLabelDecl(LabelDecl
*D
);
73 void VisitParmVarDecl(ParmVarDecl
*D
);
74 void VisitFileScopeAsmDecl(FileScopeAsmDecl
*D
);
75 void VisitTopLevelStmtDecl(TopLevelStmtDecl
*D
);
76 void VisitImportDecl(ImportDecl
*D
);
77 void VisitStaticAssertDecl(StaticAssertDecl
*D
);
78 void VisitNamespaceDecl(NamespaceDecl
*D
);
79 void VisitUsingDirectiveDecl(UsingDirectiveDecl
*D
);
80 void VisitNamespaceAliasDecl(NamespaceAliasDecl
*D
);
81 void VisitCXXRecordDecl(CXXRecordDecl
*D
);
82 void VisitLinkageSpecDecl(LinkageSpecDecl
*D
);
83 void VisitTemplateDecl(const TemplateDecl
*D
);
84 void VisitFunctionTemplateDecl(FunctionTemplateDecl
*D
);
85 void VisitClassTemplateDecl(ClassTemplateDecl
*D
);
86 void VisitClassTemplateSpecializationDecl(
87 ClassTemplateSpecializationDecl
*D
);
88 void VisitClassTemplatePartialSpecializationDecl(
89 ClassTemplatePartialSpecializationDecl
*D
);
90 void VisitObjCMethodDecl(ObjCMethodDecl
*D
);
91 void VisitObjCImplementationDecl(ObjCImplementationDecl
*D
);
92 void VisitObjCInterfaceDecl(ObjCInterfaceDecl
*D
);
93 void VisitObjCProtocolDecl(ObjCProtocolDecl
*D
);
94 void VisitObjCCategoryImplDecl(ObjCCategoryImplDecl
*D
);
95 void VisitObjCCategoryDecl(ObjCCategoryDecl
*D
);
96 void VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl
*D
);
97 void VisitObjCPropertyDecl(ObjCPropertyDecl
*D
);
98 void VisitObjCPropertyImplDecl(ObjCPropertyImplDecl
*D
);
99 void VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl
*D
);
100 void VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl
*D
);
101 void VisitUsingDecl(UsingDecl
*D
);
102 void VisitUsingEnumDecl(UsingEnumDecl
*D
);
103 void VisitUsingShadowDecl(UsingShadowDecl
*D
);
104 void VisitOMPThreadPrivateDecl(OMPThreadPrivateDecl
*D
);
105 void VisitOMPAllocateDecl(OMPAllocateDecl
*D
);
106 void VisitOMPRequiresDecl(OMPRequiresDecl
*D
);
107 void VisitOMPDeclareReductionDecl(OMPDeclareReductionDecl
*D
);
108 void VisitOMPDeclareMapperDecl(OMPDeclareMapperDecl
*D
);
109 void VisitOMPCapturedExprDecl(OMPCapturedExprDecl
*D
);
110 void VisitTemplateTypeParmDecl(const TemplateTypeParmDecl
*TTP
);
111 void VisitNonTypeTemplateParmDecl(const NonTypeTemplateParmDecl
*NTTP
);
112 void VisitHLSLBufferDecl(HLSLBufferDecl
*D
);
114 void printTemplateParameters(const TemplateParameterList
*Params
,
115 bool OmitTemplateKW
= false);
116 void printTemplateArguments(llvm::ArrayRef
<TemplateArgument
> Args
,
117 const TemplateParameterList
*Params
);
118 void printTemplateArguments(llvm::ArrayRef
<TemplateArgumentLoc
> Args
,
119 const TemplateParameterList
*Params
);
120 void prettyPrintAttributes(Decl
*D
);
121 void prettyPrintPragmas(Decl
*D
);
122 void printDeclType(QualType T
, StringRef DeclName
, bool Pack
= false);
126 void Decl::print(raw_ostream
&Out
, unsigned Indentation
,
127 bool PrintInstantiation
) const {
128 print(Out
, getASTContext().getPrintingPolicy(), Indentation
, PrintInstantiation
);
131 void Decl::print(raw_ostream
&Out
, const PrintingPolicy
&Policy
,
132 unsigned Indentation
, bool PrintInstantiation
) const {
133 DeclPrinter
Printer(Out
, Policy
, getASTContext(), Indentation
,
135 Printer
.Visit(const_cast<Decl
*>(this));
138 void TemplateParameterList::print(raw_ostream
&Out
, const ASTContext
&Context
,
139 bool OmitTemplateKW
) const {
140 print(Out
, Context
, Context
.getPrintingPolicy(), OmitTemplateKW
);
143 void TemplateParameterList::print(raw_ostream
&Out
, const ASTContext
&Context
,
144 const PrintingPolicy
&Policy
,
145 bool OmitTemplateKW
) const {
146 DeclPrinter
Printer(Out
, Policy
, Context
);
147 Printer
.printTemplateParameters(this, OmitTemplateKW
);
150 static QualType
GetBaseType(QualType T
) {
151 // FIXME: This should be on the Type class!
152 QualType BaseType
= T
;
153 while (!BaseType
->isSpecifierType()) {
154 if (const PointerType
*PTy
= BaseType
->getAs
<PointerType
>())
155 BaseType
= PTy
->getPointeeType();
156 else if (const ObjCObjectPointerType
*OPT
=
157 BaseType
->getAs
<ObjCObjectPointerType
>())
158 BaseType
= OPT
->getPointeeType();
159 else if (const BlockPointerType
*BPy
= BaseType
->getAs
<BlockPointerType
>())
160 BaseType
= BPy
->getPointeeType();
161 else if (const ArrayType
*ATy
= dyn_cast
<ArrayType
>(BaseType
))
162 BaseType
= ATy
->getElementType();
163 else if (const FunctionType
*FTy
= BaseType
->getAs
<FunctionType
>())
164 BaseType
= FTy
->getReturnType();
165 else if (const VectorType
*VTy
= BaseType
->getAs
<VectorType
>())
166 BaseType
= VTy
->getElementType();
167 else if (const ReferenceType
*RTy
= BaseType
->getAs
<ReferenceType
>())
168 BaseType
= RTy
->getPointeeType();
169 else if (const AutoType
*ATy
= BaseType
->getAs
<AutoType
>())
170 BaseType
= ATy
->getDeducedType();
171 else if (const ParenType
*PTy
= BaseType
->getAs
<ParenType
>())
172 BaseType
= PTy
->desugar();
174 // This must be a syntax error.
180 static QualType
getDeclType(Decl
* D
) {
181 if (TypedefNameDecl
* TDD
= dyn_cast
<TypedefNameDecl
>(D
))
182 return TDD
->getUnderlyingType();
183 if (ValueDecl
* VD
= dyn_cast
<ValueDecl
>(D
))
184 return VD
->getType();
188 void Decl::printGroup(Decl
** Begin
, unsigned NumDecls
,
189 raw_ostream
&Out
, const PrintingPolicy
&Policy
,
190 unsigned Indentation
) {
192 (*Begin
)->print(Out
, Policy
, Indentation
);
196 Decl
** End
= Begin
+ NumDecls
;
197 TagDecl
* TD
= dyn_cast
<TagDecl
>(*Begin
);
201 PrintingPolicy
SubPolicy(Policy
);
204 for ( ; Begin
!= End
; ++Begin
) {
207 SubPolicy
.IncludeTagDefinition
= true;
208 SubPolicy
.SuppressSpecifiers
= false;
211 if (!isFirst
) Out
<< ", ";
212 SubPolicy
.IncludeTagDefinition
= false;
213 SubPolicy
.SuppressSpecifiers
= true;
216 (*Begin
)->print(Out
, SubPolicy
, Indentation
);
220 LLVM_DUMP_METHOD
void DeclContext::dumpDeclContext() const {
221 // Get the translation unit
222 const DeclContext
*DC
= this;
223 while (!DC
->isTranslationUnit())
224 DC
= DC
->getParent();
226 ASTContext
&Ctx
= cast
<TranslationUnitDecl
>(DC
)->getASTContext();
227 DeclPrinter
Printer(llvm::errs(), Ctx
.getPrintingPolicy(), Ctx
, 0);
228 Printer
.VisitDeclContext(const_cast<DeclContext
*>(this), /*Indent=*/false);
231 raw_ostream
& DeclPrinter::Indent(unsigned Indentation
) {
232 for (unsigned i
= 0; i
!= Indentation
; ++i
)
237 void DeclPrinter::prettyPrintAttributes(Decl
*D
) {
238 if (Policy
.PolishForDeclaration
)
242 AttrVec
&Attrs
= D
->getAttrs();
243 for (auto *A
: Attrs
) {
244 if (A
->isInherited() || A
->isImplicit())
246 switch (A
->getKind()) {
248 #define PRAGMA_SPELLING_ATTR(X) case attr::X:
249 #include "clang/Basic/AttrList.inc"
252 A
->printPretty(Out
, Policy
);
259 void DeclPrinter::prettyPrintPragmas(Decl
*D
) {
260 if (Policy
.PolishForDeclaration
)
264 AttrVec
&Attrs
= D
->getAttrs();
265 for (auto *A
: Attrs
) {
266 switch (A
->getKind()) {
268 #define PRAGMA_SPELLING_ATTR(X) case attr::X:
269 #include "clang/Basic/AttrList.inc"
270 A
->printPretty(Out
, Policy
);
280 void DeclPrinter::printDeclType(QualType T
, StringRef DeclName
, bool Pack
) {
281 // Normally, a PackExpansionType is written as T[3]... (for instance, as a
282 // template argument), but if it is the type of a declaration, the ellipsis
283 // is placed before the name being declared.
284 if (auto *PET
= T
->getAs
<PackExpansionType
>()) {
286 T
= PET
->getPattern();
288 T
.print(Out
, Policy
, (Pack
? "..." : "") + DeclName
, Indentation
);
291 void DeclPrinter::ProcessDeclGroup(SmallVectorImpl
<Decl
*>& Decls
) {
293 Decl::printGroup(Decls
.data(), Decls
.size(), Out
, Policy
, Indentation
);
299 void DeclPrinter::Print(AccessSpecifier AS
) {
300 const auto AccessSpelling
= getAccessSpelling(AS
);
301 if (AccessSpelling
.empty())
302 llvm_unreachable("No access specifier!");
303 Out
<< AccessSpelling
;
306 void DeclPrinter::PrintConstructorInitializers(CXXConstructorDecl
*CDecl
,
307 std::string
&Proto
) {
308 bool HasInitializerList
= false;
309 for (const auto *BMInitializer
: CDecl
->inits()) {
310 if (BMInitializer
->isInClassMemberInitializer())
313 if (!HasInitializerList
) {
317 HasInitializerList
= true;
321 if (BMInitializer
->isAnyMemberInitializer()) {
322 FieldDecl
*FD
= BMInitializer
->getAnyMember();
325 Out
<< QualType(BMInitializer
->getBaseClass(), 0).getAsString(Policy
);
329 if (!BMInitializer
->getInit()) {
332 Expr
*Init
= BMInitializer
->getInit();
333 if (ExprWithCleanups
*Tmp
= dyn_cast
<ExprWithCleanups
>(Init
))
334 Init
= Tmp
->getSubExpr();
336 Init
= Init
->IgnoreParens();
338 Expr
*SimpleInit
= nullptr;
339 Expr
**Args
= nullptr;
340 unsigned NumArgs
= 0;
341 if (ParenListExpr
*ParenList
= dyn_cast
<ParenListExpr
>(Init
)) {
342 Args
= ParenList
->getExprs();
343 NumArgs
= ParenList
->getNumExprs();
344 } else if (CXXConstructExpr
*Construct
=
345 dyn_cast
<CXXConstructExpr
>(Init
)) {
346 Args
= Construct
->getArgs();
347 NumArgs
= Construct
->getNumArgs();
352 SimpleInit
->printPretty(Out
, nullptr, Policy
, Indentation
, "\n",
355 for (unsigned I
= 0; I
!= NumArgs
; ++I
) {
356 assert(Args
[I
] != nullptr && "Expected non-null Expr");
357 if (isa
<CXXDefaultArgExpr
>(Args
[I
]))
362 Args
[I
]->printPretty(Out
, nullptr, Policy
, Indentation
, "\n",
368 if (BMInitializer
->isPackExpansion())
373 //----------------------------------------------------------------------------
374 // Common C declarations
375 //----------------------------------------------------------------------------
377 void DeclPrinter::VisitDeclContext(DeclContext
*DC
, bool Indent
) {
378 if (Policy
.TerseOutput
)
382 Indentation
+= Policy
.Indentation
;
384 SmallVector
<Decl
*, 2> Decls
;
385 for (DeclContext::decl_iterator D
= DC
->decls_begin(), DEnd
= DC
->decls_end();
388 // Don't print ObjCIvarDecls, as they are printed when visiting the
389 // containing ObjCInterfaceDecl.
390 if (isa
<ObjCIvarDecl
>(*D
))
393 // Skip over implicit declarations in pretty-printing mode.
397 // Don't print implicit specializations, as they are printed when visiting
398 // corresponding templates.
399 if (auto FD
= dyn_cast
<FunctionDecl
>(*D
))
400 if (FD
->getTemplateSpecializationKind() == TSK_ImplicitInstantiation
&&
401 !isa
<ClassTemplateSpecializationDecl
>(DC
))
404 // The next bits of code handle stuff like "struct {int x;} a,b"; we're
405 // forced to merge the declarations because there's no other way to
406 // refer to the struct in question. When that struct is named instead, we
407 // also need to merge to avoid splitting off a stand-alone struct
408 // declaration that produces the warning ext_no_declarators in some
411 // This limited merging is safe without a bunch of other checks because it
412 // only merges declarations directly referring to the tag, not typedefs.
414 // Check whether the current declaration should be grouped with a previous
415 // non-free-standing tag declaration.
416 QualType CurDeclType
= getDeclType(*D
);
417 if (!Decls
.empty() && !CurDeclType
.isNull()) {
418 QualType BaseType
= GetBaseType(CurDeclType
);
419 if (!BaseType
.isNull() && isa
<ElaboratedType
>(BaseType
) &&
420 cast
<ElaboratedType
>(BaseType
)->getOwnedTagDecl() == Decls
[0]) {
426 // If we have a merged group waiting to be handled, handle it now.
428 ProcessDeclGroup(Decls
);
430 // If the current declaration is not a free standing declaration, save it
431 // so we can merge it with the subsequent declaration(s) using it.
432 if (isa
<TagDecl
>(*D
) && !cast
<TagDecl
>(*D
)->isFreeStanding()) {
437 if (isa
<AccessSpecDecl
>(*D
)) {
438 Indentation
-= Policy
.Indentation
;
440 Print(D
->getAccess());
442 Indentation
+= Policy
.Indentation
;
449 // FIXME: Need to be able to tell the DeclPrinter when
450 const char *Terminator
= nullptr;
451 if (isa
<OMPThreadPrivateDecl
>(*D
) || isa
<OMPDeclareReductionDecl
>(*D
) ||
452 isa
<OMPDeclareMapperDecl
>(*D
) || isa
<OMPRequiresDecl
>(*D
) ||
453 isa
<OMPAllocateDecl
>(*D
))
454 Terminator
= nullptr;
455 else if (isa
<ObjCMethodDecl
>(*D
) && cast
<ObjCMethodDecl
>(*D
)->hasBody())
456 Terminator
= nullptr;
457 else if (auto FD
= dyn_cast
<FunctionDecl
>(*D
)) {
458 if (FD
->isThisDeclarationADefinition())
459 Terminator
= nullptr;
462 } else if (auto TD
= dyn_cast
<FunctionTemplateDecl
>(*D
)) {
463 if (TD
->getTemplatedDecl()->isThisDeclarationADefinition())
464 Terminator
= nullptr;
467 } else if (isa
<NamespaceDecl
, LinkageSpecDecl
, ObjCImplementationDecl
,
468 ObjCInterfaceDecl
, ObjCProtocolDecl
, ObjCCategoryImplDecl
,
469 ObjCCategoryDecl
, HLSLBufferDecl
>(*D
))
470 Terminator
= nullptr;
471 else if (isa
<EnumConstantDecl
>(*D
)) {
472 DeclContext::decl_iterator Next
= D
;
481 if (!Policy
.TerseOutput
&&
482 ((isa
<FunctionDecl
>(*D
) &&
483 cast
<FunctionDecl
>(*D
)->doesThisDeclarationHaveABody()) ||
484 (isa
<FunctionTemplateDecl
>(*D
) &&
485 cast
<FunctionTemplateDecl
>(*D
)->getTemplatedDecl()->doesThisDeclarationHaveABody())))
486 ; // StmtPrinter already added '\n' after CompoundStmt.
490 // Declare target attribute is special one, natural spelling for the pragma
491 // assumes "ending" construct so print it here.
492 if (D
->hasAttr
<OMPDeclareTargetDeclAttr
>())
493 Out
<< "#pragma omp end declare target\n";
497 ProcessDeclGroup(Decls
);
500 Indentation
-= Policy
.Indentation
;
503 void DeclPrinter::VisitTranslationUnitDecl(TranslationUnitDecl
*D
) {
504 VisitDeclContext(D
, false);
507 void DeclPrinter::VisitTypedefDecl(TypedefDecl
*D
) {
508 if (!Policy
.SuppressSpecifiers
) {
511 if (D
->isModulePrivate())
512 Out
<< "__module_private__ ";
514 QualType Ty
= D
->getTypeSourceInfo()->getType();
515 Ty
.print(Out
, Policy
, D
->getName(), Indentation
);
516 prettyPrintAttributes(D
);
519 void DeclPrinter::VisitTypeAliasDecl(TypeAliasDecl
*D
) {
520 Out
<< "using " << *D
;
521 prettyPrintAttributes(D
);
522 Out
<< " = " << D
->getTypeSourceInfo()->getType().getAsString(Policy
);
525 void DeclPrinter::VisitEnumDecl(EnumDecl
*D
) {
526 if (!Policy
.SuppressSpecifiers
&& D
->isModulePrivate())
527 Out
<< "__module_private__ ";
530 if (D
->isScopedUsingClassTag())
536 prettyPrintAttributes(D
);
538 if (D
->getDeclName())
539 Out
<< ' ' << D
->getDeclName();
542 Out
<< " : " << D
->getIntegerType().stream(Policy
);
544 if (D
->isCompleteDefinition()) {
551 void DeclPrinter::VisitRecordDecl(RecordDecl
*D
) {
552 if (!Policy
.SuppressSpecifiers
&& D
->isModulePrivate())
553 Out
<< "__module_private__ ";
554 Out
<< D
->getKindName();
556 prettyPrintAttributes(D
);
558 if (D
->getIdentifier())
561 if (D
->isCompleteDefinition()) {
568 void DeclPrinter::VisitEnumConstantDecl(EnumConstantDecl
*D
) {
570 prettyPrintAttributes(D
);
571 if (Expr
*Init
= D
->getInitExpr()) {
573 Init
->printPretty(Out
, nullptr, Policy
, Indentation
, "\n", &Context
);
577 static void printExplicitSpecifier(ExplicitSpecifier ES
, llvm::raw_ostream
&Out
,
578 PrintingPolicy
&Policy
, unsigned Indentation
,
579 const ASTContext
&Context
) {
580 std::string Proto
= "explicit";
581 llvm::raw_string_ostream
EOut(Proto
);
584 ES
.getExpr()->printPretty(EOut
, nullptr, Policy
, Indentation
, "\n",
593 void DeclPrinter::VisitFunctionDecl(FunctionDecl
*D
) {
594 if (!D
->getDescribedFunctionTemplate() &&
595 !D
->isFunctionTemplateSpecialization())
596 prettyPrintPragmas(D
);
598 if (D
->isFunctionTemplateSpecialization())
599 Out
<< "template<> ";
600 else if (!D
->getDescribedFunctionTemplate()) {
601 for (unsigned I
= 0, NumTemplateParams
= D
->getNumTemplateParameterLists();
602 I
< NumTemplateParams
; ++I
)
603 printTemplateParameters(D
->getTemplateParameterList(I
));
606 CXXConstructorDecl
*CDecl
= dyn_cast
<CXXConstructorDecl
>(D
);
607 CXXConversionDecl
*ConversionDecl
= dyn_cast
<CXXConversionDecl
>(D
);
608 CXXDeductionGuideDecl
*GuideDecl
= dyn_cast
<CXXDeductionGuideDecl
>(D
);
609 if (!Policy
.SuppressSpecifiers
) {
610 switch (D
->getStorageClass()) {
612 case SC_Extern
: Out
<< "extern "; break;
613 case SC_Static
: Out
<< "static "; break;
614 case SC_PrivateExtern
: Out
<< "__private_extern__ "; break;
615 case SC_Auto
: case SC_Register
:
616 llvm_unreachable("invalid for functions");
619 if (D
->isInlineSpecified()) Out
<< "inline ";
620 if (D
->isVirtualAsWritten()) Out
<< "virtual ";
621 if (D
->isModulePrivate()) Out
<< "__module_private__ ";
622 if (D
->isConstexprSpecified() && !D
->isExplicitlyDefaulted())
624 if (D
->isConsteval()) Out
<< "consteval ";
625 ExplicitSpecifier ExplicitSpec
= ExplicitSpecifier::getFromDecl(D
);
626 if (ExplicitSpec
.isSpecified())
627 printExplicitSpecifier(ExplicitSpec
, Out
, Policy
, Indentation
, Context
);
630 PrintingPolicy
SubPolicy(Policy
);
631 SubPolicy
.SuppressSpecifiers
= false;
634 if (Policy
.FullyQualifiedName
) {
635 Proto
+= D
->getQualifiedNameAsString();
637 llvm::raw_string_ostream
OS(Proto
);
638 if (!Policy
.SuppressScope
) {
639 if (const NestedNameSpecifier
*NS
= D
->getQualifier()) {
640 NS
->print(OS
, Policy
);
643 D
->getNameInfo().printName(OS
, Policy
);
647 Proto
= GuideDecl
->getDeducedTemplate()->getDeclName().getAsString();
648 if (D
->isFunctionTemplateSpecialization()) {
649 llvm::raw_string_ostream
POut(Proto
);
650 DeclPrinter
TArgPrinter(POut
, SubPolicy
, Context
, Indentation
);
651 const auto *TArgAsWritten
= D
->getTemplateSpecializationArgsAsWritten();
652 if (TArgAsWritten
&& !Policy
.PrintCanonicalTypes
)
653 TArgPrinter
.printTemplateArguments(TArgAsWritten
->arguments(), nullptr);
654 else if (const TemplateArgumentList
*TArgs
=
655 D
->getTemplateSpecializationArgs())
656 TArgPrinter
.printTemplateArguments(TArgs
->asArray(), nullptr);
659 QualType Ty
= D
->getType();
660 while (const ParenType
*PT
= dyn_cast
<ParenType
>(Ty
)) {
661 Proto
= '(' + Proto
+ ')';
662 Ty
= PT
->getInnerType();
665 if (const FunctionType
*AFT
= Ty
->getAs
<FunctionType
>()) {
666 const FunctionProtoType
*FT
= nullptr;
667 if (D
->hasWrittenPrototype())
668 FT
= dyn_cast
<FunctionProtoType
>(AFT
);
672 llvm::raw_string_ostream
POut(Proto
);
673 DeclPrinter
ParamPrinter(POut
, SubPolicy
, Context
, Indentation
);
674 for (unsigned i
= 0, e
= D
->getNumParams(); i
!= e
; ++i
) {
676 ParamPrinter
.VisitParmVarDecl(D
->getParamDecl(i
));
679 if (FT
->isVariadic()) {
680 if (D
->getNumParams()) POut
<< ", ";
682 } else if (!D
->getNumParams() && !Context
.getLangOpts().CPlusPlus
) {
683 // The function has a prototype, so it needs to retain the prototype
687 } else if (D
->doesThisDeclarationHaveABody() && !D
->hasPrototype()) {
688 for (unsigned i
= 0, e
= D
->getNumParams(); i
!= e
; ++i
) {
691 Proto
+= D
->getParamDecl(i
)->getNameAsString();
700 if (FT
->isVolatile())
701 Proto
+= " volatile";
702 if (FT
->isRestrict())
703 Proto
+= " restrict";
705 switch (FT
->getRefQualifier()) {
717 if (FT
&& FT
->hasDynamicExceptionSpec()) {
719 if (FT
->getExceptionSpecType() == EST_MSAny
)
722 for (unsigned I
= 0, N
= FT
->getNumExceptions(); I
!= N
; ++I
) {
726 Proto
+= FT
->getExceptionType(I
).getAsString(SubPolicy
);
729 } else if (FT
&& isNoexceptExceptionSpec(FT
->getExceptionSpecType())) {
730 Proto
+= " noexcept";
731 if (isComputedNoexcept(FT
->getExceptionSpecType())) {
733 llvm::raw_string_ostream
EOut(Proto
);
734 FT
->getNoexceptExpr()->printPretty(EOut
, nullptr, SubPolicy
,
735 Indentation
, "\n", &Context
);
742 if (!Policy
.TerseOutput
)
743 PrintConstructorInitializers(CDecl
, Proto
);
744 } else if (!ConversionDecl
&& !isa
<CXXDestructorDecl
>(D
)) {
745 if (FT
&& FT
->hasTrailingReturn()) {
748 Out
<< Proto
<< " -> ";
751 AFT
->getReturnType().print(Out
, Policy
, Proto
);
756 if (Expr
*TrailingRequiresClause
= D
->getTrailingRequiresClause()) {
758 TrailingRequiresClause
->printPretty(Out
, nullptr, SubPolicy
, Indentation
,
762 Ty
.print(Out
, Policy
, Proto
);
765 prettyPrintAttributes(D
);
769 else if (D
->isDeletedAsWritten())
771 else if (D
->isExplicitlyDefaulted())
773 else if (D
->doesThisDeclarationHaveABody()) {
774 if (!Policy
.TerseOutput
) {
775 if (!D
->hasPrototype() && D
->getNumParams()) {
776 // This is a K&R function definition, so we need to print the
779 DeclPrinter
ParamPrinter(Out
, SubPolicy
, Context
, Indentation
);
780 Indentation
+= Policy
.Indentation
;
781 for (unsigned i
= 0, e
= D
->getNumParams(); i
!= e
; ++i
) {
783 ParamPrinter
.VisitParmVarDecl(D
->getParamDecl(i
));
786 Indentation
-= Policy
.Indentation
;
790 D
->getBody()->printPrettyControlled(Out
, nullptr, SubPolicy
, Indentation
, "\n",
793 if (!Policy
.TerseOutput
&& isa
<CXXConstructorDecl
>(*D
))
799 void DeclPrinter::VisitFriendDecl(FriendDecl
*D
) {
800 if (TypeSourceInfo
*TSI
= D
->getFriendType()) {
801 unsigned NumTPLists
= D
->getFriendTypeNumTemplateParameterLists();
802 for (unsigned i
= 0; i
< NumTPLists
; ++i
)
803 printTemplateParameters(D
->getFriendTypeTemplateParameterList(i
));
805 Out
<< " " << TSI
->getType().getAsString(Policy
);
807 else if (FunctionDecl
*FD
=
808 dyn_cast
<FunctionDecl
>(D
->getFriendDecl())) {
810 VisitFunctionDecl(FD
);
812 else if (FunctionTemplateDecl
*FTD
=
813 dyn_cast
<FunctionTemplateDecl
>(D
->getFriendDecl())) {
815 VisitFunctionTemplateDecl(FTD
);
817 else if (ClassTemplateDecl
*CTD
=
818 dyn_cast
<ClassTemplateDecl
>(D
->getFriendDecl())) {
820 VisitRedeclarableTemplateDecl(CTD
);
824 void DeclPrinter::VisitFieldDecl(FieldDecl
*D
) {
825 // FIXME: add printing of pragma attributes if required.
826 if (!Policy
.SuppressSpecifiers
&& D
->isMutable())
828 if (!Policy
.SuppressSpecifiers
&& D
->isModulePrivate())
829 Out
<< "__module_private__ ";
831 Out
<< D
->getASTContext().getUnqualifiedObjCPointerType(D
->getType()).
832 stream(Policy
, D
->getName(), Indentation
);
834 if (D
->isBitField()) {
836 D
->getBitWidth()->printPretty(Out
, nullptr, Policy
, Indentation
, "\n",
840 Expr
*Init
= D
->getInClassInitializer();
841 if (!Policy
.SuppressInitializers
&& Init
) {
842 if (D
->getInClassInitStyle() == ICIS_ListInit
)
846 Init
->printPretty(Out
, nullptr, Policy
, Indentation
, "\n", &Context
);
848 prettyPrintAttributes(D
);
851 void DeclPrinter::VisitLabelDecl(LabelDecl
*D
) {
855 void DeclPrinter::VisitVarDecl(VarDecl
*D
) {
856 prettyPrintPragmas(D
);
858 QualType T
= D
->getTypeSourceInfo()
859 ? D
->getTypeSourceInfo()->getType()
860 : D
->getASTContext().getUnqualifiedObjCPointerType(D
->getType());
862 if (!Policy
.SuppressSpecifiers
) {
863 StorageClass SC
= D
->getStorageClass();
865 Out
<< VarDecl::getStorageClassSpecifierString(SC
) << " ";
867 switch (D
->getTSCSpec()) {
868 case TSCS_unspecified
:
873 case TSCS__Thread_local
:
874 Out
<< "_Thread_local ";
876 case TSCS_thread_local
:
877 Out
<< "thread_local ";
881 if (D
->isModulePrivate())
882 Out
<< "__module_private__ ";
884 if (D
->isConstexpr()) {
886 T
.removeLocalConst();
890 printDeclType(T
, (isa
<ParmVarDecl
>(D
) && Policy
.CleanUglifiedParameters
&&
892 ? D
->getIdentifier()->deuglifiedName()
894 Expr
*Init
= D
->getInit();
895 if (!Policy
.SuppressInitializers
&& Init
) {
896 bool ImplicitInit
= false;
897 if (D
->isCXXForRangeDecl()) {
898 // FIXME: We should print the range expression instead.
900 } else if (CXXConstructExpr
*Construct
=
901 dyn_cast
<CXXConstructExpr
>(Init
->IgnoreImplicit())) {
902 if (D
->getInitStyle() == VarDecl::CallInit
&&
903 !Construct
->isListInitialization()) {
904 ImplicitInit
= Construct
->getNumArgs() == 0 ||
905 Construct
->getArg(0)->isDefaultArgument();
909 if ((D
->getInitStyle() == VarDecl::CallInit
) && !isa
<ParenListExpr
>(Init
))
911 else if (D
->getInitStyle() == VarDecl::CInit
) {
914 PrintingPolicy
SubPolicy(Policy
);
915 SubPolicy
.SuppressSpecifiers
= false;
916 SubPolicy
.IncludeTagDefinition
= false;
917 Init
->printPretty(Out
, nullptr, SubPolicy
, Indentation
, "\n", &Context
);
918 if ((D
->getInitStyle() == VarDecl::CallInit
) && !isa
<ParenListExpr
>(Init
))
922 prettyPrintAttributes(D
);
925 void DeclPrinter::VisitParmVarDecl(ParmVarDecl
*D
) {
929 void DeclPrinter::VisitFileScopeAsmDecl(FileScopeAsmDecl
*D
) {
931 D
->getAsmString()->printPretty(Out
, nullptr, Policy
, Indentation
, "\n",
936 void DeclPrinter::VisitTopLevelStmtDecl(TopLevelStmtDecl
*D
) {
937 assert(D
->getStmt());
938 D
->getStmt()->printPretty(Out
, nullptr, Policy
, Indentation
, "\n", &Context
);
941 void DeclPrinter::VisitImportDecl(ImportDecl
*D
) {
942 Out
<< "@import " << D
->getImportedModule()->getFullModuleName()
946 void DeclPrinter::VisitStaticAssertDecl(StaticAssertDecl
*D
) {
947 Out
<< "static_assert(";
948 D
->getAssertExpr()->printPretty(Out
, nullptr, Policy
, Indentation
, "\n",
950 if (StringLiteral
*SL
= D
->getMessage()) {
952 SL
->printPretty(Out
, nullptr, Policy
, Indentation
, "\n", &Context
);
957 //----------------------------------------------------------------------------
959 //----------------------------------------------------------------------------
960 void DeclPrinter::VisitNamespaceDecl(NamespaceDecl
*D
) {
965 if (D
->getDeclName())
966 Out
<< D
->getDeclName() << ' ';
973 void DeclPrinter::VisitUsingDirectiveDecl(UsingDirectiveDecl
*D
) {
974 Out
<< "using namespace ";
975 if (D
->getQualifier())
976 D
->getQualifier()->print(Out
, Policy
);
977 Out
<< *D
->getNominatedNamespaceAsWritten();
980 void DeclPrinter::VisitNamespaceAliasDecl(NamespaceAliasDecl
*D
) {
981 Out
<< "namespace " << *D
<< " = ";
982 if (D
->getQualifier())
983 D
->getQualifier()->print(Out
, Policy
);
984 Out
<< *D
->getAliasedNamespace();
987 void DeclPrinter::VisitEmptyDecl(EmptyDecl
*D
) {
988 prettyPrintAttributes(D
);
991 void DeclPrinter::VisitCXXRecordDecl(CXXRecordDecl
*D
) {
992 // FIXME: add printing of pragma attributes if required.
993 if (!Policy
.SuppressSpecifiers
&& D
->isModulePrivate())
994 Out
<< "__module_private__ ";
995 Out
<< D
->getKindName();
997 prettyPrintAttributes(D
);
999 if (D
->getIdentifier()) {
1002 if (auto S
= dyn_cast
<ClassTemplateSpecializationDecl
>(D
)) {
1003 ArrayRef
<TemplateArgument
> Args
= S
->getTemplateArgs().asArray();
1004 if (!Policy
.PrintCanonicalTypes
)
1005 if (const auto* TSI
= S
->getTypeAsWritten())
1006 if (const auto *TST
=
1007 dyn_cast
<TemplateSpecializationType
>(TSI
->getType()))
1008 Args
= TST
->template_arguments();
1009 printTemplateArguments(
1010 Args
, S
->getSpecializedTemplate()->getTemplateParameters());
1014 if (D
->hasDefinition()) {
1015 if (D
->hasAttr
<FinalAttr
>()) {
1020 if (D
->isCompleteDefinition()) {
1021 // Print the base classes
1022 if (D
->getNumBases()) {
1024 for (CXXRecordDecl::base_class_iterator Base
= D
->bases_begin(),
1025 BaseEnd
= D
->bases_end(); Base
!= BaseEnd
; ++Base
) {
1026 if (Base
!= D
->bases_begin())
1029 if (Base
->isVirtual())
1032 AccessSpecifier AS
= Base
->getAccessSpecifierAsWritten();
1033 if (AS
!= AS_none
) {
1037 Out
<< Base
->getType().getAsString(Policy
);
1039 if (Base
->isPackExpansion())
1044 // Print the class definition
1045 // FIXME: Doesn't print access specifiers, e.g., "public:"
1046 if (Policy
.TerseOutput
) {
1050 VisitDeclContext(D
);
1056 void DeclPrinter::VisitLinkageSpecDecl(LinkageSpecDecl
*D
) {
1058 if (D
->getLanguage() == LinkageSpecDecl::lang_c
)
1061 assert(D
->getLanguage() == LinkageSpecDecl::lang_cxx
&&
1062 "unknown language in linkage specification");
1066 Out
<< "extern \"" << l
<< "\" ";
1067 if (D
->hasBraces()) {
1069 VisitDeclContext(D
);
1072 Visit(*D
->decls_begin());
1075 void DeclPrinter::printTemplateParameters(const TemplateParameterList
*Params
,
1076 bool OmitTemplateKW
) {
1079 if (!OmitTemplateKW
)
1083 bool NeedComma
= false;
1084 for (const Decl
*Param
: *Params
) {
1085 if (Param
->isImplicit())
1093 if (const auto *TTP
= dyn_cast
<TemplateTypeParmDecl
>(Param
)) {
1094 VisitTemplateTypeParmDecl(TTP
);
1095 } else if (auto NTTP
= dyn_cast
<NonTypeTemplateParmDecl
>(Param
)) {
1096 VisitNonTypeTemplateParmDecl(NTTP
);
1097 } else if (auto TTPD
= dyn_cast
<TemplateTemplateParmDecl
>(Param
)) {
1098 VisitTemplateDecl(TTPD
);
1099 // FIXME: print the default argument, if present.
1104 if (!OmitTemplateKW
)
1108 void DeclPrinter::printTemplateArguments(ArrayRef
<TemplateArgument
> Args
,
1109 const TemplateParameterList
*Params
) {
1111 for (size_t I
= 0, E
= Args
.size(); I
< E
; ++I
) {
1115 Args
[I
].print(Policy
, Out
, /*IncludeType*/ true);
1117 Args
[I
].print(Policy
, Out
,
1118 TemplateParameterList::shouldIncludeTypeForArgument(
1119 Policy
, Params
, I
));
1124 void DeclPrinter::printTemplateArguments(ArrayRef
<TemplateArgumentLoc
> Args
,
1125 const TemplateParameterList
*Params
) {
1127 for (size_t I
= 0, E
= Args
.size(); I
< E
; ++I
) {
1131 Args
[I
].getArgument().print(Policy
, Out
, /*IncludeType*/ true);
1133 Args
[I
].getArgument().print(
1135 TemplateParameterList::shouldIncludeTypeForArgument(Policy
, Params
,
1141 void DeclPrinter::VisitTemplateDecl(const TemplateDecl
*D
) {
1142 printTemplateParameters(D
->getTemplateParameters());
1144 if (const TemplateTemplateParmDecl
*TTP
=
1145 dyn_cast
<TemplateTemplateParmDecl
>(D
)) {
1148 if (TTP
->isParameterPack())
1150 else if (TTP
->getDeclName())
1153 if (TTP
->getDeclName()) {
1154 if (Policy
.CleanUglifiedParameters
&& TTP
->getIdentifier())
1155 Out
<< TTP
->getIdentifier()->deuglifiedName();
1157 Out
<< TTP
->getDeclName();
1159 } else if (auto *TD
= D
->getTemplatedDecl())
1161 else if (const auto *Concept
= dyn_cast
<ConceptDecl
>(D
)) {
1162 Out
<< "concept " << Concept
->getName() << " = " ;
1163 Concept
->getConstraintExpr()->printPretty(Out
, nullptr, Policy
, Indentation
,
1168 void DeclPrinter::VisitFunctionTemplateDecl(FunctionTemplateDecl
*D
) {
1169 prettyPrintPragmas(D
->getTemplatedDecl());
1170 // Print any leading template parameter lists.
1171 if (const FunctionDecl
*FD
= D
->getTemplatedDecl()) {
1172 for (unsigned I
= 0, NumTemplateParams
= FD
->getNumTemplateParameterLists();
1173 I
< NumTemplateParams
; ++I
)
1174 printTemplateParameters(FD
->getTemplateParameterList(I
));
1176 VisitRedeclarableTemplateDecl(D
);
1177 // Declare target attribute is special one, natural spelling for the pragma
1178 // assumes "ending" construct so print it here.
1179 if (D
->getTemplatedDecl()->hasAttr
<OMPDeclareTargetDeclAttr
>())
1180 Out
<< "#pragma omp end declare target\n";
1182 // Never print "instantiations" for deduction guides (they don't really
1184 if (PrintInstantiation
&&
1185 !isa
<CXXDeductionGuideDecl
>(D
->getTemplatedDecl())) {
1186 FunctionDecl
*PrevDecl
= D
->getTemplatedDecl();
1187 const FunctionDecl
*Def
;
1188 if (PrevDecl
->isDefined(Def
) && Def
!= PrevDecl
)
1190 for (auto *I
: D
->specializations())
1191 if (I
->getTemplateSpecializationKind() == TSK_ImplicitInstantiation
) {
1192 if (!PrevDecl
->isThisDeclarationADefinition())
1195 prettyPrintPragmas(I
);
1201 void DeclPrinter::VisitClassTemplateDecl(ClassTemplateDecl
*D
) {
1202 VisitRedeclarableTemplateDecl(D
);
1204 if (PrintInstantiation
) {
1205 for (auto *I
: D
->specializations())
1206 if (I
->getSpecializationKind() == TSK_ImplicitInstantiation
) {
1207 if (D
->isThisDeclarationADefinition())
1216 void DeclPrinter::VisitClassTemplateSpecializationDecl(
1217 ClassTemplateSpecializationDecl
*D
) {
1218 Out
<< "template<> ";
1219 VisitCXXRecordDecl(D
);
1222 void DeclPrinter::VisitClassTemplatePartialSpecializationDecl(
1223 ClassTemplatePartialSpecializationDecl
*D
) {
1224 printTemplateParameters(D
->getTemplateParameters());
1225 VisitCXXRecordDecl(D
);
1228 //----------------------------------------------------------------------------
1229 // Objective-C declarations
1230 //----------------------------------------------------------------------------
1232 void DeclPrinter::PrintObjCMethodType(ASTContext
&Ctx
,
1233 Decl::ObjCDeclQualifier Quals
,
1236 if (Quals
& Decl::ObjCDeclQualifier::OBJC_TQ_In
)
1238 if (Quals
& Decl::ObjCDeclQualifier::OBJC_TQ_Inout
)
1240 if (Quals
& Decl::ObjCDeclQualifier::OBJC_TQ_Out
)
1242 if (Quals
& Decl::ObjCDeclQualifier::OBJC_TQ_Bycopy
)
1244 if (Quals
& Decl::ObjCDeclQualifier::OBJC_TQ_Byref
)
1246 if (Quals
& Decl::ObjCDeclQualifier::OBJC_TQ_Oneway
)
1248 if (Quals
& Decl::ObjCDeclQualifier::OBJC_TQ_CSNullability
) {
1249 if (auto nullability
= AttributedType::stripOuterNullability(T
))
1250 Out
<< getNullabilitySpelling(*nullability
, true) << ' ';
1253 Out
<< Ctx
.getUnqualifiedObjCPointerType(T
).getAsString(Policy
);
1257 void DeclPrinter::PrintObjCTypeParams(ObjCTypeParamList
*Params
) {
1259 unsigned First
= true;
1260 for (auto *Param
: *Params
) {
1267 switch (Param
->getVariance()) {
1268 case ObjCTypeParamVariance::Invariant
:
1271 case ObjCTypeParamVariance::Covariant
:
1272 Out
<< "__covariant ";
1275 case ObjCTypeParamVariance::Contravariant
:
1276 Out
<< "__contravariant ";
1280 Out
<< Param
->getDeclName();
1282 if (Param
->hasExplicitBound()) {
1283 Out
<< " : " << Param
->getUnderlyingType().getAsString(Policy
);
1289 void DeclPrinter::VisitObjCMethodDecl(ObjCMethodDecl
*OMD
) {
1290 if (OMD
->isInstanceMethod())
1294 if (!OMD
->getReturnType().isNull()) {
1295 PrintObjCMethodType(OMD
->getASTContext(), OMD
->getObjCDeclQualifier(),
1296 OMD
->getReturnType());
1299 std::string name
= OMD
->getSelector().getAsString();
1300 std::string::size_type pos
, lastPos
= 0;
1301 for (const auto *PI
: OMD
->parameters()) {
1302 // FIXME: selector is missing here!
1303 pos
= name
.find_first_of(':', lastPos
);
1306 Out
<< name
.substr(lastPos
, pos
- lastPos
) << ':';
1307 PrintObjCMethodType(OMD
->getASTContext(),
1308 PI
->getObjCDeclQualifier(),
1314 if (OMD
->param_begin() == OMD
->param_end())
1317 if (OMD
->isVariadic())
1320 prettyPrintAttributes(OMD
);
1322 if (OMD
->getBody() && !Policy
.TerseOutput
) {
1324 OMD
->getBody()->printPretty(Out
, nullptr, Policy
, Indentation
, "\n",
1327 else if (Policy
.PolishForDeclaration
)
1331 void DeclPrinter::VisitObjCImplementationDecl(ObjCImplementationDecl
*OID
) {
1332 std::string I
= OID
->getNameAsString();
1333 ObjCInterfaceDecl
*SID
= OID
->getSuperClass();
1335 bool eolnOut
= false;
1337 Out
<< "@implementation " << I
<< " : " << *SID
;
1339 Out
<< "@implementation " << I
;
1341 if (OID
->ivar_size() > 0) {
1344 Indentation
+= Policy
.Indentation
;
1345 for (const auto *I
: OID
->ivars()) {
1346 Indent() << I
->getASTContext().getUnqualifiedObjCPointerType(I
->getType()).
1347 getAsString(Policy
) << ' ' << *I
<< ";\n";
1349 Indentation
-= Policy
.Indentation
;
1352 else if (SID
|| (OID
->decls_begin() != OID
->decls_end())) {
1356 VisitDeclContext(OID
, false);
1362 void DeclPrinter::VisitObjCInterfaceDecl(ObjCInterfaceDecl
*OID
) {
1363 std::string I
= OID
->getNameAsString();
1364 ObjCInterfaceDecl
*SID
= OID
->getSuperClass();
1366 if (!OID
->isThisDeclarationADefinition()) {
1367 Out
<< "@class " << I
;
1369 if (auto TypeParams
= OID
->getTypeParamListAsWritten()) {
1370 PrintObjCTypeParams(TypeParams
);
1376 bool eolnOut
= false;
1377 Out
<< "@interface " << I
;
1379 if (auto TypeParams
= OID
->getTypeParamListAsWritten()) {
1380 PrintObjCTypeParams(TypeParams
);
1384 Out
<< " : " << QualType(OID
->getSuperClassType(), 0).getAsString(Policy
);
1387 const ObjCList
<ObjCProtocolDecl
> &Protocols
= OID
->getReferencedProtocols();
1388 if (!Protocols
.empty()) {
1389 for (ObjCList
<ObjCProtocolDecl
>::iterator I
= Protocols
.begin(),
1390 E
= Protocols
.end(); I
!= E
; ++I
)
1391 Out
<< (I
== Protocols
.begin() ? '<' : ',') << **I
;
1395 if (OID
->ivar_size() > 0) {
1398 Indentation
+= Policy
.Indentation
;
1399 for (const auto *I
: OID
->ivars()) {
1400 Indent() << I
->getASTContext()
1401 .getUnqualifiedObjCPointerType(I
->getType())
1402 .getAsString(Policy
) << ' ' << *I
<< ";\n";
1404 Indentation
-= Policy
.Indentation
;
1407 else if (SID
|| (OID
->decls_begin() != OID
->decls_end())) {
1412 VisitDeclContext(OID
, false);
1416 // FIXME: implement the rest...
1419 void DeclPrinter::VisitObjCProtocolDecl(ObjCProtocolDecl
*PID
) {
1420 if (!PID
->isThisDeclarationADefinition()) {
1421 Out
<< "@protocol " << *PID
<< ";\n";
1425 const ObjCList
<ObjCProtocolDecl
> &Protocols
= PID
->getReferencedProtocols();
1426 if (!Protocols
.empty()) {
1427 Out
<< "@protocol " << *PID
;
1428 for (ObjCList
<ObjCProtocolDecl
>::iterator I
= Protocols
.begin(),
1429 E
= Protocols
.end(); I
!= E
; ++I
)
1430 Out
<< (I
== Protocols
.begin() ? '<' : ',') << **I
;
1433 Out
<< "@protocol " << *PID
<< '\n';
1434 VisitDeclContext(PID
, false);
1438 void DeclPrinter::VisitObjCCategoryImplDecl(ObjCCategoryImplDecl
*PID
) {
1439 Out
<< "@implementation ";
1440 if (const auto *CID
= PID
->getClassInterface())
1443 Out
<< "<<error-type>>";
1444 Out
<< '(' << *PID
<< ")\n";
1446 VisitDeclContext(PID
, false);
1448 // FIXME: implement the rest...
1451 void DeclPrinter::VisitObjCCategoryDecl(ObjCCategoryDecl
*PID
) {
1452 Out
<< "@interface ";
1453 if (const auto *CID
= PID
->getClassInterface())
1456 Out
<< "<<error-type>>";
1457 if (auto TypeParams
= PID
->getTypeParamList()) {
1458 PrintObjCTypeParams(TypeParams
);
1460 Out
<< "(" << *PID
<< ")\n";
1461 if (PID
->ivar_size() > 0) {
1463 Indentation
+= Policy
.Indentation
;
1464 for (const auto *I
: PID
->ivars())
1465 Indent() << I
->getASTContext().getUnqualifiedObjCPointerType(I
->getType()).
1466 getAsString(Policy
) << ' ' << *I
<< ";\n";
1467 Indentation
-= Policy
.Indentation
;
1471 VisitDeclContext(PID
, false);
1474 // FIXME: implement the rest...
1477 void DeclPrinter::VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl
*AID
) {
1478 Out
<< "@compatibility_alias " << *AID
1479 << ' ' << *AID
->getClassInterface() << ";\n";
1482 /// PrintObjCPropertyDecl - print a property declaration.
1484 /// Print attributes in the following order:
1486 /// - nonatomic | atomic
1487 /// - assign | retain | strong | copy | weak | unsafe_unretained
1488 /// - readwrite | readonly
1489 /// - getter & setter
1491 void DeclPrinter::VisitObjCPropertyDecl(ObjCPropertyDecl
*PDecl
) {
1492 if (PDecl
->getPropertyImplementation() == ObjCPropertyDecl::Required
)
1493 Out
<< "@required\n";
1494 else if (PDecl
->getPropertyImplementation() == ObjCPropertyDecl::Optional
)
1495 Out
<< "@optional\n";
1497 QualType T
= PDecl
->getType();
1500 if (PDecl
->getPropertyAttributes() != ObjCPropertyAttribute::kind_noattr
) {
1503 if (PDecl
->getPropertyAttributes() & ObjCPropertyAttribute::kind_class
) {
1504 Out
<< (first
? "" : ", ") << "class";
1508 if (PDecl
->getPropertyAttributes() & ObjCPropertyAttribute::kind_direct
) {
1509 Out
<< (first
? "" : ", ") << "direct";
1513 if (PDecl
->getPropertyAttributes() &
1514 ObjCPropertyAttribute::kind_nonatomic
) {
1515 Out
<< (first
? "" : ", ") << "nonatomic";
1518 if (PDecl
->getPropertyAttributes() & ObjCPropertyAttribute::kind_atomic
) {
1519 Out
<< (first
? "" : ", ") << "atomic";
1523 if (PDecl
->getPropertyAttributes() & ObjCPropertyAttribute::kind_assign
) {
1524 Out
<< (first
? "" : ", ") << "assign";
1527 if (PDecl
->getPropertyAttributes() & ObjCPropertyAttribute::kind_retain
) {
1528 Out
<< (first
? "" : ", ") << "retain";
1532 if (PDecl
->getPropertyAttributes() & ObjCPropertyAttribute::kind_strong
) {
1533 Out
<< (first
? "" : ", ") << "strong";
1536 if (PDecl
->getPropertyAttributes() & ObjCPropertyAttribute::kind_copy
) {
1537 Out
<< (first
? "" : ", ") << "copy";
1540 if (PDecl
->getPropertyAttributes() & ObjCPropertyAttribute::kind_weak
) {
1541 Out
<< (first
? "" : ", ") << "weak";
1544 if (PDecl
->getPropertyAttributes() &
1545 ObjCPropertyAttribute::kind_unsafe_unretained
) {
1546 Out
<< (first
? "" : ", ") << "unsafe_unretained";
1550 if (PDecl
->getPropertyAttributes() &
1551 ObjCPropertyAttribute::kind_readwrite
) {
1552 Out
<< (first
? "" : ", ") << "readwrite";
1555 if (PDecl
->getPropertyAttributes() & ObjCPropertyAttribute::kind_readonly
) {
1556 Out
<< (first
? "" : ", ") << "readonly";
1560 if (PDecl
->getPropertyAttributes() & ObjCPropertyAttribute::kind_getter
) {
1561 Out
<< (first
? "" : ", ") << "getter = ";
1562 PDecl
->getGetterName().print(Out
);
1565 if (PDecl
->getPropertyAttributes() & ObjCPropertyAttribute::kind_setter
) {
1566 Out
<< (first
? "" : ", ") << "setter = ";
1567 PDecl
->getSetterName().print(Out
);
1571 if (PDecl
->getPropertyAttributes() &
1572 ObjCPropertyAttribute::kind_nullability
) {
1573 if (auto nullability
= AttributedType::stripOuterNullability(T
)) {
1574 if (*nullability
== NullabilityKind::Unspecified
&&
1575 (PDecl
->getPropertyAttributes() &
1576 ObjCPropertyAttribute::kind_null_resettable
)) {
1577 Out
<< (first
? "" : ", ") << "null_resettable";
1579 Out
<< (first
? "" : ", ")
1580 << getNullabilitySpelling(*nullability
, true);
1586 (void) first
; // Silence dead store warning due to idiomatic code.
1589 std::string TypeStr
= PDecl
->getASTContext().getUnqualifiedObjCPointerType(T
).
1590 getAsString(Policy
);
1591 Out
<< ' ' << TypeStr
;
1592 if (!StringRef(TypeStr
).endswith("*"))
1595 if (Policy
.PolishForDeclaration
)
1599 void DeclPrinter::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl
*PID
) {
1600 if (PID
->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize
)
1601 Out
<< "@synthesize ";
1604 Out
<< *PID
->getPropertyDecl();
1605 if (PID
->getPropertyIvarDecl())
1606 Out
<< '=' << *PID
->getPropertyIvarDecl();
1609 void DeclPrinter::VisitUsingDecl(UsingDecl
*D
) {
1610 if (!D
->isAccessDeclaration())
1612 if (D
->hasTypename())
1614 D
->getQualifier()->print(Out
, Policy
);
1616 // Use the correct record name when the using declaration is used for
1617 // inheriting constructors.
1618 for (const auto *Shadow
: D
->shadows()) {
1619 if (const auto *ConstructorShadow
=
1620 dyn_cast
<ConstructorUsingShadowDecl
>(Shadow
)) {
1621 assert(Shadow
->getDeclContext() == ConstructorShadow
->getDeclContext());
1622 Out
<< *ConstructorShadow
->getNominatedBaseClass();
1629 void DeclPrinter::VisitUsingEnumDecl(UsingEnumDecl
*D
) {
1630 Out
<< "using enum " << D
->getEnumDecl();
1634 DeclPrinter::VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl
*D
) {
1635 Out
<< "using typename ";
1636 D
->getQualifier()->print(Out
, Policy
);
1637 Out
<< D
->getDeclName();
1640 void DeclPrinter::VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl
*D
) {
1641 if (!D
->isAccessDeclaration())
1643 D
->getQualifier()->print(Out
, Policy
);
1644 Out
<< D
->getDeclName();
1647 void DeclPrinter::VisitUsingShadowDecl(UsingShadowDecl
*D
) {
1651 void DeclPrinter::VisitOMPThreadPrivateDecl(OMPThreadPrivateDecl
*D
) {
1652 Out
<< "#pragma omp threadprivate";
1653 if (!D
->varlist_empty()) {
1654 for (OMPThreadPrivateDecl::varlist_iterator I
= D
->varlist_begin(),
1655 E
= D
->varlist_end();
1657 Out
<< (I
== D
->varlist_begin() ? '(' : ',');
1658 NamedDecl
*ND
= cast
<DeclRefExpr
>(*I
)->getDecl();
1659 ND
->printQualifiedName(Out
);
1665 void DeclPrinter::VisitHLSLBufferDecl(HLSLBufferDecl
*D
) {
1673 prettyPrintAttributes(D
);
1676 VisitDeclContext(D
);
1680 void DeclPrinter::VisitOMPAllocateDecl(OMPAllocateDecl
*D
) {
1681 Out
<< "#pragma omp allocate";
1682 if (!D
->varlist_empty()) {
1683 for (OMPAllocateDecl::varlist_iterator I
= D
->varlist_begin(),
1684 E
= D
->varlist_end();
1686 Out
<< (I
== D
->varlist_begin() ? '(' : ',');
1687 NamedDecl
*ND
= cast
<DeclRefExpr
>(*I
)->getDecl();
1688 ND
->printQualifiedName(Out
);
1692 if (!D
->clauselist_empty()) {
1693 OMPClausePrinter
Printer(Out
, Policy
);
1694 for (OMPClause
*C
: D
->clauselists()) {
1701 void DeclPrinter::VisitOMPRequiresDecl(OMPRequiresDecl
*D
) {
1702 Out
<< "#pragma omp requires ";
1703 if (!D
->clauselist_empty()) {
1704 OMPClausePrinter
Printer(Out
, Policy
);
1705 for (auto I
= D
->clauselist_begin(), E
= D
->clauselist_end(); I
!= E
; ++I
)
1710 void DeclPrinter::VisitOMPDeclareReductionDecl(OMPDeclareReductionDecl
*D
) {
1711 if (!D
->isInvalidDecl()) {
1712 Out
<< "#pragma omp declare reduction (";
1713 if (D
->getDeclName().getNameKind() == DeclarationName::CXXOperatorName
) {
1714 const char *OpName
=
1715 getOperatorSpelling(D
->getDeclName().getCXXOverloadedOperator());
1716 assert(OpName
&& "not an overloaded operator");
1719 assert(D
->getDeclName().isIdentifier());
1720 D
->printName(Out
, Policy
);
1723 D
->getType().print(Out
, Policy
);
1725 D
->getCombiner()->printPretty(Out
, nullptr, Policy
, 0, "\n", &Context
);
1727 if (auto *Init
= D
->getInitializer()) {
1728 Out
<< " initializer(";
1729 switch (D
->getInitializerKind()) {
1730 case OMPDeclareReductionDecl::DirectInit
:
1733 case OMPDeclareReductionDecl::CopyInit
:
1734 Out
<< "omp_priv = ";
1736 case OMPDeclareReductionDecl::CallInit
:
1739 Init
->printPretty(Out
, nullptr, Policy
, 0, "\n", &Context
);
1740 if (D
->getInitializerKind() == OMPDeclareReductionDecl::DirectInit
)
1747 void DeclPrinter::VisitOMPDeclareMapperDecl(OMPDeclareMapperDecl
*D
) {
1748 if (!D
->isInvalidDecl()) {
1749 Out
<< "#pragma omp declare mapper (";
1750 D
->printName(Out
, Policy
);
1752 D
->getType().print(Out
, Policy
);
1754 Out
<< D
->getVarName();
1756 if (!D
->clauselist_empty()) {
1757 OMPClausePrinter
Printer(Out
, Policy
);
1758 for (auto *C
: D
->clauselists()) {
1766 void DeclPrinter::VisitOMPCapturedExprDecl(OMPCapturedExprDecl
*D
) {
1767 D
->getInit()->printPretty(Out
, nullptr, Policy
, Indentation
, "\n", &Context
);
1770 void DeclPrinter::VisitTemplateTypeParmDecl(const TemplateTypeParmDecl
*TTP
) {
1771 if (const TypeConstraint
*TC
= TTP
->getTypeConstraint())
1772 TC
->print(Out
, Policy
);
1773 else if (TTP
->wasDeclaredWithTypename())
1778 if (TTP
->isParameterPack())
1780 else if (TTP
->getDeclName())
1783 if (TTP
->getDeclName()) {
1784 if (Policy
.CleanUglifiedParameters
&& TTP
->getIdentifier())
1785 Out
<< TTP
->getIdentifier()->deuglifiedName();
1787 Out
<< TTP
->getDeclName();
1790 if (TTP
->hasDefaultArgument()) {
1792 Out
<< TTP
->getDefaultArgument().getAsString(Policy
);
1796 void DeclPrinter::VisitNonTypeTemplateParmDecl(
1797 const NonTypeTemplateParmDecl
*NTTP
) {
1799 if (IdentifierInfo
*II
= NTTP
->getIdentifier())
1801 Policy
.CleanUglifiedParameters
? II
->deuglifiedName() : II
->getName();
1802 printDeclType(NTTP
->getType(), Name
, NTTP
->isParameterPack());
1804 if (NTTP
->hasDefaultArgument()) {
1806 NTTP
->getDefaultArgument()->printPretty(Out
, nullptr, Policy
, Indentation
,