TypePrinter.cpp revision 13dcd00615de5c4279d97bdf63cd5f0a14fd9dcc
1de22d8f1eebd3245acccdb4098526ee1bf616c06Marek Olšák//===--- TypePrinter.cpp - Pretty-Print Clang Types -----------------------===//
2de22d8f1eebd3245acccdb4098526ee1bf616c06Marek Olšák//
3de22d8f1eebd3245acccdb4098526ee1bf616c06Marek Olšák//                     The LLVM Compiler Infrastructure
4de22d8f1eebd3245acccdb4098526ee1bf616c06Marek Olšák//
5de22d8f1eebd3245acccdb4098526ee1bf616c06Marek Olšák// This file is distributed under the University of Illinois Open Source
6de22d8f1eebd3245acccdb4098526ee1bf616c06Marek Olšák// License. See LICENSE.TXT for details.
7de22d8f1eebd3245acccdb4098526ee1bf616c06Marek Olšák//
8de22d8f1eebd3245acccdb4098526ee1bf616c06Marek Olšák//===----------------------------------------------------------------------===//
9de22d8f1eebd3245acccdb4098526ee1bf616c06Marek Olšák//
10de22d8f1eebd3245acccdb4098526ee1bf616c06Marek Olšák// This contains code to print types from Clang's type system.
11de22d8f1eebd3245acccdb4098526ee1bf616c06Marek Olšák//
12de22d8f1eebd3245acccdb4098526ee1bf616c06Marek Olšák//===----------------------------------------------------------------------===//
13de22d8f1eebd3245acccdb4098526ee1bf616c06Marek Olšák
14de22d8f1eebd3245acccdb4098526ee1bf616c06Marek Olšák#include "clang/AST/Decl.h"
15de22d8f1eebd3245acccdb4098526ee1bf616c06Marek Olšák#include "clang/AST/DeclObjC.h"
16de22d8f1eebd3245acccdb4098526ee1bf616c06Marek Olšák#include "clang/AST/DeclTemplate.h"
17de22d8f1eebd3245acccdb4098526ee1bf616c06Marek Olšák#include "clang/AST/Expr.h"
18de22d8f1eebd3245acccdb4098526ee1bf616c06Marek Olšák#include "clang/AST/Type.h"
19de22d8f1eebd3245acccdb4098526ee1bf616c06Marek Olšák#include "clang/AST/PrettyPrinter.h"
20de22d8f1eebd3245acccdb4098526ee1bf616c06Marek Olšák#include "clang/Basic/LangOptions.h"
21de22d8f1eebd3245acccdb4098526ee1bf616c06Marek Olšák#include "llvm/ADT/StringExtras.h"
22de22d8f1eebd3245acccdb4098526ee1bf616c06Marek Olšák#include "llvm/Support/raw_ostream.h"
23de22d8f1eebd3245acccdb4098526ee1bf616c06Marek Olšákusing namespace clang;
24de22d8f1eebd3245acccdb4098526ee1bf616c06Marek Olšák
25de22d8f1eebd3245acccdb4098526ee1bf616c06Marek Olšáknamespace {
26de22d8f1eebd3245acccdb4098526ee1bf616c06Marek Olšák  class TypePrinter {
276ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    PrintingPolicy Policy;
286ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák
296ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák  public:
306ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    explicit TypePrinter(const PrintingPolicy &Policy) : Policy(Policy) { }
316ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák
326ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    void Print(QualType T, std::string &S);
33bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse    void PrintTag(const TagType *T, std::string &S);
346ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák#define ABSTRACT_TYPE(CLASS, PARENT)
3570b1837dfb1b282ad9efcaeec4f9c8da5f9a74d8Chia-I Wu#define TYPE(CLASS, PARENT) \
366ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák  void Print##CLASS(const CLASS##Type *T, std::string &S);
376ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák#include "clang/AST/TypeNodes.def"
386ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák  };
396ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák}
406ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák
416ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšákstatic void AppendTypeQualList(std::string &S, unsigned TypeQuals) {
426ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák  if (TypeQuals & Qualifiers::Const) {
43bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse    if (!S.empty()) S += ' ';
44bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse    S += "const";
45bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse  }
46bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse  if (TypeQuals & Qualifiers::Volatile) {
47bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse    if (!S.empty()) S += ' ';
486ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    S += "volatile";
496ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák  }
506ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák  if (TypeQuals & Qualifiers::Restrict) {
516ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    if (!S.empty()) S += ' ';
521e3c81a068c4ae04cd1c6b18c687d5be69b7b8c4Marek Olšák    S += "restrict";
53bbc320a94def6178028a4c46012c737839e1cf61Jerome Glisse  }
541e3c81a068c4ae04cd1c6b18c687d5be69b7b8c4Marek Olšák}
55bbc320a94def6178028a4c46012c737839e1cf61Jerome Glisse
56bbc320a94def6178028a4c46012c737839e1cf61Jerome Glissevoid TypePrinter::Print(QualType T, std::string &S) {
57bbc320a94def6178028a4c46012c737839e1cf61Jerome Glisse  if (T.isNull()) {
581e3c81a068c4ae04cd1c6b18c687d5be69b7b8c4Marek Olšák    S += "NULL TYPE";
591e3c81a068c4ae04cd1c6b18c687d5be69b7b8c4Marek Olšák    return;
60bbc320a94def6178028a4c46012c737839e1cf61Jerome Glisse  }
61bbc320a94def6178028a4c46012c737839e1cf61Jerome Glisse
621e3c81a068c4ae04cd1c6b18c687d5be69b7b8c4Marek Olšák  if (Policy.SuppressSpecifiers && T->isSpecifierType())
631e3c81a068c4ae04cd1c6b18c687d5be69b7b8c4Marek Olšák    return;
641e3c81a068c4ae04cd1c6b18c687d5be69b7b8c4Marek Olšák
651e3c81a068c4ae04cd1c6b18c687d5be69b7b8c4Marek Olšák  // Print qualifiers as appropriate.
66bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse  Qualifiers Quals = T.getLocalQualifiers();
67bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse  if (!Quals.empty()) {
68bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse    std::string TQS;
69bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse    Quals.getAsStringInternal(TQS, Policy);
70bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse
71bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse    if (!S.empty()) {
72bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse      TQS += ' ';
73bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse      TQS += S;
74bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse    }
75bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse    std::swap(S, TQS);
76bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse  }
77bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse
78bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse  switch (T->getTypeClass()) {
79bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse#define ABSTRACT_TYPE(CLASS, PARENT)
80bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse#define TYPE(CLASS, PARENT) case Type::CLASS:                \
81bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse    Print##CLASS(cast<CLASS##Type>(T.getTypePtr()), S);      \
82bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse    break;
83bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse#include "clang/AST/TypeNodes.def"
84bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse  }
85bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse}
86bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse
87bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glissevoid TypePrinter::PrintBuiltin(const BuiltinType *T, std::string &S) {
88bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse  if (S.empty()) {
89bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse    S = T->getName(Policy.LangOpts);
90bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse  } else {
91bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse    // Prefix the basic type, e.g. 'int X'.
92bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse    S = ' ' + S;
931e3c81a068c4ae04cd1c6b18c687d5be69b7b8c4Marek Olšák    S = T->getName(Policy.LangOpts) + S;
946ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák  }
956ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák}
966ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák
976ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšákvoid TypePrinter::PrintFixedWidthInt(const FixedWidthIntType *T,
986ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák                                     std::string &S) {
996ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák  // FIXME: Once we get bitwidth attribute, write as
1006ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák  // "int __attribute__((bitwidth(x)))".
1016ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák  std::string prefix = "__clang_fixedwidth";
1026ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák  prefix += llvm::utostr_32(T->getWidth());
103bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse  prefix += (char)(T->isSigned() ? 'S' : 'U');
104bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse  if (S.empty()) {
105bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse    S = prefix;
106bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse  } else {
107bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse    // Prefix the basic type, e.g. 'int X'.
108bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse    S = prefix + S;
1096ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák  }
1106ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák}
1116ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák
1126ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšákvoid TypePrinter::PrintComplex(const ComplexType *T, std::string &S) {
1136ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák  Print(T->getElementType(), S);
1146ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák  S = "_Complex " + S;
1156ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák}
1166ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák
1176ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšákvoid TypePrinter::PrintPointer(const PointerType *T, std::string &S) {
1186ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák  S = '*' + S;
119bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse
120bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse  // Handle things like 'int (*A)[4];' correctly.
121bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse  // FIXME: this should include vectors, but vectors use attributes I guess.
122bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse  if (isa<ArrayType>(T->getPointeeType()))
123bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse    S = '(' + S + ')';
124bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse
1256ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák  Print(T->getPointeeType(), S);
1266ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák}
1276ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák
1286ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšákvoid TypePrinter::PrintBlockPointer(const BlockPointerType *T, std::string &S) {
1296ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák  S = '^' + S;
1306ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák  Print(T->getPointeeType(), S);
1316ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák}
1326ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák
1336ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšákvoid TypePrinter::PrintLValueReference(const LValueReferenceType *T,
1346ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák                                       std::string &S) {
1356ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák  S = '&' + S;
1366ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák
1376ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák  // Handle things like 'int (&A)[4];' correctly.
1386ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák  // FIXME: this should include vectors, but vectors use attributes I guess.
139bbc320a94def6178028a4c46012c737839e1cf61Jerome Glisse  if (isa<ArrayType>(T->getPointeeTypeAsWritten()))
140bbc320a94def6178028a4c46012c737839e1cf61Jerome Glisse    S = '(' + S + ')';
141bbc320a94def6178028a4c46012c737839e1cf61Jerome Glisse
1426ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák  Print(T->getPointeeTypeAsWritten(), S);
1436ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák}
1446ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák
1456ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšákvoid TypePrinter::PrintRValueReference(const RValueReferenceType *T,
1466ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák                                       std::string &S) {
1476ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák  S = "&&" + S;
1486ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák
1496ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák  // Handle things like 'int (&&A)[4];' correctly.
1501e3c81a068c4ae04cd1c6b18c687d5be69b7b8c4Marek Olšák  // FIXME: this should include vectors, but vectors use attributes I guess.
1516ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák  if (isa<ArrayType>(T->getPointeeTypeAsWritten()))
1522664980760c5cf2e7dde4065f9cc8e8b865627c3Marek Olšák    S = '(' + S + ')';
1536ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák
154b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšák  Print(T->getPointeeTypeAsWritten(), S);
155b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšák}
156b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšák
157b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšákvoid TypePrinter::PrintMemberPointer(const MemberPointerType *T,
158ef64da8f013691c66744064769db379e57ef95deMarek Olšák                                     std::string &S) {
159ef64da8f013691c66744064769db379e57ef95deMarek Olšák  std::string C;
1601e3c81a068c4ae04cd1c6b18c687d5be69b7b8c4Marek Olšák  Print(QualType(T->getClass(), 0), C);
1611e3c81a068c4ae04cd1c6b18c687d5be69b7b8c4Marek Olšák  C += "::*";
1621e3c81a068c4ae04cd1c6b18c687d5be69b7b8c4Marek Olšák  S = C + S;
1631e3c81a068c4ae04cd1c6b18c687d5be69b7b8c4Marek Olšák
1641e3c81a068c4ae04cd1c6b18c687d5be69b7b8c4Marek Olšák  // Handle things like 'int (Cls::*A)[4];' correctly.
165ef64da8f013691c66744064769db379e57ef95deMarek Olšák  // FIXME: this should include vectors, but vectors use attributes I guess.
1663da5196263fb2ae60483044cbd34c94270e2accdBrian Paul  if (isa<ArrayType>(T->getPointeeType()))
1673da5196263fb2ae60483044cbd34c94270e2accdBrian Paul    S = '(' + S + ')';
1681e3c81a068c4ae04cd1c6b18c687d5be69b7b8c4Marek Olšák
1691e3c81a068c4ae04cd1c6b18c687d5be69b7b8c4Marek Olšák  Print(T->getPointeeType(), S);
1701e3c81a068c4ae04cd1c6b18c687d5be69b7b8c4Marek Olšák}
1711e3c81a068c4ae04cd1c6b18c687d5be69b7b8c4Marek Olšák
1726ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšákvoid TypePrinter::PrintConstantArray(const ConstantArrayType *T,
1736ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák                                     std::string &S) {
1741e3c81a068c4ae04cd1c6b18c687d5be69b7b8c4Marek Olšák  S += '[';
1751e3c81a068c4ae04cd1c6b18c687d5be69b7b8c4Marek Olšák  S += llvm::utostr(T->getSize().getZExtValue());
1766ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák  S += ']';
1772664980760c5cf2e7dde4065f9cc8e8b865627c3Marek Olšák
1786ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák  Print(T->getElementType(), S);
179b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšák}
180b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšák
181b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšákvoid TypePrinter::PrintIncompleteArray(const IncompleteArrayType *T,
182b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšák                                       std::string &S) {
183ef64da8f013691c66744064769db379e57ef95deMarek Olšák  S += "[]";
184ef64da8f013691c66744064769db379e57ef95deMarek Olšák  Print(T->getElementType(), S);
1851e3c81a068c4ae04cd1c6b18c687d5be69b7b8c4Marek Olšák}
1861e3c81a068c4ae04cd1c6b18c687d5be69b7b8c4Marek Olšák
1871e3c81a068c4ae04cd1c6b18c687d5be69b7b8c4Marek Olšákvoid TypePrinter::PrintVariableArray(const VariableArrayType *T,
1881e3c81a068c4ae04cd1c6b18c687d5be69b7b8c4Marek Olšák                                     std::string &S) {
1891e3c81a068c4ae04cd1c6b18c687d5be69b7b8c4Marek Olšák  S += '[';
190ef64da8f013691c66744064769db379e57ef95deMarek Olšák
1913da5196263fb2ae60483044cbd34c94270e2accdBrian Paul  if (T->getIndexTypeQualifiers().hasQualifiers()) {
1923da5196263fb2ae60483044cbd34c94270e2accdBrian Paul    AppendTypeQualList(S, T->getIndexTypeCVRQualifiers());
1931e3c81a068c4ae04cd1c6b18c687d5be69b7b8c4Marek Olšák    S += ' ';
1941e3c81a068c4ae04cd1c6b18c687d5be69b7b8c4Marek Olšák  }
1951e3c81a068c4ae04cd1c6b18c687d5be69b7b8c4Marek Olšák
1961e3c81a068c4ae04cd1c6b18c687d5be69b7b8c4Marek Olšák  if (T->getSizeModifier() == VariableArrayType::Static)
1976ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    S += "static";
1986ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák  else if (T->getSizeModifier() == VariableArrayType::Star)
199356eb0aadbb977b0732da077ad31cd66d1b53e23Jerome Glisse    S += '*';
200bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse
201bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse  if (T->getSizeExpr()) {
202356eb0aadbb977b0732da077ad31cd66d1b53e23Jerome Glisse    std::string SStr;
203bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse    llvm::raw_string_ostream s(SStr);
204bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse    T->getSizeExpr()->printPretty(s, 0, Policy);
205bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse    S += s.str();
206bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse  }
207356eb0aadbb977b0732da077ad31cd66d1b53e23Jerome Glisse  S += ']';
208356eb0aadbb977b0732da077ad31cd66d1b53e23Jerome Glisse
209356eb0aadbb977b0732da077ad31cd66d1b53e23Jerome Glisse  Print(T->getElementType(), S);
210356eb0aadbb977b0732da077ad31cd66d1b53e23Jerome Glisse}
211356eb0aadbb977b0732da077ad31cd66d1b53e23Jerome Glisse
212356eb0aadbb977b0732da077ad31cd66d1b53e23Jerome Glissevoid TypePrinter::PrintDependentSizedArray(const DependentSizedArrayType *T,
213356eb0aadbb977b0732da077ad31cd66d1b53e23Jerome Glisse                                           std::string &S) {
214e372e53ee0ed57072322003e508b3ca4c58076beJerome Glisse  S += '[';
215e372e53ee0ed57072322003e508b3ca4c58076beJerome Glisse
216e372e53ee0ed57072322003e508b3ca4c58076beJerome Glisse  if (T->getSizeExpr()) {
217356eb0aadbb977b0732da077ad31cd66d1b53e23Jerome Glisse    std::string SStr;
218bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse    llvm::raw_string_ostream s(SStr);
219bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse    T->getSizeExpr()->printPretty(s, 0, Policy);
220bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse    S += s.str();
221bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse  }
222bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse  S += ']';
223bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse
224356eb0aadbb977b0732da077ad31cd66d1b53e23Jerome Glisse  Print(T->getElementType(), S);
225356eb0aadbb977b0732da077ad31cd66d1b53e23Jerome Glisse}
226356eb0aadbb977b0732da077ad31cd66d1b53e23Jerome Glisse
227356eb0aadbb977b0732da077ad31cd66d1b53e23Jerome Glissevoid TypePrinter::PrintDependentSizedExtVector(
228356eb0aadbb977b0732da077ad31cd66d1b53e23Jerome Glisse                                          const DependentSizedExtVectorType *T,
229356eb0aadbb977b0732da077ad31cd66d1b53e23Jerome Glisse                                               std::string &S) {
230356eb0aadbb977b0732da077ad31cd66d1b53e23Jerome Glisse  Print(T->getElementType(), S);
231356eb0aadbb977b0732da077ad31cd66d1b53e23Jerome Glisse
232356eb0aadbb977b0732da077ad31cd66d1b53e23Jerome Glisse  S += " __attribute__((ext_vector_type(";
233bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse  if (T->getSizeExpr()) {
234bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse    std::string SStr;
235bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse    llvm::raw_string_ostream s(SStr);
236bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse    T->getSizeExpr()->printPretty(s, 0, Policy);
237bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse    S += s.str();
238bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse  }
239356eb0aadbb977b0732da077ad31cd66d1b53e23Jerome Glisse  S += ")))";
240356eb0aadbb977b0732da077ad31cd66d1b53e23Jerome Glisse}
241356eb0aadbb977b0732da077ad31cd66d1b53e23Jerome Glisse
242356eb0aadbb977b0732da077ad31cd66d1b53e23Jerome Glissevoid TypePrinter::PrintVector(const VectorType *T, std::string &S) {
243356eb0aadbb977b0732da077ad31cd66d1b53e23Jerome Glisse  // FIXME: We prefer to print the size directly here, but have no way
244356eb0aadbb977b0732da077ad31cd66d1b53e23Jerome Glisse  // to get the size of the type.
245356eb0aadbb977b0732da077ad31cd66d1b53e23Jerome Glisse  S += " __attribute__((__vector_size__(";
246bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse  S += llvm::utostr_32(T->getNumElements()); // convert back to bytes.
247bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse  std::string ET;
248bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse  Print(T->getElementType(), ET);
249bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse  S += " * sizeof(" + ET + "))))";
250bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse  Print(T->getElementType(), S);
251bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse}
252bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse
253bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glissevoid TypePrinter::PrintExtVector(const ExtVectorType *T, std::string &S) {
254bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse  S += " __attribute__((ext_vector_type(";
255bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse  S += llvm::utostr_32(T->getNumElements());
256bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse  S += ")))";
257bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse  Print(T->getElementType(), S);
258bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse}
259bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse
260bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glissevoid TypePrinter::PrintFunctionProto(const FunctionProtoType *T,
261bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse                                     std::string &S) {
262bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse  // If needed for precedence reasons, wrap the inner part in grouping parens.
263bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse  if (!S.empty())
264bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse    S = "(" + S + ")";
265bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse
266bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse  S += "(";
267bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse  std::string Tmp;
268bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse  PrintingPolicy ParamPolicy(Policy);
269bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse  ParamPolicy.SuppressSpecifiers = false;
270bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse  for (unsigned i = 0, e = T->getNumArgs(); i != e; ++i) {
271bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse    if (i) S += ", ";
272bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse    Print(T->getArgType(i), Tmp);
273bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse    S += Tmp;
274bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse    Tmp.clear();
275bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse  }
276bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse
277bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse  if (T->isVariadic()) {
278bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse    if (T->getNumArgs())
279bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse      S += ", ";
280bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse    S += "...";
281bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse  } else if (T->getNumArgs() == 0 && !Policy.LangOpts.CPlusPlus) {
282bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse    // Do not emit int() if we have a proto, emit 'int(void)'.
283bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse    S += "void";
284bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse  }
285bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse
286bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse  S += ")";
287bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse  if (T->getNoReturnAttr())
288bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse    S += " __attribute__((noreturn))";
289bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse  Print(T->getResultType(), S);
290bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse
291bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse}
292bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse
293bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glissevoid TypePrinter::PrintFunctionNoProto(const FunctionNoProtoType *T,
294bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse                                       std::string &S) {
295bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse  // If needed for precedence reasons, wrap the inner part in grouping parens.
296bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse  if (!S.empty())
297bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse    S = "(" + S + ")";
298bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse
299bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse  S += "()";
300bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse  if (T->getNoReturnAttr())
301bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse    S += " __attribute__((noreturn))";
302bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse  Print(T->getResultType(), S);
303bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse}
3046ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák
3056ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšákvoid TypePrinter::PrintTypedef(const TypedefType *T, std::string &S) {
3066ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák  if (!S.empty())    // Prefix the basic type, e.g. 'typedefname X'.
307bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse    S = ' ' + S;
3083da5196263fb2ae60483044cbd34c94270e2accdBrian Paul  S = T->getDecl()->getIdentifier()->getName().str() + S;
3093da5196263fb2ae60483044cbd34c94270e2accdBrian Paul}
3103da5196263fb2ae60483044cbd34c94270e2accdBrian Paul
311c35572352e3e92683988ee8d151b47f4190d62f9Marek Olšákvoid TypePrinter::PrintTypeOfExpr(const TypeOfExprType *T, std::string &S) {
312c35572352e3e92683988ee8d151b47f4190d62f9Marek Olšák  if (!S.empty())    // Prefix the basic type, e.g. 'typeof(e) X'.
313c35572352e3e92683988ee8d151b47f4190d62f9Marek Olšák    S = ' ' + S;
314c35572352e3e92683988ee8d151b47f4190d62f9Marek Olšák  std::string Str;
315bbc320a94def6178028a4c46012c737839e1cf61Jerome Glisse  llvm::raw_string_ostream s(Str);
316c35572352e3e92683988ee8d151b47f4190d62f9Marek Olšák  T->getUnderlyingExpr()->printPretty(s, 0, Policy);
317c35572352e3e92683988ee8d151b47f4190d62f9Marek Olšák  S = "typeof " + s.str() + S;
3186ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák}
319c35572352e3e92683988ee8d151b47f4190d62f9Marek Olšák
320a3cd2c6c9b3724dbc3aa565dab98968c46bde963Marek Olšákvoid TypePrinter::PrintTypeOf(const TypeOfType *T, std::string &S) {
321c35572352e3e92683988ee8d151b47f4190d62f9Marek Olšák  if (!S.empty())    // Prefix the basic type, e.g. 'typeof(t) X'.
322bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse    S = ' ' + S;
323bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse  std::string Tmp;
324bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse  Print(T->getUnderlyingType(), Tmp);
325bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse  S = "typeof(" + Tmp + ")" + S;
326c35572352e3e92683988ee8d151b47f4190d62f9Marek Olšák}
327c35572352e3e92683988ee8d151b47f4190d62f9Marek Olšák
328c35572352e3e92683988ee8d151b47f4190d62f9Marek Olšákvoid TypePrinter::PrintDecltype(const DecltypeType *T, std::string &S) {
329c35572352e3e92683988ee8d151b47f4190d62f9Marek Olšák  if (!S.empty())    // Prefix the basic type, e.g. 'decltype(t) X'.
330c35572352e3e92683988ee8d151b47f4190d62f9Marek Olšák    S = ' ' + S;
3316ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák  std::string Str;
3326ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák  llvm::raw_string_ostream s(Str);
3330a6120244e66494db070ce875c0a464fbc5b15a1Marek Olšák  T->getUnderlyingExpr()->printPretty(s, 0, Policy);
3340a6120244e66494db070ce875c0a464fbc5b15a1Marek Olšák  S = "decltype(" + s.str() + ")" + S;
3350a6120244e66494db070ce875c0a464fbc5b15a1Marek Olšák}
3366ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák
3370a6120244e66494db070ce875c0a464fbc5b15a1Marek Olšákvoid TypePrinter::PrintTag(const TagType *T, std::string &InnerString) {
3380a6120244e66494db070ce875c0a464fbc5b15a1Marek Olšák  if (Policy.SuppressTag)
3390a6120244e66494db070ce875c0a464fbc5b15a1Marek Olšák    return;
3408decb0a96de0accfc8361890cbcf9db89f8fe8baMarek Olšák
3416ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák  if (!InnerString.empty())    // Prefix the basic type, e.g. 'typedefname X'.
3426ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    InnerString = ' ' + InnerString;
3430a6120244e66494db070ce875c0a464fbc5b15a1Marek Olšák
34445e1cd522bd26a5aa3d424ea49975b90feef8450Marek Olšák  const char *Kind = Policy.SuppressTagKind? 0 : T->getDecl()->getKindName();
3450a6120244e66494db070ce875c0a464fbc5b15a1Marek Olšák  const char *ID;
3460a6120244e66494db070ce875c0a464fbc5b15a1Marek Olšák  if (const IdentifierInfo *II = T->getDecl()->getIdentifier())
347ebfcc58b93cc08c534857c2314694e35b29690aeMarek Olšák    ID = II->getNameStart();
348ebfcc58b93cc08c534857c2314694e35b29690aeMarek Olšák  else if (TypedefDecl *Typedef = T->getDecl()->getTypedefForAnonDecl()) {
349ebfcc58b93cc08c534857c2314694e35b29690aeMarek Olšák    Kind = 0;
350ebfcc58b93cc08c534857c2314694e35b29690aeMarek Olšák    assert(Typedef->getIdentifier() && "Typedef without identifier?");
351ebfcc58b93cc08c534857c2314694e35b29690aeMarek Olšák    ID = Typedef->getIdentifier()->getNameStart();
352ebfcc58b93cc08c534857c2314694e35b29690aeMarek Olšák  } else
353ebfcc58b93cc08c534857c2314694e35b29690aeMarek Olšák    ID = "<anonymous>";
354ebfcc58b93cc08c534857c2314694e35b29690aeMarek Olšák
355ebfcc58b93cc08c534857c2314694e35b29690aeMarek Olšák  // If this is a class template specialization, print the template
356ebfcc58b93cc08c534857c2314694e35b29690aeMarek Olšák  // arguments.
357ebfcc58b93cc08c534857c2314694e35b29690aeMarek Olšák  if (ClassTemplateSpecializationDecl *Spec
35845e1cd522bd26a5aa3d424ea49975b90feef8450Marek Olšák      = dyn_cast<ClassTemplateSpecializationDecl>(T->getDecl())) {
359ebfcc58b93cc08c534857c2314694e35b29690aeMarek Olšák    const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs();
360ebfcc58b93cc08c534857c2314694e35b29690aeMarek Olšák    std::string TemplateArgsStr
361ebfcc58b93cc08c534857c2314694e35b29690aeMarek Olšák      = TemplateSpecializationType::PrintTemplateArgumentList(
362ebfcc58b93cc08c534857c2314694e35b29690aeMarek Olšák                                            TemplateArgs.getFlatArgumentList(),
363ebfcc58b93cc08c534857c2314694e35b29690aeMarek Olšák                                            TemplateArgs.flat_size(),
364ebfcc58b93cc08c534857c2314694e35b29690aeMarek Olšák                                            Policy);
365ebfcc58b93cc08c534857c2314694e35b29690aeMarek Olšák    InnerString = TemplateArgsStr + InnerString;
366ebfcc58b93cc08c534857c2314694e35b29690aeMarek Olšák  }
367ebfcc58b93cc08c534857c2314694e35b29690aeMarek Olšák
368ebfcc58b93cc08c534857c2314694e35b29690aeMarek Olšák  if (!Policy.SuppressScope) {
369ebfcc58b93cc08c534857c2314694e35b29690aeMarek Olšák    // Compute the full nested-name-specifier for this type. In C,
370ebfcc58b93cc08c534857c2314694e35b29690aeMarek Olšák    // this will always be empty.
371ebfcc58b93cc08c534857c2314694e35b29690aeMarek Olšák    std::string ContextStr;
372ebfcc58b93cc08c534857c2314694e35b29690aeMarek Olšák    for (DeclContext *DC = T->getDecl()->getDeclContext();
37345e1cd522bd26a5aa3d424ea49975b90feef8450Marek Olšák         !DC->isTranslationUnit(); DC = DC->getParent()) {
37445e1cd522bd26a5aa3d424ea49975b90feef8450Marek Olšák      std::string MyPart;
3750a6120244e66494db070ce875c0a464fbc5b15a1Marek Olšák      if (NamespaceDecl *NS = dyn_cast<NamespaceDecl>(DC)) {
3766caac3ecb8bc32d92c35fdb1f0a67541ffa8af29Marek Olšák        if (NS->getIdentifier())
3776caac3ecb8bc32d92c35fdb1f0a67541ffa8af29Marek Olšák          MyPart = NS->getNameAsString();
3786caac3ecb8bc32d92c35fdb1f0a67541ffa8af29Marek Olšák      } else if (ClassTemplateSpecializationDecl *Spec
3796caac3ecb8bc32d92c35fdb1f0a67541ffa8af29Marek Olšák                  = dyn_cast<ClassTemplateSpecializationDecl>(DC)) {
3806caac3ecb8bc32d92c35fdb1f0a67541ffa8af29Marek Olšák        const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs();
3816caac3ecb8bc32d92c35fdb1f0a67541ffa8af29Marek Olšák        std::string TemplateArgsStr
3826caac3ecb8bc32d92c35fdb1f0a67541ffa8af29Marek Olšák          = TemplateSpecializationType::PrintTemplateArgumentList(
3836caac3ecb8bc32d92c35fdb1f0a67541ffa8af29Marek Olšák                                            TemplateArgs.getFlatArgumentList(),
3846caac3ecb8bc32d92c35fdb1f0a67541ffa8af29Marek Olšák                                            TemplateArgs.flat_size(),
3851554e69e00566bc7255b82f5ea93b1f02f1a5bb3Marek Olšák                                            Policy);
386ebfcc58b93cc08c534857c2314694e35b29690aeMarek Olšák        MyPart = Spec->getIdentifier()->getName().str() + TemplateArgsStr;
387ebfcc58b93cc08c534857c2314694e35b29690aeMarek Olšák      } else if (TagDecl *Tag = dyn_cast<TagDecl>(DC)) {
3885650a719f0c69c00954e47bd7a7b3e9433cb551dMarek Olšák        if (TypedefDecl *Typedef = Tag->getTypedefForAnonDecl())
3896caac3ecb8bc32d92c35fdb1f0a67541ffa8af29Marek Olšák          MyPart = Typedef->getIdentifier()->getName();
3906caac3ecb8bc32d92c35fdb1f0a67541ffa8af29Marek Olšák        else if (Tag->getIdentifier())
3916caac3ecb8bc32d92c35fdb1f0a67541ffa8af29Marek Olšák          MyPart = Tag->getIdentifier()->getName();
3926caac3ecb8bc32d92c35fdb1f0a67541ffa8af29Marek Olšák      }
3936caac3ecb8bc32d92c35fdb1f0a67541ffa8af29Marek Olšák
3946caac3ecb8bc32d92c35fdb1f0a67541ffa8af29Marek Olšák      if (!MyPart.empty())
3956caac3ecb8bc32d92c35fdb1f0a67541ffa8af29Marek Olšák        ContextStr = MyPart + "::" + ContextStr;
3966caac3ecb8bc32d92c35fdb1f0a67541ffa8af29Marek Olšák    }
3976caac3ecb8bc32d92c35fdb1f0a67541ffa8af29Marek Olšák
3981e3c81a068c4ae04cd1c6b18c687d5be69b7b8c4Marek Olšák    if (Kind)
39945e1cd522bd26a5aa3d424ea49975b90feef8450Marek Olšák      InnerString = std::string(Kind) + ' ' + ContextStr + ID + InnerString;
4006ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    else
4016ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák      InnerString = ContextStr + ID + InnerString;
4026ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák  } else
4038decb0a96de0accfc8361890cbcf9db89f8fe8baMarek Olšák    InnerString = ID + InnerString;
4048decb0a96de0accfc8361890cbcf9db89f8fe8baMarek Olšák}
4058decb0a96de0accfc8361890cbcf9db89f8fe8baMarek Olšák
4068decb0a96de0accfc8361890cbcf9db89f8fe8baMarek Olšákvoid TypePrinter::PrintRecord(const RecordType *T, std::string &S) {
4078decb0a96de0accfc8361890cbcf9db89f8fe8baMarek Olšák  PrintTag(T, S);
4088decb0a96de0accfc8361890cbcf9db89f8fe8baMarek Olšák}
409652bf121f2124ec92b74f6e3e40e6aefcc1c50dcMarek Olšák
410652bf121f2124ec92b74f6e3e40e6aefcc1c50dcMarek Olšákvoid TypePrinter::PrintEnum(const EnumType *T, std::string &S) {
411652bf121f2124ec92b74f6e3e40e6aefcc1c50dcMarek Olšák  PrintTag(T, S);
412652bf121f2124ec92b74f6e3e40e6aefcc1c50dcMarek Olšák}
413652bf121f2124ec92b74f6e3e40e6aefcc1c50dcMarek Olšák
4148decb0a96de0accfc8361890cbcf9db89f8fe8baMarek Olšákvoid TypePrinter::PrintElaborated(const ElaboratedType *T, std::string &S) {
4158decb0a96de0accfc8361890cbcf9db89f8fe8baMarek Olšák  std::string TypeStr;
416a3cd2c6c9b3724dbc3aa565dab98968c46bde963Marek Olšák  PrintingPolicy InnerPolicy(Policy);
4178decb0a96de0accfc8361890cbcf9db89f8fe8baMarek Olšák  InnerPolicy.SuppressTagKind = true;
4188decb0a96de0accfc8361890cbcf9db89f8fe8baMarek Olšák  TypePrinter(InnerPolicy).Print(T->getUnderlyingType(), S);
4198decb0a96de0accfc8361890cbcf9db89f8fe8baMarek Olšák
4208decb0a96de0accfc8361890cbcf9db89f8fe8baMarek Olšák  S = std::string(T->getNameForTagKind(T->getTagKind())) + ' ' + S;
4218decb0a96de0accfc8361890cbcf9db89f8fe8baMarek Olšák}
4228decb0a96de0accfc8361890cbcf9db89f8fe8baMarek Olšák
4238decb0a96de0accfc8361890cbcf9db89f8fe8baMarek Olšákvoid TypePrinter::PrintTemplateTypeParm(const TemplateTypeParmType *T,
4248decb0a96de0accfc8361890cbcf9db89f8fe8baMarek Olšák                                        std::string &S) {
4258decb0a96de0accfc8361890cbcf9db89f8fe8baMarek Olšák  if (!S.empty())    // Prefix the basic type, e.g. 'parmname X'.
4268decb0a96de0accfc8361890cbcf9db89f8fe8baMarek Olšák    S = ' ' + S;
42770b1837dfb1b282ad9efcaeec4f9c8da5f9a74d8Chia-I Wu
4288decb0a96de0accfc8361890cbcf9db89f8fe8baMarek Olšák  if (!T->getName())
4298decb0a96de0accfc8361890cbcf9db89f8fe8baMarek Olšák    S = "type-parameter-" + llvm::utostr_32(T->getDepth()) + '-' +
4308decb0a96de0accfc8361890cbcf9db89f8fe8baMarek Olšák        llvm::utostr_32(T->getIndex()) + S;
4318decb0a96de0accfc8361890cbcf9db89f8fe8baMarek Olšák  else
4328decb0a96de0accfc8361890cbcf9db89f8fe8baMarek Olšák    S = T->getName()->getName().str() + S;
4336ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák}
4348decb0a96de0accfc8361890cbcf9db89f8fe8baMarek Olšák
4358decb0a96de0accfc8361890cbcf9db89f8fe8baMarek Olšákvoid TypePrinter::PrintSubstTemplateTypeParm(const SubstTemplateTypeParmType *T,
4366ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák                                             std::string &S) {
4376ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák  Print(T->getReplacementType(), S);
4386ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák}
4396ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák
4400a6120244e66494db070ce875c0a464fbc5b15a1Marek Olšákvoid TypePrinter::PrintTemplateSpecialization(
4416ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák                                            const TemplateSpecializationType *T,
4426ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák                                              std::string &S) {
4436ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák  std::string SpecString;
4446ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák
4456ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák  {
446bbc320a94def6178028a4c46012c737839e1cf61Jerome Glisse    llvm::raw_string_ostream OS(SpecString);
447bbc320a94def6178028a4c46012c737839e1cf61Jerome Glisse    T->getTemplateName().print(OS, Policy);
4486ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák  }
4496ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák
4506ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák  SpecString += TemplateSpecializationType::PrintTemplateArgumentList(
4516ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák                                                                  T->getArgs(),
4526ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák                                                                T->getNumArgs(),
4536ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák                                                                      Policy);
454bbc320a94def6178028a4c46012c737839e1cf61Jerome Glisse  if (S.empty())
455bbc320a94def6178028a4c46012c737839e1cf61Jerome Glisse    S.swap(SpecString);
4566ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák  else
4576ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    S = SpecString + ' ' + S;
4586ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák}
4596ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák
4606ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšákvoid TypePrinter::PrintQualifiedName(const QualifiedNameType *T,
4616ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák                                     std::string &S) {
4626ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák  std::string MyString;
4636ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák
4646ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák  {
4656ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    llvm::raw_string_ostream OS(MyString);
4666ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    T->getQualifier()->print(OS, Policy);
4676ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák  }
4680a6120244e66494db070ce875c0a464fbc5b15a1Marek Olšák
4690a6120244e66494db070ce875c0a464fbc5b15a1Marek Olšák  std::string TypeStr;
4706ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák  PrintingPolicy InnerPolicy(Policy);
4716ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák  InnerPolicy.SuppressTagKind = true;
4726ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák  InnerPolicy.SuppressScope = true;
4736ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák  TypePrinter(InnerPolicy).Print(T->getNamedType(), TypeStr);
4746ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák
4756ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák  MyString += TypeStr;
476bbc320a94def6178028a4c46012c737839e1cf61Jerome Glisse  if (S.empty())
477bbc320a94def6178028a4c46012c737839e1cf61Jerome Glisse    S.swap(MyString);
4786ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák  else
4796ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    S = MyString + ' ' + S;
4806ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák}
4816ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák
4823da5196263fb2ae60483044cbd34c94270e2accdBrian Paulvoid TypePrinter::PrintTypename(const TypenameType *T, std::string &S) {
483bfa51dfeac67a7e3383614374c86bdfb5751997aMarek Olšák  std::string MyString;
484bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse
4856ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák  {
4863da5196263fb2ae60483044cbd34c94270e2accdBrian Paul    llvm::raw_string_ostream OS(MyString);
4873da5196263fb2ae60483044cbd34c94270e2accdBrian Paul    OS << "typename ";
48893f4e3cb6c1ca303ee1f5c2a2491a8eff33f2633Marek Olšák    T->getQualifier()->print(OS, Policy);
489363ff844753c46ac9c13866627e096b091ea81f8Marek Olšák
490363ff844753c46ac9c13866627e096b091ea81f8Marek Olšák    if (const IdentifierInfo *Ident = T->getIdentifier())
491363ff844753c46ac9c13866627e096b091ea81f8Marek Olšák      OS << Ident->getName();
4926ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    else if (const TemplateSpecializationType *Spec = T->getTemplateId()) {
4936ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák      Spec->getTemplateName().print(OS, Policy, true);
494bfa51dfeac67a7e3383614374c86bdfb5751997aMarek Olšák      OS << TemplateSpecializationType::PrintTemplateArgumentList(
4956ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák                                                            Spec->getArgs(),
4966ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák                                                            Spec->getNumArgs(),
4976ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák                                                            Policy);
4989d5de0fcb6ced7a4da85a09ad25dcbc2b21bfdf9Marek Olšák    }
4999d5de0fcb6ced7a4da85a09ad25dcbc2b21bfdf9Marek Olšák  }
5009d5de0fcb6ced7a4da85a09ad25dcbc2b21bfdf9Marek Olšák
5019d5de0fcb6ced7a4da85a09ad25dcbc2b21bfdf9Marek Olšák  if (S.empty())
5026ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    S.swap(MyString);
5036ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák  else
5046ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    S = MyString + ' ' + S;
5056ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák}
5066ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák
507bbc320a94def6178028a4c46012c737839e1cf61Jerome Glissevoid TypePrinter::PrintObjCInterface(const ObjCInterfaceType *T,
5086ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák                                     std::string &S) {
5094682e706012fe26627a2f827db01b5068cc62814Marek Olšák  if (!S.empty())    // Prefix the basic type, e.g. 'typedefname X'.
5104682e706012fe26627a2f827db01b5068cc62814Marek Olšák    S = ' ' + S;
5114682e706012fe26627a2f827db01b5068cc62814Marek Olšák
5124682e706012fe26627a2f827db01b5068cc62814Marek Olšák  std::string ObjCQIString = T->getDecl()->getNameAsString();
5136ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák  if (T->getNumProtocols()) {
5146ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    ObjCQIString += '<';
515df54b53b7d12a3bca5867b6649cb308feb36f0daMarek Olšák    bool isFirst = true;
5166ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    for (ObjCInterfaceType::qual_iterator I = T->qual_begin(),
517bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse                                          E = T->qual_end();
5188decb0a96de0accfc8361890cbcf9db89f8fe8baMarek Olšák         I != E; ++I) {
5196ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák      if (isFirst)
520bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse        isFirst = false;
521bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse      else
522bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse        ObjCQIString += ',';
523bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse      ObjCQIString += (*I)->getNameAsString();
524356eb0aadbb977b0732da077ad31cd66d1b53e23Jerome Glisse    }
525bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse    ObjCQIString += '>';
526bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse  }
527bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse  S = ObjCQIString + S;
528bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse}
529bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse
530bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glissevoid TypePrinter::PrintObjCObjectPointer(const ObjCObjectPointerType *T,
531bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse                                         std::string &S) {
532bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse  std::string ObjCQIString;
533bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse
534bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse  if (T->isObjCIdType() || T->isObjCQualifiedIdType())
535bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse    ObjCQIString = "id";
536bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse  else if (T->isObjCClassType() || T->isObjCQualifiedClassType())
537bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse    ObjCQIString = "Class";
538bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse  else if (T->isObjCSelType())
539bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse    ObjCQIString = "SEL";
540bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse  else
541bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse    ObjCQIString = T->getInterfaceDecl()->getNameAsString();
542bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse
543bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse  if (!T->qual_empty()) {
544bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse    ObjCQIString += '<';
545bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse    for (ObjCObjectPointerType::qual_iterator I = T->qual_begin(),
546bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse                                              E = T->qual_end();
547bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse         I != E; ++I) {
548bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse      ObjCQIString += (*I)->getNameAsString();
5496ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák      if (I+1 != E)
5506ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák        ObjCQIString += ',';
5516ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    }
5526ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    ObjCQIString += '>';
5536ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák  }
5546ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák
5556ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák  T->getPointeeType().getLocalQualifiers().getAsStringInternal(ObjCQIString,
5566ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák                                                               Policy);
557a87730ff3f83253465fbe9a1e9e9b1ea92cb79b9Marek Olšák
558a87730ff3f83253465fbe9a1e9e9b1ea92cb79b9Marek Olšák  if (!T->isObjCIdType() && !T->isObjCQualifiedIdType())
559a87730ff3f83253465fbe9a1e9e9b1ea92cb79b9Marek Olšák    ObjCQIString += " *"; // Don't forget the implicit pointer.
560a87730ff3f83253465fbe9a1e9e9b1ea92cb79b9Marek Olšák  else if (!S.empty()) // Prefix the basic type, e.g. 'typedefname X'.
561a87730ff3f83253465fbe9a1e9e9b1ea92cb79b9Marek Olšák    S = ' ' + S;
562a87730ff3f83253465fbe9a1e9e9b1ea92cb79b9Marek Olšák
563a87730ff3f83253465fbe9a1e9e9b1ea92cb79b9Marek Olšák  S = ObjCQIString + S;
564333d3daf472485b247101932d95ccb798cb55f7bMarek Olšák}
565a87730ff3f83253465fbe9a1e9e9b1ea92cb79b9Marek Olšák
566a87730ff3f83253465fbe9a1e9e9b1ea92cb79b9Marek Olšákstatic void PrintTemplateArgument(std::string &Buffer,
5671e3c81a068c4ae04cd1c6b18c687d5be69b7b8c4Marek Olšák                                  const TemplateArgument &Arg,
568333d3daf472485b247101932d95ccb798cb55f7bMarek Olšák                                  const PrintingPolicy &Policy) {
569a87730ff3f83253465fbe9a1e9e9b1ea92cb79b9Marek Olšák  switch (Arg.getKind()) {
570a87730ff3f83253465fbe9a1e9e9b1ea92cb79b9Marek Olšák    case TemplateArgument::Null:
571333d3daf472485b247101932d95ccb798cb55f7bMarek Olšák      assert(false && "Null template argument");
572a87730ff3f83253465fbe9a1e9e9b1ea92cb79b9Marek Olšák      break;
573a87730ff3f83253465fbe9a1e9e9b1ea92cb79b9Marek Olšák
5746ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    case TemplateArgument::Type:
5756ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák      Arg.getAsType().getAsStringInternal(Buffer, Policy);
5766ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák      break;
5776ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák
5786ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    case TemplateArgument::Declaration:
579bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse      Buffer = cast<NamedDecl>(Arg.getAsDecl())->getNameAsString();
5806ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák      break;
5816ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák
5826ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    case TemplateArgument::Template: {
5838ab1fcc66a58ca87fb19fea2b0e14e62562decccMarek Olšák      llvm::raw_string_ostream s(Buffer);
584685c3262b945a7f0e9f1f3a9409a12fdda08c828Marek Olšák      Arg.getAsTemplate().print(s, Policy);
5856ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák      break;
5866ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    }
587685c3262b945a7f0e9f1f3a9409a12fdda08c828Marek Olšák
5886ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    case TemplateArgument::Integral:
5896ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák      Buffer = Arg.getAsIntegral()->toString(10, true);
5906ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák      break;
5916ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák
5928ab1fcc66a58ca87fb19fea2b0e14e62562decccMarek Olšák    case TemplateArgument::Expression: {
5936ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák      llvm::raw_string_ostream s(Buffer);
5946ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák      Arg.getAsExpr()->printPretty(s, 0, Policy);
5956ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák      break;
5966ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    }
5976ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák
5986ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    case TemplateArgument::Pack:
5996ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák      assert(0 && "FIXME: Implement!");
6006ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák      break;
601bbc320a94def6178028a4c46012c737839e1cf61Jerome Glisse  }
6026ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák}
6036ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák
6046ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšákstd::string
6056ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek OlšákTemplateSpecializationType::PrintTemplateArgumentList(
606a87730ff3f83253465fbe9a1e9e9b1ea92cb79b9Marek Olšák                                                const TemplateArgument *Args,
6076ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák                                                unsigned NumArgs,
6086ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák                                                const PrintingPolicy &Policy) {
6096ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák  std::string SpecString;
6106ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák  SpecString += '<';
611bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse  for (unsigned Arg = 0; Arg < NumArgs; ++Arg) {
612bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse    if (Arg)
613bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse      SpecString += ", ";
614bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse
615bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse    // Print the argument into a string.
616bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse    std::string ArgString;
6176ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    PrintTemplateArgument(ArgString, Args[Arg], Policy);
6186ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák
6196ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    // If this is the first argument and its string representation
620c0c979eebc076b95cc8d18a013ce2968fe6311adJerome Glisse    // begins with the global scope specifier ('::foo'), add a space
621c0c979eebc076b95cc8d18a013ce2968fe6311adJerome Glisse    // to avoid printing the diagraph '<:'.
622c0c979eebc076b95cc8d18a013ce2968fe6311adJerome Glisse    if (!Arg && !ArgString.empty() && ArgString[0] == ':')
623c0c979eebc076b95cc8d18a013ce2968fe6311adJerome Glisse      SpecString += ' ';
624c0c979eebc076b95cc8d18a013ce2968fe6311adJerome Glisse
625c0c979eebc076b95cc8d18a013ce2968fe6311adJerome Glisse    SpecString += ArgString;
626c0c979eebc076b95cc8d18a013ce2968fe6311adJerome Glisse  }
627c0c979eebc076b95cc8d18a013ce2968fe6311adJerome Glisse
628c0c979eebc076b95cc8d18a013ce2968fe6311adJerome Glisse  // If the last character of our string is '>', add another space to
629c0c979eebc076b95cc8d18a013ce2968fe6311adJerome Glisse  // keep the two '>''s separate tokens. We don't *have* to do this in
630c0c979eebc076b95cc8d18a013ce2968fe6311adJerome Glisse  // C++0x, but it's still good hygiene.
631c0c979eebc076b95cc8d18a013ce2968fe6311adJerome Glisse  if (SpecString[SpecString.size() - 1] == '>')
632c0c979eebc076b95cc8d18a013ce2968fe6311adJerome Glisse    SpecString += ' ';
633c0c979eebc076b95cc8d18a013ce2968fe6311adJerome Glisse
634c0c979eebc076b95cc8d18a013ce2968fe6311adJerome Glisse  SpecString += '>';
63511f056a3f0b87e86267efa8b5ac9d36a343c9dc1Michel Dänzer
63611f056a3f0b87e86267efa8b5ac9d36a343c9dc1Michel Dänzer  return SpecString;
63711f056a3f0b87e86267efa8b5ac9d36a343c9dc1Michel Dänzer}
63811f056a3f0b87e86267efa8b5ac9d36a343c9dc1Michel Dänzer
63911f056a3f0b87e86267efa8b5ac9d36a343c9dc1Michel Dänzer// Sadly, repeat all that with TemplateArgLoc.
64011f056a3f0b87e86267efa8b5ac9d36a343c9dc1Michel Dänzerstd::string TemplateSpecializationType::
64111f056a3f0b87e86267efa8b5ac9d36a343c9dc1Michel DänzerPrintTemplateArgumentList(const TemplateArgumentLoc *Args, unsigned NumArgs,
64211f056a3f0b87e86267efa8b5ac9d36a343c9dc1Michel Dänzer                          const PrintingPolicy &Policy) {
64311f056a3f0b87e86267efa8b5ac9d36a343c9dc1Michel Dänzer  std::string SpecString;
64411f056a3f0b87e86267efa8b5ac9d36a343c9dc1Michel Dänzer  SpecString += '<';
64511f056a3f0b87e86267efa8b5ac9d36a343c9dc1Michel Dänzer  for (unsigned Arg = 0; Arg < NumArgs; ++Arg) {
64611f056a3f0b87e86267efa8b5ac9d36a343c9dc1Michel Dänzer    if (Arg)
64711f056a3f0b87e86267efa8b5ac9d36a343c9dc1Michel Dänzer      SpecString += ", ";
64811f056a3f0b87e86267efa8b5ac9d36a343c9dc1Michel Dänzer
649d35aeff4bb0b03450b2c3c08bd7f84db5bf43283Marek Olšák    // Print the argument into a string.
650d35aeff4bb0b03450b2c3c08bd7f84db5bf43283Marek Olšák    std::string ArgString;
651c0c979eebc076b95cc8d18a013ce2968fe6311adJerome Glisse    PrintTemplateArgument(ArgString, Args[Arg].getArgument(), Policy);
652c0c979eebc076b95cc8d18a013ce2968fe6311adJerome Glisse
653c0c979eebc076b95cc8d18a013ce2968fe6311adJerome Glisse    // If this is the first argument and its string representation
654c0c979eebc076b95cc8d18a013ce2968fe6311adJerome Glisse    // begins with the global scope specifier ('::foo'), add a space
655c0c979eebc076b95cc8d18a013ce2968fe6311adJerome Glisse    // to avoid printing the diagraph '<:'.
6566ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    if (!Arg && !ArgString.empty() && ArgString[0] == ':')
6572664980760c5cf2e7dde4065f9cc8e8b865627c3Marek Olšák      SpecString += ' ';
6583da5196263fb2ae60483044cbd34c94270e2accdBrian Paul
6593da5196263fb2ae60483044cbd34c94270e2accdBrian Paul    SpecString += ArgString;
6603da5196263fb2ae60483044cbd34c94270e2accdBrian Paul  }
6616ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák
6626ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák  // If the last character of our string is '>', add another space to
6636ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák  // keep the two '>''s separate tokens. We don't *have* to do this in
664df54b53b7d12a3bca5867b6649cb308feb36f0daMarek Olšák  // C++0x, but it's still good hygiene.
6656ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák  if (SpecString[SpecString.size() - 1] == '>')
6666ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    SpecString += ' ';
6676ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák
6686ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák  SpecString += '>';
669d35aeff4bb0b03450b2c3c08bd7f84db5bf43283Marek Olšák
670d35aeff4bb0b03450b2c3c08bd7f84db5bf43283Marek Olšák  return SpecString;
6716ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák}
672bbc320a94def6178028a4c46012c737839e1cf61Jerome Glisse
6736ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšákvoid QualType::dump(const char *msg) const {
6746ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák  std::string R = "identifier";
675bbc320a94def6178028a4c46012c737839e1cf61Jerome Glisse  LangOptions LO;
676c0c979eebc076b95cc8d18a013ce2968fe6311adJerome Glisse  getAsStringInternal(R, PrintingPolicy(LO));
677c0c979eebc076b95cc8d18a013ce2968fe6311adJerome Glisse  if (msg)
678c0c979eebc076b95cc8d18a013ce2968fe6311adJerome Glisse    fprintf(stderr, "%s: %s\n", msg, R.c_str());
679c0c979eebc076b95cc8d18a013ce2968fe6311adJerome Glisse  else
680c0c979eebc076b95cc8d18a013ce2968fe6311adJerome Glisse    fprintf(stderr, "%s\n", R.c_str());
681c0c979eebc076b95cc8d18a013ce2968fe6311adJerome Glisse}
682c0c979eebc076b95cc8d18a013ce2968fe6311adJerome Glissevoid QualType::dump() const {
683c0c979eebc076b95cc8d18a013ce2968fe6311adJerome Glisse  dump("");
6846ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák}
6856ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák
686d35aeff4bb0b03450b2c3c08bd7f84db5bf43283Marek Olšákvoid Type::dump() const {
687d35aeff4bb0b03450b2c3c08bd7f84db5bf43283Marek Olšák  QualType(this, 0).dump();
688d35aeff4bb0b03450b2c3c08bd7f84db5bf43283Marek Olšák}
68911f056a3f0b87e86267efa8b5ac9d36a343c9dc1Michel Dänzer
69011f056a3f0b87e86267efa8b5ac9d36a343c9dc1Michel Dänzerstd::string Qualifiers::getAsString() const {
69111f056a3f0b87e86267efa8b5ac9d36a343c9dc1Michel Dänzer  LangOptions LO;
69211f056a3f0b87e86267efa8b5ac9d36a343c9dc1Michel Dänzer  return getAsString(PrintingPolicy(LO));
6936ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák}
6946ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák
6952664980760c5cf2e7dde4065f9cc8e8b865627c3Marek Olšák// Appends qualifiers to the given string, separated by spaces.  Will
6963da5196263fb2ae60483044cbd34c94270e2accdBrian Paul// prefix a space if the string is non-empty.  Will not append a final
6973da5196263fb2ae60483044cbd34c94270e2accdBrian Paul// space.
6983da5196263fb2ae60483044cbd34c94270e2accdBrian Paulvoid Qualifiers::getAsStringInternal(std::string &S,
6996ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák                                     const PrintingPolicy&) const {
700fa3f1348e49feeac511dbe5b22bbddc47f56ba81Marek Olšák  AppendTypeQualList(S, getCVRQualifiers());
701fa3f1348e49feeac511dbe5b22bbddc47f56ba81Marek Olšák  if (unsigned AddressSpace = getAddressSpace()) {
702fa3f1348e49feeac511dbe5b22bbddc47f56ba81Marek Olšák    if (!S.empty()) S += ' ';
703fa3f1348e49feeac511dbe5b22bbddc47f56ba81Marek Olšák    S += "__attribute__((address_space(";
704d35aeff4bb0b03450b2c3c08bd7f84db5bf43283Marek Olšák    S += llvm::utostr_32(AddressSpace);
7056ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    S += ")))";
706d35aeff4bb0b03450b2c3c08bd7f84db5bf43283Marek Olšák  }
7076ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák  if (Qualifiers::GC GCAttrType = getObjCGCAttr()) {
7086ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    if (!S.empty()) S += ' ';
709d35aeff4bb0b03450b2c3c08bd7f84db5bf43283Marek Olšák    S += "__attribute__((objc_gc(";
7106ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    if (GCAttrType == Qualifiers::Weak)
7116ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák      S += "weak";
71211f056a3f0b87e86267efa8b5ac9d36a343c9dc1Michel Dänzer    else
71311f056a3f0b87e86267efa8b5ac9d36a343c9dc1Michel Dänzer      S += "strong";
71411f056a3f0b87e86267efa8b5ac9d36a343c9dc1Michel Dänzer    S += ")))";
71511f056a3f0b87e86267efa8b5ac9d36a343c9dc1Michel Dänzer  }
71611f056a3f0b87e86267efa8b5ac9d36a343c9dc1Michel Dänzer}
71711f056a3f0b87e86267efa8b5ac9d36a343c9dc1Michel Dänzer
71811f056a3f0b87e86267efa8b5ac9d36a343c9dc1Michel Dänzerstd::string QualType::getAsString() const {
71911f056a3f0b87e86267efa8b5ac9d36a343c9dc1Michel Dänzer  std::string S;
72011f056a3f0b87e86267efa8b5ac9d36a343c9dc1Michel Dänzer  LangOptions LO;
72111f056a3f0b87e86267efa8b5ac9d36a343c9dc1Michel Dänzer  getAsStringInternal(S, PrintingPolicy(LO));
72211f056a3f0b87e86267efa8b5ac9d36a343c9dc1Michel Dänzer  return S;
72311f056a3f0b87e86267efa8b5ac9d36a343c9dc1Michel Dänzer}
72411f056a3f0b87e86267efa8b5ac9d36a343c9dc1Michel Dänzer
7256ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšákvoid QualType::getAsStringInternal(std::string &S,
7266ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák                                   const PrintingPolicy &Policy) const {
7276ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák  TypePrinter Printer(Policy);
728df54b53b7d12a3bca5867b6649cb308feb36f0daMarek Olšák  Printer.Print(*this, S);
7296ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák}
7306ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák
7316ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák