TypePrinter.cpp revision 204962
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" 21199482Srdivacky#include "llvm/ADT/StringExtras.h" 22199482Srdivacky#include "llvm/Support/raw_ostream.h" 23199482Srdivackyusing namespace clang; 24199482Srdivacky 25199482Srdivackynamespace { 26199482Srdivacky class TypePrinter { 27199482Srdivacky PrintingPolicy Policy; 28199482Srdivacky 29199482Srdivacky public: 30199482Srdivacky explicit TypePrinter(const PrintingPolicy &Policy) : Policy(Policy) { } 31199482Srdivacky 32199482Srdivacky void Print(QualType T, std::string &S); 33204962Srdivacky void AppendScope(DeclContext *DC, std::string &S); 34204962Srdivacky void PrintTag(TagDecl *T, std::string &S); 35199482Srdivacky#define ABSTRACT_TYPE(CLASS, PARENT) 36199482Srdivacky#define TYPE(CLASS, PARENT) \ 37199482Srdivacky void Print##CLASS(const CLASS##Type *T, std::string &S); 38199482Srdivacky#include "clang/AST/TypeNodes.def" 39199482Srdivacky }; 40199482Srdivacky} 41199482Srdivacky 42199482Srdivackystatic void AppendTypeQualList(std::string &S, unsigned TypeQuals) { 43199482Srdivacky if (TypeQuals & Qualifiers::Const) { 44199482Srdivacky if (!S.empty()) S += ' '; 45199482Srdivacky S += "const"; 46199482Srdivacky } 47199482Srdivacky if (TypeQuals & Qualifiers::Volatile) { 48199482Srdivacky if (!S.empty()) S += ' '; 49199482Srdivacky S += "volatile"; 50199482Srdivacky } 51199482Srdivacky if (TypeQuals & Qualifiers::Restrict) { 52199482Srdivacky if (!S.empty()) S += ' '; 53199482Srdivacky S += "restrict"; 54199482Srdivacky } 55199482Srdivacky} 56199482Srdivacky 57199482Srdivackyvoid TypePrinter::Print(QualType T, std::string &S) { 58199482Srdivacky if (T.isNull()) { 59199482Srdivacky S += "NULL TYPE"; 60199482Srdivacky return; 61199482Srdivacky } 62199482Srdivacky 63199482Srdivacky if (Policy.SuppressSpecifiers && T->isSpecifierType()) 64199482Srdivacky return; 65199482Srdivacky 66199482Srdivacky // Print qualifiers as appropriate. 67199482Srdivacky Qualifiers Quals = T.getLocalQualifiers(); 68199482Srdivacky if (!Quals.empty()) { 69199482Srdivacky std::string TQS; 70199482Srdivacky Quals.getAsStringInternal(TQS, Policy); 71199482Srdivacky 72199482Srdivacky if (!S.empty()) { 73199482Srdivacky TQS += ' '; 74199482Srdivacky TQS += S; 75199482Srdivacky } 76199482Srdivacky std::swap(S, TQS); 77199482Srdivacky } 78199482Srdivacky 79199482Srdivacky switch (T->getTypeClass()) { 80199482Srdivacky#define ABSTRACT_TYPE(CLASS, PARENT) 81199482Srdivacky#define TYPE(CLASS, PARENT) case Type::CLASS: \ 82199482Srdivacky Print##CLASS(cast<CLASS##Type>(T.getTypePtr()), S); \ 83199482Srdivacky break; 84199482Srdivacky#include "clang/AST/TypeNodes.def" 85199482Srdivacky } 86199482Srdivacky} 87199482Srdivacky 88199482Srdivackyvoid TypePrinter::PrintBuiltin(const BuiltinType *T, std::string &S) { 89199482Srdivacky if (S.empty()) { 90199482Srdivacky S = T->getName(Policy.LangOpts); 91199482Srdivacky } else { 92199482Srdivacky // Prefix the basic type, e.g. 'int X'. 93199482Srdivacky S = ' ' + S; 94199482Srdivacky S = T->getName(Policy.LangOpts) + S; 95199482Srdivacky } 96199482Srdivacky} 97199482Srdivacky 98199482Srdivackyvoid TypePrinter::PrintComplex(const ComplexType *T, std::string &S) { 99199482Srdivacky Print(T->getElementType(), S); 100199482Srdivacky S = "_Complex " + S; 101199482Srdivacky} 102199482Srdivacky 103199482Srdivackyvoid TypePrinter::PrintPointer(const PointerType *T, std::string &S) { 104199482Srdivacky S = '*' + S; 105199482Srdivacky 106199482Srdivacky // Handle things like 'int (*A)[4];' correctly. 107199482Srdivacky // FIXME: this should include vectors, but vectors use attributes I guess. 108199482Srdivacky if (isa<ArrayType>(T->getPointeeType())) 109199482Srdivacky S = '(' + S + ')'; 110199482Srdivacky 111199482Srdivacky Print(T->getPointeeType(), S); 112199482Srdivacky} 113199482Srdivacky 114199482Srdivackyvoid TypePrinter::PrintBlockPointer(const BlockPointerType *T, std::string &S) { 115199482Srdivacky S = '^' + S; 116199482Srdivacky Print(T->getPointeeType(), S); 117199482Srdivacky} 118199482Srdivacky 119199482Srdivackyvoid TypePrinter::PrintLValueReference(const LValueReferenceType *T, 120199482Srdivacky std::string &S) { 121199482Srdivacky S = '&' + S; 122199482Srdivacky 123199482Srdivacky // Handle things like 'int (&A)[4];' correctly. 124199482Srdivacky // FIXME: this should include vectors, but vectors use attributes I guess. 125199482Srdivacky if (isa<ArrayType>(T->getPointeeTypeAsWritten())) 126199482Srdivacky S = '(' + S + ')'; 127199482Srdivacky 128199482Srdivacky Print(T->getPointeeTypeAsWritten(), S); 129199482Srdivacky} 130199482Srdivacky 131199482Srdivackyvoid TypePrinter::PrintRValueReference(const RValueReferenceType *T, 132199482Srdivacky std::string &S) { 133199482Srdivacky S = "&&" + S; 134199482Srdivacky 135199482Srdivacky // Handle things like 'int (&&A)[4];' correctly. 136199482Srdivacky // FIXME: this should include vectors, but vectors use attributes I guess. 137199482Srdivacky if (isa<ArrayType>(T->getPointeeTypeAsWritten())) 138199482Srdivacky S = '(' + S + ')'; 139199482Srdivacky 140199482Srdivacky Print(T->getPointeeTypeAsWritten(), S); 141199482Srdivacky} 142199482Srdivacky 143199482Srdivackyvoid TypePrinter::PrintMemberPointer(const MemberPointerType *T, 144199482Srdivacky std::string &S) { 145199482Srdivacky std::string C; 146199482Srdivacky Print(QualType(T->getClass(), 0), C); 147199482Srdivacky C += "::*"; 148199482Srdivacky S = C + S; 149199482Srdivacky 150199482Srdivacky // Handle things like 'int (Cls::*A)[4];' correctly. 151199482Srdivacky // FIXME: this should include vectors, but vectors use attributes I guess. 152199482Srdivacky if (isa<ArrayType>(T->getPointeeType())) 153199482Srdivacky S = '(' + S + ')'; 154199482Srdivacky 155199482Srdivacky Print(T->getPointeeType(), S); 156199482Srdivacky} 157199482Srdivacky 158199482Srdivackyvoid TypePrinter::PrintConstantArray(const ConstantArrayType *T, 159199482Srdivacky std::string &S) { 160199482Srdivacky S += '['; 161199482Srdivacky S += llvm::utostr(T->getSize().getZExtValue()); 162199482Srdivacky S += ']'; 163199482Srdivacky 164199482Srdivacky Print(T->getElementType(), S); 165199482Srdivacky} 166199482Srdivacky 167199482Srdivackyvoid TypePrinter::PrintIncompleteArray(const IncompleteArrayType *T, 168199482Srdivacky std::string &S) { 169199482Srdivacky S += "[]"; 170199482Srdivacky Print(T->getElementType(), S); 171199482Srdivacky} 172199482Srdivacky 173199482Srdivackyvoid TypePrinter::PrintVariableArray(const VariableArrayType *T, 174199482Srdivacky std::string &S) { 175199482Srdivacky S += '['; 176199482Srdivacky 177199482Srdivacky if (T->getIndexTypeQualifiers().hasQualifiers()) { 178199482Srdivacky AppendTypeQualList(S, T->getIndexTypeCVRQualifiers()); 179199482Srdivacky S += ' '; 180199482Srdivacky } 181199482Srdivacky 182199482Srdivacky if (T->getSizeModifier() == VariableArrayType::Static) 183199482Srdivacky S += "static"; 184199482Srdivacky else if (T->getSizeModifier() == VariableArrayType::Star) 185199482Srdivacky S += '*'; 186199482Srdivacky 187199482Srdivacky if (T->getSizeExpr()) { 188199482Srdivacky std::string SStr; 189199482Srdivacky llvm::raw_string_ostream s(SStr); 190199482Srdivacky T->getSizeExpr()->printPretty(s, 0, Policy); 191199482Srdivacky S += s.str(); 192199482Srdivacky } 193199482Srdivacky S += ']'; 194199482Srdivacky 195199482Srdivacky Print(T->getElementType(), S); 196199482Srdivacky} 197199482Srdivacky 198199482Srdivackyvoid TypePrinter::PrintDependentSizedArray(const DependentSizedArrayType *T, 199199482Srdivacky std::string &S) { 200199482Srdivacky S += '['; 201199482Srdivacky 202199482Srdivacky if (T->getSizeExpr()) { 203199482Srdivacky std::string SStr; 204199482Srdivacky llvm::raw_string_ostream s(SStr); 205199482Srdivacky T->getSizeExpr()->printPretty(s, 0, Policy); 206199482Srdivacky S += s.str(); 207199482Srdivacky } 208199482Srdivacky S += ']'; 209199482Srdivacky 210199482Srdivacky Print(T->getElementType(), S); 211199482Srdivacky} 212199482Srdivacky 213199482Srdivackyvoid TypePrinter::PrintDependentSizedExtVector( 214199482Srdivacky const DependentSizedExtVectorType *T, 215199482Srdivacky std::string &S) { 216199482Srdivacky Print(T->getElementType(), S); 217199482Srdivacky 218199482Srdivacky S += " __attribute__((ext_vector_type("; 219199482Srdivacky if (T->getSizeExpr()) { 220199482Srdivacky std::string SStr; 221199482Srdivacky llvm::raw_string_ostream s(SStr); 222199482Srdivacky T->getSizeExpr()->printPretty(s, 0, Policy); 223199482Srdivacky S += s.str(); 224199482Srdivacky } 225199482Srdivacky S += ")))"; 226199482Srdivacky} 227199482Srdivacky 228199482Srdivackyvoid TypePrinter::PrintVector(const VectorType *T, std::string &S) { 229203955Srdivacky if (T->isAltiVec()) { 230203955Srdivacky if (T->isPixel()) 231203955Srdivacky S = "__vector __pixel " + S; 232203955Srdivacky else { 233203955Srdivacky Print(T->getElementType(), S); 234203955Srdivacky S = "__vector " + S; 235203955Srdivacky } 236203955Srdivacky } else { 237203955Srdivacky // FIXME: We prefer to print the size directly here, but have no way 238203955Srdivacky // to get the size of the type. 239203955Srdivacky Print(T->getElementType(), S); 240203955Srdivacky std::string V = "__attribute__((__vector_size__("; 241203955Srdivacky V += llvm::utostr_32(T->getNumElements()); // convert back to bytes. 242203955Srdivacky std::string ET; 243203955Srdivacky Print(T->getElementType(), ET); 244203955Srdivacky V += " * sizeof(" + ET + ")))) "; 245203955Srdivacky S = V + S; 246203955Srdivacky } 247199482Srdivacky} 248199482Srdivacky 249199482Srdivackyvoid TypePrinter::PrintExtVector(const ExtVectorType *T, std::string &S) { 250199482Srdivacky S += " __attribute__((ext_vector_type("; 251199482Srdivacky S += llvm::utostr_32(T->getNumElements()); 252199482Srdivacky S += ")))"; 253199482Srdivacky Print(T->getElementType(), S); 254199482Srdivacky} 255199482Srdivacky 256199482Srdivackyvoid TypePrinter::PrintFunctionProto(const FunctionProtoType *T, 257199482Srdivacky std::string &S) { 258199482Srdivacky // If needed for precedence reasons, wrap the inner part in grouping parens. 259199482Srdivacky if (!S.empty()) 260199482Srdivacky S = "(" + S + ")"; 261199482Srdivacky 262199482Srdivacky S += "("; 263199482Srdivacky std::string Tmp; 264199482Srdivacky PrintingPolicy ParamPolicy(Policy); 265199482Srdivacky ParamPolicy.SuppressSpecifiers = false; 266199482Srdivacky for (unsigned i = 0, e = T->getNumArgs(); i != e; ++i) { 267199482Srdivacky if (i) S += ", "; 268199482Srdivacky Print(T->getArgType(i), Tmp); 269199482Srdivacky S += Tmp; 270199482Srdivacky Tmp.clear(); 271199482Srdivacky } 272199482Srdivacky 273199482Srdivacky if (T->isVariadic()) { 274199482Srdivacky if (T->getNumArgs()) 275199482Srdivacky S += ", "; 276199482Srdivacky S += "..."; 277199482Srdivacky } else if (T->getNumArgs() == 0 && !Policy.LangOpts.CPlusPlus) { 278199482Srdivacky // Do not emit int() if we have a proto, emit 'int(void)'. 279199482Srdivacky S += "void"; 280199482Srdivacky } 281199482Srdivacky 282199482Srdivacky S += ")"; 283200583Srdivacky 284203955Srdivacky switch(T->getCallConv()) { 285203955Srdivacky case CC_Default: 286203955Srdivacky default: break; 287203955Srdivacky case CC_C: 288203955Srdivacky S += " __attribute__((cdecl))"; 289203955Srdivacky break; 290203955Srdivacky case CC_X86StdCall: 291203955Srdivacky S += " __attribute__((stdcall))"; 292203955Srdivacky break; 293203955Srdivacky case CC_X86FastCall: 294203955Srdivacky S += " __attribute__((fastcall))"; 295203955Srdivacky break; 296203955Srdivacky } 297202379Srdivacky if (T->getNoReturnAttr()) 298202379Srdivacky S += " __attribute__((noreturn))"; 299202379Srdivacky 300202379Srdivacky 301200583Srdivacky if (T->hasExceptionSpec()) { 302200583Srdivacky S += " throw("; 303200583Srdivacky if (T->hasAnyExceptionSpec()) 304200583Srdivacky S += "..."; 305200583Srdivacky else 306200583Srdivacky for (unsigned I = 0, N = T->getNumExceptions(); I != N; ++I) { 307200583Srdivacky if (I) 308200583Srdivacky S += ", "; 309200583Srdivacky 310200583Srdivacky std::string ExceptionType; 311200583Srdivacky Print(T->getExceptionType(I), ExceptionType); 312200583Srdivacky S += ExceptionType; 313200583Srdivacky } 314200583Srdivacky S += ")"; 315200583Srdivacky } 316200583Srdivacky 317202379Srdivacky AppendTypeQualList(S, T->getTypeQuals()); 318202379Srdivacky 319199482Srdivacky Print(T->getResultType(), S); 320199482Srdivacky} 321199482Srdivacky 322199482Srdivackyvoid TypePrinter::PrintFunctionNoProto(const FunctionNoProtoType *T, 323199482Srdivacky std::string &S) { 324199482Srdivacky // If needed for precedence reasons, wrap the inner part in grouping parens. 325199482Srdivacky if (!S.empty()) 326199482Srdivacky S = "(" + S + ")"; 327199482Srdivacky 328199482Srdivacky S += "()"; 329199482Srdivacky if (T->getNoReturnAttr()) 330199482Srdivacky S += " __attribute__((noreturn))"; 331199482Srdivacky Print(T->getResultType(), S); 332199482Srdivacky} 333199482Srdivacky 334204962Srdivackystatic void PrintTypeSpec(const NamedDecl *D, std::string &S) { 335204962Srdivacky IdentifierInfo *II = D->getIdentifier(); 336200583Srdivacky if (S.empty()) 337200583Srdivacky S = II->getName().str(); 338200583Srdivacky else 339200583Srdivacky S = II->getName().str() + ' ' + S; 340200583Srdivacky} 341200583Srdivacky 342204962Srdivackyvoid TypePrinter::PrintUnresolvedUsing(const UnresolvedUsingType *T, 343204962Srdivacky std::string &S) { 344204962Srdivacky PrintTypeSpec(T->getDecl(), S); 345204962Srdivacky} 346204962Srdivacky 347199482Srdivackyvoid TypePrinter::PrintTypedef(const TypedefType *T, std::string &S) { 348204962Srdivacky PrintTypeSpec(T->getDecl(), S); 349199482Srdivacky} 350199482Srdivacky 351199482Srdivackyvoid TypePrinter::PrintTypeOfExpr(const TypeOfExprType *T, std::string &S) { 352199482Srdivacky if (!S.empty()) // Prefix the basic type, e.g. 'typeof(e) X'. 353199482Srdivacky S = ' ' + S; 354199482Srdivacky std::string Str; 355199482Srdivacky llvm::raw_string_ostream s(Str); 356199482Srdivacky T->getUnderlyingExpr()->printPretty(s, 0, Policy); 357199482Srdivacky S = "typeof " + s.str() + S; 358199482Srdivacky} 359199482Srdivacky 360199482Srdivackyvoid TypePrinter::PrintTypeOf(const TypeOfType *T, std::string &S) { 361199482Srdivacky if (!S.empty()) // Prefix the basic type, e.g. 'typeof(t) X'. 362199482Srdivacky S = ' ' + S; 363199482Srdivacky std::string Tmp; 364199482Srdivacky Print(T->getUnderlyingType(), Tmp); 365199482Srdivacky S = "typeof(" + Tmp + ")" + S; 366199482Srdivacky} 367199482Srdivacky 368199482Srdivackyvoid TypePrinter::PrintDecltype(const DecltypeType *T, std::string &S) { 369199482Srdivacky if (!S.empty()) // Prefix the basic type, e.g. 'decltype(t) X'. 370199482Srdivacky S = ' ' + S; 371199482Srdivacky std::string Str; 372199482Srdivacky llvm::raw_string_ostream s(Str); 373199482Srdivacky T->getUnderlyingExpr()->printPretty(s, 0, Policy); 374199482Srdivacky S = "decltype(" + s.str() + ")" + S; 375199482Srdivacky} 376199482Srdivacky 377204962Srdivacky/// Appends the given scope to the end of a string. 378204962Srdivackyvoid TypePrinter::AppendScope(DeclContext *DC, std::string &Buffer) { 379204962Srdivacky if (DC->isTranslationUnit()) return; 380204962Srdivacky AppendScope(DC->getParent(), Buffer); 381204962Srdivacky 382204962Srdivacky unsigned OldSize = Buffer.size(); 383204962Srdivacky 384204962Srdivacky if (NamespaceDecl *NS = dyn_cast<NamespaceDecl>(DC)) { 385204962Srdivacky if (NS->getIdentifier()) 386204962Srdivacky Buffer += NS->getNameAsString(); 387204962Srdivacky else 388204962Srdivacky Buffer += "<anonymous>"; 389204962Srdivacky } else if (ClassTemplateSpecializationDecl *Spec 390204962Srdivacky = dyn_cast<ClassTemplateSpecializationDecl>(DC)) { 391204962Srdivacky const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs(); 392204962Srdivacky std::string TemplateArgsStr 393204962Srdivacky = TemplateSpecializationType::PrintTemplateArgumentList( 394204962Srdivacky TemplateArgs.getFlatArgumentList(), 395204962Srdivacky TemplateArgs.flat_size(), 396204962Srdivacky Policy); 397204962Srdivacky Buffer += Spec->getIdentifier()->getName(); 398204962Srdivacky Buffer += TemplateArgsStr; 399204962Srdivacky } else if (TagDecl *Tag = dyn_cast<TagDecl>(DC)) { 400204962Srdivacky if (TypedefDecl *Typedef = Tag->getTypedefForAnonDecl()) 401204962Srdivacky Buffer += Typedef->getIdentifier()->getName(); 402204962Srdivacky else if (Tag->getIdentifier()) 403204962Srdivacky Buffer += Tag->getIdentifier()->getName(); 404204962Srdivacky } 405204962Srdivacky 406204962Srdivacky if (Buffer.size() != OldSize) 407204962Srdivacky Buffer += "::"; 408204962Srdivacky} 409204962Srdivacky 410204962Srdivackyvoid TypePrinter::PrintTag(TagDecl *D, std::string &InnerString) { 411199482Srdivacky if (Policy.SuppressTag) 412199482Srdivacky return; 413204962Srdivacky 414204962Srdivacky std::string Buffer; 415204962Srdivacky 416204962Srdivacky // We don't print tags unless this is an elaborated type. 417204962Srdivacky // In C, we just assume every RecordType is an elaborated type. 418204962Srdivacky if (!Policy.LangOpts.CPlusPlus && !D->getTypedefForAnonDecl()) { 419204962Srdivacky Buffer += D->getKindName(); 420204962Srdivacky Buffer += ' '; 421204962Srdivacky } 422204962Srdivacky 423204962Srdivacky if (!Policy.SuppressScope) 424204962Srdivacky // Compute the full nested-name-specifier for this type. In C, 425204962Srdivacky // this will always be empty. 426204962Srdivacky AppendScope(D->getDeclContext(), Buffer); 427204962Srdivacky 428199482Srdivacky const char *ID; 429204962Srdivacky if (const IdentifierInfo *II = D->getIdentifier()) 430199482Srdivacky ID = II->getNameStart(); 431204962Srdivacky else if (TypedefDecl *Typedef = D->getTypedefForAnonDecl()) { 432199482Srdivacky assert(Typedef->getIdentifier() && "Typedef without identifier?"); 433199482Srdivacky ID = Typedef->getIdentifier()->getNameStart(); 434199482Srdivacky } else 435199482Srdivacky ID = "<anonymous>"; 436204962Srdivacky Buffer += ID; 437204962Srdivacky 438199482Srdivacky // If this is a class template specialization, print the template 439199482Srdivacky // arguments. 440199482Srdivacky if (ClassTemplateSpecializationDecl *Spec 441204962Srdivacky = dyn_cast<ClassTemplateSpecializationDecl>(D)) { 442204962Srdivacky const TemplateArgument *Args; 443204962Srdivacky unsigned NumArgs; 444204962Srdivacky if (TypeSourceInfo *TAW = Spec->getTypeAsWritten()) { 445204962Srdivacky const TemplateSpecializationType *TST = 446204962Srdivacky cast<TemplateSpecializationType>(TAW->getType()); 447204962Srdivacky Args = TST->getArgs(); 448204962Srdivacky NumArgs = TST->getNumArgs(); 449204962Srdivacky } else { 450204962Srdivacky const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs(); 451204962Srdivacky Args = TemplateArgs.getFlatArgumentList(); 452204962Srdivacky NumArgs = TemplateArgs.flat_size(); 453204962Srdivacky } 454204962Srdivacky Buffer += TemplateSpecializationType::PrintTemplateArgumentList(Args, 455204962Srdivacky NumArgs, 456204962Srdivacky Policy); 457199482Srdivacky } 458204962Srdivacky 459204962Srdivacky if (!InnerString.empty()) { 460204962Srdivacky Buffer += ' '; 461204962Srdivacky Buffer += InnerString; 462204962Srdivacky } 463204962Srdivacky 464204962Srdivacky std::swap(Buffer, InnerString); 465199482Srdivacky} 466199482Srdivacky 467199482Srdivackyvoid TypePrinter::PrintRecord(const RecordType *T, std::string &S) { 468204962Srdivacky PrintTag(T->getDecl(), S); 469199482Srdivacky} 470199482Srdivacky 471199482Srdivackyvoid TypePrinter::PrintEnum(const EnumType *T, std::string &S) { 472204962Srdivacky PrintTag(T->getDecl(), S); 473199482Srdivacky} 474199482Srdivacky 475199482Srdivackyvoid TypePrinter::PrintElaborated(const ElaboratedType *T, std::string &S) { 476204962Srdivacky Print(T->getUnderlyingType(), S); 477199482Srdivacky S = std::string(T->getNameForTagKind(T->getTagKind())) + ' ' + S; 478199482Srdivacky} 479199482Srdivacky 480199482Srdivackyvoid TypePrinter::PrintTemplateTypeParm(const TemplateTypeParmType *T, 481199482Srdivacky std::string &S) { 482199482Srdivacky if (!S.empty()) // Prefix the basic type, e.g. 'parmname X'. 483199482Srdivacky S = ' ' + S; 484199482Srdivacky 485199482Srdivacky if (!T->getName()) 486199482Srdivacky S = "type-parameter-" + llvm::utostr_32(T->getDepth()) + '-' + 487199482Srdivacky llvm::utostr_32(T->getIndex()) + S; 488199482Srdivacky else 489199482Srdivacky S = T->getName()->getName().str() + S; 490199482Srdivacky} 491199482Srdivacky 492199482Srdivackyvoid TypePrinter::PrintSubstTemplateTypeParm(const SubstTemplateTypeParmType *T, 493199482Srdivacky std::string &S) { 494199482Srdivacky Print(T->getReplacementType(), S); 495199482Srdivacky} 496199482Srdivacky 497199482Srdivackyvoid TypePrinter::PrintTemplateSpecialization( 498199482Srdivacky const TemplateSpecializationType *T, 499199482Srdivacky std::string &S) { 500199482Srdivacky std::string SpecString; 501199482Srdivacky 502199482Srdivacky { 503199482Srdivacky llvm::raw_string_ostream OS(SpecString); 504199482Srdivacky T->getTemplateName().print(OS, Policy); 505199482Srdivacky } 506199482Srdivacky 507199482Srdivacky SpecString += TemplateSpecializationType::PrintTemplateArgumentList( 508199482Srdivacky T->getArgs(), 509199482Srdivacky T->getNumArgs(), 510199482Srdivacky Policy); 511199482Srdivacky if (S.empty()) 512199482Srdivacky S.swap(SpecString); 513199482Srdivacky else 514199482Srdivacky S = SpecString + ' ' + S; 515199482Srdivacky} 516199482Srdivacky 517204962Srdivackyvoid TypePrinter::PrintInjectedClassName(const InjectedClassNameType *T, 518204962Srdivacky std::string &S) { 519204962Srdivacky PrintTemplateSpecialization(T->getUnderlyingTST(), S); 520204962Srdivacky} 521204962Srdivacky 522199482Srdivackyvoid TypePrinter::PrintQualifiedName(const QualifiedNameType *T, 523199482Srdivacky std::string &S) { 524199482Srdivacky std::string MyString; 525199482Srdivacky 526199482Srdivacky { 527199482Srdivacky llvm::raw_string_ostream OS(MyString); 528199482Srdivacky T->getQualifier()->print(OS, Policy); 529199482Srdivacky } 530199482Srdivacky 531199482Srdivacky std::string TypeStr; 532199482Srdivacky PrintingPolicy InnerPolicy(Policy); 533199482Srdivacky InnerPolicy.SuppressScope = true; 534199482Srdivacky TypePrinter(InnerPolicy).Print(T->getNamedType(), TypeStr); 535199482Srdivacky 536199482Srdivacky MyString += TypeStr; 537199482Srdivacky if (S.empty()) 538199482Srdivacky S.swap(MyString); 539199482Srdivacky else 540199482Srdivacky S = MyString + ' ' + S; 541199482Srdivacky} 542199482Srdivacky 543199482Srdivackyvoid TypePrinter::PrintTypename(const TypenameType *T, std::string &S) { 544199482Srdivacky std::string MyString; 545199482Srdivacky 546199482Srdivacky { 547199482Srdivacky llvm::raw_string_ostream OS(MyString); 548199482Srdivacky OS << "typename "; 549199482Srdivacky T->getQualifier()->print(OS, Policy); 550199482Srdivacky 551199482Srdivacky if (const IdentifierInfo *Ident = T->getIdentifier()) 552199482Srdivacky OS << Ident->getName(); 553199482Srdivacky else if (const TemplateSpecializationType *Spec = T->getTemplateId()) { 554199482Srdivacky Spec->getTemplateName().print(OS, Policy, true); 555199482Srdivacky OS << TemplateSpecializationType::PrintTemplateArgumentList( 556199482Srdivacky Spec->getArgs(), 557199482Srdivacky Spec->getNumArgs(), 558199482Srdivacky Policy); 559199482Srdivacky } 560199482Srdivacky } 561199482Srdivacky 562199482Srdivacky if (S.empty()) 563199482Srdivacky S.swap(MyString); 564199482Srdivacky else 565199482Srdivacky S = MyString + ' ' + S; 566199482Srdivacky} 567199482Srdivacky 568199482Srdivackyvoid TypePrinter::PrintObjCInterface(const ObjCInterfaceType *T, 569199482Srdivacky std::string &S) { 570199482Srdivacky if (!S.empty()) // Prefix the basic type, e.g. 'typedefname X'. 571199482Srdivacky S = ' ' + S; 572199482Srdivacky 573199482Srdivacky std::string ObjCQIString = T->getDecl()->getNameAsString(); 574199482Srdivacky if (T->getNumProtocols()) { 575199482Srdivacky ObjCQIString += '<'; 576199482Srdivacky bool isFirst = true; 577199482Srdivacky for (ObjCInterfaceType::qual_iterator I = T->qual_begin(), 578199482Srdivacky E = T->qual_end(); 579199482Srdivacky I != E; ++I) { 580199482Srdivacky if (isFirst) 581199482Srdivacky isFirst = false; 582199482Srdivacky else 583199482Srdivacky ObjCQIString += ','; 584199482Srdivacky ObjCQIString += (*I)->getNameAsString(); 585199482Srdivacky } 586199482Srdivacky ObjCQIString += '>'; 587199482Srdivacky } 588199482Srdivacky S = ObjCQIString + S; 589199482Srdivacky} 590199482Srdivacky 591199482Srdivackyvoid TypePrinter::PrintObjCObjectPointer(const ObjCObjectPointerType *T, 592199482Srdivacky std::string &S) { 593199482Srdivacky std::string ObjCQIString; 594199482Srdivacky 595199482Srdivacky if (T->isObjCIdType() || T->isObjCQualifiedIdType()) 596199482Srdivacky ObjCQIString = "id"; 597199482Srdivacky else if (T->isObjCClassType() || T->isObjCQualifiedClassType()) 598199482Srdivacky ObjCQIString = "Class"; 599199990Srdivacky else if (T->isObjCSelType()) 600199990Srdivacky ObjCQIString = "SEL"; 601199482Srdivacky else 602199482Srdivacky ObjCQIString = T->getInterfaceDecl()->getNameAsString(); 603199482Srdivacky 604199482Srdivacky if (!T->qual_empty()) { 605199482Srdivacky ObjCQIString += '<'; 606199482Srdivacky for (ObjCObjectPointerType::qual_iterator I = T->qual_begin(), 607199482Srdivacky E = T->qual_end(); 608199482Srdivacky I != E; ++I) { 609199482Srdivacky ObjCQIString += (*I)->getNameAsString(); 610199482Srdivacky if (I+1 != E) 611199482Srdivacky ObjCQIString += ','; 612199482Srdivacky } 613199482Srdivacky ObjCQIString += '>'; 614199482Srdivacky } 615199482Srdivacky 616199482Srdivacky T->getPointeeType().getLocalQualifiers().getAsStringInternal(ObjCQIString, 617199482Srdivacky Policy); 618199482Srdivacky 619199482Srdivacky if (!T->isObjCIdType() && !T->isObjCQualifiedIdType()) 620199482Srdivacky ObjCQIString += " *"; // Don't forget the implicit pointer. 621199482Srdivacky else if (!S.empty()) // Prefix the basic type, e.g. 'typedefname X'. 622199482Srdivacky S = ' ' + S; 623199482Srdivacky 624199482Srdivacky S = ObjCQIString + S; 625199482Srdivacky} 626199482Srdivacky 627199482Srdivackystatic void PrintTemplateArgument(std::string &Buffer, 628199482Srdivacky const TemplateArgument &Arg, 629199482Srdivacky const PrintingPolicy &Policy) { 630199482Srdivacky switch (Arg.getKind()) { 631199482Srdivacky case TemplateArgument::Null: 632199482Srdivacky assert(false && "Null template argument"); 633199482Srdivacky break; 634199482Srdivacky 635199482Srdivacky case TemplateArgument::Type: 636199482Srdivacky Arg.getAsType().getAsStringInternal(Buffer, Policy); 637199482Srdivacky break; 638199482Srdivacky 639199482Srdivacky case TemplateArgument::Declaration: 640199482Srdivacky Buffer = cast<NamedDecl>(Arg.getAsDecl())->getNameAsString(); 641199482Srdivacky break; 642199482Srdivacky 643199482Srdivacky case TemplateArgument::Template: { 644199482Srdivacky llvm::raw_string_ostream s(Buffer); 645199482Srdivacky Arg.getAsTemplate().print(s, Policy); 646199482Srdivacky break; 647199482Srdivacky } 648199482Srdivacky 649199482Srdivacky case TemplateArgument::Integral: 650199482Srdivacky Buffer = Arg.getAsIntegral()->toString(10, true); 651199482Srdivacky break; 652199482Srdivacky 653199482Srdivacky case TemplateArgument::Expression: { 654199482Srdivacky llvm::raw_string_ostream s(Buffer); 655199482Srdivacky Arg.getAsExpr()->printPretty(s, 0, Policy); 656199482Srdivacky break; 657199482Srdivacky } 658199482Srdivacky 659199482Srdivacky case TemplateArgument::Pack: 660199482Srdivacky assert(0 && "FIXME: Implement!"); 661199482Srdivacky break; 662199482Srdivacky } 663199482Srdivacky} 664199482Srdivacky 665199990Srdivackystd::string TemplateSpecializationType:: 666199990Srdivacky PrintTemplateArgumentList(const TemplateArgumentListInfo &Args, 667199990Srdivacky const PrintingPolicy &Policy) { 668199990Srdivacky return PrintTemplateArgumentList(Args.getArgumentArray(), 669199990Srdivacky Args.size(), 670199990Srdivacky Policy); 671199990Srdivacky} 672199990Srdivacky 673199482Srdivackystd::string 674199482SrdivackyTemplateSpecializationType::PrintTemplateArgumentList( 675199482Srdivacky const TemplateArgument *Args, 676199482Srdivacky unsigned NumArgs, 677199482Srdivacky const PrintingPolicy &Policy) { 678199482Srdivacky std::string SpecString; 679199482Srdivacky SpecString += '<'; 680199482Srdivacky for (unsigned Arg = 0; Arg < NumArgs; ++Arg) { 681199482Srdivacky if (Arg) 682199482Srdivacky SpecString += ", "; 683199482Srdivacky 684199482Srdivacky // Print the argument into a string. 685199482Srdivacky std::string ArgString; 686199482Srdivacky PrintTemplateArgument(ArgString, Args[Arg], Policy); 687199482Srdivacky 688199482Srdivacky // If this is the first argument and its string representation 689199482Srdivacky // begins with the global scope specifier ('::foo'), add a space 690199482Srdivacky // to avoid printing the diagraph '<:'. 691199482Srdivacky if (!Arg && !ArgString.empty() && ArgString[0] == ':') 692199482Srdivacky SpecString += ' '; 693199482Srdivacky 694199482Srdivacky SpecString += ArgString; 695199482Srdivacky } 696199482Srdivacky 697199482Srdivacky // If the last character of our string is '>', add another space to 698199482Srdivacky // keep the two '>''s separate tokens. We don't *have* to do this in 699199482Srdivacky // C++0x, but it's still good hygiene. 700199482Srdivacky if (SpecString[SpecString.size() - 1] == '>') 701199482Srdivacky SpecString += ' '; 702199482Srdivacky 703199482Srdivacky SpecString += '>'; 704199482Srdivacky 705199482Srdivacky return SpecString; 706199482Srdivacky} 707199482Srdivacky 708199482Srdivacky// Sadly, repeat all that with TemplateArgLoc. 709199482Srdivackystd::string TemplateSpecializationType:: 710199482SrdivackyPrintTemplateArgumentList(const TemplateArgumentLoc *Args, unsigned NumArgs, 711199482Srdivacky const PrintingPolicy &Policy) { 712199482Srdivacky std::string SpecString; 713199482Srdivacky SpecString += '<'; 714199482Srdivacky for (unsigned Arg = 0; Arg < NumArgs; ++Arg) { 715199482Srdivacky if (Arg) 716199482Srdivacky SpecString += ", "; 717199482Srdivacky 718199482Srdivacky // Print the argument into a string. 719199482Srdivacky std::string ArgString; 720199482Srdivacky PrintTemplateArgument(ArgString, Args[Arg].getArgument(), Policy); 721199482Srdivacky 722199482Srdivacky // If this is the first argument and its string representation 723199482Srdivacky // begins with the global scope specifier ('::foo'), add a space 724199482Srdivacky // to avoid printing the diagraph '<:'. 725199482Srdivacky if (!Arg && !ArgString.empty() && ArgString[0] == ':') 726199482Srdivacky SpecString += ' '; 727199482Srdivacky 728199482Srdivacky SpecString += ArgString; 729199482Srdivacky } 730199482Srdivacky 731199482Srdivacky // If the last character of our string is '>', add another space to 732199482Srdivacky // keep the two '>''s separate tokens. We don't *have* to do this in 733199482Srdivacky // C++0x, but it's still good hygiene. 734199482Srdivacky if (SpecString[SpecString.size() - 1] == '>') 735199482Srdivacky SpecString += ' '; 736199482Srdivacky 737199482Srdivacky SpecString += '>'; 738199482Srdivacky 739199482Srdivacky return SpecString; 740199482Srdivacky} 741199482Srdivacky 742199482Srdivackyvoid QualType::dump(const char *msg) const { 743199482Srdivacky std::string R = "identifier"; 744199482Srdivacky LangOptions LO; 745199482Srdivacky getAsStringInternal(R, PrintingPolicy(LO)); 746199482Srdivacky if (msg) 747200583Srdivacky llvm::errs() << msg << ": "; 748200583Srdivacky llvm::errs() << R << "\n"; 749199482Srdivacky} 750199482Srdivackyvoid QualType::dump() const { 751199482Srdivacky dump(""); 752199482Srdivacky} 753199482Srdivacky 754199482Srdivackyvoid Type::dump() const { 755199482Srdivacky QualType(this, 0).dump(); 756199482Srdivacky} 757199482Srdivacky 758199482Srdivackystd::string Qualifiers::getAsString() const { 759199482Srdivacky LangOptions LO; 760199482Srdivacky return getAsString(PrintingPolicy(LO)); 761199482Srdivacky} 762199482Srdivacky 763199482Srdivacky// Appends qualifiers to the given string, separated by spaces. Will 764199482Srdivacky// prefix a space if the string is non-empty. Will not append a final 765199482Srdivacky// space. 766199482Srdivackyvoid Qualifiers::getAsStringInternal(std::string &S, 767199482Srdivacky const PrintingPolicy&) const { 768199482Srdivacky AppendTypeQualList(S, getCVRQualifiers()); 769199482Srdivacky if (unsigned AddressSpace = getAddressSpace()) { 770199482Srdivacky if (!S.empty()) S += ' '; 771199482Srdivacky S += "__attribute__((address_space("; 772199482Srdivacky S += llvm::utostr_32(AddressSpace); 773199482Srdivacky S += ")))"; 774199482Srdivacky } 775199482Srdivacky if (Qualifiers::GC GCAttrType = getObjCGCAttr()) { 776199482Srdivacky if (!S.empty()) S += ' '; 777199482Srdivacky S += "__attribute__((objc_gc("; 778199482Srdivacky if (GCAttrType == Qualifiers::Weak) 779199482Srdivacky S += "weak"; 780199482Srdivacky else 781199482Srdivacky S += "strong"; 782199482Srdivacky S += ")))"; 783199482Srdivacky } 784199482Srdivacky} 785199482Srdivacky 786199482Srdivackystd::string QualType::getAsString() const { 787199482Srdivacky std::string S; 788199482Srdivacky LangOptions LO; 789199482Srdivacky getAsStringInternal(S, PrintingPolicy(LO)); 790199482Srdivacky return S; 791199482Srdivacky} 792199482Srdivacky 793199482Srdivackyvoid QualType::getAsStringInternal(std::string &S, 794199482Srdivacky const PrintingPolicy &Policy) const { 795199482Srdivacky TypePrinter Printer(Policy); 796199482Srdivacky Printer.Print(*this, S); 797199482Srdivacky} 798199482Srdivacky 799