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