clang API Documentation
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