1f4a2713aSLionel Sambuc //===--- DeclPrinter.cpp - Printing implementation for Decl ASTs ----------===//
2f4a2713aSLionel Sambuc //
3f4a2713aSLionel Sambuc // The LLVM Compiler Infrastructure
4f4a2713aSLionel Sambuc //
5f4a2713aSLionel Sambuc // This file is distributed under the University of Illinois Open Source
6f4a2713aSLionel Sambuc // License. See LICENSE.TXT for details.
7f4a2713aSLionel Sambuc //
8f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
9f4a2713aSLionel Sambuc //
10f4a2713aSLionel Sambuc // This file implements the Decl::print method, which pretty prints the
11f4a2713aSLionel Sambuc // AST back out to C/Objective-C/C++/Objective-C++ code.
12f4a2713aSLionel Sambuc //
13f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
14f4a2713aSLionel Sambuc #include "clang/AST/ASTContext.h"
15f4a2713aSLionel Sambuc #include "clang/AST/Attr.h"
16f4a2713aSLionel Sambuc #include "clang/AST/Decl.h"
17f4a2713aSLionel Sambuc #include "clang/AST/DeclCXX.h"
18f4a2713aSLionel Sambuc #include "clang/AST/DeclObjC.h"
19f4a2713aSLionel Sambuc #include "clang/AST/DeclVisitor.h"
20f4a2713aSLionel Sambuc #include "clang/AST/Expr.h"
21f4a2713aSLionel Sambuc #include "clang/AST/ExprCXX.h"
22f4a2713aSLionel Sambuc #include "clang/AST/PrettyPrinter.h"
23f4a2713aSLionel Sambuc #include "clang/Basic/Module.h"
24f4a2713aSLionel Sambuc #include "llvm/Support/raw_ostream.h"
25f4a2713aSLionel Sambuc using namespace clang;
26f4a2713aSLionel Sambuc
27f4a2713aSLionel Sambuc namespace {
28f4a2713aSLionel Sambuc class DeclPrinter : public DeclVisitor<DeclPrinter> {
29f4a2713aSLionel Sambuc raw_ostream &Out;
30f4a2713aSLionel Sambuc PrintingPolicy Policy;
31f4a2713aSLionel Sambuc unsigned Indentation;
32f4a2713aSLionel Sambuc bool PrintInstantiation;
33f4a2713aSLionel Sambuc
Indent()34f4a2713aSLionel Sambuc raw_ostream& Indent() { return Indent(Indentation); }
35f4a2713aSLionel Sambuc raw_ostream& Indent(unsigned Indentation);
36f4a2713aSLionel Sambuc void ProcessDeclGroup(SmallVectorImpl<Decl*>& Decls);
37f4a2713aSLionel Sambuc
38f4a2713aSLionel Sambuc void Print(AccessSpecifier AS);
39f4a2713aSLionel Sambuc
40f4a2713aSLionel Sambuc public:
DeclPrinter(raw_ostream & Out,const PrintingPolicy & Policy,unsigned Indentation=0,bool PrintInstantiation=false)41f4a2713aSLionel Sambuc DeclPrinter(raw_ostream &Out, const PrintingPolicy &Policy,
42f4a2713aSLionel Sambuc unsigned Indentation = 0, bool PrintInstantiation = false)
43f4a2713aSLionel Sambuc : Out(Out), Policy(Policy), Indentation(Indentation),
44f4a2713aSLionel Sambuc PrintInstantiation(PrintInstantiation) { }
45f4a2713aSLionel Sambuc
46f4a2713aSLionel Sambuc void VisitDeclContext(DeclContext *DC, bool Indent = true);
47f4a2713aSLionel Sambuc
48f4a2713aSLionel Sambuc void VisitTranslationUnitDecl(TranslationUnitDecl *D);
49f4a2713aSLionel Sambuc void VisitTypedefDecl(TypedefDecl *D);
50f4a2713aSLionel Sambuc void VisitTypeAliasDecl(TypeAliasDecl *D);
51f4a2713aSLionel Sambuc void VisitEnumDecl(EnumDecl *D);
52f4a2713aSLionel Sambuc void VisitRecordDecl(RecordDecl *D);
53f4a2713aSLionel Sambuc void VisitEnumConstantDecl(EnumConstantDecl *D);
54f4a2713aSLionel Sambuc void VisitEmptyDecl(EmptyDecl *D);
55f4a2713aSLionel Sambuc void VisitFunctionDecl(FunctionDecl *D);
56f4a2713aSLionel Sambuc void VisitFriendDecl(FriendDecl *D);
57f4a2713aSLionel Sambuc void VisitFieldDecl(FieldDecl *D);
58f4a2713aSLionel Sambuc void VisitVarDecl(VarDecl *D);
59f4a2713aSLionel Sambuc void VisitLabelDecl(LabelDecl *D);
60f4a2713aSLionel Sambuc void VisitParmVarDecl(ParmVarDecl *D);
61f4a2713aSLionel Sambuc void VisitFileScopeAsmDecl(FileScopeAsmDecl *D);
62f4a2713aSLionel Sambuc void VisitImportDecl(ImportDecl *D);
63f4a2713aSLionel Sambuc void VisitStaticAssertDecl(StaticAssertDecl *D);
64f4a2713aSLionel Sambuc void VisitNamespaceDecl(NamespaceDecl *D);
65f4a2713aSLionel Sambuc void VisitUsingDirectiveDecl(UsingDirectiveDecl *D);
66f4a2713aSLionel Sambuc void VisitNamespaceAliasDecl(NamespaceAliasDecl *D);
67f4a2713aSLionel Sambuc void VisitCXXRecordDecl(CXXRecordDecl *D);
68f4a2713aSLionel Sambuc void VisitLinkageSpecDecl(LinkageSpecDecl *D);
69f4a2713aSLionel Sambuc void VisitTemplateDecl(const TemplateDecl *D);
70f4a2713aSLionel Sambuc void VisitFunctionTemplateDecl(FunctionTemplateDecl *D);
71f4a2713aSLionel Sambuc void VisitClassTemplateDecl(ClassTemplateDecl *D);
72f4a2713aSLionel Sambuc void VisitObjCMethodDecl(ObjCMethodDecl *D);
73f4a2713aSLionel Sambuc void VisitObjCImplementationDecl(ObjCImplementationDecl *D);
74f4a2713aSLionel Sambuc void VisitObjCInterfaceDecl(ObjCInterfaceDecl *D);
75f4a2713aSLionel Sambuc void VisitObjCProtocolDecl(ObjCProtocolDecl *D);
76f4a2713aSLionel Sambuc void VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D);
77f4a2713aSLionel Sambuc void VisitObjCCategoryDecl(ObjCCategoryDecl *D);
78f4a2713aSLionel Sambuc void VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *D);
79f4a2713aSLionel Sambuc void VisitObjCPropertyDecl(ObjCPropertyDecl *D);
80f4a2713aSLionel Sambuc void VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D);
81f4a2713aSLionel Sambuc void VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D);
82f4a2713aSLionel Sambuc void VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D);
83f4a2713aSLionel Sambuc void VisitUsingDecl(UsingDecl *D);
84f4a2713aSLionel Sambuc void VisitUsingShadowDecl(UsingShadowDecl *D);
85f4a2713aSLionel Sambuc void VisitOMPThreadPrivateDecl(OMPThreadPrivateDecl *D);
86f4a2713aSLionel Sambuc
87f4a2713aSLionel Sambuc void PrintTemplateParameters(const TemplateParameterList *Params,
88*0a6a1f1dSLionel Sambuc const TemplateArgumentList *Args = nullptr);
89f4a2713aSLionel Sambuc void prettyPrintAttributes(Decl *D);
90*0a6a1f1dSLionel Sambuc void printDeclType(QualType T, StringRef DeclName, bool Pack = false);
91f4a2713aSLionel Sambuc };
92f4a2713aSLionel Sambuc }
93f4a2713aSLionel Sambuc
print(raw_ostream & Out,unsigned Indentation,bool PrintInstantiation) const94f4a2713aSLionel Sambuc void Decl::print(raw_ostream &Out, unsigned Indentation,
95f4a2713aSLionel Sambuc bool PrintInstantiation) const {
96f4a2713aSLionel Sambuc print(Out, getASTContext().getPrintingPolicy(), Indentation, PrintInstantiation);
97f4a2713aSLionel Sambuc }
98f4a2713aSLionel Sambuc
print(raw_ostream & Out,const PrintingPolicy & Policy,unsigned Indentation,bool PrintInstantiation) const99f4a2713aSLionel Sambuc void Decl::print(raw_ostream &Out, const PrintingPolicy &Policy,
100f4a2713aSLionel Sambuc unsigned Indentation, bool PrintInstantiation) const {
101f4a2713aSLionel Sambuc DeclPrinter Printer(Out, Policy, Indentation, PrintInstantiation);
102f4a2713aSLionel Sambuc Printer.Visit(const_cast<Decl*>(this));
103f4a2713aSLionel Sambuc }
104f4a2713aSLionel Sambuc
GetBaseType(QualType T)105f4a2713aSLionel Sambuc static QualType GetBaseType(QualType T) {
106f4a2713aSLionel Sambuc // FIXME: This should be on the Type class!
107f4a2713aSLionel Sambuc QualType BaseType = T;
108f4a2713aSLionel Sambuc while (!BaseType->isSpecifierType()) {
109f4a2713aSLionel Sambuc if (isa<TypedefType>(BaseType))
110f4a2713aSLionel Sambuc break;
111f4a2713aSLionel Sambuc else if (const PointerType* PTy = BaseType->getAs<PointerType>())
112f4a2713aSLionel Sambuc BaseType = PTy->getPointeeType();
113f4a2713aSLionel Sambuc else if (const BlockPointerType *BPy = BaseType->getAs<BlockPointerType>())
114f4a2713aSLionel Sambuc BaseType = BPy->getPointeeType();
115f4a2713aSLionel Sambuc else if (const ArrayType* ATy = dyn_cast<ArrayType>(BaseType))
116f4a2713aSLionel Sambuc BaseType = ATy->getElementType();
117f4a2713aSLionel Sambuc else if (const FunctionType* FTy = BaseType->getAs<FunctionType>())
118*0a6a1f1dSLionel Sambuc BaseType = FTy->getReturnType();
119f4a2713aSLionel Sambuc else if (const VectorType *VTy = BaseType->getAs<VectorType>())
120f4a2713aSLionel Sambuc BaseType = VTy->getElementType();
121f4a2713aSLionel Sambuc else if (const ReferenceType *RTy = BaseType->getAs<ReferenceType>())
122f4a2713aSLionel Sambuc BaseType = RTy->getPointeeType();
123f4a2713aSLionel Sambuc else
124f4a2713aSLionel Sambuc llvm_unreachable("Unknown declarator!");
125f4a2713aSLionel Sambuc }
126f4a2713aSLionel Sambuc return BaseType;
127f4a2713aSLionel Sambuc }
128f4a2713aSLionel Sambuc
getDeclType(Decl * D)129f4a2713aSLionel Sambuc static QualType getDeclType(Decl* D) {
130f4a2713aSLionel Sambuc if (TypedefNameDecl* TDD = dyn_cast<TypedefNameDecl>(D))
131f4a2713aSLionel Sambuc return TDD->getUnderlyingType();
132f4a2713aSLionel Sambuc if (ValueDecl* VD = dyn_cast<ValueDecl>(D))
133f4a2713aSLionel Sambuc return VD->getType();
134f4a2713aSLionel Sambuc return QualType();
135f4a2713aSLionel Sambuc }
136f4a2713aSLionel Sambuc
printGroup(Decl ** Begin,unsigned NumDecls,raw_ostream & Out,const PrintingPolicy & Policy,unsigned Indentation)137f4a2713aSLionel Sambuc void Decl::printGroup(Decl** Begin, unsigned NumDecls,
138f4a2713aSLionel Sambuc raw_ostream &Out, const PrintingPolicy &Policy,
139f4a2713aSLionel Sambuc unsigned Indentation) {
140f4a2713aSLionel Sambuc if (NumDecls == 1) {
141f4a2713aSLionel Sambuc (*Begin)->print(Out, Policy, Indentation);
142f4a2713aSLionel Sambuc return;
143f4a2713aSLionel Sambuc }
144f4a2713aSLionel Sambuc
145f4a2713aSLionel Sambuc Decl** End = Begin + NumDecls;
146f4a2713aSLionel Sambuc TagDecl* TD = dyn_cast<TagDecl>(*Begin);
147f4a2713aSLionel Sambuc if (TD)
148f4a2713aSLionel Sambuc ++Begin;
149f4a2713aSLionel Sambuc
150f4a2713aSLionel Sambuc PrintingPolicy SubPolicy(Policy);
151f4a2713aSLionel Sambuc if (TD && TD->isCompleteDefinition()) {
152f4a2713aSLionel Sambuc TD->print(Out, Policy, Indentation);
153f4a2713aSLionel Sambuc Out << " ";
154f4a2713aSLionel Sambuc SubPolicy.SuppressTag = true;
155f4a2713aSLionel Sambuc }
156f4a2713aSLionel Sambuc
157f4a2713aSLionel Sambuc bool isFirst = true;
158f4a2713aSLionel Sambuc for ( ; Begin != End; ++Begin) {
159f4a2713aSLionel Sambuc if (isFirst) {
160f4a2713aSLionel Sambuc SubPolicy.SuppressSpecifiers = false;
161f4a2713aSLionel Sambuc isFirst = false;
162f4a2713aSLionel Sambuc } else {
163f4a2713aSLionel Sambuc if (!isFirst) Out << ", ";
164f4a2713aSLionel Sambuc SubPolicy.SuppressSpecifiers = true;
165f4a2713aSLionel Sambuc }
166f4a2713aSLionel Sambuc
167f4a2713aSLionel Sambuc (*Begin)->print(Out, SubPolicy, Indentation);
168f4a2713aSLionel Sambuc }
169f4a2713aSLionel Sambuc }
170f4a2713aSLionel Sambuc
dumpDeclContext() const171*0a6a1f1dSLionel Sambuc LLVM_DUMP_METHOD void DeclContext::dumpDeclContext() const {
172f4a2713aSLionel Sambuc // Get the translation unit
173f4a2713aSLionel Sambuc const DeclContext *DC = this;
174f4a2713aSLionel Sambuc while (!DC->isTranslationUnit())
175f4a2713aSLionel Sambuc DC = DC->getParent();
176f4a2713aSLionel Sambuc
177f4a2713aSLionel Sambuc ASTContext &Ctx = cast<TranslationUnitDecl>(DC)->getASTContext();
178f4a2713aSLionel Sambuc DeclPrinter Printer(llvm::errs(), Ctx.getPrintingPolicy(), 0);
179f4a2713aSLionel Sambuc Printer.VisitDeclContext(const_cast<DeclContext *>(this), /*Indent=*/false);
180f4a2713aSLionel Sambuc }
181f4a2713aSLionel Sambuc
Indent(unsigned Indentation)182f4a2713aSLionel Sambuc raw_ostream& DeclPrinter::Indent(unsigned Indentation) {
183f4a2713aSLionel Sambuc for (unsigned i = 0; i != Indentation; ++i)
184f4a2713aSLionel Sambuc Out << " ";
185f4a2713aSLionel Sambuc return Out;
186f4a2713aSLionel Sambuc }
187f4a2713aSLionel Sambuc
prettyPrintAttributes(Decl * D)188f4a2713aSLionel Sambuc void DeclPrinter::prettyPrintAttributes(Decl *D) {
189f4a2713aSLionel Sambuc if (Policy.PolishForDeclaration)
190f4a2713aSLionel Sambuc return;
191f4a2713aSLionel Sambuc
192f4a2713aSLionel Sambuc if (D->hasAttrs()) {
193f4a2713aSLionel Sambuc AttrVec &Attrs = D->getAttrs();
194f4a2713aSLionel Sambuc for (AttrVec::const_iterator i=Attrs.begin(), e=Attrs.end(); i!=e; ++i) {
195f4a2713aSLionel Sambuc Attr *A = *i;
196f4a2713aSLionel Sambuc A->printPretty(Out, Policy);
197f4a2713aSLionel Sambuc }
198f4a2713aSLionel Sambuc }
199f4a2713aSLionel Sambuc }
200f4a2713aSLionel Sambuc
printDeclType(QualType T,StringRef DeclName,bool Pack)201*0a6a1f1dSLionel Sambuc void DeclPrinter::printDeclType(QualType T, StringRef DeclName, bool Pack) {
202*0a6a1f1dSLionel Sambuc // Normally, a PackExpansionType is written as T[3]... (for instance, as a
203*0a6a1f1dSLionel Sambuc // template argument), but if it is the type of a declaration, the ellipsis
204*0a6a1f1dSLionel Sambuc // is placed before the name being declared.
205*0a6a1f1dSLionel Sambuc if (auto *PET = T->getAs<PackExpansionType>()) {
206*0a6a1f1dSLionel Sambuc Pack = true;
207*0a6a1f1dSLionel Sambuc T = PET->getPattern();
208*0a6a1f1dSLionel Sambuc }
209*0a6a1f1dSLionel Sambuc T.print(Out, Policy, (Pack ? "..." : "") + DeclName);
210*0a6a1f1dSLionel Sambuc }
211*0a6a1f1dSLionel Sambuc
ProcessDeclGroup(SmallVectorImpl<Decl * > & Decls)212f4a2713aSLionel Sambuc void DeclPrinter::ProcessDeclGroup(SmallVectorImpl<Decl*>& Decls) {
213f4a2713aSLionel Sambuc this->Indent();
214f4a2713aSLionel Sambuc Decl::printGroup(Decls.data(), Decls.size(), Out, Policy, Indentation);
215f4a2713aSLionel Sambuc Out << ";\n";
216f4a2713aSLionel Sambuc Decls.clear();
217f4a2713aSLionel Sambuc
218f4a2713aSLionel Sambuc }
219f4a2713aSLionel Sambuc
Print(AccessSpecifier AS)220f4a2713aSLionel Sambuc void DeclPrinter::Print(AccessSpecifier AS) {
221f4a2713aSLionel Sambuc switch(AS) {
222f4a2713aSLionel Sambuc case AS_none: llvm_unreachable("No access specifier!");
223f4a2713aSLionel Sambuc case AS_public: Out << "public"; break;
224f4a2713aSLionel Sambuc case AS_protected: Out << "protected"; break;
225f4a2713aSLionel Sambuc case AS_private: Out << "private"; break;
226f4a2713aSLionel Sambuc }
227f4a2713aSLionel Sambuc }
228f4a2713aSLionel Sambuc
229f4a2713aSLionel Sambuc //----------------------------------------------------------------------------
230f4a2713aSLionel Sambuc // Common C declarations
231f4a2713aSLionel Sambuc //----------------------------------------------------------------------------
232f4a2713aSLionel Sambuc
VisitDeclContext(DeclContext * DC,bool Indent)233f4a2713aSLionel Sambuc void DeclPrinter::VisitDeclContext(DeclContext *DC, bool Indent) {
234f4a2713aSLionel Sambuc if (Policy.TerseOutput)
235f4a2713aSLionel Sambuc return;
236f4a2713aSLionel Sambuc
237f4a2713aSLionel Sambuc if (Indent)
238f4a2713aSLionel Sambuc Indentation += Policy.Indentation;
239f4a2713aSLionel Sambuc
240f4a2713aSLionel Sambuc SmallVector<Decl*, 2> Decls;
241f4a2713aSLionel Sambuc for (DeclContext::decl_iterator D = DC->decls_begin(), DEnd = DC->decls_end();
242f4a2713aSLionel Sambuc D != DEnd; ++D) {
243f4a2713aSLionel Sambuc
244f4a2713aSLionel Sambuc // Don't print ObjCIvarDecls, as they are printed when visiting the
245f4a2713aSLionel Sambuc // containing ObjCInterfaceDecl.
246f4a2713aSLionel Sambuc if (isa<ObjCIvarDecl>(*D))
247f4a2713aSLionel Sambuc continue;
248f4a2713aSLionel Sambuc
249f4a2713aSLionel Sambuc // Skip over implicit declarations in pretty-printing mode.
250f4a2713aSLionel Sambuc if (D->isImplicit())
251f4a2713aSLionel Sambuc continue;
252f4a2713aSLionel Sambuc
253f4a2713aSLionel Sambuc // The next bits of code handles stuff like "struct {int x;} a,b"; we're
254f4a2713aSLionel Sambuc // forced to merge the declarations because there's no other way to
255f4a2713aSLionel Sambuc // refer to the struct in question. This limited merging is safe without
256f4a2713aSLionel Sambuc // a bunch of other checks because it only merges declarations directly
257f4a2713aSLionel Sambuc // referring to the tag, not typedefs.
258f4a2713aSLionel Sambuc //
259f4a2713aSLionel Sambuc // Check whether the current declaration should be grouped with a previous
260f4a2713aSLionel Sambuc // unnamed struct.
261f4a2713aSLionel Sambuc QualType CurDeclType = getDeclType(*D);
262f4a2713aSLionel Sambuc if (!Decls.empty() && !CurDeclType.isNull()) {
263f4a2713aSLionel Sambuc QualType BaseType = GetBaseType(CurDeclType);
264f4a2713aSLionel Sambuc if (!BaseType.isNull() && isa<ElaboratedType>(BaseType))
265f4a2713aSLionel Sambuc BaseType = cast<ElaboratedType>(BaseType)->getNamedType();
266f4a2713aSLionel Sambuc if (!BaseType.isNull() && isa<TagType>(BaseType) &&
267f4a2713aSLionel Sambuc cast<TagType>(BaseType)->getDecl() == Decls[0]) {
268f4a2713aSLionel Sambuc Decls.push_back(*D);
269f4a2713aSLionel Sambuc continue;
270f4a2713aSLionel Sambuc }
271f4a2713aSLionel Sambuc }
272f4a2713aSLionel Sambuc
273f4a2713aSLionel Sambuc // If we have a merged group waiting to be handled, handle it now.
274f4a2713aSLionel Sambuc if (!Decls.empty())
275f4a2713aSLionel Sambuc ProcessDeclGroup(Decls);
276f4a2713aSLionel Sambuc
277f4a2713aSLionel Sambuc // If the current declaration is an unnamed tag type, save it
278f4a2713aSLionel Sambuc // so we can merge it with the subsequent declaration(s) using it.
279f4a2713aSLionel Sambuc if (isa<TagDecl>(*D) && !cast<TagDecl>(*D)->getIdentifier()) {
280f4a2713aSLionel Sambuc Decls.push_back(*D);
281f4a2713aSLionel Sambuc continue;
282f4a2713aSLionel Sambuc }
283f4a2713aSLionel Sambuc
284f4a2713aSLionel Sambuc if (isa<AccessSpecDecl>(*D)) {
285f4a2713aSLionel Sambuc Indentation -= Policy.Indentation;
286f4a2713aSLionel Sambuc this->Indent();
287f4a2713aSLionel Sambuc Print(D->getAccess());
288f4a2713aSLionel Sambuc Out << ":\n";
289f4a2713aSLionel Sambuc Indentation += Policy.Indentation;
290f4a2713aSLionel Sambuc continue;
291f4a2713aSLionel Sambuc }
292f4a2713aSLionel Sambuc
293f4a2713aSLionel Sambuc this->Indent();
294f4a2713aSLionel Sambuc Visit(*D);
295f4a2713aSLionel Sambuc
296f4a2713aSLionel Sambuc // FIXME: Need to be able to tell the DeclPrinter when
297*0a6a1f1dSLionel Sambuc const char *Terminator = nullptr;
298f4a2713aSLionel Sambuc if (isa<OMPThreadPrivateDecl>(*D))
299*0a6a1f1dSLionel Sambuc Terminator = nullptr;
300f4a2713aSLionel Sambuc else if (isa<FunctionDecl>(*D) &&
301f4a2713aSLionel Sambuc cast<FunctionDecl>(*D)->isThisDeclarationADefinition())
302*0a6a1f1dSLionel Sambuc Terminator = nullptr;
303f4a2713aSLionel Sambuc else if (isa<ObjCMethodDecl>(*D) && cast<ObjCMethodDecl>(*D)->getBody())
304*0a6a1f1dSLionel Sambuc Terminator = nullptr;
305f4a2713aSLionel Sambuc else if (isa<NamespaceDecl>(*D) || isa<LinkageSpecDecl>(*D) ||
306f4a2713aSLionel Sambuc isa<ObjCImplementationDecl>(*D) ||
307f4a2713aSLionel Sambuc isa<ObjCInterfaceDecl>(*D) ||
308f4a2713aSLionel Sambuc isa<ObjCProtocolDecl>(*D) ||
309f4a2713aSLionel Sambuc isa<ObjCCategoryImplDecl>(*D) ||
310f4a2713aSLionel Sambuc isa<ObjCCategoryDecl>(*D))
311*0a6a1f1dSLionel Sambuc Terminator = nullptr;
312f4a2713aSLionel Sambuc else if (isa<EnumConstantDecl>(*D)) {
313f4a2713aSLionel Sambuc DeclContext::decl_iterator Next = D;
314f4a2713aSLionel Sambuc ++Next;
315f4a2713aSLionel Sambuc if (Next != DEnd)
316f4a2713aSLionel Sambuc Terminator = ",";
317f4a2713aSLionel Sambuc } else
318f4a2713aSLionel Sambuc Terminator = ";";
319f4a2713aSLionel Sambuc
320f4a2713aSLionel Sambuc if (Terminator)
321f4a2713aSLionel Sambuc Out << Terminator;
322f4a2713aSLionel Sambuc Out << "\n";
323f4a2713aSLionel Sambuc }
324f4a2713aSLionel Sambuc
325f4a2713aSLionel Sambuc if (!Decls.empty())
326f4a2713aSLionel Sambuc ProcessDeclGroup(Decls);
327f4a2713aSLionel Sambuc
328f4a2713aSLionel Sambuc if (Indent)
329f4a2713aSLionel Sambuc Indentation -= Policy.Indentation;
330f4a2713aSLionel Sambuc }
331f4a2713aSLionel Sambuc
VisitTranslationUnitDecl(TranslationUnitDecl * D)332f4a2713aSLionel Sambuc void DeclPrinter::VisitTranslationUnitDecl(TranslationUnitDecl *D) {
333f4a2713aSLionel Sambuc VisitDeclContext(D, false);
334f4a2713aSLionel Sambuc }
335f4a2713aSLionel Sambuc
VisitTypedefDecl(TypedefDecl * D)336f4a2713aSLionel Sambuc void DeclPrinter::VisitTypedefDecl(TypedefDecl *D) {
337f4a2713aSLionel Sambuc if (!Policy.SuppressSpecifiers) {
338f4a2713aSLionel Sambuc Out << "typedef ";
339f4a2713aSLionel Sambuc
340f4a2713aSLionel Sambuc if (D->isModulePrivate())
341f4a2713aSLionel Sambuc Out << "__module_private__ ";
342f4a2713aSLionel Sambuc }
343f4a2713aSLionel Sambuc D->getTypeSourceInfo()->getType().print(Out, Policy, D->getName());
344f4a2713aSLionel Sambuc prettyPrintAttributes(D);
345f4a2713aSLionel Sambuc }
346f4a2713aSLionel Sambuc
VisitTypeAliasDecl(TypeAliasDecl * D)347f4a2713aSLionel Sambuc void DeclPrinter::VisitTypeAliasDecl(TypeAliasDecl *D) {
348f4a2713aSLionel Sambuc Out << "using " << *D;
349f4a2713aSLionel Sambuc prettyPrintAttributes(D);
350f4a2713aSLionel Sambuc Out << " = " << D->getTypeSourceInfo()->getType().getAsString(Policy);
351f4a2713aSLionel Sambuc }
352f4a2713aSLionel Sambuc
VisitEnumDecl(EnumDecl * D)353f4a2713aSLionel Sambuc void DeclPrinter::VisitEnumDecl(EnumDecl *D) {
354f4a2713aSLionel Sambuc if (!Policy.SuppressSpecifiers && D->isModulePrivate())
355f4a2713aSLionel Sambuc Out << "__module_private__ ";
356f4a2713aSLionel Sambuc Out << "enum ";
357f4a2713aSLionel Sambuc if (D->isScoped()) {
358f4a2713aSLionel Sambuc if (D->isScopedUsingClassTag())
359f4a2713aSLionel Sambuc Out << "class ";
360f4a2713aSLionel Sambuc else
361f4a2713aSLionel Sambuc Out << "struct ";
362f4a2713aSLionel Sambuc }
363f4a2713aSLionel Sambuc Out << *D;
364f4a2713aSLionel Sambuc
365f4a2713aSLionel Sambuc if (D->isFixed())
366f4a2713aSLionel Sambuc Out << " : " << D->getIntegerType().stream(Policy);
367f4a2713aSLionel Sambuc
368f4a2713aSLionel Sambuc if (D->isCompleteDefinition()) {
369f4a2713aSLionel Sambuc Out << " {\n";
370f4a2713aSLionel Sambuc VisitDeclContext(D);
371f4a2713aSLionel Sambuc Indent() << "}";
372f4a2713aSLionel Sambuc }
373f4a2713aSLionel Sambuc prettyPrintAttributes(D);
374f4a2713aSLionel Sambuc }
375f4a2713aSLionel Sambuc
VisitRecordDecl(RecordDecl * D)376f4a2713aSLionel Sambuc void DeclPrinter::VisitRecordDecl(RecordDecl *D) {
377f4a2713aSLionel Sambuc if (!Policy.SuppressSpecifiers && D->isModulePrivate())
378f4a2713aSLionel Sambuc Out << "__module_private__ ";
379f4a2713aSLionel Sambuc Out << D->getKindName();
380*0a6a1f1dSLionel Sambuc
381*0a6a1f1dSLionel Sambuc prettyPrintAttributes(D);
382*0a6a1f1dSLionel Sambuc
383f4a2713aSLionel Sambuc if (D->getIdentifier())
384f4a2713aSLionel Sambuc Out << ' ' << *D;
385f4a2713aSLionel Sambuc
386f4a2713aSLionel Sambuc if (D->isCompleteDefinition()) {
387f4a2713aSLionel Sambuc Out << " {\n";
388f4a2713aSLionel Sambuc VisitDeclContext(D);
389f4a2713aSLionel Sambuc Indent() << "}";
390f4a2713aSLionel Sambuc }
391f4a2713aSLionel Sambuc }
392f4a2713aSLionel Sambuc
VisitEnumConstantDecl(EnumConstantDecl * D)393f4a2713aSLionel Sambuc void DeclPrinter::VisitEnumConstantDecl(EnumConstantDecl *D) {
394f4a2713aSLionel Sambuc Out << *D;
395f4a2713aSLionel Sambuc if (Expr *Init = D->getInitExpr()) {
396f4a2713aSLionel Sambuc Out << " = ";
397*0a6a1f1dSLionel Sambuc Init->printPretty(Out, nullptr, Policy, Indentation);
398f4a2713aSLionel Sambuc }
399f4a2713aSLionel Sambuc }
400f4a2713aSLionel Sambuc
VisitFunctionDecl(FunctionDecl * D)401f4a2713aSLionel Sambuc void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
402f4a2713aSLionel Sambuc CXXConstructorDecl *CDecl = dyn_cast<CXXConstructorDecl>(D);
403*0a6a1f1dSLionel Sambuc CXXConversionDecl *ConversionDecl = dyn_cast<CXXConversionDecl>(D);
404f4a2713aSLionel Sambuc if (!Policy.SuppressSpecifiers) {
405f4a2713aSLionel Sambuc switch (D->getStorageClass()) {
406f4a2713aSLionel Sambuc case SC_None: break;
407f4a2713aSLionel Sambuc case SC_Extern: Out << "extern "; break;
408f4a2713aSLionel Sambuc case SC_Static: Out << "static "; break;
409f4a2713aSLionel Sambuc case SC_PrivateExtern: Out << "__private_extern__ "; break;
410f4a2713aSLionel Sambuc case SC_Auto: case SC_Register: case SC_OpenCLWorkGroupLocal:
411f4a2713aSLionel Sambuc llvm_unreachable("invalid for functions");
412f4a2713aSLionel Sambuc }
413f4a2713aSLionel Sambuc
414f4a2713aSLionel Sambuc if (D->isInlineSpecified()) Out << "inline ";
415f4a2713aSLionel Sambuc if (D->isVirtualAsWritten()) Out << "virtual ";
416f4a2713aSLionel Sambuc if (D->isModulePrivate()) Out << "__module_private__ ";
417*0a6a1f1dSLionel Sambuc if (D->isConstexpr() && !D->isExplicitlyDefaulted()) Out << "constexpr ";
418*0a6a1f1dSLionel Sambuc if ((CDecl && CDecl->isExplicitSpecified()) ||
419*0a6a1f1dSLionel Sambuc (ConversionDecl && ConversionDecl->isExplicit()))
420f4a2713aSLionel Sambuc Out << "explicit ";
421f4a2713aSLionel Sambuc }
422f4a2713aSLionel Sambuc
423f4a2713aSLionel Sambuc PrintingPolicy SubPolicy(Policy);
424f4a2713aSLionel Sambuc SubPolicy.SuppressSpecifiers = false;
425f4a2713aSLionel Sambuc std::string Proto = D->getNameInfo().getAsString();
426f4a2713aSLionel Sambuc
427f4a2713aSLionel Sambuc QualType Ty = D->getType();
428f4a2713aSLionel Sambuc while (const ParenType *PT = dyn_cast<ParenType>(Ty)) {
429f4a2713aSLionel Sambuc Proto = '(' + Proto + ')';
430f4a2713aSLionel Sambuc Ty = PT->getInnerType();
431f4a2713aSLionel Sambuc }
432f4a2713aSLionel Sambuc
433*0a6a1f1dSLionel Sambuc if (const FunctionType *AFT = Ty->getAs<FunctionType>()) {
434*0a6a1f1dSLionel Sambuc const FunctionProtoType *FT = nullptr;
435f4a2713aSLionel Sambuc if (D->hasWrittenPrototype())
436f4a2713aSLionel Sambuc FT = dyn_cast<FunctionProtoType>(AFT);
437f4a2713aSLionel Sambuc
438f4a2713aSLionel Sambuc Proto += "(";
439f4a2713aSLionel Sambuc if (FT) {
440f4a2713aSLionel Sambuc llvm::raw_string_ostream POut(Proto);
441f4a2713aSLionel Sambuc DeclPrinter ParamPrinter(POut, SubPolicy, Indentation);
442f4a2713aSLionel Sambuc for (unsigned i = 0, e = D->getNumParams(); i != e; ++i) {
443f4a2713aSLionel Sambuc if (i) POut << ", ";
444f4a2713aSLionel Sambuc ParamPrinter.VisitParmVarDecl(D->getParamDecl(i));
445f4a2713aSLionel Sambuc }
446f4a2713aSLionel Sambuc
447f4a2713aSLionel Sambuc if (FT->isVariadic()) {
448f4a2713aSLionel Sambuc if (D->getNumParams()) POut << ", ";
449f4a2713aSLionel Sambuc POut << "...";
450f4a2713aSLionel Sambuc }
451f4a2713aSLionel Sambuc } else if (D->doesThisDeclarationHaveABody() && !D->hasPrototype()) {
452f4a2713aSLionel Sambuc for (unsigned i = 0, e = D->getNumParams(); i != e; ++i) {
453f4a2713aSLionel Sambuc if (i)
454f4a2713aSLionel Sambuc Proto += ", ";
455f4a2713aSLionel Sambuc Proto += D->getParamDecl(i)->getNameAsString();
456f4a2713aSLionel Sambuc }
457f4a2713aSLionel Sambuc }
458f4a2713aSLionel Sambuc
459f4a2713aSLionel Sambuc Proto += ")";
460f4a2713aSLionel Sambuc
461f4a2713aSLionel Sambuc if (FT) {
462f4a2713aSLionel Sambuc if (FT->isConst())
463f4a2713aSLionel Sambuc Proto += " const";
464f4a2713aSLionel Sambuc if (FT->isVolatile())
465f4a2713aSLionel Sambuc Proto += " volatile";
466f4a2713aSLionel Sambuc if (FT->isRestrict())
467f4a2713aSLionel Sambuc Proto += " restrict";
468*0a6a1f1dSLionel Sambuc
469*0a6a1f1dSLionel Sambuc switch (FT->getRefQualifier()) {
470*0a6a1f1dSLionel Sambuc case RQ_None:
471*0a6a1f1dSLionel Sambuc break;
472*0a6a1f1dSLionel Sambuc case RQ_LValue:
473*0a6a1f1dSLionel Sambuc Proto += " &";
474*0a6a1f1dSLionel Sambuc break;
475*0a6a1f1dSLionel Sambuc case RQ_RValue:
476*0a6a1f1dSLionel Sambuc Proto += " &&";
477*0a6a1f1dSLionel Sambuc break;
478*0a6a1f1dSLionel Sambuc }
479f4a2713aSLionel Sambuc }
480f4a2713aSLionel Sambuc
481f4a2713aSLionel Sambuc if (FT && FT->hasDynamicExceptionSpec()) {
482f4a2713aSLionel Sambuc Proto += " throw(";
483f4a2713aSLionel Sambuc if (FT->getExceptionSpecType() == EST_MSAny)
484f4a2713aSLionel Sambuc Proto += "...";
485f4a2713aSLionel Sambuc else
486f4a2713aSLionel Sambuc for (unsigned I = 0, N = FT->getNumExceptions(); I != N; ++I) {
487f4a2713aSLionel Sambuc if (I)
488f4a2713aSLionel Sambuc Proto += ", ";
489f4a2713aSLionel Sambuc
490f4a2713aSLionel Sambuc Proto += FT->getExceptionType(I).getAsString(SubPolicy);
491f4a2713aSLionel Sambuc }
492f4a2713aSLionel Sambuc Proto += ")";
493f4a2713aSLionel Sambuc } else if (FT && isNoexceptExceptionSpec(FT->getExceptionSpecType())) {
494f4a2713aSLionel Sambuc Proto += " noexcept";
495f4a2713aSLionel Sambuc if (FT->getExceptionSpecType() == EST_ComputedNoexcept) {
496f4a2713aSLionel Sambuc Proto += "(";
497f4a2713aSLionel Sambuc llvm::raw_string_ostream EOut(Proto);
498*0a6a1f1dSLionel Sambuc FT->getNoexceptExpr()->printPretty(EOut, nullptr, SubPolicy,
499f4a2713aSLionel Sambuc Indentation);
500f4a2713aSLionel Sambuc EOut.flush();
501f4a2713aSLionel Sambuc Proto += EOut.str();
502f4a2713aSLionel Sambuc Proto += ")";
503f4a2713aSLionel Sambuc }
504f4a2713aSLionel Sambuc }
505f4a2713aSLionel Sambuc
506f4a2713aSLionel Sambuc if (CDecl) {
507f4a2713aSLionel Sambuc bool HasInitializerList = false;
508*0a6a1f1dSLionel Sambuc for (const auto *BMInitializer : CDecl->inits()) {
509f4a2713aSLionel Sambuc if (BMInitializer->isInClassMemberInitializer())
510f4a2713aSLionel Sambuc continue;
511f4a2713aSLionel Sambuc
512f4a2713aSLionel Sambuc if (!HasInitializerList) {
513f4a2713aSLionel Sambuc Proto += " : ";
514f4a2713aSLionel Sambuc Out << Proto;
515f4a2713aSLionel Sambuc Proto.clear();
516f4a2713aSLionel Sambuc HasInitializerList = true;
517f4a2713aSLionel Sambuc } else
518f4a2713aSLionel Sambuc Out << ", ";
519f4a2713aSLionel Sambuc
520f4a2713aSLionel Sambuc if (BMInitializer->isAnyMemberInitializer()) {
521f4a2713aSLionel Sambuc FieldDecl *FD = BMInitializer->getAnyMember();
522f4a2713aSLionel Sambuc Out << *FD;
523f4a2713aSLionel Sambuc } else {
524f4a2713aSLionel Sambuc Out << QualType(BMInitializer->getBaseClass(), 0).getAsString(Policy);
525f4a2713aSLionel Sambuc }
526f4a2713aSLionel Sambuc
527f4a2713aSLionel Sambuc Out << "(";
528f4a2713aSLionel Sambuc if (!BMInitializer->getInit()) {
529f4a2713aSLionel Sambuc // Nothing to print
530f4a2713aSLionel Sambuc } else {
531f4a2713aSLionel Sambuc Expr *Init = BMInitializer->getInit();
532f4a2713aSLionel Sambuc if (ExprWithCleanups *Tmp = dyn_cast<ExprWithCleanups>(Init))
533f4a2713aSLionel Sambuc Init = Tmp->getSubExpr();
534f4a2713aSLionel Sambuc
535f4a2713aSLionel Sambuc Init = Init->IgnoreParens();
536f4a2713aSLionel Sambuc
537*0a6a1f1dSLionel Sambuc Expr *SimpleInit = nullptr;
538*0a6a1f1dSLionel Sambuc Expr **Args = nullptr;
539f4a2713aSLionel Sambuc unsigned NumArgs = 0;
540f4a2713aSLionel Sambuc if (ParenListExpr *ParenList = dyn_cast<ParenListExpr>(Init)) {
541f4a2713aSLionel Sambuc Args = ParenList->getExprs();
542f4a2713aSLionel Sambuc NumArgs = ParenList->getNumExprs();
543f4a2713aSLionel Sambuc } else if (CXXConstructExpr *Construct
544f4a2713aSLionel Sambuc = dyn_cast<CXXConstructExpr>(Init)) {
545f4a2713aSLionel Sambuc Args = Construct->getArgs();
546f4a2713aSLionel Sambuc NumArgs = Construct->getNumArgs();
547f4a2713aSLionel Sambuc } else
548f4a2713aSLionel Sambuc SimpleInit = Init;
549f4a2713aSLionel Sambuc
550f4a2713aSLionel Sambuc if (SimpleInit)
551*0a6a1f1dSLionel Sambuc SimpleInit->printPretty(Out, nullptr, Policy, Indentation);
552f4a2713aSLionel Sambuc else {
553f4a2713aSLionel Sambuc for (unsigned I = 0; I != NumArgs; ++I) {
554*0a6a1f1dSLionel Sambuc assert(Args[I] != nullptr && "Expected non-null Expr");
555f4a2713aSLionel Sambuc if (isa<CXXDefaultArgExpr>(Args[I]))
556f4a2713aSLionel Sambuc break;
557f4a2713aSLionel Sambuc
558f4a2713aSLionel Sambuc if (I)
559f4a2713aSLionel Sambuc Out << ", ";
560*0a6a1f1dSLionel Sambuc Args[I]->printPretty(Out, nullptr, Policy, Indentation);
561f4a2713aSLionel Sambuc }
562f4a2713aSLionel Sambuc }
563f4a2713aSLionel Sambuc }
564f4a2713aSLionel Sambuc Out << ")";
565*0a6a1f1dSLionel Sambuc if (BMInitializer->isPackExpansion())
566*0a6a1f1dSLionel Sambuc Out << "...";
567f4a2713aSLionel Sambuc }
568*0a6a1f1dSLionel Sambuc } else if (!ConversionDecl && !isa<CXXDestructorDecl>(D)) {
569f4a2713aSLionel Sambuc if (FT && FT->hasTrailingReturn()) {
570f4a2713aSLionel Sambuc Out << "auto " << Proto << " -> ";
571f4a2713aSLionel Sambuc Proto.clear();
572f4a2713aSLionel Sambuc }
573*0a6a1f1dSLionel Sambuc AFT->getReturnType().print(Out, Policy, Proto);
574*0a6a1f1dSLionel Sambuc Proto.clear();
575f4a2713aSLionel Sambuc }
576*0a6a1f1dSLionel Sambuc Out << Proto;
577f4a2713aSLionel Sambuc } else {
578f4a2713aSLionel Sambuc Ty.print(Out, Policy, Proto);
579f4a2713aSLionel Sambuc }
580f4a2713aSLionel Sambuc
581f4a2713aSLionel Sambuc prettyPrintAttributes(D);
582f4a2713aSLionel Sambuc
583f4a2713aSLionel Sambuc if (D->isPure())
584f4a2713aSLionel Sambuc Out << " = 0";
585f4a2713aSLionel Sambuc else if (D->isDeletedAsWritten())
586f4a2713aSLionel Sambuc Out << " = delete";
587f4a2713aSLionel Sambuc else if (D->isExplicitlyDefaulted())
588f4a2713aSLionel Sambuc Out << " = default";
589f4a2713aSLionel Sambuc else if (D->doesThisDeclarationHaveABody() && !Policy.TerseOutput) {
590f4a2713aSLionel Sambuc if (!D->hasPrototype() && D->getNumParams()) {
591f4a2713aSLionel Sambuc // This is a K&R function definition, so we need to print the
592f4a2713aSLionel Sambuc // parameters.
593f4a2713aSLionel Sambuc Out << '\n';
594f4a2713aSLionel Sambuc DeclPrinter ParamPrinter(Out, SubPolicy, Indentation);
595f4a2713aSLionel Sambuc Indentation += Policy.Indentation;
596f4a2713aSLionel Sambuc for (unsigned i = 0, e = D->getNumParams(); i != e; ++i) {
597f4a2713aSLionel Sambuc Indent();
598f4a2713aSLionel Sambuc ParamPrinter.VisitParmVarDecl(D->getParamDecl(i));
599f4a2713aSLionel Sambuc Out << ";\n";
600f4a2713aSLionel Sambuc }
601f4a2713aSLionel Sambuc Indentation -= Policy.Indentation;
602f4a2713aSLionel Sambuc } else
603f4a2713aSLionel Sambuc Out << ' ';
604f4a2713aSLionel Sambuc
605*0a6a1f1dSLionel Sambuc if (D->getBody())
606*0a6a1f1dSLionel Sambuc D->getBody()->printPretty(Out, nullptr, SubPolicy, Indentation);
607f4a2713aSLionel Sambuc Out << '\n';
608f4a2713aSLionel Sambuc }
609f4a2713aSLionel Sambuc }
610f4a2713aSLionel Sambuc
VisitFriendDecl(FriendDecl * D)611f4a2713aSLionel Sambuc void DeclPrinter::VisitFriendDecl(FriendDecl *D) {
612f4a2713aSLionel Sambuc if (TypeSourceInfo *TSI = D->getFriendType()) {
613f4a2713aSLionel Sambuc unsigned NumTPLists = D->getFriendTypeNumTemplateParameterLists();
614f4a2713aSLionel Sambuc for (unsigned i = 0; i < NumTPLists; ++i)
615f4a2713aSLionel Sambuc PrintTemplateParameters(D->getFriendTypeTemplateParameterList(i));
616f4a2713aSLionel Sambuc Out << "friend ";
617f4a2713aSLionel Sambuc Out << " " << TSI->getType().getAsString(Policy);
618f4a2713aSLionel Sambuc }
619f4a2713aSLionel Sambuc else if (FunctionDecl *FD =
620f4a2713aSLionel Sambuc dyn_cast<FunctionDecl>(D->getFriendDecl())) {
621f4a2713aSLionel Sambuc Out << "friend ";
622f4a2713aSLionel Sambuc VisitFunctionDecl(FD);
623f4a2713aSLionel Sambuc }
624f4a2713aSLionel Sambuc else if (FunctionTemplateDecl *FTD =
625f4a2713aSLionel Sambuc dyn_cast<FunctionTemplateDecl>(D->getFriendDecl())) {
626f4a2713aSLionel Sambuc Out << "friend ";
627f4a2713aSLionel Sambuc VisitFunctionTemplateDecl(FTD);
628f4a2713aSLionel Sambuc }
629f4a2713aSLionel Sambuc else if (ClassTemplateDecl *CTD =
630f4a2713aSLionel Sambuc dyn_cast<ClassTemplateDecl>(D->getFriendDecl())) {
631f4a2713aSLionel Sambuc Out << "friend ";
632f4a2713aSLionel Sambuc VisitRedeclarableTemplateDecl(CTD);
633f4a2713aSLionel Sambuc }
634f4a2713aSLionel Sambuc }
635f4a2713aSLionel Sambuc
VisitFieldDecl(FieldDecl * D)636f4a2713aSLionel Sambuc void DeclPrinter::VisitFieldDecl(FieldDecl *D) {
637f4a2713aSLionel Sambuc if (!Policy.SuppressSpecifiers && D->isMutable())
638f4a2713aSLionel Sambuc Out << "mutable ";
639f4a2713aSLionel Sambuc if (!Policy.SuppressSpecifiers && D->isModulePrivate())
640f4a2713aSLionel Sambuc Out << "__module_private__ ";
641f4a2713aSLionel Sambuc
642f4a2713aSLionel Sambuc Out << D->getASTContext().getUnqualifiedObjCPointerType(D->getType()).
643f4a2713aSLionel Sambuc stream(Policy, D->getName());
644f4a2713aSLionel Sambuc
645f4a2713aSLionel Sambuc if (D->isBitField()) {
646f4a2713aSLionel Sambuc Out << " : ";
647*0a6a1f1dSLionel Sambuc D->getBitWidth()->printPretty(Out, nullptr, Policy, Indentation);
648f4a2713aSLionel Sambuc }
649f4a2713aSLionel Sambuc
650f4a2713aSLionel Sambuc Expr *Init = D->getInClassInitializer();
651f4a2713aSLionel Sambuc if (!Policy.SuppressInitializers && Init) {
652f4a2713aSLionel Sambuc if (D->getInClassInitStyle() == ICIS_ListInit)
653f4a2713aSLionel Sambuc Out << " ";
654f4a2713aSLionel Sambuc else
655f4a2713aSLionel Sambuc Out << " = ";
656*0a6a1f1dSLionel Sambuc Init->printPretty(Out, nullptr, Policy, Indentation);
657f4a2713aSLionel Sambuc }
658f4a2713aSLionel Sambuc prettyPrintAttributes(D);
659f4a2713aSLionel Sambuc }
660f4a2713aSLionel Sambuc
VisitLabelDecl(LabelDecl * D)661f4a2713aSLionel Sambuc void DeclPrinter::VisitLabelDecl(LabelDecl *D) {
662f4a2713aSLionel Sambuc Out << *D << ":";
663f4a2713aSLionel Sambuc }
664f4a2713aSLionel Sambuc
VisitVarDecl(VarDecl * D)665f4a2713aSLionel Sambuc void DeclPrinter::VisitVarDecl(VarDecl *D) {
666f4a2713aSLionel Sambuc if (!Policy.SuppressSpecifiers) {
667f4a2713aSLionel Sambuc StorageClass SC = D->getStorageClass();
668f4a2713aSLionel Sambuc if (SC != SC_None)
669f4a2713aSLionel Sambuc Out << VarDecl::getStorageClassSpecifierString(SC) << " ";
670f4a2713aSLionel Sambuc
671f4a2713aSLionel Sambuc switch (D->getTSCSpec()) {
672f4a2713aSLionel Sambuc case TSCS_unspecified:
673f4a2713aSLionel Sambuc break;
674f4a2713aSLionel Sambuc case TSCS___thread:
675f4a2713aSLionel Sambuc Out << "__thread ";
676f4a2713aSLionel Sambuc break;
677f4a2713aSLionel Sambuc case TSCS__Thread_local:
678f4a2713aSLionel Sambuc Out << "_Thread_local ";
679f4a2713aSLionel Sambuc break;
680f4a2713aSLionel Sambuc case TSCS_thread_local:
681f4a2713aSLionel Sambuc Out << "thread_local ";
682f4a2713aSLionel Sambuc break;
683f4a2713aSLionel Sambuc }
684f4a2713aSLionel Sambuc
685f4a2713aSLionel Sambuc if (D->isModulePrivate())
686f4a2713aSLionel Sambuc Out << "__module_private__ ";
687f4a2713aSLionel Sambuc }
688f4a2713aSLionel Sambuc
689f4a2713aSLionel Sambuc QualType T = D->getTypeSourceInfo()
690f4a2713aSLionel Sambuc ? D->getTypeSourceInfo()->getType()
691f4a2713aSLionel Sambuc : D->getASTContext().getUnqualifiedObjCPointerType(D->getType());
692*0a6a1f1dSLionel Sambuc printDeclType(T, D->getName());
693f4a2713aSLionel Sambuc Expr *Init = D->getInit();
694f4a2713aSLionel Sambuc if (!Policy.SuppressInitializers && Init) {
695f4a2713aSLionel Sambuc bool ImplicitInit = false;
696f4a2713aSLionel Sambuc if (CXXConstructExpr *Construct =
697f4a2713aSLionel Sambuc dyn_cast<CXXConstructExpr>(Init->IgnoreImplicit())) {
698f4a2713aSLionel Sambuc if (D->getInitStyle() == VarDecl::CallInit &&
699f4a2713aSLionel Sambuc !Construct->isListInitialization()) {
700f4a2713aSLionel Sambuc ImplicitInit = Construct->getNumArgs() == 0 ||
701f4a2713aSLionel Sambuc Construct->getArg(0)->isDefaultArgument();
702f4a2713aSLionel Sambuc }
703f4a2713aSLionel Sambuc }
704f4a2713aSLionel Sambuc if (!ImplicitInit) {
705f4a2713aSLionel Sambuc if ((D->getInitStyle() == VarDecl::CallInit) && !isa<ParenListExpr>(Init))
706f4a2713aSLionel Sambuc Out << "(";
707f4a2713aSLionel Sambuc else if (D->getInitStyle() == VarDecl::CInit) {
708f4a2713aSLionel Sambuc Out << " = ";
709f4a2713aSLionel Sambuc }
710*0a6a1f1dSLionel Sambuc Init->printPretty(Out, nullptr, Policy, Indentation);
711f4a2713aSLionel Sambuc if ((D->getInitStyle() == VarDecl::CallInit) && !isa<ParenListExpr>(Init))
712f4a2713aSLionel Sambuc Out << ")";
713f4a2713aSLionel Sambuc }
714f4a2713aSLionel Sambuc }
715f4a2713aSLionel Sambuc prettyPrintAttributes(D);
716f4a2713aSLionel Sambuc }
717f4a2713aSLionel Sambuc
VisitParmVarDecl(ParmVarDecl * D)718f4a2713aSLionel Sambuc void DeclPrinter::VisitParmVarDecl(ParmVarDecl *D) {
719f4a2713aSLionel Sambuc VisitVarDecl(D);
720f4a2713aSLionel Sambuc }
721f4a2713aSLionel Sambuc
VisitFileScopeAsmDecl(FileScopeAsmDecl * D)722f4a2713aSLionel Sambuc void DeclPrinter::VisitFileScopeAsmDecl(FileScopeAsmDecl *D) {
723f4a2713aSLionel Sambuc Out << "__asm (";
724*0a6a1f1dSLionel Sambuc D->getAsmString()->printPretty(Out, nullptr, Policy, Indentation);
725f4a2713aSLionel Sambuc Out << ")";
726f4a2713aSLionel Sambuc }
727f4a2713aSLionel Sambuc
VisitImportDecl(ImportDecl * D)728f4a2713aSLionel Sambuc void DeclPrinter::VisitImportDecl(ImportDecl *D) {
729f4a2713aSLionel Sambuc Out << "@import " << D->getImportedModule()->getFullModuleName()
730f4a2713aSLionel Sambuc << ";\n";
731f4a2713aSLionel Sambuc }
732f4a2713aSLionel Sambuc
VisitStaticAssertDecl(StaticAssertDecl * D)733f4a2713aSLionel Sambuc void DeclPrinter::VisitStaticAssertDecl(StaticAssertDecl *D) {
734f4a2713aSLionel Sambuc Out << "static_assert(";
735*0a6a1f1dSLionel Sambuc D->getAssertExpr()->printPretty(Out, nullptr, Policy, Indentation);
736f4a2713aSLionel Sambuc Out << ", ";
737*0a6a1f1dSLionel Sambuc D->getMessage()->printPretty(Out, nullptr, Policy, Indentation);
738f4a2713aSLionel Sambuc Out << ")";
739f4a2713aSLionel Sambuc }
740f4a2713aSLionel Sambuc
741f4a2713aSLionel Sambuc //----------------------------------------------------------------------------
742f4a2713aSLionel Sambuc // C++ declarations
743f4a2713aSLionel Sambuc //----------------------------------------------------------------------------
VisitNamespaceDecl(NamespaceDecl * D)744f4a2713aSLionel Sambuc void DeclPrinter::VisitNamespaceDecl(NamespaceDecl *D) {
745f4a2713aSLionel Sambuc if (D->isInline())
746f4a2713aSLionel Sambuc Out << "inline ";
747f4a2713aSLionel Sambuc Out << "namespace " << *D << " {\n";
748f4a2713aSLionel Sambuc VisitDeclContext(D);
749f4a2713aSLionel Sambuc Indent() << "}";
750f4a2713aSLionel Sambuc }
751f4a2713aSLionel Sambuc
VisitUsingDirectiveDecl(UsingDirectiveDecl * D)752f4a2713aSLionel Sambuc void DeclPrinter::VisitUsingDirectiveDecl(UsingDirectiveDecl *D) {
753f4a2713aSLionel Sambuc Out << "using namespace ";
754f4a2713aSLionel Sambuc if (D->getQualifier())
755f4a2713aSLionel Sambuc D->getQualifier()->print(Out, Policy);
756f4a2713aSLionel Sambuc Out << *D->getNominatedNamespaceAsWritten();
757f4a2713aSLionel Sambuc }
758f4a2713aSLionel Sambuc
VisitNamespaceAliasDecl(NamespaceAliasDecl * D)759f4a2713aSLionel Sambuc void DeclPrinter::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) {
760f4a2713aSLionel Sambuc Out << "namespace " << *D << " = ";
761f4a2713aSLionel Sambuc if (D->getQualifier())
762f4a2713aSLionel Sambuc D->getQualifier()->print(Out, Policy);
763f4a2713aSLionel Sambuc Out << *D->getAliasedNamespace();
764f4a2713aSLionel Sambuc }
765f4a2713aSLionel Sambuc
VisitEmptyDecl(EmptyDecl * D)766f4a2713aSLionel Sambuc void DeclPrinter::VisitEmptyDecl(EmptyDecl *D) {
767f4a2713aSLionel Sambuc prettyPrintAttributes(D);
768f4a2713aSLionel Sambuc }
769f4a2713aSLionel Sambuc
VisitCXXRecordDecl(CXXRecordDecl * D)770f4a2713aSLionel Sambuc void DeclPrinter::VisitCXXRecordDecl(CXXRecordDecl *D) {
771f4a2713aSLionel Sambuc if (!Policy.SuppressSpecifiers && D->isModulePrivate())
772f4a2713aSLionel Sambuc Out << "__module_private__ ";
773f4a2713aSLionel Sambuc Out << D->getKindName();
774*0a6a1f1dSLionel Sambuc
775*0a6a1f1dSLionel Sambuc prettyPrintAttributes(D);
776*0a6a1f1dSLionel Sambuc
777f4a2713aSLionel Sambuc if (D->getIdentifier())
778f4a2713aSLionel Sambuc Out << ' ' << *D;
779f4a2713aSLionel Sambuc
780f4a2713aSLionel Sambuc if (D->isCompleteDefinition()) {
781f4a2713aSLionel Sambuc // Print the base classes
782f4a2713aSLionel Sambuc if (D->getNumBases()) {
783f4a2713aSLionel Sambuc Out << " : ";
784f4a2713aSLionel Sambuc for (CXXRecordDecl::base_class_iterator Base = D->bases_begin(),
785f4a2713aSLionel Sambuc BaseEnd = D->bases_end(); Base != BaseEnd; ++Base) {
786f4a2713aSLionel Sambuc if (Base != D->bases_begin())
787f4a2713aSLionel Sambuc Out << ", ";
788f4a2713aSLionel Sambuc
789f4a2713aSLionel Sambuc if (Base->isVirtual())
790f4a2713aSLionel Sambuc Out << "virtual ";
791f4a2713aSLionel Sambuc
792f4a2713aSLionel Sambuc AccessSpecifier AS = Base->getAccessSpecifierAsWritten();
793*0a6a1f1dSLionel Sambuc if (AS != AS_none) {
794f4a2713aSLionel Sambuc Print(AS);
795*0a6a1f1dSLionel Sambuc Out << " ";
796*0a6a1f1dSLionel Sambuc }
797*0a6a1f1dSLionel Sambuc Out << Base->getType().getAsString(Policy);
798f4a2713aSLionel Sambuc
799f4a2713aSLionel Sambuc if (Base->isPackExpansion())
800f4a2713aSLionel Sambuc Out << "...";
801f4a2713aSLionel Sambuc }
802f4a2713aSLionel Sambuc }
803f4a2713aSLionel Sambuc
804f4a2713aSLionel Sambuc // Print the class definition
805f4a2713aSLionel Sambuc // FIXME: Doesn't print access specifiers, e.g., "public:"
806f4a2713aSLionel Sambuc Out << " {\n";
807f4a2713aSLionel Sambuc VisitDeclContext(D);
808f4a2713aSLionel Sambuc Indent() << "}";
809f4a2713aSLionel Sambuc }
810f4a2713aSLionel Sambuc }
811f4a2713aSLionel Sambuc
VisitLinkageSpecDecl(LinkageSpecDecl * D)812f4a2713aSLionel Sambuc void DeclPrinter::VisitLinkageSpecDecl(LinkageSpecDecl *D) {
813f4a2713aSLionel Sambuc const char *l;
814f4a2713aSLionel Sambuc if (D->getLanguage() == LinkageSpecDecl::lang_c)
815f4a2713aSLionel Sambuc l = "C";
816f4a2713aSLionel Sambuc else {
817f4a2713aSLionel Sambuc assert(D->getLanguage() == LinkageSpecDecl::lang_cxx &&
818f4a2713aSLionel Sambuc "unknown language in linkage specification");
819f4a2713aSLionel Sambuc l = "C++";
820f4a2713aSLionel Sambuc }
821f4a2713aSLionel Sambuc
822f4a2713aSLionel Sambuc Out << "extern \"" << l << "\" ";
823f4a2713aSLionel Sambuc if (D->hasBraces()) {
824f4a2713aSLionel Sambuc Out << "{\n";
825f4a2713aSLionel Sambuc VisitDeclContext(D);
826f4a2713aSLionel Sambuc Indent() << "}";
827f4a2713aSLionel Sambuc } else
828f4a2713aSLionel Sambuc Visit(*D->decls_begin());
829f4a2713aSLionel Sambuc }
830f4a2713aSLionel Sambuc
PrintTemplateParameters(const TemplateParameterList * Params,const TemplateArgumentList * Args)831f4a2713aSLionel Sambuc void DeclPrinter::PrintTemplateParameters(const TemplateParameterList *Params,
832f4a2713aSLionel Sambuc const TemplateArgumentList *Args) {
833f4a2713aSLionel Sambuc assert(Params);
834f4a2713aSLionel Sambuc assert(!Args || Params->size() == Args->size());
835f4a2713aSLionel Sambuc
836f4a2713aSLionel Sambuc Out << "template <";
837f4a2713aSLionel Sambuc
838f4a2713aSLionel Sambuc for (unsigned i = 0, e = Params->size(); i != e; ++i) {
839f4a2713aSLionel Sambuc if (i != 0)
840f4a2713aSLionel Sambuc Out << ", ";
841f4a2713aSLionel Sambuc
842f4a2713aSLionel Sambuc const Decl *Param = Params->getParam(i);
843f4a2713aSLionel Sambuc if (const TemplateTypeParmDecl *TTP =
844f4a2713aSLionel Sambuc dyn_cast<TemplateTypeParmDecl>(Param)) {
845f4a2713aSLionel Sambuc
846f4a2713aSLionel Sambuc if (TTP->wasDeclaredWithTypename())
847f4a2713aSLionel Sambuc Out << "typename ";
848f4a2713aSLionel Sambuc else
849f4a2713aSLionel Sambuc Out << "class ";
850f4a2713aSLionel Sambuc
851f4a2713aSLionel Sambuc if (TTP->isParameterPack())
852f4a2713aSLionel Sambuc Out << "...";
853f4a2713aSLionel Sambuc
854f4a2713aSLionel Sambuc Out << *TTP;
855f4a2713aSLionel Sambuc
856f4a2713aSLionel Sambuc if (Args) {
857f4a2713aSLionel Sambuc Out << " = ";
858f4a2713aSLionel Sambuc Args->get(i).print(Policy, Out);
859f4a2713aSLionel Sambuc } else if (TTP->hasDefaultArgument()) {
860f4a2713aSLionel Sambuc Out << " = ";
861f4a2713aSLionel Sambuc Out << TTP->getDefaultArgument().getAsString(Policy);
862f4a2713aSLionel Sambuc };
863f4a2713aSLionel Sambuc } else if (const NonTypeTemplateParmDecl *NTTP =
864f4a2713aSLionel Sambuc dyn_cast<NonTypeTemplateParmDecl>(Param)) {
865*0a6a1f1dSLionel Sambuc StringRef Name;
866*0a6a1f1dSLionel Sambuc if (IdentifierInfo *II = NTTP->getIdentifier())
867*0a6a1f1dSLionel Sambuc Name = II->getName();
868*0a6a1f1dSLionel Sambuc printDeclType(NTTP->getType(), Name, NTTP->isParameterPack());
869f4a2713aSLionel Sambuc
870f4a2713aSLionel Sambuc if (Args) {
871f4a2713aSLionel Sambuc Out << " = ";
872f4a2713aSLionel Sambuc Args->get(i).print(Policy, Out);
873f4a2713aSLionel Sambuc } else if (NTTP->hasDefaultArgument()) {
874f4a2713aSLionel Sambuc Out << " = ";
875*0a6a1f1dSLionel Sambuc NTTP->getDefaultArgument()->printPretty(Out, nullptr, Policy,
876*0a6a1f1dSLionel Sambuc Indentation);
877f4a2713aSLionel Sambuc }
878f4a2713aSLionel Sambuc } else if (const TemplateTemplateParmDecl *TTPD =
879f4a2713aSLionel Sambuc dyn_cast<TemplateTemplateParmDecl>(Param)) {
880f4a2713aSLionel Sambuc VisitTemplateDecl(TTPD);
881f4a2713aSLionel Sambuc // FIXME: print the default argument, if present.
882f4a2713aSLionel Sambuc }
883f4a2713aSLionel Sambuc }
884f4a2713aSLionel Sambuc
885f4a2713aSLionel Sambuc Out << "> ";
886f4a2713aSLionel Sambuc }
887f4a2713aSLionel Sambuc
VisitTemplateDecl(const TemplateDecl * D)888f4a2713aSLionel Sambuc void DeclPrinter::VisitTemplateDecl(const TemplateDecl *D) {
889f4a2713aSLionel Sambuc PrintTemplateParameters(D->getTemplateParameters());
890f4a2713aSLionel Sambuc
891f4a2713aSLionel Sambuc if (const TemplateTemplateParmDecl *TTP =
892f4a2713aSLionel Sambuc dyn_cast<TemplateTemplateParmDecl>(D)) {
893f4a2713aSLionel Sambuc Out << "class ";
894f4a2713aSLionel Sambuc if (TTP->isParameterPack())
895f4a2713aSLionel Sambuc Out << "...";
896f4a2713aSLionel Sambuc Out << D->getName();
897f4a2713aSLionel Sambuc } else {
898f4a2713aSLionel Sambuc Visit(D->getTemplatedDecl());
899f4a2713aSLionel Sambuc }
900f4a2713aSLionel Sambuc }
901f4a2713aSLionel Sambuc
VisitFunctionTemplateDecl(FunctionTemplateDecl * D)902f4a2713aSLionel Sambuc void DeclPrinter::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
903f4a2713aSLionel Sambuc if (PrintInstantiation) {
904f4a2713aSLionel Sambuc TemplateParameterList *Params = D->getTemplateParameters();
905*0a6a1f1dSLionel Sambuc for (auto *I : D->specializations()) {
906*0a6a1f1dSLionel Sambuc PrintTemplateParameters(Params, I->getTemplateSpecializationArgs());
907*0a6a1f1dSLionel Sambuc Visit(I);
908f4a2713aSLionel Sambuc }
909f4a2713aSLionel Sambuc }
910f4a2713aSLionel Sambuc
911f4a2713aSLionel Sambuc return VisitRedeclarableTemplateDecl(D);
912f4a2713aSLionel Sambuc }
913f4a2713aSLionel Sambuc
VisitClassTemplateDecl(ClassTemplateDecl * D)914f4a2713aSLionel Sambuc void DeclPrinter::VisitClassTemplateDecl(ClassTemplateDecl *D) {
915f4a2713aSLionel Sambuc if (PrintInstantiation) {
916f4a2713aSLionel Sambuc TemplateParameterList *Params = D->getTemplateParameters();
917*0a6a1f1dSLionel Sambuc for (auto *I : D->specializations()) {
918*0a6a1f1dSLionel Sambuc PrintTemplateParameters(Params, &I->getTemplateArgs());
919*0a6a1f1dSLionel Sambuc Visit(I);
920f4a2713aSLionel Sambuc Out << '\n';
921f4a2713aSLionel Sambuc }
922f4a2713aSLionel Sambuc }
923f4a2713aSLionel Sambuc
924f4a2713aSLionel Sambuc return VisitRedeclarableTemplateDecl(D);
925f4a2713aSLionel Sambuc }
926f4a2713aSLionel Sambuc
927f4a2713aSLionel Sambuc //----------------------------------------------------------------------------
928f4a2713aSLionel Sambuc // Objective-C declarations
929f4a2713aSLionel Sambuc //----------------------------------------------------------------------------
930f4a2713aSLionel Sambuc
VisitObjCMethodDecl(ObjCMethodDecl * OMD)931f4a2713aSLionel Sambuc void DeclPrinter::VisitObjCMethodDecl(ObjCMethodDecl *OMD) {
932f4a2713aSLionel Sambuc if (OMD->isInstanceMethod())
933f4a2713aSLionel Sambuc Out << "- ";
934f4a2713aSLionel Sambuc else
935f4a2713aSLionel Sambuc Out << "+ ";
936*0a6a1f1dSLionel Sambuc if (!OMD->getReturnType().isNull())
937*0a6a1f1dSLionel Sambuc Out << '(' << OMD->getASTContext()
938*0a6a1f1dSLionel Sambuc .getUnqualifiedObjCPointerType(OMD->getReturnType())
939*0a6a1f1dSLionel Sambuc .getAsString(Policy) << ")";
940f4a2713aSLionel Sambuc
941f4a2713aSLionel Sambuc std::string name = OMD->getSelector().getAsString();
942f4a2713aSLionel Sambuc std::string::size_type pos, lastPos = 0;
943*0a6a1f1dSLionel Sambuc for (const auto *PI : OMD->params()) {
944f4a2713aSLionel Sambuc // FIXME: selector is missing here!
945f4a2713aSLionel Sambuc pos = name.find_first_of(':', lastPos);
946f4a2713aSLionel Sambuc Out << " " << name.substr(lastPos, pos - lastPos);
947*0a6a1f1dSLionel Sambuc Out << ":(" << PI->getASTContext().getUnqualifiedObjCPointerType(PI->getType()).
948*0a6a1f1dSLionel Sambuc getAsString(Policy) << ')' << *PI;
949f4a2713aSLionel Sambuc lastPos = pos + 1;
950f4a2713aSLionel Sambuc }
951f4a2713aSLionel Sambuc
952f4a2713aSLionel Sambuc if (OMD->param_begin() == OMD->param_end())
953f4a2713aSLionel Sambuc Out << " " << name;
954f4a2713aSLionel Sambuc
955f4a2713aSLionel Sambuc if (OMD->isVariadic())
956f4a2713aSLionel Sambuc Out << ", ...";
957f4a2713aSLionel Sambuc
958*0a6a1f1dSLionel Sambuc prettyPrintAttributes(OMD);
959*0a6a1f1dSLionel Sambuc
960f4a2713aSLionel Sambuc if (OMD->getBody() && !Policy.TerseOutput) {
961f4a2713aSLionel Sambuc Out << ' ';
962*0a6a1f1dSLionel Sambuc OMD->getBody()->printPretty(Out, nullptr, Policy);
963f4a2713aSLionel Sambuc }
964f4a2713aSLionel Sambuc else if (Policy.PolishForDeclaration)
965f4a2713aSLionel Sambuc Out << ';';
966f4a2713aSLionel Sambuc }
967f4a2713aSLionel Sambuc
VisitObjCImplementationDecl(ObjCImplementationDecl * OID)968f4a2713aSLionel Sambuc void DeclPrinter::VisitObjCImplementationDecl(ObjCImplementationDecl *OID) {
969f4a2713aSLionel Sambuc std::string I = OID->getNameAsString();
970f4a2713aSLionel Sambuc ObjCInterfaceDecl *SID = OID->getSuperClass();
971f4a2713aSLionel Sambuc
972*0a6a1f1dSLionel Sambuc bool eolnOut = false;
973f4a2713aSLionel Sambuc if (SID)
974f4a2713aSLionel Sambuc Out << "@implementation " << I << " : " << *SID;
975f4a2713aSLionel Sambuc else
976f4a2713aSLionel Sambuc Out << "@implementation " << I;
977f4a2713aSLionel Sambuc
978f4a2713aSLionel Sambuc if (OID->ivar_size() > 0) {
979f4a2713aSLionel Sambuc Out << "{\n";
980*0a6a1f1dSLionel Sambuc eolnOut = true;
981f4a2713aSLionel Sambuc Indentation += Policy.Indentation;
982*0a6a1f1dSLionel Sambuc for (const auto *I : OID->ivars()) {
983f4a2713aSLionel Sambuc Indent() << I->getASTContext().getUnqualifiedObjCPointerType(I->getType()).
984*0a6a1f1dSLionel Sambuc getAsString(Policy) << ' ' << *I << ";\n";
985f4a2713aSLionel Sambuc }
986f4a2713aSLionel Sambuc Indentation -= Policy.Indentation;
987f4a2713aSLionel Sambuc Out << "}\n";
988f4a2713aSLionel Sambuc }
989*0a6a1f1dSLionel Sambuc else if (SID || (OID->decls_begin() != OID->decls_end())) {
990*0a6a1f1dSLionel Sambuc Out << "\n";
991*0a6a1f1dSLionel Sambuc eolnOut = true;
992*0a6a1f1dSLionel Sambuc }
993f4a2713aSLionel Sambuc VisitDeclContext(OID, false);
994*0a6a1f1dSLionel Sambuc if (!eolnOut)
995*0a6a1f1dSLionel Sambuc Out << "\n";
996f4a2713aSLionel Sambuc Out << "@end";
997f4a2713aSLionel Sambuc }
998f4a2713aSLionel Sambuc
VisitObjCInterfaceDecl(ObjCInterfaceDecl * OID)999f4a2713aSLionel Sambuc void DeclPrinter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *OID) {
1000f4a2713aSLionel Sambuc std::string I = OID->getNameAsString();
1001f4a2713aSLionel Sambuc ObjCInterfaceDecl *SID = OID->getSuperClass();
1002f4a2713aSLionel Sambuc
1003f4a2713aSLionel Sambuc if (!OID->isThisDeclarationADefinition()) {
1004f4a2713aSLionel Sambuc Out << "@class " << I << ";";
1005f4a2713aSLionel Sambuc return;
1006f4a2713aSLionel Sambuc }
1007f4a2713aSLionel Sambuc bool eolnOut = false;
1008f4a2713aSLionel Sambuc if (SID)
1009f4a2713aSLionel Sambuc Out << "@interface " << I << " : " << *SID;
1010f4a2713aSLionel Sambuc else
1011f4a2713aSLionel Sambuc Out << "@interface " << I;
1012f4a2713aSLionel Sambuc
1013f4a2713aSLionel Sambuc // Protocols?
1014f4a2713aSLionel Sambuc const ObjCList<ObjCProtocolDecl> &Protocols = OID->getReferencedProtocols();
1015f4a2713aSLionel Sambuc if (!Protocols.empty()) {
1016f4a2713aSLionel Sambuc for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
1017f4a2713aSLionel Sambuc E = Protocols.end(); I != E; ++I)
1018f4a2713aSLionel Sambuc Out << (I == Protocols.begin() ? '<' : ',') << **I;
1019f4a2713aSLionel Sambuc Out << "> ";
1020f4a2713aSLionel Sambuc }
1021f4a2713aSLionel Sambuc
1022f4a2713aSLionel Sambuc if (OID->ivar_size() > 0) {
1023f4a2713aSLionel Sambuc Out << "{\n";
1024f4a2713aSLionel Sambuc eolnOut = true;
1025f4a2713aSLionel Sambuc Indentation += Policy.Indentation;
1026*0a6a1f1dSLionel Sambuc for (const auto *I : OID->ivars()) {
1027*0a6a1f1dSLionel Sambuc Indent() << I->getASTContext()
1028*0a6a1f1dSLionel Sambuc .getUnqualifiedObjCPointerType(I->getType())
1029*0a6a1f1dSLionel Sambuc .getAsString(Policy) << ' ' << *I << ";\n";
1030f4a2713aSLionel Sambuc }
1031f4a2713aSLionel Sambuc Indentation -= Policy.Indentation;
1032f4a2713aSLionel Sambuc Out << "}\n";
1033f4a2713aSLionel Sambuc }
1034*0a6a1f1dSLionel Sambuc else if (SID || (OID->decls_begin() != OID->decls_end())) {
1035f4a2713aSLionel Sambuc Out << "\n";
1036f4a2713aSLionel Sambuc eolnOut = true;
1037f4a2713aSLionel Sambuc }
1038f4a2713aSLionel Sambuc
1039f4a2713aSLionel Sambuc VisitDeclContext(OID, false);
1040f4a2713aSLionel Sambuc if (!eolnOut)
1041*0a6a1f1dSLionel Sambuc Out << "\n";
1042f4a2713aSLionel Sambuc Out << "@end";
1043f4a2713aSLionel Sambuc // FIXME: implement the rest...
1044f4a2713aSLionel Sambuc }
1045f4a2713aSLionel Sambuc
VisitObjCProtocolDecl(ObjCProtocolDecl * PID)1046f4a2713aSLionel Sambuc void DeclPrinter::VisitObjCProtocolDecl(ObjCProtocolDecl *PID) {
1047f4a2713aSLionel Sambuc if (!PID->isThisDeclarationADefinition()) {
1048f4a2713aSLionel Sambuc Out << "@protocol " << *PID << ";\n";
1049f4a2713aSLionel Sambuc return;
1050f4a2713aSLionel Sambuc }
1051f4a2713aSLionel Sambuc // Protocols?
1052f4a2713aSLionel Sambuc const ObjCList<ObjCProtocolDecl> &Protocols = PID->getReferencedProtocols();
1053f4a2713aSLionel Sambuc if (!Protocols.empty()) {
1054f4a2713aSLionel Sambuc Out << "@protocol " << *PID;
1055f4a2713aSLionel Sambuc for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
1056f4a2713aSLionel Sambuc E = Protocols.end(); I != E; ++I)
1057f4a2713aSLionel Sambuc Out << (I == Protocols.begin() ? '<' : ',') << **I;
1058f4a2713aSLionel Sambuc Out << ">\n";
1059f4a2713aSLionel Sambuc } else
1060f4a2713aSLionel Sambuc Out << "@protocol " << *PID << '\n';
1061f4a2713aSLionel Sambuc VisitDeclContext(PID, false);
1062f4a2713aSLionel Sambuc Out << "@end";
1063f4a2713aSLionel Sambuc }
1064f4a2713aSLionel Sambuc
VisitObjCCategoryImplDecl(ObjCCategoryImplDecl * PID)1065f4a2713aSLionel Sambuc void DeclPrinter::VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *PID) {
1066f4a2713aSLionel Sambuc Out << "@implementation " << *PID->getClassInterface() << '(' << *PID <<")\n";
1067f4a2713aSLionel Sambuc
1068f4a2713aSLionel Sambuc VisitDeclContext(PID, false);
1069f4a2713aSLionel Sambuc Out << "@end";
1070f4a2713aSLionel Sambuc // FIXME: implement the rest...
1071f4a2713aSLionel Sambuc }
1072f4a2713aSLionel Sambuc
VisitObjCCategoryDecl(ObjCCategoryDecl * PID)1073f4a2713aSLionel Sambuc void DeclPrinter::VisitObjCCategoryDecl(ObjCCategoryDecl *PID) {
1074f4a2713aSLionel Sambuc Out << "@interface " << *PID->getClassInterface() << '(' << *PID << ")\n";
1075f4a2713aSLionel Sambuc if (PID->ivar_size() > 0) {
1076f4a2713aSLionel Sambuc Out << "{\n";
1077f4a2713aSLionel Sambuc Indentation += Policy.Indentation;
1078*0a6a1f1dSLionel Sambuc for (const auto *I : PID->ivars())
1079f4a2713aSLionel Sambuc Indent() << I->getASTContext().getUnqualifiedObjCPointerType(I->getType()).
1080*0a6a1f1dSLionel Sambuc getAsString(Policy) << ' ' << *I << ";\n";
1081f4a2713aSLionel Sambuc Indentation -= Policy.Indentation;
1082f4a2713aSLionel Sambuc Out << "}\n";
1083f4a2713aSLionel Sambuc }
1084f4a2713aSLionel Sambuc
1085f4a2713aSLionel Sambuc VisitDeclContext(PID, false);
1086f4a2713aSLionel Sambuc Out << "@end";
1087f4a2713aSLionel Sambuc
1088f4a2713aSLionel Sambuc // FIXME: implement the rest...
1089f4a2713aSLionel Sambuc }
1090f4a2713aSLionel Sambuc
VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl * AID)1091f4a2713aSLionel Sambuc void DeclPrinter::VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *AID) {
1092f4a2713aSLionel Sambuc Out << "@compatibility_alias " << *AID
1093f4a2713aSLionel Sambuc << ' ' << *AID->getClassInterface() << ";\n";
1094f4a2713aSLionel Sambuc }
1095f4a2713aSLionel Sambuc
1096f4a2713aSLionel Sambuc /// PrintObjCPropertyDecl - print a property declaration.
1097f4a2713aSLionel Sambuc ///
VisitObjCPropertyDecl(ObjCPropertyDecl * PDecl)1098f4a2713aSLionel Sambuc void DeclPrinter::VisitObjCPropertyDecl(ObjCPropertyDecl *PDecl) {
1099f4a2713aSLionel Sambuc if (PDecl->getPropertyImplementation() == ObjCPropertyDecl::Required)
1100f4a2713aSLionel Sambuc Out << "@required\n";
1101f4a2713aSLionel Sambuc else if (PDecl->getPropertyImplementation() == ObjCPropertyDecl::Optional)
1102f4a2713aSLionel Sambuc Out << "@optional\n";
1103f4a2713aSLionel Sambuc
1104f4a2713aSLionel Sambuc Out << "@property";
1105f4a2713aSLionel Sambuc if (PDecl->getPropertyAttributes() != ObjCPropertyDecl::OBJC_PR_noattr) {
1106f4a2713aSLionel Sambuc bool first = true;
1107f4a2713aSLionel Sambuc Out << " (";
1108f4a2713aSLionel Sambuc if (PDecl->getPropertyAttributes() &
1109f4a2713aSLionel Sambuc ObjCPropertyDecl::OBJC_PR_readonly) {
1110f4a2713aSLionel Sambuc Out << (first ? ' ' : ',') << "readonly";
1111f4a2713aSLionel Sambuc first = false;
1112f4a2713aSLionel Sambuc }
1113f4a2713aSLionel Sambuc
1114f4a2713aSLionel Sambuc if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_getter) {
1115*0a6a1f1dSLionel Sambuc Out << (first ? ' ' : ',') << "getter = ";
1116*0a6a1f1dSLionel Sambuc PDecl->getGetterName().print(Out);
1117f4a2713aSLionel Sambuc first = false;
1118f4a2713aSLionel Sambuc }
1119f4a2713aSLionel Sambuc if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_setter) {
1120*0a6a1f1dSLionel Sambuc Out << (first ? ' ' : ',') << "setter = ";
1121*0a6a1f1dSLionel Sambuc PDecl->getSetterName().print(Out);
1122f4a2713aSLionel Sambuc first = false;
1123f4a2713aSLionel Sambuc }
1124f4a2713aSLionel Sambuc
1125f4a2713aSLionel Sambuc if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_assign) {
1126f4a2713aSLionel Sambuc Out << (first ? ' ' : ',') << "assign";
1127f4a2713aSLionel Sambuc first = false;
1128f4a2713aSLionel Sambuc }
1129f4a2713aSLionel Sambuc
1130f4a2713aSLionel Sambuc if (PDecl->getPropertyAttributes() &
1131f4a2713aSLionel Sambuc ObjCPropertyDecl::OBJC_PR_readwrite) {
1132f4a2713aSLionel Sambuc Out << (first ? ' ' : ',') << "readwrite";
1133f4a2713aSLionel Sambuc first = false;
1134f4a2713aSLionel Sambuc }
1135f4a2713aSLionel Sambuc
1136f4a2713aSLionel Sambuc if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_retain) {
1137f4a2713aSLionel Sambuc Out << (first ? ' ' : ',') << "retain";
1138f4a2713aSLionel Sambuc first = false;
1139f4a2713aSLionel Sambuc }
1140f4a2713aSLionel Sambuc
1141f4a2713aSLionel Sambuc if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_strong) {
1142f4a2713aSLionel Sambuc Out << (first ? ' ' : ',') << "strong";
1143f4a2713aSLionel Sambuc first = false;
1144f4a2713aSLionel Sambuc }
1145f4a2713aSLionel Sambuc
1146f4a2713aSLionel Sambuc if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_copy) {
1147f4a2713aSLionel Sambuc Out << (first ? ' ' : ',') << "copy";
1148f4a2713aSLionel Sambuc first = false;
1149f4a2713aSLionel Sambuc }
1150f4a2713aSLionel Sambuc
1151f4a2713aSLionel Sambuc if (PDecl->getPropertyAttributes() &
1152f4a2713aSLionel Sambuc ObjCPropertyDecl::OBJC_PR_nonatomic) {
1153f4a2713aSLionel Sambuc Out << (first ? ' ' : ',') << "nonatomic";
1154f4a2713aSLionel Sambuc first = false;
1155f4a2713aSLionel Sambuc }
1156f4a2713aSLionel Sambuc if (PDecl->getPropertyAttributes() &
1157f4a2713aSLionel Sambuc ObjCPropertyDecl::OBJC_PR_atomic) {
1158f4a2713aSLionel Sambuc Out << (first ? ' ' : ',') << "atomic";
1159f4a2713aSLionel Sambuc first = false;
1160f4a2713aSLionel Sambuc }
1161f4a2713aSLionel Sambuc
1162f4a2713aSLionel Sambuc (void) first; // Silence dead store warning due to idiomatic code.
1163f4a2713aSLionel Sambuc Out << " )";
1164f4a2713aSLionel Sambuc }
1165f4a2713aSLionel Sambuc Out << ' ' << PDecl->getASTContext().getUnqualifiedObjCPointerType(PDecl->getType()).
1166f4a2713aSLionel Sambuc getAsString(Policy) << ' ' << *PDecl;
1167f4a2713aSLionel Sambuc if (Policy.PolishForDeclaration)
1168f4a2713aSLionel Sambuc Out << ';';
1169f4a2713aSLionel Sambuc }
1170f4a2713aSLionel Sambuc
VisitObjCPropertyImplDecl(ObjCPropertyImplDecl * PID)1171f4a2713aSLionel Sambuc void DeclPrinter::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *PID) {
1172f4a2713aSLionel Sambuc if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize)
1173f4a2713aSLionel Sambuc Out << "@synthesize ";
1174f4a2713aSLionel Sambuc else
1175f4a2713aSLionel Sambuc Out << "@dynamic ";
1176f4a2713aSLionel Sambuc Out << *PID->getPropertyDecl();
1177f4a2713aSLionel Sambuc if (PID->getPropertyIvarDecl())
1178f4a2713aSLionel Sambuc Out << '=' << *PID->getPropertyIvarDecl();
1179f4a2713aSLionel Sambuc }
1180f4a2713aSLionel Sambuc
VisitUsingDecl(UsingDecl * D)1181f4a2713aSLionel Sambuc void DeclPrinter::VisitUsingDecl(UsingDecl *D) {
1182f4a2713aSLionel Sambuc if (!D->isAccessDeclaration())
1183f4a2713aSLionel Sambuc Out << "using ";
1184f4a2713aSLionel Sambuc if (D->hasTypename())
1185f4a2713aSLionel Sambuc Out << "typename ";
1186f4a2713aSLionel Sambuc D->getQualifier()->print(Out, Policy);
1187f4a2713aSLionel Sambuc Out << *D;
1188f4a2713aSLionel Sambuc }
1189f4a2713aSLionel Sambuc
1190f4a2713aSLionel Sambuc void
VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl * D)1191f4a2713aSLionel Sambuc DeclPrinter::VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D) {
1192f4a2713aSLionel Sambuc Out << "using typename ";
1193f4a2713aSLionel Sambuc D->getQualifier()->print(Out, Policy);
1194f4a2713aSLionel Sambuc Out << D->getDeclName();
1195f4a2713aSLionel Sambuc }
1196f4a2713aSLionel Sambuc
VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl * D)1197f4a2713aSLionel Sambuc void DeclPrinter::VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D) {
1198f4a2713aSLionel Sambuc if (!D->isAccessDeclaration())
1199f4a2713aSLionel Sambuc Out << "using ";
1200f4a2713aSLionel Sambuc D->getQualifier()->print(Out, Policy);
1201f4a2713aSLionel Sambuc Out << D->getName();
1202f4a2713aSLionel Sambuc }
1203f4a2713aSLionel Sambuc
VisitUsingShadowDecl(UsingShadowDecl * D)1204f4a2713aSLionel Sambuc void DeclPrinter::VisitUsingShadowDecl(UsingShadowDecl *D) {
1205f4a2713aSLionel Sambuc // ignore
1206f4a2713aSLionel Sambuc }
1207f4a2713aSLionel Sambuc
VisitOMPThreadPrivateDecl(OMPThreadPrivateDecl * D)1208f4a2713aSLionel Sambuc void DeclPrinter::VisitOMPThreadPrivateDecl(OMPThreadPrivateDecl *D) {
1209f4a2713aSLionel Sambuc Out << "#pragma omp threadprivate";
1210f4a2713aSLionel Sambuc if (!D->varlist_empty()) {
1211f4a2713aSLionel Sambuc for (OMPThreadPrivateDecl::varlist_iterator I = D->varlist_begin(),
1212f4a2713aSLionel Sambuc E = D->varlist_end();
1213f4a2713aSLionel Sambuc I != E; ++I) {
1214f4a2713aSLionel Sambuc Out << (I == D->varlist_begin() ? '(' : ',');
1215f4a2713aSLionel Sambuc NamedDecl *ND = cast<NamedDecl>(cast<DeclRefExpr>(*I)->getDecl());
1216f4a2713aSLionel Sambuc ND->printQualifiedName(Out);
1217f4a2713aSLionel Sambuc }
1218f4a2713aSLionel Sambuc Out << ")";
1219f4a2713aSLionel Sambuc }
1220f4a2713aSLionel Sambuc }
1221f4a2713aSLionel Sambuc
1222