TypePrinter.cpp revision 52fc314e1b5e1baee6305067cf831763d02bd243
1//===--- TypePrinter.cpp - Pretty-Print Clang Types -----------------------===// 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 contains code to print types from Clang's type system. 11// 12//===----------------------------------------------------------------------===// 13 14#include "clang/AST/Decl.h" 15#include "clang/AST/DeclObjC.h" 16#include "clang/AST/DeclTemplate.h" 17#include "clang/AST/Expr.h" 18#include "clang/AST/Type.h" 19#include "clang/AST/PrettyPrinter.h" 20#include "clang/Basic/LangOptions.h" 21#include "clang/Basic/SourceManager.h" 22#include "llvm/ADT/StringExtras.h" 23#include "llvm/Support/raw_ostream.h" 24using namespace clang; 25 26namespace { 27 class TypePrinter { 28 PrintingPolicy Policy; 29 30 public: 31 explicit TypePrinter(const PrintingPolicy &Policy) : Policy(Policy) { } 32 33 void Print(QualType T, std::string &S); 34 void AppendScope(DeclContext *DC, std::string &S); 35 void PrintTag(TagDecl *T, std::string &S); 36#define ABSTRACT_TYPE(CLASS, PARENT) 37#define TYPE(CLASS, PARENT) \ 38 void Print##CLASS(const CLASS##Type *T, std::string &S); 39#include "clang/AST/TypeNodes.def" 40 }; 41} 42 43static void AppendTypeQualList(std::string &S, unsigned TypeQuals) { 44 if (TypeQuals & Qualifiers::Const) { 45 if (!S.empty()) S += ' '; 46 S += "const"; 47 } 48 if (TypeQuals & Qualifiers::Volatile) { 49 if (!S.empty()) S += ' '; 50 S += "volatile"; 51 } 52 if (TypeQuals & Qualifiers::Restrict) { 53 if (!S.empty()) S += ' '; 54 S += "restrict"; 55 } 56} 57 58void TypePrinter::Print(QualType T, std::string &S) { 59 if (T.isNull()) { 60 S += "NULL TYPE"; 61 return; 62 } 63 64 if (Policy.SuppressSpecifiers && T->isSpecifierType()) 65 return; 66 67 // Print qualifiers as appropriate. 68 Qualifiers Quals = T.getLocalQualifiers(); 69 if (!Quals.empty()) { 70 std::string TQS; 71 Quals.getAsStringInternal(TQS, Policy); 72 73 if (!S.empty()) { 74 TQS += ' '; 75 TQS += S; 76 } 77 std::swap(S, TQS); 78 } 79 80 switch (T->getTypeClass()) { 81#define ABSTRACT_TYPE(CLASS, PARENT) 82#define TYPE(CLASS, PARENT) case Type::CLASS: \ 83 Print##CLASS(cast<CLASS##Type>(T.getTypePtr()), S); \ 84 break; 85#include "clang/AST/TypeNodes.def" 86 } 87} 88 89void TypePrinter::PrintBuiltin(const BuiltinType *T, std::string &S) { 90 if (S.empty()) { 91 S = T->getName(Policy.LangOpts); 92 } else { 93 // Prefix the basic type, e.g. 'int X'. 94 S = ' ' + S; 95 S = T->getName(Policy.LangOpts) + S; 96 } 97} 98 99void TypePrinter::PrintComplex(const ComplexType *T, std::string &S) { 100 Print(T->getElementType(), S); 101 S = "_Complex " + S; 102} 103 104void TypePrinter::PrintPointer(const PointerType *T, std::string &S) { 105 S = '*' + S; 106 107 // Handle things like 'int (*A)[4];' correctly. 108 // FIXME: this should include vectors, but vectors use attributes I guess. 109 if (isa<ArrayType>(T->getPointeeType())) 110 S = '(' + S + ')'; 111 112 Print(T->getPointeeType(), S); 113} 114 115void TypePrinter::PrintBlockPointer(const BlockPointerType *T, std::string &S) { 116 S = '^' + S; 117 Print(T->getPointeeType(), S); 118} 119 120void TypePrinter::PrintLValueReference(const LValueReferenceType *T, 121 std::string &S) { 122 S = '&' + S; 123 124 // Handle things like 'int (&A)[4];' correctly. 125 // FIXME: this should include vectors, but vectors use attributes I guess. 126 if (isa<ArrayType>(T->getPointeeTypeAsWritten())) 127 S = '(' + S + ')'; 128 129 Print(T->getPointeeTypeAsWritten(), S); 130} 131 132void TypePrinter::PrintRValueReference(const RValueReferenceType *T, 133 std::string &S) { 134 S = "&&" + S; 135 136 // Handle things like 'int (&&A)[4];' correctly. 137 // FIXME: this should include vectors, but vectors use attributes I guess. 138 if (isa<ArrayType>(T->getPointeeTypeAsWritten())) 139 S = '(' + S + ')'; 140 141 Print(T->getPointeeTypeAsWritten(), S); 142} 143 144void TypePrinter::PrintMemberPointer(const MemberPointerType *T, 145 std::string &S) { 146 std::string C; 147 Print(QualType(T->getClass(), 0), C); 148 C += "::*"; 149 S = C + S; 150 151 // Handle things like 'int (Cls::*A)[4];' correctly. 152 // FIXME: this should include vectors, but vectors use attributes I guess. 153 if (isa<ArrayType>(T->getPointeeType())) 154 S = '(' + S + ')'; 155 156 Print(T->getPointeeType(), S); 157} 158 159void TypePrinter::PrintConstantArray(const ConstantArrayType *T, 160 std::string &S) { 161 S += '['; 162 S += llvm::utostr(T->getSize().getZExtValue()); 163 S += ']'; 164 165 Print(T->getElementType(), S); 166} 167 168void TypePrinter::PrintIncompleteArray(const IncompleteArrayType *T, 169 std::string &S) { 170 S += "[]"; 171 Print(T->getElementType(), S); 172} 173 174void TypePrinter::PrintVariableArray(const VariableArrayType *T, 175 std::string &S) { 176 S += '['; 177 178 if (T->getIndexTypeQualifiers().hasQualifiers()) { 179 AppendTypeQualList(S, T->getIndexTypeCVRQualifiers()); 180 S += ' '; 181 } 182 183 if (T->getSizeModifier() == VariableArrayType::Static) 184 S += "static"; 185 else if (T->getSizeModifier() == VariableArrayType::Star) 186 S += '*'; 187 188 if (T->getSizeExpr()) { 189 std::string SStr; 190 llvm::raw_string_ostream s(SStr); 191 T->getSizeExpr()->printPretty(s, 0, Policy); 192 S += s.str(); 193 } 194 S += ']'; 195 196 Print(T->getElementType(), S); 197} 198 199void TypePrinter::PrintDependentSizedArray(const DependentSizedArrayType *T, 200 std::string &S) { 201 S += '['; 202 203 if (T->getSizeExpr()) { 204 std::string SStr; 205 llvm::raw_string_ostream s(SStr); 206 T->getSizeExpr()->printPretty(s, 0, Policy); 207 S += s.str(); 208 } 209 S += ']'; 210 211 Print(T->getElementType(), S); 212} 213 214void TypePrinter::PrintDependentSizedExtVector( 215 const DependentSizedExtVectorType *T, 216 std::string &S) { 217 Print(T->getElementType(), S); 218 219 S += " __attribute__((ext_vector_type("; 220 if (T->getSizeExpr()) { 221 std::string SStr; 222 llvm::raw_string_ostream s(SStr); 223 T->getSizeExpr()->printPretty(s, 0, Policy); 224 S += s.str(); 225 } 226 S += ")))"; 227} 228 229void TypePrinter::PrintVector(const VectorType *T, std::string &S) { 230 if (T->getAltiVecSpecific() != VectorType::NotAltiVec) { 231 if (T->getAltiVecSpecific() == VectorType::Pixel) 232 S = "__vector __pixel " + S; 233 else { 234 Print(T->getElementType(), S); 235 S = ((T->getAltiVecSpecific() == VectorType::Bool) 236 ? "__vector __bool " : "__vector ") + S; 237 } 238 } else { 239 // FIXME: We prefer to print the size directly here, but have no way 240 // to get the size of the type. 241 Print(T->getElementType(), S); 242 std::string V = "__attribute__((__vector_size__("; 243 V += llvm::utostr_32(T->getNumElements()); // convert back to bytes. 244 std::string ET; 245 Print(T->getElementType(), ET); 246 V += " * sizeof(" + ET + ")))) "; 247 S = V + S; 248 } 249} 250 251void TypePrinter::PrintExtVector(const ExtVectorType *T, std::string &S) { 252 S += " __attribute__((ext_vector_type("; 253 S += llvm::utostr_32(T->getNumElements()); 254 S += ")))"; 255 Print(T->getElementType(), S); 256} 257 258void TypePrinter::PrintFunctionProto(const FunctionProtoType *T, 259 std::string &S) { 260 // If needed for precedence reasons, wrap the inner part in grouping parens. 261 if (!S.empty()) 262 S = "(" + S + ")"; 263 264 S += "("; 265 std::string Tmp; 266 PrintingPolicy ParamPolicy(Policy); 267 ParamPolicy.SuppressSpecifiers = false; 268 for (unsigned i = 0, e = T->getNumArgs(); i != e; ++i) { 269 if (i) S += ", "; 270 Print(T->getArgType(i), Tmp); 271 S += Tmp; 272 Tmp.clear(); 273 } 274 275 if (T->isVariadic()) { 276 if (T->getNumArgs()) 277 S += ", "; 278 S += "..."; 279 } else if (T->getNumArgs() == 0 && !Policy.LangOpts.CPlusPlus) { 280 // Do not emit int() if we have a proto, emit 'int(void)'. 281 S += "void"; 282 } 283 284 S += ")"; 285 286 FunctionType::ExtInfo Info = T->getExtInfo(); 287 switch(Info.getCC()) { 288 case CC_Default: 289 default: break; 290 case CC_C: 291 S += " __attribute__((cdecl))"; 292 break; 293 case CC_X86StdCall: 294 S += " __attribute__((stdcall))"; 295 break; 296 case CC_X86FastCall: 297 S += " __attribute__((fastcall))"; 298 break; 299 case CC_X86ThisCall: 300 S += " __attribute__((thiscall))"; 301 break; 302 case CC_X86Pascal: 303 S += " __attribute__((pascal))"; 304 break; 305 } 306 if (Info.getNoReturn()) 307 S += " __attribute__((noreturn))"; 308 if (Info.getRegParm()) 309 S += " __attribute__((regparm (" + 310 llvm::utostr_32(Info.getRegParm()) + ")))"; 311 312 if (T->hasExceptionSpec()) { 313 S += " throw("; 314 if (T->hasAnyExceptionSpec()) 315 S += "..."; 316 else 317 for (unsigned I = 0, N = T->getNumExceptions(); I != N; ++I) { 318 if (I) 319 S += ", "; 320 321 std::string ExceptionType; 322 Print(T->getExceptionType(I), ExceptionType); 323 S += ExceptionType; 324 } 325 S += ")"; 326 } 327 328 AppendTypeQualList(S, T->getTypeQuals()); 329 330 Print(T->getResultType(), S); 331} 332 333void TypePrinter::PrintFunctionNoProto(const FunctionNoProtoType *T, 334 std::string &S) { 335 // If needed for precedence reasons, wrap the inner part in grouping parens. 336 if (!S.empty()) 337 S = "(" + S + ")"; 338 339 S += "()"; 340 if (T->getNoReturnAttr()) 341 S += " __attribute__((noreturn))"; 342 Print(T->getResultType(), S); 343} 344 345static void PrintTypeSpec(const NamedDecl *D, std::string &S) { 346 IdentifierInfo *II = D->getIdentifier(); 347 if (S.empty()) 348 S = II->getName().str(); 349 else 350 S = II->getName().str() + ' ' + S; 351} 352 353void TypePrinter::PrintUnresolvedUsing(const UnresolvedUsingType *T, 354 std::string &S) { 355 PrintTypeSpec(T->getDecl(), S); 356} 357 358void TypePrinter::PrintTypedef(const TypedefType *T, std::string &S) { 359 PrintTypeSpec(T->getDecl(), S); 360} 361 362void TypePrinter::PrintTypeOfExpr(const TypeOfExprType *T, std::string &S) { 363 if (!S.empty()) // Prefix the basic type, e.g. 'typeof(e) X'. 364 S = ' ' + S; 365 std::string Str; 366 llvm::raw_string_ostream s(Str); 367 T->getUnderlyingExpr()->printPretty(s, 0, Policy); 368 S = "typeof " + s.str() + S; 369} 370 371void TypePrinter::PrintTypeOf(const TypeOfType *T, std::string &S) { 372 if (!S.empty()) // Prefix the basic type, e.g. 'typeof(t) X'. 373 S = ' ' + S; 374 std::string Tmp; 375 Print(T->getUnderlyingType(), Tmp); 376 S = "typeof(" + Tmp + ")" + S; 377} 378 379void TypePrinter::PrintDecltype(const DecltypeType *T, std::string &S) { 380 if (!S.empty()) // Prefix the basic type, e.g. 'decltype(t) X'. 381 S = ' ' + S; 382 std::string Str; 383 llvm::raw_string_ostream s(Str); 384 T->getUnderlyingExpr()->printPretty(s, 0, Policy); 385 S = "decltype(" + s.str() + ")" + S; 386} 387 388/// Appends the given scope to the end of a string. 389void TypePrinter::AppendScope(DeclContext *DC, std::string &Buffer) { 390 if (DC->isTranslationUnit()) return; 391 AppendScope(DC->getParent(), Buffer); 392 393 unsigned OldSize = Buffer.size(); 394 395 if (NamespaceDecl *NS = dyn_cast<NamespaceDecl>(DC)) { 396 if (NS->getIdentifier()) 397 Buffer += NS->getNameAsString(); 398 else 399 Buffer += "<anonymous>"; 400 } else if (ClassTemplateSpecializationDecl *Spec 401 = dyn_cast<ClassTemplateSpecializationDecl>(DC)) { 402 const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs(); 403 std::string TemplateArgsStr 404 = TemplateSpecializationType::PrintTemplateArgumentList( 405 TemplateArgs.getFlatArgumentList(), 406 TemplateArgs.flat_size(), 407 Policy); 408 Buffer += Spec->getIdentifier()->getName(); 409 Buffer += TemplateArgsStr; 410 } else if (TagDecl *Tag = dyn_cast<TagDecl>(DC)) { 411 if (TypedefDecl *Typedef = Tag->getTypedefForAnonDecl()) 412 Buffer += Typedef->getIdentifier()->getName(); 413 else if (Tag->getIdentifier()) 414 Buffer += Tag->getIdentifier()->getName(); 415 } 416 417 if (Buffer.size() != OldSize) 418 Buffer += "::"; 419} 420 421void TypePrinter::PrintTag(TagDecl *D, std::string &InnerString) { 422 if (Policy.SuppressTag) 423 return; 424 425 std::string Buffer; 426 bool HasKindDecoration = false; 427 428 // We don't print tags unless this is an elaborated type. 429 // In C, we just assume every RecordType is an elaborated type. 430 if (!Policy.LangOpts.CPlusPlus && !D->getTypedefForAnonDecl()) { 431 HasKindDecoration = true; 432 Buffer += D->getKindName(); 433 Buffer += ' '; 434 } 435 436 // Compute the full nested-name-specifier for this type. 437 // In C, this will always be empty except when the type 438 // being printed is anonymous within other Record. 439 if (!Policy.SuppressScope) 440 AppendScope(D->getDeclContext(), Buffer); 441 442 if (const IdentifierInfo *II = D->getIdentifier()) 443 Buffer += II->getNameStart(); 444 else if (TypedefDecl *Typedef = D->getTypedefForAnonDecl()) { 445 assert(Typedef->getIdentifier() && "Typedef without identifier?"); 446 Buffer += Typedef->getIdentifier()->getNameStart(); 447 } else { 448 // Make an unambiguous representation for anonymous types, e.g. 449 // <anonymous enum at /usr/include/string.h:120:9> 450 llvm::raw_string_ostream OS(Buffer); 451 OS << "<anonymous"; 452 453 if (Policy.AnonymousTagLocations) { 454 // Suppress the redundant tag keyword if we just printed one. 455 // We don't have to worry about ElaboratedTypes here because you can't 456 // refer to an anonymous type with one. 457 if (!HasKindDecoration) 458 OS << " " << D->getKindName(); 459 460 if (D->getLocation().isValid()) { 461 PresumedLoc PLoc = D->getASTContext().getSourceManager().getPresumedLoc( 462 D->getLocation()); 463 OS << " at " << PLoc.getFilename() 464 << ':' << PLoc.getLine() 465 << ':' << PLoc.getColumn(); 466 } 467 } 468 469 OS << '>'; 470 } 471 472 // If this is a class template specialization, print the template 473 // arguments. 474 if (ClassTemplateSpecializationDecl *Spec 475 = dyn_cast<ClassTemplateSpecializationDecl>(D)) { 476 const TemplateArgument *Args; 477 unsigned NumArgs; 478 if (TypeSourceInfo *TAW = Spec->getTypeAsWritten()) { 479 const TemplateSpecializationType *TST = 480 cast<TemplateSpecializationType>(TAW->getType()); 481 Args = TST->getArgs(); 482 NumArgs = TST->getNumArgs(); 483 } else { 484 const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs(); 485 Args = TemplateArgs.getFlatArgumentList(); 486 NumArgs = TemplateArgs.flat_size(); 487 } 488 Buffer += TemplateSpecializationType::PrintTemplateArgumentList(Args, 489 NumArgs, 490 Policy); 491 } 492 493 if (!InnerString.empty()) { 494 Buffer += ' '; 495 Buffer += InnerString; 496 } 497 498 std::swap(Buffer, InnerString); 499} 500 501void TypePrinter::PrintRecord(const RecordType *T, std::string &S) { 502 PrintTag(T->getDecl(), S); 503} 504 505void TypePrinter::PrintEnum(const EnumType *T, std::string &S) { 506 PrintTag(T->getDecl(), S); 507} 508 509void TypePrinter::PrintTemplateTypeParm(const TemplateTypeParmType *T, 510 std::string &S) { 511 if (!S.empty()) // Prefix the basic type, e.g. 'parmname X'. 512 S = ' ' + S; 513 514 if (!T->getName()) 515 S = "type-parameter-" + llvm::utostr_32(T->getDepth()) + '-' + 516 llvm::utostr_32(T->getIndex()) + S; 517 else 518 S = T->getName()->getName().str() + S; 519} 520 521void TypePrinter::PrintSubstTemplateTypeParm(const SubstTemplateTypeParmType *T, 522 std::string &S) { 523 Print(T->getReplacementType(), S); 524} 525 526void TypePrinter::PrintTemplateSpecialization( 527 const TemplateSpecializationType *T, 528 std::string &S) { 529 std::string SpecString; 530 531 { 532 llvm::raw_string_ostream OS(SpecString); 533 T->getTemplateName().print(OS, Policy); 534 } 535 536 SpecString += TemplateSpecializationType::PrintTemplateArgumentList( 537 T->getArgs(), 538 T->getNumArgs(), 539 Policy); 540 if (S.empty()) 541 S.swap(SpecString); 542 else 543 S = SpecString + ' ' + S; 544} 545 546void TypePrinter::PrintInjectedClassName(const InjectedClassNameType *T, 547 std::string &S) { 548 PrintTemplateSpecialization(T->getInjectedTST(), S); 549} 550 551void TypePrinter::PrintElaborated(const ElaboratedType *T, std::string &S) { 552 std::string MyString; 553 554 { 555 llvm::raw_string_ostream OS(MyString); 556 OS << TypeWithKeyword::getKeywordName(T->getKeyword()); 557 if (T->getKeyword() != ETK_None) 558 OS << " "; 559 NestedNameSpecifier* Qualifier = T->getQualifier(); 560 if (Qualifier) 561 Qualifier->print(OS, Policy); 562 } 563 564 std::string TypeStr; 565 PrintingPolicy InnerPolicy(Policy); 566 InnerPolicy.SuppressScope = true; 567 TypePrinter(InnerPolicy).Print(T->getNamedType(), TypeStr); 568 569 MyString += TypeStr; 570 if (S.empty()) 571 S.swap(MyString); 572 else 573 S = MyString + ' ' + S; 574} 575 576void TypePrinter::PrintDependentName(const DependentNameType *T, std::string &S) { 577 std::string MyString; 578 579 { 580 llvm::raw_string_ostream OS(MyString); 581 OS << TypeWithKeyword::getKeywordName(T->getKeyword()); 582 if (T->getKeyword() != ETK_None) 583 OS << " "; 584 585 T->getQualifier()->print(OS, Policy); 586 587 OS << T->getIdentifier()->getName(); 588 } 589 590 if (S.empty()) 591 S.swap(MyString); 592 else 593 S = MyString + ' ' + S; 594} 595 596void TypePrinter::PrintDependentTemplateSpecialization( 597 const DependentTemplateSpecializationType *T, std::string &S) { 598 std::string MyString; 599 { 600 llvm::raw_string_ostream OS(MyString); 601 602 OS << TypeWithKeyword::getKeywordName(T->getKeyword()); 603 if (T->getKeyword() != ETK_None) 604 OS << " "; 605 606 T->getQualifier()->print(OS, Policy); 607 OS << T->getIdentifier()->getName(); 608 OS << TemplateSpecializationType::PrintTemplateArgumentList( 609 T->getArgs(), 610 T->getNumArgs(), 611 Policy); 612 } 613 614 if (S.empty()) 615 S.swap(MyString); 616 else 617 S = MyString + ' ' + S; 618} 619 620void TypePrinter::PrintObjCInterface(const ObjCInterfaceType *T, 621 std::string &S) { 622 if (!S.empty()) // Prefix the basic type, e.g. 'typedefname X'. 623 S = ' ' + S; 624 625 std::string ObjCQIString = T->getDecl()->getNameAsString(); 626 S = ObjCQIString + S; 627} 628 629void TypePrinter::PrintObjCObject(const ObjCObjectType *T, 630 std::string &S) { 631 if (T->qual_empty()) 632 return Print(T->getBaseType(), S); 633 634 std::string tmp; 635 Print(T->getBaseType(), tmp); 636 tmp += '<'; 637 bool isFirst = true; 638 for (ObjCObjectType::qual_iterator 639 I = T->qual_begin(), E = T->qual_end(); I != E; ++I) { 640 if (isFirst) 641 isFirst = false; 642 else 643 tmp += ','; 644 tmp += (*I)->getNameAsString(); 645 } 646 tmp += '>'; 647 648 if (!S.empty()) { 649 tmp += ' '; 650 tmp += S; 651 } 652 std::swap(tmp, S); 653} 654 655void TypePrinter::PrintObjCObjectPointer(const ObjCObjectPointerType *T, 656 std::string &S) { 657 std::string ObjCQIString; 658 659 if (T->isObjCIdType() || T->isObjCQualifiedIdType()) 660 ObjCQIString = "id"; 661 else if (T->isObjCClassType() || T->isObjCQualifiedClassType()) 662 ObjCQIString = "Class"; 663 else if (T->isObjCSelType()) 664 ObjCQIString = "SEL"; 665 else 666 ObjCQIString = T->getInterfaceDecl()->getNameAsString(); 667 668 if (!T->qual_empty()) { 669 ObjCQIString += '<'; 670 for (ObjCObjectPointerType::qual_iterator I = T->qual_begin(), 671 E = T->qual_end(); 672 I != E; ++I) { 673 ObjCQIString += (*I)->getNameAsString(); 674 if (I+1 != E) 675 ObjCQIString += ','; 676 } 677 ObjCQIString += '>'; 678 } 679 680 T->getPointeeType().getLocalQualifiers().getAsStringInternal(ObjCQIString, 681 Policy); 682 683 if (!T->isObjCIdType() && !T->isObjCQualifiedIdType()) 684 ObjCQIString += " *"; // Don't forget the implicit pointer. 685 else if (!S.empty()) // Prefix the basic type, e.g. 'typedefname X'. 686 S = ' ' + S; 687 688 S = ObjCQIString + S; 689} 690 691static void PrintTemplateArgument(std::string &Buffer, 692 const TemplateArgument &Arg, 693 const PrintingPolicy &Policy) { 694 switch (Arg.getKind()) { 695 case TemplateArgument::Null: 696 assert(false && "Null template argument"); 697 break; 698 699 case TemplateArgument::Type: 700 Arg.getAsType().getAsStringInternal(Buffer, Policy); 701 break; 702 703 case TemplateArgument::Declaration: 704 Buffer = cast<NamedDecl>(Arg.getAsDecl())->getNameAsString(); 705 break; 706 707 case TemplateArgument::Template: { 708 llvm::raw_string_ostream s(Buffer); 709 Arg.getAsTemplate().print(s, Policy); 710 break; 711 } 712 713 case TemplateArgument::Integral: 714 Buffer = Arg.getAsIntegral()->toString(10, true); 715 break; 716 717 case TemplateArgument::Expression: { 718 llvm::raw_string_ostream s(Buffer); 719 Arg.getAsExpr()->printPretty(s, 0, Policy); 720 break; 721 } 722 723 case TemplateArgument::Pack: 724 assert(0 && "FIXME: Implement!"); 725 break; 726 } 727} 728 729std::string TemplateSpecializationType:: 730 PrintTemplateArgumentList(const TemplateArgumentListInfo &Args, 731 const PrintingPolicy &Policy) { 732 return PrintTemplateArgumentList(Args.getArgumentArray(), 733 Args.size(), 734 Policy); 735} 736 737std::string 738TemplateSpecializationType::PrintTemplateArgumentList( 739 const TemplateArgument *Args, 740 unsigned NumArgs, 741 const PrintingPolicy &Policy) { 742 std::string SpecString; 743 SpecString += '<'; 744 for (unsigned Arg = 0; Arg < NumArgs; ++Arg) { 745 if (Arg) 746 SpecString += ", "; 747 748 // Print the argument into a string. 749 std::string ArgString; 750 PrintTemplateArgument(ArgString, Args[Arg], Policy); 751 752 // If this is the first argument and its string representation 753 // begins with the global scope specifier ('::foo'), add a space 754 // to avoid printing the diagraph '<:'. 755 if (!Arg && !ArgString.empty() && ArgString[0] == ':') 756 SpecString += ' '; 757 758 SpecString += ArgString; 759 } 760 761 // If the last character of our string is '>', add another space to 762 // keep the two '>''s separate tokens. We don't *have* to do this in 763 // C++0x, but it's still good hygiene. 764 if (SpecString[SpecString.size() - 1] == '>') 765 SpecString += ' '; 766 767 SpecString += '>'; 768 769 return SpecString; 770} 771 772// Sadly, repeat all that with TemplateArgLoc. 773std::string TemplateSpecializationType:: 774PrintTemplateArgumentList(const TemplateArgumentLoc *Args, unsigned NumArgs, 775 const PrintingPolicy &Policy) { 776 std::string SpecString; 777 SpecString += '<'; 778 for (unsigned Arg = 0; Arg < NumArgs; ++Arg) { 779 if (Arg) 780 SpecString += ", "; 781 782 // Print the argument into a string. 783 std::string ArgString; 784 PrintTemplateArgument(ArgString, Args[Arg].getArgument(), Policy); 785 786 // If this is the first argument and its string representation 787 // begins with the global scope specifier ('::foo'), add a space 788 // to avoid printing the diagraph '<:'. 789 if (!Arg && !ArgString.empty() && ArgString[0] == ':') 790 SpecString += ' '; 791 792 SpecString += ArgString; 793 } 794 795 // If the last character of our string is '>', add another space to 796 // keep the two '>''s separate tokens. We don't *have* to do this in 797 // C++0x, but it's still good hygiene. 798 if (SpecString[SpecString.size() - 1] == '>') 799 SpecString += ' '; 800 801 SpecString += '>'; 802 803 return SpecString; 804} 805 806void QualType::dump(const char *msg) const { 807 std::string R = "identifier"; 808 LangOptions LO; 809 getAsStringInternal(R, PrintingPolicy(LO)); 810 if (msg) 811 llvm::errs() << msg << ": "; 812 llvm::errs() << R << "\n"; 813} 814void QualType::dump() const { 815 dump(""); 816} 817 818void Type::dump() const { 819 QualType(this, 0).dump(); 820} 821 822std::string Qualifiers::getAsString() const { 823 LangOptions LO; 824 return getAsString(PrintingPolicy(LO)); 825} 826 827// Appends qualifiers to the given string, separated by spaces. Will 828// prefix a space if the string is non-empty. Will not append a final 829// space. 830void Qualifiers::getAsStringInternal(std::string &S, 831 const PrintingPolicy&) const { 832 AppendTypeQualList(S, getCVRQualifiers()); 833 if (unsigned AddressSpace = getAddressSpace()) { 834 if (!S.empty()) S += ' '; 835 S += "__attribute__((address_space("; 836 S += llvm::utostr_32(AddressSpace); 837 S += ")))"; 838 } 839 if (Qualifiers::GC GCAttrType = getObjCGCAttr()) { 840 if (!S.empty()) S += ' '; 841 S += "__attribute__((objc_gc("; 842 if (GCAttrType == Qualifiers::Weak) 843 S += "weak"; 844 else 845 S += "strong"; 846 S += ")))"; 847 } 848} 849 850std::string QualType::getAsString() const { 851 std::string S; 852 LangOptions LO; 853 getAsStringInternal(S, PrintingPolicy(LO)); 854 return S; 855} 856 857void QualType::getAsStringInternal(std::string &S, 858 const PrintingPolicy &Policy) const { 859 TypePrinter Printer(Policy); 860 Printer.Print(*this, S); 861} 862