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