TypePrinter.cpp revision 6e132aab867c189b1c3ee7463ef9d2b1f03a294d
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 Print(T->getElementType(), S); 246 std::string V = "__attribute__((__vector_size__("; 247 V += llvm::utostr_32(T->getNumElements()); // convert back to bytes. 248 std::string ET; 249 Print(T->getElementType(), ET); 250 V += " * sizeof(" + ET + ")))) "; 251 S = V + S; 252} 253 254void TypePrinter::PrintExtVector(const ExtVectorType *T, std::string &S) { 255 S += " __attribute__((ext_vector_type("; 256 S += llvm::utostr_32(T->getNumElements()); 257 S += ")))"; 258 Print(T->getElementType(), S); 259} 260 261void TypePrinter::PrintFunctionProto(const FunctionProtoType *T, 262 std::string &S) { 263 // If needed for precedence reasons, wrap the inner part in grouping parens. 264 if (!S.empty()) 265 S = "(" + S + ")"; 266 267 S += "("; 268 std::string Tmp; 269 PrintingPolicy ParamPolicy(Policy); 270 ParamPolicy.SuppressSpecifiers = false; 271 for (unsigned i = 0, e = T->getNumArgs(); i != e; ++i) { 272 if (i) S += ", "; 273 Print(T->getArgType(i), Tmp); 274 S += Tmp; 275 Tmp.clear(); 276 } 277 278 if (T->isVariadic()) { 279 if (T->getNumArgs()) 280 S += ", "; 281 S += "..."; 282 } else if (T->getNumArgs() == 0 && !Policy.LangOpts.CPlusPlus) { 283 // Do not emit int() if we have a proto, emit 'int(void)'. 284 S += "void"; 285 } 286 287 S += ")"; 288 if (T->getNoReturnAttr()) 289 S += " __attribute__((noreturn))"; 290 Print(T->getResultType(), S); 291 292} 293 294void TypePrinter::PrintFunctionNoProto(const FunctionNoProtoType *T, 295 std::string &S) { 296 // If needed for precedence reasons, wrap the inner part in grouping parens. 297 if (!S.empty()) 298 S = "(" + S + ")"; 299 300 S += "()"; 301 if (T->getNoReturnAttr()) 302 S += " __attribute__((noreturn))"; 303 Print(T->getResultType(), S); 304} 305 306void TypePrinter::PrintTypedef(const TypedefType *T, std::string &S) { 307 if (!S.empty()) // Prefix the basic type, e.g. 'typedefname X'. 308 S = ' ' + S; 309 S = T->getDecl()->getIdentifier()->getName().str() + S; 310} 311 312void TypePrinter::PrintTypeOfExpr(const TypeOfExprType *T, std::string &S) { 313 if (!S.empty()) // Prefix the basic type, e.g. 'typeof(e) X'. 314 S = ' ' + S; 315 std::string Str; 316 llvm::raw_string_ostream s(Str); 317 T->getUnderlyingExpr()->printPretty(s, 0, Policy); 318 S = "typeof " + s.str() + S; 319} 320 321void TypePrinter::PrintTypeOf(const TypeOfType *T, std::string &S) { 322 if (!S.empty()) // Prefix the basic type, e.g. 'typeof(t) X'. 323 S = ' ' + S; 324 std::string Tmp; 325 Print(T->getUnderlyingType(), Tmp); 326 S = "typeof(" + Tmp + ")" + S; 327} 328 329void TypePrinter::PrintDecltype(const DecltypeType *T, std::string &S) { 330 if (!S.empty()) // Prefix the basic type, e.g. 'decltype(t) X'. 331 S = ' ' + S; 332 std::string Str; 333 llvm::raw_string_ostream s(Str); 334 T->getUnderlyingExpr()->printPretty(s, 0, Policy); 335 S = "decltype(" + s.str() + ")" + S; 336} 337 338void TypePrinter::PrintTag(const TagType *T, std::string &InnerString) { 339 if (Policy.SuppressTag) 340 return; 341 342 if (!InnerString.empty()) // Prefix the basic type, e.g. 'typedefname X'. 343 InnerString = ' ' + InnerString; 344 345 const char *Kind = Policy.SuppressTagKind? 0 : T->getDecl()->getKindName(); 346 const char *ID; 347 if (const IdentifierInfo *II = T->getDecl()->getIdentifier()) 348 ID = II->getNameStart(); 349 else if (TypedefDecl *Typedef = T->getDecl()->getTypedefForAnonDecl()) { 350 Kind = 0; 351 assert(Typedef->getIdentifier() && "Typedef without identifier?"); 352 ID = Typedef->getIdentifier()->getNameStart(); 353 } else 354 ID = "<anonymous>"; 355 356 // If this is a class template specialization, print the template 357 // arguments. 358 if (ClassTemplateSpecializationDecl *Spec 359 = dyn_cast<ClassTemplateSpecializationDecl>(T->getDecl())) { 360 const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs(); 361 std::string TemplateArgsStr 362 = TemplateSpecializationType::PrintTemplateArgumentList( 363 TemplateArgs.getFlatArgumentList(), 364 TemplateArgs.flat_size(), 365 Policy); 366 InnerString = TemplateArgsStr + InnerString; 367 } 368 369 if (!Policy.SuppressScope) { 370 // Compute the full nested-name-specifier for this type. In C, 371 // this will always be empty. 372 std::string ContextStr; 373 for (DeclContext *DC = T->getDecl()->getDeclContext(); 374 !DC->isTranslationUnit(); DC = DC->getParent()) { 375 std::string MyPart; 376 if (NamespaceDecl *NS = dyn_cast<NamespaceDecl>(DC)) { 377 if (NS->getIdentifier()) 378 MyPart = NS->getNameAsString(); 379 } else if (ClassTemplateSpecializationDecl *Spec 380 = dyn_cast<ClassTemplateSpecializationDecl>(DC)) { 381 const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs(); 382 std::string TemplateArgsStr 383 = TemplateSpecializationType::PrintTemplateArgumentList( 384 TemplateArgs.getFlatArgumentList(), 385 TemplateArgs.flat_size(), 386 Policy); 387 MyPart = Spec->getIdentifier()->getName().str() + TemplateArgsStr; 388 } else if (TagDecl *Tag = dyn_cast<TagDecl>(DC)) { 389 if (TypedefDecl *Typedef = Tag->getTypedefForAnonDecl()) 390 MyPart = Typedef->getIdentifier()->getName(); 391 else if (Tag->getIdentifier()) 392 MyPart = Tag->getIdentifier()->getName(); 393 } 394 395 if (!MyPart.empty()) 396 ContextStr = MyPart + "::" + ContextStr; 397 } 398 399 if (Kind) 400 InnerString = std::string(Kind) + ' ' + ContextStr + ID + InnerString; 401 else 402 InnerString = ContextStr + ID + InnerString; 403 } else 404 InnerString = ID + InnerString; 405} 406 407void TypePrinter::PrintRecord(const RecordType *T, std::string &S) { 408 PrintTag(T, S); 409} 410 411void TypePrinter::PrintEnum(const EnumType *T, std::string &S) { 412 PrintTag(T, S); 413} 414 415void TypePrinter::PrintElaborated(const ElaboratedType *T, std::string &S) { 416 std::string TypeStr; 417 PrintingPolicy InnerPolicy(Policy); 418 InnerPolicy.SuppressTagKind = true; 419 TypePrinter(InnerPolicy).Print(T->getUnderlyingType(), S); 420 421 S = std::string(T->getNameForTagKind(T->getTagKind())) + ' ' + S; 422} 423 424void TypePrinter::PrintTemplateTypeParm(const TemplateTypeParmType *T, 425 std::string &S) { 426 if (!S.empty()) // Prefix the basic type, e.g. 'parmname X'. 427 S = ' ' + S; 428 429 if (!T->getName()) 430 S = "type-parameter-" + llvm::utostr_32(T->getDepth()) + '-' + 431 llvm::utostr_32(T->getIndex()) + S; 432 else 433 S = T->getName()->getName().str() + S; 434} 435 436void TypePrinter::PrintSubstTemplateTypeParm(const SubstTemplateTypeParmType *T, 437 std::string &S) { 438 Print(T->getReplacementType(), S); 439} 440 441void TypePrinter::PrintTemplateSpecialization( 442 const TemplateSpecializationType *T, 443 std::string &S) { 444 std::string SpecString; 445 446 { 447 llvm::raw_string_ostream OS(SpecString); 448 T->getTemplateName().print(OS, Policy); 449 } 450 451 SpecString += TemplateSpecializationType::PrintTemplateArgumentList( 452 T->getArgs(), 453 T->getNumArgs(), 454 Policy); 455 if (S.empty()) 456 S.swap(SpecString); 457 else 458 S = SpecString + ' ' + S; 459} 460 461void TypePrinter::PrintQualifiedName(const QualifiedNameType *T, 462 std::string &S) { 463 std::string MyString; 464 465 { 466 llvm::raw_string_ostream OS(MyString); 467 T->getQualifier()->print(OS, Policy); 468 } 469 470 std::string TypeStr; 471 PrintingPolicy InnerPolicy(Policy); 472 InnerPolicy.SuppressTagKind = true; 473 InnerPolicy.SuppressScope = true; 474 TypePrinter(InnerPolicy).Print(T->getNamedType(), TypeStr); 475 476 MyString += TypeStr; 477 if (S.empty()) 478 S.swap(MyString); 479 else 480 S = MyString + ' ' + S; 481} 482 483void TypePrinter::PrintTypename(const TypenameType *T, std::string &S) { 484 std::string MyString; 485 486 { 487 llvm::raw_string_ostream OS(MyString); 488 OS << "typename "; 489 T->getQualifier()->print(OS, Policy); 490 491 if (const IdentifierInfo *Ident = T->getIdentifier()) 492 OS << Ident->getName(); 493 else if (const TemplateSpecializationType *Spec = T->getTemplateId()) { 494 Spec->getTemplateName().print(OS, Policy, true); 495 OS << TemplateSpecializationType::PrintTemplateArgumentList( 496 Spec->getArgs(), 497 Spec->getNumArgs(), 498 Policy); 499 } 500 } 501 502 if (S.empty()) 503 S.swap(MyString); 504 else 505 S = MyString + ' ' + S; 506} 507 508void TypePrinter::PrintObjCInterface(const ObjCInterfaceType *T, 509 std::string &S) { 510 if (!S.empty()) // Prefix the basic type, e.g. 'typedefname X'. 511 S = ' ' + S; 512 513 std::string ObjCQIString = T->getDecl()->getNameAsString(); 514 if (T->getNumProtocols()) { 515 ObjCQIString += '<'; 516 bool isFirst = true; 517 for (ObjCInterfaceType::qual_iterator I = T->qual_begin(), 518 E = T->qual_end(); 519 I != E; ++I) { 520 if (isFirst) 521 isFirst = false; 522 else 523 ObjCQIString += ','; 524 ObjCQIString += (*I)->getNameAsString(); 525 } 526 ObjCQIString += '>'; 527 } 528 S = ObjCQIString + S; 529} 530 531void TypePrinter::PrintObjCObjectPointer(const ObjCObjectPointerType *T, 532 std::string &S) { 533 std::string ObjCQIString; 534 535 if (T->isObjCIdType() || T->isObjCQualifiedIdType()) 536 ObjCQIString = "id"; 537 else if (T->isObjCClassType() || T->isObjCQualifiedClassType()) 538 ObjCQIString = "Class"; 539 else if (T->isObjCSelType()) 540 ObjCQIString = "SEL"; 541 else 542 ObjCQIString = T->getInterfaceDecl()->getNameAsString(); 543 544 if (!T->qual_empty()) { 545 ObjCQIString += '<'; 546 for (ObjCObjectPointerType::qual_iterator I = T->qual_begin(), 547 E = T->qual_end(); 548 I != E; ++I) { 549 ObjCQIString += (*I)->getNameAsString(); 550 if (I+1 != E) 551 ObjCQIString += ','; 552 } 553 ObjCQIString += '>'; 554 } 555 556 T->getPointeeType().getLocalQualifiers().getAsStringInternal(ObjCQIString, 557 Policy); 558 559 if (!T->isObjCIdType() && !T->isObjCQualifiedIdType()) 560 ObjCQIString += " *"; // Don't forget the implicit pointer. 561 else if (!S.empty()) // Prefix the basic type, e.g. 'typedefname X'. 562 S = ' ' + S; 563 564 S = ObjCQIString + S; 565} 566 567static void PrintTemplateArgument(std::string &Buffer, 568 const TemplateArgument &Arg, 569 const PrintingPolicy &Policy) { 570 switch (Arg.getKind()) { 571 case TemplateArgument::Null: 572 assert(false && "Null template argument"); 573 break; 574 575 case TemplateArgument::Type: 576 Arg.getAsType().getAsStringInternal(Buffer, Policy); 577 break; 578 579 case TemplateArgument::Declaration: 580 Buffer = cast<NamedDecl>(Arg.getAsDecl())->getNameAsString(); 581 break; 582 583 case TemplateArgument::Template: { 584 llvm::raw_string_ostream s(Buffer); 585 Arg.getAsTemplate().print(s, Policy); 586 break; 587 } 588 589 case TemplateArgument::Integral: 590 Buffer = Arg.getAsIntegral()->toString(10, true); 591 break; 592 593 case TemplateArgument::Expression: { 594 llvm::raw_string_ostream s(Buffer); 595 Arg.getAsExpr()->printPretty(s, 0, Policy); 596 break; 597 } 598 599 case TemplateArgument::Pack: 600 assert(0 && "FIXME: Implement!"); 601 break; 602 } 603} 604 605std::string TemplateSpecializationType:: 606 PrintTemplateArgumentList(const TemplateArgumentListInfo &Args, 607 const PrintingPolicy &Policy) { 608 return PrintTemplateArgumentList(Args.getArgumentArray(), 609 Args.size(), 610 Policy); 611} 612 613std::string 614TemplateSpecializationType::PrintTemplateArgumentList( 615 const TemplateArgument *Args, 616 unsigned NumArgs, 617 const PrintingPolicy &Policy) { 618 std::string SpecString; 619 SpecString += '<'; 620 for (unsigned Arg = 0; Arg < NumArgs; ++Arg) { 621 if (Arg) 622 SpecString += ", "; 623 624 // Print the argument into a string. 625 std::string ArgString; 626 PrintTemplateArgument(ArgString, Args[Arg], Policy); 627 628 // If this is the first argument and its string representation 629 // begins with the global scope specifier ('::foo'), add a space 630 // to avoid printing the diagraph '<:'. 631 if (!Arg && !ArgString.empty() && ArgString[0] == ':') 632 SpecString += ' '; 633 634 SpecString += ArgString; 635 } 636 637 // If the last character of our string is '>', add another space to 638 // keep the two '>''s separate tokens. We don't *have* to do this in 639 // C++0x, but it's still good hygiene. 640 if (SpecString[SpecString.size() - 1] == '>') 641 SpecString += ' '; 642 643 SpecString += '>'; 644 645 return SpecString; 646} 647 648// Sadly, repeat all that with TemplateArgLoc. 649std::string TemplateSpecializationType:: 650PrintTemplateArgumentList(const TemplateArgumentLoc *Args, unsigned NumArgs, 651 const PrintingPolicy &Policy) { 652 std::string SpecString; 653 SpecString += '<'; 654 for (unsigned Arg = 0; Arg < NumArgs; ++Arg) { 655 if (Arg) 656 SpecString += ", "; 657 658 // Print the argument into a string. 659 std::string ArgString; 660 PrintTemplateArgument(ArgString, Args[Arg].getArgument(), Policy); 661 662 // If this is the first argument and its string representation 663 // begins with the global scope specifier ('::foo'), add a space 664 // to avoid printing the diagraph '<:'. 665 if (!Arg && !ArgString.empty() && ArgString[0] == ':') 666 SpecString += ' '; 667 668 SpecString += ArgString; 669 } 670 671 // If the last character of our string is '>', add another space to 672 // keep the two '>''s separate tokens. We don't *have* to do this in 673 // C++0x, but it's still good hygiene. 674 if (SpecString[SpecString.size() - 1] == '>') 675 SpecString += ' '; 676 677 SpecString += '>'; 678 679 return SpecString; 680} 681 682void QualType::dump(const char *msg) const { 683 std::string R = "identifier"; 684 LangOptions LO; 685 getAsStringInternal(R, PrintingPolicy(LO)); 686 if (msg) 687 llvm::errs() << msg << ": "; 688 llvm::errs() << R << "\n"; 689} 690void QualType::dump() const { 691 dump(""); 692} 693 694void Type::dump() const { 695 QualType(this, 0).dump(); 696} 697 698std::string Qualifiers::getAsString() const { 699 LangOptions LO; 700 return getAsString(PrintingPolicy(LO)); 701} 702 703// Appends qualifiers to the given string, separated by spaces. Will 704// prefix a space if the string is non-empty. Will not append a final 705// space. 706void Qualifiers::getAsStringInternal(std::string &S, 707 const PrintingPolicy&) const { 708 AppendTypeQualList(S, getCVRQualifiers()); 709 if (unsigned AddressSpace = getAddressSpace()) { 710 if (!S.empty()) S += ' '; 711 S += "__attribute__((address_space("; 712 S += llvm::utostr_32(AddressSpace); 713 S += ")))"; 714 } 715 if (Qualifiers::GC GCAttrType = getObjCGCAttr()) { 716 if (!S.empty()) S += ' '; 717 S += "__attribute__((objc_gc("; 718 if (GCAttrType == Qualifiers::Weak) 719 S += "weak"; 720 else 721 S += "strong"; 722 S += ")))"; 723 } 724} 725 726std::string QualType::getAsString() const { 727 std::string S; 728 LangOptions LO; 729 getAsStringInternal(S, PrintingPolicy(LO)); 730 return S; 731} 732 733void QualType::getAsStringInternal(std::string &S, 734 const PrintingPolicy &Policy) const { 735 TypePrinter Printer(Policy); 736 Printer.Print(*this, S); 737} 738 739