clang API Documentation

DeclPrinter.cpp
Go to the documentation of this file.
00001 //===--- DeclPrinter.cpp - Printing implementation for Decl ASTs ----------===//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 //
00010 // This file implements the Decl::print method, which pretty prints the
00011 // AST back out to C/Objective-C/C++/Objective-C++ code.
00012 //
00013 //===----------------------------------------------------------------------===//
00014 #include "clang/AST/ASTContext.h"
00015 #include "clang/AST/Attr.h"
00016 #include "clang/AST/Decl.h"
00017 #include "clang/AST/DeclCXX.h"
00018 #include "clang/AST/DeclObjC.h"
00019 #include "clang/AST/DeclVisitor.h"
00020 #include "clang/AST/Expr.h"
00021 #include "clang/AST/ExprCXX.h"
00022 #include "clang/AST/PrettyPrinter.h"
00023 #include "clang/Basic/Module.h"
00024 #include "llvm/Support/raw_ostream.h"
00025 using namespace clang;
00026 
00027 namespace {
00028   class DeclPrinter : public DeclVisitor<DeclPrinter> {
00029     raw_ostream &Out;
00030     PrintingPolicy Policy;
00031     unsigned Indentation;
00032     bool PrintInstantiation;
00033 
00034     raw_ostream& Indent() { return Indent(Indentation); }
00035     raw_ostream& Indent(unsigned Indentation);
00036     void ProcessDeclGroup(SmallVectorImpl<Decl*>& Decls);
00037 
00038     void Print(AccessSpecifier AS);
00039 
00040   public:
00041     DeclPrinter(raw_ostream &Out, const PrintingPolicy &Policy,
00042                 unsigned Indentation = 0, bool PrintInstantiation = false)
00043       : Out(Out), Policy(Policy), Indentation(Indentation),
00044         PrintInstantiation(PrintInstantiation) { }
00045 
00046     void VisitDeclContext(DeclContext *DC, bool Indent = true);
00047 
00048     void VisitTranslationUnitDecl(TranslationUnitDecl *D);
00049     void VisitTypedefDecl(TypedefDecl *D);
00050     void VisitTypeAliasDecl(TypeAliasDecl *D);
00051     void VisitEnumDecl(EnumDecl *D);
00052     void VisitRecordDecl(RecordDecl *D);
00053     void VisitEnumConstantDecl(EnumConstantDecl *D);
00054     void VisitEmptyDecl(EmptyDecl *D);
00055     void VisitFunctionDecl(FunctionDecl *D);
00056     void VisitFriendDecl(FriendDecl *D);
00057     void VisitFieldDecl(FieldDecl *D);
00058     void VisitVarDecl(VarDecl *D);
00059     void VisitLabelDecl(LabelDecl *D);
00060     void VisitParmVarDecl(ParmVarDecl *D);
00061     void VisitFileScopeAsmDecl(FileScopeAsmDecl *D);
00062     void VisitImportDecl(ImportDecl *D);
00063     void VisitStaticAssertDecl(StaticAssertDecl *D);
00064     void VisitNamespaceDecl(NamespaceDecl *D);
00065     void VisitUsingDirectiveDecl(UsingDirectiveDecl *D);
00066     void VisitNamespaceAliasDecl(NamespaceAliasDecl *D);
00067     void VisitCXXRecordDecl(CXXRecordDecl *D);
00068     void VisitLinkageSpecDecl(LinkageSpecDecl *D);
00069     void VisitTemplateDecl(const TemplateDecl *D);
00070     void VisitFunctionTemplateDecl(FunctionTemplateDecl *D);
00071     void VisitClassTemplateDecl(ClassTemplateDecl *D);
00072     void VisitObjCMethodDecl(ObjCMethodDecl *D);
00073     void VisitObjCImplementationDecl(ObjCImplementationDecl *D);
00074     void VisitObjCInterfaceDecl(ObjCInterfaceDecl *D);
00075     void VisitObjCProtocolDecl(ObjCProtocolDecl *D);
00076     void VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D);
00077     void VisitObjCCategoryDecl(ObjCCategoryDecl *D);
00078     void VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *D);
00079     void VisitObjCPropertyDecl(ObjCPropertyDecl *D);
00080     void VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D);
00081     void VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D);
00082     void VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D);
00083     void VisitUsingDecl(UsingDecl *D);
00084     void VisitUsingShadowDecl(UsingShadowDecl *D);
00085     void VisitOMPThreadPrivateDecl(OMPThreadPrivateDecl *D);
00086 
00087     void PrintTemplateParameters(const TemplateParameterList *Params,
00088                                  const TemplateArgumentList *Args = nullptr);
00089     void prettyPrintAttributes(Decl *D);
00090     void printDeclType(QualType T, StringRef DeclName, bool Pack = false);
00091   };
00092 }
00093 
00094 void Decl::print(raw_ostream &Out, unsigned Indentation,
00095                  bool PrintInstantiation) const {
00096   print(Out, getASTContext().getPrintingPolicy(), Indentation, PrintInstantiation);
00097 }
00098 
00099 void Decl::print(raw_ostream &Out, const PrintingPolicy &Policy,
00100                  unsigned Indentation, bool PrintInstantiation) const {
00101   DeclPrinter Printer(Out, Policy, Indentation, PrintInstantiation);
00102   Printer.Visit(const_cast<Decl*>(this));
00103 }
00104 
00105 static QualType GetBaseType(QualType T) {
00106   // FIXME: This should be on the Type class!
00107   QualType BaseType = T;
00108   while (!BaseType->isSpecifierType()) {
00109     if (isa<TypedefType>(BaseType))
00110       break;
00111     else if (const PointerType* PTy = BaseType->getAs<PointerType>())
00112       BaseType = PTy->getPointeeType();
00113     else if (const BlockPointerType *BPy = BaseType->getAs<BlockPointerType>())
00114       BaseType = BPy->getPointeeType();
00115     else if (const ArrayType* ATy = dyn_cast<ArrayType>(BaseType))
00116       BaseType = ATy->getElementType();
00117     else if (const FunctionType* FTy = BaseType->getAs<FunctionType>())
00118       BaseType = FTy->getReturnType();
00119     else if (const VectorType *VTy = BaseType->getAs<VectorType>())
00120       BaseType = VTy->getElementType();
00121     else if (const ReferenceType *RTy = BaseType->getAs<ReferenceType>())
00122       BaseType = RTy->getPointeeType();
00123     else
00124       llvm_unreachable("Unknown declarator!");
00125   }
00126   return BaseType;
00127 }
00128 
00129 static QualType getDeclType(Decl* D) {
00130   if (TypedefNameDecl* TDD = dyn_cast<TypedefNameDecl>(D))
00131     return TDD->getUnderlyingType();
00132   if (ValueDecl* VD = dyn_cast<ValueDecl>(D))
00133     return VD->getType();
00134   return QualType();
00135 }
00136 
00137 void Decl::printGroup(Decl** Begin, unsigned NumDecls,
00138                       raw_ostream &Out, const PrintingPolicy &Policy,
00139                       unsigned Indentation) {
00140   if (NumDecls == 1) {
00141     (*Begin)->print(Out, Policy, Indentation);
00142     return;
00143   }
00144 
00145   Decl** End = Begin + NumDecls;
00146   TagDecl* TD = dyn_cast<TagDecl>(*Begin);
00147   if (TD)
00148     ++Begin;
00149 
00150   PrintingPolicy SubPolicy(Policy);
00151   if (TD && TD->isCompleteDefinition()) {
00152     TD->print(Out, Policy, Indentation);
00153     Out << " ";
00154     SubPolicy.SuppressTag = true;
00155   }
00156 
00157   bool isFirst = true;
00158   for ( ; Begin != End; ++Begin) {
00159     if (isFirst) {
00160       SubPolicy.SuppressSpecifiers = false;
00161       isFirst = false;
00162     } else {
00163       if (!isFirst) Out << ", ";
00164       SubPolicy.SuppressSpecifiers = true;
00165     }
00166 
00167     (*Begin)->print(Out, SubPolicy, Indentation);
00168   }
00169 }
00170 
00171 LLVM_DUMP_METHOD void DeclContext::dumpDeclContext() const {
00172   // Get the translation unit
00173   const DeclContext *DC = this;
00174   while (!DC->isTranslationUnit())
00175     DC = DC->getParent();
00176   
00177   ASTContext &Ctx = cast<TranslationUnitDecl>(DC)->getASTContext();
00178   DeclPrinter Printer(llvm::errs(), Ctx.getPrintingPolicy(), 0);
00179   Printer.VisitDeclContext(const_cast<DeclContext *>(this), /*Indent=*/false);
00180 }
00181 
00182 raw_ostream& DeclPrinter::Indent(unsigned Indentation) {
00183   for (unsigned i = 0; i != Indentation; ++i)
00184     Out << "  ";
00185   return Out;
00186 }
00187 
00188 void DeclPrinter::prettyPrintAttributes(Decl *D) {
00189   if (Policy.PolishForDeclaration)
00190     return;
00191   
00192   if (D->hasAttrs()) {
00193     AttrVec &Attrs = D->getAttrs();
00194     for (AttrVec::const_iterator i=Attrs.begin(), e=Attrs.end(); i!=e; ++i) {
00195       Attr *A = *i;
00196       A->printPretty(Out, Policy);
00197     }
00198   }
00199 }
00200 
00201 void DeclPrinter::printDeclType(QualType T, StringRef DeclName, bool Pack) {
00202   // Normally, a PackExpansionType is written as T[3]... (for instance, as a
00203   // template argument), but if it is the type of a declaration, the ellipsis
00204   // is placed before the name being declared.
00205   if (auto *PET = T->getAs<PackExpansionType>()) {
00206     Pack = true;
00207     T = PET->getPattern();
00208   }
00209   T.print(Out, Policy, (Pack ? "..." : "") + DeclName);
00210 }
00211 
00212 void DeclPrinter::ProcessDeclGroup(SmallVectorImpl<Decl*>& Decls) {
00213   this->Indent();
00214   Decl::printGroup(Decls.data(), Decls.size(), Out, Policy, Indentation);
00215   Out << ";\n";
00216   Decls.clear();
00217 
00218 }
00219 
00220 void DeclPrinter::Print(AccessSpecifier AS) {
00221   switch(AS) {
00222   case AS_none:      llvm_unreachable("No access specifier!");
00223   case AS_public:    Out << "public"; break;
00224   case AS_protected: Out << "protected"; break;
00225   case AS_private:   Out << "private"; break;
00226   }
00227 }
00228 
00229 //----------------------------------------------------------------------------
00230 // Common C declarations
00231 //----------------------------------------------------------------------------
00232 
00233 void DeclPrinter::VisitDeclContext(DeclContext *DC, bool Indent) {
00234   if (Policy.TerseOutput)
00235     return;
00236 
00237   if (Indent)
00238     Indentation += Policy.Indentation;
00239 
00240   SmallVector<Decl*, 2> Decls;
00241   for (DeclContext::decl_iterator D = DC->decls_begin(), DEnd = DC->decls_end();
00242        D != DEnd; ++D) {
00243 
00244     // Don't print ObjCIvarDecls, as they are printed when visiting the
00245     // containing ObjCInterfaceDecl.
00246     if (isa<ObjCIvarDecl>(*D))
00247       continue;
00248 
00249     // Skip over implicit declarations in pretty-printing mode.
00250     if (D->isImplicit())
00251       continue;
00252 
00253     // The next bits of code handles stuff like "struct {int x;} a,b"; we're
00254     // forced to merge the declarations because there's no other way to
00255     // refer to the struct in question.  This limited merging is safe without
00256     // a bunch of other checks because it only merges declarations directly
00257     // referring to the tag, not typedefs.
00258     //
00259     // Check whether the current declaration should be grouped with a previous
00260     // unnamed struct.
00261     QualType CurDeclType = getDeclType(*D);
00262     if (!Decls.empty() && !CurDeclType.isNull()) {
00263       QualType BaseType = GetBaseType(CurDeclType);
00264       if (!BaseType.isNull() && isa<ElaboratedType>(BaseType))
00265         BaseType = cast<ElaboratedType>(BaseType)->getNamedType();
00266       if (!BaseType.isNull() && isa<TagType>(BaseType) &&
00267           cast<TagType>(BaseType)->getDecl() == Decls[0]) {
00268         Decls.push_back(*D);
00269         continue;
00270       }
00271     }
00272 
00273     // If we have a merged group waiting to be handled, handle it now.
00274     if (!Decls.empty())
00275       ProcessDeclGroup(Decls);
00276 
00277     // If the current declaration is an unnamed tag type, save it
00278     // so we can merge it with the subsequent declaration(s) using it.
00279     if (isa<TagDecl>(*D) && !cast<TagDecl>(*D)->getIdentifier()) {
00280       Decls.push_back(*D);
00281       continue;
00282     }
00283 
00284     if (isa<AccessSpecDecl>(*D)) {
00285       Indentation -= Policy.Indentation;
00286       this->Indent();
00287       Print(D->getAccess());
00288       Out << ":\n";
00289       Indentation += Policy.Indentation;
00290       continue;
00291     }
00292 
00293     this->Indent();
00294     Visit(*D);
00295 
00296     // FIXME: Need to be able to tell the DeclPrinter when
00297     const char *Terminator = nullptr;
00298     if (isa<OMPThreadPrivateDecl>(*D))
00299       Terminator = nullptr;
00300     else if (isa<FunctionDecl>(*D) &&
00301              cast<FunctionDecl>(*D)->isThisDeclarationADefinition())
00302       Terminator = nullptr;
00303     else if (isa<ObjCMethodDecl>(*D) && cast<ObjCMethodDecl>(*D)->getBody())
00304       Terminator = nullptr;
00305     else if (isa<NamespaceDecl>(*D) || isa<LinkageSpecDecl>(*D) ||
00306              isa<ObjCImplementationDecl>(*D) ||
00307              isa<ObjCInterfaceDecl>(*D) ||
00308              isa<ObjCProtocolDecl>(*D) ||
00309              isa<ObjCCategoryImplDecl>(*D) ||
00310              isa<ObjCCategoryDecl>(*D))
00311       Terminator = nullptr;
00312     else if (isa<EnumConstantDecl>(*D)) {
00313       DeclContext::decl_iterator Next = D;
00314       ++Next;
00315       if (Next != DEnd)
00316         Terminator = ",";
00317     } else
00318       Terminator = ";";
00319 
00320     if (Terminator)
00321       Out << Terminator;
00322     Out << "\n";
00323   }
00324 
00325   if (!Decls.empty())
00326     ProcessDeclGroup(Decls);
00327 
00328   if (Indent)
00329     Indentation -= Policy.Indentation;
00330 }
00331 
00332 void DeclPrinter::VisitTranslationUnitDecl(TranslationUnitDecl *D) {
00333   VisitDeclContext(D, false);
00334 }
00335 
00336 void DeclPrinter::VisitTypedefDecl(TypedefDecl *D) {
00337   if (!Policy.SuppressSpecifiers) {
00338     Out << "typedef ";
00339     
00340     if (D->isModulePrivate())
00341       Out << "__module_private__ ";
00342   }
00343   D->getTypeSourceInfo()->getType().print(Out, Policy, D->getName());
00344   prettyPrintAttributes(D);
00345 }
00346 
00347 void DeclPrinter::VisitTypeAliasDecl(TypeAliasDecl *D) {
00348   Out << "using " << *D;
00349   prettyPrintAttributes(D);
00350   Out << " = " << D->getTypeSourceInfo()->getType().getAsString(Policy);
00351 }
00352 
00353 void DeclPrinter::VisitEnumDecl(EnumDecl *D) {
00354   if (!Policy.SuppressSpecifiers && D->isModulePrivate())
00355     Out << "__module_private__ ";
00356   Out << "enum ";
00357   if (D->isScoped()) {
00358     if (D->isScopedUsingClassTag())
00359       Out << "class ";
00360     else
00361       Out << "struct ";
00362   }
00363   Out << *D;
00364 
00365   if (D->isFixed())
00366     Out << " : " << D->getIntegerType().stream(Policy);
00367 
00368   if (D->isCompleteDefinition()) {
00369     Out << " {\n";
00370     VisitDeclContext(D);
00371     Indent() << "}";
00372   }
00373   prettyPrintAttributes(D);
00374 }
00375 
00376 void DeclPrinter::VisitRecordDecl(RecordDecl *D) {
00377   if (!Policy.SuppressSpecifiers && D->isModulePrivate())
00378     Out << "__module_private__ ";
00379   Out << D->getKindName();
00380 
00381   prettyPrintAttributes(D);
00382 
00383   if (D->getIdentifier())
00384     Out << ' ' << *D;
00385 
00386   if (D->isCompleteDefinition()) {
00387     Out << " {\n";
00388     VisitDeclContext(D);
00389     Indent() << "}";
00390   }
00391 }
00392 
00393 void DeclPrinter::VisitEnumConstantDecl(EnumConstantDecl *D) {
00394   Out << *D;
00395   if (Expr *Init = D->getInitExpr()) {
00396     Out << " = ";
00397     Init->printPretty(Out, nullptr, Policy, Indentation);
00398   }
00399 }
00400 
00401 void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
00402   CXXConstructorDecl *CDecl = dyn_cast<CXXConstructorDecl>(D);
00403   CXXConversionDecl *ConversionDecl = dyn_cast<CXXConversionDecl>(D);
00404   if (!Policy.SuppressSpecifiers) {
00405     switch (D->getStorageClass()) {
00406     case SC_None: break;
00407     case SC_Extern: Out << "extern "; break;
00408     case SC_Static: Out << "static "; break;
00409     case SC_PrivateExtern: Out << "__private_extern__ "; break;
00410     case SC_Auto: case SC_Register: case SC_OpenCLWorkGroupLocal:
00411       llvm_unreachable("invalid for functions");
00412     }
00413 
00414     if (D->isInlineSpecified())  Out << "inline ";
00415     if (D->isVirtualAsWritten()) Out << "virtual ";
00416     if (D->isModulePrivate())    Out << "__module_private__ ";
00417     if (D->isConstexpr() && !D->isExplicitlyDefaulted()) Out << "constexpr ";
00418     if ((CDecl && CDecl->isExplicitSpecified()) ||
00419         (ConversionDecl && ConversionDecl->isExplicit()))
00420       Out << "explicit ";
00421   }
00422 
00423   PrintingPolicy SubPolicy(Policy);
00424   SubPolicy.SuppressSpecifiers = false;
00425   std::string Proto = D->getNameInfo().getAsString();
00426 
00427   QualType Ty = D->getType();
00428   while (const ParenType *PT = dyn_cast<ParenType>(Ty)) {
00429     Proto = '(' + Proto + ')';
00430     Ty = PT->getInnerType();
00431   }
00432 
00433   if (const FunctionType *AFT = Ty->getAs<FunctionType>()) {
00434     const FunctionProtoType *FT = nullptr;
00435     if (D->hasWrittenPrototype())
00436       FT = dyn_cast<FunctionProtoType>(AFT);
00437 
00438     Proto += "(";
00439     if (FT) {
00440       llvm::raw_string_ostream POut(Proto);
00441       DeclPrinter ParamPrinter(POut, SubPolicy, Indentation);
00442       for (unsigned i = 0, e = D->getNumParams(); i != e; ++i) {
00443         if (i) POut << ", ";
00444         ParamPrinter.VisitParmVarDecl(D->getParamDecl(i));
00445       }
00446 
00447       if (FT->isVariadic()) {
00448         if (D->getNumParams()) POut << ", ";
00449         POut << "...";
00450       }
00451     } else if (D->doesThisDeclarationHaveABody() && !D->hasPrototype()) {
00452       for (unsigned i = 0, e = D->getNumParams(); i != e; ++i) {
00453         if (i)
00454           Proto += ", ";
00455         Proto += D->getParamDecl(i)->getNameAsString();
00456       }
00457     }
00458 
00459     Proto += ")";
00460     
00461     if (FT) {
00462       if (FT->isConst())
00463         Proto += " const";
00464       if (FT->isVolatile())
00465         Proto += " volatile";
00466       if (FT->isRestrict())
00467         Proto += " restrict";
00468 
00469       switch (FT->getRefQualifier()) {
00470       case RQ_None:
00471         break;
00472       case RQ_LValue:
00473         Proto += " &";
00474         break;
00475       case RQ_RValue:
00476         Proto += " &&";
00477         break;
00478       }
00479     }
00480 
00481     if (FT && FT->hasDynamicExceptionSpec()) {
00482       Proto += " throw(";
00483       if (FT->getExceptionSpecType() == EST_MSAny)
00484         Proto += "...";
00485       else 
00486         for (unsigned I = 0, N = FT->getNumExceptions(); I != N; ++I) {
00487           if (I)
00488             Proto += ", ";
00489 
00490           Proto += FT->getExceptionType(I).getAsString(SubPolicy);
00491         }
00492       Proto += ")";
00493     } else if (FT && isNoexceptExceptionSpec(FT->getExceptionSpecType())) {
00494       Proto += " noexcept";
00495       if (FT->getExceptionSpecType() == EST_ComputedNoexcept) {
00496         Proto += "(";
00497         llvm::raw_string_ostream EOut(Proto);
00498         FT->getNoexceptExpr()->printPretty(EOut, nullptr, SubPolicy,
00499                                            Indentation);
00500         EOut.flush();
00501         Proto += EOut.str();
00502         Proto += ")";
00503       }
00504     }
00505 
00506     if (CDecl) {
00507       bool HasInitializerList = false;
00508       for (const auto *BMInitializer : CDecl->inits()) {
00509         if (BMInitializer->isInClassMemberInitializer())
00510           continue;
00511 
00512         if (!HasInitializerList) {
00513           Proto += " : ";
00514           Out << Proto;
00515           Proto.clear();
00516           HasInitializerList = true;
00517         } else
00518           Out << ", ";
00519 
00520         if (BMInitializer->isAnyMemberInitializer()) {
00521           FieldDecl *FD = BMInitializer->getAnyMember();
00522           Out << *FD;
00523         } else {
00524           Out << QualType(BMInitializer->getBaseClass(), 0).getAsString(Policy);
00525         }
00526         
00527         Out << "(";
00528         if (!BMInitializer->getInit()) {
00529           // Nothing to print
00530         } else {
00531           Expr *Init = BMInitializer->getInit();
00532           if (ExprWithCleanups *Tmp = dyn_cast<ExprWithCleanups>(Init))
00533             Init = Tmp->getSubExpr();
00534           
00535           Init = Init->IgnoreParens();
00536 
00537           Expr *SimpleInit = nullptr;
00538           Expr **Args = nullptr;
00539           unsigned NumArgs = 0;
00540           if (ParenListExpr *ParenList = dyn_cast<ParenListExpr>(Init)) {
00541             Args = ParenList->getExprs();
00542             NumArgs = ParenList->getNumExprs();
00543           } else if (CXXConstructExpr *Construct
00544                                         = dyn_cast<CXXConstructExpr>(Init)) {
00545             Args = Construct->getArgs();
00546             NumArgs = Construct->getNumArgs();
00547           } else
00548             SimpleInit = Init;
00549           
00550           if (SimpleInit)
00551             SimpleInit->printPretty(Out, nullptr, Policy, Indentation);
00552           else {
00553             for (unsigned I = 0; I != NumArgs; ++I) {
00554               assert(Args[I] != nullptr && "Expected non-null Expr");
00555               if (isa<CXXDefaultArgExpr>(Args[I]))
00556                 break;
00557               
00558               if (I)
00559                 Out << ", ";
00560               Args[I]->printPretty(Out, nullptr, Policy, Indentation);
00561             }
00562           }
00563         }
00564         Out << ")";
00565         if (BMInitializer->isPackExpansion())
00566           Out << "...";
00567       }
00568     } else if (!ConversionDecl && !isa<CXXDestructorDecl>(D)) {
00569       if (FT && FT->hasTrailingReturn()) {
00570         Out << "auto " << Proto << " -> ";
00571         Proto.clear();
00572       }
00573       AFT->getReturnType().print(Out, Policy, Proto);
00574       Proto.clear();
00575     }
00576     Out << Proto;
00577   } else {
00578     Ty.print(Out, Policy, Proto);
00579   }
00580 
00581   prettyPrintAttributes(D);
00582 
00583   if (D->isPure())
00584     Out << " = 0";
00585   else if (D->isDeletedAsWritten())
00586     Out << " = delete";
00587   else if (D->isExplicitlyDefaulted())
00588     Out << " = default";
00589   else if (D->doesThisDeclarationHaveABody() && !Policy.TerseOutput) {
00590     if (!D->hasPrototype() && D->getNumParams()) {
00591       // This is a K&R function definition, so we need to print the
00592       // parameters.
00593       Out << '\n';
00594       DeclPrinter ParamPrinter(Out, SubPolicy, Indentation);
00595       Indentation += Policy.Indentation;
00596       for (unsigned i = 0, e = D->getNumParams(); i != e; ++i) {
00597         Indent();
00598         ParamPrinter.VisitParmVarDecl(D->getParamDecl(i));
00599         Out << ";\n";
00600       }
00601       Indentation -= Policy.Indentation;
00602     } else
00603       Out << ' ';
00604 
00605     if (D->getBody())
00606       D->getBody()->printPretty(Out, nullptr, SubPolicy, Indentation);
00607     Out << '\n';
00608   }
00609 }
00610 
00611 void DeclPrinter::VisitFriendDecl(FriendDecl *D) {
00612   if (TypeSourceInfo *TSI = D->getFriendType()) {
00613     unsigned NumTPLists = D->getFriendTypeNumTemplateParameterLists();
00614     for (unsigned i = 0; i < NumTPLists; ++i)
00615       PrintTemplateParameters(D->getFriendTypeTemplateParameterList(i));
00616     Out << "friend ";
00617     Out << " " << TSI->getType().getAsString(Policy);
00618   }
00619   else if (FunctionDecl *FD =
00620       dyn_cast<FunctionDecl>(D->getFriendDecl())) {
00621     Out << "friend ";
00622     VisitFunctionDecl(FD);
00623   }
00624   else if (FunctionTemplateDecl *FTD =
00625            dyn_cast<FunctionTemplateDecl>(D->getFriendDecl())) {
00626     Out << "friend ";
00627     VisitFunctionTemplateDecl(FTD);
00628   }
00629   else if (ClassTemplateDecl *CTD =
00630            dyn_cast<ClassTemplateDecl>(D->getFriendDecl())) {
00631     Out << "friend ";
00632     VisitRedeclarableTemplateDecl(CTD);
00633   }
00634 }
00635 
00636 void DeclPrinter::VisitFieldDecl(FieldDecl *D) {
00637   if (!Policy.SuppressSpecifiers && D->isMutable())
00638     Out << "mutable ";
00639   if (!Policy.SuppressSpecifiers && D->isModulePrivate())
00640     Out << "__module_private__ ";
00641 
00642   Out << D->getASTContext().getUnqualifiedObjCPointerType(D->getType()).
00643             stream(Policy, D->getName());
00644 
00645   if (D->isBitField()) {
00646     Out << " : ";
00647     D->getBitWidth()->printPretty(Out, nullptr, Policy, Indentation);
00648   }
00649 
00650   Expr *Init = D->getInClassInitializer();
00651   if (!Policy.SuppressInitializers && Init) {
00652     if (D->getInClassInitStyle() == ICIS_ListInit)
00653       Out << " ";
00654     else
00655       Out << " = ";
00656     Init->printPretty(Out, nullptr, Policy, Indentation);
00657   }
00658   prettyPrintAttributes(D);
00659 }
00660 
00661 void DeclPrinter::VisitLabelDecl(LabelDecl *D) {
00662   Out << *D << ":";
00663 }
00664 
00665 void DeclPrinter::VisitVarDecl(VarDecl *D) {
00666   if (!Policy.SuppressSpecifiers) {
00667     StorageClass SC = D->getStorageClass();
00668     if (SC != SC_None)
00669       Out << VarDecl::getStorageClassSpecifierString(SC) << " ";
00670 
00671     switch (D->getTSCSpec()) {
00672     case TSCS_unspecified:
00673       break;
00674     case TSCS___thread:
00675       Out << "__thread ";
00676       break;
00677     case TSCS__Thread_local:
00678       Out << "_Thread_local ";
00679       break;
00680     case TSCS_thread_local:
00681       Out << "thread_local ";
00682       break;
00683     }
00684 
00685     if (D->isModulePrivate())
00686       Out << "__module_private__ ";
00687   }
00688 
00689   QualType T = D->getTypeSourceInfo()
00690     ? D->getTypeSourceInfo()->getType()
00691     : D->getASTContext().getUnqualifiedObjCPointerType(D->getType());
00692   printDeclType(T, D->getName());
00693   Expr *Init = D->getInit();
00694   if (!Policy.SuppressInitializers && Init) {
00695     bool ImplicitInit = false;
00696     if (CXXConstructExpr *Construct =
00697             dyn_cast<CXXConstructExpr>(Init->IgnoreImplicit())) {
00698       if (D->getInitStyle() == VarDecl::CallInit &&
00699           !Construct->isListInitialization()) {
00700         ImplicitInit = Construct->getNumArgs() == 0 ||
00701           Construct->getArg(0)->isDefaultArgument();
00702       }
00703     }
00704     if (!ImplicitInit) {
00705       if ((D->getInitStyle() == VarDecl::CallInit) && !isa<ParenListExpr>(Init))
00706         Out << "(";
00707       else if (D->getInitStyle() == VarDecl::CInit) {
00708         Out << " = ";
00709       }
00710       Init->printPretty(Out, nullptr, Policy, Indentation);
00711       if ((D->getInitStyle() == VarDecl::CallInit) && !isa<ParenListExpr>(Init))
00712         Out << ")";
00713     }
00714   }
00715   prettyPrintAttributes(D);
00716 }
00717 
00718 void DeclPrinter::VisitParmVarDecl(ParmVarDecl *D) {
00719   VisitVarDecl(D);
00720 }
00721 
00722 void DeclPrinter::VisitFileScopeAsmDecl(FileScopeAsmDecl *D) {
00723   Out << "__asm (";
00724   D->getAsmString()->printPretty(Out, nullptr, Policy, Indentation);
00725   Out << ")";
00726 }
00727 
00728 void DeclPrinter::VisitImportDecl(ImportDecl *D) {
00729   Out << "@import " << D->getImportedModule()->getFullModuleName()
00730       << ";\n";
00731 }
00732 
00733 void DeclPrinter::VisitStaticAssertDecl(StaticAssertDecl *D) {
00734   Out << "static_assert(";
00735   D->getAssertExpr()->printPretty(Out, nullptr, Policy, Indentation);
00736   Out << ", ";
00737   D->getMessage()->printPretty(Out, nullptr, Policy, Indentation);
00738   Out << ")";
00739 }
00740 
00741 //----------------------------------------------------------------------------
00742 // C++ declarations
00743 //----------------------------------------------------------------------------
00744 void DeclPrinter::VisitNamespaceDecl(NamespaceDecl *D) {
00745   if (D->isInline())
00746     Out << "inline ";
00747   Out << "namespace " << *D << " {\n";
00748   VisitDeclContext(D);
00749   Indent() << "}";
00750 }
00751 
00752 void DeclPrinter::VisitUsingDirectiveDecl(UsingDirectiveDecl *D) {
00753   Out << "using namespace ";
00754   if (D->getQualifier())
00755     D->getQualifier()->print(Out, Policy);
00756   Out << *D->getNominatedNamespaceAsWritten();
00757 }
00758 
00759 void DeclPrinter::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) {
00760   Out << "namespace " << *D << " = ";
00761   if (D->getQualifier())
00762     D->getQualifier()->print(Out, Policy);
00763   Out << *D->getAliasedNamespace();
00764 }
00765 
00766 void DeclPrinter::VisitEmptyDecl(EmptyDecl *D) {
00767   prettyPrintAttributes(D);
00768 }
00769 
00770 void DeclPrinter::VisitCXXRecordDecl(CXXRecordDecl *D) {
00771   if (!Policy.SuppressSpecifiers && D->isModulePrivate())
00772     Out << "__module_private__ ";
00773   Out << D->getKindName();
00774 
00775   prettyPrintAttributes(D);
00776 
00777   if (D->getIdentifier())
00778     Out << ' ' << *D;
00779 
00780   if (D->isCompleteDefinition()) {
00781     // Print the base classes
00782     if (D->getNumBases()) {
00783       Out << " : ";
00784       for (CXXRecordDecl::base_class_iterator Base = D->bases_begin(),
00785              BaseEnd = D->bases_end(); Base != BaseEnd; ++Base) {
00786         if (Base != D->bases_begin())
00787           Out << ", ";
00788 
00789         if (Base->isVirtual())
00790           Out << "virtual ";
00791 
00792         AccessSpecifier AS = Base->getAccessSpecifierAsWritten();
00793         if (AS != AS_none) {
00794           Print(AS);
00795           Out << " ";
00796         }
00797         Out << Base->getType().getAsString(Policy);
00798 
00799         if (Base->isPackExpansion())
00800           Out << "...";
00801       }
00802     }
00803 
00804     // Print the class definition
00805     // FIXME: Doesn't print access specifiers, e.g., "public:"
00806     Out << " {\n";
00807     VisitDeclContext(D);
00808     Indent() << "}";
00809   }
00810 }
00811 
00812 void DeclPrinter::VisitLinkageSpecDecl(LinkageSpecDecl *D) {
00813   const char *l;
00814   if (D->getLanguage() == LinkageSpecDecl::lang_c)
00815     l = "C";
00816   else {
00817     assert(D->getLanguage() == LinkageSpecDecl::lang_cxx &&
00818            "unknown language in linkage specification");
00819     l = "C++";
00820   }
00821 
00822   Out << "extern \"" << l << "\" ";
00823   if (D->hasBraces()) {
00824     Out << "{\n";
00825     VisitDeclContext(D);
00826     Indent() << "}";
00827   } else
00828     Visit(*D->decls_begin());
00829 }
00830 
00831 void DeclPrinter::PrintTemplateParameters(const TemplateParameterList *Params,
00832                                           const TemplateArgumentList *Args) {
00833   assert(Params);
00834   assert(!Args || Params->size() == Args->size());
00835 
00836   Out << "template <";
00837 
00838   for (unsigned i = 0, e = Params->size(); i != e; ++i) {
00839     if (i != 0)
00840       Out << ", ";
00841 
00842     const Decl *Param = Params->getParam(i);
00843     if (const TemplateTypeParmDecl *TTP =
00844           dyn_cast<TemplateTypeParmDecl>(Param)) {
00845 
00846       if (TTP->wasDeclaredWithTypename())
00847         Out << "typename ";
00848       else
00849         Out << "class ";
00850 
00851       if (TTP->isParameterPack())
00852         Out << "...";
00853 
00854       Out << *TTP;
00855 
00856       if (Args) {
00857         Out << " = ";
00858         Args->get(i).print(Policy, Out);
00859       } else if (TTP->hasDefaultArgument()) {
00860         Out << " = ";
00861         Out << TTP->getDefaultArgument().getAsString(Policy);
00862       };
00863     } else if (const NonTypeTemplateParmDecl *NTTP =
00864                  dyn_cast<NonTypeTemplateParmDecl>(Param)) {
00865       StringRef Name;
00866       if (IdentifierInfo *II = NTTP->getIdentifier())
00867         Name = II->getName();
00868       printDeclType(NTTP->getType(), Name, NTTP->isParameterPack());
00869 
00870       if (Args) {
00871         Out << " = ";
00872         Args->get(i).print(Policy, Out);
00873       } else if (NTTP->hasDefaultArgument()) {
00874         Out << " = ";
00875         NTTP->getDefaultArgument()->printPretty(Out, nullptr, Policy,
00876                                                 Indentation);
00877       }
00878     } else if (const TemplateTemplateParmDecl *TTPD =
00879                  dyn_cast<TemplateTemplateParmDecl>(Param)) {
00880       VisitTemplateDecl(TTPD);
00881       // FIXME: print the default argument, if present.
00882     }
00883   }
00884 
00885   Out << "> ";
00886 }
00887 
00888 void DeclPrinter::VisitTemplateDecl(const TemplateDecl *D) {
00889   PrintTemplateParameters(D->getTemplateParameters());
00890 
00891   if (const TemplateTemplateParmDecl *TTP =
00892         dyn_cast<TemplateTemplateParmDecl>(D)) {
00893     Out << "class ";
00894     if (TTP->isParameterPack())
00895       Out << "...";
00896     Out << D->getName();
00897   } else {
00898     Visit(D->getTemplatedDecl());
00899   }
00900 }
00901 
00902 void DeclPrinter::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
00903   if (PrintInstantiation) {
00904     TemplateParameterList *Params = D->getTemplateParameters();
00905     for (auto *I : D->specializations()) {
00906       PrintTemplateParameters(Params, I->getTemplateSpecializationArgs());
00907       Visit(I);
00908     }
00909   }
00910 
00911   return VisitRedeclarableTemplateDecl(D);
00912 }
00913 
00914 void DeclPrinter::VisitClassTemplateDecl(ClassTemplateDecl *D) {
00915   if (PrintInstantiation) {
00916     TemplateParameterList *Params = D->getTemplateParameters();
00917     for (auto *I : D->specializations()) {
00918       PrintTemplateParameters(Params, &I->getTemplateArgs());
00919       Visit(I);
00920       Out << '\n';
00921     }
00922   }
00923 
00924   return VisitRedeclarableTemplateDecl(D);
00925 }
00926 
00927 //----------------------------------------------------------------------------
00928 // Objective-C declarations
00929 //----------------------------------------------------------------------------
00930 
00931 void DeclPrinter::VisitObjCMethodDecl(ObjCMethodDecl *OMD) {
00932   if (OMD->isInstanceMethod())
00933     Out << "- ";
00934   else
00935     Out << "+ ";
00936   if (!OMD->getReturnType().isNull())
00937     Out << '(' << OMD->getASTContext()
00938                       .getUnqualifiedObjCPointerType(OMD->getReturnType())
00939                       .getAsString(Policy) << ")";
00940 
00941   std::string name = OMD->getSelector().getAsString();
00942   std::string::size_type pos, lastPos = 0;
00943   for (const auto *PI : OMD->params()) {
00944     // FIXME: selector is missing here!
00945     pos = name.find_first_of(':', lastPos);
00946     Out << " " << name.substr(lastPos, pos - lastPos);
00947     Out << ":(" << PI->getASTContext().getUnqualifiedObjCPointerType(PI->getType()).
00948                       getAsString(Policy) << ')' << *PI;
00949     lastPos = pos + 1;
00950   }
00951 
00952   if (OMD->param_begin() == OMD->param_end())
00953     Out << " " << name;
00954 
00955   if (OMD->isVariadic())
00956       Out << ", ...";
00957   
00958   prettyPrintAttributes(OMD);
00959 
00960   if (OMD->getBody() && !Policy.TerseOutput) {
00961     Out << ' ';
00962     OMD->getBody()->printPretty(Out, nullptr, Policy);
00963   }
00964   else if (Policy.PolishForDeclaration)
00965     Out << ';';
00966 }
00967 
00968 void DeclPrinter::VisitObjCImplementationDecl(ObjCImplementationDecl *OID) {
00969   std::string I = OID->getNameAsString();
00970   ObjCInterfaceDecl *SID = OID->getSuperClass();
00971 
00972   bool eolnOut = false;
00973   if (SID)
00974     Out << "@implementation " << I << " : " << *SID;
00975   else
00976     Out << "@implementation " << I;
00977   
00978   if (OID->ivar_size() > 0) {
00979     Out << "{\n";
00980     eolnOut = true;
00981     Indentation += Policy.Indentation;
00982     for (const auto *I : OID->ivars()) {
00983       Indent() << I->getASTContext().getUnqualifiedObjCPointerType(I->getType()).
00984                     getAsString(Policy) << ' ' << *I << ";\n";
00985     }
00986     Indentation -= Policy.Indentation;
00987     Out << "}\n";
00988   }
00989   else if (SID || (OID->decls_begin() != OID->decls_end())) {
00990     Out << "\n";
00991     eolnOut = true;
00992   }
00993   VisitDeclContext(OID, false);
00994   if (!eolnOut)
00995     Out << "\n";
00996   Out << "@end";
00997 }
00998 
00999 void DeclPrinter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *OID) {
01000   std::string I = OID->getNameAsString();
01001   ObjCInterfaceDecl *SID = OID->getSuperClass();
01002 
01003   if (!OID->isThisDeclarationADefinition()) {
01004     Out << "@class " << I << ";";
01005     return;
01006   }
01007   bool eolnOut = false;
01008   if (SID)
01009     Out << "@interface " << I << " : " << *SID;
01010   else
01011     Out << "@interface " << I;
01012 
01013   // Protocols?
01014   const ObjCList<ObjCProtocolDecl> &Protocols = OID->getReferencedProtocols();
01015   if (!Protocols.empty()) {
01016     for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
01017          E = Protocols.end(); I != E; ++I)
01018       Out << (I == Protocols.begin() ? '<' : ',') << **I;
01019     Out << "> ";
01020   }
01021 
01022   if (OID->ivar_size() > 0) {
01023     Out << "{\n";
01024     eolnOut = true;
01025     Indentation += Policy.Indentation;
01026     for (const auto *I : OID->ivars()) {
01027       Indent() << I->getASTContext()
01028                       .getUnqualifiedObjCPointerType(I->getType())
01029                       .getAsString(Policy) << ' ' << *I << ";\n";
01030     }
01031     Indentation -= Policy.Indentation;
01032     Out << "}\n";
01033   }
01034   else if (SID || (OID->decls_begin() != OID->decls_end())) {
01035     Out << "\n";
01036     eolnOut = true;
01037   }
01038 
01039   VisitDeclContext(OID, false);
01040   if (!eolnOut)
01041     Out << "\n";
01042   Out << "@end";
01043   // FIXME: implement the rest...
01044 }
01045 
01046 void DeclPrinter::VisitObjCProtocolDecl(ObjCProtocolDecl *PID) {
01047   if (!PID->isThisDeclarationADefinition()) {
01048     Out << "@protocol " << *PID << ";\n";
01049     return;
01050   }
01051   // Protocols?
01052   const ObjCList<ObjCProtocolDecl> &Protocols = PID->getReferencedProtocols();
01053   if (!Protocols.empty()) {
01054     Out << "@protocol " << *PID;
01055     for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
01056          E = Protocols.end(); I != E; ++I)
01057       Out << (I == Protocols.begin() ? '<' : ',') << **I;
01058     Out << ">\n";
01059   } else
01060     Out << "@protocol " << *PID << '\n';
01061   VisitDeclContext(PID, false);
01062   Out << "@end";
01063 }
01064 
01065 void DeclPrinter::VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *PID) {
01066   Out << "@implementation " << *PID->getClassInterface() << '(' << *PID <<")\n";
01067 
01068   VisitDeclContext(PID, false);
01069   Out << "@end";
01070   // FIXME: implement the rest...
01071 }
01072 
01073 void DeclPrinter::VisitObjCCategoryDecl(ObjCCategoryDecl *PID) {
01074   Out << "@interface " << *PID->getClassInterface() << '(' << *PID << ")\n";
01075   if (PID->ivar_size() > 0) {
01076     Out << "{\n";
01077     Indentation += Policy.Indentation;
01078     for (const auto *I : PID->ivars())
01079       Indent() << I->getASTContext().getUnqualifiedObjCPointerType(I->getType()).
01080                     getAsString(Policy) << ' ' << *I << ";\n";
01081     Indentation -= Policy.Indentation;
01082     Out << "}\n";
01083   }
01084   
01085   VisitDeclContext(PID, false);
01086   Out << "@end";
01087 
01088   // FIXME: implement the rest...
01089 }
01090 
01091 void DeclPrinter::VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *AID) {
01092   Out << "@compatibility_alias " << *AID
01093       << ' ' << *AID->getClassInterface() << ";\n";
01094 }
01095 
01096 /// PrintObjCPropertyDecl - print a property declaration.
01097 ///
01098 void DeclPrinter::VisitObjCPropertyDecl(ObjCPropertyDecl *PDecl) {
01099   if (PDecl->getPropertyImplementation() == ObjCPropertyDecl::Required)
01100     Out << "@required\n";
01101   else if (PDecl->getPropertyImplementation() == ObjCPropertyDecl::Optional)
01102     Out << "@optional\n";
01103 
01104   Out << "@property";
01105   if (PDecl->getPropertyAttributes() != ObjCPropertyDecl::OBJC_PR_noattr) {
01106     bool first = true;
01107     Out << " (";
01108     if (PDecl->getPropertyAttributes() &
01109         ObjCPropertyDecl::OBJC_PR_readonly) {
01110       Out << (first ? ' ' : ',') << "readonly";
01111       first = false;
01112     }
01113 
01114     if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_getter) {
01115       Out << (first ? ' ' : ',') << "getter = ";
01116       PDecl->getGetterName().print(Out);
01117       first = false;
01118     }
01119     if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_setter) {
01120       Out << (first ? ' ' : ',') << "setter = ";
01121       PDecl->getSetterName().print(Out);
01122       first = false;
01123     }
01124 
01125     if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_assign) {
01126       Out << (first ? ' ' : ',') << "assign";
01127       first = false;
01128     }
01129 
01130     if (PDecl->getPropertyAttributes() &
01131         ObjCPropertyDecl::OBJC_PR_readwrite) {
01132       Out << (first ? ' ' : ',') << "readwrite";
01133       first = false;
01134     }
01135 
01136     if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_retain) {
01137       Out << (first ? ' ' : ',') << "retain";
01138       first = false;
01139     }
01140 
01141     if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_strong) {
01142       Out << (first ? ' ' : ',') << "strong";
01143       first = false;
01144     }
01145 
01146     if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_copy) {
01147       Out << (first ? ' ' : ',') << "copy";
01148       first = false;
01149     }
01150 
01151     if (PDecl->getPropertyAttributes() &
01152         ObjCPropertyDecl::OBJC_PR_nonatomic) {
01153       Out << (first ? ' ' : ',') << "nonatomic";
01154       first = false;
01155     }
01156     if (PDecl->getPropertyAttributes() &
01157         ObjCPropertyDecl::OBJC_PR_atomic) {
01158       Out << (first ? ' ' : ',') << "atomic";
01159       first = false;
01160     }
01161     
01162     (void) first; // Silence dead store warning due to idiomatic code.
01163     Out << " )";
01164   }
01165   Out << ' ' << PDecl->getASTContext().getUnqualifiedObjCPointerType(PDecl->getType()).
01166                   getAsString(Policy) << ' ' << *PDecl;
01167   if (Policy.PolishForDeclaration)
01168     Out << ';';
01169 }
01170 
01171 void DeclPrinter::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *PID) {
01172   if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize)
01173     Out << "@synthesize ";
01174   else
01175     Out << "@dynamic ";
01176   Out << *PID->getPropertyDecl();
01177   if (PID->getPropertyIvarDecl())
01178     Out << '=' << *PID->getPropertyIvarDecl();
01179 }
01180 
01181 void DeclPrinter::VisitUsingDecl(UsingDecl *D) {
01182   if (!D->isAccessDeclaration())
01183     Out << "using ";
01184   if (D->hasTypename())
01185     Out << "typename ";
01186   D->getQualifier()->print(Out, Policy);
01187   Out << *D;
01188 }
01189 
01190 void
01191 DeclPrinter::VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D) {
01192   Out << "using typename ";
01193   D->getQualifier()->print(Out, Policy);
01194   Out << D->getDeclName();
01195 }
01196 
01197 void DeclPrinter::VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D) {
01198   if (!D->isAccessDeclaration())
01199     Out << "using ";
01200   D->getQualifier()->print(Out, Policy);
01201   Out << D->getName();
01202 }
01203 
01204 void DeclPrinter::VisitUsingShadowDecl(UsingShadowDecl *D) {
01205   // ignore
01206 }
01207 
01208 void DeclPrinter::VisitOMPThreadPrivateDecl(OMPThreadPrivateDecl *D) {
01209   Out << "#pragma omp threadprivate";
01210   if (!D->varlist_empty()) {
01211     for (OMPThreadPrivateDecl::varlist_iterator I = D->varlist_begin(),
01212                                                 E = D->varlist_end();
01213                                                 I != E; ++I) {
01214       Out << (I == D->varlist_begin() ? '(' : ',');
01215       NamedDecl *ND = cast<NamedDecl>(cast<DeclRefExpr>(*I)->getDecl());
01216       ND->printQualifiedName(Out);
01217     }
01218     Out << ")";
01219   }
01220 }
01221