blob: d0267caabda7f8185be88283bbd096eadf6590c4 [file] [log] [blame]
Douglas Gregorfee8a3c2009-11-10 00:39:07 +00001//===--- TypePrinter.cpp - Pretty-Print Clang Types -----------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This contains code to print types from Clang's type system.
11//
12//===----------------------------------------------------------------------===//
13
14#include "clang/AST/Decl.h"
15#include "clang/AST/DeclObjC.h"
16#include "clang/AST/DeclTemplate.h"
17#include "clang/AST/Expr.h"
18#include "clang/AST/Type.h"
19#include "clang/AST/PrettyPrinter.h"
20#include "clang/Basic/LangOptions.h"
John McCall73061d02010-03-19 07:56:44 +000021#include "clang/Basic/SourceManager.h"
Douglas Gregorfee8a3c2009-11-10 00:39:07 +000022#include "llvm/ADT/StringExtras.h"
23#include "llvm/Support/raw_ostream.h"
24using namespace clang;
25
26namespace {
27 class TypePrinter {
28 PrintingPolicy Policy;
29
30 public:
31 explicit TypePrinter(const PrintingPolicy &Policy) : Policy(Policy) { }
Abramo Bagnara493ec512010-04-27 21:08:25 +000032
John McCall49f4e1c2010-12-10 11:01:00 +000033 void print(const Type *ty, Qualifiers qs, std::string &buffer);
34 void print(QualType T, std::string &S);
John McCall7c2342d2010-03-10 11:27:22 +000035 void AppendScope(DeclContext *DC, std::string &S);
John McCall49f4e1c2010-12-10 11:01:00 +000036 void printTag(TagDecl *T, std::string &S);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +000037#define ABSTRACT_TYPE(CLASS, PARENT)
38#define TYPE(CLASS, PARENT) \
Douglas Gregor7536dd52010-12-20 02:24:11 +000039 void print##CLASS(const CLASS##Type *T, std::string &S);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +000040#include "clang/AST/TypeNodes.def"
41 };
42}
43
44static void AppendTypeQualList(std::string &S, unsigned TypeQuals) {
45 if (TypeQuals & Qualifiers::Const) {
46 if (!S.empty()) S += ' ';
47 S += "const";
48 }
49 if (TypeQuals & Qualifiers::Volatile) {
50 if (!S.empty()) S += ' ';
51 S += "volatile";
52 }
53 if (TypeQuals & Qualifiers::Restrict) {
54 if (!S.empty()) S += ' ';
55 S += "restrict";
56 }
57}
58
John McCall49f4e1c2010-12-10 11:01:00 +000059void TypePrinter::print(QualType t, std::string &buffer) {
60 SplitQualType split = t.split();
61 print(split.first, split.second, buffer);
62}
63
64void TypePrinter::print(const Type *T, Qualifiers Quals, std::string &buffer) {
65 if (!T) {
66 buffer += "NULL TYPE";
Douglas Gregorfee8a3c2009-11-10 00:39:07 +000067 return;
68 }
69
70 if (Policy.SuppressSpecifiers && T->isSpecifierType())
71 return;
72
73 // Print qualifiers as appropriate.
Chris Lattner58f9e132010-09-05 00:04:01 +000074
75 // CanPrefixQualifiers - We prefer to print type qualifiers before the type,
76 // so that we get "const int" instead of "int const", but we can't do this if
77 // the type is complex. For example if the type is "int*", we *must* print
78 // "int * const", printing "const int *" is different. Only do this when the
79 // type expands to a simple string.
Douglas Gregorc6daf0b2011-02-17 06:52:25 +000080 bool CanPrefixQualifiers = false;
81
82 Type::TypeClass TC = T->getTypeClass();
Richard Smith34b41d92011-02-20 03:19:35 +000083 if (const AutoType *AT = dyn_cast<AutoType>(T))
84 TC = AT->desugar()->getTypeClass();
Douglas Gregorc6daf0b2011-02-17 06:52:25 +000085 if (const SubstTemplateTypeParmType *Subst
86 = dyn_cast<SubstTemplateTypeParmType>(T))
87 TC = Subst->getReplacementType()->getTypeClass();
88
89 switch (TC) {
90 case Type::Builtin:
91 case Type::Complex:
92 case Type::UnresolvedUsing:
93 case Type::Typedef:
94 case Type::TypeOfExpr:
95 case Type::TypeOf:
96 case Type::Decltype:
97 case Type::Record:
98 case Type::Enum:
99 case Type::Elaborated:
100 case Type::TemplateTypeParm:
101 case Type::SubstTemplateTypeParmPack:
102 case Type::TemplateSpecialization:
103 case Type::InjectedClassName:
104 case Type::DependentName:
105 case Type::DependentTemplateSpecialization:
106 case Type::ObjCObject:
107 case Type::ObjCInterface:
108 CanPrefixQualifiers = true;
109 break;
110
111 case Type::ObjCObjectPointer:
112 CanPrefixQualifiers = T->isObjCIdType() || T->isObjCClassType() ||
113 T->isObjCQualifiedIdType() || T->isObjCQualifiedClassType();
114 break;
115
116 case Type::Pointer:
117 case Type::BlockPointer:
118 case Type::LValueReference:
119 case Type::RValueReference:
120 case Type::MemberPointer:
121 case Type::ConstantArray:
122 case Type::IncompleteArray:
123 case Type::VariableArray:
124 case Type::DependentSizedArray:
125 case Type::DependentSizedExtVector:
126 case Type::Vector:
127 case Type::ExtVector:
128 case Type::FunctionProto:
129 case Type::FunctionNoProto:
130 case Type::Paren:
131 case Type::Attributed:
132 case Type::PackExpansion:
133 case Type::SubstTemplateTypeParm:
Richard Smith34b41d92011-02-20 03:19:35 +0000134 case Type::Auto:
Douglas Gregorc6daf0b2011-02-17 06:52:25 +0000135 CanPrefixQualifiers = false;
136 break;
137 }
Chris Lattner58f9e132010-09-05 00:04:01 +0000138
139 if (!CanPrefixQualifiers && !Quals.empty()) {
John McCall49f4e1c2010-12-10 11:01:00 +0000140 std::string qualsBuffer;
141 Quals.getAsStringInternal(qualsBuffer, Policy);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000142
John McCall49f4e1c2010-12-10 11:01:00 +0000143 if (!buffer.empty()) {
144 qualsBuffer += ' ';
145 qualsBuffer += buffer;
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000146 }
John McCall49f4e1c2010-12-10 11:01:00 +0000147 std::swap(buffer, qualsBuffer);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000148 }
149
150 switch (T->getTypeClass()) {
151#define ABSTRACT_TYPE(CLASS, PARENT)
John McCall49f4e1c2010-12-10 11:01:00 +0000152#define TYPE(CLASS, PARENT) case Type::CLASS: \
153 print##CLASS(cast<CLASS##Type>(T), buffer); \
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000154 break;
155#include "clang/AST/TypeNodes.def"
156 }
Chris Lattner58f9e132010-09-05 00:04:01 +0000157
158 // If we're adding the qualifiers as a prefix, do it now.
159 if (CanPrefixQualifiers && !Quals.empty()) {
John McCall49f4e1c2010-12-10 11:01:00 +0000160 std::string qualsBuffer;
161 Quals.getAsStringInternal(qualsBuffer, Policy);
Chris Lattner58f9e132010-09-05 00:04:01 +0000162
John McCall49f4e1c2010-12-10 11:01:00 +0000163 if (!buffer.empty()) {
164 qualsBuffer += ' ';
165 qualsBuffer += buffer;
Chris Lattner58f9e132010-09-05 00:04:01 +0000166 }
John McCall49f4e1c2010-12-10 11:01:00 +0000167 std::swap(buffer, qualsBuffer);
Chris Lattner58f9e132010-09-05 00:04:01 +0000168 }
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000169}
170
John McCall49f4e1c2010-12-10 11:01:00 +0000171void TypePrinter::printBuiltin(const BuiltinType *T, std::string &S) {
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000172 if (S.empty()) {
173 S = T->getName(Policy.LangOpts);
174 } else {
175 // Prefix the basic type, e.g. 'int X'.
Chris Lattner59742de2010-09-04 23:43:40 +0000176 S = ' ' + S;
177 S = T->getName(Policy.LangOpts) + S;
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000178 }
179}
180
John McCall49f4e1c2010-12-10 11:01:00 +0000181void TypePrinter::printComplex(const ComplexType *T, std::string &S) {
182 print(T->getElementType(), S);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000183 S = "_Complex " + S;
184}
185
John McCall49f4e1c2010-12-10 11:01:00 +0000186void TypePrinter::printPointer(const PointerType *T, std::string &S) {
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000187 S = '*' + S;
188
189 // Handle things like 'int (*A)[4];' correctly.
190 // FIXME: this should include vectors, but vectors use attributes I guess.
191 if (isa<ArrayType>(T->getPointeeType()))
192 S = '(' + S + ')';
193
John McCall49f4e1c2010-12-10 11:01:00 +0000194 print(T->getPointeeType(), S);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000195}
196
John McCall49f4e1c2010-12-10 11:01:00 +0000197void TypePrinter::printBlockPointer(const BlockPointerType *T, std::string &S) {
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000198 S = '^' + S;
John McCall49f4e1c2010-12-10 11:01:00 +0000199 print(T->getPointeeType(), S);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000200}
201
John McCall49f4e1c2010-12-10 11:01:00 +0000202void TypePrinter::printLValueReference(const LValueReferenceType *T,
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000203 std::string &S) {
204 S = '&' + S;
205
206 // Handle things like 'int (&A)[4];' correctly.
207 // FIXME: this should include vectors, but vectors use attributes I guess.
208 if (isa<ArrayType>(T->getPointeeTypeAsWritten()))
209 S = '(' + S + ')';
210
John McCall49f4e1c2010-12-10 11:01:00 +0000211 print(T->getPointeeTypeAsWritten(), S);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000212}
213
John McCall49f4e1c2010-12-10 11:01:00 +0000214void TypePrinter::printRValueReference(const RValueReferenceType *T,
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000215 std::string &S) {
216 S = "&&" + S;
217
218 // Handle things like 'int (&&A)[4];' correctly.
219 // FIXME: this should include vectors, but vectors use attributes I guess.
220 if (isa<ArrayType>(T->getPointeeTypeAsWritten()))
221 S = '(' + S + ')';
222
John McCall49f4e1c2010-12-10 11:01:00 +0000223 print(T->getPointeeTypeAsWritten(), S);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000224}
225
John McCall49f4e1c2010-12-10 11:01:00 +0000226void TypePrinter::printMemberPointer(const MemberPointerType *T,
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000227 std::string &S) {
228 std::string C;
John McCall49f4e1c2010-12-10 11:01:00 +0000229 print(QualType(T->getClass(), 0), C);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000230 C += "::*";
231 S = C + S;
232
233 // Handle things like 'int (Cls::*A)[4];' correctly.
234 // FIXME: this should include vectors, but vectors use attributes I guess.
235 if (isa<ArrayType>(T->getPointeeType()))
236 S = '(' + S + ')';
237
John McCall49f4e1c2010-12-10 11:01:00 +0000238 print(T->getPointeeType(), S);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000239}
240
John McCall49f4e1c2010-12-10 11:01:00 +0000241void TypePrinter::printConstantArray(const ConstantArrayType *T,
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000242 std::string &S) {
243 S += '[';
244 S += llvm::utostr(T->getSize().getZExtValue());
245 S += ']';
246
John McCall49f4e1c2010-12-10 11:01:00 +0000247 print(T->getElementType(), S);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000248}
249
John McCall49f4e1c2010-12-10 11:01:00 +0000250void TypePrinter::printIncompleteArray(const IncompleteArrayType *T,
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000251 std::string &S) {
252 S += "[]";
John McCall49f4e1c2010-12-10 11:01:00 +0000253 print(T->getElementType(), S);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000254}
255
John McCall49f4e1c2010-12-10 11:01:00 +0000256void TypePrinter::printVariableArray(const VariableArrayType *T,
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000257 std::string &S) {
258 S += '[';
259
260 if (T->getIndexTypeQualifiers().hasQualifiers()) {
261 AppendTypeQualList(S, T->getIndexTypeCVRQualifiers());
262 S += ' ';
263 }
264
265 if (T->getSizeModifier() == VariableArrayType::Static)
266 S += "static";
267 else if (T->getSizeModifier() == VariableArrayType::Star)
268 S += '*';
269
270 if (T->getSizeExpr()) {
271 std::string SStr;
272 llvm::raw_string_ostream s(SStr);
273 T->getSizeExpr()->printPretty(s, 0, Policy);
274 S += s.str();
275 }
276 S += ']';
277
John McCall49f4e1c2010-12-10 11:01:00 +0000278 print(T->getElementType(), S);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000279}
280
John McCall49f4e1c2010-12-10 11:01:00 +0000281void TypePrinter::printDependentSizedArray(const DependentSizedArrayType *T,
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000282 std::string &S) {
283 S += '[';
284
285 if (T->getSizeExpr()) {
286 std::string SStr;
287 llvm::raw_string_ostream s(SStr);
288 T->getSizeExpr()->printPretty(s, 0, Policy);
289 S += s.str();
290 }
291 S += ']';
292
John McCall49f4e1c2010-12-10 11:01:00 +0000293 print(T->getElementType(), S);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000294}
295
John McCall49f4e1c2010-12-10 11:01:00 +0000296void TypePrinter::printDependentSizedExtVector(
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000297 const DependentSizedExtVectorType *T,
298 std::string &S) {
John McCall49f4e1c2010-12-10 11:01:00 +0000299 print(T->getElementType(), S);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000300
301 S += " __attribute__((ext_vector_type(";
302 if (T->getSizeExpr()) {
303 std::string SStr;
304 llvm::raw_string_ostream s(SStr);
305 T->getSizeExpr()->printPretty(s, 0, Policy);
306 S += s.str();
307 }
308 S += ")))";
309}
310
John McCall49f4e1c2010-12-10 11:01:00 +0000311void TypePrinter::printVector(const VectorType *T, std::string &S) {
Bob Wilsonec33cbe2010-11-16 00:32:26 +0000312 switch (T->getVectorKind()) {
313 case VectorType::AltiVecPixel:
314 S = "__vector __pixel " + S;
315 break;
316 case VectorType::AltiVecBool:
John McCall49f4e1c2010-12-10 11:01:00 +0000317 print(T->getElementType(), S);
Bob Wilsonec33cbe2010-11-16 00:32:26 +0000318 S = "__vector __bool " + S;
319 break;
320 case VectorType::AltiVecVector:
John McCall49f4e1c2010-12-10 11:01:00 +0000321 print(T->getElementType(), S);
Bob Wilsonec33cbe2010-11-16 00:32:26 +0000322 S = "__vector " + S;
323 break;
324 case VectorType::NeonVector:
John McCall49f4e1c2010-12-10 11:01:00 +0000325 print(T->getElementType(), S);
Bob Wilsonec33cbe2010-11-16 00:32:26 +0000326 S = ("__attribute__((neon_vector_type(" +
327 llvm::utostr_32(T->getNumElements()) + "))) " + S);
328 break;
329 case VectorType::NeonPolyVector:
John McCall49f4e1c2010-12-10 11:01:00 +0000330 print(T->getElementType(), S);
Bob Wilsonec33cbe2010-11-16 00:32:26 +0000331 S = ("__attribute__((neon_polyvector_type(" +
332 llvm::utostr_32(T->getNumElements()) + "))) " + S);
333 break;
334 case VectorType::GenericVector: {
John Thompson82287d12010-02-05 00:12:22 +0000335 // FIXME: We prefer to print the size directly here, but have no way
336 // to get the size of the type.
John McCall49f4e1c2010-12-10 11:01:00 +0000337 print(T->getElementType(), S);
John Thompson82287d12010-02-05 00:12:22 +0000338 std::string V = "__attribute__((__vector_size__(";
339 V += llvm::utostr_32(T->getNumElements()); // convert back to bytes.
340 std::string ET;
John McCall49f4e1c2010-12-10 11:01:00 +0000341 print(T->getElementType(), ET);
John Thompson82287d12010-02-05 00:12:22 +0000342 V += " * sizeof(" + ET + ")))) ";
343 S = V + S;
Bob Wilsonec33cbe2010-11-16 00:32:26 +0000344 break;
345 }
John Thompson82287d12010-02-05 00:12:22 +0000346 }
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000347}
348
John McCall49f4e1c2010-12-10 11:01:00 +0000349void TypePrinter::printExtVector(const ExtVectorType *T, std::string &S) {
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000350 S += " __attribute__((ext_vector_type(";
351 S += llvm::utostr_32(T->getNumElements());
352 S += ")))";
John McCall49f4e1c2010-12-10 11:01:00 +0000353 print(T->getElementType(), S);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000354}
355
John McCall49f4e1c2010-12-10 11:01:00 +0000356void TypePrinter::printFunctionProto(const FunctionProtoType *T,
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000357 std::string &S) {
358 // If needed for precedence reasons, wrap the inner part in grouping parens.
359 if (!S.empty())
360 S = "(" + S + ")";
361
362 S += "(";
363 std::string Tmp;
364 PrintingPolicy ParamPolicy(Policy);
365 ParamPolicy.SuppressSpecifiers = false;
366 for (unsigned i = 0, e = T->getNumArgs(); i != e; ++i) {
367 if (i) S += ", ";
John McCall49f4e1c2010-12-10 11:01:00 +0000368 print(T->getArgType(i), Tmp);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000369 S += Tmp;
370 Tmp.clear();
371 }
372
373 if (T->isVariadic()) {
374 if (T->getNumArgs())
375 S += ", ";
376 S += "...";
377 } else if (T->getNumArgs() == 0 && !Policy.LangOpts.CPlusPlus) {
378 // Do not emit int() if we have a proto, emit 'int(void)'.
379 S += "void";
380 }
381
382 S += ")";
Douglas Gregor0ae7b3f2009-12-08 17:45:32 +0000383
Rafael Espindola264ba482010-03-30 20:24:48 +0000384 FunctionType::ExtInfo Info = T->getExtInfo();
385 switch(Info.getCC()) {
John McCallf82b4e82010-02-04 05:44:44 +0000386 case CC_Default:
387 default: break;
388 case CC_C:
389 S += " __attribute__((cdecl))";
390 break;
391 case CC_X86StdCall:
392 S += " __attribute__((stdcall))";
393 break;
394 case CC_X86FastCall:
395 S += " __attribute__((fastcall))";
396 break;
Douglas Gregorf813a2c2010-05-18 16:57:00 +0000397 case CC_X86ThisCall:
398 S += " __attribute__((thiscall))";
399 break;
Dawn Perchik52fc3142010-09-03 01:29:35 +0000400 case CC_X86Pascal:
401 S += " __attribute__((pascal))";
402 break;
John McCallf82b4e82010-02-04 05:44:44 +0000403 }
Rafael Espindola264ba482010-03-30 20:24:48 +0000404 if (Info.getNoReturn())
Douglas Gregor48026d22010-01-11 18:40:55 +0000405 S += " __attribute__((noreturn))";
Rafael Espindola425ef722010-03-30 22:15:11 +0000406 if (Info.getRegParm())
407 S += " __attribute__((regparm (" +
408 llvm::utostr_32(Info.getRegParm()) + ")))";
Douglas Gregor48026d22010-01-11 18:40:55 +0000409
Douglas Gregorc938c162011-01-26 05:01:58 +0000410 AppendTypeQualList(S, T->getTypeQuals());
411
412 switch (T->getRefQualifier()) {
413 case RQ_None:
414 break;
415
416 case RQ_LValue:
417 S += " &";
418 break;
419
420 case RQ_RValue:
421 S += " &&";
422 break;
423 }
Sebastian Redl60618fa2011-03-12 11:50:43 +0000424
425 if (T->hasDynamicExceptionSpec()) {
Douglas Gregor0ae7b3f2009-12-08 17:45:32 +0000426 S += " throw(";
Sebastian Redl60618fa2011-03-12 11:50:43 +0000427 if (T->getExceptionSpecType() == EST_MSAny)
Douglas Gregor0ae7b3f2009-12-08 17:45:32 +0000428 S += "...";
Sebastian Redl60618fa2011-03-12 11:50:43 +0000429 else
Douglas Gregor0ae7b3f2009-12-08 17:45:32 +0000430 for (unsigned I = 0, N = T->getNumExceptions(); I != N; ++I) {
431 if (I)
432 S += ", ";
433
434 std::string ExceptionType;
John McCall49f4e1c2010-12-10 11:01:00 +0000435 print(T->getExceptionType(I), ExceptionType);
Douglas Gregor0ae7b3f2009-12-08 17:45:32 +0000436 S += ExceptionType;
437 }
438 S += ")";
Sebastian Redl60618fa2011-03-12 11:50:43 +0000439 } else if (isNoexceptExceptionSpec(T->getExceptionSpecType())) {
440 S += " noexcept";
441 if (T->getExceptionSpecType() == EST_ComputedNoexcept) {
442 S += "(";
443 llvm::raw_string_ostream EOut(S);
444 T->getNoexceptExpr()->printPretty(EOut, 0, Policy);
445 EOut.flush();
446 S += EOut.str();
447 S += ")";
448 }
Douglas Gregor0ae7b3f2009-12-08 17:45:32 +0000449 }
450
John McCall49f4e1c2010-12-10 11:01:00 +0000451 print(T->getResultType(), S);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000452}
453
John McCall49f4e1c2010-12-10 11:01:00 +0000454void TypePrinter::printFunctionNoProto(const FunctionNoProtoType *T,
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000455 std::string &S) {
456 // If needed for precedence reasons, wrap the inner part in grouping parens.
457 if (!S.empty())
458 S = "(" + S + ")";
459
460 S += "()";
461 if (T->getNoReturnAttr())
462 S += " __attribute__((noreturn))";
John McCall49f4e1c2010-12-10 11:01:00 +0000463 print(T->getResultType(), S);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000464}
465
John McCall49f4e1c2010-12-10 11:01:00 +0000466static void printTypeSpec(const NamedDecl *D, std::string &S) {
John McCall3cb0ebd2010-03-10 03:28:59 +0000467 IdentifierInfo *II = D->getIdentifier();
John McCalled976492009-12-04 22:46:56 +0000468 if (S.empty())
469 S = II->getName().str();
470 else
471 S = II->getName().str() + ' ' + S;
472}
473
John McCall49f4e1c2010-12-10 11:01:00 +0000474void TypePrinter::printUnresolvedUsing(const UnresolvedUsingType *T,
John McCall3cb0ebd2010-03-10 03:28:59 +0000475 std::string &S) {
John McCall49f4e1c2010-12-10 11:01:00 +0000476 printTypeSpec(T->getDecl(), S);
John McCall3cb0ebd2010-03-10 03:28:59 +0000477}
478
John McCall49f4e1c2010-12-10 11:01:00 +0000479void TypePrinter::printTypedef(const TypedefType *T, std::string &S) {
480 printTypeSpec(T->getDecl(), S);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000481}
482
John McCall49f4e1c2010-12-10 11:01:00 +0000483void TypePrinter::printTypeOfExpr(const TypeOfExprType *T, std::string &S) {
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000484 if (!S.empty()) // Prefix the basic type, e.g. 'typeof(e) X'.
485 S = ' ' + S;
486 std::string Str;
487 llvm::raw_string_ostream s(Str);
488 T->getUnderlyingExpr()->printPretty(s, 0, Policy);
489 S = "typeof " + s.str() + S;
490}
491
John McCall49f4e1c2010-12-10 11:01:00 +0000492void TypePrinter::printTypeOf(const TypeOfType *T, std::string &S) {
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000493 if (!S.empty()) // Prefix the basic type, e.g. 'typeof(t) X'.
494 S = ' ' + S;
495 std::string Tmp;
John McCall49f4e1c2010-12-10 11:01:00 +0000496 print(T->getUnderlyingType(), Tmp);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000497 S = "typeof(" + Tmp + ")" + S;
498}
499
John McCall49f4e1c2010-12-10 11:01:00 +0000500void TypePrinter::printDecltype(const DecltypeType *T, std::string &S) {
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000501 if (!S.empty()) // Prefix the basic type, e.g. 'decltype(t) X'.
502 S = ' ' + S;
503 std::string Str;
504 llvm::raw_string_ostream s(Str);
505 T->getUnderlyingExpr()->printPretty(s, 0, Policy);
506 S = "decltype(" + s.str() + ")" + S;
507}
508
Richard Smith34b41d92011-02-20 03:19:35 +0000509void TypePrinter::printAuto(const AutoType *T, std::string &S) {
510 // If the type has been deduced, do not print 'auto'.
511 if (T->isDeduced()) {
512 print(T->getDeducedType(), S);
513 } else {
514 if (!S.empty()) // Prefix the basic type, e.g. 'auto X'.
515 S = ' ' + S;
516 S = "auto" + S;
517 }
518}
519
John McCall7c2342d2010-03-10 11:27:22 +0000520/// Appends the given scope to the end of a string.
521void TypePrinter::AppendScope(DeclContext *DC, std::string &Buffer) {
522 if (DC->isTranslationUnit()) return;
523 AppendScope(DC->getParent(), Buffer);
524
525 unsigned OldSize = Buffer.size();
526
527 if (NamespaceDecl *NS = dyn_cast<NamespaceDecl>(DC)) {
528 if (NS->getIdentifier())
529 Buffer += NS->getNameAsString();
530 else
531 Buffer += "<anonymous>";
532 } else if (ClassTemplateSpecializationDecl *Spec
533 = dyn_cast<ClassTemplateSpecializationDecl>(DC)) {
534 const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs();
535 std::string TemplateArgsStr
536 = TemplateSpecializationType::PrintTemplateArgumentList(
Douglas Gregor910f8002010-11-07 23:05:16 +0000537 TemplateArgs.data(),
538 TemplateArgs.size(),
John McCall7c2342d2010-03-10 11:27:22 +0000539 Policy);
540 Buffer += Spec->getIdentifier()->getName();
541 Buffer += TemplateArgsStr;
542 } else if (TagDecl *Tag = dyn_cast<TagDecl>(DC)) {
543 if (TypedefDecl *Typedef = Tag->getTypedefForAnonDecl())
544 Buffer += Typedef->getIdentifier()->getName();
545 else if (Tag->getIdentifier())
546 Buffer += Tag->getIdentifier()->getName();
547 }
548
549 if (Buffer.size() != OldSize)
550 Buffer += "::";
551}
552
John McCall49f4e1c2010-12-10 11:01:00 +0000553void TypePrinter::printTag(TagDecl *D, std::string &InnerString) {
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000554 if (Policy.SuppressTag)
555 return;
John McCall7c2342d2010-03-10 11:27:22 +0000556
557 std::string Buffer;
John McCall73061d02010-03-19 07:56:44 +0000558 bool HasKindDecoration = false;
John McCall7c2342d2010-03-10 11:27:22 +0000559
560 // We don't print tags unless this is an elaborated type.
561 // In C, we just assume every RecordType is an elaborated type.
562 if (!Policy.LangOpts.CPlusPlus && !D->getTypedefForAnonDecl()) {
John McCall73061d02010-03-19 07:56:44 +0000563 HasKindDecoration = true;
John McCall7c2342d2010-03-10 11:27:22 +0000564 Buffer += D->getKindName();
565 Buffer += ' ';
566 }
567
Chris Lattnerc7acc662010-08-28 16:26:18 +0000568 // Compute the full nested-name-specifier for this type.
569 // In C, this will always be empty except when the type
570 // being printed is anonymous within other Record.
John McCall7c2342d2010-03-10 11:27:22 +0000571 if (!Policy.SuppressScope)
John McCall7c2342d2010-03-10 11:27:22 +0000572 AppendScope(D->getDeclContext(), Buffer);
573
John McCall3cb0ebd2010-03-10 03:28:59 +0000574 if (const IdentifierInfo *II = D->getIdentifier())
John McCall73061d02010-03-19 07:56:44 +0000575 Buffer += II->getNameStart();
John McCall3cb0ebd2010-03-10 03:28:59 +0000576 else if (TypedefDecl *Typedef = D->getTypedefForAnonDecl()) {
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000577 assert(Typedef->getIdentifier() && "Typedef without identifier?");
John McCall73061d02010-03-19 07:56:44 +0000578 Buffer += Typedef->getIdentifier()->getNameStart();
579 } else {
580 // Make an unambiguous representation for anonymous types, e.g.
581 // <anonymous enum at /usr/include/string.h:120:9>
582 llvm::raw_string_ostream OS(Buffer);
583 OS << "<anonymous";
584
Douglas Gregor84139d62010-04-05 21:25:31 +0000585 if (Policy.AnonymousTagLocations) {
586 // Suppress the redundant tag keyword if we just printed one.
587 // We don't have to worry about ElaboratedTypes here because you can't
588 // refer to an anonymous type with one.
589 if (!HasKindDecoration)
590 OS << " " << D->getKindName();
John McCall73061d02010-03-19 07:56:44 +0000591
Douglas Gregorcb7b1e12010-11-12 07:15:47 +0000592 PresumedLoc PLoc = D->getASTContext().getSourceManager().getPresumedLoc(
Douglas Gregor16834e82010-05-28 21:47:04 +0000593 D->getLocation());
Douglas Gregorcb7b1e12010-11-12 07:15:47 +0000594 if (PLoc.isValid()) {
Douglas Gregor16834e82010-05-28 21:47:04 +0000595 OS << " at " << PLoc.getFilename()
596 << ':' << PLoc.getLine()
597 << ':' << PLoc.getColumn();
598 }
Douglas Gregor84139d62010-04-05 21:25:31 +0000599 }
600
601 OS << '>';
John McCall73061d02010-03-19 07:56:44 +0000602 }
John McCall7c2342d2010-03-10 11:27:22 +0000603
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000604 // If this is a class template specialization, print the template
605 // arguments.
606 if (ClassTemplateSpecializationDecl *Spec
John McCall7c2342d2010-03-10 11:27:22 +0000607 = dyn_cast<ClassTemplateSpecializationDecl>(D)) {
John McCall3cb0ebd2010-03-10 03:28:59 +0000608 const TemplateArgument *Args;
609 unsigned NumArgs;
610 if (TypeSourceInfo *TAW = Spec->getTypeAsWritten()) {
611 const TemplateSpecializationType *TST =
612 cast<TemplateSpecializationType>(TAW->getType());
613 Args = TST->getArgs();
614 NumArgs = TST->getNumArgs();
615 } else {
616 const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs();
Douglas Gregor910f8002010-11-07 23:05:16 +0000617 Args = TemplateArgs.data();
618 NumArgs = TemplateArgs.size();
John McCall3cb0ebd2010-03-10 03:28:59 +0000619 }
John McCall7c2342d2010-03-10 11:27:22 +0000620 Buffer += TemplateSpecializationType::PrintTemplateArgumentList(Args,
621 NumArgs,
622 Policy);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000623 }
John McCall7c2342d2010-03-10 11:27:22 +0000624
625 if (!InnerString.empty()) {
626 Buffer += ' ';
627 Buffer += InnerString;
628 }
629
630 std::swap(Buffer, InnerString);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000631}
632
John McCall49f4e1c2010-12-10 11:01:00 +0000633void TypePrinter::printRecord(const RecordType *T, std::string &S) {
634 printTag(T->getDecl(), S);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000635}
636
John McCall49f4e1c2010-12-10 11:01:00 +0000637void TypePrinter::printEnum(const EnumType *T, std::string &S) {
638 printTag(T->getDecl(), S);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000639}
640
John McCall49f4e1c2010-12-10 11:01:00 +0000641void TypePrinter::printTemplateTypeParm(const TemplateTypeParmType *T,
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000642 std::string &S) {
643 if (!S.empty()) // Prefix the basic type, e.g. 'parmname X'.
644 S = ' ' + S;
Douglas Gregorefed5c82010-06-16 15:23:05 +0000645
646 if (!T->getName())
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000647 S = "type-parameter-" + llvm::utostr_32(T->getDepth()) + '-' +
648 llvm::utostr_32(T->getIndex()) + S;
Douglas Gregorefed5c82010-06-16 15:23:05 +0000649 else
650 S = T->getName()->getName().str() + S;
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000651}
652
John McCall49f4e1c2010-12-10 11:01:00 +0000653void TypePrinter::printSubstTemplateTypeParm(const SubstTemplateTypeParmType *T,
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000654 std::string &S) {
John McCall49f4e1c2010-12-10 11:01:00 +0000655 print(T->getReplacementType(), S);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000656}
657
Douglas Gregorc3069d62011-01-14 02:55:32 +0000658void TypePrinter::printSubstTemplateTypeParmPack(
659 const SubstTemplateTypeParmPackType *T,
660 std::string &S) {
661 printTemplateTypeParm(T->getReplacedParameter(), S);
662}
663
John McCall49f4e1c2010-12-10 11:01:00 +0000664void TypePrinter::printTemplateSpecialization(
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000665 const TemplateSpecializationType *T,
666 std::string &S) {
667 std::string SpecString;
668
669 {
670 llvm::raw_string_ostream OS(SpecString);
671 T->getTemplateName().print(OS, Policy);
672 }
673
674 SpecString += TemplateSpecializationType::PrintTemplateArgumentList(
675 T->getArgs(),
676 T->getNumArgs(),
677 Policy);
678 if (S.empty())
679 S.swap(SpecString);
680 else
681 S = SpecString + ' ' + S;
682}
683
John McCall49f4e1c2010-12-10 11:01:00 +0000684void TypePrinter::printInjectedClassName(const InjectedClassNameType *T,
John McCall3cb0ebd2010-03-10 03:28:59 +0000685 std::string &S) {
John McCall49f4e1c2010-12-10 11:01:00 +0000686 printTemplateSpecialization(T->getInjectedTST(), S);
John McCall3cb0ebd2010-03-10 03:28:59 +0000687}
688
John McCall49f4e1c2010-12-10 11:01:00 +0000689void TypePrinter::printElaborated(const ElaboratedType *T, std::string &S) {
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000690 std::string MyString;
691
692 {
693 llvm::raw_string_ostream OS(MyString);
Abramo Bagnara465d41b2010-05-11 21:36:43 +0000694 OS << TypeWithKeyword::getKeywordName(T->getKeyword());
695 if (T->getKeyword() != ETK_None)
696 OS << " ";
697 NestedNameSpecifier* Qualifier = T->getQualifier();
698 if (Qualifier)
699 Qualifier->print(OS, Policy);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000700 }
701
702 std::string TypeStr;
703 PrintingPolicy InnerPolicy(Policy);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000704 InnerPolicy.SuppressScope = true;
John McCall49f4e1c2010-12-10 11:01:00 +0000705 TypePrinter(InnerPolicy).print(T->getNamedType(), TypeStr);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000706
707 MyString += TypeStr;
708 if (S.empty())
709 S.swap(MyString);
710 else
711 S = MyString + ' ' + S;
712}
713
Abramo Bagnara075f8f12010-12-10 16:29:40 +0000714void TypePrinter::printParen(const ParenType *T, std::string &S) {
715 if (!S.empty() && !isa<FunctionType>(T->getInnerType()))
716 S = '(' + S + ')';
717 print(T->getInnerType(), S);
718}
719
John McCall49f4e1c2010-12-10 11:01:00 +0000720void TypePrinter::printDependentName(const DependentNameType *T, std::string &S) {
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000721 std::string MyString;
722
723 {
724 llvm::raw_string_ostream OS(MyString);
Abramo Bagnara465d41b2010-05-11 21:36:43 +0000725 OS << TypeWithKeyword::getKeywordName(T->getKeyword());
726 if (T->getKeyword() != ETK_None)
727 OS << " ";
Douglas Gregor4a2023f2010-03-31 20:19:30 +0000728
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000729 T->getQualifier()->print(OS, Policy);
730
John McCall33500952010-06-11 00:33:02 +0000731 OS << T->getIdentifier()->getName();
732 }
733
734 if (S.empty())
735 S.swap(MyString);
736 else
737 S = MyString + ' ' + S;
738}
739
John McCall49f4e1c2010-12-10 11:01:00 +0000740void TypePrinter::printDependentTemplateSpecialization(
John McCall33500952010-06-11 00:33:02 +0000741 const DependentTemplateSpecializationType *T, std::string &S) {
742 std::string MyString;
743 {
744 llvm::raw_string_ostream OS(MyString);
745
746 OS << TypeWithKeyword::getKeywordName(T->getKeyword());
747 if (T->getKeyword() != ETK_None)
748 OS << " ";
749
Douglas Gregora88f09f2011-02-28 17:23:35 +0000750 if (T->getQualifier())
751 T->getQualifier()->print(OS, Policy);
John McCall33500952010-06-11 00:33:02 +0000752 OS << T->getIdentifier()->getName();
753 OS << TemplateSpecializationType::PrintTemplateArgumentList(
754 T->getArgs(),
755 T->getNumArgs(),
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000756 Policy);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000757 }
758
759 if (S.empty())
760 S.swap(MyString);
761 else
762 S = MyString + ' ' + S;
763}
764
Douglas Gregor7536dd52010-12-20 02:24:11 +0000765void TypePrinter::printPackExpansion(const PackExpansionType *T,
766 std::string &S) {
767 print(T->getPattern(), S);
768 S += "...";
769}
770
John McCall9d156a72011-01-06 01:58:22 +0000771void TypePrinter::printAttributed(const AttributedType *T,
772 std::string &S) {
John McCall14aa2172011-03-04 04:00:19 +0000773 // Prefer the macro forms of the GC qualifiers.
774 if (T->getAttrKind() == AttributedType::attr_objc_gc)
775 return print(T->getEquivalentType(), S);
776
John McCall9d156a72011-01-06 01:58:22 +0000777 print(T->getModifiedType(), S);
778
779 // TODO: not all attributes are GCC-style attributes.
John McCall14aa2172011-03-04 04:00:19 +0000780 S += " __attribute__((";
John McCall9d156a72011-01-06 01:58:22 +0000781 switch (T->getAttrKind()) {
Francois Pichet170464b2011-01-07 03:17:31 +0000782 case AttributedType::attr_address_space:
John McCall9d156a72011-01-06 01:58:22 +0000783 S += "address_space(";
784 S += T->getEquivalentType().getAddressSpace();
785 S += ")";
786 break;
787
Francois Pichet170464b2011-01-07 03:17:31 +0000788 case AttributedType::attr_vector_size: {
John McCall9d156a72011-01-06 01:58:22 +0000789 S += "__vector_size__(";
790 if (const VectorType *vector =T->getEquivalentType()->getAs<VectorType>()) {
791 S += vector->getNumElements();
792 S += " * sizeof(";
793
794 std::string tmp;
795 print(vector->getElementType(), tmp);
796 S += tmp;
797 S += ")";
798 }
799 S += ")";
800 break;
801 }
802
Francois Pichet170464b2011-01-07 03:17:31 +0000803 case AttributedType::attr_neon_vector_type:
804 case AttributedType::attr_neon_polyvector_type: {
805 if (T->getAttrKind() == AttributedType::attr_neon_vector_type)
John McCall9d156a72011-01-06 01:58:22 +0000806 S += "neon_vector_type(";
807 else
808 S += "neon_polyvector_type(";
809 const VectorType *vector = T->getEquivalentType()->getAs<VectorType>();
810 S += llvm::utostr_32(vector->getNumElements());
811 S += ")";
812 break;
813 }
814
Francois Pichet170464b2011-01-07 03:17:31 +0000815 case AttributedType::attr_regparm: {
John McCall9d156a72011-01-06 01:58:22 +0000816 S += "regparm(";
817 QualType t = T->getEquivalentType();
818 while (!t->isFunctionType())
819 t = t->getPointeeType();
820 S += t->getAs<FunctionType>()->getRegParmType();
821 S += ")";
822 break;
823 }
824
Francois Pichet170464b2011-01-07 03:17:31 +0000825 case AttributedType::attr_objc_gc: {
John McCall9d156a72011-01-06 01:58:22 +0000826 S += "objc_gc(";
827
828 QualType tmp = T->getEquivalentType();
829 while (tmp.getObjCGCAttr() == Qualifiers::GCNone) {
830 QualType next = tmp->getPointeeType();
831 if (next == tmp) break;
832 tmp = next;
833 }
834
835 if (tmp.isObjCGCWeak())
836 S += "weak";
837 else
838 S += "strong";
839 S += ")";
840 break;
841 }
842
Francois Pichet3cd47e72011-01-07 02:58:13 +0000843 case AttributedType::attr_noreturn: S += "noreturn"; break;
844 case AttributedType::attr_cdecl: S += "cdecl"; break;
845 case AttributedType::attr_fastcall: S += "fastcall"; break;
846 case AttributedType::attr_stdcall: S += "stdcall"; break;
847 case AttributedType::attr_thiscall: S += "thiscall"; break;
848 case AttributedType::attr_pascal: S += "pascal"; break;
John McCall9d156a72011-01-06 01:58:22 +0000849 }
850 S += "))";
851}
852
John McCall49f4e1c2010-12-10 11:01:00 +0000853void TypePrinter::printObjCInterface(const ObjCInterfaceType *T,
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000854 std::string &S) {
855 if (!S.empty()) // Prefix the basic type, e.g. 'typedefname X'.
856 S = ' ' + S;
John McCallc12c5bb2010-05-15 11:32:37 +0000857
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000858 std::string ObjCQIString = T->getDecl()->getNameAsString();
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000859 S = ObjCQIString + S;
860}
861
John McCall49f4e1c2010-12-10 11:01:00 +0000862void TypePrinter::printObjCObject(const ObjCObjectType *T,
John McCallc12c5bb2010-05-15 11:32:37 +0000863 std::string &S) {
864 if (T->qual_empty())
John McCall49f4e1c2010-12-10 11:01:00 +0000865 return print(T->getBaseType(), S);
John McCallc12c5bb2010-05-15 11:32:37 +0000866
867 std::string tmp;
John McCall49f4e1c2010-12-10 11:01:00 +0000868 print(T->getBaseType(), tmp);
John McCallc12c5bb2010-05-15 11:32:37 +0000869 tmp += '<';
870 bool isFirst = true;
871 for (ObjCObjectType::qual_iterator
872 I = T->qual_begin(), E = T->qual_end(); I != E; ++I) {
873 if (isFirst)
874 isFirst = false;
875 else
876 tmp += ',';
877 tmp += (*I)->getNameAsString();
878 }
879 tmp += '>';
880
881 if (!S.empty()) {
882 tmp += ' ';
883 tmp += S;
884 }
885 std::swap(tmp, S);
886}
887
John McCall49f4e1c2010-12-10 11:01:00 +0000888void TypePrinter::printObjCObjectPointer(const ObjCObjectPointerType *T,
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000889 std::string &S) {
890 std::string ObjCQIString;
891
Chris Lattnerd7e52b82010-09-05 00:43:21 +0000892 T->getPointeeType().getLocalQualifiers().getAsStringInternal(ObjCQIString,
893 Policy);
894 if (!ObjCQIString.empty())
895 ObjCQIString += ' ';
896
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000897 if (T->isObjCIdType() || T->isObjCQualifiedIdType())
Chris Lattnerd7e52b82010-09-05 00:43:21 +0000898 ObjCQIString += "id";
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000899 else if (T->isObjCClassType() || T->isObjCQualifiedClassType())
Chris Lattnerd7e52b82010-09-05 00:43:21 +0000900 ObjCQIString += "Class";
Fariborz Jahanian13dcd002009-11-21 19:53:08 +0000901 else if (T->isObjCSelType())
Chris Lattnerd7e52b82010-09-05 00:43:21 +0000902 ObjCQIString += "SEL";
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000903 else
Chris Lattnerd7e52b82010-09-05 00:43:21 +0000904 ObjCQIString += T->getInterfaceDecl()->getNameAsString();
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000905
906 if (!T->qual_empty()) {
907 ObjCQIString += '<';
908 for (ObjCObjectPointerType::qual_iterator I = T->qual_begin(),
909 E = T->qual_end();
910 I != E; ++I) {
911 ObjCQIString += (*I)->getNameAsString();
912 if (I+1 != E)
913 ObjCQIString += ',';
914 }
915 ObjCQIString += '>';
916 }
917
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000918 if (!T->isObjCIdType() && !T->isObjCQualifiedIdType())
919 ObjCQIString += " *"; // Don't forget the implicit pointer.
920 else if (!S.empty()) // Prefix the basic type, e.g. 'typedefname X'.
921 S = ' ' + S;
922
923 S = ObjCQIString + S;
924}
925
John McCalld5532b62009-11-23 01:53:49 +0000926std::string TemplateSpecializationType::
927 PrintTemplateArgumentList(const TemplateArgumentListInfo &Args,
928 const PrintingPolicy &Policy) {
929 return PrintTemplateArgumentList(Args.getArgumentArray(),
930 Args.size(),
931 Policy);
932}
933
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000934std::string
935TemplateSpecializationType::PrintTemplateArgumentList(
936 const TemplateArgument *Args,
937 unsigned NumArgs,
Douglas Gregordace95b2010-12-20 22:28:59 +0000938 const PrintingPolicy &Policy,
939 bool SkipBrackets) {
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000940 std::string SpecString;
Douglas Gregordace95b2010-12-20 22:28:59 +0000941 if (!SkipBrackets)
942 SpecString += '<';
943
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000944 for (unsigned Arg = 0; Arg < NumArgs; ++Arg) {
Douglas Gregordace95b2010-12-20 22:28:59 +0000945 if (SpecString.size() > !SkipBrackets)
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000946 SpecString += ", ";
947
948 // Print the argument into a string.
949 std::string ArgString;
Douglas Gregordace95b2010-12-20 22:28:59 +0000950 if (Args[Arg].getKind() == TemplateArgument::Pack) {
951 ArgString = PrintTemplateArgumentList(Args[Arg].pack_begin(),
952 Args[Arg].pack_size(),
953 Policy, true);
954 } else {
Douglas Gregor87dd6972010-12-20 16:52:59 +0000955 llvm::raw_string_ostream ArgOut(ArgString);
956 Args[Arg].print(Policy, ArgOut);
957 }
958
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000959 // If this is the first argument and its string representation
960 // begins with the global scope specifier ('::foo'), add a space
961 // to avoid printing the diagraph '<:'.
962 if (!Arg && !ArgString.empty() && ArgString[0] == ':')
963 SpecString += ' ';
964
965 SpecString += ArgString;
966 }
967
968 // If the last character of our string is '>', add another space to
969 // keep the two '>''s separate tokens. We don't *have* to do this in
970 // C++0x, but it's still good hygiene.
Francois Pichetb5bc7d02011-01-09 22:32:25 +0000971 if (!SpecString.empty() && SpecString[SpecString.size() - 1] == '>')
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000972 SpecString += ' ';
973
Douglas Gregordace95b2010-12-20 22:28:59 +0000974 if (!SkipBrackets)
975 SpecString += '>';
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000976
977 return SpecString;
978}
979
980// Sadly, repeat all that with TemplateArgLoc.
981std::string TemplateSpecializationType::
982PrintTemplateArgumentList(const TemplateArgumentLoc *Args, unsigned NumArgs,
983 const PrintingPolicy &Policy) {
984 std::string SpecString;
985 SpecString += '<';
986 for (unsigned Arg = 0; Arg < NumArgs; ++Arg) {
Douglas Gregordace95b2010-12-20 22:28:59 +0000987 if (SpecString.size() > 1)
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000988 SpecString += ", ";
989
990 // Print the argument into a string.
991 std::string ArgString;
Douglas Gregordace95b2010-12-20 22:28:59 +0000992 if (Args[Arg].getArgument().getKind() == TemplateArgument::Pack) {
993 ArgString = PrintTemplateArgumentList(
994 Args[Arg].getArgument().pack_begin(),
995 Args[Arg].getArgument().pack_size(),
996 Policy, true);
997 } else {
Douglas Gregor87dd6972010-12-20 16:52:59 +0000998 llvm::raw_string_ostream ArgOut(ArgString);
999 Args[Arg].getArgument().print(Policy, ArgOut);
1000 }
Douglas Gregorfee8a3c2009-11-10 00:39:07 +00001001
1002 // If this is the first argument and its string representation
1003 // begins with the global scope specifier ('::foo'), add a space
1004 // to avoid printing the diagraph '<:'.
1005 if (!Arg && !ArgString.empty() && ArgString[0] == ':')
1006 SpecString += ' ';
1007
1008 SpecString += ArgString;
1009 }
1010
1011 // If the last character of our string is '>', add another space to
1012 // keep the two '>''s separate tokens. We don't *have* to do this in
1013 // C++0x, but it's still good hygiene.
1014 if (SpecString[SpecString.size() - 1] == '>')
1015 SpecString += ' ';
1016
1017 SpecString += '>';
1018
1019 return SpecString;
1020}
1021
1022void QualType::dump(const char *msg) const {
1023 std::string R = "identifier";
1024 LangOptions LO;
1025 getAsStringInternal(R, PrintingPolicy(LO));
1026 if (msg)
Daniel Dunbare7cb7e42009-12-03 09:14:02 +00001027 llvm::errs() << msg << ": ";
1028 llvm::errs() << R << "\n";
Douglas Gregorfee8a3c2009-11-10 00:39:07 +00001029}
1030void QualType::dump() const {
1031 dump("");
1032}
1033
1034void Type::dump() const {
1035 QualType(this, 0).dump();
1036}
1037
1038std::string Qualifiers::getAsString() const {
1039 LangOptions LO;
1040 return getAsString(PrintingPolicy(LO));
1041}
1042
1043// Appends qualifiers to the given string, separated by spaces. Will
1044// prefix a space if the string is non-empty. Will not append a final
1045// space.
1046void Qualifiers::getAsStringInternal(std::string &S,
1047 const PrintingPolicy&) const {
1048 AppendTypeQualList(S, getCVRQualifiers());
John McCall14aa2172011-03-04 04:00:19 +00001049 if (unsigned addrspace = getAddressSpace()) {
Douglas Gregorfee8a3c2009-11-10 00:39:07 +00001050 if (!S.empty()) S += ' ';
1051 S += "__attribute__((address_space(";
John McCall14aa2172011-03-04 04:00:19 +00001052 S += llvm::utostr_32(addrspace);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +00001053 S += ")))";
1054 }
John McCall14aa2172011-03-04 04:00:19 +00001055 if (Qualifiers::GC gc = getObjCGCAttr()) {
Douglas Gregorfee8a3c2009-11-10 00:39:07 +00001056 if (!S.empty()) S += ' ';
John McCall14aa2172011-03-04 04:00:19 +00001057 if (gc == Qualifiers::Weak)
1058 S += "__weak";
Douglas Gregorfee8a3c2009-11-10 00:39:07 +00001059 else
John McCall14aa2172011-03-04 04:00:19 +00001060 S += "__strong";
Douglas Gregorfee8a3c2009-11-10 00:39:07 +00001061 }
1062}
1063
John McCall49f4e1c2010-12-10 11:01:00 +00001064std::string QualType::getAsString(const Type *ty, Qualifiers qs) {
1065 std::string buffer;
1066 LangOptions options;
1067 getAsStringInternal(ty, qs, buffer, PrintingPolicy(options));
1068 return buffer;
Douglas Gregorfee8a3c2009-11-10 00:39:07 +00001069}
1070
John McCall49f4e1c2010-12-10 11:01:00 +00001071void QualType::getAsStringInternal(const Type *ty, Qualifiers qs,
1072 std::string &buffer,
1073 const PrintingPolicy &policy) {
1074 TypePrinter(policy).print(ty, qs, buffer);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +00001075}