blob: 139073987a0ea233cfbbd55180146c88e783ef32 [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 }
424
Douglas Gregor0ae7b3f2009-12-08 17:45:32 +0000425 if (T->hasExceptionSpec()) {
426 S += " throw(";
427 if (T->hasAnyExceptionSpec())
428 S += "...";
429 else
430 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 += ")";
439 }
440
John McCall49f4e1c2010-12-10 11:01:00 +0000441 print(T->getResultType(), S);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000442}
443
John McCall49f4e1c2010-12-10 11:01:00 +0000444void TypePrinter::printFunctionNoProto(const FunctionNoProtoType *T,
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000445 std::string &S) {
446 // If needed for precedence reasons, wrap the inner part in grouping parens.
447 if (!S.empty())
448 S = "(" + S + ")";
449
450 S += "()";
451 if (T->getNoReturnAttr())
452 S += " __attribute__((noreturn))";
John McCall49f4e1c2010-12-10 11:01:00 +0000453 print(T->getResultType(), S);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000454}
455
John McCall49f4e1c2010-12-10 11:01:00 +0000456static void printTypeSpec(const NamedDecl *D, std::string &S) {
John McCall3cb0ebd2010-03-10 03:28:59 +0000457 IdentifierInfo *II = D->getIdentifier();
John McCalled976492009-12-04 22:46:56 +0000458 if (S.empty())
459 S = II->getName().str();
460 else
461 S = II->getName().str() + ' ' + S;
462}
463
John McCall49f4e1c2010-12-10 11:01:00 +0000464void TypePrinter::printUnresolvedUsing(const UnresolvedUsingType *T,
John McCall3cb0ebd2010-03-10 03:28:59 +0000465 std::string &S) {
John McCall49f4e1c2010-12-10 11:01:00 +0000466 printTypeSpec(T->getDecl(), S);
John McCall3cb0ebd2010-03-10 03:28:59 +0000467}
468
John McCall49f4e1c2010-12-10 11:01:00 +0000469void TypePrinter::printTypedef(const TypedefType *T, std::string &S) {
470 printTypeSpec(T->getDecl(), S);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000471}
472
John McCall49f4e1c2010-12-10 11:01:00 +0000473void TypePrinter::printTypeOfExpr(const TypeOfExprType *T, std::string &S) {
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000474 if (!S.empty()) // Prefix the basic type, e.g. 'typeof(e) X'.
475 S = ' ' + S;
476 std::string Str;
477 llvm::raw_string_ostream s(Str);
478 T->getUnderlyingExpr()->printPretty(s, 0, Policy);
479 S = "typeof " + s.str() + S;
480}
481
John McCall49f4e1c2010-12-10 11:01:00 +0000482void TypePrinter::printTypeOf(const TypeOfType *T, std::string &S) {
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000483 if (!S.empty()) // Prefix the basic type, e.g. 'typeof(t) X'.
484 S = ' ' + S;
485 std::string Tmp;
John McCall49f4e1c2010-12-10 11:01:00 +0000486 print(T->getUnderlyingType(), Tmp);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000487 S = "typeof(" + Tmp + ")" + S;
488}
489
John McCall49f4e1c2010-12-10 11:01:00 +0000490void TypePrinter::printDecltype(const DecltypeType *T, std::string &S) {
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000491 if (!S.empty()) // Prefix the basic type, e.g. 'decltype(t) X'.
492 S = ' ' + S;
493 std::string Str;
494 llvm::raw_string_ostream s(Str);
495 T->getUnderlyingExpr()->printPretty(s, 0, Policy);
496 S = "decltype(" + s.str() + ")" + S;
497}
498
Richard Smith34b41d92011-02-20 03:19:35 +0000499void TypePrinter::printAuto(const AutoType *T, std::string &S) {
500 // If the type has been deduced, do not print 'auto'.
501 if (T->isDeduced()) {
502 print(T->getDeducedType(), S);
503 } else {
504 if (!S.empty()) // Prefix the basic type, e.g. 'auto X'.
505 S = ' ' + S;
506 S = "auto" + S;
507 }
508}
509
John McCall7c2342d2010-03-10 11:27:22 +0000510/// Appends the given scope to the end of a string.
511void TypePrinter::AppendScope(DeclContext *DC, std::string &Buffer) {
512 if (DC->isTranslationUnit()) return;
513 AppendScope(DC->getParent(), Buffer);
514
515 unsigned OldSize = Buffer.size();
516
517 if (NamespaceDecl *NS = dyn_cast<NamespaceDecl>(DC)) {
518 if (NS->getIdentifier())
519 Buffer += NS->getNameAsString();
520 else
521 Buffer += "<anonymous>";
522 } else if (ClassTemplateSpecializationDecl *Spec
523 = dyn_cast<ClassTemplateSpecializationDecl>(DC)) {
524 const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs();
525 std::string TemplateArgsStr
526 = TemplateSpecializationType::PrintTemplateArgumentList(
Douglas Gregor910f8002010-11-07 23:05:16 +0000527 TemplateArgs.data(),
528 TemplateArgs.size(),
John McCall7c2342d2010-03-10 11:27:22 +0000529 Policy);
530 Buffer += Spec->getIdentifier()->getName();
531 Buffer += TemplateArgsStr;
532 } else if (TagDecl *Tag = dyn_cast<TagDecl>(DC)) {
533 if (TypedefDecl *Typedef = Tag->getTypedefForAnonDecl())
534 Buffer += Typedef->getIdentifier()->getName();
535 else if (Tag->getIdentifier())
536 Buffer += Tag->getIdentifier()->getName();
537 }
538
539 if (Buffer.size() != OldSize)
540 Buffer += "::";
541}
542
John McCall49f4e1c2010-12-10 11:01:00 +0000543void TypePrinter::printTag(TagDecl *D, std::string &InnerString) {
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000544 if (Policy.SuppressTag)
545 return;
John McCall7c2342d2010-03-10 11:27:22 +0000546
547 std::string Buffer;
John McCall73061d02010-03-19 07:56:44 +0000548 bool HasKindDecoration = false;
John McCall7c2342d2010-03-10 11:27:22 +0000549
550 // We don't print tags unless this is an elaborated type.
551 // In C, we just assume every RecordType is an elaborated type.
552 if (!Policy.LangOpts.CPlusPlus && !D->getTypedefForAnonDecl()) {
John McCall73061d02010-03-19 07:56:44 +0000553 HasKindDecoration = true;
John McCall7c2342d2010-03-10 11:27:22 +0000554 Buffer += D->getKindName();
555 Buffer += ' ';
556 }
557
Chris Lattnerc7acc662010-08-28 16:26:18 +0000558 // Compute the full nested-name-specifier for this type.
559 // In C, this will always be empty except when the type
560 // being printed is anonymous within other Record.
John McCall7c2342d2010-03-10 11:27:22 +0000561 if (!Policy.SuppressScope)
John McCall7c2342d2010-03-10 11:27:22 +0000562 AppendScope(D->getDeclContext(), Buffer);
563
John McCall3cb0ebd2010-03-10 03:28:59 +0000564 if (const IdentifierInfo *II = D->getIdentifier())
John McCall73061d02010-03-19 07:56:44 +0000565 Buffer += II->getNameStart();
John McCall3cb0ebd2010-03-10 03:28:59 +0000566 else if (TypedefDecl *Typedef = D->getTypedefForAnonDecl()) {
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000567 assert(Typedef->getIdentifier() && "Typedef without identifier?");
John McCall73061d02010-03-19 07:56:44 +0000568 Buffer += Typedef->getIdentifier()->getNameStart();
569 } else {
570 // Make an unambiguous representation for anonymous types, e.g.
571 // <anonymous enum at /usr/include/string.h:120:9>
572 llvm::raw_string_ostream OS(Buffer);
573 OS << "<anonymous";
574
Douglas Gregor84139d62010-04-05 21:25:31 +0000575 if (Policy.AnonymousTagLocations) {
576 // Suppress the redundant tag keyword if we just printed one.
577 // We don't have to worry about ElaboratedTypes here because you can't
578 // refer to an anonymous type with one.
579 if (!HasKindDecoration)
580 OS << " " << D->getKindName();
John McCall73061d02010-03-19 07:56:44 +0000581
Douglas Gregorcb7b1e12010-11-12 07:15:47 +0000582 PresumedLoc PLoc = D->getASTContext().getSourceManager().getPresumedLoc(
Douglas Gregor16834e82010-05-28 21:47:04 +0000583 D->getLocation());
Douglas Gregorcb7b1e12010-11-12 07:15:47 +0000584 if (PLoc.isValid()) {
Douglas Gregor16834e82010-05-28 21:47:04 +0000585 OS << " at " << PLoc.getFilename()
586 << ':' << PLoc.getLine()
587 << ':' << PLoc.getColumn();
588 }
Douglas Gregor84139d62010-04-05 21:25:31 +0000589 }
590
591 OS << '>';
John McCall73061d02010-03-19 07:56:44 +0000592 }
John McCall7c2342d2010-03-10 11:27:22 +0000593
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000594 // If this is a class template specialization, print the template
595 // arguments.
596 if (ClassTemplateSpecializationDecl *Spec
John McCall7c2342d2010-03-10 11:27:22 +0000597 = dyn_cast<ClassTemplateSpecializationDecl>(D)) {
John McCall3cb0ebd2010-03-10 03:28:59 +0000598 const TemplateArgument *Args;
599 unsigned NumArgs;
600 if (TypeSourceInfo *TAW = Spec->getTypeAsWritten()) {
601 const TemplateSpecializationType *TST =
602 cast<TemplateSpecializationType>(TAW->getType());
603 Args = TST->getArgs();
604 NumArgs = TST->getNumArgs();
605 } else {
606 const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs();
Douglas Gregor910f8002010-11-07 23:05:16 +0000607 Args = TemplateArgs.data();
608 NumArgs = TemplateArgs.size();
John McCall3cb0ebd2010-03-10 03:28:59 +0000609 }
John McCall7c2342d2010-03-10 11:27:22 +0000610 Buffer += TemplateSpecializationType::PrintTemplateArgumentList(Args,
611 NumArgs,
612 Policy);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000613 }
John McCall7c2342d2010-03-10 11:27:22 +0000614
615 if (!InnerString.empty()) {
616 Buffer += ' ';
617 Buffer += InnerString;
618 }
619
620 std::swap(Buffer, InnerString);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000621}
622
John McCall49f4e1c2010-12-10 11:01:00 +0000623void TypePrinter::printRecord(const RecordType *T, std::string &S) {
624 printTag(T->getDecl(), S);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000625}
626
John McCall49f4e1c2010-12-10 11:01:00 +0000627void TypePrinter::printEnum(const EnumType *T, std::string &S) {
628 printTag(T->getDecl(), S);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000629}
630
John McCall49f4e1c2010-12-10 11:01:00 +0000631void TypePrinter::printTemplateTypeParm(const TemplateTypeParmType *T,
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000632 std::string &S) {
633 if (!S.empty()) // Prefix the basic type, e.g. 'parmname X'.
634 S = ' ' + S;
Douglas Gregorefed5c82010-06-16 15:23:05 +0000635
636 if (!T->getName())
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000637 S = "type-parameter-" + llvm::utostr_32(T->getDepth()) + '-' +
638 llvm::utostr_32(T->getIndex()) + S;
Douglas Gregorefed5c82010-06-16 15:23:05 +0000639 else
640 S = T->getName()->getName().str() + S;
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000641}
642
John McCall49f4e1c2010-12-10 11:01:00 +0000643void TypePrinter::printSubstTemplateTypeParm(const SubstTemplateTypeParmType *T,
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000644 std::string &S) {
John McCall49f4e1c2010-12-10 11:01:00 +0000645 print(T->getReplacementType(), S);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000646}
647
Douglas Gregorc3069d62011-01-14 02:55:32 +0000648void TypePrinter::printSubstTemplateTypeParmPack(
649 const SubstTemplateTypeParmPackType *T,
650 std::string &S) {
651 printTemplateTypeParm(T->getReplacedParameter(), S);
652}
653
John McCall49f4e1c2010-12-10 11:01:00 +0000654void TypePrinter::printTemplateSpecialization(
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000655 const TemplateSpecializationType *T,
656 std::string &S) {
657 std::string SpecString;
658
659 {
660 llvm::raw_string_ostream OS(SpecString);
661 T->getTemplateName().print(OS, Policy);
662 }
663
664 SpecString += TemplateSpecializationType::PrintTemplateArgumentList(
665 T->getArgs(),
666 T->getNumArgs(),
667 Policy);
668 if (S.empty())
669 S.swap(SpecString);
670 else
671 S = SpecString + ' ' + S;
672}
673
John McCall49f4e1c2010-12-10 11:01:00 +0000674void TypePrinter::printInjectedClassName(const InjectedClassNameType *T,
John McCall3cb0ebd2010-03-10 03:28:59 +0000675 std::string &S) {
John McCall49f4e1c2010-12-10 11:01:00 +0000676 printTemplateSpecialization(T->getInjectedTST(), S);
John McCall3cb0ebd2010-03-10 03:28:59 +0000677}
678
John McCall49f4e1c2010-12-10 11:01:00 +0000679void TypePrinter::printElaborated(const ElaboratedType *T, std::string &S) {
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000680 std::string MyString;
681
682 {
683 llvm::raw_string_ostream OS(MyString);
Abramo Bagnara465d41b2010-05-11 21:36:43 +0000684 OS << TypeWithKeyword::getKeywordName(T->getKeyword());
685 if (T->getKeyword() != ETK_None)
686 OS << " ";
687 NestedNameSpecifier* Qualifier = T->getQualifier();
688 if (Qualifier)
689 Qualifier->print(OS, Policy);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000690 }
691
692 std::string TypeStr;
693 PrintingPolicy InnerPolicy(Policy);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000694 InnerPolicy.SuppressScope = true;
John McCall49f4e1c2010-12-10 11:01:00 +0000695 TypePrinter(InnerPolicy).print(T->getNamedType(), TypeStr);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000696
697 MyString += TypeStr;
698 if (S.empty())
699 S.swap(MyString);
700 else
701 S = MyString + ' ' + S;
702}
703
Abramo Bagnara075f8f12010-12-10 16:29:40 +0000704void TypePrinter::printParen(const ParenType *T, std::string &S) {
705 if (!S.empty() && !isa<FunctionType>(T->getInnerType()))
706 S = '(' + S + ')';
707 print(T->getInnerType(), S);
708}
709
John McCall49f4e1c2010-12-10 11:01:00 +0000710void TypePrinter::printDependentName(const DependentNameType *T, std::string &S) {
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000711 std::string MyString;
712
713 {
714 llvm::raw_string_ostream OS(MyString);
Abramo Bagnara465d41b2010-05-11 21:36:43 +0000715 OS << TypeWithKeyword::getKeywordName(T->getKeyword());
716 if (T->getKeyword() != ETK_None)
717 OS << " ";
Douglas Gregor4a2023f2010-03-31 20:19:30 +0000718
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000719 T->getQualifier()->print(OS, Policy);
720
John McCall33500952010-06-11 00:33:02 +0000721 OS << T->getIdentifier()->getName();
722 }
723
724 if (S.empty())
725 S.swap(MyString);
726 else
727 S = MyString + ' ' + S;
728}
729
John McCall49f4e1c2010-12-10 11:01:00 +0000730void TypePrinter::printDependentTemplateSpecialization(
John McCall33500952010-06-11 00:33:02 +0000731 const DependentTemplateSpecializationType *T, std::string &S) {
732 std::string MyString;
733 {
734 llvm::raw_string_ostream OS(MyString);
735
736 OS << TypeWithKeyword::getKeywordName(T->getKeyword());
737 if (T->getKeyword() != ETK_None)
738 OS << " ";
739
740 T->getQualifier()->print(OS, Policy);
741 OS << T->getIdentifier()->getName();
742 OS << TemplateSpecializationType::PrintTemplateArgumentList(
743 T->getArgs(),
744 T->getNumArgs(),
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000745 Policy);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000746 }
747
748 if (S.empty())
749 S.swap(MyString);
750 else
751 S = MyString + ' ' + S;
752}
753
Douglas Gregor7536dd52010-12-20 02:24:11 +0000754void TypePrinter::printPackExpansion(const PackExpansionType *T,
755 std::string &S) {
756 print(T->getPattern(), S);
757 S += "...";
758}
759
John McCall9d156a72011-01-06 01:58:22 +0000760void TypePrinter::printAttributed(const AttributedType *T,
761 std::string &S) {
762 print(T->getModifiedType(), S);
763
764 // TODO: not all attributes are GCC-style attributes.
765 S += "__attribute__((";
766 switch (T->getAttrKind()) {
Francois Pichet170464b2011-01-07 03:17:31 +0000767 case AttributedType::attr_address_space:
John McCall9d156a72011-01-06 01:58:22 +0000768 S += "address_space(";
769 S += T->getEquivalentType().getAddressSpace();
770 S += ")";
771 break;
772
Francois Pichet170464b2011-01-07 03:17:31 +0000773 case AttributedType::attr_vector_size: {
John McCall9d156a72011-01-06 01:58:22 +0000774 S += "__vector_size__(";
775 if (const VectorType *vector =T->getEquivalentType()->getAs<VectorType>()) {
776 S += vector->getNumElements();
777 S += " * sizeof(";
778
779 std::string tmp;
780 print(vector->getElementType(), tmp);
781 S += tmp;
782 S += ")";
783 }
784 S += ")";
785 break;
786 }
787
Francois Pichet170464b2011-01-07 03:17:31 +0000788 case AttributedType::attr_neon_vector_type:
789 case AttributedType::attr_neon_polyvector_type: {
790 if (T->getAttrKind() == AttributedType::attr_neon_vector_type)
John McCall9d156a72011-01-06 01:58:22 +0000791 S += "neon_vector_type(";
792 else
793 S += "neon_polyvector_type(";
794 const VectorType *vector = T->getEquivalentType()->getAs<VectorType>();
795 S += llvm::utostr_32(vector->getNumElements());
796 S += ")";
797 break;
798 }
799
Francois Pichet170464b2011-01-07 03:17:31 +0000800 case AttributedType::attr_regparm: {
John McCall9d156a72011-01-06 01:58:22 +0000801 S += "regparm(";
802 QualType t = T->getEquivalentType();
803 while (!t->isFunctionType())
804 t = t->getPointeeType();
805 S += t->getAs<FunctionType>()->getRegParmType();
806 S += ")";
807 break;
808 }
809
Francois Pichet170464b2011-01-07 03:17:31 +0000810 case AttributedType::attr_objc_gc: {
John McCall9d156a72011-01-06 01:58:22 +0000811 S += "objc_gc(";
812
813 QualType tmp = T->getEquivalentType();
814 while (tmp.getObjCGCAttr() == Qualifiers::GCNone) {
815 QualType next = tmp->getPointeeType();
816 if (next == tmp) break;
817 tmp = next;
818 }
819
820 if (tmp.isObjCGCWeak())
821 S += "weak";
822 else
823 S += "strong";
824 S += ")";
825 break;
826 }
827
Francois Pichet3cd47e72011-01-07 02:58:13 +0000828 case AttributedType::attr_noreturn: S += "noreturn"; break;
829 case AttributedType::attr_cdecl: S += "cdecl"; break;
830 case AttributedType::attr_fastcall: S += "fastcall"; break;
831 case AttributedType::attr_stdcall: S += "stdcall"; break;
832 case AttributedType::attr_thiscall: S += "thiscall"; break;
833 case AttributedType::attr_pascal: S += "pascal"; break;
John McCall9d156a72011-01-06 01:58:22 +0000834 }
835 S += "))";
836}
837
John McCall49f4e1c2010-12-10 11:01:00 +0000838void TypePrinter::printObjCInterface(const ObjCInterfaceType *T,
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000839 std::string &S) {
840 if (!S.empty()) // Prefix the basic type, e.g. 'typedefname X'.
841 S = ' ' + S;
John McCallc12c5bb2010-05-15 11:32:37 +0000842
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000843 std::string ObjCQIString = T->getDecl()->getNameAsString();
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000844 S = ObjCQIString + S;
845}
846
John McCall49f4e1c2010-12-10 11:01:00 +0000847void TypePrinter::printObjCObject(const ObjCObjectType *T,
John McCallc12c5bb2010-05-15 11:32:37 +0000848 std::string &S) {
849 if (T->qual_empty())
John McCall49f4e1c2010-12-10 11:01:00 +0000850 return print(T->getBaseType(), S);
John McCallc12c5bb2010-05-15 11:32:37 +0000851
852 std::string tmp;
John McCall49f4e1c2010-12-10 11:01:00 +0000853 print(T->getBaseType(), tmp);
John McCallc12c5bb2010-05-15 11:32:37 +0000854 tmp += '<';
855 bool isFirst = true;
856 for (ObjCObjectType::qual_iterator
857 I = T->qual_begin(), E = T->qual_end(); I != E; ++I) {
858 if (isFirst)
859 isFirst = false;
860 else
861 tmp += ',';
862 tmp += (*I)->getNameAsString();
863 }
864 tmp += '>';
865
866 if (!S.empty()) {
867 tmp += ' ';
868 tmp += S;
869 }
870 std::swap(tmp, S);
871}
872
John McCall49f4e1c2010-12-10 11:01:00 +0000873void TypePrinter::printObjCObjectPointer(const ObjCObjectPointerType *T,
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000874 std::string &S) {
875 std::string ObjCQIString;
876
Chris Lattnerd7e52b82010-09-05 00:43:21 +0000877 T->getPointeeType().getLocalQualifiers().getAsStringInternal(ObjCQIString,
878 Policy);
879 if (!ObjCQIString.empty())
880 ObjCQIString += ' ';
881
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000882 if (T->isObjCIdType() || T->isObjCQualifiedIdType())
Chris Lattnerd7e52b82010-09-05 00:43:21 +0000883 ObjCQIString += "id";
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000884 else if (T->isObjCClassType() || T->isObjCQualifiedClassType())
Chris Lattnerd7e52b82010-09-05 00:43:21 +0000885 ObjCQIString += "Class";
Fariborz Jahanian13dcd002009-11-21 19:53:08 +0000886 else if (T->isObjCSelType())
Chris Lattnerd7e52b82010-09-05 00:43:21 +0000887 ObjCQIString += "SEL";
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000888 else
Chris Lattnerd7e52b82010-09-05 00:43:21 +0000889 ObjCQIString += T->getInterfaceDecl()->getNameAsString();
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000890
891 if (!T->qual_empty()) {
892 ObjCQIString += '<';
893 for (ObjCObjectPointerType::qual_iterator I = T->qual_begin(),
894 E = T->qual_end();
895 I != E; ++I) {
896 ObjCQIString += (*I)->getNameAsString();
897 if (I+1 != E)
898 ObjCQIString += ',';
899 }
900 ObjCQIString += '>';
901 }
902
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000903 if (!T->isObjCIdType() && !T->isObjCQualifiedIdType())
904 ObjCQIString += " *"; // Don't forget the implicit pointer.
905 else if (!S.empty()) // Prefix the basic type, e.g. 'typedefname X'.
906 S = ' ' + S;
907
908 S = ObjCQIString + S;
909}
910
John McCalld5532b62009-11-23 01:53:49 +0000911std::string TemplateSpecializationType::
912 PrintTemplateArgumentList(const TemplateArgumentListInfo &Args,
913 const PrintingPolicy &Policy) {
914 return PrintTemplateArgumentList(Args.getArgumentArray(),
915 Args.size(),
916 Policy);
917}
918
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000919std::string
920TemplateSpecializationType::PrintTemplateArgumentList(
921 const TemplateArgument *Args,
922 unsigned NumArgs,
Douglas Gregordace95b2010-12-20 22:28:59 +0000923 const PrintingPolicy &Policy,
924 bool SkipBrackets) {
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000925 std::string SpecString;
Douglas Gregordace95b2010-12-20 22:28:59 +0000926 if (!SkipBrackets)
927 SpecString += '<';
928
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000929 for (unsigned Arg = 0; Arg < NumArgs; ++Arg) {
Douglas Gregordace95b2010-12-20 22:28:59 +0000930 if (SpecString.size() > !SkipBrackets)
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000931 SpecString += ", ";
932
933 // Print the argument into a string.
934 std::string ArgString;
Douglas Gregordace95b2010-12-20 22:28:59 +0000935 if (Args[Arg].getKind() == TemplateArgument::Pack) {
936 ArgString = PrintTemplateArgumentList(Args[Arg].pack_begin(),
937 Args[Arg].pack_size(),
938 Policy, true);
939 } else {
Douglas Gregor87dd6972010-12-20 16:52:59 +0000940 llvm::raw_string_ostream ArgOut(ArgString);
941 Args[Arg].print(Policy, ArgOut);
942 }
943
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000944 // If this is the first argument and its string representation
945 // begins with the global scope specifier ('::foo'), add a space
946 // to avoid printing the diagraph '<:'.
947 if (!Arg && !ArgString.empty() && ArgString[0] == ':')
948 SpecString += ' ';
949
950 SpecString += ArgString;
951 }
952
953 // If the last character of our string is '>', add another space to
954 // keep the two '>''s separate tokens. We don't *have* to do this in
955 // C++0x, but it's still good hygiene.
Francois Pichetb5bc7d02011-01-09 22:32:25 +0000956 if (!SpecString.empty() && SpecString[SpecString.size() - 1] == '>')
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000957 SpecString += ' ';
958
Douglas Gregordace95b2010-12-20 22:28:59 +0000959 if (!SkipBrackets)
960 SpecString += '>';
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000961
962 return SpecString;
963}
964
965// Sadly, repeat all that with TemplateArgLoc.
966std::string TemplateSpecializationType::
967PrintTemplateArgumentList(const TemplateArgumentLoc *Args, unsigned NumArgs,
968 const PrintingPolicy &Policy) {
969 std::string SpecString;
970 SpecString += '<';
971 for (unsigned Arg = 0; Arg < NumArgs; ++Arg) {
Douglas Gregordace95b2010-12-20 22:28:59 +0000972 if (SpecString.size() > 1)
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000973 SpecString += ", ";
974
975 // Print the argument into a string.
976 std::string ArgString;
Douglas Gregordace95b2010-12-20 22:28:59 +0000977 if (Args[Arg].getArgument().getKind() == TemplateArgument::Pack) {
978 ArgString = PrintTemplateArgumentList(
979 Args[Arg].getArgument().pack_begin(),
980 Args[Arg].getArgument().pack_size(),
981 Policy, true);
982 } else {
Douglas Gregor87dd6972010-12-20 16:52:59 +0000983 llvm::raw_string_ostream ArgOut(ArgString);
984 Args[Arg].getArgument().print(Policy, ArgOut);
985 }
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000986
987 // If this is the first argument and its string representation
988 // begins with the global scope specifier ('::foo'), add a space
989 // to avoid printing the diagraph '<:'.
990 if (!Arg && !ArgString.empty() && ArgString[0] == ':')
991 SpecString += ' ';
992
993 SpecString += ArgString;
994 }
995
996 // If the last character of our string is '>', add another space to
997 // keep the two '>''s separate tokens. We don't *have* to do this in
998 // C++0x, but it's still good hygiene.
999 if (SpecString[SpecString.size() - 1] == '>')
1000 SpecString += ' ';
1001
1002 SpecString += '>';
1003
1004 return SpecString;
1005}
1006
1007void QualType::dump(const char *msg) const {
1008 std::string R = "identifier";
1009 LangOptions LO;
1010 getAsStringInternal(R, PrintingPolicy(LO));
1011 if (msg)
Daniel Dunbare7cb7e42009-12-03 09:14:02 +00001012 llvm::errs() << msg << ": ";
1013 llvm::errs() << R << "\n";
Douglas Gregorfee8a3c2009-11-10 00:39:07 +00001014}
1015void QualType::dump() const {
1016 dump("");
1017}
1018
1019void Type::dump() const {
1020 QualType(this, 0).dump();
1021}
1022
1023std::string Qualifiers::getAsString() const {
1024 LangOptions LO;
1025 return getAsString(PrintingPolicy(LO));
1026}
1027
1028// Appends qualifiers to the given string, separated by spaces. Will
1029// prefix a space if the string is non-empty. Will not append a final
1030// space.
1031void Qualifiers::getAsStringInternal(std::string &S,
1032 const PrintingPolicy&) const {
1033 AppendTypeQualList(S, getCVRQualifiers());
1034 if (unsigned AddressSpace = getAddressSpace()) {
1035 if (!S.empty()) S += ' ';
1036 S += "__attribute__((address_space(";
1037 S += llvm::utostr_32(AddressSpace);
1038 S += ")))";
1039 }
1040 if (Qualifiers::GC GCAttrType = getObjCGCAttr()) {
1041 if (!S.empty()) S += ' ';
1042 S += "__attribute__((objc_gc(";
1043 if (GCAttrType == Qualifiers::Weak)
1044 S += "weak";
1045 else
1046 S += "strong";
1047 S += ")))";
1048 }
1049}
1050
John McCall49f4e1c2010-12-10 11:01:00 +00001051std::string QualType::getAsString(const Type *ty, Qualifiers qs) {
1052 std::string buffer;
1053 LangOptions options;
1054 getAsStringInternal(ty, qs, buffer, PrintingPolicy(options));
1055 return buffer;
Douglas Gregorfee8a3c2009-11-10 00:39:07 +00001056}
1057
John McCall49f4e1c2010-12-10 11:01:00 +00001058void QualType::getAsStringInternal(const Type *ty, Qualifiers qs,
1059 std::string &buffer,
1060 const PrintingPolicy &policy) {
1061 TypePrinter(policy).print(ty, qs, buffer);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +00001062}