blob: ef9704ec8581795f67bd7c8cd564e81bc287edbf [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 Gregor0ae7b3f2009-12-08 17:45:32 +0000357 if (T->hasExceptionSpec()) {
358 S += " throw(";
359 if (T->hasAnyExceptionSpec())
360 S += "...";
361 else
362 for (unsigned I = 0, N = T->getNumExceptions(); I != N; ++I) {
363 if (I)
364 S += ", ";
365
366 std::string ExceptionType;
John McCall49f4e1c2010-12-10 11:01:00 +0000367 print(T->getExceptionType(I), ExceptionType);
Douglas Gregor0ae7b3f2009-12-08 17:45:32 +0000368 S += ExceptionType;
369 }
370 S += ")";
371 }
372
Douglas Gregor48026d22010-01-11 18:40:55 +0000373 AppendTypeQualList(S, T->getTypeQuals());
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000374
John McCall49f4e1c2010-12-10 11:01:00 +0000375 print(T->getResultType(), S);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000376}
377
John McCall49f4e1c2010-12-10 11:01:00 +0000378void TypePrinter::printFunctionNoProto(const FunctionNoProtoType *T,
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000379 std::string &S) {
380 // If needed for precedence reasons, wrap the inner part in grouping parens.
381 if (!S.empty())
382 S = "(" + S + ")";
383
384 S += "()";
385 if (T->getNoReturnAttr())
386 S += " __attribute__((noreturn))";
John McCall49f4e1c2010-12-10 11:01:00 +0000387 print(T->getResultType(), S);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000388}
389
John McCall49f4e1c2010-12-10 11:01:00 +0000390static void printTypeSpec(const NamedDecl *D, std::string &S) {
John McCall3cb0ebd2010-03-10 03:28:59 +0000391 IdentifierInfo *II = D->getIdentifier();
John McCalled976492009-12-04 22:46:56 +0000392 if (S.empty())
393 S = II->getName().str();
394 else
395 S = II->getName().str() + ' ' + S;
396}
397
John McCall49f4e1c2010-12-10 11:01:00 +0000398void TypePrinter::printUnresolvedUsing(const UnresolvedUsingType *T,
John McCall3cb0ebd2010-03-10 03:28:59 +0000399 std::string &S) {
John McCall49f4e1c2010-12-10 11:01:00 +0000400 printTypeSpec(T->getDecl(), S);
John McCall3cb0ebd2010-03-10 03:28:59 +0000401}
402
John McCall49f4e1c2010-12-10 11:01:00 +0000403void TypePrinter::printTypedef(const TypedefType *T, std::string &S) {
404 printTypeSpec(T->getDecl(), S);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000405}
406
John McCall49f4e1c2010-12-10 11:01:00 +0000407void TypePrinter::printTypeOfExpr(const TypeOfExprType *T, std::string &S) {
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000408 if (!S.empty()) // Prefix the basic type, e.g. 'typeof(e) X'.
409 S = ' ' + S;
410 std::string Str;
411 llvm::raw_string_ostream s(Str);
412 T->getUnderlyingExpr()->printPretty(s, 0, Policy);
413 S = "typeof " + s.str() + S;
414}
415
John McCall49f4e1c2010-12-10 11:01:00 +0000416void TypePrinter::printTypeOf(const TypeOfType *T, std::string &S) {
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000417 if (!S.empty()) // Prefix the basic type, e.g. 'typeof(t) X'.
418 S = ' ' + S;
419 std::string Tmp;
John McCall49f4e1c2010-12-10 11:01:00 +0000420 print(T->getUnderlyingType(), Tmp);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000421 S = "typeof(" + Tmp + ")" + S;
422}
423
John McCall49f4e1c2010-12-10 11:01:00 +0000424void TypePrinter::printDecltype(const DecltypeType *T, std::string &S) {
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000425 if (!S.empty()) // Prefix the basic type, e.g. 'decltype(t) X'.
426 S = ' ' + S;
427 std::string Str;
428 llvm::raw_string_ostream s(Str);
429 T->getUnderlyingExpr()->printPretty(s, 0, Policy);
430 S = "decltype(" + s.str() + ")" + S;
431}
432
John McCall7c2342d2010-03-10 11:27:22 +0000433/// Appends the given scope to the end of a string.
434void TypePrinter::AppendScope(DeclContext *DC, std::string &Buffer) {
435 if (DC->isTranslationUnit()) return;
436 AppendScope(DC->getParent(), Buffer);
437
438 unsigned OldSize = Buffer.size();
439
440 if (NamespaceDecl *NS = dyn_cast<NamespaceDecl>(DC)) {
441 if (NS->getIdentifier())
442 Buffer += NS->getNameAsString();
443 else
444 Buffer += "<anonymous>";
445 } else if (ClassTemplateSpecializationDecl *Spec
446 = dyn_cast<ClassTemplateSpecializationDecl>(DC)) {
447 const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs();
448 std::string TemplateArgsStr
449 = TemplateSpecializationType::PrintTemplateArgumentList(
Douglas Gregor910f8002010-11-07 23:05:16 +0000450 TemplateArgs.data(),
451 TemplateArgs.size(),
John McCall7c2342d2010-03-10 11:27:22 +0000452 Policy);
453 Buffer += Spec->getIdentifier()->getName();
454 Buffer += TemplateArgsStr;
455 } else if (TagDecl *Tag = dyn_cast<TagDecl>(DC)) {
456 if (TypedefDecl *Typedef = Tag->getTypedefForAnonDecl())
457 Buffer += Typedef->getIdentifier()->getName();
458 else if (Tag->getIdentifier())
459 Buffer += Tag->getIdentifier()->getName();
460 }
461
462 if (Buffer.size() != OldSize)
463 Buffer += "::";
464}
465
John McCall49f4e1c2010-12-10 11:01:00 +0000466void TypePrinter::printTag(TagDecl *D, std::string &InnerString) {
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000467 if (Policy.SuppressTag)
468 return;
John McCall7c2342d2010-03-10 11:27:22 +0000469
470 std::string Buffer;
John McCall73061d02010-03-19 07:56:44 +0000471 bool HasKindDecoration = false;
John McCall7c2342d2010-03-10 11:27:22 +0000472
473 // We don't print tags unless this is an elaborated type.
474 // In C, we just assume every RecordType is an elaborated type.
475 if (!Policy.LangOpts.CPlusPlus && !D->getTypedefForAnonDecl()) {
John McCall73061d02010-03-19 07:56:44 +0000476 HasKindDecoration = true;
John McCall7c2342d2010-03-10 11:27:22 +0000477 Buffer += D->getKindName();
478 Buffer += ' ';
479 }
480
Chris Lattnerc7acc662010-08-28 16:26:18 +0000481 // Compute the full nested-name-specifier for this type.
482 // In C, this will always be empty except when the type
483 // being printed is anonymous within other Record.
John McCall7c2342d2010-03-10 11:27:22 +0000484 if (!Policy.SuppressScope)
John McCall7c2342d2010-03-10 11:27:22 +0000485 AppendScope(D->getDeclContext(), Buffer);
486
John McCall3cb0ebd2010-03-10 03:28:59 +0000487 if (const IdentifierInfo *II = D->getIdentifier())
John McCall73061d02010-03-19 07:56:44 +0000488 Buffer += II->getNameStart();
John McCall3cb0ebd2010-03-10 03:28:59 +0000489 else if (TypedefDecl *Typedef = D->getTypedefForAnonDecl()) {
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000490 assert(Typedef->getIdentifier() && "Typedef without identifier?");
John McCall73061d02010-03-19 07:56:44 +0000491 Buffer += Typedef->getIdentifier()->getNameStart();
492 } else {
493 // Make an unambiguous representation for anonymous types, e.g.
494 // <anonymous enum at /usr/include/string.h:120:9>
495 llvm::raw_string_ostream OS(Buffer);
496 OS << "<anonymous";
497
Douglas Gregor84139d62010-04-05 21:25:31 +0000498 if (Policy.AnonymousTagLocations) {
499 // Suppress the redundant tag keyword if we just printed one.
500 // We don't have to worry about ElaboratedTypes here because you can't
501 // refer to an anonymous type with one.
502 if (!HasKindDecoration)
503 OS << " " << D->getKindName();
John McCall73061d02010-03-19 07:56:44 +0000504
Douglas Gregorcb7b1e12010-11-12 07:15:47 +0000505 PresumedLoc PLoc = D->getASTContext().getSourceManager().getPresumedLoc(
Douglas Gregor16834e82010-05-28 21:47:04 +0000506 D->getLocation());
Douglas Gregorcb7b1e12010-11-12 07:15:47 +0000507 if (PLoc.isValid()) {
Douglas Gregor16834e82010-05-28 21:47:04 +0000508 OS << " at " << PLoc.getFilename()
509 << ':' << PLoc.getLine()
510 << ':' << PLoc.getColumn();
511 }
Douglas Gregor84139d62010-04-05 21:25:31 +0000512 }
513
514 OS << '>';
John McCall73061d02010-03-19 07:56:44 +0000515 }
John McCall7c2342d2010-03-10 11:27:22 +0000516
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000517 // If this is a class template specialization, print the template
518 // arguments.
519 if (ClassTemplateSpecializationDecl *Spec
John McCall7c2342d2010-03-10 11:27:22 +0000520 = dyn_cast<ClassTemplateSpecializationDecl>(D)) {
John McCall3cb0ebd2010-03-10 03:28:59 +0000521 const TemplateArgument *Args;
522 unsigned NumArgs;
523 if (TypeSourceInfo *TAW = Spec->getTypeAsWritten()) {
524 const TemplateSpecializationType *TST =
525 cast<TemplateSpecializationType>(TAW->getType());
526 Args = TST->getArgs();
527 NumArgs = TST->getNumArgs();
528 } else {
529 const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs();
Douglas Gregor910f8002010-11-07 23:05:16 +0000530 Args = TemplateArgs.data();
531 NumArgs = TemplateArgs.size();
John McCall3cb0ebd2010-03-10 03:28:59 +0000532 }
John McCall7c2342d2010-03-10 11:27:22 +0000533 Buffer += TemplateSpecializationType::PrintTemplateArgumentList(Args,
534 NumArgs,
535 Policy);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000536 }
John McCall7c2342d2010-03-10 11:27:22 +0000537
538 if (!InnerString.empty()) {
539 Buffer += ' ';
540 Buffer += InnerString;
541 }
542
543 std::swap(Buffer, InnerString);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000544}
545
John McCall49f4e1c2010-12-10 11:01:00 +0000546void TypePrinter::printRecord(const RecordType *T, std::string &S) {
547 printTag(T->getDecl(), S);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000548}
549
John McCall49f4e1c2010-12-10 11:01:00 +0000550void TypePrinter::printEnum(const EnumType *T, std::string &S) {
551 printTag(T->getDecl(), S);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000552}
553
John McCall49f4e1c2010-12-10 11:01:00 +0000554void TypePrinter::printTemplateTypeParm(const TemplateTypeParmType *T,
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000555 std::string &S) {
556 if (!S.empty()) // Prefix the basic type, e.g. 'parmname X'.
557 S = ' ' + S;
Douglas Gregorefed5c82010-06-16 15:23:05 +0000558
559 if (!T->getName())
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000560 S = "type-parameter-" + llvm::utostr_32(T->getDepth()) + '-' +
561 llvm::utostr_32(T->getIndex()) + S;
Douglas Gregorefed5c82010-06-16 15:23:05 +0000562 else
563 S = T->getName()->getName().str() + S;
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000564}
565
John McCall49f4e1c2010-12-10 11:01:00 +0000566void TypePrinter::printSubstTemplateTypeParm(const SubstTemplateTypeParmType *T,
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000567 std::string &S) {
John McCall49f4e1c2010-12-10 11:01:00 +0000568 print(T->getReplacementType(), S);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000569}
570
John McCall49f4e1c2010-12-10 11:01:00 +0000571void TypePrinter::printTemplateSpecialization(
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000572 const TemplateSpecializationType *T,
573 std::string &S) {
574 std::string SpecString;
575
576 {
577 llvm::raw_string_ostream OS(SpecString);
578 T->getTemplateName().print(OS, Policy);
579 }
580
581 SpecString += TemplateSpecializationType::PrintTemplateArgumentList(
582 T->getArgs(),
583 T->getNumArgs(),
584 Policy);
585 if (S.empty())
586 S.swap(SpecString);
587 else
588 S = SpecString + ' ' + S;
589}
590
John McCall49f4e1c2010-12-10 11:01:00 +0000591void TypePrinter::printInjectedClassName(const InjectedClassNameType *T,
John McCall3cb0ebd2010-03-10 03:28:59 +0000592 std::string &S) {
John McCall49f4e1c2010-12-10 11:01:00 +0000593 printTemplateSpecialization(T->getInjectedTST(), S);
John McCall3cb0ebd2010-03-10 03:28:59 +0000594}
595
John McCall49f4e1c2010-12-10 11:01:00 +0000596void TypePrinter::printElaborated(const ElaboratedType *T, std::string &S) {
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000597 std::string MyString;
598
599 {
600 llvm::raw_string_ostream OS(MyString);
Abramo Bagnara465d41b2010-05-11 21:36:43 +0000601 OS << TypeWithKeyword::getKeywordName(T->getKeyword());
602 if (T->getKeyword() != ETK_None)
603 OS << " ";
604 NestedNameSpecifier* Qualifier = T->getQualifier();
605 if (Qualifier)
606 Qualifier->print(OS, Policy);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000607 }
608
609 std::string TypeStr;
610 PrintingPolicy InnerPolicy(Policy);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000611 InnerPolicy.SuppressScope = true;
John McCall49f4e1c2010-12-10 11:01:00 +0000612 TypePrinter(InnerPolicy).print(T->getNamedType(), TypeStr);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000613
614 MyString += TypeStr;
615 if (S.empty())
616 S.swap(MyString);
617 else
618 S = MyString + ' ' + S;
619}
620
Abramo Bagnara075f8f12010-12-10 16:29:40 +0000621void TypePrinter::printParen(const ParenType *T, std::string &S) {
622 if (!S.empty() && !isa<FunctionType>(T->getInnerType()))
623 S = '(' + S + ')';
624 print(T->getInnerType(), S);
625}
626
John McCall49f4e1c2010-12-10 11:01:00 +0000627void TypePrinter::printDependentName(const DependentNameType *T, std::string &S) {
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000628 std::string MyString;
629
630 {
631 llvm::raw_string_ostream OS(MyString);
Abramo Bagnara465d41b2010-05-11 21:36:43 +0000632 OS << TypeWithKeyword::getKeywordName(T->getKeyword());
633 if (T->getKeyword() != ETK_None)
634 OS << " ";
Douglas Gregor4a2023f2010-03-31 20:19:30 +0000635
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000636 T->getQualifier()->print(OS, Policy);
637
John McCall33500952010-06-11 00:33:02 +0000638 OS << T->getIdentifier()->getName();
639 }
640
641 if (S.empty())
642 S.swap(MyString);
643 else
644 S = MyString + ' ' + S;
645}
646
John McCall49f4e1c2010-12-10 11:01:00 +0000647void TypePrinter::printDependentTemplateSpecialization(
John McCall33500952010-06-11 00:33:02 +0000648 const DependentTemplateSpecializationType *T, std::string &S) {
649 std::string MyString;
650 {
651 llvm::raw_string_ostream OS(MyString);
652
653 OS << TypeWithKeyword::getKeywordName(T->getKeyword());
654 if (T->getKeyword() != ETK_None)
655 OS << " ";
656
657 T->getQualifier()->print(OS, Policy);
658 OS << T->getIdentifier()->getName();
659 OS << TemplateSpecializationType::PrintTemplateArgumentList(
660 T->getArgs(),
661 T->getNumArgs(),
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000662 Policy);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000663 }
664
665 if (S.empty())
666 S.swap(MyString);
667 else
668 S = MyString + ' ' + S;
669}
670
Douglas Gregor7536dd52010-12-20 02:24:11 +0000671void TypePrinter::printPackExpansion(const PackExpansionType *T,
672 std::string &S) {
673 print(T->getPattern(), S);
674 S += "...";
675}
676
John McCall9d156a72011-01-06 01:58:22 +0000677void TypePrinter::printAttributed(const AttributedType *T,
678 std::string &S) {
679 print(T->getModifiedType(), S);
680
681 // TODO: not all attributes are GCC-style attributes.
682 S += "__attribute__((";
683 switch (T->getAttrKind()) {
Francois Pichet170464b2011-01-07 03:17:31 +0000684 case AttributedType::attr_address_space:
John McCall9d156a72011-01-06 01:58:22 +0000685 S += "address_space(";
686 S += T->getEquivalentType().getAddressSpace();
687 S += ")";
688 break;
689
Francois Pichet170464b2011-01-07 03:17:31 +0000690 case AttributedType::attr_vector_size: {
John McCall9d156a72011-01-06 01:58:22 +0000691 S += "__vector_size__(";
692 if (const VectorType *vector =T->getEquivalentType()->getAs<VectorType>()) {
693 S += vector->getNumElements();
694 S += " * sizeof(";
695
696 std::string tmp;
697 print(vector->getElementType(), tmp);
698 S += tmp;
699 S += ")";
700 }
701 S += ")";
702 break;
703 }
704
Francois Pichet170464b2011-01-07 03:17:31 +0000705 case AttributedType::attr_neon_vector_type:
706 case AttributedType::attr_neon_polyvector_type: {
707 if (T->getAttrKind() == AttributedType::attr_neon_vector_type)
John McCall9d156a72011-01-06 01:58:22 +0000708 S += "neon_vector_type(";
709 else
710 S += "neon_polyvector_type(";
711 const VectorType *vector = T->getEquivalentType()->getAs<VectorType>();
712 S += llvm::utostr_32(vector->getNumElements());
713 S += ")";
714 break;
715 }
716
Francois Pichet170464b2011-01-07 03:17:31 +0000717 case AttributedType::attr_regparm: {
John McCall9d156a72011-01-06 01:58:22 +0000718 S += "regparm(";
719 QualType t = T->getEquivalentType();
720 while (!t->isFunctionType())
721 t = t->getPointeeType();
722 S += t->getAs<FunctionType>()->getRegParmType();
723 S += ")";
724 break;
725 }
726
Francois Pichet170464b2011-01-07 03:17:31 +0000727 case AttributedType::attr_objc_gc: {
John McCall9d156a72011-01-06 01:58:22 +0000728 S += "objc_gc(";
729
730 QualType tmp = T->getEquivalentType();
731 while (tmp.getObjCGCAttr() == Qualifiers::GCNone) {
732 QualType next = tmp->getPointeeType();
733 if (next == tmp) break;
734 tmp = next;
735 }
736
737 if (tmp.isObjCGCWeak())
738 S += "weak";
739 else
740 S += "strong";
741 S += ")";
742 break;
743 }
744
Francois Pichet3cd47e72011-01-07 02:58:13 +0000745 case AttributedType::attr_noreturn: S += "noreturn"; break;
746 case AttributedType::attr_cdecl: S += "cdecl"; break;
747 case AttributedType::attr_fastcall: S += "fastcall"; break;
748 case AttributedType::attr_stdcall: S += "stdcall"; break;
749 case AttributedType::attr_thiscall: S += "thiscall"; break;
750 case AttributedType::attr_pascal: S += "pascal"; break;
John McCall9d156a72011-01-06 01:58:22 +0000751 }
752 S += "))";
753}
754
John McCall49f4e1c2010-12-10 11:01:00 +0000755void TypePrinter::printObjCInterface(const ObjCInterfaceType *T,
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000756 std::string &S) {
757 if (!S.empty()) // Prefix the basic type, e.g. 'typedefname X'.
758 S = ' ' + S;
John McCallc12c5bb2010-05-15 11:32:37 +0000759
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000760 std::string ObjCQIString = T->getDecl()->getNameAsString();
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000761 S = ObjCQIString + S;
762}
763
John McCall49f4e1c2010-12-10 11:01:00 +0000764void TypePrinter::printObjCObject(const ObjCObjectType *T,
John McCallc12c5bb2010-05-15 11:32:37 +0000765 std::string &S) {
766 if (T->qual_empty())
John McCall49f4e1c2010-12-10 11:01:00 +0000767 return print(T->getBaseType(), S);
John McCallc12c5bb2010-05-15 11:32:37 +0000768
769 std::string tmp;
John McCall49f4e1c2010-12-10 11:01:00 +0000770 print(T->getBaseType(), tmp);
John McCallc12c5bb2010-05-15 11:32:37 +0000771 tmp += '<';
772 bool isFirst = true;
773 for (ObjCObjectType::qual_iterator
774 I = T->qual_begin(), E = T->qual_end(); I != E; ++I) {
775 if (isFirst)
776 isFirst = false;
777 else
778 tmp += ',';
779 tmp += (*I)->getNameAsString();
780 }
781 tmp += '>';
782
783 if (!S.empty()) {
784 tmp += ' ';
785 tmp += S;
786 }
787 std::swap(tmp, S);
788}
789
John McCall49f4e1c2010-12-10 11:01:00 +0000790void TypePrinter::printObjCObjectPointer(const ObjCObjectPointerType *T,
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000791 std::string &S) {
792 std::string ObjCQIString;
793
Chris Lattnerd7e52b82010-09-05 00:43:21 +0000794 T->getPointeeType().getLocalQualifiers().getAsStringInternal(ObjCQIString,
795 Policy);
796 if (!ObjCQIString.empty())
797 ObjCQIString += ' ';
798
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000799 if (T->isObjCIdType() || T->isObjCQualifiedIdType())
Chris Lattnerd7e52b82010-09-05 00:43:21 +0000800 ObjCQIString += "id";
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000801 else if (T->isObjCClassType() || T->isObjCQualifiedClassType())
Chris Lattnerd7e52b82010-09-05 00:43:21 +0000802 ObjCQIString += "Class";
Fariborz Jahanian13dcd002009-11-21 19:53:08 +0000803 else if (T->isObjCSelType())
Chris Lattnerd7e52b82010-09-05 00:43:21 +0000804 ObjCQIString += "SEL";
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000805 else
Chris Lattnerd7e52b82010-09-05 00:43:21 +0000806 ObjCQIString += T->getInterfaceDecl()->getNameAsString();
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000807
808 if (!T->qual_empty()) {
809 ObjCQIString += '<';
810 for (ObjCObjectPointerType::qual_iterator I = T->qual_begin(),
811 E = T->qual_end();
812 I != E; ++I) {
813 ObjCQIString += (*I)->getNameAsString();
814 if (I+1 != E)
815 ObjCQIString += ',';
816 }
817 ObjCQIString += '>';
818 }
819
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000820 if (!T->isObjCIdType() && !T->isObjCQualifiedIdType())
821 ObjCQIString += " *"; // Don't forget the implicit pointer.
822 else if (!S.empty()) // Prefix the basic type, e.g. 'typedefname X'.
823 S = ' ' + S;
824
825 S = ObjCQIString + S;
826}
827
John McCalld5532b62009-11-23 01:53:49 +0000828std::string TemplateSpecializationType::
829 PrintTemplateArgumentList(const TemplateArgumentListInfo &Args,
830 const PrintingPolicy &Policy) {
831 return PrintTemplateArgumentList(Args.getArgumentArray(),
832 Args.size(),
833 Policy);
834}
835
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000836std::string
837TemplateSpecializationType::PrintTemplateArgumentList(
838 const TemplateArgument *Args,
839 unsigned NumArgs,
Douglas Gregordace95b2010-12-20 22:28:59 +0000840 const PrintingPolicy &Policy,
841 bool SkipBrackets) {
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000842 std::string SpecString;
Douglas Gregordace95b2010-12-20 22:28:59 +0000843 if (!SkipBrackets)
844 SpecString += '<';
845
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000846 for (unsigned Arg = 0; Arg < NumArgs; ++Arg) {
Douglas Gregordace95b2010-12-20 22:28:59 +0000847 if (SpecString.size() > !SkipBrackets)
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000848 SpecString += ", ";
849
850 // Print the argument into a string.
851 std::string ArgString;
Douglas Gregordace95b2010-12-20 22:28:59 +0000852 if (Args[Arg].getKind() == TemplateArgument::Pack) {
853 ArgString = PrintTemplateArgumentList(Args[Arg].pack_begin(),
854 Args[Arg].pack_size(),
855 Policy, true);
856 } else {
Douglas Gregor87dd6972010-12-20 16:52:59 +0000857 llvm::raw_string_ostream ArgOut(ArgString);
858 Args[Arg].print(Policy, ArgOut);
859 }
860
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000861 // If this is the first argument and its string representation
862 // begins with the global scope specifier ('::foo'), add a space
863 // to avoid printing the diagraph '<:'.
864 if (!Arg && !ArgString.empty() && ArgString[0] == ':')
865 SpecString += ' ';
866
867 SpecString += ArgString;
868 }
869
870 // If the last character of our string is '>', add another space to
871 // keep the two '>''s separate tokens. We don't *have* to do this in
872 // C++0x, but it's still good hygiene.
Francois Pichetb5bc7d02011-01-09 22:32:25 +0000873 if (!SpecString.empty() && SpecString[SpecString.size() - 1] == '>')
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000874 SpecString += ' ';
875
Douglas Gregordace95b2010-12-20 22:28:59 +0000876 if (!SkipBrackets)
877 SpecString += '>';
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000878
879 return SpecString;
880}
881
882// Sadly, repeat all that with TemplateArgLoc.
883std::string TemplateSpecializationType::
884PrintTemplateArgumentList(const TemplateArgumentLoc *Args, unsigned NumArgs,
885 const PrintingPolicy &Policy) {
886 std::string SpecString;
887 SpecString += '<';
888 for (unsigned Arg = 0; Arg < NumArgs; ++Arg) {
Douglas Gregordace95b2010-12-20 22:28:59 +0000889 if (SpecString.size() > 1)
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000890 SpecString += ", ";
891
892 // Print the argument into a string.
893 std::string ArgString;
Douglas Gregordace95b2010-12-20 22:28:59 +0000894 if (Args[Arg].getArgument().getKind() == TemplateArgument::Pack) {
895 ArgString = PrintTemplateArgumentList(
896 Args[Arg].getArgument().pack_begin(),
897 Args[Arg].getArgument().pack_size(),
898 Policy, true);
899 } else {
Douglas Gregor87dd6972010-12-20 16:52:59 +0000900 llvm::raw_string_ostream ArgOut(ArgString);
901 Args[Arg].getArgument().print(Policy, ArgOut);
902 }
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000903
904 // If this is the first argument and its string representation
905 // begins with the global scope specifier ('::foo'), add a space
906 // to avoid printing the diagraph '<:'.
907 if (!Arg && !ArgString.empty() && ArgString[0] == ':')
908 SpecString += ' ';
909
910 SpecString += ArgString;
911 }
912
913 // If the last character of our string is '>', add another space to
914 // keep the two '>''s separate tokens. We don't *have* to do this in
915 // C++0x, but it's still good hygiene.
916 if (SpecString[SpecString.size() - 1] == '>')
917 SpecString += ' ';
918
919 SpecString += '>';
920
921 return SpecString;
922}
923
924void QualType::dump(const char *msg) const {
925 std::string R = "identifier";
926 LangOptions LO;
927 getAsStringInternal(R, PrintingPolicy(LO));
928 if (msg)
Daniel Dunbare7cb7e42009-12-03 09:14:02 +0000929 llvm::errs() << msg << ": ";
930 llvm::errs() << R << "\n";
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000931}
932void QualType::dump() const {
933 dump("");
934}
935
936void Type::dump() const {
937 QualType(this, 0).dump();
938}
939
940std::string Qualifiers::getAsString() const {
941 LangOptions LO;
942 return getAsString(PrintingPolicy(LO));
943}
944
945// Appends qualifiers to the given string, separated by spaces. Will
946// prefix a space if the string is non-empty. Will not append a final
947// space.
948void Qualifiers::getAsStringInternal(std::string &S,
949 const PrintingPolicy&) const {
950 AppendTypeQualList(S, getCVRQualifiers());
951 if (unsigned AddressSpace = getAddressSpace()) {
952 if (!S.empty()) S += ' ';
953 S += "__attribute__((address_space(";
954 S += llvm::utostr_32(AddressSpace);
955 S += ")))";
956 }
957 if (Qualifiers::GC GCAttrType = getObjCGCAttr()) {
958 if (!S.empty()) S += ' ';
959 S += "__attribute__((objc_gc(";
960 if (GCAttrType == Qualifiers::Weak)
961 S += "weak";
962 else
963 S += "strong";
964 S += ")))";
965 }
966}
967
John McCall49f4e1c2010-12-10 11:01:00 +0000968std::string QualType::getAsString(const Type *ty, Qualifiers qs) {
969 std::string buffer;
970 LangOptions options;
971 getAsStringInternal(ty, qs, buffer, PrintingPolicy(options));
972 return buffer;
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000973}
974
John McCall49f4e1c2010-12-10 11:01:00 +0000975void QualType::getAsStringInternal(const Type *ty, Qualifiers qs,
976 std::string &buffer,
977 const PrintingPolicy &policy) {
978 TypePrinter(policy).print(ty, qs, buffer);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000979}