blob: c0ce1f25bf578489e9d77fcd270241407000842a [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.
Chris Lattner66cf2d12010-09-05 00:07:29 +000080 bool CanPrefixQualifiers =
Chris Lattner219b9e42010-09-05 00:22:25 +000081 isa<BuiltinType>(T) || isa<TypedefType>(T) || isa<TagType>(T) ||
Chris Lattner78643b02010-09-05 00:36:44 +000082 isa<ComplexType>(T) || isa<TemplateSpecializationType>(T) ||
83 isa<ObjCObjectType>(T) || isa<ObjCInterfaceType>(T) ||
84 T->isObjCIdType() || T->isObjCQualifiedIdType();
Chris Lattner58f9e132010-09-05 00:04:01 +000085
86 if (!CanPrefixQualifiers && !Quals.empty()) {
John McCall49f4e1c2010-12-10 11:01:00 +000087 std::string qualsBuffer;
88 Quals.getAsStringInternal(qualsBuffer, Policy);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +000089
John McCall49f4e1c2010-12-10 11:01:00 +000090 if (!buffer.empty()) {
91 qualsBuffer += ' ';
92 qualsBuffer += buffer;
Douglas Gregorfee8a3c2009-11-10 00:39:07 +000093 }
John McCall49f4e1c2010-12-10 11:01:00 +000094 std::swap(buffer, qualsBuffer);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +000095 }
96
97 switch (T->getTypeClass()) {
98#define ABSTRACT_TYPE(CLASS, PARENT)
John McCall49f4e1c2010-12-10 11:01:00 +000099#define TYPE(CLASS, PARENT) case Type::CLASS: \
100 print##CLASS(cast<CLASS##Type>(T), buffer); \
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000101 break;
102#include "clang/AST/TypeNodes.def"
103 }
Chris Lattner58f9e132010-09-05 00:04:01 +0000104
105 // If we're adding the qualifiers as a prefix, do it now.
106 if (CanPrefixQualifiers && !Quals.empty()) {
John McCall49f4e1c2010-12-10 11:01:00 +0000107 std::string qualsBuffer;
108 Quals.getAsStringInternal(qualsBuffer, Policy);
Chris Lattner58f9e132010-09-05 00:04:01 +0000109
John McCall49f4e1c2010-12-10 11:01:00 +0000110 if (!buffer.empty()) {
111 qualsBuffer += ' ';
112 qualsBuffer += buffer;
Chris Lattner58f9e132010-09-05 00:04:01 +0000113 }
John McCall49f4e1c2010-12-10 11:01:00 +0000114 std::swap(buffer, qualsBuffer);
Chris Lattner58f9e132010-09-05 00:04:01 +0000115 }
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000116}
117
John McCall49f4e1c2010-12-10 11:01:00 +0000118void TypePrinter::printBuiltin(const BuiltinType *T, std::string &S) {
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000119 if (S.empty()) {
120 S = T->getName(Policy.LangOpts);
121 } else {
122 // Prefix the basic type, e.g. 'int X'.
Chris Lattner59742de2010-09-04 23:43:40 +0000123 S = ' ' + S;
124 S = T->getName(Policy.LangOpts) + S;
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000125 }
126}
127
John McCall49f4e1c2010-12-10 11:01:00 +0000128void TypePrinter::printComplex(const ComplexType *T, std::string &S) {
129 print(T->getElementType(), S);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000130 S = "_Complex " + S;
131}
132
John McCall49f4e1c2010-12-10 11:01:00 +0000133void TypePrinter::printPointer(const PointerType *T, std::string &S) {
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000134 S = '*' + S;
135
136 // Handle things like 'int (*A)[4];' correctly.
137 // FIXME: this should include vectors, but vectors use attributes I guess.
138 if (isa<ArrayType>(T->getPointeeType()))
139 S = '(' + S + ')';
140
John McCall49f4e1c2010-12-10 11:01:00 +0000141 print(T->getPointeeType(), S);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000142}
143
John McCall49f4e1c2010-12-10 11:01:00 +0000144void TypePrinter::printBlockPointer(const BlockPointerType *T, std::string &S) {
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000145 S = '^' + S;
John McCall49f4e1c2010-12-10 11:01:00 +0000146 print(T->getPointeeType(), S);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000147}
148
John McCall49f4e1c2010-12-10 11:01:00 +0000149void TypePrinter::printLValueReference(const LValueReferenceType *T,
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000150 std::string &S) {
151 S = '&' + S;
152
153 // Handle things like 'int (&A)[4];' correctly.
154 // FIXME: this should include vectors, but vectors use attributes I guess.
155 if (isa<ArrayType>(T->getPointeeTypeAsWritten()))
156 S = '(' + S + ')';
157
John McCall49f4e1c2010-12-10 11:01:00 +0000158 print(T->getPointeeTypeAsWritten(), S);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000159}
160
John McCall49f4e1c2010-12-10 11:01:00 +0000161void TypePrinter::printRValueReference(const RValueReferenceType *T,
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000162 std::string &S) {
163 S = "&&" + S;
164
165 // Handle things like 'int (&&A)[4];' correctly.
166 // FIXME: this should include vectors, but vectors use attributes I guess.
167 if (isa<ArrayType>(T->getPointeeTypeAsWritten()))
168 S = '(' + S + ')';
169
John McCall49f4e1c2010-12-10 11:01:00 +0000170 print(T->getPointeeTypeAsWritten(), S);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000171}
172
John McCall49f4e1c2010-12-10 11:01:00 +0000173void TypePrinter::printMemberPointer(const MemberPointerType *T,
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000174 std::string &S) {
175 std::string C;
John McCall49f4e1c2010-12-10 11:01:00 +0000176 print(QualType(T->getClass(), 0), C);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000177 C += "::*";
178 S = C + S;
179
180 // Handle things like 'int (Cls::*A)[4];' correctly.
181 // FIXME: this should include vectors, but vectors use attributes I guess.
182 if (isa<ArrayType>(T->getPointeeType()))
183 S = '(' + S + ')';
184
John McCall49f4e1c2010-12-10 11:01:00 +0000185 print(T->getPointeeType(), S);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000186}
187
John McCall49f4e1c2010-12-10 11:01:00 +0000188void TypePrinter::printConstantArray(const ConstantArrayType *T,
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000189 std::string &S) {
190 S += '[';
191 S += llvm::utostr(T->getSize().getZExtValue());
192 S += ']';
193
John McCall49f4e1c2010-12-10 11:01:00 +0000194 print(T->getElementType(), S);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000195}
196
John McCall49f4e1c2010-12-10 11:01:00 +0000197void TypePrinter::printIncompleteArray(const IncompleteArrayType *T,
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000198 std::string &S) {
199 S += "[]";
John McCall49f4e1c2010-12-10 11:01:00 +0000200 print(T->getElementType(), S);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000201}
202
John McCall49f4e1c2010-12-10 11:01:00 +0000203void TypePrinter::printVariableArray(const VariableArrayType *T,
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000204 std::string &S) {
205 S += '[';
206
207 if (T->getIndexTypeQualifiers().hasQualifiers()) {
208 AppendTypeQualList(S, T->getIndexTypeCVRQualifiers());
209 S += ' ';
210 }
211
212 if (T->getSizeModifier() == VariableArrayType::Static)
213 S += "static";
214 else if (T->getSizeModifier() == VariableArrayType::Star)
215 S += '*';
216
217 if (T->getSizeExpr()) {
218 std::string SStr;
219 llvm::raw_string_ostream s(SStr);
220 T->getSizeExpr()->printPretty(s, 0, Policy);
221 S += s.str();
222 }
223 S += ']';
224
John McCall49f4e1c2010-12-10 11:01:00 +0000225 print(T->getElementType(), S);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000226}
227
John McCall49f4e1c2010-12-10 11:01:00 +0000228void TypePrinter::printDependentSizedArray(const DependentSizedArrayType *T,
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000229 std::string &S) {
230 S += '[';
231
232 if (T->getSizeExpr()) {
233 std::string SStr;
234 llvm::raw_string_ostream s(SStr);
235 T->getSizeExpr()->printPretty(s, 0, Policy);
236 S += s.str();
237 }
238 S += ']';
239
John McCall49f4e1c2010-12-10 11:01:00 +0000240 print(T->getElementType(), S);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000241}
242
John McCall49f4e1c2010-12-10 11:01:00 +0000243void TypePrinter::printDependentSizedExtVector(
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000244 const DependentSizedExtVectorType *T,
245 std::string &S) {
John McCall49f4e1c2010-12-10 11:01:00 +0000246 print(T->getElementType(), S);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000247
248 S += " __attribute__((ext_vector_type(";
249 if (T->getSizeExpr()) {
250 std::string SStr;
251 llvm::raw_string_ostream s(SStr);
252 T->getSizeExpr()->printPretty(s, 0, Policy);
253 S += s.str();
254 }
255 S += ")))";
256}
257
John McCall49f4e1c2010-12-10 11:01:00 +0000258void TypePrinter::printVector(const VectorType *T, std::string &S) {
Bob Wilsonec33cbe2010-11-16 00:32:26 +0000259 switch (T->getVectorKind()) {
260 case VectorType::AltiVecPixel:
261 S = "__vector __pixel " + S;
262 break;
263 case VectorType::AltiVecBool:
John McCall49f4e1c2010-12-10 11:01:00 +0000264 print(T->getElementType(), S);
Bob Wilsonec33cbe2010-11-16 00:32:26 +0000265 S = "__vector __bool " + S;
266 break;
267 case VectorType::AltiVecVector:
John McCall49f4e1c2010-12-10 11:01:00 +0000268 print(T->getElementType(), S);
Bob Wilsonec33cbe2010-11-16 00:32:26 +0000269 S = "__vector " + S;
270 break;
271 case VectorType::NeonVector:
John McCall49f4e1c2010-12-10 11:01:00 +0000272 print(T->getElementType(), S);
Bob Wilsonec33cbe2010-11-16 00:32:26 +0000273 S = ("__attribute__((neon_vector_type(" +
274 llvm::utostr_32(T->getNumElements()) + "))) " + S);
275 break;
276 case VectorType::NeonPolyVector:
John McCall49f4e1c2010-12-10 11:01:00 +0000277 print(T->getElementType(), S);
Bob Wilsonec33cbe2010-11-16 00:32:26 +0000278 S = ("__attribute__((neon_polyvector_type(" +
279 llvm::utostr_32(T->getNumElements()) + "))) " + S);
280 break;
281 case VectorType::GenericVector: {
John Thompson82287d12010-02-05 00:12:22 +0000282 // FIXME: We prefer to print the size directly here, but have no way
283 // to get the size of the type.
John McCall49f4e1c2010-12-10 11:01:00 +0000284 print(T->getElementType(), S);
John Thompson82287d12010-02-05 00:12:22 +0000285 std::string V = "__attribute__((__vector_size__(";
286 V += llvm::utostr_32(T->getNumElements()); // convert back to bytes.
287 std::string ET;
John McCall49f4e1c2010-12-10 11:01:00 +0000288 print(T->getElementType(), ET);
John Thompson82287d12010-02-05 00:12:22 +0000289 V += " * sizeof(" + ET + ")))) ";
290 S = V + S;
Bob Wilsonec33cbe2010-11-16 00:32:26 +0000291 break;
292 }
John Thompson82287d12010-02-05 00:12:22 +0000293 }
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000294}
295
John McCall49f4e1c2010-12-10 11:01:00 +0000296void TypePrinter::printExtVector(const ExtVectorType *T, std::string &S) {
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000297 S += " __attribute__((ext_vector_type(";
298 S += llvm::utostr_32(T->getNumElements());
299 S += ")))";
John McCall49f4e1c2010-12-10 11:01:00 +0000300 print(T->getElementType(), S);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000301}
302
John McCall49f4e1c2010-12-10 11:01:00 +0000303void TypePrinter::printFunctionProto(const FunctionProtoType *T,
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000304 std::string &S) {
305 // If needed for precedence reasons, wrap the inner part in grouping parens.
306 if (!S.empty())
307 S = "(" + S + ")";
308
309 S += "(";
310 std::string Tmp;
311 PrintingPolicy ParamPolicy(Policy);
312 ParamPolicy.SuppressSpecifiers = false;
313 for (unsigned i = 0, e = T->getNumArgs(); i != e; ++i) {
314 if (i) S += ", ";
John McCall49f4e1c2010-12-10 11:01:00 +0000315 print(T->getArgType(i), Tmp);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000316 S += Tmp;
317 Tmp.clear();
318 }
319
320 if (T->isVariadic()) {
321 if (T->getNumArgs())
322 S += ", ";
323 S += "...";
324 } else if (T->getNumArgs() == 0 && !Policy.LangOpts.CPlusPlus) {
325 // Do not emit int() if we have a proto, emit 'int(void)'.
326 S += "void";
327 }
328
329 S += ")";
Douglas Gregor0ae7b3f2009-12-08 17:45:32 +0000330
Rafael Espindola264ba482010-03-30 20:24:48 +0000331 FunctionType::ExtInfo Info = T->getExtInfo();
332 switch(Info.getCC()) {
John McCallf82b4e82010-02-04 05:44:44 +0000333 case CC_Default:
334 default: break;
335 case CC_C:
336 S += " __attribute__((cdecl))";
337 break;
338 case CC_X86StdCall:
339 S += " __attribute__((stdcall))";
340 break;
341 case CC_X86FastCall:
342 S += " __attribute__((fastcall))";
343 break;
Douglas Gregorf813a2c2010-05-18 16:57:00 +0000344 case CC_X86ThisCall:
345 S += " __attribute__((thiscall))";
346 break;
Dawn Perchik52fc3142010-09-03 01:29:35 +0000347 case CC_X86Pascal:
348 S += " __attribute__((pascal))";
349 break;
John McCallf82b4e82010-02-04 05:44:44 +0000350 }
Rafael Espindola264ba482010-03-30 20:24:48 +0000351 if (Info.getNoReturn())
Douglas Gregor48026d22010-01-11 18:40:55 +0000352 S += " __attribute__((noreturn))";
Rafael Espindola425ef722010-03-30 22:15:11 +0000353 if (Info.getRegParm())
354 S += " __attribute__((regparm (" +
355 llvm::utostr_32(Info.getRegParm()) + ")))";
Douglas Gregor48026d22010-01-11 18:40:55 +0000356
Douglas Gregorc938c162011-01-26 05:01:58 +0000357 AppendTypeQualList(S, T->getTypeQuals());
358
359 switch (T->getRefQualifier()) {
360 case RQ_None:
361 break;
362
363 case RQ_LValue:
364 S += " &";
365 break;
366
367 case RQ_RValue:
368 S += " &&";
369 break;
370 }
371
Douglas Gregor0ae7b3f2009-12-08 17:45:32 +0000372 if (T->hasExceptionSpec()) {
373 S += " throw(";
374 if (T->hasAnyExceptionSpec())
375 S += "...";
376 else
377 for (unsigned I = 0, N = T->getNumExceptions(); I != N; ++I) {
378 if (I)
379 S += ", ";
380
381 std::string ExceptionType;
John McCall49f4e1c2010-12-10 11:01:00 +0000382 print(T->getExceptionType(I), ExceptionType);
Douglas Gregor0ae7b3f2009-12-08 17:45:32 +0000383 S += ExceptionType;
384 }
385 S += ")";
386 }
387
John McCall49f4e1c2010-12-10 11:01:00 +0000388 print(T->getResultType(), S);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000389}
390
John McCall49f4e1c2010-12-10 11:01:00 +0000391void TypePrinter::printFunctionNoProto(const FunctionNoProtoType *T,
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000392 std::string &S) {
393 // If needed for precedence reasons, wrap the inner part in grouping parens.
394 if (!S.empty())
395 S = "(" + S + ")";
396
397 S += "()";
398 if (T->getNoReturnAttr())
399 S += " __attribute__((noreturn))";
John McCall49f4e1c2010-12-10 11:01:00 +0000400 print(T->getResultType(), S);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000401}
402
John McCall49f4e1c2010-12-10 11:01:00 +0000403static void printTypeSpec(const NamedDecl *D, std::string &S) {
John McCall3cb0ebd2010-03-10 03:28:59 +0000404 IdentifierInfo *II = D->getIdentifier();
John McCalled976492009-12-04 22:46:56 +0000405 if (S.empty())
406 S = II->getName().str();
407 else
408 S = II->getName().str() + ' ' + S;
409}
410
John McCall49f4e1c2010-12-10 11:01:00 +0000411void TypePrinter::printUnresolvedUsing(const UnresolvedUsingType *T,
John McCall3cb0ebd2010-03-10 03:28:59 +0000412 std::string &S) {
John McCall49f4e1c2010-12-10 11:01:00 +0000413 printTypeSpec(T->getDecl(), S);
John McCall3cb0ebd2010-03-10 03:28:59 +0000414}
415
John McCall49f4e1c2010-12-10 11:01:00 +0000416void TypePrinter::printTypedef(const TypedefType *T, std::string &S) {
417 printTypeSpec(T->getDecl(), S);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000418}
419
John McCall49f4e1c2010-12-10 11:01:00 +0000420void TypePrinter::printTypeOfExpr(const TypeOfExprType *T, std::string &S) {
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000421 if (!S.empty()) // Prefix the basic type, e.g. 'typeof(e) X'.
422 S = ' ' + S;
423 std::string Str;
424 llvm::raw_string_ostream s(Str);
425 T->getUnderlyingExpr()->printPretty(s, 0, Policy);
426 S = "typeof " + s.str() + S;
427}
428
John McCall49f4e1c2010-12-10 11:01:00 +0000429void TypePrinter::printTypeOf(const TypeOfType *T, std::string &S) {
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000430 if (!S.empty()) // Prefix the basic type, e.g. 'typeof(t) X'.
431 S = ' ' + S;
432 std::string Tmp;
John McCall49f4e1c2010-12-10 11:01:00 +0000433 print(T->getUnderlyingType(), Tmp);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000434 S = "typeof(" + Tmp + ")" + S;
435}
436
John McCall49f4e1c2010-12-10 11:01:00 +0000437void TypePrinter::printDecltype(const DecltypeType *T, std::string &S) {
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000438 if (!S.empty()) // Prefix the basic type, e.g. 'decltype(t) X'.
439 S = ' ' + S;
440 std::string Str;
441 llvm::raw_string_ostream s(Str);
442 T->getUnderlyingExpr()->printPretty(s, 0, Policy);
443 S = "decltype(" + s.str() + ")" + S;
444}
445
John McCall7c2342d2010-03-10 11:27:22 +0000446/// Appends the given scope to the end of a string.
447void TypePrinter::AppendScope(DeclContext *DC, std::string &Buffer) {
448 if (DC->isTranslationUnit()) return;
449 AppendScope(DC->getParent(), Buffer);
450
451 unsigned OldSize = Buffer.size();
452
453 if (NamespaceDecl *NS = dyn_cast<NamespaceDecl>(DC)) {
454 if (NS->getIdentifier())
455 Buffer += NS->getNameAsString();
456 else
457 Buffer += "<anonymous>";
458 } else if (ClassTemplateSpecializationDecl *Spec
459 = dyn_cast<ClassTemplateSpecializationDecl>(DC)) {
460 const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs();
461 std::string TemplateArgsStr
462 = TemplateSpecializationType::PrintTemplateArgumentList(
Douglas Gregor910f8002010-11-07 23:05:16 +0000463 TemplateArgs.data(),
464 TemplateArgs.size(),
John McCall7c2342d2010-03-10 11:27:22 +0000465 Policy);
466 Buffer += Spec->getIdentifier()->getName();
467 Buffer += TemplateArgsStr;
468 } else if (TagDecl *Tag = dyn_cast<TagDecl>(DC)) {
469 if (TypedefDecl *Typedef = Tag->getTypedefForAnonDecl())
470 Buffer += Typedef->getIdentifier()->getName();
471 else if (Tag->getIdentifier())
472 Buffer += Tag->getIdentifier()->getName();
473 }
474
475 if (Buffer.size() != OldSize)
476 Buffer += "::";
477}
478
John McCall49f4e1c2010-12-10 11:01:00 +0000479void TypePrinter::printTag(TagDecl *D, std::string &InnerString) {
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000480 if (Policy.SuppressTag)
481 return;
John McCall7c2342d2010-03-10 11:27:22 +0000482
483 std::string Buffer;
John McCall73061d02010-03-19 07:56:44 +0000484 bool HasKindDecoration = false;
John McCall7c2342d2010-03-10 11:27:22 +0000485
486 // We don't print tags unless this is an elaborated type.
487 // In C, we just assume every RecordType is an elaborated type.
488 if (!Policy.LangOpts.CPlusPlus && !D->getTypedefForAnonDecl()) {
John McCall73061d02010-03-19 07:56:44 +0000489 HasKindDecoration = true;
John McCall7c2342d2010-03-10 11:27:22 +0000490 Buffer += D->getKindName();
491 Buffer += ' ';
492 }
493
Chris Lattnerc7acc662010-08-28 16:26:18 +0000494 // Compute the full nested-name-specifier for this type.
495 // In C, this will always be empty except when the type
496 // being printed is anonymous within other Record.
John McCall7c2342d2010-03-10 11:27:22 +0000497 if (!Policy.SuppressScope)
John McCall7c2342d2010-03-10 11:27:22 +0000498 AppendScope(D->getDeclContext(), Buffer);
499
John McCall3cb0ebd2010-03-10 03:28:59 +0000500 if (const IdentifierInfo *II = D->getIdentifier())
John McCall73061d02010-03-19 07:56:44 +0000501 Buffer += II->getNameStart();
John McCall3cb0ebd2010-03-10 03:28:59 +0000502 else if (TypedefDecl *Typedef = D->getTypedefForAnonDecl()) {
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000503 assert(Typedef->getIdentifier() && "Typedef without identifier?");
John McCall73061d02010-03-19 07:56:44 +0000504 Buffer += Typedef->getIdentifier()->getNameStart();
505 } else {
506 // Make an unambiguous representation for anonymous types, e.g.
507 // <anonymous enum at /usr/include/string.h:120:9>
508 llvm::raw_string_ostream OS(Buffer);
509 OS << "<anonymous";
510
Douglas Gregor84139d62010-04-05 21:25:31 +0000511 if (Policy.AnonymousTagLocations) {
512 // Suppress the redundant tag keyword if we just printed one.
513 // We don't have to worry about ElaboratedTypes here because you can't
514 // refer to an anonymous type with one.
515 if (!HasKindDecoration)
516 OS << " " << D->getKindName();
John McCall73061d02010-03-19 07:56:44 +0000517
Douglas Gregorcb7b1e12010-11-12 07:15:47 +0000518 PresumedLoc PLoc = D->getASTContext().getSourceManager().getPresumedLoc(
Douglas Gregor16834e82010-05-28 21:47:04 +0000519 D->getLocation());
Douglas Gregorcb7b1e12010-11-12 07:15:47 +0000520 if (PLoc.isValid()) {
Douglas Gregor16834e82010-05-28 21:47:04 +0000521 OS << " at " << PLoc.getFilename()
522 << ':' << PLoc.getLine()
523 << ':' << PLoc.getColumn();
524 }
Douglas Gregor84139d62010-04-05 21:25:31 +0000525 }
526
527 OS << '>';
John McCall73061d02010-03-19 07:56:44 +0000528 }
John McCall7c2342d2010-03-10 11:27:22 +0000529
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000530 // If this is a class template specialization, print the template
531 // arguments.
532 if (ClassTemplateSpecializationDecl *Spec
John McCall7c2342d2010-03-10 11:27:22 +0000533 = dyn_cast<ClassTemplateSpecializationDecl>(D)) {
John McCall3cb0ebd2010-03-10 03:28:59 +0000534 const TemplateArgument *Args;
535 unsigned NumArgs;
536 if (TypeSourceInfo *TAW = Spec->getTypeAsWritten()) {
537 const TemplateSpecializationType *TST =
538 cast<TemplateSpecializationType>(TAW->getType());
539 Args = TST->getArgs();
540 NumArgs = TST->getNumArgs();
541 } else {
542 const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs();
Douglas Gregor910f8002010-11-07 23:05:16 +0000543 Args = TemplateArgs.data();
544 NumArgs = TemplateArgs.size();
John McCall3cb0ebd2010-03-10 03:28:59 +0000545 }
John McCall7c2342d2010-03-10 11:27:22 +0000546 Buffer += TemplateSpecializationType::PrintTemplateArgumentList(Args,
547 NumArgs,
548 Policy);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000549 }
John McCall7c2342d2010-03-10 11:27:22 +0000550
551 if (!InnerString.empty()) {
552 Buffer += ' ';
553 Buffer += InnerString;
554 }
555
556 std::swap(Buffer, InnerString);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000557}
558
John McCall49f4e1c2010-12-10 11:01:00 +0000559void TypePrinter::printRecord(const RecordType *T, std::string &S) {
560 printTag(T->getDecl(), S);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000561}
562
John McCall49f4e1c2010-12-10 11:01:00 +0000563void TypePrinter::printEnum(const EnumType *T, std::string &S) {
564 printTag(T->getDecl(), S);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000565}
566
John McCall49f4e1c2010-12-10 11:01:00 +0000567void TypePrinter::printTemplateTypeParm(const TemplateTypeParmType *T,
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000568 std::string &S) {
569 if (!S.empty()) // Prefix the basic type, e.g. 'parmname X'.
570 S = ' ' + S;
Douglas Gregorefed5c82010-06-16 15:23:05 +0000571
572 if (!T->getName())
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000573 S = "type-parameter-" + llvm::utostr_32(T->getDepth()) + '-' +
574 llvm::utostr_32(T->getIndex()) + S;
Douglas Gregorefed5c82010-06-16 15:23:05 +0000575 else
576 S = T->getName()->getName().str() + S;
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000577}
578
John McCall49f4e1c2010-12-10 11:01:00 +0000579void TypePrinter::printSubstTemplateTypeParm(const SubstTemplateTypeParmType *T,
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000580 std::string &S) {
John McCall49f4e1c2010-12-10 11:01:00 +0000581 print(T->getReplacementType(), S);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000582}
583
Douglas Gregorc3069d62011-01-14 02:55:32 +0000584void TypePrinter::printSubstTemplateTypeParmPack(
585 const SubstTemplateTypeParmPackType *T,
586 std::string &S) {
587 printTemplateTypeParm(T->getReplacedParameter(), S);
588}
589
John McCall49f4e1c2010-12-10 11:01:00 +0000590void TypePrinter::printTemplateSpecialization(
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000591 const TemplateSpecializationType *T,
592 std::string &S) {
593 std::string SpecString;
594
595 {
596 llvm::raw_string_ostream OS(SpecString);
597 T->getTemplateName().print(OS, Policy);
598 }
599
600 SpecString += TemplateSpecializationType::PrintTemplateArgumentList(
601 T->getArgs(),
602 T->getNumArgs(),
603 Policy);
604 if (S.empty())
605 S.swap(SpecString);
606 else
607 S = SpecString + ' ' + S;
608}
609
John McCall49f4e1c2010-12-10 11:01:00 +0000610void TypePrinter::printInjectedClassName(const InjectedClassNameType *T,
John McCall3cb0ebd2010-03-10 03:28:59 +0000611 std::string &S) {
John McCall49f4e1c2010-12-10 11:01:00 +0000612 printTemplateSpecialization(T->getInjectedTST(), S);
John McCall3cb0ebd2010-03-10 03:28:59 +0000613}
614
John McCall49f4e1c2010-12-10 11:01:00 +0000615void TypePrinter::printElaborated(const ElaboratedType *T, std::string &S) {
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000616 std::string MyString;
617
618 {
619 llvm::raw_string_ostream OS(MyString);
Abramo Bagnara465d41b2010-05-11 21:36:43 +0000620 OS << TypeWithKeyword::getKeywordName(T->getKeyword());
621 if (T->getKeyword() != ETK_None)
622 OS << " ";
623 NestedNameSpecifier* Qualifier = T->getQualifier();
624 if (Qualifier)
625 Qualifier->print(OS, Policy);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000626 }
627
628 std::string TypeStr;
629 PrintingPolicy InnerPolicy(Policy);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000630 InnerPolicy.SuppressScope = true;
John McCall49f4e1c2010-12-10 11:01:00 +0000631 TypePrinter(InnerPolicy).print(T->getNamedType(), TypeStr);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000632
633 MyString += TypeStr;
634 if (S.empty())
635 S.swap(MyString);
636 else
637 S = MyString + ' ' + S;
638}
639
Abramo Bagnara075f8f12010-12-10 16:29:40 +0000640void TypePrinter::printParen(const ParenType *T, std::string &S) {
641 if (!S.empty() && !isa<FunctionType>(T->getInnerType()))
642 S = '(' + S + ')';
643 print(T->getInnerType(), S);
644}
645
John McCall49f4e1c2010-12-10 11:01:00 +0000646void TypePrinter::printDependentName(const DependentNameType *T, std::string &S) {
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000647 std::string MyString;
648
649 {
650 llvm::raw_string_ostream OS(MyString);
Abramo Bagnara465d41b2010-05-11 21:36:43 +0000651 OS << TypeWithKeyword::getKeywordName(T->getKeyword());
652 if (T->getKeyword() != ETK_None)
653 OS << " ";
Douglas Gregor4a2023f2010-03-31 20:19:30 +0000654
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000655 T->getQualifier()->print(OS, Policy);
656
John McCall33500952010-06-11 00:33:02 +0000657 OS << T->getIdentifier()->getName();
658 }
659
660 if (S.empty())
661 S.swap(MyString);
662 else
663 S = MyString + ' ' + S;
664}
665
John McCall49f4e1c2010-12-10 11:01:00 +0000666void TypePrinter::printDependentTemplateSpecialization(
John McCall33500952010-06-11 00:33:02 +0000667 const DependentTemplateSpecializationType *T, std::string &S) {
668 std::string MyString;
669 {
670 llvm::raw_string_ostream OS(MyString);
671
672 OS << TypeWithKeyword::getKeywordName(T->getKeyword());
673 if (T->getKeyword() != ETK_None)
674 OS << " ";
675
676 T->getQualifier()->print(OS, Policy);
677 OS << T->getIdentifier()->getName();
678 OS << TemplateSpecializationType::PrintTemplateArgumentList(
679 T->getArgs(),
680 T->getNumArgs(),
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000681 Policy);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000682 }
683
684 if (S.empty())
685 S.swap(MyString);
686 else
687 S = MyString + ' ' + S;
688}
689
Douglas Gregor7536dd52010-12-20 02:24:11 +0000690void TypePrinter::printPackExpansion(const PackExpansionType *T,
691 std::string &S) {
692 print(T->getPattern(), S);
693 S += "...";
694}
695
John McCall9d156a72011-01-06 01:58:22 +0000696void TypePrinter::printAttributed(const AttributedType *T,
697 std::string &S) {
698 print(T->getModifiedType(), S);
699
700 // TODO: not all attributes are GCC-style attributes.
701 S += "__attribute__((";
702 switch (T->getAttrKind()) {
Francois Pichet170464b2011-01-07 03:17:31 +0000703 case AttributedType::attr_address_space:
John McCall9d156a72011-01-06 01:58:22 +0000704 S += "address_space(";
705 S += T->getEquivalentType().getAddressSpace();
706 S += ")";
707 break;
708
Francois Pichet170464b2011-01-07 03:17:31 +0000709 case AttributedType::attr_vector_size: {
John McCall9d156a72011-01-06 01:58:22 +0000710 S += "__vector_size__(";
711 if (const VectorType *vector =T->getEquivalentType()->getAs<VectorType>()) {
712 S += vector->getNumElements();
713 S += " * sizeof(";
714
715 std::string tmp;
716 print(vector->getElementType(), tmp);
717 S += tmp;
718 S += ")";
719 }
720 S += ")";
721 break;
722 }
723
Francois Pichet170464b2011-01-07 03:17:31 +0000724 case AttributedType::attr_neon_vector_type:
725 case AttributedType::attr_neon_polyvector_type: {
726 if (T->getAttrKind() == AttributedType::attr_neon_vector_type)
John McCall9d156a72011-01-06 01:58:22 +0000727 S += "neon_vector_type(";
728 else
729 S += "neon_polyvector_type(";
730 const VectorType *vector = T->getEquivalentType()->getAs<VectorType>();
731 S += llvm::utostr_32(vector->getNumElements());
732 S += ")";
733 break;
734 }
735
Francois Pichet170464b2011-01-07 03:17:31 +0000736 case AttributedType::attr_regparm: {
John McCall9d156a72011-01-06 01:58:22 +0000737 S += "regparm(";
738 QualType t = T->getEquivalentType();
739 while (!t->isFunctionType())
740 t = t->getPointeeType();
741 S += t->getAs<FunctionType>()->getRegParmType();
742 S += ")";
743 break;
744 }
745
Francois Pichet170464b2011-01-07 03:17:31 +0000746 case AttributedType::attr_objc_gc: {
John McCall9d156a72011-01-06 01:58:22 +0000747 S += "objc_gc(";
748
749 QualType tmp = T->getEquivalentType();
750 while (tmp.getObjCGCAttr() == Qualifiers::GCNone) {
751 QualType next = tmp->getPointeeType();
752 if (next == tmp) break;
753 tmp = next;
754 }
755
756 if (tmp.isObjCGCWeak())
757 S += "weak";
758 else
759 S += "strong";
760 S += ")";
761 break;
762 }
763
Francois Pichet3cd47e72011-01-07 02:58:13 +0000764 case AttributedType::attr_noreturn: S += "noreturn"; break;
765 case AttributedType::attr_cdecl: S += "cdecl"; break;
766 case AttributedType::attr_fastcall: S += "fastcall"; break;
767 case AttributedType::attr_stdcall: S += "stdcall"; break;
768 case AttributedType::attr_thiscall: S += "thiscall"; break;
769 case AttributedType::attr_pascal: S += "pascal"; break;
John McCall9d156a72011-01-06 01:58:22 +0000770 }
771 S += "))";
772}
773
John McCall49f4e1c2010-12-10 11:01:00 +0000774void TypePrinter::printObjCInterface(const ObjCInterfaceType *T,
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000775 std::string &S) {
776 if (!S.empty()) // Prefix the basic type, e.g. 'typedefname X'.
777 S = ' ' + S;
John McCallc12c5bb2010-05-15 11:32:37 +0000778
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000779 std::string ObjCQIString = T->getDecl()->getNameAsString();
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000780 S = ObjCQIString + S;
781}
782
John McCall49f4e1c2010-12-10 11:01:00 +0000783void TypePrinter::printObjCObject(const ObjCObjectType *T,
John McCallc12c5bb2010-05-15 11:32:37 +0000784 std::string &S) {
785 if (T->qual_empty())
John McCall49f4e1c2010-12-10 11:01:00 +0000786 return print(T->getBaseType(), S);
John McCallc12c5bb2010-05-15 11:32:37 +0000787
788 std::string tmp;
John McCall49f4e1c2010-12-10 11:01:00 +0000789 print(T->getBaseType(), tmp);
John McCallc12c5bb2010-05-15 11:32:37 +0000790 tmp += '<';
791 bool isFirst = true;
792 for (ObjCObjectType::qual_iterator
793 I = T->qual_begin(), E = T->qual_end(); I != E; ++I) {
794 if (isFirst)
795 isFirst = false;
796 else
797 tmp += ',';
798 tmp += (*I)->getNameAsString();
799 }
800 tmp += '>';
801
802 if (!S.empty()) {
803 tmp += ' ';
804 tmp += S;
805 }
806 std::swap(tmp, S);
807}
808
John McCall49f4e1c2010-12-10 11:01:00 +0000809void TypePrinter::printObjCObjectPointer(const ObjCObjectPointerType *T,
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000810 std::string &S) {
811 std::string ObjCQIString;
812
Chris Lattnerd7e52b82010-09-05 00:43:21 +0000813 T->getPointeeType().getLocalQualifiers().getAsStringInternal(ObjCQIString,
814 Policy);
815 if (!ObjCQIString.empty())
816 ObjCQIString += ' ';
817
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000818 if (T->isObjCIdType() || T->isObjCQualifiedIdType())
Chris Lattnerd7e52b82010-09-05 00:43:21 +0000819 ObjCQIString += "id";
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000820 else if (T->isObjCClassType() || T->isObjCQualifiedClassType())
Chris Lattnerd7e52b82010-09-05 00:43:21 +0000821 ObjCQIString += "Class";
Fariborz Jahanian13dcd002009-11-21 19:53:08 +0000822 else if (T->isObjCSelType())
Chris Lattnerd7e52b82010-09-05 00:43:21 +0000823 ObjCQIString += "SEL";
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000824 else
Chris Lattnerd7e52b82010-09-05 00:43:21 +0000825 ObjCQIString += T->getInterfaceDecl()->getNameAsString();
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000826
827 if (!T->qual_empty()) {
828 ObjCQIString += '<';
829 for (ObjCObjectPointerType::qual_iterator I = T->qual_begin(),
830 E = T->qual_end();
831 I != E; ++I) {
832 ObjCQIString += (*I)->getNameAsString();
833 if (I+1 != E)
834 ObjCQIString += ',';
835 }
836 ObjCQIString += '>';
837 }
838
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000839 if (!T->isObjCIdType() && !T->isObjCQualifiedIdType())
840 ObjCQIString += " *"; // Don't forget the implicit pointer.
841 else if (!S.empty()) // Prefix the basic type, e.g. 'typedefname X'.
842 S = ' ' + S;
843
844 S = ObjCQIString + S;
845}
846
John McCalld5532b62009-11-23 01:53:49 +0000847std::string TemplateSpecializationType::
848 PrintTemplateArgumentList(const TemplateArgumentListInfo &Args,
849 const PrintingPolicy &Policy) {
850 return PrintTemplateArgumentList(Args.getArgumentArray(),
851 Args.size(),
852 Policy);
853}
854
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000855std::string
856TemplateSpecializationType::PrintTemplateArgumentList(
857 const TemplateArgument *Args,
858 unsigned NumArgs,
Douglas Gregordace95b2010-12-20 22:28:59 +0000859 const PrintingPolicy &Policy,
860 bool SkipBrackets) {
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000861 std::string SpecString;
Douglas Gregordace95b2010-12-20 22:28:59 +0000862 if (!SkipBrackets)
863 SpecString += '<';
864
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000865 for (unsigned Arg = 0; Arg < NumArgs; ++Arg) {
Douglas Gregordace95b2010-12-20 22:28:59 +0000866 if (SpecString.size() > !SkipBrackets)
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000867 SpecString += ", ";
868
869 // Print the argument into a string.
870 std::string ArgString;
Douglas Gregordace95b2010-12-20 22:28:59 +0000871 if (Args[Arg].getKind() == TemplateArgument::Pack) {
872 ArgString = PrintTemplateArgumentList(Args[Arg].pack_begin(),
873 Args[Arg].pack_size(),
874 Policy, true);
875 } else {
Douglas Gregor87dd6972010-12-20 16:52:59 +0000876 llvm::raw_string_ostream ArgOut(ArgString);
877 Args[Arg].print(Policy, ArgOut);
878 }
879
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000880 // If this is the first argument and its string representation
881 // begins with the global scope specifier ('::foo'), add a space
882 // to avoid printing the diagraph '<:'.
883 if (!Arg && !ArgString.empty() && ArgString[0] == ':')
884 SpecString += ' ';
885
886 SpecString += ArgString;
887 }
888
889 // If the last character of our string is '>', add another space to
890 // keep the two '>''s separate tokens. We don't *have* to do this in
891 // C++0x, but it's still good hygiene.
Francois Pichetb5bc7d02011-01-09 22:32:25 +0000892 if (!SpecString.empty() && SpecString[SpecString.size() - 1] == '>')
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000893 SpecString += ' ';
894
Douglas Gregordace95b2010-12-20 22:28:59 +0000895 if (!SkipBrackets)
896 SpecString += '>';
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000897
898 return SpecString;
899}
900
901// Sadly, repeat all that with TemplateArgLoc.
902std::string TemplateSpecializationType::
903PrintTemplateArgumentList(const TemplateArgumentLoc *Args, unsigned NumArgs,
904 const PrintingPolicy &Policy) {
905 std::string SpecString;
906 SpecString += '<';
907 for (unsigned Arg = 0; Arg < NumArgs; ++Arg) {
Douglas Gregordace95b2010-12-20 22:28:59 +0000908 if (SpecString.size() > 1)
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000909 SpecString += ", ";
910
911 // Print the argument into a string.
912 std::string ArgString;
Douglas Gregordace95b2010-12-20 22:28:59 +0000913 if (Args[Arg].getArgument().getKind() == TemplateArgument::Pack) {
914 ArgString = PrintTemplateArgumentList(
915 Args[Arg].getArgument().pack_begin(),
916 Args[Arg].getArgument().pack_size(),
917 Policy, true);
918 } else {
Douglas Gregor87dd6972010-12-20 16:52:59 +0000919 llvm::raw_string_ostream ArgOut(ArgString);
920 Args[Arg].getArgument().print(Policy, ArgOut);
921 }
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000922
923 // If this is the first argument and its string representation
924 // begins with the global scope specifier ('::foo'), add a space
925 // to avoid printing the diagraph '<:'.
926 if (!Arg && !ArgString.empty() && ArgString[0] == ':')
927 SpecString += ' ';
928
929 SpecString += ArgString;
930 }
931
932 // If the last character of our string is '>', add another space to
933 // keep the two '>''s separate tokens. We don't *have* to do this in
934 // C++0x, but it's still good hygiene.
935 if (SpecString[SpecString.size() - 1] == '>')
936 SpecString += ' ';
937
938 SpecString += '>';
939
940 return SpecString;
941}
942
943void QualType::dump(const char *msg) const {
944 std::string R = "identifier";
945 LangOptions LO;
946 getAsStringInternal(R, PrintingPolicy(LO));
947 if (msg)
Daniel Dunbare7cb7e42009-12-03 09:14:02 +0000948 llvm::errs() << msg << ": ";
949 llvm::errs() << R << "\n";
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000950}
951void QualType::dump() const {
952 dump("");
953}
954
955void Type::dump() const {
956 QualType(this, 0).dump();
957}
958
959std::string Qualifiers::getAsString() const {
960 LangOptions LO;
961 return getAsString(PrintingPolicy(LO));
962}
963
964// Appends qualifiers to the given string, separated by spaces. Will
965// prefix a space if the string is non-empty. Will not append a final
966// space.
967void Qualifiers::getAsStringInternal(std::string &S,
968 const PrintingPolicy&) const {
969 AppendTypeQualList(S, getCVRQualifiers());
970 if (unsigned AddressSpace = getAddressSpace()) {
971 if (!S.empty()) S += ' ';
972 S += "__attribute__((address_space(";
973 S += llvm::utostr_32(AddressSpace);
974 S += ")))";
975 }
976 if (Qualifiers::GC GCAttrType = getObjCGCAttr()) {
977 if (!S.empty()) S += ' ';
978 S += "__attribute__((objc_gc(";
979 if (GCAttrType == Qualifiers::Weak)
980 S += "weak";
981 else
982 S += "strong";
983 S += ")))";
984 }
985}
986
John McCall49f4e1c2010-12-10 11:01:00 +0000987std::string QualType::getAsString(const Type *ty, Qualifiers qs) {
988 std::string buffer;
989 LangOptions options;
990 getAsStringInternal(ty, qs, buffer, PrintingPolicy(options));
991 return buffer;
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000992}
993
John McCall49f4e1c2010-12-10 11:01:00 +0000994void QualType::getAsStringInternal(const Type *ty, Qualifiers qs,
995 std::string &buffer,
996 const PrintingPolicy &policy) {
997 TypePrinter(policy).print(ty, qs, buffer);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000998}