TypePrinter.cpp revision a4923eb7c4b04d360cb2747641a5e92818edf804
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 "llvm/ADT/StringExtras.h" 22#include "llvm/Support/raw_ostream.h" 23using namespace clang; 24 25namespace { 26 class TypePrinter { 27 PrintingPolicy Policy; 28 29 public: 30 explicit TypePrinter(const PrintingPolicy &Policy) : Policy(Policy) { } 31 32 void Print(QualType T, std::string &S); 33 void PrintTag(const TagType *T, std::string &S); 34#define ABSTRACT_TYPE(CLASS, PARENT) 35#define TYPE(CLASS, PARENT) \ 36 void Print##CLASS(const CLASS##Type *T, std::string &S); 37#include "clang/AST/TypeNodes.def" 38 }; 39} 40 41static void AppendTypeQualList(std::string &S, unsigned TypeQuals) { 42 if (TypeQuals & Qualifiers::Const) { 43 if (!S.empty()) S += ' '; 44 S += "const"; 45 } 46 if (TypeQuals & Qualifiers::Volatile) { 47 if (!S.empty()) S += ' '; 48 S += "volatile"; 49 } 50 if (TypeQuals & Qualifiers::Restrict) { 51 if (!S.empty()) S += ' '; 52 S += "restrict"; 53 } 54} 55 56void TypePrinter::Print(QualType T, std::string &S) { 57 if (T.isNull()) { 58 S += "NULL TYPE"; 59 return; 60 } 61 62 if (Policy.SuppressSpecifiers && T->isSpecifierType()) 63 return; 64 65 // Print qualifiers as appropriate. 66 Qualifiers Quals = T.getLocalQualifiers(); 67 if (!Quals.empty()) { 68 std::string TQS; 69 Quals.getAsStringInternal(TQS, Policy); 70 71 if (!S.empty()) { 72 TQS += ' '; 73 TQS += S; 74 } 75 std::swap(S, TQS); 76 } 77 78 switch (T->getTypeClass()) { 79#define ABSTRACT_TYPE(CLASS, PARENT) 80#define TYPE(CLASS, PARENT) case Type::CLASS: \ 81 Print##CLASS(cast<CLASS##Type>(T.getTypePtr()), S); \ 82 break; 83#include "clang/AST/TypeNodes.def" 84 } 85} 86 87void TypePrinter::PrintBuiltin(const BuiltinType *T, std::string &S) { 88 if (S.empty()) { 89 S = T->getName(Policy.LangOpts); 90 } else { 91 // Prefix the basic type, e.g. 'int X'. 92 S = ' ' + S; 93 S = T->getName(Policy.LangOpts) + S; 94 } 95} 96 97void TypePrinter::PrintFixedWidthInt(const FixedWidthIntType *T, 98 std::string &S) { 99 // FIXME: Once we get bitwidth attribute, write as 100 // "int __attribute__((bitwidth(x)))". 101 std::string prefix = "__clang_fixedwidth"; 102 prefix += llvm::utostr_32(T->getWidth()); 103 prefix += (char)(T->isSigned() ? 'S' : 'U'); 104 if (S.empty()) { 105 S = prefix; 106 } else { 107 // Prefix the basic type, e.g. 'int X'. 108 S = prefix + S; 109 } 110} 111 112void TypePrinter::PrintComplex(const ComplexType *T, std::string &S) { 113 Print(T->getElementType(), S); 114 S = "_Complex " + S; 115} 116 117void TypePrinter::PrintPointer(const PointerType *T, std::string &S) { 118 S = '*' + S; 119 120 // Handle things like 'int (*A)[4];' correctly. 121 // FIXME: this should include vectors, but vectors use attributes I guess. 122 if (isa<ArrayType>(T->getPointeeType())) 123 S = '(' + S + ')'; 124 125 Print(T->getPointeeType(), S); 126} 127 128void TypePrinter::PrintBlockPointer(const BlockPointerType *T, std::string &S) { 129 S = '^' + S; 130 Print(T->getPointeeType(), S); 131} 132 133void TypePrinter::PrintLValueReference(const LValueReferenceType *T, 134 std::string &S) { 135 S = '&' + S; 136 137 // Handle things like 'int (&A)[4];' correctly. 138 // FIXME: this should include vectors, but vectors use attributes I guess. 139 if (isa<ArrayType>(T->getPointeeTypeAsWritten())) 140 S = '(' + S + ')'; 141 142 Print(T->getPointeeTypeAsWritten(), S); 143} 144 145void TypePrinter::PrintRValueReference(const RValueReferenceType *T, 146 std::string &S) { 147 S = "&&" + S; 148 149 // Handle things like 'int (&&A)[4];' correctly. 150 // FIXME: this should include vectors, but vectors use attributes I guess. 151 if (isa<ArrayType>(T->getPointeeTypeAsWritten())) 152 S = '(' + S + ')'; 153 154 Print(T->getPointeeTypeAsWritten(), S); 155} 156 157void TypePrinter::PrintMemberPointer(const MemberPointerType *T, 158 std::string &S) { 159 std::string C; 160 Print(QualType(T->getClass(), 0), C); 161 C += "::*"; 162 S = C + S; 163 164 // Handle things like 'int (Cls::*A)[4];' correctly. 165 // FIXME: this should include vectors, but vectors use attributes I guess. 166 if (isa<ArrayType>(T->getPointeeType())) 167 S = '(' + S + ')'; 168 169 Print(T->getPointeeType(), S); 170} 171 172void TypePrinter::PrintConstantArray(const ConstantArrayType *T, 173 std::string &S) { 174 S += '['; 175 S += llvm::utostr(T->getSize().getZExtValue()); 176 S += ']'; 177 178 Print(T->getElementType(), S); 179} 180 181void TypePrinter::PrintIncompleteArray(const IncompleteArrayType *T, 182 std::string &S) { 183 S += "[]"; 184 Print(T->getElementType(), S); 185} 186 187void TypePrinter::PrintVariableArray(const VariableArrayType *T, 188 std::string &S) { 189 S += '['; 190 191 if (T->getIndexTypeQualifiers().hasQualifiers()) { 192 AppendTypeQualList(S, T->getIndexTypeCVRQualifiers()); 193 S += ' '; 194 } 195 196 if (T->getSizeModifier() == VariableArrayType::Static) 197 S += "static"; 198 else if (T->getSizeModifier() == VariableArrayType::Star) 199 S += '*'; 200 201 if (T->getSizeExpr()) { 202 std::string SStr; 203 llvm::raw_string_ostream s(SStr); 204 T->getSizeExpr()->printPretty(s, 0, Policy); 205 S += s.str(); 206 } 207 S += ']'; 208 209 Print(T->getElementType(), S); 210} 211 212void TypePrinter::PrintDependentSizedArray(const DependentSizedArrayType *T, 213 std::string &S) { 214 S += '['; 215 216 if (T->getSizeExpr()) { 217 std::string SStr; 218 llvm::raw_string_ostream s(SStr); 219 T->getSizeExpr()->printPretty(s, 0, Policy); 220 S += s.str(); 221 } 222 S += ']'; 223 224 Print(T->getElementType(), S); 225} 226 227void TypePrinter::PrintDependentSizedExtVector( 228 const DependentSizedExtVectorType *T, 229 std::string &S) { 230 Print(T->getElementType(), S); 231 232 S += " __attribute__((ext_vector_type("; 233 if (T->getSizeExpr()) { 234 std::string SStr; 235 llvm::raw_string_ostream s(SStr); 236 T->getSizeExpr()->printPretty(s, 0, Policy); 237 S += s.str(); 238 } 239 S += ")))"; 240} 241 242void TypePrinter::PrintVector(const VectorType *T, std::string &S) { 243 // FIXME: We prefer to print the size directly here, but have no way 244 // to get the size of the type. 245 S += " __attribute__((__vector_size__("; 246 S += llvm::utostr_32(T->getNumElements()); // convert back to bytes. 247 std::string ET; 248 Print(T->getElementType(), ET); 249 S += " * sizeof(" + ET + "))))"; 250 Print(T->getElementType(), S); 251} 252 253void TypePrinter::PrintExtVector(const ExtVectorType *T, std::string &S) { 254 S += " __attribute__((ext_vector_type("; 255 S += llvm::utostr_32(T->getNumElements()); 256 S += ")))"; 257 Print(T->getElementType(), S); 258} 259 260void TypePrinter::PrintFunctionProto(const FunctionProtoType *T, 261 std::string &S) { 262 // If needed for precedence reasons, wrap the inner part in grouping parens. 263 if (!S.empty()) 264 S = "(" + S + ")"; 265 266 S += "("; 267 std::string Tmp; 268 PrintingPolicy ParamPolicy(Policy); 269 ParamPolicy.SuppressSpecifiers = false; 270 for (unsigned i = 0, e = T->getNumArgs(); i != e; ++i) { 271 if (i) S += ", "; 272 Print(T->getArgType(i), Tmp); 273 S += Tmp; 274 Tmp.clear(); 275 } 276 277 if (T->isVariadic()) { 278 if (T->getNumArgs()) 279 S += ", "; 280 S += "..."; 281 } else if (T->getNumArgs() == 0 && !Policy.LangOpts.CPlusPlus) { 282 // Do not emit int() if we have a proto, emit 'int(void)'. 283 S += "void"; 284 } 285 286 S += ")"; 287 if (T->getNoReturnAttr()) 288 S += " __attribute__((noreturn))"; 289 Print(T->getResultType(), S); 290 291} 292 293void TypePrinter::PrintFunctionNoProto(const FunctionNoProtoType *T, 294 std::string &S) { 295 // If needed for precedence reasons, wrap the inner part in grouping parens. 296 if (!S.empty()) 297 S = "(" + S + ")"; 298 299 S += "()"; 300 if (T->getNoReturnAttr()) 301 S += " __attribute__((noreturn))"; 302 Print(T->getResultType(), S); 303} 304 305void TypePrinter::PrintTypedef(const TypedefType *T, std::string &S) { 306 if (!S.empty()) // Prefix the basic type, e.g. 'typedefname X'. 307 S = ' ' + S; 308 S = T->getDecl()->getIdentifier()->getName().str() + S; 309} 310 311void TypePrinter::PrintTypeOfExpr(const TypeOfExprType *T, std::string &S) { 312 if (!S.empty()) // Prefix the basic type, e.g. 'typeof(e) X'. 313 S = ' ' + S; 314 std::string Str; 315 llvm::raw_string_ostream s(Str); 316 T->getUnderlyingExpr()->printPretty(s, 0, Policy); 317 S = "typeof " + s.str() + S; 318} 319 320void TypePrinter::PrintTypeOf(const TypeOfType *T, std::string &S) { 321 if (!S.empty()) // Prefix the basic type, e.g. 'typeof(t) X'. 322 S = ' ' + S; 323 std::string Tmp; 324 Print(T->getUnderlyingType(), Tmp); 325 S = "typeof(" + Tmp + ")" + S; 326} 327 328void TypePrinter::PrintDecltype(const DecltypeType *T, std::string &S) { 329 if (!S.empty()) // Prefix the basic type, e.g. 'decltype(t) X'. 330 S = ' ' + S; 331 std::string Str; 332 llvm::raw_string_ostream s(Str); 333 T->getUnderlyingExpr()->printPretty(s, 0, Policy); 334 S = "decltype(" + s.str() + ")" + S; 335} 336 337void TypePrinter::PrintTag(const TagType *T, std::string &InnerString) { 338 if (Policy.SuppressTag) 339 return; 340 341 if (!InnerString.empty()) // Prefix the basic type, e.g. 'typedefname X'. 342 InnerString = ' ' + InnerString; 343 344 const char *Kind = Policy.SuppressTagKind? 0 : T->getDecl()->getKindName(); 345 const char *ID; 346 if (const IdentifierInfo *II = T->getDecl()->getIdentifier()) 347 ID = II->getNameStart(); 348 else if (TypedefDecl *Typedef = T->getDecl()->getTypedefForAnonDecl()) { 349 Kind = 0; 350 assert(Typedef->getIdentifier() && "Typedef without identifier?"); 351 ID = Typedef->getIdentifier()->getNameStart(); 352 } else 353 ID = "<anonymous>"; 354 355 // If this is a class template specialization, print the template 356 // arguments. 357 if (ClassTemplateSpecializationDecl *Spec 358 = dyn_cast<ClassTemplateSpecializationDecl>(T->getDecl())) { 359 const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs(); 360 std::string TemplateArgsStr 361 = TemplateSpecializationType::PrintTemplateArgumentList( 362 TemplateArgs.getFlatArgumentList(), 363 TemplateArgs.flat_size(), 364 Policy); 365 InnerString = TemplateArgsStr + InnerString; 366 } 367 368 if (!Policy.SuppressScope) { 369 // Compute the full nested-name-specifier for this type. In C, 370 // this will always be empty. 371 std::string ContextStr; 372 for (DeclContext *DC = T->getDecl()->getDeclContext(); 373 !DC->isTranslationUnit(); DC = DC->getParent()) { 374 std::string MyPart; 375 if (NamespaceDecl *NS = dyn_cast<NamespaceDecl>(DC)) { 376 if (NS->getIdentifier()) 377 MyPart = NS->getNameAsString(); 378 } else if (ClassTemplateSpecializationDecl *Spec 379 = dyn_cast<ClassTemplateSpecializationDecl>(DC)) { 380 const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs(); 381 std::string TemplateArgsStr 382 = TemplateSpecializationType::PrintTemplateArgumentList( 383 TemplateArgs.getFlatArgumentList(), 384 TemplateArgs.flat_size(), 385 Policy); 386 MyPart = Spec->getIdentifier()->getName().str() + TemplateArgsStr; 387 } else if (TagDecl *Tag = dyn_cast<TagDecl>(DC)) { 388 if (TypedefDecl *Typedef = Tag->getTypedefForAnonDecl()) 389 MyPart = Typedef->getIdentifier()->getName(); 390 else if (Tag->getIdentifier()) 391 MyPart = Tag->getIdentifier()->getName(); 392 } 393 394 if (!MyPart.empty()) 395 ContextStr = MyPart + "::" + ContextStr; 396 } 397 398 if (Kind) 399 InnerString = std::string(Kind) + ' ' + ContextStr + ID + InnerString; 400 else 401 InnerString = ContextStr + ID + InnerString; 402 } else 403 InnerString = ID + InnerString; 404} 405 406void TypePrinter::PrintRecord(const RecordType *T, std::string &S) { 407 PrintTag(T, S); 408} 409 410void TypePrinter::PrintEnum(const EnumType *T, std::string &S) { 411 PrintTag(T, S); 412} 413 414void TypePrinter::PrintElaborated(const ElaboratedType *T, std::string &S) { 415 std::string TypeStr; 416 PrintingPolicy InnerPolicy(Policy); 417 InnerPolicy.SuppressTagKind = true; 418 TypePrinter(InnerPolicy).Print(T->getUnderlyingType(), S); 419 420 S = std::string(T->getNameForTagKind(T->getTagKind())) + ' ' + S; 421} 422 423void TypePrinter::PrintTemplateTypeParm(const TemplateTypeParmType *T, 424 std::string &S) { 425 if (!S.empty()) // Prefix the basic type, e.g. 'parmname X'. 426 S = ' ' + S; 427 428 if (!T->getName()) 429 S = "type-parameter-" + llvm::utostr_32(T->getDepth()) + '-' + 430 llvm::utostr_32(T->getIndex()) + S; 431 else 432 S = T->getName()->getName().str() + S; 433} 434 435void TypePrinter::PrintSubstTemplateTypeParm(const SubstTemplateTypeParmType *T, 436 std::string &S) { 437 Print(T->getReplacementType(), S); 438} 439 440void TypePrinter::PrintTemplateSpecialization( 441 const TemplateSpecializationType *T, 442 std::string &S) { 443 std::string SpecString; 444 445 { 446 llvm::raw_string_ostream OS(SpecString); 447 T->getTemplateName().print(OS, Policy); 448 } 449 450 SpecString += TemplateSpecializationType::PrintTemplateArgumentList( 451 T->getArgs(), 452 T->getNumArgs(), 453 Policy); 454 if (S.empty()) 455 S.swap(SpecString); 456 else 457 S = SpecString + ' ' + S; 458} 459 460void TypePrinter::PrintQualifiedName(const QualifiedNameType *T, 461 std::string &S) { 462 std::string MyString; 463 464 { 465 llvm::raw_string_ostream OS(MyString); 466 T->getQualifier()->print(OS, Policy); 467 } 468 469 std::string TypeStr; 470 PrintingPolicy InnerPolicy(Policy); 471 InnerPolicy.SuppressTagKind = true; 472 InnerPolicy.SuppressScope = true; 473 TypePrinter(InnerPolicy).Print(T->getNamedType(), TypeStr); 474 475 MyString += TypeStr; 476 if (S.empty()) 477 S.swap(MyString); 478 else 479 S = MyString + ' ' + S; 480} 481 482void TypePrinter::PrintTypename(const TypenameType *T, std::string &S) { 483 std::string MyString; 484 485 { 486 llvm::raw_string_ostream OS(MyString); 487 OS << "typename "; 488 T->getQualifier()->print(OS, Policy); 489 490 if (const IdentifierInfo *Ident = T->getIdentifier()) 491 OS << Ident->getName(); 492 else if (const TemplateSpecializationType *Spec = T->getTemplateId()) { 493 Spec->getTemplateName().print(OS, Policy, true); 494 OS << TemplateSpecializationType::PrintTemplateArgumentList( 495 Spec->getArgs(), 496 Spec->getNumArgs(), 497 Policy); 498 } 499 } 500 501 if (S.empty()) 502 S.swap(MyString); 503 else 504 S = MyString + ' ' + S; 505} 506 507void TypePrinter::PrintObjCInterface(const ObjCInterfaceType *T, 508 std::string &S) { 509 if (!S.empty()) // Prefix the basic type, e.g. 'typedefname X'. 510 S = ' ' + S; 511 512 std::string ObjCQIString = T->getDecl()->getNameAsString(); 513 if (T->getNumProtocols()) { 514 ObjCQIString += '<'; 515 bool isFirst = true; 516 for (ObjCInterfaceType::qual_iterator I = T->qual_begin(), 517 E = T->qual_end(); 518 I != E; ++I) { 519 if (isFirst) 520 isFirst = false; 521 else 522 ObjCQIString += ','; 523 ObjCQIString += (*I)->getNameAsString(); 524 } 525 ObjCQIString += '>'; 526 } 527 S = ObjCQIString + S; 528} 529 530void TypePrinter::PrintObjCObjectPointer(const ObjCObjectPointerType *T, 531 std::string &S) { 532 std::string ObjCQIString; 533 534 if (T->isObjCIdType() || T->isObjCQualifiedIdType()) 535 ObjCQIString = "id"; 536 else if (T->isObjCClassType() || T->isObjCQualifiedClassType()) 537 ObjCQIString = "Class"; 538 else 539 ObjCQIString = T->getInterfaceDecl()->getNameAsString(); 540 541 if (!T->qual_empty()) { 542 ObjCQIString += '<'; 543 for (ObjCObjectPointerType::qual_iterator I = T->qual_begin(), 544 E = T->qual_end(); 545 I != E; ++I) { 546 ObjCQIString += (*I)->getNameAsString(); 547 if (I+1 != E) 548 ObjCQIString += ','; 549 } 550 ObjCQIString += '>'; 551 } 552 553 T->getPointeeType().getLocalQualifiers().getAsStringInternal(ObjCQIString, 554 Policy); 555 556 if (!T->isObjCIdType() && !T->isObjCQualifiedIdType()) 557 ObjCQIString += " *"; // Don't forget the implicit pointer. 558 else if (!S.empty()) // Prefix the basic type, e.g. 'typedefname X'. 559 S = ' ' + S; 560 561 S = ObjCQIString + S; 562} 563 564static void PrintTemplateArgument(std::string &Buffer, 565 const TemplateArgument &Arg, 566 const PrintingPolicy &Policy) { 567 switch (Arg.getKind()) { 568 case TemplateArgument::Null: 569 assert(false && "Null template argument"); 570 break; 571 572 case TemplateArgument::Type: 573 Arg.getAsType().getAsStringInternal(Buffer, Policy); 574 break; 575 576 case TemplateArgument::Declaration: 577 Buffer = cast<NamedDecl>(Arg.getAsDecl())->getNameAsString(); 578 break; 579 580 case TemplateArgument::Template: { 581 llvm::raw_string_ostream s(Buffer); 582 Arg.getAsTemplate().print(s, Policy); 583 break; 584 } 585 586 case TemplateArgument::Integral: 587 Buffer = Arg.getAsIntegral()->toString(10, true); 588 break; 589 590 case TemplateArgument::Expression: { 591 llvm::raw_string_ostream s(Buffer); 592 Arg.getAsExpr()->printPretty(s, 0, Policy); 593 break; 594 } 595 596 case TemplateArgument::Pack: 597 assert(0 && "FIXME: Implement!"); 598 break; 599 } 600} 601 602std::string 603TemplateSpecializationType::PrintTemplateArgumentList( 604 const TemplateArgument *Args, 605 unsigned NumArgs, 606 const PrintingPolicy &Policy) { 607 std::string SpecString; 608 SpecString += '<'; 609 for (unsigned Arg = 0; Arg < NumArgs; ++Arg) { 610 if (Arg) 611 SpecString += ", "; 612 613 // Print the argument into a string. 614 std::string ArgString; 615 PrintTemplateArgument(ArgString, Args[Arg], Policy); 616 617 // If this is the first argument and its string representation 618 // begins with the global scope specifier ('::foo'), add a space 619 // to avoid printing the diagraph '<:'. 620 if (!Arg && !ArgString.empty() && ArgString[0] == ':') 621 SpecString += ' '; 622 623 SpecString += ArgString; 624 } 625 626 // If the last character of our string is '>', add another space to 627 // keep the two '>''s separate tokens. We don't *have* to do this in 628 // C++0x, but it's still good hygiene. 629 if (SpecString[SpecString.size() - 1] == '>') 630 SpecString += ' '; 631 632 SpecString += '>'; 633 634 return SpecString; 635} 636 637// Sadly, repeat all that with TemplateArgLoc. 638std::string TemplateSpecializationType:: 639PrintTemplateArgumentList(const TemplateArgumentLoc *Args, unsigned NumArgs, 640 const PrintingPolicy &Policy) { 641 std::string SpecString; 642 SpecString += '<'; 643 for (unsigned Arg = 0; Arg < NumArgs; ++Arg) { 644 if (Arg) 645 SpecString += ", "; 646 647 // Print the argument into a string. 648 std::string ArgString; 649 PrintTemplateArgument(ArgString, Args[Arg].getArgument(), Policy); 650 651 // If this is the first argument and its string representation 652 // begins with the global scope specifier ('::foo'), add a space 653 // to avoid printing the diagraph '<:'. 654 if (!Arg && !ArgString.empty() && ArgString[0] == ':') 655 SpecString += ' '; 656 657 SpecString += ArgString; 658 } 659 660 // If the last character of our string is '>', add another space to 661 // keep the two '>''s separate tokens. We don't *have* to do this in 662 // C++0x, but it's still good hygiene. 663 if (SpecString[SpecString.size() - 1] == '>') 664 SpecString += ' '; 665 666 SpecString += '>'; 667 668 return SpecString; 669} 670 671void QualType::dump(const char *msg) const { 672 std::string R = "identifier"; 673 LangOptions LO; 674 getAsStringInternal(R, PrintingPolicy(LO)); 675 if (msg) 676 fprintf(stderr, "%s: %s\n", msg, R.c_str()); 677 else 678 fprintf(stderr, "%s\n", R.c_str()); 679} 680void QualType::dump() const { 681 dump(""); 682} 683 684void Type::dump() const { 685 QualType(this, 0).dump(); 686} 687 688std::string Qualifiers::getAsString() const { 689 LangOptions LO; 690 return getAsString(PrintingPolicy(LO)); 691} 692 693// Appends qualifiers to the given string, separated by spaces. Will 694// prefix a space if the string is non-empty. Will not append a final 695// space. 696void Qualifiers::getAsStringInternal(std::string &S, 697 const PrintingPolicy&) const { 698 AppendTypeQualList(S, getCVRQualifiers()); 699 if (unsigned AddressSpace = getAddressSpace()) { 700 if (!S.empty()) S += ' '; 701 S += "__attribute__((address_space("; 702 S += llvm::utostr_32(AddressSpace); 703 S += ")))"; 704 } 705 if (Qualifiers::GC GCAttrType = getObjCGCAttr()) { 706 if (!S.empty()) S += ' '; 707 S += "__attribute__((objc_gc("; 708 if (GCAttrType == Qualifiers::Weak) 709 S += "weak"; 710 else 711 S += "strong"; 712 S += ")))"; 713 } 714} 715 716std::string QualType::getAsString() const { 717 std::string S; 718 LangOptions LO; 719 getAsStringInternal(S, PrintingPolicy(LO)); 720 return S; 721} 722 723void QualType::getAsStringInternal(std::string &S, 724 const PrintingPolicy &Policy) const { 725 TypePrinter Printer(Policy); 726 Printer.Print(*this, S); 727} 728 729