TypePrinter.cpp revision 218893
1199482Srdivacky//===--- TypePrinter.cpp - Pretty-Print Clang Types -----------------------===// 2199482Srdivacky// 3199482Srdivacky// The LLVM Compiler Infrastructure 4199482Srdivacky// 5199482Srdivacky// This file is distributed under the University of Illinois Open Source 6199482Srdivacky// License. See LICENSE.TXT for details. 7199482Srdivacky// 8199482Srdivacky//===----------------------------------------------------------------------===// 9199482Srdivacky// 10199482Srdivacky// This contains code to print types from Clang's type system. 11199482Srdivacky// 12199482Srdivacky//===----------------------------------------------------------------------===// 13199482Srdivacky 14199482Srdivacky#include "clang/AST/Decl.h" 15199482Srdivacky#include "clang/AST/DeclObjC.h" 16199482Srdivacky#include "clang/AST/DeclTemplate.h" 17199482Srdivacky#include "clang/AST/Expr.h" 18199482Srdivacky#include "clang/AST/Type.h" 19199482Srdivacky#include "clang/AST/PrettyPrinter.h" 20199482Srdivacky#include "clang/Basic/LangOptions.h" 21205408Srdivacky#include "clang/Basic/SourceManager.h" 22199482Srdivacky#include "llvm/ADT/StringExtras.h" 23199482Srdivacky#include "llvm/Support/raw_ostream.h" 24199482Srdivackyusing namespace clang; 25199482Srdivacky 26199482Srdivackynamespace { 27199482Srdivacky class TypePrinter { 28199482Srdivacky PrintingPolicy Policy; 29199482Srdivacky 30199482Srdivacky public: 31199482Srdivacky explicit TypePrinter(const PrintingPolicy &Policy) : Policy(Policy) { } 32207619Srdivacky 33218893Sdim void print(const Type *ty, Qualifiers qs, std::string &buffer); 34218893Sdim void print(QualType T, std::string &S); 35204962Srdivacky void AppendScope(DeclContext *DC, std::string &S); 36218893Sdim void printTag(TagDecl *T, std::string &S); 37199482Srdivacky#define ABSTRACT_TYPE(CLASS, PARENT) 38199482Srdivacky#define TYPE(CLASS, PARENT) \ 39218893Sdim void print##CLASS(const CLASS##Type *T, std::string &S); 40199482Srdivacky#include "clang/AST/TypeNodes.def" 41199482Srdivacky }; 42199482Srdivacky} 43199482Srdivacky 44199482Srdivackystatic void AppendTypeQualList(std::string &S, unsigned TypeQuals) { 45199482Srdivacky if (TypeQuals & Qualifiers::Const) { 46199482Srdivacky if (!S.empty()) S += ' '; 47199482Srdivacky S += "const"; 48199482Srdivacky } 49199482Srdivacky if (TypeQuals & Qualifiers::Volatile) { 50199482Srdivacky if (!S.empty()) S += ' '; 51199482Srdivacky S += "volatile"; 52199482Srdivacky } 53199482Srdivacky if (TypeQuals & Qualifiers::Restrict) { 54199482Srdivacky if (!S.empty()) S += ' '; 55199482Srdivacky S += "restrict"; 56199482Srdivacky } 57199482Srdivacky} 58199482Srdivacky 59218893Sdimvoid TypePrinter::print(QualType t, std::string &buffer) { 60218893Sdim SplitQualType split = t.split(); 61218893Sdim print(split.first, split.second, buffer); 62218893Sdim} 63218893Sdim 64218893Sdimvoid TypePrinter::print(const Type *T, Qualifiers Quals, std::string &buffer) { 65218893Sdim if (!T) { 66218893Sdim buffer += "NULL TYPE"; 67199482Srdivacky return; 68199482Srdivacky } 69199482Srdivacky 70199482Srdivacky if (Policy.SuppressSpecifiers && T->isSpecifierType()) 71199482Srdivacky return; 72199482Srdivacky 73199482Srdivacky // Print qualifiers as appropriate. 74218893Sdim 75218893Sdim // CanPrefixQualifiers - We prefer to print type qualifiers before the type, 76218893Sdim // so that we get "const int" instead of "int const", but we can't do this if 77218893Sdim // the type is complex. For example if the type is "int*", we *must* print 78218893Sdim // "int * const", printing "const int *" is different. Only do this when the 79218893Sdim // type expands to a simple string. 80218893Sdim bool CanPrefixQualifiers = false; 81218893Sdim 82218893Sdim Type::TypeClass TC = T->getTypeClass(); 83218893Sdim if (const AutoType *AT = dyn_cast<AutoType>(T)) 84218893Sdim TC = AT->desugar()->getTypeClass(); 85218893Sdim if (const SubstTemplateTypeParmType *Subst 86218893Sdim = dyn_cast<SubstTemplateTypeParmType>(T)) 87218893Sdim TC = Subst->getReplacementType()->getTypeClass(); 88218893Sdim 89218893Sdim switch (TC) { 90218893Sdim case Type::Builtin: 91218893Sdim case Type::Complex: 92218893Sdim case Type::UnresolvedUsing: 93218893Sdim case Type::Typedef: 94218893Sdim case Type::TypeOfExpr: 95218893Sdim case Type::TypeOf: 96218893Sdim case Type::Decltype: 97218893Sdim case Type::Record: 98218893Sdim case Type::Enum: 99218893Sdim case Type::Elaborated: 100218893Sdim case Type::TemplateTypeParm: 101218893Sdim case Type::SubstTemplateTypeParmPack: 102218893Sdim case Type::TemplateSpecialization: 103218893Sdim case Type::InjectedClassName: 104218893Sdim case Type::DependentName: 105218893Sdim case Type::DependentTemplateSpecialization: 106218893Sdim case Type::ObjCObject: 107218893Sdim case Type::ObjCInterface: 108218893Sdim CanPrefixQualifiers = true; 109218893Sdim break; 110218893Sdim 111218893Sdim case Type::ObjCObjectPointer: 112218893Sdim CanPrefixQualifiers = T->isObjCIdType() || T->isObjCClassType() || 113218893Sdim T->isObjCQualifiedIdType() || T->isObjCQualifiedClassType(); 114218893Sdim break; 115218893Sdim 116218893Sdim case Type::Pointer: 117218893Sdim case Type::BlockPointer: 118218893Sdim case Type::LValueReference: 119218893Sdim case Type::RValueReference: 120218893Sdim case Type::MemberPointer: 121218893Sdim case Type::ConstantArray: 122218893Sdim case Type::IncompleteArray: 123218893Sdim case Type::VariableArray: 124218893Sdim case Type::DependentSizedArray: 125218893Sdim case Type::DependentSizedExtVector: 126218893Sdim case Type::Vector: 127218893Sdim case Type::ExtVector: 128218893Sdim case Type::FunctionProto: 129218893Sdim case Type::FunctionNoProto: 130218893Sdim case Type::Paren: 131218893Sdim case Type::Attributed: 132218893Sdim case Type::PackExpansion: 133218893Sdim case Type::SubstTemplateTypeParm: 134218893Sdim case Type::Auto: 135218893Sdim CanPrefixQualifiers = false; 136218893Sdim break; 137218893Sdim } 138218893Sdim 139218893Sdim if (!CanPrefixQualifiers && !Quals.empty()) { 140218893Sdim std::string qualsBuffer; 141218893Sdim Quals.getAsStringInternal(qualsBuffer, Policy); 142199482Srdivacky 143218893Sdim if (!buffer.empty()) { 144218893Sdim qualsBuffer += ' '; 145218893Sdim qualsBuffer += buffer; 146199482Srdivacky } 147218893Sdim std::swap(buffer, qualsBuffer); 148199482Srdivacky } 149199482Srdivacky 150199482Srdivacky switch (T->getTypeClass()) { 151199482Srdivacky#define ABSTRACT_TYPE(CLASS, PARENT) 152218893Sdim#define TYPE(CLASS, PARENT) case Type::CLASS: \ 153218893Sdim print##CLASS(cast<CLASS##Type>(T), buffer); \ 154199482Srdivacky break; 155199482Srdivacky#include "clang/AST/TypeNodes.def" 156199482Srdivacky } 157218893Sdim 158218893Sdim // If we're adding the qualifiers as a prefix, do it now. 159218893Sdim if (CanPrefixQualifiers && !Quals.empty()) { 160218893Sdim std::string qualsBuffer; 161218893Sdim Quals.getAsStringInternal(qualsBuffer, Policy); 162218893Sdim 163218893Sdim if (!buffer.empty()) { 164218893Sdim qualsBuffer += ' '; 165218893Sdim qualsBuffer += buffer; 166218893Sdim } 167218893Sdim std::swap(buffer, qualsBuffer); 168218893Sdim } 169199482Srdivacky} 170199482Srdivacky 171218893Sdimvoid TypePrinter::printBuiltin(const BuiltinType *T, std::string &S) { 172199482Srdivacky if (S.empty()) { 173199482Srdivacky S = T->getName(Policy.LangOpts); 174199482Srdivacky } else { 175199482Srdivacky // Prefix the basic type, e.g. 'int X'. 176199482Srdivacky S = ' ' + S; 177199482Srdivacky S = T->getName(Policy.LangOpts) + S; 178199482Srdivacky } 179199482Srdivacky} 180199482Srdivacky 181218893Sdimvoid TypePrinter::printComplex(const ComplexType *T, std::string &S) { 182218893Sdim print(T->getElementType(), S); 183199482Srdivacky S = "_Complex " + S; 184199482Srdivacky} 185199482Srdivacky 186218893Sdimvoid TypePrinter::printPointer(const PointerType *T, std::string &S) { 187199482Srdivacky S = '*' + S; 188199482Srdivacky 189199482Srdivacky // Handle things like 'int (*A)[4];' correctly. 190199482Srdivacky // FIXME: this should include vectors, but vectors use attributes I guess. 191199482Srdivacky if (isa<ArrayType>(T->getPointeeType())) 192199482Srdivacky S = '(' + S + ')'; 193199482Srdivacky 194218893Sdim print(T->getPointeeType(), S); 195199482Srdivacky} 196199482Srdivacky 197218893Sdimvoid TypePrinter::printBlockPointer(const BlockPointerType *T, std::string &S) { 198199482Srdivacky S = '^' + S; 199218893Sdim print(T->getPointeeType(), S); 200199482Srdivacky} 201199482Srdivacky 202218893Sdimvoid TypePrinter::printLValueReference(const LValueReferenceType *T, 203199482Srdivacky std::string &S) { 204199482Srdivacky S = '&' + S; 205199482Srdivacky 206199482Srdivacky // Handle things like 'int (&A)[4];' correctly. 207199482Srdivacky // FIXME: this should include vectors, but vectors use attributes I guess. 208199482Srdivacky if (isa<ArrayType>(T->getPointeeTypeAsWritten())) 209199482Srdivacky S = '(' + S + ')'; 210199482Srdivacky 211218893Sdim print(T->getPointeeTypeAsWritten(), S); 212199482Srdivacky} 213199482Srdivacky 214218893Sdimvoid TypePrinter::printRValueReference(const RValueReferenceType *T, 215199482Srdivacky std::string &S) { 216199482Srdivacky S = "&&" + S; 217199482Srdivacky 218199482Srdivacky // Handle things like 'int (&&A)[4];' correctly. 219199482Srdivacky // FIXME: this should include vectors, but vectors use attributes I guess. 220199482Srdivacky if (isa<ArrayType>(T->getPointeeTypeAsWritten())) 221199482Srdivacky S = '(' + S + ')'; 222199482Srdivacky 223218893Sdim print(T->getPointeeTypeAsWritten(), S); 224199482Srdivacky} 225199482Srdivacky 226218893Sdimvoid TypePrinter::printMemberPointer(const MemberPointerType *T, 227199482Srdivacky std::string &S) { 228199482Srdivacky std::string C; 229218893Sdim print(QualType(T->getClass(), 0), C); 230199482Srdivacky C += "::*"; 231199482Srdivacky S = C + S; 232199482Srdivacky 233199482Srdivacky // Handle things like 'int (Cls::*A)[4];' correctly. 234199482Srdivacky // FIXME: this should include vectors, but vectors use attributes I guess. 235199482Srdivacky if (isa<ArrayType>(T->getPointeeType())) 236199482Srdivacky S = '(' + S + ')'; 237199482Srdivacky 238218893Sdim print(T->getPointeeType(), S); 239199482Srdivacky} 240199482Srdivacky 241218893Sdimvoid TypePrinter::printConstantArray(const ConstantArrayType *T, 242199482Srdivacky std::string &S) { 243199482Srdivacky S += '['; 244199482Srdivacky S += llvm::utostr(T->getSize().getZExtValue()); 245199482Srdivacky S += ']'; 246199482Srdivacky 247218893Sdim print(T->getElementType(), S); 248199482Srdivacky} 249199482Srdivacky 250218893Sdimvoid TypePrinter::printIncompleteArray(const IncompleteArrayType *T, 251199482Srdivacky std::string &S) { 252199482Srdivacky S += "[]"; 253218893Sdim print(T->getElementType(), S); 254199482Srdivacky} 255199482Srdivacky 256218893Sdimvoid TypePrinter::printVariableArray(const VariableArrayType *T, 257199482Srdivacky std::string &S) { 258199482Srdivacky S += '['; 259199482Srdivacky 260199482Srdivacky if (T->getIndexTypeQualifiers().hasQualifiers()) { 261199482Srdivacky AppendTypeQualList(S, T->getIndexTypeCVRQualifiers()); 262199482Srdivacky S += ' '; 263199482Srdivacky } 264199482Srdivacky 265199482Srdivacky if (T->getSizeModifier() == VariableArrayType::Static) 266199482Srdivacky S += "static"; 267199482Srdivacky else if (T->getSizeModifier() == VariableArrayType::Star) 268199482Srdivacky S += '*'; 269199482Srdivacky 270199482Srdivacky if (T->getSizeExpr()) { 271199482Srdivacky std::string SStr; 272199482Srdivacky llvm::raw_string_ostream s(SStr); 273199482Srdivacky T->getSizeExpr()->printPretty(s, 0, Policy); 274199482Srdivacky S += s.str(); 275199482Srdivacky } 276199482Srdivacky S += ']'; 277199482Srdivacky 278218893Sdim print(T->getElementType(), S); 279199482Srdivacky} 280199482Srdivacky 281218893Sdimvoid TypePrinter::printDependentSizedArray(const DependentSizedArrayType *T, 282199482Srdivacky std::string &S) { 283199482Srdivacky S += '['; 284199482Srdivacky 285199482Srdivacky if (T->getSizeExpr()) { 286199482Srdivacky std::string SStr; 287199482Srdivacky llvm::raw_string_ostream s(SStr); 288199482Srdivacky T->getSizeExpr()->printPretty(s, 0, Policy); 289199482Srdivacky S += s.str(); 290199482Srdivacky } 291199482Srdivacky S += ']'; 292199482Srdivacky 293218893Sdim print(T->getElementType(), S); 294199482Srdivacky} 295199482Srdivacky 296218893Sdimvoid TypePrinter::printDependentSizedExtVector( 297199482Srdivacky const DependentSizedExtVectorType *T, 298199482Srdivacky std::string &S) { 299218893Sdim print(T->getElementType(), S); 300199482Srdivacky 301199482Srdivacky S += " __attribute__((ext_vector_type("; 302199482Srdivacky if (T->getSizeExpr()) { 303199482Srdivacky std::string SStr; 304199482Srdivacky llvm::raw_string_ostream s(SStr); 305199482Srdivacky T->getSizeExpr()->printPretty(s, 0, Policy); 306199482Srdivacky S += s.str(); 307199482Srdivacky } 308199482Srdivacky S += ")))"; 309199482Srdivacky} 310199482Srdivacky 311218893Sdimvoid TypePrinter::printVector(const VectorType *T, std::string &S) { 312218893Sdim switch (T->getVectorKind()) { 313218893Sdim case VectorType::AltiVecPixel: 314218893Sdim S = "__vector __pixel " + S; 315218893Sdim break; 316218893Sdim case VectorType::AltiVecBool: 317218893Sdim print(T->getElementType(), S); 318218893Sdim S = "__vector __bool " + S; 319218893Sdim break; 320218893Sdim case VectorType::AltiVecVector: 321218893Sdim print(T->getElementType(), S); 322218893Sdim S = "__vector " + S; 323218893Sdim break; 324218893Sdim case VectorType::NeonVector: 325218893Sdim print(T->getElementType(), S); 326218893Sdim S = ("__attribute__((neon_vector_type(" + 327218893Sdim llvm::utostr_32(T->getNumElements()) + "))) " + S); 328218893Sdim break; 329218893Sdim case VectorType::NeonPolyVector: 330218893Sdim print(T->getElementType(), S); 331218893Sdim S = ("__attribute__((neon_polyvector_type(" + 332218893Sdim llvm::utostr_32(T->getNumElements()) + "))) " + S); 333218893Sdim break; 334218893Sdim case VectorType::GenericVector: { 335203955Srdivacky // FIXME: We prefer to print the size directly here, but have no way 336203955Srdivacky // to get the size of the type. 337218893Sdim print(T->getElementType(), S); 338203955Srdivacky std::string V = "__attribute__((__vector_size__("; 339203955Srdivacky V += llvm::utostr_32(T->getNumElements()); // convert back to bytes. 340203955Srdivacky std::string ET; 341218893Sdim print(T->getElementType(), ET); 342203955Srdivacky V += " * sizeof(" + ET + ")))) "; 343203955Srdivacky S = V + S; 344218893Sdim break; 345203955Srdivacky } 346218893Sdim } 347199482Srdivacky} 348199482Srdivacky 349218893Sdimvoid TypePrinter::printExtVector(const ExtVectorType *T, std::string &S) { 350199482Srdivacky S += " __attribute__((ext_vector_type("; 351199482Srdivacky S += llvm::utostr_32(T->getNumElements()); 352199482Srdivacky S += ")))"; 353218893Sdim print(T->getElementType(), S); 354199482Srdivacky} 355199482Srdivacky 356218893Sdimvoid TypePrinter::printFunctionProto(const FunctionProtoType *T, 357199482Srdivacky std::string &S) { 358199482Srdivacky // If needed for precedence reasons, wrap the inner part in grouping parens. 359199482Srdivacky if (!S.empty()) 360199482Srdivacky S = "(" + S + ")"; 361199482Srdivacky 362199482Srdivacky S += "("; 363199482Srdivacky std::string Tmp; 364199482Srdivacky PrintingPolicy ParamPolicy(Policy); 365199482Srdivacky ParamPolicy.SuppressSpecifiers = false; 366199482Srdivacky for (unsigned i = 0, e = T->getNumArgs(); i != e; ++i) { 367199482Srdivacky if (i) S += ", "; 368218893Sdim print(T->getArgType(i), Tmp); 369199482Srdivacky S += Tmp; 370199482Srdivacky Tmp.clear(); 371199482Srdivacky } 372199482Srdivacky 373199482Srdivacky if (T->isVariadic()) { 374199482Srdivacky if (T->getNumArgs()) 375199482Srdivacky S += ", "; 376199482Srdivacky S += "..."; 377199482Srdivacky } else if (T->getNumArgs() == 0 && !Policy.LangOpts.CPlusPlus) { 378199482Srdivacky // Do not emit int() if we have a proto, emit 'int(void)'. 379199482Srdivacky S += "void"; 380199482Srdivacky } 381199482Srdivacky 382199482Srdivacky S += ")"; 383200583Srdivacky 384206084Srdivacky FunctionType::ExtInfo Info = T->getExtInfo(); 385206084Srdivacky switch(Info.getCC()) { 386203955Srdivacky case CC_Default: 387203955Srdivacky default: break; 388203955Srdivacky case CC_C: 389203955Srdivacky S += " __attribute__((cdecl))"; 390203955Srdivacky break; 391203955Srdivacky case CC_X86StdCall: 392203955Srdivacky S += " __attribute__((stdcall))"; 393203955Srdivacky break; 394203955Srdivacky case CC_X86FastCall: 395203955Srdivacky S += " __attribute__((fastcall))"; 396203955Srdivacky break; 397208600Srdivacky case CC_X86ThisCall: 398208600Srdivacky S += " __attribute__((thiscall))"; 399208600Srdivacky break; 400212904Sdim case CC_X86Pascal: 401212904Sdim S += " __attribute__((pascal))"; 402212904Sdim break; 403203955Srdivacky } 404206084Srdivacky if (Info.getNoReturn()) 405202379Srdivacky S += " __attribute__((noreturn))"; 406206084Srdivacky if (Info.getRegParm()) 407206084Srdivacky S += " __attribute__((regparm (" + 408206084Srdivacky llvm::utostr_32(Info.getRegParm()) + ")))"; 409202379Srdivacky 410218893Sdim AppendTypeQualList(S, T->getTypeQuals()); 411218893Sdim 412218893Sdim switch (T->getRefQualifier()) { 413218893Sdim case RQ_None: 414218893Sdim break; 415218893Sdim 416218893Sdim case RQ_LValue: 417218893Sdim S += " &"; 418218893Sdim break; 419218893Sdim 420218893Sdim case RQ_RValue: 421218893Sdim S += " &&"; 422218893Sdim break; 423218893Sdim } 424218893Sdim 425200583Srdivacky if (T->hasExceptionSpec()) { 426200583Srdivacky S += " throw("; 427200583Srdivacky if (T->hasAnyExceptionSpec()) 428200583Srdivacky S += "..."; 429200583Srdivacky else 430200583Srdivacky for (unsigned I = 0, N = T->getNumExceptions(); I != N; ++I) { 431200583Srdivacky if (I) 432200583Srdivacky S += ", "; 433200583Srdivacky 434200583Srdivacky std::string ExceptionType; 435218893Sdim print(T->getExceptionType(I), ExceptionType); 436200583Srdivacky S += ExceptionType; 437200583Srdivacky } 438200583Srdivacky S += ")"; 439200583Srdivacky } 440200583Srdivacky 441218893Sdim print(T->getResultType(), S); 442199482Srdivacky} 443199482Srdivacky 444218893Sdimvoid TypePrinter::printFunctionNoProto(const FunctionNoProtoType *T, 445199482Srdivacky std::string &S) { 446199482Srdivacky // If needed for precedence reasons, wrap the inner part in grouping parens. 447199482Srdivacky if (!S.empty()) 448199482Srdivacky S = "(" + S + ")"; 449199482Srdivacky 450199482Srdivacky S += "()"; 451199482Srdivacky if (T->getNoReturnAttr()) 452199482Srdivacky S += " __attribute__((noreturn))"; 453218893Sdim print(T->getResultType(), S); 454199482Srdivacky} 455199482Srdivacky 456218893Sdimstatic void printTypeSpec(const NamedDecl *D, std::string &S) { 457204962Srdivacky IdentifierInfo *II = D->getIdentifier(); 458200583Srdivacky if (S.empty()) 459200583Srdivacky S = II->getName().str(); 460200583Srdivacky else 461200583Srdivacky S = II->getName().str() + ' ' + S; 462200583Srdivacky} 463200583Srdivacky 464218893Sdimvoid TypePrinter::printUnresolvedUsing(const UnresolvedUsingType *T, 465204962Srdivacky std::string &S) { 466218893Sdim printTypeSpec(T->getDecl(), S); 467204962Srdivacky} 468204962Srdivacky 469218893Sdimvoid TypePrinter::printTypedef(const TypedefType *T, std::string &S) { 470218893Sdim printTypeSpec(T->getDecl(), S); 471199482Srdivacky} 472199482Srdivacky 473218893Sdimvoid TypePrinter::printTypeOfExpr(const TypeOfExprType *T, std::string &S) { 474199482Srdivacky if (!S.empty()) // Prefix the basic type, e.g. 'typeof(e) X'. 475199482Srdivacky S = ' ' + S; 476199482Srdivacky std::string Str; 477199482Srdivacky llvm::raw_string_ostream s(Str); 478199482Srdivacky T->getUnderlyingExpr()->printPretty(s, 0, Policy); 479199482Srdivacky S = "typeof " + s.str() + S; 480199482Srdivacky} 481199482Srdivacky 482218893Sdimvoid TypePrinter::printTypeOf(const TypeOfType *T, std::string &S) { 483199482Srdivacky if (!S.empty()) // Prefix the basic type, e.g. 'typeof(t) X'. 484199482Srdivacky S = ' ' + S; 485199482Srdivacky std::string Tmp; 486218893Sdim print(T->getUnderlyingType(), Tmp); 487199482Srdivacky S = "typeof(" + Tmp + ")" + S; 488199482Srdivacky} 489199482Srdivacky 490218893Sdimvoid TypePrinter::printDecltype(const DecltypeType *T, std::string &S) { 491199482Srdivacky if (!S.empty()) // Prefix the basic type, e.g. 'decltype(t) X'. 492199482Srdivacky S = ' ' + S; 493199482Srdivacky std::string Str; 494199482Srdivacky llvm::raw_string_ostream s(Str); 495199482Srdivacky T->getUnderlyingExpr()->printPretty(s, 0, Policy); 496199482Srdivacky S = "decltype(" + s.str() + ")" + S; 497199482Srdivacky} 498199482Srdivacky 499218893Sdimvoid TypePrinter::printAuto(const AutoType *T, std::string &S) { 500218893Sdim // If the type has been deduced, do not print 'auto'. 501218893Sdim if (T->isDeduced()) { 502218893Sdim print(T->getDeducedType(), S); 503218893Sdim } else { 504218893Sdim if (!S.empty()) // Prefix the basic type, e.g. 'auto X'. 505218893Sdim S = ' ' + S; 506218893Sdim S = "auto" + S; 507218893Sdim } 508218893Sdim} 509218893Sdim 510204962Srdivacky/// Appends the given scope to the end of a string. 511204962Srdivackyvoid TypePrinter::AppendScope(DeclContext *DC, std::string &Buffer) { 512204962Srdivacky if (DC->isTranslationUnit()) return; 513204962Srdivacky AppendScope(DC->getParent(), Buffer); 514204962Srdivacky 515204962Srdivacky unsigned OldSize = Buffer.size(); 516204962Srdivacky 517204962Srdivacky if (NamespaceDecl *NS = dyn_cast<NamespaceDecl>(DC)) { 518204962Srdivacky if (NS->getIdentifier()) 519204962Srdivacky Buffer += NS->getNameAsString(); 520204962Srdivacky else 521204962Srdivacky Buffer += "<anonymous>"; 522204962Srdivacky } else if (ClassTemplateSpecializationDecl *Spec 523204962Srdivacky = dyn_cast<ClassTemplateSpecializationDecl>(DC)) { 524204962Srdivacky const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs(); 525204962Srdivacky std::string TemplateArgsStr 526204962Srdivacky = TemplateSpecializationType::PrintTemplateArgumentList( 527218893Sdim TemplateArgs.data(), 528218893Sdim TemplateArgs.size(), 529204962Srdivacky Policy); 530204962Srdivacky Buffer += Spec->getIdentifier()->getName(); 531204962Srdivacky Buffer += TemplateArgsStr; 532204962Srdivacky } else if (TagDecl *Tag = dyn_cast<TagDecl>(DC)) { 533204962Srdivacky if (TypedefDecl *Typedef = Tag->getTypedefForAnonDecl()) 534204962Srdivacky Buffer += Typedef->getIdentifier()->getName(); 535204962Srdivacky else if (Tag->getIdentifier()) 536204962Srdivacky Buffer += Tag->getIdentifier()->getName(); 537204962Srdivacky } 538204962Srdivacky 539204962Srdivacky if (Buffer.size() != OldSize) 540204962Srdivacky Buffer += "::"; 541204962Srdivacky} 542204962Srdivacky 543218893Sdimvoid TypePrinter::printTag(TagDecl *D, std::string &InnerString) { 544199482Srdivacky if (Policy.SuppressTag) 545199482Srdivacky return; 546204962Srdivacky 547204962Srdivacky std::string Buffer; 548205408Srdivacky bool HasKindDecoration = false; 549204962Srdivacky 550204962Srdivacky // We don't print tags unless this is an elaborated type. 551204962Srdivacky // In C, we just assume every RecordType is an elaborated type. 552204962Srdivacky if (!Policy.LangOpts.CPlusPlus && !D->getTypedefForAnonDecl()) { 553205408Srdivacky HasKindDecoration = true; 554204962Srdivacky Buffer += D->getKindName(); 555204962Srdivacky Buffer += ' '; 556204962Srdivacky } 557204962Srdivacky 558212904Sdim // Compute the full nested-name-specifier for this type. 559212904Sdim // In C, this will always be empty except when the type 560212904Sdim // being printed is anonymous within other Record. 561204962Srdivacky if (!Policy.SuppressScope) 562204962Srdivacky AppendScope(D->getDeclContext(), Buffer); 563204962Srdivacky 564204962Srdivacky if (const IdentifierInfo *II = D->getIdentifier()) 565205408Srdivacky Buffer += II->getNameStart(); 566204962Srdivacky else if (TypedefDecl *Typedef = D->getTypedefForAnonDecl()) { 567199482Srdivacky assert(Typedef->getIdentifier() && "Typedef without identifier?"); 568205408Srdivacky Buffer += Typedef->getIdentifier()->getNameStart(); 569205408Srdivacky } else { 570205408Srdivacky // Make an unambiguous representation for anonymous types, e.g. 571205408Srdivacky // <anonymous enum at /usr/include/string.h:120:9> 572205408Srdivacky llvm::raw_string_ostream OS(Buffer); 573205408Srdivacky OS << "<anonymous"; 574204962Srdivacky 575206275Srdivacky if (Policy.AnonymousTagLocations) { 576206275Srdivacky // Suppress the redundant tag keyword if we just printed one. 577206275Srdivacky // We don't have to worry about ElaboratedTypes here because you can't 578206275Srdivacky // refer to an anonymous type with one. 579206275Srdivacky if (!HasKindDecoration) 580206275Srdivacky OS << " " << D->getKindName(); 581205408Srdivacky 582218893Sdim PresumedLoc PLoc = D->getASTContext().getSourceManager().getPresumedLoc( 583210299Sed D->getLocation()); 584218893Sdim if (PLoc.isValid()) { 585210299Sed OS << " at " << PLoc.getFilename() 586210299Sed << ':' << PLoc.getLine() 587210299Sed << ':' << PLoc.getColumn(); 588210299Sed } 589206275Srdivacky } 590206275Srdivacky 591206275Srdivacky OS << '>'; 592205408Srdivacky } 593205408Srdivacky 594199482Srdivacky // If this is a class template specialization, print the template 595199482Srdivacky // arguments. 596199482Srdivacky if (ClassTemplateSpecializationDecl *Spec 597204962Srdivacky = dyn_cast<ClassTemplateSpecializationDecl>(D)) { 598204962Srdivacky const TemplateArgument *Args; 599204962Srdivacky unsigned NumArgs; 600204962Srdivacky if (TypeSourceInfo *TAW = Spec->getTypeAsWritten()) { 601204962Srdivacky const TemplateSpecializationType *TST = 602204962Srdivacky cast<TemplateSpecializationType>(TAW->getType()); 603204962Srdivacky Args = TST->getArgs(); 604204962Srdivacky NumArgs = TST->getNumArgs(); 605204962Srdivacky } else { 606204962Srdivacky const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs(); 607218893Sdim Args = TemplateArgs.data(); 608218893Sdim NumArgs = TemplateArgs.size(); 609204962Srdivacky } 610204962Srdivacky Buffer += TemplateSpecializationType::PrintTemplateArgumentList(Args, 611204962Srdivacky NumArgs, 612204962Srdivacky Policy); 613199482Srdivacky } 614204962Srdivacky 615204962Srdivacky if (!InnerString.empty()) { 616204962Srdivacky Buffer += ' '; 617204962Srdivacky Buffer += InnerString; 618204962Srdivacky } 619204962Srdivacky 620204962Srdivacky std::swap(Buffer, InnerString); 621199482Srdivacky} 622199482Srdivacky 623218893Sdimvoid TypePrinter::printRecord(const RecordType *T, std::string &S) { 624218893Sdim printTag(T->getDecl(), S); 625199482Srdivacky} 626199482Srdivacky 627218893Sdimvoid TypePrinter::printEnum(const EnumType *T, std::string &S) { 628218893Sdim printTag(T->getDecl(), S); 629199482Srdivacky} 630199482Srdivacky 631218893Sdimvoid TypePrinter::printTemplateTypeParm(const TemplateTypeParmType *T, 632199482Srdivacky std::string &S) { 633199482Srdivacky if (!S.empty()) // Prefix the basic type, e.g. 'parmname X'. 634199482Srdivacky S = ' ' + S; 635199482Srdivacky 636199482Srdivacky if (!T->getName()) 637199482Srdivacky S = "type-parameter-" + llvm::utostr_32(T->getDepth()) + '-' + 638199482Srdivacky llvm::utostr_32(T->getIndex()) + S; 639199482Srdivacky else 640199482Srdivacky S = T->getName()->getName().str() + S; 641199482Srdivacky} 642199482Srdivacky 643218893Sdimvoid TypePrinter::printSubstTemplateTypeParm(const SubstTemplateTypeParmType *T, 644199482Srdivacky std::string &S) { 645218893Sdim print(T->getReplacementType(), S); 646199482Srdivacky} 647199482Srdivacky 648218893Sdimvoid TypePrinter::printSubstTemplateTypeParmPack( 649218893Sdim const SubstTemplateTypeParmPackType *T, 650218893Sdim std::string &S) { 651218893Sdim printTemplateTypeParm(T->getReplacedParameter(), S); 652218893Sdim} 653218893Sdim 654218893Sdimvoid TypePrinter::printTemplateSpecialization( 655199482Srdivacky const TemplateSpecializationType *T, 656199482Srdivacky std::string &S) { 657199482Srdivacky std::string SpecString; 658199482Srdivacky 659199482Srdivacky { 660199482Srdivacky llvm::raw_string_ostream OS(SpecString); 661199482Srdivacky T->getTemplateName().print(OS, Policy); 662199482Srdivacky } 663199482Srdivacky 664199482Srdivacky SpecString += TemplateSpecializationType::PrintTemplateArgumentList( 665199482Srdivacky T->getArgs(), 666199482Srdivacky T->getNumArgs(), 667199482Srdivacky Policy); 668199482Srdivacky if (S.empty()) 669199482Srdivacky S.swap(SpecString); 670199482Srdivacky else 671199482Srdivacky S = SpecString + ' ' + S; 672199482Srdivacky} 673199482Srdivacky 674218893Sdimvoid TypePrinter::printInjectedClassName(const InjectedClassNameType *T, 675204962Srdivacky std::string &S) { 676218893Sdim printTemplateSpecialization(T->getInjectedTST(), S); 677204962Srdivacky} 678204962Srdivacky 679218893Sdimvoid TypePrinter::printElaborated(const ElaboratedType *T, std::string &S) { 680199482Srdivacky std::string MyString; 681199482Srdivacky 682199482Srdivacky { 683199482Srdivacky llvm::raw_string_ostream OS(MyString); 684208600Srdivacky OS << TypeWithKeyword::getKeywordName(T->getKeyword()); 685208600Srdivacky if (T->getKeyword() != ETK_None) 686208600Srdivacky OS << " "; 687208600Srdivacky NestedNameSpecifier* Qualifier = T->getQualifier(); 688208600Srdivacky if (Qualifier) 689208600Srdivacky Qualifier->print(OS, Policy); 690199482Srdivacky } 691199482Srdivacky 692199482Srdivacky std::string TypeStr; 693199482Srdivacky PrintingPolicy InnerPolicy(Policy); 694199482Srdivacky InnerPolicy.SuppressScope = true; 695218893Sdim TypePrinter(InnerPolicy).print(T->getNamedType(), TypeStr); 696199482Srdivacky 697199482Srdivacky MyString += TypeStr; 698199482Srdivacky if (S.empty()) 699199482Srdivacky S.swap(MyString); 700199482Srdivacky else 701199482Srdivacky S = MyString + ' ' + S; 702199482Srdivacky} 703199482Srdivacky 704218893Sdimvoid TypePrinter::printParen(const ParenType *T, std::string &S) { 705218893Sdim if (!S.empty() && !isa<FunctionType>(T->getInnerType())) 706218893Sdim S = '(' + S + ')'; 707218893Sdim print(T->getInnerType(), S); 708218893Sdim} 709218893Sdim 710218893Sdimvoid TypePrinter::printDependentName(const DependentNameType *T, std::string &S) { 711199482Srdivacky std::string MyString; 712199482Srdivacky 713199482Srdivacky { 714199482Srdivacky llvm::raw_string_ostream OS(MyString); 715208600Srdivacky OS << TypeWithKeyword::getKeywordName(T->getKeyword()); 716208600Srdivacky if (T->getKeyword() != ETK_None) 717208600Srdivacky OS << " "; 718206084Srdivacky 719199482Srdivacky T->getQualifier()->print(OS, Policy); 720199482Srdivacky 721210299Sed OS << T->getIdentifier()->getName(); 722210299Sed } 723210299Sed 724210299Sed if (S.empty()) 725210299Sed S.swap(MyString); 726210299Sed else 727210299Sed S = MyString + ' ' + S; 728210299Sed} 729210299Sed 730218893Sdimvoid TypePrinter::printDependentTemplateSpecialization( 731210299Sed const DependentTemplateSpecializationType *T, std::string &S) { 732210299Sed std::string MyString; 733210299Sed { 734210299Sed llvm::raw_string_ostream OS(MyString); 735210299Sed 736210299Sed OS << TypeWithKeyword::getKeywordName(T->getKeyword()); 737210299Sed if (T->getKeyword() != ETK_None) 738210299Sed OS << " "; 739210299Sed 740210299Sed T->getQualifier()->print(OS, Policy); 741210299Sed OS << T->getIdentifier()->getName(); 742210299Sed OS << TemplateSpecializationType::PrintTemplateArgumentList( 743210299Sed T->getArgs(), 744210299Sed T->getNumArgs(), 745199482Srdivacky Policy); 746199482Srdivacky } 747199482Srdivacky 748199482Srdivacky if (S.empty()) 749199482Srdivacky S.swap(MyString); 750199482Srdivacky else 751199482Srdivacky S = MyString + ' ' + S; 752199482Srdivacky} 753199482Srdivacky 754218893Sdimvoid TypePrinter::printPackExpansion(const PackExpansionType *T, 755218893Sdim std::string &S) { 756218893Sdim print(T->getPattern(), S); 757218893Sdim S += "..."; 758218893Sdim} 759218893Sdim 760218893Sdimvoid TypePrinter::printAttributed(const AttributedType *T, 761218893Sdim std::string &S) { 762218893Sdim print(T->getModifiedType(), S); 763218893Sdim 764218893Sdim // TODO: not all attributes are GCC-style attributes. 765218893Sdim S += "__attribute__(("; 766218893Sdim switch (T->getAttrKind()) { 767218893Sdim case AttributedType::attr_address_space: 768218893Sdim S += "address_space("; 769218893Sdim S += T->getEquivalentType().getAddressSpace(); 770218893Sdim S += ")"; 771218893Sdim break; 772218893Sdim 773218893Sdim case AttributedType::attr_vector_size: { 774218893Sdim S += "__vector_size__("; 775218893Sdim if (const VectorType *vector =T->getEquivalentType()->getAs<VectorType>()) { 776218893Sdim S += vector->getNumElements(); 777218893Sdim S += " * sizeof("; 778218893Sdim 779218893Sdim std::string tmp; 780218893Sdim print(vector->getElementType(), tmp); 781218893Sdim S += tmp; 782218893Sdim S += ")"; 783218893Sdim } 784218893Sdim S += ")"; 785218893Sdim break; 786218893Sdim } 787218893Sdim 788218893Sdim case AttributedType::attr_neon_vector_type: 789218893Sdim case AttributedType::attr_neon_polyvector_type: { 790218893Sdim if (T->getAttrKind() == AttributedType::attr_neon_vector_type) 791218893Sdim S += "neon_vector_type("; 792218893Sdim else 793218893Sdim S += "neon_polyvector_type("; 794218893Sdim const VectorType *vector = T->getEquivalentType()->getAs<VectorType>(); 795218893Sdim S += llvm::utostr_32(vector->getNumElements()); 796218893Sdim S += ")"; 797218893Sdim break; 798218893Sdim } 799218893Sdim 800218893Sdim case AttributedType::attr_regparm: { 801218893Sdim S += "regparm("; 802218893Sdim QualType t = T->getEquivalentType(); 803218893Sdim while (!t->isFunctionType()) 804218893Sdim t = t->getPointeeType(); 805218893Sdim S += t->getAs<FunctionType>()->getRegParmType(); 806218893Sdim S += ")"; 807218893Sdim break; 808218893Sdim } 809218893Sdim 810218893Sdim case AttributedType::attr_objc_gc: { 811218893Sdim S += "objc_gc("; 812218893Sdim 813218893Sdim QualType tmp = T->getEquivalentType(); 814218893Sdim while (tmp.getObjCGCAttr() == Qualifiers::GCNone) { 815218893Sdim QualType next = tmp->getPointeeType(); 816218893Sdim if (next == tmp) break; 817218893Sdim tmp = next; 818218893Sdim } 819218893Sdim 820218893Sdim if (tmp.isObjCGCWeak()) 821218893Sdim S += "weak"; 822218893Sdim else 823218893Sdim S += "strong"; 824218893Sdim S += ")"; 825218893Sdim break; 826218893Sdim } 827218893Sdim 828218893Sdim case AttributedType::attr_noreturn: S += "noreturn"; break; 829218893Sdim case AttributedType::attr_cdecl: S += "cdecl"; break; 830218893Sdim case AttributedType::attr_fastcall: S += "fastcall"; break; 831218893Sdim case AttributedType::attr_stdcall: S += "stdcall"; break; 832218893Sdim case AttributedType::attr_thiscall: S += "thiscall"; break; 833218893Sdim case AttributedType::attr_pascal: S += "pascal"; break; 834218893Sdim } 835218893Sdim S += "))"; 836218893Sdim} 837218893Sdim 838218893Sdimvoid TypePrinter::printObjCInterface(const ObjCInterfaceType *T, 839199482Srdivacky std::string &S) { 840199482Srdivacky if (!S.empty()) // Prefix the basic type, e.g. 'typedefname X'. 841199482Srdivacky S = ' ' + S; 842208600Srdivacky 843199482Srdivacky std::string ObjCQIString = T->getDecl()->getNameAsString(); 844199482Srdivacky S = ObjCQIString + S; 845199482Srdivacky} 846199482Srdivacky 847218893Sdimvoid TypePrinter::printObjCObject(const ObjCObjectType *T, 848208600Srdivacky std::string &S) { 849208600Srdivacky if (T->qual_empty()) 850218893Sdim return print(T->getBaseType(), S); 851208600Srdivacky 852208600Srdivacky std::string tmp; 853218893Sdim print(T->getBaseType(), tmp); 854208600Srdivacky tmp += '<'; 855208600Srdivacky bool isFirst = true; 856208600Srdivacky for (ObjCObjectType::qual_iterator 857208600Srdivacky I = T->qual_begin(), E = T->qual_end(); I != E; ++I) { 858208600Srdivacky if (isFirst) 859208600Srdivacky isFirst = false; 860208600Srdivacky else 861208600Srdivacky tmp += ','; 862208600Srdivacky tmp += (*I)->getNameAsString(); 863208600Srdivacky } 864208600Srdivacky tmp += '>'; 865208600Srdivacky 866208600Srdivacky if (!S.empty()) { 867208600Srdivacky tmp += ' '; 868208600Srdivacky tmp += S; 869208600Srdivacky } 870208600Srdivacky std::swap(tmp, S); 871208600Srdivacky} 872208600Srdivacky 873218893Sdimvoid TypePrinter::printObjCObjectPointer(const ObjCObjectPointerType *T, 874199482Srdivacky std::string &S) { 875199482Srdivacky std::string ObjCQIString; 876199482Srdivacky 877218893Sdim T->getPointeeType().getLocalQualifiers().getAsStringInternal(ObjCQIString, 878218893Sdim Policy); 879218893Sdim if (!ObjCQIString.empty()) 880218893Sdim ObjCQIString += ' '; 881218893Sdim 882199482Srdivacky if (T->isObjCIdType() || T->isObjCQualifiedIdType()) 883218893Sdim ObjCQIString += "id"; 884199482Srdivacky else if (T->isObjCClassType() || T->isObjCQualifiedClassType()) 885218893Sdim ObjCQIString += "Class"; 886199990Srdivacky else if (T->isObjCSelType()) 887218893Sdim ObjCQIString += "SEL"; 888199482Srdivacky else 889218893Sdim ObjCQIString += T->getInterfaceDecl()->getNameAsString(); 890199482Srdivacky 891199482Srdivacky if (!T->qual_empty()) { 892199482Srdivacky ObjCQIString += '<'; 893199482Srdivacky for (ObjCObjectPointerType::qual_iterator I = T->qual_begin(), 894199482Srdivacky E = T->qual_end(); 895199482Srdivacky I != E; ++I) { 896199482Srdivacky ObjCQIString += (*I)->getNameAsString(); 897199482Srdivacky if (I+1 != E) 898199482Srdivacky ObjCQIString += ','; 899199482Srdivacky } 900199482Srdivacky ObjCQIString += '>'; 901199482Srdivacky } 902199482Srdivacky 903199482Srdivacky if (!T->isObjCIdType() && !T->isObjCQualifiedIdType()) 904199482Srdivacky ObjCQIString += " *"; // Don't forget the implicit pointer. 905199482Srdivacky else if (!S.empty()) // Prefix the basic type, e.g. 'typedefname X'. 906199482Srdivacky S = ' ' + S; 907199482Srdivacky 908199482Srdivacky S = ObjCQIString + S; 909199482Srdivacky} 910199482Srdivacky 911199990Srdivackystd::string TemplateSpecializationType:: 912199990Srdivacky PrintTemplateArgumentList(const TemplateArgumentListInfo &Args, 913199990Srdivacky const PrintingPolicy &Policy) { 914199990Srdivacky return PrintTemplateArgumentList(Args.getArgumentArray(), 915199990Srdivacky Args.size(), 916199990Srdivacky Policy); 917199990Srdivacky} 918199990Srdivacky 919199482Srdivackystd::string 920199482SrdivackyTemplateSpecializationType::PrintTemplateArgumentList( 921199482Srdivacky const TemplateArgument *Args, 922199482Srdivacky unsigned NumArgs, 923218893Sdim const PrintingPolicy &Policy, 924218893Sdim bool SkipBrackets) { 925199482Srdivacky std::string SpecString; 926218893Sdim if (!SkipBrackets) 927218893Sdim SpecString += '<'; 928218893Sdim 929199482Srdivacky for (unsigned Arg = 0; Arg < NumArgs; ++Arg) { 930218893Sdim if (SpecString.size() > !SkipBrackets) 931199482Srdivacky SpecString += ", "; 932199482Srdivacky 933199482Srdivacky // Print the argument into a string. 934199482Srdivacky std::string ArgString; 935218893Sdim if (Args[Arg].getKind() == TemplateArgument::Pack) { 936218893Sdim ArgString = PrintTemplateArgumentList(Args[Arg].pack_begin(), 937218893Sdim Args[Arg].pack_size(), 938218893Sdim Policy, true); 939218893Sdim } else { 940218893Sdim llvm::raw_string_ostream ArgOut(ArgString); 941218893Sdim Args[Arg].print(Policy, ArgOut); 942218893Sdim } 943218893Sdim 944199482Srdivacky // If this is the first argument and its string representation 945199482Srdivacky // begins with the global scope specifier ('::foo'), add a space 946199482Srdivacky // to avoid printing the diagraph '<:'. 947199482Srdivacky if (!Arg && !ArgString.empty() && ArgString[0] == ':') 948199482Srdivacky SpecString += ' '; 949199482Srdivacky 950199482Srdivacky SpecString += ArgString; 951199482Srdivacky } 952199482Srdivacky 953199482Srdivacky // If the last character of our string is '>', add another space to 954199482Srdivacky // keep the two '>''s separate tokens. We don't *have* to do this in 955199482Srdivacky // C++0x, but it's still good hygiene. 956218893Sdim if (!SpecString.empty() && SpecString[SpecString.size() - 1] == '>') 957199482Srdivacky SpecString += ' '; 958199482Srdivacky 959218893Sdim if (!SkipBrackets) 960218893Sdim SpecString += '>'; 961199482Srdivacky 962199482Srdivacky return SpecString; 963199482Srdivacky} 964199482Srdivacky 965199482Srdivacky// Sadly, repeat all that with TemplateArgLoc. 966199482Srdivackystd::string TemplateSpecializationType:: 967199482SrdivackyPrintTemplateArgumentList(const TemplateArgumentLoc *Args, unsigned NumArgs, 968199482Srdivacky const PrintingPolicy &Policy) { 969199482Srdivacky std::string SpecString; 970199482Srdivacky SpecString += '<'; 971199482Srdivacky for (unsigned Arg = 0; Arg < NumArgs; ++Arg) { 972218893Sdim if (SpecString.size() > 1) 973199482Srdivacky SpecString += ", "; 974199482Srdivacky 975199482Srdivacky // Print the argument into a string. 976199482Srdivacky std::string ArgString; 977218893Sdim if (Args[Arg].getArgument().getKind() == TemplateArgument::Pack) { 978218893Sdim ArgString = PrintTemplateArgumentList( 979218893Sdim Args[Arg].getArgument().pack_begin(), 980218893Sdim Args[Arg].getArgument().pack_size(), 981218893Sdim Policy, true); 982218893Sdim } else { 983218893Sdim llvm::raw_string_ostream ArgOut(ArgString); 984218893Sdim Args[Arg].getArgument().print(Policy, ArgOut); 985218893Sdim } 986199482Srdivacky 987199482Srdivacky // If this is the first argument and its string representation 988199482Srdivacky // begins with the global scope specifier ('::foo'), add a space 989199482Srdivacky // to avoid printing the diagraph '<:'. 990199482Srdivacky if (!Arg && !ArgString.empty() && ArgString[0] == ':') 991199482Srdivacky SpecString += ' '; 992199482Srdivacky 993199482Srdivacky SpecString += ArgString; 994199482Srdivacky } 995199482Srdivacky 996199482Srdivacky // If the last character of our string is '>', add another space to 997199482Srdivacky // keep the two '>''s separate tokens. We don't *have* to do this in 998199482Srdivacky // C++0x, but it's still good hygiene. 999199482Srdivacky if (SpecString[SpecString.size() - 1] == '>') 1000199482Srdivacky SpecString += ' '; 1001199482Srdivacky 1002199482Srdivacky SpecString += '>'; 1003199482Srdivacky 1004199482Srdivacky return SpecString; 1005199482Srdivacky} 1006199482Srdivacky 1007199482Srdivackyvoid QualType::dump(const char *msg) const { 1008199482Srdivacky std::string R = "identifier"; 1009199482Srdivacky LangOptions LO; 1010199482Srdivacky getAsStringInternal(R, PrintingPolicy(LO)); 1011199482Srdivacky if (msg) 1012200583Srdivacky llvm::errs() << msg << ": "; 1013200583Srdivacky llvm::errs() << R << "\n"; 1014199482Srdivacky} 1015199482Srdivackyvoid QualType::dump() const { 1016199482Srdivacky dump(""); 1017199482Srdivacky} 1018199482Srdivacky 1019199482Srdivackyvoid Type::dump() const { 1020199482Srdivacky QualType(this, 0).dump(); 1021199482Srdivacky} 1022199482Srdivacky 1023199482Srdivackystd::string Qualifiers::getAsString() const { 1024199482Srdivacky LangOptions LO; 1025199482Srdivacky return getAsString(PrintingPolicy(LO)); 1026199482Srdivacky} 1027199482Srdivacky 1028199482Srdivacky// Appends qualifiers to the given string, separated by spaces. Will 1029199482Srdivacky// prefix a space if the string is non-empty. Will not append a final 1030199482Srdivacky// space. 1031199482Srdivackyvoid Qualifiers::getAsStringInternal(std::string &S, 1032199482Srdivacky const PrintingPolicy&) const { 1033199482Srdivacky AppendTypeQualList(S, getCVRQualifiers()); 1034199482Srdivacky if (unsigned AddressSpace = getAddressSpace()) { 1035199482Srdivacky if (!S.empty()) S += ' '; 1036199482Srdivacky S += "__attribute__((address_space("; 1037199482Srdivacky S += llvm::utostr_32(AddressSpace); 1038199482Srdivacky S += ")))"; 1039199482Srdivacky } 1040199482Srdivacky if (Qualifiers::GC GCAttrType = getObjCGCAttr()) { 1041199482Srdivacky if (!S.empty()) S += ' '; 1042199482Srdivacky S += "__attribute__((objc_gc("; 1043199482Srdivacky if (GCAttrType == Qualifiers::Weak) 1044199482Srdivacky S += "weak"; 1045199482Srdivacky else 1046199482Srdivacky S += "strong"; 1047199482Srdivacky S += ")))"; 1048199482Srdivacky } 1049199482Srdivacky} 1050199482Srdivacky 1051218893Sdimstd::string QualType::getAsString(const Type *ty, Qualifiers qs) { 1052218893Sdim std::string buffer; 1053218893Sdim LangOptions options; 1054218893Sdim getAsStringInternal(ty, qs, buffer, PrintingPolicy(options)); 1055218893Sdim return buffer; 1056199482Srdivacky} 1057199482Srdivacky 1058218893Sdimvoid QualType::getAsStringInternal(const Type *ty, Qualifiers qs, 1059218893Sdim std::string &buffer, 1060218893Sdim const PrintingPolicy &policy) { 1061218893Sdim TypePrinter(policy).print(ty, qs, buffer); 1062199482Srdivacky} 1063