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