blob: ccb456018ddd5ae42373ed15a9f4ea03aa9095b8 [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 {
John McCallf85e1932011-06-15 23:02:42 +000027 /// \brief RAII object that enables printing of the ARC __strong lifetime
28 /// qualifier.
29 class IncludeStrongLifetimeRAII {
30 PrintingPolicy &Policy;
31 bool Old;
32
33 public:
34 explicit IncludeStrongLifetimeRAII(PrintingPolicy &Policy)
35 : Policy(Policy), Old(Policy.SuppressStrongLifetime) {
36 Policy.SuppressStrongLifetime = false;
37 }
38
39 ~IncludeStrongLifetimeRAII() {
40 Policy.SuppressStrongLifetime = Old;
41 }
42 };
43
Douglas Gregorfee8a3c2009-11-10 00:39:07 +000044 class TypePrinter {
45 PrintingPolicy Policy;
46
47 public:
48 explicit TypePrinter(const PrintingPolicy &Policy) : Policy(Policy) { }
Abramo Bagnara493ec512010-04-27 21:08:25 +000049
John McCall49f4e1c2010-12-10 11:01:00 +000050 void print(const Type *ty, Qualifiers qs, std::string &buffer);
51 void print(QualType T, std::string &S);
John McCall7c2342d2010-03-10 11:27:22 +000052 void AppendScope(DeclContext *DC, std::string &S);
John McCall49f4e1c2010-12-10 11:01:00 +000053 void printTag(TagDecl *T, std::string &S);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +000054#define ABSTRACT_TYPE(CLASS, PARENT)
55#define TYPE(CLASS, PARENT) \
Douglas Gregor7536dd52010-12-20 02:24:11 +000056 void print##CLASS(const CLASS##Type *T, std::string &S);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +000057#include "clang/AST/TypeNodes.def"
58 };
59}
60
61static void AppendTypeQualList(std::string &S, unsigned TypeQuals) {
62 if (TypeQuals & Qualifiers::Const) {
63 if (!S.empty()) S += ' ';
64 S += "const";
65 }
66 if (TypeQuals & Qualifiers::Volatile) {
67 if (!S.empty()) S += ' ';
68 S += "volatile";
69 }
70 if (TypeQuals & Qualifiers::Restrict) {
71 if (!S.empty()) S += ' ';
72 S += "restrict";
73 }
74}
75
John McCall49f4e1c2010-12-10 11:01:00 +000076void TypePrinter::print(QualType t, std::string &buffer) {
77 SplitQualType split = t.split();
78 print(split.first, split.second, buffer);
79}
80
81void TypePrinter::print(const Type *T, Qualifiers Quals, std::string &buffer) {
82 if (!T) {
83 buffer += "NULL TYPE";
Douglas Gregorfee8a3c2009-11-10 00:39:07 +000084 return;
85 }
86
87 if (Policy.SuppressSpecifiers && T->isSpecifierType())
88 return;
89
90 // Print qualifiers as appropriate.
Chris Lattner58f9e132010-09-05 00:04:01 +000091
92 // CanPrefixQualifiers - We prefer to print type qualifiers before the type,
93 // so that we get "const int" instead of "int const", but we can't do this if
94 // the type is complex. For example if the type is "int*", we *must* print
95 // "int * const", printing "const int *" is different. Only do this when the
96 // type expands to a simple string.
Douglas Gregorc6daf0b2011-02-17 06:52:25 +000097 bool CanPrefixQualifiers = false;
John McCallf85e1932011-06-15 23:02:42 +000098 bool NeedARCStrongQualifier = false;
Douglas Gregorc6daf0b2011-02-17 06:52:25 +000099 Type::TypeClass TC = T->getTypeClass();
Richard Smith34b41d92011-02-20 03:19:35 +0000100 if (const AutoType *AT = dyn_cast<AutoType>(T))
101 TC = AT->desugar()->getTypeClass();
Douglas Gregorc6daf0b2011-02-17 06:52:25 +0000102 if (const SubstTemplateTypeParmType *Subst
103 = dyn_cast<SubstTemplateTypeParmType>(T))
104 TC = Subst->getReplacementType()->getTypeClass();
105
106 switch (TC) {
107 case Type::Builtin:
108 case Type::Complex:
109 case Type::UnresolvedUsing:
110 case Type::Typedef:
111 case Type::TypeOfExpr:
112 case Type::TypeOf:
113 case Type::Decltype:
Sean Huntca63c202011-05-24 22:41:36 +0000114 case Type::UnaryTransform:
Douglas Gregorc6daf0b2011-02-17 06:52:25 +0000115 case Type::Record:
116 case Type::Enum:
117 case Type::Elaborated:
118 case Type::TemplateTypeParm:
119 case Type::SubstTemplateTypeParmPack:
120 case Type::TemplateSpecialization:
121 case Type::InjectedClassName:
122 case Type::DependentName:
123 case Type::DependentTemplateSpecialization:
124 case Type::ObjCObject:
125 case Type::ObjCInterface:
126 CanPrefixQualifiers = true;
127 break;
128
129 case Type::ObjCObjectPointer:
130 CanPrefixQualifiers = T->isObjCIdType() || T->isObjCClassType() ||
131 T->isObjCQualifiedIdType() || T->isObjCQualifiedClassType();
132 break;
133
John McCallf85e1932011-06-15 23:02:42 +0000134 case Type::ConstantArray:
135 case Type::IncompleteArray:
136 case Type::VariableArray:
137 case Type::DependentSizedArray:
138 NeedARCStrongQualifier = true;
139 // Fall through
140
Douglas Gregorc6daf0b2011-02-17 06:52:25 +0000141 case Type::Pointer:
142 case Type::BlockPointer:
143 case Type::LValueReference:
144 case Type::RValueReference:
145 case Type::MemberPointer:
Douglas Gregorc6daf0b2011-02-17 06:52:25 +0000146 case Type::DependentSizedExtVector:
147 case Type::Vector:
148 case Type::ExtVector:
149 case Type::FunctionProto:
150 case Type::FunctionNoProto:
151 case Type::Paren:
152 case Type::Attributed:
153 case Type::PackExpansion:
154 case Type::SubstTemplateTypeParm:
Richard Smith34b41d92011-02-20 03:19:35 +0000155 case Type::Auto:
Douglas Gregorc6daf0b2011-02-17 06:52:25 +0000156 CanPrefixQualifiers = false;
157 break;
158 }
Chris Lattner58f9e132010-09-05 00:04:01 +0000159
160 if (!CanPrefixQualifiers && !Quals.empty()) {
John McCall49f4e1c2010-12-10 11:01:00 +0000161 std::string qualsBuffer;
John McCallf85e1932011-06-15 23:02:42 +0000162 if (NeedARCStrongQualifier) {
163 IncludeStrongLifetimeRAII Strong(Policy);
164 Quals.getAsStringInternal(qualsBuffer, Policy);
165 } else {
166 Quals.getAsStringInternal(qualsBuffer, Policy);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000167 }
John McCallf85e1932011-06-15 23:02:42 +0000168
169 if (!qualsBuffer.empty()) {
170 if (!buffer.empty()) {
171 qualsBuffer += ' ';
172 qualsBuffer += buffer;
173 }
174 std::swap(buffer, qualsBuffer);
175 }
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000176 }
177
178 switch (T->getTypeClass()) {
179#define ABSTRACT_TYPE(CLASS, PARENT)
John McCall49f4e1c2010-12-10 11:01:00 +0000180#define TYPE(CLASS, PARENT) case Type::CLASS: \
181 print##CLASS(cast<CLASS##Type>(T), buffer); \
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000182 break;
183#include "clang/AST/TypeNodes.def"
184 }
Chris Lattner58f9e132010-09-05 00:04:01 +0000185
186 // If we're adding the qualifiers as a prefix, do it now.
187 if (CanPrefixQualifiers && !Quals.empty()) {
John McCall49f4e1c2010-12-10 11:01:00 +0000188 std::string qualsBuffer;
John McCallf85e1932011-06-15 23:02:42 +0000189 if (NeedARCStrongQualifier) {
190 IncludeStrongLifetimeRAII Strong(Policy);
191 Quals.getAsStringInternal(qualsBuffer, Policy);
192 } else {
193 Quals.getAsStringInternal(qualsBuffer, Policy);
Chris Lattner58f9e132010-09-05 00:04:01 +0000194 }
John McCallf85e1932011-06-15 23:02:42 +0000195
196 if (!qualsBuffer.empty()) {
197 if (!buffer.empty()) {
198 qualsBuffer += ' ';
199 qualsBuffer += buffer;
200 }
201 std::swap(buffer, qualsBuffer);
202 }
Chris Lattner58f9e132010-09-05 00:04:01 +0000203 }
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000204}
205
John McCall49f4e1c2010-12-10 11:01:00 +0000206void TypePrinter::printBuiltin(const BuiltinType *T, std::string &S) {
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000207 if (S.empty()) {
208 S = T->getName(Policy.LangOpts);
209 } else {
210 // Prefix the basic type, e.g. 'int X'.
Chris Lattner59742de2010-09-04 23:43:40 +0000211 S = ' ' + S;
212 S = T->getName(Policy.LangOpts) + S;
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000213 }
214}
215
John McCall49f4e1c2010-12-10 11:01:00 +0000216void TypePrinter::printComplex(const ComplexType *T, std::string &S) {
217 print(T->getElementType(), S);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000218 S = "_Complex " + S;
219}
220
John McCall49f4e1c2010-12-10 11:01:00 +0000221void TypePrinter::printPointer(const PointerType *T, std::string &S) {
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000222 S = '*' + S;
223
224 // Handle things like 'int (*A)[4];' correctly.
225 // FIXME: this should include vectors, but vectors use attributes I guess.
226 if (isa<ArrayType>(T->getPointeeType()))
227 S = '(' + S + ')';
228
John McCallf85e1932011-06-15 23:02:42 +0000229 IncludeStrongLifetimeRAII Strong(Policy);
John McCall49f4e1c2010-12-10 11:01:00 +0000230 print(T->getPointeeType(), S);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000231}
232
John McCall49f4e1c2010-12-10 11:01:00 +0000233void TypePrinter::printBlockPointer(const BlockPointerType *T, std::string &S) {
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000234 S = '^' + S;
John McCall49f4e1c2010-12-10 11:01:00 +0000235 print(T->getPointeeType(), S);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000236}
237
John McCall49f4e1c2010-12-10 11:01:00 +0000238void TypePrinter::printLValueReference(const LValueReferenceType *T,
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000239 std::string &S) {
240 S = '&' + S;
241
242 // Handle things like 'int (&A)[4];' correctly.
243 // FIXME: this should include vectors, but vectors use attributes I guess.
244 if (isa<ArrayType>(T->getPointeeTypeAsWritten()))
245 S = '(' + S + ')';
246
John McCallf85e1932011-06-15 23:02:42 +0000247 IncludeStrongLifetimeRAII Strong(Policy);
John McCall49f4e1c2010-12-10 11:01:00 +0000248 print(T->getPointeeTypeAsWritten(), S);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000249}
250
John McCall49f4e1c2010-12-10 11:01:00 +0000251void TypePrinter::printRValueReference(const RValueReferenceType *T,
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000252 std::string &S) {
253 S = "&&" + S;
254
255 // Handle things like 'int (&&A)[4];' correctly.
256 // FIXME: this should include vectors, but vectors use attributes I guess.
257 if (isa<ArrayType>(T->getPointeeTypeAsWritten()))
258 S = '(' + S + ')';
259
John McCallf85e1932011-06-15 23:02:42 +0000260 IncludeStrongLifetimeRAII Strong(Policy);
John McCall49f4e1c2010-12-10 11:01:00 +0000261 print(T->getPointeeTypeAsWritten(), S);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000262}
263
John McCall49f4e1c2010-12-10 11:01:00 +0000264void TypePrinter::printMemberPointer(const MemberPointerType *T,
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000265 std::string &S) {
266 std::string C;
John McCall49f4e1c2010-12-10 11:01:00 +0000267 print(QualType(T->getClass(), 0), C);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000268 C += "::*";
269 S = C + S;
270
271 // Handle things like 'int (Cls::*A)[4];' correctly.
272 // FIXME: this should include vectors, but vectors use attributes I guess.
273 if (isa<ArrayType>(T->getPointeeType()))
274 S = '(' + S + ')';
275
John McCallf85e1932011-06-15 23:02:42 +0000276 IncludeStrongLifetimeRAII Strong(Policy);
John McCall49f4e1c2010-12-10 11:01:00 +0000277 print(T->getPointeeType(), S);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000278}
279
John McCall49f4e1c2010-12-10 11:01:00 +0000280void TypePrinter::printConstantArray(const ConstantArrayType *T,
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000281 std::string &S) {
282 S += '[';
283 S += llvm::utostr(T->getSize().getZExtValue());
284 S += ']';
285
John McCallf85e1932011-06-15 23:02:42 +0000286 IncludeStrongLifetimeRAII Strong(Policy);
John McCall49f4e1c2010-12-10 11:01:00 +0000287 print(T->getElementType(), S);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000288}
289
John McCall49f4e1c2010-12-10 11:01:00 +0000290void TypePrinter::printIncompleteArray(const IncompleteArrayType *T,
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000291 std::string &S) {
292 S += "[]";
John McCallf85e1932011-06-15 23:02:42 +0000293 IncludeStrongLifetimeRAII Strong(Policy);
John McCall49f4e1c2010-12-10 11:01:00 +0000294 print(T->getElementType(), S);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000295}
296
John McCall49f4e1c2010-12-10 11:01:00 +0000297void TypePrinter::printVariableArray(const VariableArrayType *T,
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000298 std::string &S) {
299 S += '[';
300
301 if (T->getIndexTypeQualifiers().hasQualifiers()) {
302 AppendTypeQualList(S, T->getIndexTypeCVRQualifiers());
303 S += ' ';
304 }
305
306 if (T->getSizeModifier() == VariableArrayType::Static)
307 S += "static";
308 else if (T->getSizeModifier() == VariableArrayType::Star)
309 S += '*';
310
311 if (T->getSizeExpr()) {
312 std::string SStr;
313 llvm::raw_string_ostream s(SStr);
314 T->getSizeExpr()->printPretty(s, 0, Policy);
315 S += s.str();
316 }
317 S += ']';
318
John McCallf85e1932011-06-15 23:02:42 +0000319 IncludeStrongLifetimeRAII Strong(Policy);
John McCall49f4e1c2010-12-10 11:01:00 +0000320 print(T->getElementType(), S);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000321}
322
John McCall49f4e1c2010-12-10 11:01:00 +0000323void TypePrinter::printDependentSizedArray(const DependentSizedArrayType *T,
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000324 std::string &S) {
325 S += '[';
326
327 if (T->getSizeExpr()) {
328 std::string SStr;
329 llvm::raw_string_ostream s(SStr);
330 T->getSizeExpr()->printPretty(s, 0, Policy);
331 S += s.str();
332 }
333 S += ']';
334
John McCallf85e1932011-06-15 23:02:42 +0000335 IncludeStrongLifetimeRAII Strong(Policy);
John McCall49f4e1c2010-12-10 11:01:00 +0000336 print(T->getElementType(), S);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000337}
338
John McCall49f4e1c2010-12-10 11:01:00 +0000339void TypePrinter::printDependentSizedExtVector(
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000340 const DependentSizedExtVectorType *T,
341 std::string &S) {
John McCall49f4e1c2010-12-10 11:01:00 +0000342 print(T->getElementType(), S);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000343
344 S += " __attribute__((ext_vector_type(";
345 if (T->getSizeExpr()) {
346 std::string SStr;
347 llvm::raw_string_ostream s(SStr);
348 T->getSizeExpr()->printPretty(s, 0, Policy);
349 S += s.str();
350 }
351 S += ")))";
352}
353
John McCall49f4e1c2010-12-10 11:01:00 +0000354void TypePrinter::printVector(const VectorType *T, std::string &S) {
Bob Wilsonec33cbe2010-11-16 00:32:26 +0000355 switch (T->getVectorKind()) {
356 case VectorType::AltiVecPixel:
357 S = "__vector __pixel " + S;
358 break;
359 case VectorType::AltiVecBool:
John McCall49f4e1c2010-12-10 11:01:00 +0000360 print(T->getElementType(), S);
Bob Wilsonec33cbe2010-11-16 00:32:26 +0000361 S = "__vector __bool " + S;
362 break;
363 case VectorType::AltiVecVector:
John McCall49f4e1c2010-12-10 11:01:00 +0000364 print(T->getElementType(), S);
Bob Wilsonec33cbe2010-11-16 00:32:26 +0000365 S = "__vector " + S;
366 break;
367 case VectorType::NeonVector:
John McCall49f4e1c2010-12-10 11:01:00 +0000368 print(T->getElementType(), S);
Bob Wilsonec33cbe2010-11-16 00:32:26 +0000369 S = ("__attribute__((neon_vector_type(" +
370 llvm::utostr_32(T->getNumElements()) + "))) " + S);
371 break;
372 case VectorType::NeonPolyVector:
John McCall49f4e1c2010-12-10 11:01:00 +0000373 print(T->getElementType(), S);
Bob Wilsonec33cbe2010-11-16 00:32:26 +0000374 S = ("__attribute__((neon_polyvector_type(" +
375 llvm::utostr_32(T->getNumElements()) + "))) " + S);
376 break;
377 case VectorType::GenericVector: {
John Thompson82287d12010-02-05 00:12:22 +0000378 // FIXME: We prefer to print the size directly here, but have no way
379 // to get the size of the type.
John McCall49f4e1c2010-12-10 11:01:00 +0000380 print(T->getElementType(), S);
John Thompson82287d12010-02-05 00:12:22 +0000381 std::string V = "__attribute__((__vector_size__(";
382 V += llvm::utostr_32(T->getNumElements()); // convert back to bytes.
383 std::string ET;
John McCall49f4e1c2010-12-10 11:01:00 +0000384 print(T->getElementType(), ET);
John Thompson82287d12010-02-05 00:12:22 +0000385 V += " * sizeof(" + ET + ")))) ";
386 S = V + S;
Bob Wilsonec33cbe2010-11-16 00:32:26 +0000387 break;
388 }
John Thompson82287d12010-02-05 00:12:22 +0000389 }
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000390}
391
John McCall49f4e1c2010-12-10 11:01:00 +0000392void TypePrinter::printExtVector(const ExtVectorType *T, std::string &S) {
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000393 S += " __attribute__((ext_vector_type(";
394 S += llvm::utostr_32(T->getNumElements());
395 S += ")))";
John McCall49f4e1c2010-12-10 11:01:00 +0000396 print(T->getElementType(), S);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000397}
398
John McCall49f4e1c2010-12-10 11:01:00 +0000399void TypePrinter::printFunctionProto(const FunctionProtoType *T,
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000400 std::string &S) {
401 // If needed for precedence reasons, wrap the inner part in grouping parens.
402 if (!S.empty())
403 S = "(" + S + ")";
404
405 S += "(";
406 std::string Tmp;
407 PrintingPolicy ParamPolicy(Policy);
408 ParamPolicy.SuppressSpecifiers = false;
409 for (unsigned i = 0, e = T->getNumArgs(); i != e; ++i) {
410 if (i) S += ", ";
John McCall49f4e1c2010-12-10 11:01:00 +0000411 print(T->getArgType(i), Tmp);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000412 S += Tmp;
413 Tmp.clear();
414 }
415
416 if (T->isVariadic()) {
417 if (T->getNumArgs())
418 S += ", ";
419 S += "...";
420 } else if (T->getNumArgs() == 0 && !Policy.LangOpts.CPlusPlus) {
421 // Do not emit int() if we have a proto, emit 'int(void)'.
422 S += "void";
423 }
424
425 S += ")";
Douglas Gregor0ae7b3f2009-12-08 17:45:32 +0000426
Rafael Espindola264ba482010-03-30 20:24:48 +0000427 FunctionType::ExtInfo Info = T->getExtInfo();
428 switch(Info.getCC()) {
John McCallf82b4e82010-02-04 05:44:44 +0000429 case CC_Default:
430 default: break;
431 case CC_C:
432 S += " __attribute__((cdecl))";
433 break;
434 case CC_X86StdCall:
435 S += " __attribute__((stdcall))";
436 break;
437 case CC_X86FastCall:
438 S += " __attribute__((fastcall))";
439 break;
Douglas Gregorf813a2c2010-05-18 16:57:00 +0000440 case CC_X86ThisCall:
441 S += " __attribute__((thiscall))";
442 break;
Dawn Perchik52fc3142010-09-03 01:29:35 +0000443 case CC_X86Pascal:
444 S += " __attribute__((pascal))";
445 break;
Anton Korobeynikov414d8962011-04-14 20:06:49 +0000446 case CC_AAPCS:
447 S += " __attribute__((pcs(\"aapcs\")))";
448 break;
449 case CC_AAPCS_VFP:
450 S += " __attribute__((pcs(\"aapcs-vfp\")))";
451 break;
John McCallf82b4e82010-02-04 05:44:44 +0000452 }
Rafael Espindola264ba482010-03-30 20:24:48 +0000453 if (Info.getNoReturn())
Douglas Gregor48026d22010-01-11 18:40:55 +0000454 S += " __attribute__((noreturn))";
Rafael Espindola425ef722010-03-30 22:15:11 +0000455 if (Info.getRegParm())
456 S += " __attribute__((regparm (" +
457 llvm::utostr_32(Info.getRegParm()) + ")))";
Douglas Gregor48026d22010-01-11 18:40:55 +0000458
Douglas Gregorc938c162011-01-26 05:01:58 +0000459 AppendTypeQualList(S, T->getTypeQuals());
460
461 switch (T->getRefQualifier()) {
462 case RQ_None:
463 break;
464
465 case RQ_LValue:
466 S += " &";
467 break;
468
469 case RQ_RValue:
470 S += " &&";
471 break;
472 }
Sebastian Redl60618fa2011-03-12 11:50:43 +0000473
474 if (T->hasDynamicExceptionSpec()) {
Douglas Gregor0ae7b3f2009-12-08 17:45:32 +0000475 S += " throw(";
Sebastian Redl60618fa2011-03-12 11:50:43 +0000476 if (T->getExceptionSpecType() == EST_MSAny)
Douglas Gregor0ae7b3f2009-12-08 17:45:32 +0000477 S += "...";
Sebastian Redl60618fa2011-03-12 11:50:43 +0000478 else
Douglas Gregor0ae7b3f2009-12-08 17:45:32 +0000479 for (unsigned I = 0, N = T->getNumExceptions(); I != N; ++I) {
480 if (I)
481 S += ", ";
482
483 std::string ExceptionType;
John McCall49f4e1c2010-12-10 11:01:00 +0000484 print(T->getExceptionType(I), ExceptionType);
Douglas Gregor0ae7b3f2009-12-08 17:45:32 +0000485 S += ExceptionType;
486 }
487 S += ")";
Sebastian Redl60618fa2011-03-12 11:50:43 +0000488 } else if (isNoexceptExceptionSpec(T->getExceptionSpecType())) {
489 S += " noexcept";
490 if (T->getExceptionSpecType() == EST_ComputedNoexcept) {
491 S += "(";
492 llvm::raw_string_ostream EOut(S);
493 T->getNoexceptExpr()->printPretty(EOut, 0, Policy);
494 EOut.flush();
495 S += EOut.str();
496 S += ")";
497 }
Douglas Gregor0ae7b3f2009-12-08 17:45:32 +0000498 }
499
John McCall49f4e1c2010-12-10 11:01:00 +0000500 print(T->getResultType(), S);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000501}
502
John McCall49f4e1c2010-12-10 11:01:00 +0000503void TypePrinter::printFunctionNoProto(const FunctionNoProtoType *T,
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000504 std::string &S) {
505 // If needed for precedence reasons, wrap the inner part in grouping parens.
506 if (!S.empty())
507 S = "(" + S + ")";
508
509 S += "()";
510 if (T->getNoReturnAttr())
511 S += " __attribute__((noreturn))";
John McCall49f4e1c2010-12-10 11:01:00 +0000512 print(T->getResultType(), S);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000513}
514
John McCall49f4e1c2010-12-10 11:01:00 +0000515static void printTypeSpec(const NamedDecl *D, std::string &S) {
John McCall3cb0ebd2010-03-10 03:28:59 +0000516 IdentifierInfo *II = D->getIdentifier();
John McCalled976492009-12-04 22:46:56 +0000517 if (S.empty())
518 S = II->getName().str();
519 else
520 S = II->getName().str() + ' ' + S;
521}
522
John McCall49f4e1c2010-12-10 11:01:00 +0000523void TypePrinter::printUnresolvedUsing(const UnresolvedUsingType *T,
John McCall3cb0ebd2010-03-10 03:28:59 +0000524 std::string &S) {
John McCall49f4e1c2010-12-10 11:01:00 +0000525 printTypeSpec(T->getDecl(), S);
John McCall3cb0ebd2010-03-10 03:28:59 +0000526}
527
John McCall49f4e1c2010-12-10 11:01:00 +0000528void TypePrinter::printTypedef(const TypedefType *T, std::string &S) {
529 printTypeSpec(T->getDecl(), S);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000530}
531
John McCall49f4e1c2010-12-10 11:01:00 +0000532void TypePrinter::printTypeOfExpr(const TypeOfExprType *T, std::string &S) {
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000533 if (!S.empty()) // Prefix the basic type, e.g. 'typeof(e) X'.
534 S = ' ' + S;
535 std::string Str;
536 llvm::raw_string_ostream s(Str);
537 T->getUnderlyingExpr()->printPretty(s, 0, Policy);
538 S = "typeof " + s.str() + S;
539}
540
John McCall49f4e1c2010-12-10 11:01:00 +0000541void TypePrinter::printTypeOf(const TypeOfType *T, std::string &S) {
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000542 if (!S.empty()) // Prefix the basic type, e.g. 'typeof(t) X'.
543 S = ' ' + S;
544 std::string Tmp;
John McCall49f4e1c2010-12-10 11:01:00 +0000545 print(T->getUnderlyingType(), Tmp);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000546 S = "typeof(" + Tmp + ")" + S;
547}
548
John McCall49f4e1c2010-12-10 11:01:00 +0000549void TypePrinter::printDecltype(const DecltypeType *T, std::string &S) {
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000550 if (!S.empty()) // Prefix the basic type, e.g. 'decltype(t) X'.
551 S = ' ' + S;
552 std::string Str;
553 llvm::raw_string_ostream s(Str);
554 T->getUnderlyingExpr()->printPretty(s, 0, Policy);
555 S = "decltype(" + s.str() + ")" + S;
556}
557
Sean Huntca63c202011-05-24 22:41:36 +0000558void TypePrinter::printUnaryTransform(const UnaryTransformType *T,
559 std::string &S) {
560 if (!S.empty())
561 S = ' ' + S;
562 std::string Str;
John McCallf85e1932011-06-15 23:02:42 +0000563 IncludeStrongLifetimeRAII Strong(Policy);
Sean Huntca63c202011-05-24 22:41:36 +0000564 print(T->getBaseType(), Str);
565
566 switch (T->getUTTKind()) {
567 case UnaryTransformType::EnumUnderlyingType:
568 S = "__underlying_type(" + Str + ")" + S;
569 break;
570 }
571}
572
Richard Smith34b41d92011-02-20 03:19:35 +0000573void TypePrinter::printAuto(const AutoType *T, std::string &S) {
574 // If the type has been deduced, do not print 'auto'.
575 if (T->isDeduced()) {
576 print(T->getDeducedType(), S);
577 } else {
578 if (!S.empty()) // Prefix the basic type, e.g. 'auto X'.
579 S = ' ' + S;
580 S = "auto" + S;
581 }
582}
583
John McCall7c2342d2010-03-10 11:27:22 +0000584/// Appends the given scope to the end of a string.
585void TypePrinter::AppendScope(DeclContext *DC, std::string &Buffer) {
586 if (DC->isTranslationUnit()) return;
587 AppendScope(DC->getParent(), Buffer);
588
589 unsigned OldSize = Buffer.size();
590
591 if (NamespaceDecl *NS = dyn_cast<NamespaceDecl>(DC)) {
592 if (NS->getIdentifier())
593 Buffer += NS->getNameAsString();
594 else
595 Buffer += "<anonymous>";
596 } else if (ClassTemplateSpecializationDecl *Spec
597 = dyn_cast<ClassTemplateSpecializationDecl>(DC)) {
John McCallf85e1932011-06-15 23:02:42 +0000598 IncludeStrongLifetimeRAII Strong(Policy);
John McCall7c2342d2010-03-10 11:27:22 +0000599 const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs();
600 std::string TemplateArgsStr
601 = TemplateSpecializationType::PrintTemplateArgumentList(
Douglas Gregor910f8002010-11-07 23:05:16 +0000602 TemplateArgs.data(),
603 TemplateArgs.size(),
John McCall7c2342d2010-03-10 11:27:22 +0000604 Policy);
605 Buffer += Spec->getIdentifier()->getName();
606 Buffer += TemplateArgsStr;
607 } else if (TagDecl *Tag = dyn_cast<TagDecl>(DC)) {
Richard Smith162e1c12011-04-15 14:24:37 +0000608 if (TypedefNameDecl *Typedef = Tag->getTypedefNameForAnonDecl())
John McCall7c2342d2010-03-10 11:27:22 +0000609 Buffer += Typedef->getIdentifier()->getName();
610 else if (Tag->getIdentifier())
611 Buffer += Tag->getIdentifier()->getName();
612 }
613
614 if (Buffer.size() != OldSize)
615 Buffer += "::";
616}
617
John McCall49f4e1c2010-12-10 11:01:00 +0000618void TypePrinter::printTag(TagDecl *D, std::string &InnerString) {
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000619 if (Policy.SuppressTag)
620 return;
John McCall7c2342d2010-03-10 11:27:22 +0000621
622 std::string Buffer;
John McCall73061d02010-03-19 07:56:44 +0000623 bool HasKindDecoration = false;
John McCall7c2342d2010-03-10 11:27:22 +0000624
Abramo Bagnara0daaf322011-03-16 20:16:18 +0000625 // bool SuppressTagKeyword
626 // = Policy.LangOpts.CPlusPlus || Policy.SuppressTagKeyword;
627
John McCall7c2342d2010-03-10 11:27:22 +0000628 // We don't print tags unless this is an elaborated type.
629 // In C, we just assume every RecordType is an elaborated type.
Abramo Bagnara0daaf322011-03-16 20:16:18 +0000630 if (!(Policy.LangOpts.CPlusPlus || Policy.SuppressTagKeyword ||
Richard Smith162e1c12011-04-15 14:24:37 +0000631 D->getTypedefNameForAnonDecl())) {
John McCall73061d02010-03-19 07:56:44 +0000632 HasKindDecoration = true;
John McCall7c2342d2010-03-10 11:27:22 +0000633 Buffer += D->getKindName();
634 Buffer += ' ';
635 }
636
Chris Lattnerc7acc662010-08-28 16:26:18 +0000637 // Compute the full nested-name-specifier for this type.
638 // In C, this will always be empty except when the type
639 // being printed is anonymous within other Record.
John McCall7c2342d2010-03-10 11:27:22 +0000640 if (!Policy.SuppressScope)
John McCall7c2342d2010-03-10 11:27:22 +0000641 AppendScope(D->getDeclContext(), Buffer);
642
John McCall3cb0ebd2010-03-10 03:28:59 +0000643 if (const IdentifierInfo *II = D->getIdentifier())
John McCall73061d02010-03-19 07:56:44 +0000644 Buffer += II->getNameStart();
Richard Smith162e1c12011-04-15 14:24:37 +0000645 else if (TypedefNameDecl *Typedef = D->getTypedefNameForAnonDecl()) {
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000646 assert(Typedef->getIdentifier() && "Typedef without identifier?");
John McCall73061d02010-03-19 07:56:44 +0000647 Buffer += Typedef->getIdentifier()->getNameStart();
648 } else {
649 // Make an unambiguous representation for anonymous types, e.g.
650 // <anonymous enum at /usr/include/string.h:120:9>
651 llvm::raw_string_ostream OS(Buffer);
652 OS << "<anonymous";
653
Douglas Gregor84139d62010-04-05 21:25:31 +0000654 if (Policy.AnonymousTagLocations) {
655 // Suppress the redundant tag keyword if we just printed one.
656 // We don't have to worry about ElaboratedTypes here because you can't
657 // refer to an anonymous type with one.
658 if (!HasKindDecoration)
659 OS << " " << D->getKindName();
John McCall73061d02010-03-19 07:56:44 +0000660
Douglas Gregorcb7b1e12010-11-12 07:15:47 +0000661 PresumedLoc PLoc = D->getASTContext().getSourceManager().getPresumedLoc(
Douglas Gregor16834e82010-05-28 21:47:04 +0000662 D->getLocation());
Douglas Gregorcb7b1e12010-11-12 07:15:47 +0000663 if (PLoc.isValid()) {
Douglas Gregor16834e82010-05-28 21:47:04 +0000664 OS << " at " << PLoc.getFilename()
665 << ':' << PLoc.getLine()
666 << ':' << PLoc.getColumn();
667 }
Douglas Gregor84139d62010-04-05 21:25:31 +0000668 }
669
670 OS << '>';
John McCall73061d02010-03-19 07:56:44 +0000671 }
John McCall7c2342d2010-03-10 11:27:22 +0000672
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000673 // If this is a class template specialization, print the template
674 // arguments.
675 if (ClassTemplateSpecializationDecl *Spec
John McCall7c2342d2010-03-10 11:27:22 +0000676 = dyn_cast<ClassTemplateSpecializationDecl>(D)) {
John McCall3cb0ebd2010-03-10 03:28:59 +0000677 const TemplateArgument *Args;
678 unsigned NumArgs;
679 if (TypeSourceInfo *TAW = Spec->getTypeAsWritten()) {
680 const TemplateSpecializationType *TST =
681 cast<TemplateSpecializationType>(TAW->getType());
682 Args = TST->getArgs();
683 NumArgs = TST->getNumArgs();
684 } else {
685 const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs();
Douglas Gregor910f8002010-11-07 23:05:16 +0000686 Args = TemplateArgs.data();
687 NumArgs = TemplateArgs.size();
John McCall3cb0ebd2010-03-10 03:28:59 +0000688 }
John McCallf85e1932011-06-15 23:02:42 +0000689 IncludeStrongLifetimeRAII Strong(Policy);
John McCall7c2342d2010-03-10 11:27:22 +0000690 Buffer += TemplateSpecializationType::PrintTemplateArgumentList(Args,
691 NumArgs,
692 Policy);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000693 }
John McCall7c2342d2010-03-10 11:27:22 +0000694
695 if (!InnerString.empty()) {
696 Buffer += ' ';
697 Buffer += InnerString;
698 }
699
700 std::swap(Buffer, InnerString);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000701}
702
John McCall49f4e1c2010-12-10 11:01:00 +0000703void TypePrinter::printRecord(const RecordType *T, std::string &S) {
704 printTag(T->getDecl(), S);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000705}
706
John McCall49f4e1c2010-12-10 11:01:00 +0000707void TypePrinter::printEnum(const EnumType *T, std::string &S) {
708 printTag(T->getDecl(), S);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000709}
710
John McCall49f4e1c2010-12-10 11:01:00 +0000711void TypePrinter::printTemplateTypeParm(const TemplateTypeParmType *T,
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000712 std::string &S) {
713 if (!S.empty()) // Prefix the basic type, e.g. 'parmname X'.
714 S = ' ' + S;
Chandler Carruth4fb86f82011-05-01 00:51:33 +0000715
Chandler Carruthb7efff42011-05-01 01:05:51 +0000716 if (IdentifierInfo *Id = T->getIdentifier())
Chandler Carruth4fb86f82011-05-01 00:51:33 +0000717 S = Id->getName().str() + S;
718 else
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000719 S = "type-parameter-" + llvm::utostr_32(T->getDepth()) + '-' +
720 llvm::utostr_32(T->getIndex()) + S;
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000721}
722
John McCall49f4e1c2010-12-10 11:01:00 +0000723void TypePrinter::printSubstTemplateTypeParm(const SubstTemplateTypeParmType *T,
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000724 std::string &S) {
John McCallf85e1932011-06-15 23:02:42 +0000725 IncludeStrongLifetimeRAII Strong(Policy);
John McCall49f4e1c2010-12-10 11:01:00 +0000726 print(T->getReplacementType(), S);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000727}
728
Douglas Gregorc3069d62011-01-14 02:55:32 +0000729void TypePrinter::printSubstTemplateTypeParmPack(
730 const SubstTemplateTypeParmPackType *T,
731 std::string &S) {
John McCallf85e1932011-06-15 23:02:42 +0000732 IncludeStrongLifetimeRAII Strong(Policy);
Douglas Gregorc3069d62011-01-14 02:55:32 +0000733 printTemplateTypeParm(T->getReplacedParameter(), S);
734}
735
John McCall49f4e1c2010-12-10 11:01:00 +0000736void TypePrinter::printTemplateSpecialization(
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000737 const TemplateSpecializationType *T,
738 std::string &S) {
John McCallf85e1932011-06-15 23:02:42 +0000739 IncludeStrongLifetimeRAII Strong(Policy);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000740 std::string SpecString;
741
742 {
743 llvm::raw_string_ostream OS(SpecString);
744 T->getTemplateName().print(OS, Policy);
745 }
746
747 SpecString += TemplateSpecializationType::PrintTemplateArgumentList(
748 T->getArgs(),
749 T->getNumArgs(),
750 Policy);
751 if (S.empty())
752 S.swap(SpecString);
753 else
754 S = SpecString + ' ' + S;
755}
756
John McCall49f4e1c2010-12-10 11:01:00 +0000757void TypePrinter::printInjectedClassName(const InjectedClassNameType *T,
John McCall3cb0ebd2010-03-10 03:28:59 +0000758 std::string &S) {
John McCall49f4e1c2010-12-10 11:01:00 +0000759 printTemplateSpecialization(T->getInjectedTST(), S);
John McCall3cb0ebd2010-03-10 03:28:59 +0000760}
761
John McCall49f4e1c2010-12-10 11:01:00 +0000762void TypePrinter::printElaborated(const ElaboratedType *T, std::string &S) {
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000763 std::string MyString;
764
765 {
766 llvm::raw_string_ostream OS(MyString);
Abramo Bagnara465d41b2010-05-11 21:36:43 +0000767 OS << TypeWithKeyword::getKeywordName(T->getKeyword());
768 if (T->getKeyword() != ETK_None)
769 OS << " ";
770 NestedNameSpecifier* Qualifier = T->getQualifier();
771 if (Qualifier)
772 Qualifier->print(OS, Policy);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000773 }
774
775 std::string TypeStr;
776 PrintingPolicy InnerPolicy(Policy);
Abramo Bagnara0daaf322011-03-16 20:16:18 +0000777 InnerPolicy.SuppressTagKeyword = true;
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000778 InnerPolicy.SuppressScope = true;
John McCall49f4e1c2010-12-10 11:01:00 +0000779 TypePrinter(InnerPolicy).print(T->getNamedType(), TypeStr);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000780
781 MyString += TypeStr;
782 if (S.empty())
783 S.swap(MyString);
784 else
785 S = MyString + ' ' + S;
786}
787
Abramo Bagnara075f8f12010-12-10 16:29:40 +0000788void TypePrinter::printParen(const ParenType *T, std::string &S) {
789 if (!S.empty() && !isa<FunctionType>(T->getInnerType()))
790 S = '(' + S + ')';
791 print(T->getInnerType(), S);
792}
793
John McCall49f4e1c2010-12-10 11:01:00 +0000794void TypePrinter::printDependentName(const DependentNameType *T, std::string &S) {
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000795 std::string MyString;
796
797 {
798 llvm::raw_string_ostream OS(MyString);
Abramo Bagnara465d41b2010-05-11 21:36:43 +0000799 OS << TypeWithKeyword::getKeywordName(T->getKeyword());
800 if (T->getKeyword() != ETK_None)
801 OS << " ";
Douglas Gregor4a2023f2010-03-31 20:19:30 +0000802
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000803 T->getQualifier()->print(OS, Policy);
804
John McCall33500952010-06-11 00:33:02 +0000805 OS << T->getIdentifier()->getName();
806 }
807
808 if (S.empty())
809 S.swap(MyString);
810 else
811 S = MyString + ' ' + S;
812}
813
John McCall49f4e1c2010-12-10 11:01:00 +0000814void TypePrinter::printDependentTemplateSpecialization(
John McCall33500952010-06-11 00:33:02 +0000815 const DependentTemplateSpecializationType *T, std::string &S) {
John McCallf85e1932011-06-15 23:02:42 +0000816 IncludeStrongLifetimeRAII Strong(Policy);
John McCall33500952010-06-11 00:33:02 +0000817 std::string MyString;
818 {
819 llvm::raw_string_ostream OS(MyString);
820
821 OS << TypeWithKeyword::getKeywordName(T->getKeyword());
822 if (T->getKeyword() != ETK_None)
823 OS << " ";
824
Douglas Gregora88f09f2011-02-28 17:23:35 +0000825 if (T->getQualifier())
826 T->getQualifier()->print(OS, Policy);
John McCall33500952010-06-11 00:33:02 +0000827 OS << T->getIdentifier()->getName();
828 OS << TemplateSpecializationType::PrintTemplateArgumentList(
829 T->getArgs(),
830 T->getNumArgs(),
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000831 Policy);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000832 }
833
834 if (S.empty())
835 S.swap(MyString);
836 else
837 S = MyString + ' ' + S;
838}
839
Douglas Gregor7536dd52010-12-20 02:24:11 +0000840void TypePrinter::printPackExpansion(const PackExpansionType *T,
841 std::string &S) {
842 print(T->getPattern(), S);
843 S += "...";
844}
845
John McCall9d156a72011-01-06 01:58:22 +0000846void TypePrinter::printAttributed(const AttributedType *T,
847 std::string &S) {
John McCallf85e1932011-06-15 23:02:42 +0000848 // Prefer the macro forms of the GC and lifetime qualifiers.
849 if (T->getAttrKind() == AttributedType::attr_objc_gc ||
850 T->getAttrKind() == AttributedType::attr_objc_lifetime)
John McCall14aa2172011-03-04 04:00:19 +0000851 return print(T->getEquivalentType(), S);
852
John McCall9d156a72011-01-06 01:58:22 +0000853 print(T->getModifiedType(), S);
854
855 // TODO: not all attributes are GCC-style attributes.
John McCall14aa2172011-03-04 04:00:19 +0000856 S += " __attribute__((";
John McCall9d156a72011-01-06 01:58:22 +0000857 switch (T->getAttrKind()) {
Francois Pichet170464b2011-01-07 03:17:31 +0000858 case AttributedType::attr_address_space:
John McCall9d156a72011-01-06 01:58:22 +0000859 S += "address_space(";
860 S += T->getEquivalentType().getAddressSpace();
861 S += ")";
862 break;
863
Francois Pichet170464b2011-01-07 03:17:31 +0000864 case AttributedType::attr_vector_size: {
John McCall9d156a72011-01-06 01:58:22 +0000865 S += "__vector_size__(";
866 if (const VectorType *vector =T->getEquivalentType()->getAs<VectorType>()) {
867 S += vector->getNumElements();
868 S += " * sizeof(";
869
870 std::string tmp;
871 print(vector->getElementType(), tmp);
872 S += tmp;
873 S += ")";
874 }
875 S += ")";
876 break;
877 }
878
Francois Pichet170464b2011-01-07 03:17:31 +0000879 case AttributedType::attr_neon_vector_type:
880 case AttributedType::attr_neon_polyvector_type: {
881 if (T->getAttrKind() == AttributedType::attr_neon_vector_type)
John McCall9d156a72011-01-06 01:58:22 +0000882 S += "neon_vector_type(";
883 else
884 S += "neon_polyvector_type(";
885 const VectorType *vector = T->getEquivalentType()->getAs<VectorType>();
886 S += llvm::utostr_32(vector->getNumElements());
887 S += ")";
888 break;
889 }
890
Francois Pichet170464b2011-01-07 03:17:31 +0000891 case AttributedType::attr_regparm: {
John McCall9d156a72011-01-06 01:58:22 +0000892 S += "regparm(";
893 QualType t = T->getEquivalentType();
894 while (!t->isFunctionType())
895 t = t->getPointeeType();
896 S += t->getAs<FunctionType>()->getRegParmType();
897 S += ")";
898 break;
899 }
900
Francois Pichet170464b2011-01-07 03:17:31 +0000901 case AttributedType::attr_objc_gc: {
John McCall9d156a72011-01-06 01:58:22 +0000902 S += "objc_gc(";
903
904 QualType tmp = T->getEquivalentType();
905 while (tmp.getObjCGCAttr() == Qualifiers::GCNone) {
906 QualType next = tmp->getPointeeType();
907 if (next == tmp) break;
908 tmp = next;
909 }
910
911 if (tmp.isObjCGCWeak())
912 S += "weak";
913 else
914 S += "strong";
915 S += ")";
916 break;
917 }
918
John McCallf85e1932011-06-15 23:02:42 +0000919 case AttributedType::attr_objc_lifetime:
920 S += "objc_lifetime(";
921 switch (T->getEquivalentType().getObjCLifetime()) {
922 case Qualifiers::OCL_None: llvm_unreachable("no lifetime!"); break;
923 case Qualifiers::OCL_ExplicitNone: S += "none"; break;
924 case Qualifiers::OCL_Strong: S += "strong"; break;
925 case Qualifiers::OCL_Weak: S += "weak"; break;
926 case Qualifiers::OCL_Autoreleasing: S += "autoreleasing"; break;
927 }
928 S += ")";
929 break;
930
Francois Pichet3cd47e72011-01-07 02:58:13 +0000931 case AttributedType::attr_noreturn: S += "noreturn"; break;
932 case AttributedType::attr_cdecl: S += "cdecl"; break;
933 case AttributedType::attr_fastcall: S += "fastcall"; break;
934 case AttributedType::attr_stdcall: S += "stdcall"; break;
935 case AttributedType::attr_thiscall: S += "thiscall"; break;
936 case AttributedType::attr_pascal: S += "pascal"; break;
Anton Korobeynikov414d8962011-04-14 20:06:49 +0000937 case AttributedType::attr_pcs: {
938 S += "pcs(";
939 QualType t = T->getEquivalentType();
940 while (!t->isFunctionType())
941 t = t->getPointeeType();
942 S += (t->getAs<FunctionType>()->getCallConv() == CC_AAPCS ?
943 "\"aapcs\"" : "\"aapcs-vfp\"");
944 S += ")";
945 break;
946 }
John McCall9d156a72011-01-06 01:58:22 +0000947 }
948 S += "))";
949}
950
John McCall49f4e1c2010-12-10 11:01:00 +0000951void TypePrinter::printObjCInterface(const ObjCInterfaceType *T,
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000952 std::string &S) {
953 if (!S.empty()) // Prefix the basic type, e.g. 'typedefname X'.
954 S = ' ' + S;
John McCallc12c5bb2010-05-15 11:32:37 +0000955
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000956 std::string ObjCQIString = T->getDecl()->getNameAsString();
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000957 S = ObjCQIString + S;
958}
959
John McCall49f4e1c2010-12-10 11:01:00 +0000960void TypePrinter::printObjCObject(const ObjCObjectType *T,
John McCallc12c5bb2010-05-15 11:32:37 +0000961 std::string &S) {
962 if (T->qual_empty())
John McCall49f4e1c2010-12-10 11:01:00 +0000963 return print(T->getBaseType(), S);
John McCallc12c5bb2010-05-15 11:32:37 +0000964
965 std::string tmp;
John McCall49f4e1c2010-12-10 11:01:00 +0000966 print(T->getBaseType(), tmp);
John McCallc12c5bb2010-05-15 11:32:37 +0000967 tmp += '<';
968 bool isFirst = true;
969 for (ObjCObjectType::qual_iterator
970 I = T->qual_begin(), E = T->qual_end(); I != E; ++I) {
971 if (isFirst)
972 isFirst = false;
973 else
974 tmp += ',';
975 tmp += (*I)->getNameAsString();
976 }
977 tmp += '>';
978
979 if (!S.empty()) {
980 tmp += ' ';
981 tmp += S;
982 }
983 std::swap(tmp, S);
984}
985
John McCall49f4e1c2010-12-10 11:01:00 +0000986void TypePrinter::printObjCObjectPointer(const ObjCObjectPointerType *T,
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000987 std::string &S) {
988 std::string ObjCQIString;
989
Chris Lattnerd7e52b82010-09-05 00:43:21 +0000990 T->getPointeeType().getLocalQualifiers().getAsStringInternal(ObjCQIString,
991 Policy);
992 if (!ObjCQIString.empty())
993 ObjCQIString += ' ';
994
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000995 if (T->isObjCIdType() || T->isObjCQualifiedIdType())
Chris Lattnerd7e52b82010-09-05 00:43:21 +0000996 ObjCQIString += "id";
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000997 else if (T->isObjCClassType() || T->isObjCQualifiedClassType())
Chris Lattnerd7e52b82010-09-05 00:43:21 +0000998 ObjCQIString += "Class";
Fariborz Jahanian13dcd002009-11-21 19:53:08 +0000999 else if (T->isObjCSelType())
Chris Lattnerd7e52b82010-09-05 00:43:21 +00001000 ObjCQIString += "SEL";
Douglas Gregorfee8a3c2009-11-10 00:39:07 +00001001 else
Chris Lattnerd7e52b82010-09-05 00:43:21 +00001002 ObjCQIString += T->getInterfaceDecl()->getNameAsString();
Douglas Gregorfee8a3c2009-11-10 00:39:07 +00001003
1004 if (!T->qual_empty()) {
1005 ObjCQIString += '<';
1006 for (ObjCObjectPointerType::qual_iterator I = T->qual_begin(),
1007 E = T->qual_end();
1008 I != E; ++I) {
1009 ObjCQIString += (*I)->getNameAsString();
1010 if (I+1 != E)
1011 ObjCQIString += ',';
1012 }
1013 ObjCQIString += '>';
1014 }
1015
Douglas Gregorfee8a3c2009-11-10 00:39:07 +00001016 if (!T->isObjCIdType() && !T->isObjCQualifiedIdType())
1017 ObjCQIString += " *"; // Don't forget the implicit pointer.
1018 else if (!S.empty()) // Prefix the basic type, e.g. 'typedefname X'.
1019 S = ' ' + S;
1020
1021 S = ObjCQIString + S;
1022}
1023
John McCalld5532b62009-11-23 01:53:49 +00001024std::string TemplateSpecializationType::
1025 PrintTemplateArgumentList(const TemplateArgumentListInfo &Args,
1026 const PrintingPolicy &Policy) {
1027 return PrintTemplateArgumentList(Args.getArgumentArray(),
1028 Args.size(),
1029 Policy);
1030}
1031
Douglas Gregorfee8a3c2009-11-10 00:39:07 +00001032std::string
1033TemplateSpecializationType::PrintTemplateArgumentList(
1034 const TemplateArgument *Args,
1035 unsigned NumArgs,
Douglas Gregordace95b2010-12-20 22:28:59 +00001036 const PrintingPolicy &Policy,
1037 bool SkipBrackets) {
Douglas Gregorfee8a3c2009-11-10 00:39:07 +00001038 std::string SpecString;
Douglas Gregordace95b2010-12-20 22:28:59 +00001039 if (!SkipBrackets)
1040 SpecString += '<';
1041
Douglas Gregorfee8a3c2009-11-10 00:39:07 +00001042 for (unsigned Arg = 0; Arg < NumArgs; ++Arg) {
Francois Pichet319b4a62011-05-25 16:07:10 +00001043 if (SpecString.size() > unsigned(!SkipBrackets))
Douglas Gregorfee8a3c2009-11-10 00:39:07 +00001044 SpecString += ", ";
1045
1046 // Print the argument into a string.
1047 std::string ArgString;
Douglas Gregordace95b2010-12-20 22:28:59 +00001048 if (Args[Arg].getKind() == TemplateArgument::Pack) {
1049 ArgString = PrintTemplateArgumentList(Args[Arg].pack_begin(),
1050 Args[Arg].pack_size(),
1051 Policy, true);
1052 } else {
Douglas Gregor87dd6972010-12-20 16:52:59 +00001053 llvm::raw_string_ostream ArgOut(ArgString);
1054 Args[Arg].print(Policy, ArgOut);
1055 }
1056
Douglas Gregorfee8a3c2009-11-10 00:39:07 +00001057 // If this is the first argument and its string representation
1058 // begins with the global scope specifier ('::foo'), add a space
1059 // to avoid printing the diagraph '<:'.
1060 if (!Arg && !ArgString.empty() && ArgString[0] == ':')
1061 SpecString += ' ';
1062
1063 SpecString += ArgString;
1064 }
1065
1066 // If the last character of our string is '>', add another space to
1067 // keep the two '>''s separate tokens. We don't *have* to do this in
1068 // C++0x, but it's still good hygiene.
Francois Pichetb5bc7d02011-01-09 22:32:25 +00001069 if (!SpecString.empty() && SpecString[SpecString.size() - 1] == '>')
Douglas Gregorfee8a3c2009-11-10 00:39:07 +00001070 SpecString += ' ';
1071
Douglas Gregordace95b2010-12-20 22:28:59 +00001072 if (!SkipBrackets)
1073 SpecString += '>';
Douglas Gregorfee8a3c2009-11-10 00:39:07 +00001074
1075 return SpecString;
1076}
1077
1078// Sadly, repeat all that with TemplateArgLoc.
1079std::string TemplateSpecializationType::
1080PrintTemplateArgumentList(const TemplateArgumentLoc *Args, unsigned NumArgs,
1081 const PrintingPolicy &Policy) {
1082 std::string SpecString;
1083 SpecString += '<';
1084 for (unsigned Arg = 0; Arg < NumArgs; ++Arg) {
Douglas Gregordace95b2010-12-20 22:28:59 +00001085 if (SpecString.size() > 1)
Douglas Gregorfee8a3c2009-11-10 00:39:07 +00001086 SpecString += ", ";
1087
1088 // Print the argument into a string.
1089 std::string ArgString;
Douglas Gregordace95b2010-12-20 22:28:59 +00001090 if (Args[Arg].getArgument().getKind() == TemplateArgument::Pack) {
1091 ArgString = PrintTemplateArgumentList(
1092 Args[Arg].getArgument().pack_begin(),
1093 Args[Arg].getArgument().pack_size(),
1094 Policy, true);
1095 } else {
Douglas Gregor87dd6972010-12-20 16:52:59 +00001096 llvm::raw_string_ostream ArgOut(ArgString);
1097 Args[Arg].getArgument().print(Policy, ArgOut);
1098 }
Douglas Gregorfee8a3c2009-11-10 00:39:07 +00001099
1100 // If this is the first argument and its string representation
1101 // begins with the global scope specifier ('::foo'), add a space
1102 // to avoid printing the diagraph '<:'.
1103 if (!Arg && !ArgString.empty() && ArgString[0] == ':')
1104 SpecString += ' ';
1105
1106 SpecString += ArgString;
1107 }
1108
1109 // If the last character of our string is '>', add another space to
1110 // keep the two '>''s separate tokens. We don't *have* to do this in
1111 // C++0x, but it's still good hygiene.
1112 if (SpecString[SpecString.size() - 1] == '>')
1113 SpecString += ' ';
1114
1115 SpecString += '>';
1116
1117 return SpecString;
1118}
1119
1120void QualType::dump(const char *msg) const {
1121 std::string R = "identifier";
1122 LangOptions LO;
1123 getAsStringInternal(R, PrintingPolicy(LO));
1124 if (msg)
Daniel Dunbare7cb7e42009-12-03 09:14:02 +00001125 llvm::errs() << msg << ": ";
1126 llvm::errs() << R << "\n";
Douglas Gregorfee8a3c2009-11-10 00:39:07 +00001127}
1128void QualType::dump() const {
1129 dump("");
1130}
1131
1132void Type::dump() const {
1133 QualType(this, 0).dump();
1134}
1135
1136std::string Qualifiers::getAsString() const {
1137 LangOptions LO;
1138 return getAsString(PrintingPolicy(LO));
1139}
1140
1141// Appends qualifiers to the given string, separated by spaces. Will
1142// prefix a space if the string is non-empty. Will not append a final
1143// space.
1144void Qualifiers::getAsStringInternal(std::string &S,
John McCallf85e1932011-06-15 23:02:42 +00001145 const PrintingPolicy& Policy) const {
Douglas Gregorfee8a3c2009-11-10 00:39:07 +00001146 AppendTypeQualList(S, getCVRQualifiers());
John McCall14aa2172011-03-04 04:00:19 +00001147 if (unsigned addrspace = getAddressSpace()) {
Douglas Gregorfee8a3c2009-11-10 00:39:07 +00001148 if (!S.empty()) S += ' ';
1149 S += "__attribute__((address_space(";
John McCall14aa2172011-03-04 04:00:19 +00001150 S += llvm::utostr_32(addrspace);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +00001151 S += ")))";
1152 }
John McCall14aa2172011-03-04 04:00:19 +00001153 if (Qualifiers::GC gc = getObjCGCAttr()) {
Douglas Gregorfee8a3c2009-11-10 00:39:07 +00001154 if (!S.empty()) S += ' ';
John McCall14aa2172011-03-04 04:00:19 +00001155 if (gc == Qualifiers::Weak)
1156 S += "__weak";
Douglas Gregorfee8a3c2009-11-10 00:39:07 +00001157 else
John McCall14aa2172011-03-04 04:00:19 +00001158 S += "__strong";
Douglas Gregorfee8a3c2009-11-10 00:39:07 +00001159 }
John McCallf85e1932011-06-15 23:02:42 +00001160 if (Qualifiers::ObjCLifetime lifetime = getObjCLifetime()) {
1161 if (!S.empty() &&
1162 !(lifetime == Qualifiers::OCL_Strong && Policy.SuppressStrongLifetime))
1163 S += ' ';
1164
1165 switch (lifetime) {
1166 case Qualifiers::OCL_None: llvm_unreachable("none but true");
1167 case Qualifiers::OCL_ExplicitNone: S += "__unsafe_unretained"; break;
1168 case Qualifiers::OCL_Strong:
1169 if (!Policy.SuppressStrongLifetime)
1170 S += "__strong";
1171 break;
1172
1173 case Qualifiers::OCL_Weak: S += "__weak"; break;
1174 case Qualifiers::OCL_Autoreleasing: S += "__autoreleasing"; break;
1175 }
1176 }
Douglas Gregorfee8a3c2009-11-10 00:39:07 +00001177}
1178
John McCall49f4e1c2010-12-10 11:01:00 +00001179std::string QualType::getAsString(const Type *ty, Qualifiers qs) {
1180 std::string buffer;
1181 LangOptions options;
1182 getAsStringInternal(ty, qs, buffer, PrintingPolicy(options));
1183 return buffer;
Douglas Gregorfee8a3c2009-11-10 00:39:07 +00001184}
1185
John McCall49f4e1c2010-12-10 11:01:00 +00001186void QualType::getAsStringInternal(const Type *ty, Qualifiers qs,
1187 std::string &buffer,
1188 const PrintingPolicy &policy) {
1189 TypePrinter(policy).print(ty, qs, buffer);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +00001190}