DeclPrinter.cpp revision 723df245307a530da5433dfb43accf187dc3e243
12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//===--- DeclPrinter.cpp - Printing implementation for Decl ASTs ----------===//
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//                     The LLVM Compiler Infrastructure
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//
51320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// This file is distributed under the University of Illinois Open Source
61320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// License. See LICENSE.TXT for details.
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//===----------------------------------------------------------------------===//
958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)//
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// This file implements the Decl::dump method, which pretty print the
11868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// AST back out to C/Objective-C/C++/Objective-C++ code.
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//===----------------------------------------------------------------------===//
141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "clang/AST/ASTContext.h"
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "clang/AST/DeclVisitor.h"
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "clang/AST/Decl.h"
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "clang/AST/DeclCXX.h"
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "clang/AST/DeclObjC.h"
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "clang/AST/Expr.h"
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "clang/AST/ExprCXX.h"
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "clang/AST/PrettyPrinter.h"
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "llvm/Support/raw_ostream.h"
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using namespace clang;
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace {
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  class DeclPrinter : public DeclVisitor<DeclPrinter> {
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    llvm::raw_ostream &Out;
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ASTContext &Context;
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    PrintingPolicy Policy;
30a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    unsigned Indentation;
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    llvm::raw_ostream& Indent() { return Indent(Indentation); }
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    llvm::raw_ostream& Indent(unsigned Indentation);
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    void ProcessDeclGroup(llvm::SmallVectorImpl<Decl*>& Decls);
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    void Print(AccessSpecifier AS);
375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  public:
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DeclPrinter(llvm::raw_ostream &Out, ASTContext &Context,
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                const PrintingPolicy &Policy,
41a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)                unsigned Indentation = 0)
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      : Out(Out), Context(Context), Policy(Policy), Indentation(Indentation) { }
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
44a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    void VisitDeclContext(DeclContext *DC, bool Indent = true);
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    void VisitTranslationUnitDecl(TranslationUnitDecl *D);
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    void VisitTypedefDecl(TypedefDecl *D);
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    void VisitEnumDecl(EnumDecl *D);
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    void VisitRecordDecl(RecordDecl *D);
50868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    void VisitEnumConstantDecl(EnumConstantDecl *D);
51868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    void VisitFunctionDecl(FunctionDecl *D);
52868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    void VisitFieldDecl(FieldDecl *D);
53868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    void VisitVarDecl(VarDecl *D);
5458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    void VisitParmVarDecl(ParmVarDecl *D);
5558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    void VisitFileScopeAsmDecl(FileScopeAsmDecl *D);
5658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    void VisitNamespaceDecl(NamespaceDecl *D);
5758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    void VisitUsingDirectiveDecl(UsingDirectiveDecl *D);
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    void VisitNamespaceAliasDecl(NamespaceAliasDecl *D);
59eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    void VisitCXXRecordDecl(CXXRecordDecl *D);
6058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    void VisitLinkageSpecDecl(LinkageSpecDecl *D);
6158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    void VisitTemplateDecl(TemplateDecl *D);
62eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    void VisitObjCMethodDecl(ObjCMethodDecl *D);
63eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    void VisitObjCClassDecl(ObjCClassDecl *D);
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    void VisitObjCImplementationDecl(ObjCImplementationDecl *D);
65868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    void VisitObjCInterfaceDecl(ObjCInterfaceDecl *D);
66868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    void VisitObjCForwardProtocolDecl(ObjCForwardProtocolDecl *D);
67868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    void VisitObjCProtocolDecl(ObjCProtocolDecl *D);
6890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    void VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D);
697dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    void VisitObjCCategoryDecl(ObjCCategoryDecl *D);
70a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    void VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *D);
7158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    void VisitObjCPropertyDecl(ObjCPropertyDecl *D);
7203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    void VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D);
7303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    void VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D);
74eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    void VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D);
7590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    void VisitUsingDecl(UsingDecl *D);
76a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    void VisitUsingShadowDecl(UsingShadowDecl *D);
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void Decl::print(llvm::raw_ostream &Out, unsigned Indentation) const {
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  print(Out, getASTContext().PrintingPolicy, Indentation);
82eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
837dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void Decl::print(llvm::raw_ostream &Out, const PrintingPolicy &Policy,
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 unsigned Indentation) const {
861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DeclPrinter Printer(Out, getASTContext(), Policy, Indentation);
87  Printer.Visit(const_cast<Decl*>(this));
88}
89
90static QualType GetBaseType(QualType T) {
91  // FIXME: This should be on the Type class!
92  QualType BaseType = T;
93  while (!BaseType->isSpecifierType()) {
94    if (isa<TypedefType>(BaseType))
95      break;
96    else if (const PointerType* PTy = BaseType->getAs<PointerType>())
97      BaseType = PTy->getPointeeType();
98    else if (const ArrayType* ATy = dyn_cast<ArrayType>(BaseType))
99      BaseType = ATy->getElementType();
100    else if (const FunctionType* FTy = BaseType->getAs<FunctionType>())
101      BaseType = FTy->getResultType();
102    else if (const VectorType *VTy = BaseType->getAs<VectorType>())
103      BaseType = VTy->getElementType();
104    else
105      assert(0 && "Unknown declarator!");
106  }
107  return BaseType;
108}
109
110static QualType getDeclType(Decl* D) {
111  if (TypedefDecl* TDD = dyn_cast<TypedefDecl>(D))
112    return TDD->getUnderlyingType();
113  if (ValueDecl* VD = dyn_cast<ValueDecl>(D))
114    return VD->getType();
115  return QualType();
116}
117
118void Decl::printGroup(Decl** Begin, unsigned NumDecls,
119                      llvm::raw_ostream &Out, const PrintingPolicy &Policy,
120                      unsigned Indentation) {
121  if (NumDecls == 1) {
122    (*Begin)->print(Out, Policy, Indentation);
123    return;
124  }
125
126  Decl** End = Begin + NumDecls;
127  TagDecl* TD = dyn_cast<TagDecl>(*Begin);
128  if (TD)
129    ++Begin;
130
131  PrintingPolicy SubPolicy(Policy);
132  if (TD && TD->isDefinition()) {
133    TD->print(Out, Policy, Indentation);
134    Out << " ";
135    SubPolicy.SuppressTag = true;
136  }
137
138  bool isFirst = true;
139  for ( ; Begin != End; ++Begin) {
140    if (isFirst) {
141      SubPolicy.SuppressSpecifiers = false;
142      isFirst = false;
143    } else {
144      if (!isFirst) Out << ", ";
145      SubPolicy.SuppressSpecifiers = true;
146    }
147
148    (*Begin)->print(Out, SubPolicy, Indentation);
149  }
150}
151
152void DeclContext::dumpDeclContext() const {
153  // Get the translation unit
154  const DeclContext *DC = this;
155  while (!DC->isTranslationUnit())
156    DC = DC->getParent();
157
158  ASTContext &Ctx = cast<TranslationUnitDecl>(DC)->getASTContext();
159  DeclPrinter Printer(llvm::errs(), Ctx, Ctx.PrintingPolicy, 0);
160  Printer.VisitDeclContext(const_cast<DeclContext *>(this), /*Indent=*/false);
161}
162
163void Decl::dump() const {
164  print(llvm::errs());
165}
166
167llvm::raw_ostream& DeclPrinter::Indent(unsigned Indentation) {
168  for (unsigned i = 0; i != Indentation; ++i)
169    Out << "  ";
170  return Out;
171}
172
173void DeclPrinter::ProcessDeclGroup(llvm::SmallVectorImpl<Decl*>& Decls) {
174  this->Indent();
175  Decl::printGroup(Decls.data(), Decls.size(), Out, Policy, Indentation);
176  Out << ";\n";
177  Decls.clear();
178
179}
180
181void DeclPrinter::Print(AccessSpecifier AS) {
182  switch(AS) {
183  case AS_none:      assert(0 && "No access specifier!"); break;
184  case AS_public:    Out << "public"; break;
185  case AS_protected: Out << "protected"; break;
186  case AS_private:   Out << "private"; break;
187  }
188}
189
190//----------------------------------------------------------------------------
191// Common C declarations
192//----------------------------------------------------------------------------
193
194void DeclPrinter::VisitDeclContext(DeclContext *DC, bool Indent) {
195  if (Indent)
196    Indentation += Policy.Indentation;
197
198  llvm::SmallVector<Decl*, 2> Decls;
199  for (DeclContext::decl_iterator D = DC->decls_begin(), DEnd = DC->decls_end();
200       D != DEnd; ++D) {
201
202    // Don't print ObjCIvarDecls, as they are printed when visiting the
203    // containing ObjCInterfaceDecl.
204    if (isa<ObjCIvarDecl>(*D))
205      continue;
206
207    if (!Policy.Dump) {
208      // Skip over implicit declarations in pretty-printing mode.
209      if (D->isImplicit()) continue;
210      // FIXME: Ugly hack so we don't pretty-print the builtin declaration
211      // of __builtin_va_list or __[u]int128_t.  There should be some other way
212      // to check that.
213      if (NamedDecl *ND = dyn_cast<NamedDecl>(*D)) {
214        if (IdentifierInfo *II = ND->getIdentifier()) {
215          if (II->isStr("__builtin_va_list") ||
216              II->isStr("__int128_t") || II->isStr("__uint128_t"))
217            continue;
218        }
219      }
220    }
221
222    // The next bits of code handles stuff like "struct {int x;} a,b"; we're
223    // forced to merge the declarations because there's no other way to
224    // refer to the struct in question.  This limited merging is safe without
225    // a bunch of other checks because it only merges declarations directly
226    // referring to the tag, not typedefs.
227    //
228    // Check whether the current declaration should be grouped with a previous
229    // unnamed struct.
230    QualType CurDeclType = getDeclType(*D);
231    if (!Decls.empty() && !CurDeclType.isNull()) {
232      QualType BaseType = GetBaseType(CurDeclType);
233      if (!BaseType.isNull() && isa<TagType>(BaseType) &&
234          cast<TagType>(BaseType)->getDecl() == Decls[0]) {
235        Decls.push_back(*D);
236        continue;
237      }
238    }
239
240    // If we have a merged group waiting to be handled, handle it now.
241    if (!Decls.empty())
242      ProcessDeclGroup(Decls);
243
244    // If the current declaration is an unnamed tag type, save it
245    // so we can merge it with the subsequent declaration(s) using it.
246    if (isa<TagDecl>(*D) && !cast<TagDecl>(*D)->getIdentifier()) {
247      Decls.push_back(*D);
248      continue;
249    }
250
251    if (isa<AccessSpecDecl>(*D)) {
252      Indentation -= Policy.Indentation;
253      this->Indent();
254      Print(D->getAccess());
255      Out << ":\n";
256      Indentation += Policy.Indentation;
257      continue;
258    }
259
260    this->Indent();
261    Visit(*D);
262
263    // FIXME: Need to be able to tell the DeclPrinter when
264    const char *Terminator = 0;
265    if (isa<FunctionDecl>(*D) &&
266        cast<FunctionDecl>(*D)->isThisDeclarationADefinition())
267      Terminator = 0;
268    else if (isa<ObjCMethodDecl>(*D) && cast<ObjCMethodDecl>(*D)->getBody())
269      Terminator = 0;
270    else if (isa<NamespaceDecl>(*D) || isa<LinkageSpecDecl>(*D) ||
271             isa<ObjCImplementationDecl>(*D) ||
272             isa<ObjCInterfaceDecl>(*D) ||
273             isa<ObjCProtocolDecl>(*D) ||
274             isa<ObjCCategoryImplDecl>(*D) ||
275             isa<ObjCCategoryDecl>(*D))
276      Terminator = 0;
277    else if (isa<EnumConstantDecl>(*D)) {
278      DeclContext::decl_iterator Next = D;
279      ++Next;
280      if (Next != DEnd)
281        Terminator = ",";
282    } else
283      Terminator = ";";
284
285    if (Terminator)
286      Out << Terminator;
287    Out << "\n";
288  }
289
290  if (!Decls.empty())
291    ProcessDeclGroup(Decls);
292
293  if (Indent)
294    Indentation -= Policy.Indentation;
295}
296
297void DeclPrinter::VisitTranslationUnitDecl(TranslationUnitDecl *D) {
298  VisitDeclContext(D, false);
299}
300
301void DeclPrinter::VisitTypedefDecl(TypedefDecl *D) {
302  std::string S = D->getNameAsString();
303  D->getUnderlyingType().getAsStringInternal(S, Policy);
304  if (!Policy.SuppressSpecifiers)
305    Out << "typedef ";
306  Out << S;
307}
308
309void DeclPrinter::VisitEnumDecl(EnumDecl *D) {
310  Out << "enum ";
311  if (D->isScoped()) {
312    if (D->isScopedUsingClassTag())
313      Out << "class ";
314    else
315      Out << "struct ";
316  }
317  Out << D;
318
319  if (D->isFixed()) {
320    std::string Underlying;
321    D->getIntegerType().getAsStringInternal(Underlying, Policy);
322    Out << " : " << Underlying;
323  }
324
325  if (D->isDefinition()) {
326    Out << " {\n";
327    VisitDeclContext(D);
328    Indent() << "}";
329  }
330}
331
332void DeclPrinter::VisitRecordDecl(RecordDecl *D) {
333  Out << D->getKindName();
334  if (D->getIdentifier())
335    Out << ' ' << D;
336
337  if (D->isDefinition()) {
338    Out << " {\n";
339    VisitDeclContext(D);
340    Indent() << "}";
341  }
342}
343
344void DeclPrinter::VisitEnumConstantDecl(EnumConstantDecl *D) {
345  Out << D;
346  if (Expr *Init = D->getInitExpr()) {
347    Out << " = ";
348    Init->printPretty(Out, Context, 0, Policy, Indentation);
349  }
350}
351
352void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
353  if (!Policy.SuppressSpecifiers) {
354    switch (D->getStorageClass()) {
355    case SC_None: break;
356    case SC_Extern: Out << "extern "; break;
357    case SC_Static: Out << "static "; break;
358    case SC_PrivateExtern: Out << "__private_extern__ "; break;
359    case SC_Auto: case SC_Register: llvm_unreachable("invalid for functions");
360    }
361
362    if (D->isInlineSpecified())           Out << "inline ";
363    if (D->isVirtualAsWritten()) Out << "virtual ";
364  }
365
366  PrintingPolicy SubPolicy(Policy);
367  SubPolicy.SuppressSpecifiers = false;
368  std::string Proto = D->getNameInfo().getAsString();
369
370  QualType Ty = D->getType();
371  while (ParenType* PT = dyn_cast<ParenType>(Ty)) {
372    Proto = '(' + Proto + ')';
373    Ty = PT->getInnerType();
374  }
375
376  if (isa<FunctionType>(Ty)) {
377    const FunctionType *AFT = Ty->getAs<FunctionType>();
378    const FunctionProtoType *FT = 0;
379    if (D->hasWrittenPrototype())
380      FT = dyn_cast<FunctionProtoType>(AFT);
381
382    Proto += "(";
383    if (FT) {
384      llvm::raw_string_ostream POut(Proto);
385      DeclPrinter ParamPrinter(POut, Context, SubPolicy, Indentation);
386      for (unsigned i = 0, e = D->getNumParams(); i != e; ++i) {
387        if (i) POut << ", ";
388        ParamPrinter.VisitParmVarDecl(D->getParamDecl(i));
389      }
390
391      if (FT->isVariadic()) {
392        if (D->getNumParams()) POut << ", ";
393        POut << "...";
394      }
395    } else if (D->isThisDeclarationADefinition() && !D->hasPrototype()) {
396      for (unsigned i = 0, e = D->getNumParams(); i != e; ++i) {
397        if (i)
398          Proto += ", ";
399        Proto += D->getParamDecl(i)->getNameAsString();
400      }
401    }
402
403    Proto += ")";
404
405    if (FT && FT->getTypeQuals()) {
406      unsigned TypeQuals = FT->getTypeQuals();
407      if (TypeQuals & Qualifiers::Const)
408        Proto += " const";
409      if (TypeQuals & Qualifiers::Volatile)
410        Proto += " volatile";
411      if (TypeQuals & Qualifiers::Restrict)
412        Proto += " restrict";
413    }
414
415    if (FT && FT->hasExceptionSpec()) {
416      Proto += " throw(";
417      if (FT->hasAnyExceptionSpec())
418        Proto += "...";
419      else
420        for (unsigned I = 0, N = FT->getNumExceptions(); I != N; ++I) {
421          if (I)
422            Proto += ", ";
423
424
425          std::string ExceptionType;
426          FT->getExceptionType(I).getAsStringInternal(ExceptionType, SubPolicy);
427          Proto += ExceptionType;
428        }
429      Proto += ")";
430    }
431
432    if (D->hasAttr<NoReturnAttr>())
433      Proto += " __attribute((noreturn))";
434    if (CXXConstructorDecl *CDecl = dyn_cast<CXXConstructorDecl>(D)) {
435      if (CDecl->getNumBaseOrMemberInitializers() > 0) {
436        Proto += " : ";
437        Out << Proto;
438        Proto.clear();
439        for (CXXConstructorDecl::init_const_iterator B = CDecl->init_begin(),
440             E = CDecl->init_end();
441             B != E; ++B) {
442          CXXBaseOrMemberInitializer * BMInitializer = (*B);
443          if (B != CDecl->init_begin())
444            Out << ", ";
445          if (BMInitializer->isAnyMemberInitializer()) {
446            FieldDecl *FD = BMInitializer->getAnyMember();
447            Out << FD;
448          } else {
449            Out << QualType(BMInitializer->getBaseClass(),
450                            0).getAsString(Policy);
451          }
452
453          Out << "(";
454          if (!BMInitializer->getInit()) {
455            // Nothing to print
456          } else {
457            Expr *Init = BMInitializer->getInit();
458            if (ExprWithCleanups *Tmp = dyn_cast<ExprWithCleanups>(Init))
459              Init = Tmp->getSubExpr();
460
461            Init = Init->IgnoreParens();
462
463            Expr *SimpleInit = 0;
464            Expr **Args = 0;
465            unsigned NumArgs = 0;
466            if (ParenListExpr *ParenList = dyn_cast<ParenListExpr>(Init)) {
467              Args = ParenList->getExprs();
468              NumArgs = ParenList->getNumExprs();
469            } else if (CXXConstructExpr *Construct
470                                          = dyn_cast<CXXConstructExpr>(Init)) {
471              Args = Construct->getArgs();
472              NumArgs = Construct->getNumArgs();
473            } else
474              SimpleInit = Init;
475
476            if (SimpleInit)
477              SimpleInit->printPretty(Out, Context, 0, Policy, Indentation);
478            else {
479              for (unsigned I = 0; I != NumArgs; ++I) {
480                if (isa<CXXDefaultArgExpr>(Args[I]))
481                  break;
482
483                if (I)
484                  Out << ", ";
485                Args[I]->printPretty(Out, Context, 0, Policy, Indentation);
486              }
487            }
488          }
489          Out << ")";
490        }
491      }
492    }
493    else
494      AFT->getResultType().getAsStringInternal(Proto, Policy);
495  } else {
496    Ty.getAsStringInternal(Proto, Policy);
497  }
498
499  Out << Proto;
500
501  if (D->isPure())
502    Out << " = 0";
503  else if (D->isDeleted())
504    Out << " = delete";
505  else if (D->isThisDeclarationADefinition()) {
506    if (!D->hasPrototype() && D->getNumParams()) {
507      // This is a K&R function definition, so we need to print the
508      // parameters.
509      Out << '\n';
510      DeclPrinter ParamPrinter(Out, Context, SubPolicy, Indentation);
511      Indentation += Policy.Indentation;
512      for (unsigned i = 0, e = D->getNumParams(); i != e; ++i) {
513        Indent();
514        ParamPrinter.VisitParmVarDecl(D->getParamDecl(i));
515        Out << ";\n";
516      }
517      Indentation -= Policy.Indentation;
518    } else
519      Out << ' ';
520
521    D->getBody()->printPretty(Out, Context, 0, SubPolicy, Indentation);
522    Out << '\n';
523  }
524}
525
526void DeclPrinter::VisitFieldDecl(FieldDecl *D) {
527  if (!Policy.SuppressSpecifiers && D->isMutable())
528    Out << "mutable ";
529
530  std::string Name = D->getNameAsString();
531  D->getType().getAsStringInternal(Name, Policy);
532  Out << Name;
533
534  if (D->isBitField()) {
535    Out << " : ";
536    D->getBitWidth()->printPretty(Out, Context, 0, Policy, Indentation);
537  }
538}
539
540void DeclPrinter::VisitVarDecl(VarDecl *D) {
541  if (!Policy.SuppressSpecifiers && D->getStorageClass() != SC_None)
542    Out << VarDecl::getStorageClassSpecifierString(D->getStorageClass()) << " ";
543
544  if (!Policy.SuppressSpecifiers && D->isThreadSpecified())
545    Out << "__thread ";
546
547  std::string Name = D->getNameAsString();
548  QualType T = D->getType();
549  if (ParmVarDecl *Parm = dyn_cast<ParmVarDecl>(D))
550    T = Parm->getOriginalType();
551  T.getAsStringInternal(Name, Policy);
552  Out << Name;
553  if (Expr *Init = D->getInit()) {
554    if (D->hasCXXDirectInitializer())
555      Out << "(";
556    else {
557        CXXConstructExpr *CCE = dyn_cast<CXXConstructExpr>(Init);
558        if (!CCE || CCE->getConstructor()->isCopyConstructor())
559          Out << " = ";
560    }
561    Init->printPretty(Out, Context, 0, Policy, Indentation);
562    if (D->hasCXXDirectInitializer())
563      Out << ")";
564  }
565}
566
567void DeclPrinter::VisitParmVarDecl(ParmVarDecl *D) {
568  VisitVarDecl(D);
569}
570
571void DeclPrinter::VisitFileScopeAsmDecl(FileScopeAsmDecl *D) {
572  Out << "__asm (";
573  D->getAsmString()->printPretty(Out, Context, 0, Policy, Indentation);
574  Out << ")";
575}
576
577//----------------------------------------------------------------------------
578// C++ declarations
579//----------------------------------------------------------------------------
580void DeclPrinter::VisitNamespaceDecl(NamespaceDecl *D) {
581  Out << "namespace " << D << " {\n";
582  VisitDeclContext(D);
583  Indent() << "}";
584}
585
586void DeclPrinter::VisitUsingDirectiveDecl(UsingDirectiveDecl *D) {
587  Out << "using namespace ";
588  if (D->getQualifier())
589    D->getQualifier()->print(Out, Policy);
590  Out << D->getNominatedNamespaceAsWritten();
591}
592
593void DeclPrinter::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) {
594  Out << "namespace " << D << " = ";
595  if (D->getQualifier())
596    D->getQualifier()->print(Out, Policy);
597  Out << D->getAliasedNamespace();
598}
599
600void DeclPrinter::VisitCXXRecordDecl(CXXRecordDecl *D) {
601  Out << D->getKindName();
602  if (D->getIdentifier())
603    Out << ' ' << D;
604
605  if (D->isDefinition()) {
606    // Print the base classes
607    if (D->getNumBases()) {
608      Out << " : ";
609      for (CXXRecordDecl::base_class_iterator Base = D->bases_begin(),
610             BaseEnd = D->bases_end(); Base != BaseEnd; ++Base) {
611        if (Base != D->bases_begin())
612          Out << ", ";
613
614        if (Base->isVirtual())
615          Out << "virtual ";
616
617        AccessSpecifier AS = Base->getAccessSpecifierAsWritten();
618        if (AS != AS_none)
619          Print(AS);
620        Out << " " << Base->getType().getAsString(Policy);
621      }
622    }
623
624    // Print the class definition
625    // FIXME: Doesn't print access specifiers, e.g., "public:"
626    Out << " {\n";
627    VisitDeclContext(D);
628    Indent() << "}";
629  }
630}
631
632void DeclPrinter::VisitLinkageSpecDecl(LinkageSpecDecl *D) {
633  const char *l;
634  if (D->getLanguage() == LinkageSpecDecl::lang_c)
635    l = "C";
636  else {
637    assert(D->getLanguage() == LinkageSpecDecl::lang_cxx &&
638           "unknown language in linkage specification");
639    l = "C++";
640  }
641
642  Out << "extern \"" << l << "\" ";
643  if (D->hasBraces()) {
644    Out << "{\n";
645    VisitDeclContext(D);
646    Indent() << "}";
647  } else
648    Visit(*D->decls_begin());
649}
650
651void DeclPrinter::VisitTemplateDecl(TemplateDecl *D) {
652  Out << "template <";
653
654  TemplateParameterList *Params = D->getTemplateParameters();
655  for (unsigned i = 0, e = Params->size(); i != e; ++i) {
656    if (i != 0)
657      Out << ", ";
658
659    const Decl *Param = Params->getParam(i);
660    if (const TemplateTypeParmDecl *TTP =
661          dyn_cast<TemplateTypeParmDecl>(Param)) {
662
663      QualType ParamType =
664        Context.getTypeDeclType(const_cast<TemplateTypeParmDecl*>(TTP));
665
666      if (TTP->wasDeclaredWithTypename())
667        Out << "typename ";
668      else
669        Out << "class ";
670
671      if (TTP->isParameterPack())
672        Out << "... ";
673
674      Out << ParamType.getAsString(Policy);
675
676      if (TTP->hasDefaultArgument()) {
677        Out << " = ";
678        Out << TTP->getDefaultArgument().getAsString(Policy);
679      };
680    } else if (const NonTypeTemplateParmDecl *NTTP =
681                 dyn_cast<NonTypeTemplateParmDecl>(Param)) {
682      Out << NTTP->getType().getAsString(Policy);
683
684      if (IdentifierInfo *Name = NTTP->getIdentifier()) {
685        Out << ' ';
686        Out << Name->getName();
687      }
688
689      if (NTTP->hasDefaultArgument()) {
690        Out << " = ";
691        NTTP->getDefaultArgument()->printPretty(Out, Context, 0, Policy,
692                                                Indentation);
693      }
694    }
695  }
696
697  Out << "> ";
698
699  if (isa<TemplateTemplateParmDecl>(D)) {
700    Out << "class " << D->getName();
701  } else {
702    Visit(D->getTemplatedDecl());
703  }
704}
705
706//----------------------------------------------------------------------------
707// Objective-C declarations
708//----------------------------------------------------------------------------
709
710void DeclPrinter::VisitObjCClassDecl(ObjCClassDecl *D) {
711  Out << "@class ";
712  for (ObjCClassDecl::iterator I = D->begin(), E = D->end();
713       I != E; ++I) {
714    if (I != D->begin()) Out << ", ";
715    Out << I->getInterface();
716  }
717}
718
719void DeclPrinter::VisitObjCMethodDecl(ObjCMethodDecl *OMD) {
720  if (OMD->isInstanceMethod())
721    Out << "- ";
722  else
723    Out << "+ ";
724  if (!OMD->getResultType().isNull())
725    Out << '(' << OMD->getResultType().getAsString(Policy) << ")";
726
727  std::string name = OMD->getSelector().getAsString();
728  std::string::size_type pos, lastPos = 0;
729  for (ObjCMethodDecl::param_iterator PI = OMD->param_begin(),
730       E = OMD->param_end(); PI != E; ++PI) {
731    // FIXME: selector is missing here!
732    pos = name.find_first_of(":", lastPos);
733    Out << " " << name.substr(lastPos, pos - lastPos);
734    Out << ":(" << (*PI)->getType().getAsString(Policy) << ')' << *PI;
735    lastPos = pos + 1;
736  }
737
738  if (OMD->param_begin() == OMD->param_end())
739    Out << " " << name;
740
741  if (OMD->isVariadic())
742      Out << ", ...";
743
744  if (OMD->getBody()) {
745    Out << ' ';
746    OMD->getBody()->printPretty(Out, Context, 0, Policy);
747    Out << '\n';
748  }
749}
750
751void DeclPrinter::VisitObjCImplementationDecl(ObjCImplementationDecl *OID) {
752  std::string I = OID->getNameAsString();
753  ObjCInterfaceDecl *SID = OID->getSuperClass();
754
755  if (SID)
756    Out << "@implementation " << I << " : " << SID;
757  else
758    Out << "@implementation " << I;
759  Out << "\n";
760  VisitDeclContext(OID, false);
761  Out << "@end";
762}
763
764void DeclPrinter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *OID) {
765  std::string I = OID->getNameAsString();
766  ObjCInterfaceDecl *SID = OID->getSuperClass();
767
768  if (SID)
769    Out << "@interface " << I << " : " << SID;
770  else
771    Out << "@interface " << I;
772
773  // Protocols?
774  const ObjCList<ObjCProtocolDecl> &Protocols = OID->getReferencedProtocols();
775  if (!Protocols.empty()) {
776    for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
777         E = Protocols.end(); I != E; ++I)
778      Out << (I == Protocols.begin() ? '<' : ',') << *I;
779  }
780
781  if (!Protocols.empty())
782    Out << "> ";
783
784  if (OID->ivar_size() > 0) {
785    Out << "{\n";
786    Indentation += Policy.Indentation;
787    for (ObjCInterfaceDecl::ivar_iterator I = OID->ivar_begin(),
788         E = OID->ivar_end(); I != E; ++I) {
789      Indent() << (*I)->getType().getAsString(Policy) << ' ' << *I << ";\n";
790    }
791    Indentation -= Policy.Indentation;
792    Out << "}\n";
793  }
794
795  VisitDeclContext(OID, false);
796  Out << "@end";
797  // FIXME: implement the rest...
798}
799
800void DeclPrinter::VisitObjCForwardProtocolDecl(ObjCForwardProtocolDecl *D) {
801  Out << "@protocol ";
802  for (ObjCForwardProtocolDecl::protocol_iterator I = D->protocol_begin(),
803         E = D->protocol_end();
804       I != E; ++I) {
805    if (I != D->protocol_begin()) Out << ", ";
806    Out << *I;
807  }
808}
809
810void DeclPrinter::VisitObjCProtocolDecl(ObjCProtocolDecl *PID) {
811  Out << "@protocol " << PID << '\n';
812  VisitDeclContext(PID, false);
813  Out << "@end";
814}
815
816void DeclPrinter::VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *PID) {
817  Out << "@implementation " << PID->getClassInterface() << '(' << PID << ")\n";
818
819  VisitDeclContext(PID, false);
820  Out << "@end";
821  // FIXME: implement the rest...
822}
823
824void DeclPrinter::VisitObjCCategoryDecl(ObjCCategoryDecl *PID) {
825  Out << "@interface " << PID->getClassInterface() << '(' << PID << ")\n";
826  VisitDeclContext(PID, false);
827  Out << "@end";
828
829  // FIXME: implement the rest...
830}
831
832void DeclPrinter::VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *AID) {
833  Out << "@compatibility_alias " << AID
834      << ' ' << AID->getClassInterface() << ";\n";
835}
836
837/// PrintObjCPropertyDecl - print a property declaration.
838///
839void DeclPrinter::VisitObjCPropertyDecl(ObjCPropertyDecl *PDecl) {
840  if (PDecl->getPropertyImplementation() == ObjCPropertyDecl::Required)
841    Out << "@required\n";
842  else if (PDecl->getPropertyImplementation() == ObjCPropertyDecl::Optional)
843    Out << "@optional\n";
844
845  Out << "@property";
846  if (PDecl->getPropertyAttributes() != ObjCPropertyDecl::OBJC_PR_noattr) {
847    bool first = true;
848    Out << " (";
849    if (PDecl->getPropertyAttributes() &
850        ObjCPropertyDecl::OBJC_PR_readonly) {
851      Out << (first ? ' ' : ',') << "readonly";
852      first = false;
853  }
854
855  if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_getter) {
856    Out << (first ? ' ' : ',') << "getter = "
857        << PDecl->getGetterName().getAsString();
858    first = false;
859  }
860  if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_setter) {
861    Out << (first ? ' ' : ',') << "setter = "
862        << PDecl->getSetterName().getAsString();
863    first = false;
864  }
865
866  if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_assign) {
867    Out << (first ? ' ' : ',') << "assign";
868    first = false;
869  }
870
871  if (PDecl->getPropertyAttributes() &
872      ObjCPropertyDecl::OBJC_PR_readwrite) {
873    Out << (first ? ' ' : ',') << "readwrite";
874    first = false;
875  }
876
877  if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_retain) {
878    Out << (first ? ' ' : ',') << "retain";
879    first = false;
880  }
881
882  if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_copy) {
883    Out << (first ? ' ' : ',') << "copy";
884    first = false;
885  }
886
887  if (PDecl->getPropertyAttributes() &
888      ObjCPropertyDecl::OBJC_PR_nonatomic) {
889    Out << (first ? ' ' : ',') << "nonatomic";
890    first = false;
891  }
892  Out << " )";
893  }
894  Out << ' ' << PDecl->getType().getAsString(Policy) << ' ' << PDecl;
895}
896
897void DeclPrinter::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *PID) {
898  if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize)
899    Out << "@synthesize ";
900  else
901    Out << "@dynamic ";
902  Out << PID->getPropertyDecl();
903  if (PID->getPropertyIvarDecl())
904    Out << '=' << PID->getPropertyIvarDecl();
905}
906
907void DeclPrinter::VisitUsingDecl(UsingDecl *D) {
908  Out << "using ";
909  D->getTargetNestedNameDecl()->print(Out, Policy);
910  Out << D;
911}
912
913void
914DeclPrinter::VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D) {
915  Out << "using typename ";
916  D->getTargetNestedNameSpecifier()->print(Out, Policy);
917  Out << D->getDeclName();
918}
919
920void DeclPrinter::VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D) {
921  Out << "using ";
922  D->getTargetNestedNameSpecifier()->print(Out, Policy);
923  Out << D->getDeclName();
924}
925
926void DeclPrinter::VisitUsingShadowDecl(UsingShadowDecl *D) {
927  // ignore
928}
929