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