blob: e11e5065728c4d831e2e7beb49696277fda8cc0b [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:
Eli Friedmanb001de72011-10-06 23:00:33 +0000126 case Type::Atomic:
Douglas Gregorc6daf0b2011-02-17 06:52:25 +0000127 CanPrefixQualifiers = true;
128 break;
129
130 case Type::ObjCObjectPointer:
131 CanPrefixQualifiers = T->isObjCIdType() || T->isObjCClassType() ||
132 T->isObjCQualifiedIdType() || T->isObjCQualifiedClassType();
133 break;
134
John McCallf85e1932011-06-15 23:02:42 +0000135 case Type::ConstantArray:
136 case Type::IncompleteArray:
137 case Type::VariableArray:
138 case Type::DependentSizedArray:
139 NeedARCStrongQualifier = true;
140 // Fall through
141
Douglas Gregorc6daf0b2011-02-17 06:52:25 +0000142 case Type::Pointer:
143 case Type::BlockPointer:
144 case Type::LValueReference:
145 case Type::RValueReference:
146 case Type::MemberPointer:
Douglas Gregorc6daf0b2011-02-17 06:52:25 +0000147 case Type::DependentSizedExtVector:
148 case Type::Vector:
149 case Type::ExtVector:
150 case Type::FunctionProto:
151 case Type::FunctionNoProto:
152 case Type::Paren:
153 case Type::Attributed:
154 case Type::PackExpansion:
155 case Type::SubstTemplateTypeParm:
Richard Smith34b41d92011-02-20 03:19:35 +0000156 case Type::Auto:
Douglas Gregorc6daf0b2011-02-17 06:52:25 +0000157 CanPrefixQualifiers = false;
158 break;
159 }
Chris Lattner58f9e132010-09-05 00:04:01 +0000160
161 if (!CanPrefixQualifiers && !Quals.empty()) {
John McCall49f4e1c2010-12-10 11:01:00 +0000162 std::string qualsBuffer;
John McCallf85e1932011-06-15 23:02:42 +0000163 if (NeedARCStrongQualifier) {
164 IncludeStrongLifetimeRAII Strong(Policy);
165 Quals.getAsStringInternal(qualsBuffer, Policy);
166 } else {
167 Quals.getAsStringInternal(qualsBuffer, Policy);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000168 }
John McCallf85e1932011-06-15 23:02:42 +0000169
170 if (!qualsBuffer.empty()) {
171 if (!buffer.empty()) {
172 qualsBuffer += ' ';
173 qualsBuffer += buffer;
174 }
175 std::swap(buffer, qualsBuffer);
176 }
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000177 }
178
179 switch (T->getTypeClass()) {
180#define ABSTRACT_TYPE(CLASS, PARENT)
John McCall49f4e1c2010-12-10 11:01:00 +0000181#define TYPE(CLASS, PARENT) case Type::CLASS: \
182 print##CLASS(cast<CLASS##Type>(T), buffer); \
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000183 break;
184#include "clang/AST/TypeNodes.def"
185 }
Chris Lattner58f9e132010-09-05 00:04:01 +0000186
187 // If we're adding the qualifiers as a prefix, do it now.
188 if (CanPrefixQualifiers && !Quals.empty()) {
John McCall49f4e1c2010-12-10 11:01:00 +0000189 std::string qualsBuffer;
John McCallf85e1932011-06-15 23:02:42 +0000190 if (NeedARCStrongQualifier) {
191 IncludeStrongLifetimeRAII Strong(Policy);
192 Quals.getAsStringInternal(qualsBuffer, Policy);
193 } else {
194 Quals.getAsStringInternal(qualsBuffer, Policy);
Chris Lattner58f9e132010-09-05 00:04:01 +0000195 }
John McCallf85e1932011-06-15 23:02:42 +0000196
197 if (!qualsBuffer.empty()) {
198 if (!buffer.empty()) {
199 qualsBuffer += ' ';
200 qualsBuffer += buffer;
201 }
202 std::swap(buffer, qualsBuffer);
203 }
Chris Lattner58f9e132010-09-05 00:04:01 +0000204 }
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000205}
206
John McCall49f4e1c2010-12-10 11:01:00 +0000207void TypePrinter::printBuiltin(const BuiltinType *T, std::string &S) {
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000208 if (S.empty()) {
Douglas Gregor30c42402011-09-27 22:38:19 +0000209 S = T->getName(Policy);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000210 } else {
211 // Prefix the basic type, e.g. 'int X'.
Chris Lattner59742de2010-09-04 23:43:40 +0000212 S = ' ' + S;
Douglas Gregor30c42402011-09-27 22:38:19 +0000213 S = T->getName(Policy) + S;
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000214 }
215}
216
John McCall49f4e1c2010-12-10 11:01:00 +0000217void TypePrinter::printComplex(const ComplexType *T, std::string &S) {
218 print(T->getElementType(), S);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000219 S = "_Complex " + S;
220}
221
John McCall49f4e1c2010-12-10 11:01:00 +0000222void TypePrinter::printPointer(const PointerType *T, std::string &S) {
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000223 S = '*' + S;
224
225 // Handle things like 'int (*A)[4];' correctly.
226 // FIXME: this should include vectors, but vectors use attributes I guess.
227 if (isa<ArrayType>(T->getPointeeType()))
228 S = '(' + S + ')';
229
John McCallf85e1932011-06-15 23:02:42 +0000230 IncludeStrongLifetimeRAII Strong(Policy);
John McCall49f4e1c2010-12-10 11:01:00 +0000231 print(T->getPointeeType(), S);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000232}
233
John McCall49f4e1c2010-12-10 11:01:00 +0000234void TypePrinter::printBlockPointer(const BlockPointerType *T, std::string &S) {
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000235 S = '^' + S;
John McCall49f4e1c2010-12-10 11:01:00 +0000236 print(T->getPointeeType(), S);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000237}
238
John McCall49f4e1c2010-12-10 11:01:00 +0000239void TypePrinter::printLValueReference(const LValueReferenceType *T,
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000240 std::string &S) {
241 S = '&' + S;
242
243 // Handle things like 'int (&A)[4];' correctly.
244 // FIXME: this should include vectors, but vectors use attributes I guess.
245 if (isa<ArrayType>(T->getPointeeTypeAsWritten()))
246 S = '(' + S + ')';
247
John McCallf85e1932011-06-15 23:02:42 +0000248 IncludeStrongLifetimeRAII Strong(Policy);
John McCall49f4e1c2010-12-10 11:01:00 +0000249 print(T->getPointeeTypeAsWritten(), S);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000250}
251
John McCall49f4e1c2010-12-10 11:01:00 +0000252void TypePrinter::printRValueReference(const RValueReferenceType *T,
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000253 std::string &S) {
254 S = "&&" + S;
255
256 // Handle things like 'int (&&A)[4];' correctly.
257 // FIXME: this should include vectors, but vectors use attributes I guess.
258 if (isa<ArrayType>(T->getPointeeTypeAsWritten()))
259 S = '(' + S + ')';
260
John McCallf85e1932011-06-15 23:02:42 +0000261 IncludeStrongLifetimeRAII Strong(Policy);
John McCall49f4e1c2010-12-10 11:01:00 +0000262 print(T->getPointeeTypeAsWritten(), S);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000263}
264
John McCall49f4e1c2010-12-10 11:01:00 +0000265void TypePrinter::printMemberPointer(const MemberPointerType *T,
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000266 std::string &S) {
267 std::string C;
John McCall49f4e1c2010-12-10 11:01:00 +0000268 print(QualType(T->getClass(), 0), C);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000269 C += "::*";
270 S = C + S;
271
272 // Handle things like 'int (Cls::*A)[4];' correctly.
273 // FIXME: this should include vectors, but vectors use attributes I guess.
274 if (isa<ArrayType>(T->getPointeeType()))
275 S = '(' + S + ')';
276
John McCallf85e1932011-06-15 23:02:42 +0000277 IncludeStrongLifetimeRAII Strong(Policy);
John McCall49f4e1c2010-12-10 11:01:00 +0000278 print(T->getPointeeType(), S);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000279}
280
John McCall49f4e1c2010-12-10 11:01:00 +0000281void TypePrinter::printConstantArray(const ConstantArrayType *T,
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000282 std::string &S) {
283 S += '[';
284 S += llvm::utostr(T->getSize().getZExtValue());
285 S += ']';
286
John McCallf85e1932011-06-15 23:02:42 +0000287 IncludeStrongLifetimeRAII Strong(Policy);
John McCall49f4e1c2010-12-10 11:01:00 +0000288 print(T->getElementType(), S);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000289}
290
John McCall49f4e1c2010-12-10 11:01:00 +0000291void TypePrinter::printIncompleteArray(const IncompleteArrayType *T,
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000292 std::string &S) {
293 S += "[]";
John McCallf85e1932011-06-15 23:02:42 +0000294 IncludeStrongLifetimeRAII Strong(Policy);
John McCall49f4e1c2010-12-10 11:01:00 +0000295 print(T->getElementType(), S);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000296}
297
John McCall49f4e1c2010-12-10 11:01:00 +0000298void TypePrinter::printVariableArray(const VariableArrayType *T,
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000299 std::string &S) {
300 S += '[';
301
302 if (T->getIndexTypeQualifiers().hasQualifiers()) {
303 AppendTypeQualList(S, T->getIndexTypeCVRQualifiers());
304 S += ' ';
305 }
306
307 if (T->getSizeModifier() == VariableArrayType::Static)
308 S += "static";
309 else if (T->getSizeModifier() == VariableArrayType::Star)
310 S += '*';
311
312 if (T->getSizeExpr()) {
313 std::string SStr;
314 llvm::raw_string_ostream s(SStr);
315 T->getSizeExpr()->printPretty(s, 0, Policy);
316 S += s.str();
317 }
318 S += ']';
319
John McCallf85e1932011-06-15 23:02:42 +0000320 IncludeStrongLifetimeRAII Strong(Policy);
John McCall49f4e1c2010-12-10 11:01:00 +0000321 print(T->getElementType(), S);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000322}
323
John McCall49f4e1c2010-12-10 11:01:00 +0000324void TypePrinter::printDependentSizedArray(const DependentSizedArrayType *T,
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000325 std::string &S) {
326 S += '[';
327
328 if (T->getSizeExpr()) {
329 std::string SStr;
330 llvm::raw_string_ostream s(SStr);
331 T->getSizeExpr()->printPretty(s, 0, Policy);
332 S += s.str();
333 }
334 S += ']';
335
John McCallf85e1932011-06-15 23:02:42 +0000336 IncludeStrongLifetimeRAII Strong(Policy);
John McCall49f4e1c2010-12-10 11:01:00 +0000337 print(T->getElementType(), S);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000338}
339
John McCall49f4e1c2010-12-10 11:01:00 +0000340void TypePrinter::printDependentSizedExtVector(
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000341 const DependentSizedExtVectorType *T,
342 std::string &S) {
John McCall49f4e1c2010-12-10 11:01:00 +0000343 print(T->getElementType(), S);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000344
345 S += " __attribute__((ext_vector_type(";
346 if (T->getSizeExpr()) {
347 std::string SStr;
348 llvm::raw_string_ostream s(SStr);
349 T->getSizeExpr()->printPretty(s, 0, Policy);
350 S += s.str();
351 }
352 S += ")))";
353}
354
John McCall49f4e1c2010-12-10 11:01:00 +0000355void TypePrinter::printVector(const VectorType *T, std::string &S) {
Bob Wilsonec33cbe2010-11-16 00:32:26 +0000356 switch (T->getVectorKind()) {
357 case VectorType::AltiVecPixel:
358 S = "__vector __pixel " + S;
359 break;
360 case VectorType::AltiVecBool:
John McCall49f4e1c2010-12-10 11:01:00 +0000361 print(T->getElementType(), S);
Bob Wilsonec33cbe2010-11-16 00:32:26 +0000362 S = "__vector __bool " + S;
363 break;
364 case VectorType::AltiVecVector:
John McCall49f4e1c2010-12-10 11:01:00 +0000365 print(T->getElementType(), S);
Bob Wilsonec33cbe2010-11-16 00:32:26 +0000366 S = "__vector " + S;
367 break;
368 case VectorType::NeonVector:
John McCall49f4e1c2010-12-10 11:01:00 +0000369 print(T->getElementType(), S);
Bob Wilsonec33cbe2010-11-16 00:32:26 +0000370 S = ("__attribute__((neon_vector_type(" +
371 llvm::utostr_32(T->getNumElements()) + "))) " + S);
372 break;
373 case VectorType::NeonPolyVector:
John McCall49f4e1c2010-12-10 11:01:00 +0000374 print(T->getElementType(), S);
Bob Wilsonec33cbe2010-11-16 00:32:26 +0000375 S = ("__attribute__((neon_polyvector_type(" +
376 llvm::utostr_32(T->getNumElements()) + "))) " + S);
377 break;
378 case VectorType::GenericVector: {
John Thompson82287d12010-02-05 00:12:22 +0000379 // FIXME: We prefer to print the size directly here, but have no way
380 // to get the size of the type.
John McCall49f4e1c2010-12-10 11:01:00 +0000381 print(T->getElementType(), S);
John Thompson82287d12010-02-05 00:12:22 +0000382 std::string V = "__attribute__((__vector_size__(";
383 V += llvm::utostr_32(T->getNumElements()); // convert back to bytes.
384 std::string ET;
John McCall49f4e1c2010-12-10 11:01:00 +0000385 print(T->getElementType(), ET);
John Thompson82287d12010-02-05 00:12:22 +0000386 V += " * sizeof(" + ET + ")))) ";
387 S = V + S;
Bob Wilsonec33cbe2010-11-16 00:32:26 +0000388 break;
389 }
John Thompson82287d12010-02-05 00:12:22 +0000390 }
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000391}
392
John McCall49f4e1c2010-12-10 11:01:00 +0000393void TypePrinter::printExtVector(const ExtVectorType *T, std::string &S) {
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000394 S += " __attribute__((ext_vector_type(";
395 S += llvm::utostr_32(T->getNumElements());
396 S += ")))";
John McCall49f4e1c2010-12-10 11:01:00 +0000397 print(T->getElementType(), S);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000398}
399
John McCall49f4e1c2010-12-10 11:01:00 +0000400void TypePrinter::printFunctionProto(const FunctionProtoType *T,
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000401 std::string &S) {
402 // If needed for precedence reasons, wrap the inner part in grouping parens.
403 if (!S.empty())
404 S = "(" + S + ")";
405
406 S += "(";
407 std::string Tmp;
408 PrintingPolicy ParamPolicy(Policy);
409 ParamPolicy.SuppressSpecifiers = false;
410 for (unsigned i = 0, e = T->getNumArgs(); i != e; ++i) {
411 if (i) S += ", ";
John McCall49f4e1c2010-12-10 11:01:00 +0000412 print(T->getArgType(i), Tmp);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000413 S += Tmp;
414 Tmp.clear();
415 }
416
417 if (T->isVariadic()) {
418 if (T->getNumArgs())
419 S += ", ";
420 S += "...";
421 } else if (T->getNumArgs() == 0 && !Policy.LangOpts.CPlusPlus) {
422 // Do not emit int() if we have a proto, emit 'int(void)'.
423 S += "void";
424 }
425
426 S += ")";
Douglas Gregor0ae7b3f2009-12-08 17:45:32 +0000427
Rafael Espindola264ba482010-03-30 20:24:48 +0000428 FunctionType::ExtInfo Info = T->getExtInfo();
429 switch(Info.getCC()) {
John McCallf82b4e82010-02-04 05:44:44 +0000430 case CC_Default:
431 default: break;
432 case CC_C:
433 S += " __attribute__((cdecl))";
434 break;
435 case CC_X86StdCall:
436 S += " __attribute__((stdcall))";
437 break;
438 case CC_X86FastCall:
439 S += " __attribute__((fastcall))";
440 break;
Douglas Gregorf813a2c2010-05-18 16:57:00 +0000441 case CC_X86ThisCall:
442 S += " __attribute__((thiscall))";
443 break;
Dawn Perchik52fc3142010-09-03 01:29:35 +0000444 case CC_X86Pascal:
445 S += " __attribute__((pascal))";
446 break;
Anton Korobeynikov414d8962011-04-14 20:06:49 +0000447 case CC_AAPCS:
448 S += " __attribute__((pcs(\"aapcs\")))";
449 break;
450 case CC_AAPCS_VFP:
451 S += " __attribute__((pcs(\"aapcs-vfp\")))";
452 break;
John McCallf82b4e82010-02-04 05:44:44 +0000453 }
Rafael Espindola264ba482010-03-30 20:24:48 +0000454 if (Info.getNoReturn())
Douglas Gregor48026d22010-01-11 18:40:55 +0000455 S += " __attribute__((noreturn))";
Rafael Espindola425ef722010-03-30 22:15:11 +0000456 if (Info.getRegParm())
457 S += " __attribute__((regparm (" +
458 llvm::utostr_32(Info.getRegParm()) + ")))";
Douglas Gregor48026d22010-01-11 18:40:55 +0000459
Douglas Gregorc938c162011-01-26 05:01:58 +0000460 AppendTypeQualList(S, T->getTypeQuals());
461
462 switch (T->getRefQualifier()) {
463 case RQ_None:
464 break;
465
466 case RQ_LValue:
467 S += " &";
468 break;
469
470 case RQ_RValue:
471 S += " &&";
472 break;
473 }
Sebastian Redl60618fa2011-03-12 11:50:43 +0000474
475 if (T->hasDynamicExceptionSpec()) {
Douglas Gregor0ae7b3f2009-12-08 17:45:32 +0000476 S += " throw(";
Sebastian Redl60618fa2011-03-12 11:50:43 +0000477 if (T->getExceptionSpecType() == EST_MSAny)
Douglas Gregor0ae7b3f2009-12-08 17:45:32 +0000478 S += "...";
Sebastian Redl60618fa2011-03-12 11:50:43 +0000479 else
Douglas Gregor0ae7b3f2009-12-08 17:45:32 +0000480 for (unsigned I = 0, N = T->getNumExceptions(); I != N; ++I) {
481 if (I)
482 S += ", ";
483
484 std::string ExceptionType;
John McCall49f4e1c2010-12-10 11:01:00 +0000485 print(T->getExceptionType(I), ExceptionType);
Douglas Gregor0ae7b3f2009-12-08 17:45:32 +0000486 S += ExceptionType;
487 }
488 S += ")";
Sebastian Redl60618fa2011-03-12 11:50:43 +0000489 } else if (isNoexceptExceptionSpec(T->getExceptionSpecType())) {
490 S += " noexcept";
491 if (T->getExceptionSpecType() == EST_ComputedNoexcept) {
492 S += "(";
493 llvm::raw_string_ostream EOut(S);
494 T->getNoexceptExpr()->printPretty(EOut, 0, Policy);
495 EOut.flush();
496 S += EOut.str();
497 S += ")";
498 }
Douglas Gregor0ae7b3f2009-12-08 17:45:32 +0000499 }
500
John McCall49f4e1c2010-12-10 11:01:00 +0000501 print(T->getResultType(), S);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000502}
503
John McCall49f4e1c2010-12-10 11:01:00 +0000504void TypePrinter::printFunctionNoProto(const FunctionNoProtoType *T,
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000505 std::string &S) {
506 // If needed for precedence reasons, wrap the inner part in grouping parens.
507 if (!S.empty())
508 S = "(" + S + ")";
509
510 S += "()";
511 if (T->getNoReturnAttr())
512 S += " __attribute__((noreturn))";
John McCall49f4e1c2010-12-10 11:01:00 +0000513 print(T->getResultType(), S);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000514}
515
John McCall49f4e1c2010-12-10 11:01:00 +0000516static void printTypeSpec(const NamedDecl *D, std::string &S) {
John McCall3cb0ebd2010-03-10 03:28:59 +0000517 IdentifierInfo *II = D->getIdentifier();
John McCalled976492009-12-04 22:46:56 +0000518 if (S.empty())
519 S = II->getName().str();
520 else
521 S = II->getName().str() + ' ' + S;
522}
523
John McCall49f4e1c2010-12-10 11:01:00 +0000524void TypePrinter::printUnresolvedUsing(const UnresolvedUsingType *T,
John McCall3cb0ebd2010-03-10 03:28:59 +0000525 std::string &S) {
John McCall49f4e1c2010-12-10 11:01:00 +0000526 printTypeSpec(T->getDecl(), S);
John McCall3cb0ebd2010-03-10 03:28:59 +0000527}
528
John McCall49f4e1c2010-12-10 11:01:00 +0000529void TypePrinter::printTypedef(const TypedefType *T, std::string &S) {
530 printTypeSpec(T->getDecl(), S);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000531}
532
John McCall49f4e1c2010-12-10 11:01:00 +0000533void TypePrinter::printTypeOfExpr(const TypeOfExprType *T, std::string &S) {
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000534 if (!S.empty()) // Prefix the basic type, e.g. 'typeof(e) X'.
535 S = ' ' + S;
536 std::string Str;
537 llvm::raw_string_ostream s(Str);
538 T->getUnderlyingExpr()->printPretty(s, 0, Policy);
539 S = "typeof " + s.str() + S;
540}
541
John McCall49f4e1c2010-12-10 11:01:00 +0000542void TypePrinter::printTypeOf(const TypeOfType *T, std::string &S) {
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000543 if (!S.empty()) // Prefix the basic type, e.g. 'typeof(t) X'.
544 S = ' ' + S;
545 std::string Tmp;
John McCall49f4e1c2010-12-10 11:01:00 +0000546 print(T->getUnderlyingType(), Tmp);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000547 S = "typeof(" + Tmp + ")" + S;
548}
549
John McCall49f4e1c2010-12-10 11:01:00 +0000550void TypePrinter::printDecltype(const DecltypeType *T, std::string &S) {
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000551 if (!S.empty()) // Prefix the basic type, e.g. 'decltype(t) X'.
552 S = ' ' + S;
553 std::string Str;
554 llvm::raw_string_ostream s(Str);
555 T->getUnderlyingExpr()->printPretty(s, 0, Policy);
556 S = "decltype(" + s.str() + ")" + S;
557}
558
Sean Huntca63c202011-05-24 22:41:36 +0000559void TypePrinter::printUnaryTransform(const UnaryTransformType *T,
560 std::string &S) {
561 if (!S.empty())
562 S = ' ' + S;
563 std::string Str;
John McCallf85e1932011-06-15 23:02:42 +0000564 IncludeStrongLifetimeRAII Strong(Policy);
Sean Huntca63c202011-05-24 22:41:36 +0000565 print(T->getBaseType(), Str);
566
567 switch (T->getUTTKind()) {
568 case UnaryTransformType::EnumUnderlyingType:
569 S = "__underlying_type(" + Str + ")" + S;
570 break;
571 }
572}
573
Richard Smith34b41d92011-02-20 03:19:35 +0000574void TypePrinter::printAuto(const AutoType *T, std::string &S) {
575 // If the type has been deduced, do not print 'auto'.
576 if (T->isDeduced()) {
577 print(T->getDeducedType(), S);
578 } else {
579 if (!S.empty()) // Prefix the basic type, e.g. 'auto X'.
580 S = ' ' + S;
581 S = "auto" + S;
582 }
583}
584
Eli Friedmanb001de72011-10-06 23:00:33 +0000585void TypePrinter::printAtomic(const AtomicType *T, std::string &S) {
586 if (!S.empty())
587 S = ' ' + S;
588 std::string Str;
589 IncludeStrongLifetimeRAII Strong(Policy);
590 print(T->getValueType(), Str);
591
592 S = "_Atomic(" + Str + ")" + S;
593}
594
John McCall7c2342d2010-03-10 11:27:22 +0000595/// Appends the given scope to the end of a string.
596void TypePrinter::AppendScope(DeclContext *DC, std::string &Buffer) {
597 if (DC->isTranslationUnit()) return;
598 AppendScope(DC->getParent(), Buffer);
599
600 unsigned OldSize = Buffer.size();
601
602 if (NamespaceDecl *NS = dyn_cast<NamespaceDecl>(DC)) {
Douglas Gregor25270b62011-11-03 00:16:13 +0000603 if (Policy.SuppressUnwrittenScope &&
604 (NS->isAnonymousNamespace() || NS->isInline()))
605 return;
John McCall7c2342d2010-03-10 11:27:22 +0000606 if (NS->getIdentifier())
607 Buffer += NS->getNameAsString();
608 else
609 Buffer += "<anonymous>";
610 } else if (ClassTemplateSpecializationDecl *Spec
611 = dyn_cast<ClassTemplateSpecializationDecl>(DC)) {
John McCallf85e1932011-06-15 23:02:42 +0000612 IncludeStrongLifetimeRAII Strong(Policy);
John McCall7c2342d2010-03-10 11:27:22 +0000613 const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs();
614 std::string TemplateArgsStr
615 = TemplateSpecializationType::PrintTemplateArgumentList(
Douglas Gregor910f8002010-11-07 23:05:16 +0000616 TemplateArgs.data(),
617 TemplateArgs.size(),
John McCall7c2342d2010-03-10 11:27:22 +0000618 Policy);
619 Buffer += Spec->getIdentifier()->getName();
620 Buffer += TemplateArgsStr;
621 } else if (TagDecl *Tag = dyn_cast<TagDecl>(DC)) {
Richard Smith162e1c12011-04-15 14:24:37 +0000622 if (TypedefNameDecl *Typedef = Tag->getTypedefNameForAnonDecl())
John McCall7c2342d2010-03-10 11:27:22 +0000623 Buffer += Typedef->getIdentifier()->getName();
624 else if (Tag->getIdentifier())
625 Buffer += Tag->getIdentifier()->getName();
Douglas Gregor25270b62011-11-03 00:16:13 +0000626 else
627 return;
John McCall7c2342d2010-03-10 11:27:22 +0000628 }
629
630 if (Buffer.size() != OldSize)
631 Buffer += "::";
632}
633
John McCall49f4e1c2010-12-10 11:01:00 +0000634void TypePrinter::printTag(TagDecl *D, std::string &InnerString) {
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000635 if (Policy.SuppressTag)
636 return;
John McCall7c2342d2010-03-10 11:27:22 +0000637
638 std::string Buffer;
John McCall73061d02010-03-19 07:56:44 +0000639 bool HasKindDecoration = false;
John McCall7c2342d2010-03-10 11:27:22 +0000640
Abramo Bagnara0daaf322011-03-16 20:16:18 +0000641 // bool SuppressTagKeyword
642 // = Policy.LangOpts.CPlusPlus || Policy.SuppressTagKeyword;
643
John McCall7c2342d2010-03-10 11:27:22 +0000644 // We don't print tags unless this is an elaborated type.
645 // In C, we just assume every RecordType is an elaborated type.
Abramo Bagnara0daaf322011-03-16 20:16:18 +0000646 if (!(Policy.LangOpts.CPlusPlus || Policy.SuppressTagKeyword ||
Richard Smith162e1c12011-04-15 14:24:37 +0000647 D->getTypedefNameForAnonDecl())) {
John McCall73061d02010-03-19 07:56:44 +0000648 HasKindDecoration = true;
John McCall7c2342d2010-03-10 11:27:22 +0000649 Buffer += D->getKindName();
650 Buffer += ' ';
651 }
652
Chris Lattnerc7acc662010-08-28 16:26:18 +0000653 // Compute the full nested-name-specifier for this type.
654 // In C, this will always be empty except when the type
655 // being printed is anonymous within other Record.
John McCall7c2342d2010-03-10 11:27:22 +0000656 if (!Policy.SuppressScope)
John McCall7c2342d2010-03-10 11:27:22 +0000657 AppendScope(D->getDeclContext(), Buffer);
658
John McCall3cb0ebd2010-03-10 03:28:59 +0000659 if (const IdentifierInfo *II = D->getIdentifier())
John McCall73061d02010-03-19 07:56:44 +0000660 Buffer += II->getNameStart();
Richard Smith162e1c12011-04-15 14:24:37 +0000661 else if (TypedefNameDecl *Typedef = D->getTypedefNameForAnonDecl()) {
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000662 assert(Typedef->getIdentifier() && "Typedef without identifier?");
John McCall73061d02010-03-19 07:56:44 +0000663 Buffer += Typedef->getIdentifier()->getNameStart();
664 } else {
665 // Make an unambiguous representation for anonymous types, e.g.
666 // <anonymous enum at /usr/include/string.h:120:9>
667 llvm::raw_string_ostream OS(Buffer);
668 OS << "<anonymous";
669
Douglas Gregor84139d62010-04-05 21:25:31 +0000670 if (Policy.AnonymousTagLocations) {
671 // Suppress the redundant tag keyword if we just printed one.
672 // We don't have to worry about ElaboratedTypes here because you can't
673 // refer to an anonymous type with one.
674 if (!HasKindDecoration)
675 OS << " " << D->getKindName();
John McCall73061d02010-03-19 07:56:44 +0000676
Douglas Gregorcb7b1e12010-11-12 07:15:47 +0000677 PresumedLoc PLoc = D->getASTContext().getSourceManager().getPresumedLoc(
Douglas Gregor16834e82010-05-28 21:47:04 +0000678 D->getLocation());
Douglas Gregorcb7b1e12010-11-12 07:15:47 +0000679 if (PLoc.isValid()) {
Douglas Gregor16834e82010-05-28 21:47:04 +0000680 OS << " at " << PLoc.getFilename()
681 << ':' << PLoc.getLine()
682 << ':' << PLoc.getColumn();
683 }
Douglas Gregor84139d62010-04-05 21:25:31 +0000684 }
685
686 OS << '>';
John McCall73061d02010-03-19 07:56:44 +0000687 }
John McCall7c2342d2010-03-10 11:27:22 +0000688
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000689 // If this is a class template specialization, print the template
690 // arguments.
691 if (ClassTemplateSpecializationDecl *Spec
John McCall7c2342d2010-03-10 11:27:22 +0000692 = dyn_cast<ClassTemplateSpecializationDecl>(D)) {
John McCall3cb0ebd2010-03-10 03:28:59 +0000693 const TemplateArgument *Args;
694 unsigned NumArgs;
695 if (TypeSourceInfo *TAW = Spec->getTypeAsWritten()) {
696 const TemplateSpecializationType *TST =
697 cast<TemplateSpecializationType>(TAW->getType());
698 Args = TST->getArgs();
699 NumArgs = TST->getNumArgs();
700 } else {
701 const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs();
Douglas Gregor910f8002010-11-07 23:05:16 +0000702 Args = TemplateArgs.data();
703 NumArgs = TemplateArgs.size();
John McCall3cb0ebd2010-03-10 03:28:59 +0000704 }
John McCallf85e1932011-06-15 23:02:42 +0000705 IncludeStrongLifetimeRAII Strong(Policy);
John McCall7c2342d2010-03-10 11:27:22 +0000706 Buffer += TemplateSpecializationType::PrintTemplateArgumentList(Args,
707 NumArgs,
708 Policy);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000709 }
John McCall7c2342d2010-03-10 11:27:22 +0000710
711 if (!InnerString.empty()) {
712 Buffer += ' ';
713 Buffer += InnerString;
714 }
715
716 std::swap(Buffer, InnerString);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000717}
718
John McCall49f4e1c2010-12-10 11:01:00 +0000719void TypePrinter::printRecord(const RecordType *T, std::string &S) {
720 printTag(T->getDecl(), S);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000721}
722
John McCall49f4e1c2010-12-10 11:01:00 +0000723void TypePrinter::printEnum(const EnumType *T, std::string &S) {
724 printTag(T->getDecl(), S);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000725}
726
John McCall49f4e1c2010-12-10 11:01:00 +0000727void TypePrinter::printTemplateTypeParm(const TemplateTypeParmType *T,
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000728 std::string &S) {
729 if (!S.empty()) // Prefix the basic type, e.g. 'parmname X'.
730 S = ' ' + S;
Chandler Carruth4fb86f82011-05-01 00:51:33 +0000731
Chandler Carruthb7efff42011-05-01 01:05:51 +0000732 if (IdentifierInfo *Id = T->getIdentifier())
Chandler Carruth4fb86f82011-05-01 00:51:33 +0000733 S = Id->getName().str() + S;
734 else
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000735 S = "type-parameter-" + llvm::utostr_32(T->getDepth()) + '-' +
736 llvm::utostr_32(T->getIndex()) + S;
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000737}
738
John McCall49f4e1c2010-12-10 11:01:00 +0000739void TypePrinter::printSubstTemplateTypeParm(const SubstTemplateTypeParmType *T,
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000740 std::string &S) {
John McCallf85e1932011-06-15 23:02:42 +0000741 IncludeStrongLifetimeRAII Strong(Policy);
John McCall49f4e1c2010-12-10 11:01:00 +0000742 print(T->getReplacementType(), S);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000743}
744
Douglas Gregorc3069d62011-01-14 02:55:32 +0000745void TypePrinter::printSubstTemplateTypeParmPack(
746 const SubstTemplateTypeParmPackType *T,
747 std::string &S) {
John McCallf85e1932011-06-15 23:02:42 +0000748 IncludeStrongLifetimeRAII Strong(Policy);
Douglas Gregorc3069d62011-01-14 02:55:32 +0000749 printTemplateTypeParm(T->getReplacedParameter(), S);
750}
751
John McCall49f4e1c2010-12-10 11:01:00 +0000752void TypePrinter::printTemplateSpecialization(
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000753 const TemplateSpecializationType *T,
754 std::string &S) {
John McCallf85e1932011-06-15 23:02:42 +0000755 IncludeStrongLifetimeRAII Strong(Policy);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000756 std::string SpecString;
757
758 {
759 llvm::raw_string_ostream OS(SpecString);
760 T->getTemplateName().print(OS, Policy);
761 }
762
763 SpecString += TemplateSpecializationType::PrintTemplateArgumentList(
764 T->getArgs(),
765 T->getNumArgs(),
766 Policy);
767 if (S.empty())
768 S.swap(SpecString);
769 else
770 S = SpecString + ' ' + S;
771}
772
John McCall49f4e1c2010-12-10 11:01:00 +0000773void TypePrinter::printInjectedClassName(const InjectedClassNameType *T,
John McCall3cb0ebd2010-03-10 03:28:59 +0000774 std::string &S) {
John McCall49f4e1c2010-12-10 11:01:00 +0000775 printTemplateSpecialization(T->getInjectedTST(), S);
John McCall3cb0ebd2010-03-10 03:28:59 +0000776}
777
John McCall49f4e1c2010-12-10 11:01:00 +0000778void TypePrinter::printElaborated(const ElaboratedType *T, std::string &S) {
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000779 std::string MyString;
780
781 {
782 llvm::raw_string_ostream OS(MyString);
Abramo Bagnara465d41b2010-05-11 21:36:43 +0000783 OS << TypeWithKeyword::getKeywordName(T->getKeyword());
784 if (T->getKeyword() != ETK_None)
785 OS << " ";
786 NestedNameSpecifier* Qualifier = T->getQualifier();
787 if (Qualifier)
788 Qualifier->print(OS, Policy);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000789 }
790
791 std::string TypeStr;
792 PrintingPolicy InnerPolicy(Policy);
Abramo Bagnara0daaf322011-03-16 20:16:18 +0000793 InnerPolicy.SuppressTagKeyword = true;
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000794 InnerPolicy.SuppressScope = true;
John McCall49f4e1c2010-12-10 11:01:00 +0000795 TypePrinter(InnerPolicy).print(T->getNamedType(), TypeStr);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000796
797 MyString += TypeStr;
798 if (S.empty())
799 S.swap(MyString);
800 else
801 S = MyString + ' ' + S;
802}
803
Abramo Bagnara075f8f12010-12-10 16:29:40 +0000804void TypePrinter::printParen(const ParenType *T, std::string &S) {
805 if (!S.empty() && !isa<FunctionType>(T->getInnerType()))
806 S = '(' + S + ')';
807 print(T->getInnerType(), S);
808}
809
John McCall49f4e1c2010-12-10 11:01:00 +0000810void TypePrinter::printDependentName(const DependentNameType *T, std::string &S) {
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000811 std::string MyString;
812
813 {
814 llvm::raw_string_ostream OS(MyString);
Abramo Bagnara465d41b2010-05-11 21:36:43 +0000815 OS << TypeWithKeyword::getKeywordName(T->getKeyword());
816 if (T->getKeyword() != ETK_None)
817 OS << " ";
Douglas Gregor4a2023f2010-03-31 20:19:30 +0000818
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000819 T->getQualifier()->print(OS, Policy);
820
John McCall33500952010-06-11 00:33:02 +0000821 OS << T->getIdentifier()->getName();
822 }
823
824 if (S.empty())
825 S.swap(MyString);
826 else
827 S = MyString + ' ' + S;
828}
829
John McCall49f4e1c2010-12-10 11:01:00 +0000830void TypePrinter::printDependentTemplateSpecialization(
John McCall33500952010-06-11 00:33:02 +0000831 const DependentTemplateSpecializationType *T, std::string &S) {
John McCallf85e1932011-06-15 23:02:42 +0000832 IncludeStrongLifetimeRAII Strong(Policy);
John McCall33500952010-06-11 00:33:02 +0000833 std::string MyString;
834 {
835 llvm::raw_string_ostream OS(MyString);
836
837 OS << TypeWithKeyword::getKeywordName(T->getKeyword());
838 if (T->getKeyword() != ETK_None)
839 OS << " ";
840
Douglas Gregora88f09f2011-02-28 17:23:35 +0000841 if (T->getQualifier())
842 T->getQualifier()->print(OS, Policy);
John McCall33500952010-06-11 00:33:02 +0000843 OS << T->getIdentifier()->getName();
844 OS << TemplateSpecializationType::PrintTemplateArgumentList(
845 T->getArgs(),
846 T->getNumArgs(),
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000847 Policy);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000848 }
849
850 if (S.empty())
851 S.swap(MyString);
852 else
853 S = MyString + ' ' + S;
854}
855
Douglas Gregor7536dd52010-12-20 02:24:11 +0000856void TypePrinter::printPackExpansion(const PackExpansionType *T,
857 std::string &S) {
858 print(T->getPattern(), S);
859 S += "...";
860}
861
John McCall9d156a72011-01-06 01:58:22 +0000862void TypePrinter::printAttributed(const AttributedType *T,
863 std::string &S) {
Argyrios Kyrtzidisb8b03132011-06-24 00:08:59 +0000864 // Prefer the macro forms of the GC and ownership qualifiers.
John McCallf85e1932011-06-15 23:02:42 +0000865 if (T->getAttrKind() == AttributedType::attr_objc_gc ||
Argyrios Kyrtzidisb8b03132011-06-24 00:08:59 +0000866 T->getAttrKind() == AttributedType::attr_objc_ownership)
John McCall14aa2172011-03-04 04:00:19 +0000867 return print(T->getEquivalentType(), S);
868
John McCall9d156a72011-01-06 01:58:22 +0000869 print(T->getModifiedType(), S);
870
871 // TODO: not all attributes are GCC-style attributes.
John McCall14aa2172011-03-04 04:00:19 +0000872 S += " __attribute__((";
John McCall9d156a72011-01-06 01:58:22 +0000873 switch (T->getAttrKind()) {
Francois Pichet170464b2011-01-07 03:17:31 +0000874 case AttributedType::attr_address_space:
John McCall9d156a72011-01-06 01:58:22 +0000875 S += "address_space(";
876 S += T->getEquivalentType().getAddressSpace();
877 S += ")";
878 break;
879
Francois Pichet170464b2011-01-07 03:17:31 +0000880 case AttributedType::attr_vector_size: {
John McCall9d156a72011-01-06 01:58:22 +0000881 S += "__vector_size__(";
882 if (const VectorType *vector =T->getEquivalentType()->getAs<VectorType>()) {
883 S += vector->getNumElements();
884 S += " * sizeof(";
885
886 std::string tmp;
887 print(vector->getElementType(), tmp);
888 S += tmp;
889 S += ")";
890 }
891 S += ")";
892 break;
893 }
894
Francois Pichet170464b2011-01-07 03:17:31 +0000895 case AttributedType::attr_neon_vector_type:
896 case AttributedType::attr_neon_polyvector_type: {
897 if (T->getAttrKind() == AttributedType::attr_neon_vector_type)
John McCall9d156a72011-01-06 01:58:22 +0000898 S += "neon_vector_type(";
899 else
900 S += "neon_polyvector_type(";
901 const VectorType *vector = T->getEquivalentType()->getAs<VectorType>();
902 S += llvm::utostr_32(vector->getNumElements());
903 S += ")";
904 break;
905 }
906
Francois Pichet170464b2011-01-07 03:17:31 +0000907 case AttributedType::attr_regparm: {
John McCall9d156a72011-01-06 01:58:22 +0000908 S += "regparm(";
909 QualType t = T->getEquivalentType();
910 while (!t->isFunctionType())
911 t = t->getPointeeType();
912 S += t->getAs<FunctionType>()->getRegParmType();
913 S += ")";
914 break;
915 }
916
Francois Pichet170464b2011-01-07 03:17:31 +0000917 case AttributedType::attr_objc_gc: {
John McCall9d156a72011-01-06 01:58:22 +0000918 S += "objc_gc(";
919
920 QualType tmp = T->getEquivalentType();
921 while (tmp.getObjCGCAttr() == Qualifiers::GCNone) {
922 QualType next = tmp->getPointeeType();
923 if (next == tmp) break;
924 tmp = next;
925 }
926
927 if (tmp.isObjCGCWeak())
928 S += "weak";
929 else
930 S += "strong";
931 S += ")";
932 break;
933 }
934
Argyrios Kyrtzidisb8b03132011-06-24 00:08:59 +0000935 case AttributedType::attr_objc_ownership:
936 S += "objc_ownership(";
John McCallf85e1932011-06-15 23:02:42 +0000937 switch (T->getEquivalentType().getObjCLifetime()) {
Argyrios Kyrtzidisb8b03132011-06-24 00:08:59 +0000938 case Qualifiers::OCL_None: llvm_unreachable("no ownership!"); break;
John McCallf85e1932011-06-15 23:02:42 +0000939 case Qualifiers::OCL_ExplicitNone: S += "none"; break;
940 case Qualifiers::OCL_Strong: S += "strong"; break;
941 case Qualifiers::OCL_Weak: S += "weak"; break;
942 case Qualifiers::OCL_Autoreleasing: S += "autoreleasing"; break;
943 }
944 S += ")";
945 break;
946
Francois Pichet3cd47e72011-01-07 02:58:13 +0000947 case AttributedType::attr_noreturn: S += "noreturn"; break;
948 case AttributedType::attr_cdecl: S += "cdecl"; break;
949 case AttributedType::attr_fastcall: S += "fastcall"; break;
950 case AttributedType::attr_stdcall: S += "stdcall"; break;
951 case AttributedType::attr_thiscall: S += "thiscall"; break;
952 case AttributedType::attr_pascal: S += "pascal"; break;
Anton Korobeynikov414d8962011-04-14 20:06:49 +0000953 case AttributedType::attr_pcs: {
954 S += "pcs(";
955 QualType t = T->getEquivalentType();
956 while (!t->isFunctionType())
957 t = t->getPointeeType();
958 S += (t->getAs<FunctionType>()->getCallConv() == CC_AAPCS ?
959 "\"aapcs\"" : "\"aapcs-vfp\"");
960 S += ")";
961 break;
962 }
John McCall9d156a72011-01-06 01:58:22 +0000963 }
964 S += "))";
965}
966
John McCall49f4e1c2010-12-10 11:01:00 +0000967void TypePrinter::printObjCInterface(const ObjCInterfaceType *T,
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000968 std::string &S) {
969 if (!S.empty()) // Prefix the basic type, e.g. 'typedefname X'.
970 S = ' ' + S;
John McCallc12c5bb2010-05-15 11:32:37 +0000971
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000972 std::string ObjCQIString = T->getDecl()->getNameAsString();
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000973 S = ObjCQIString + S;
974}
975
John McCall49f4e1c2010-12-10 11:01:00 +0000976void TypePrinter::printObjCObject(const ObjCObjectType *T,
John McCallc12c5bb2010-05-15 11:32:37 +0000977 std::string &S) {
978 if (T->qual_empty())
John McCall49f4e1c2010-12-10 11:01:00 +0000979 return print(T->getBaseType(), S);
John McCallc12c5bb2010-05-15 11:32:37 +0000980
981 std::string tmp;
John McCall49f4e1c2010-12-10 11:01:00 +0000982 print(T->getBaseType(), tmp);
John McCallc12c5bb2010-05-15 11:32:37 +0000983 tmp += '<';
984 bool isFirst = true;
985 for (ObjCObjectType::qual_iterator
986 I = T->qual_begin(), E = T->qual_end(); I != E; ++I) {
987 if (isFirst)
988 isFirst = false;
989 else
990 tmp += ',';
991 tmp += (*I)->getNameAsString();
992 }
993 tmp += '>';
994
995 if (!S.empty()) {
996 tmp += ' ';
997 tmp += S;
998 }
999 std::swap(tmp, S);
1000}
1001
John McCall49f4e1c2010-12-10 11:01:00 +00001002void TypePrinter::printObjCObjectPointer(const ObjCObjectPointerType *T,
Douglas Gregorfee8a3c2009-11-10 00:39:07 +00001003 std::string &S) {
1004 std::string ObjCQIString;
1005
Chris Lattnerd7e52b82010-09-05 00:43:21 +00001006 T->getPointeeType().getLocalQualifiers().getAsStringInternal(ObjCQIString,
1007 Policy);
1008 if (!ObjCQIString.empty())
1009 ObjCQIString += ' ';
1010
Douglas Gregorfee8a3c2009-11-10 00:39:07 +00001011 if (T->isObjCIdType() || T->isObjCQualifiedIdType())
Chris Lattnerd7e52b82010-09-05 00:43:21 +00001012 ObjCQIString += "id";
Douglas Gregorfee8a3c2009-11-10 00:39:07 +00001013 else if (T->isObjCClassType() || T->isObjCQualifiedClassType())
Chris Lattnerd7e52b82010-09-05 00:43:21 +00001014 ObjCQIString += "Class";
Fariborz Jahanian13dcd002009-11-21 19:53:08 +00001015 else if (T->isObjCSelType())
Chris Lattnerd7e52b82010-09-05 00:43:21 +00001016 ObjCQIString += "SEL";
Douglas Gregorfee8a3c2009-11-10 00:39:07 +00001017 else
Chris Lattnerd7e52b82010-09-05 00:43:21 +00001018 ObjCQIString += T->getInterfaceDecl()->getNameAsString();
Douglas Gregorfee8a3c2009-11-10 00:39:07 +00001019
1020 if (!T->qual_empty()) {
1021 ObjCQIString += '<';
1022 for (ObjCObjectPointerType::qual_iterator I = T->qual_begin(),
1023 E = T->qual_end();
1024 I != E; ++I) {
1025 ObjCQIString += (*I)->getNameAsString();
1026 if (I+1 != E)
1027 ObjCQIString += ',';
1028 }
1029 ObjCQIString += '>';
1030 }
1031
Douglas Gregorfee8a3c2009-11-10 00:39:07 +00001032 if (!T->isObjCIdType() && !T->isObjCQualifiedIdType())
1033 ObjCQIString += " *"; // Don't forget the implicit pointer.
1034 else if (!S.empty()) // Prefix the basic type, e.g. 'typedefname X'.
1035 S = ' ' + S;
1036
1037 S = ObjCQIString + S;
1038}
1039
John McCalld5532b62009-11-23 01:53:49 +00001040std::string TemplateSpecializationType::
1041 PrintTemplateArgumentList(const TemplateArgumentListInfo &Args,
1042 const PrintingPolicy &Policy) {
1043 return PrintTemplateArgumentList(Args.getArgumentArray(),
1044 Args.size(),
1045 Policy);
1046}
1047
Douglas Gregorfee8a3c2009-11-10 00:39:07 +00001048std::string
1049TemplateSpecializationType::PrintTemplateArgumentList(
1050 const TemplateArgument *Args,
1051 unsigned NumArgs,
Douglas Gregordace95b2010-12-20 22:28:59 +00001052 const PrintingPolicy &Policy,
1053 bool SkipBrackets) {
Douglas Gregorfee8a3c2009-11-10 00:39:07 +00001054 std::string SpecString;
Douglas Gregordace95b2010-12-20 22:28:59 +00001055 if (!SkipBrackets)
1056 SpecString += '<';
1057
Douglas Gregorfee8a3c2009-11-10 00:39:07 +00001058 for (unsigned Arg = 0; Arg < NumArgs; ++Arg) {
Francois Pichet319b4a62011-05-25 16:07:10 +00001059 if (SpecString.size() > unsigned(!SkipBrackets))
Douglas Gregorfee8a3c2009-11-10 00:39:07 +00001060 SpecString += ", ";
1061
1062 // Print the argument into a string.
1063 std::string ArgString;
Douglas Gregordace95b2010-12-20 22:28:59 +00001064 if (Args[Arg].getKind() == TemplateArgument::Pack) {
1065 ArgString = PrintTemplateArgumentList(Args[Arg].pack_begin(),
1066 Args[Arg].pack_size(),
1067 Policy, true);
1068 } else {
Douglas Gregor87dd6972010-12-20 16:52:59 +00001069 llvm::raw_string_ostream ArgOut(ArgString);
1070 Args[Arg].print(Policy, ArgOut);
1071 }
1072
Douglas Gregorfee8a3c2009-11-10 00:39:07 +00001073 // If this is the first argument and its string representation
1074 // begins with the global scope specifier ('::foo'), add a space
1075 // to avoid printing the diagraph '<:'.
1076 if (!Arg && !ArgString.empty() && ArgString[0] == ':')
1077 SpecString += ' ';
1078
1079 SpecString += ArgString;
1080 }
1081
1082 // If the last character of our string is '>', add another space to
1083 // keep the two '>''s separate tokens. We don't *have* to do this in
1084 // C++0x, but it's still good hygiene.
Francois Pichetb5bc7d02011-01-09 22:32:25 +00001085 if (!SpecString.empty() && SpecString[SpecString.size() - 1] == '>')
Douglas Gregorfee8a3c2009-11-10 00:39:07 +00001086 SpecString += ' ';
1087
Douglas Gregordace95b2010-12-20 22:28:59 +00001088 if (!SkipBrackets)
1089 SpecString += '>';
Douglas Gregorfee8a3c2009-11-10 00:39:07 +00001090
1091 return SpecString;
1092}
1093
1094// Sadly, repeat all that with TemplateArgLoc.
1095std::string TemplateSpecializationType::
1096PrintTemplateArgumentList(const TemplateArgumentLoc *Args, unsigned NumArgs,
1097 const PrintingPolicy &Policy) {
1098 std::string SpecString;
1099 SpecString += '<';
1100 for (unsigned Arg = 0; Arg < NumArgs; ++Arg) {
Douglas Gregordace95b2010-12-20 22:28:59 +00001101 if (SpecString.size() > 1)
Douglas Gregorfee8a3c2009-11-10 00:39:07 +00001102 SpecString += ", ";
1103
1104 // Print the argument into a string.
1105 std::string ArgString;
Douglas Gregordace95b2010-12-20 22:28:59 +00001106 if (Args[Arg].getArgument().getKind() == TemplateArgument::Pack) {
1107 ArgString = PrintTemplateArgumentList(
1108 Args[Arg].getArgument().pack_begin(),
1109 Args[Arg].getArgument().pack_size(),
1110 Policy, true);
1111 } else {
Douglas Gregor87dd6972010-12-20 16:52:59 +00001112 llvm::raw_string_ostream ArgOut(ArgString);
1113 Args[Arg].getArgument().print(Policy, ArgOut);
1114 }
Douglas Gregorfee8a3c2009-11-10 00:39:07 +00001115
1116 // If this is the first argument and its string representation
1117 // begins with the global scope specifier ('::foo'), add a space
1118 // to avoid printing the diagraph '<:'.
1119 if (!Arg && !ArgString.empty() && ArgString[0] == ':')
1120 SpecString += ' ';
1121
1122 SpecString += ArgString;
1123 }
1124
1125 // If the last character of our string is '>', add another space to
1126 // keep the two '>''s separate tokens. We don't *have* to do this in
1127 // C++0x, but it's still good hygiene.
1128 if (SpecString[SpecString.size() - 1] == '>')
1129 SpecString += ' ';
1130
1131 SpecString += '>';
1132
1133 return SpecString;
1134}
1135
1136void QualType::dump(const char *msg) const {
1137 std::string R = "identifier";
1138 LangOptions LO;
1139 getAsStringInternal(R, PrintingPolicy(LO));
1140 if (msg)
Daniel Dunbare7cb7e42009-12-03 09:14:02 +00001141 llvm::errs() << msg << ": ";
1142 llvm::errs() << R << "\n";
Douglas Gregorfee8a3c2009-11-10 00:39:07 +00001143}
1144void QualType::dump() const {
1145 dump("");
1146}
1147
1148void Type::dump() const {
1149 QualType(this, 0).dump();
1150}
1151
1152std::string Qualifiers::getAsString() const {
1153 LangOptions LO;
1154 return getAsString(PrintingPolicy(LO));
1155}
1156
1157// Appends qualifiers to the given string, separated by spaces. Will
1158// prefix a space if the string is non-empty. Will not append a final
1159// space.
1160void Qualifiers::getAsStringInternal(std::string &S,
John McCallf85e1932011-06-15 23:02:42 +00001161 const PrintingPolicy& Policy) const {
Douglas Gregorfee8a3c2009-11-10 00:39:07 +00001162 AppendTypeQualList(S, getCVRQualifiers());
John McCall14aa2172011-03-04 04:00:19 +00001163 if (unsigned addrspace = getAddressSpace()) {
Douglas Gregorfee8a3c2009-11-10 00:39:07 +00001164 if (!S.empty()) S += ' ';
Peter Collingbourne63cf68a2011-11-08 02:52:58 +00001165 switch (addrspace) {
1166 case LangAS::opencl_global:
1167 S += "__global";
1168 break;
1169 case LangAS::opencl_local:
1170 S += "__local";
1171 break;
1172 case LangAS::opencl_constant:
1173 S += "__constant";
1174 break;
1175 default:
1176 S += "__attribute__((address_space(";
1177 S += llvm::utostr_32(addrspace);
1178 S += ")))";
1179 }
Douglas Gregorfee8a3c2009-11-10 00:39:07 +00001180 }
John McCall14aa2172011-03-04 04:00:19 +00001181 if (Qualifiers::GC gc = getObjCGCAttr()) {
Douglas Gregorfee8a3c2009-11-10 00:39:07 +00001182 if (!S.empty()) S += ' ';
John McCall14aa2172011-03-04 04:00:19 +00001183 if (gc == Qualifiers::Weak)
1184 S += "__weak";
Douglas Gregorfee8a3c2009-11-10 00:39:07 +00001185 else
John McCall14aa2172011-03-04 04:00:19 +00001186 S += "__strong";
Douglas Gregorfee8a3c2009-11-10 00:39:07 +00001187 }
John McCallf85e1932011-06-15 23:02:42 +00001188 if (Qualifiers::ObjCLifetime lifetime = getObjCLifetime()) {
1189 if (!S.empty() &&
1190 !(lifetime == Qualifiers::OCL_Strong && Policy.SuppressStrongLifetime))
1191 S += ' ';
1192
1193 switch (lifetime) {
1194 case Qualifiers::OCL_None: llvm_unreachable("none but true");
1195 case Qualifiers::OCL_ExplicitNone: S += "__unsafe_unretained"; break;
1196 case Qualifiers::OCL_Strong:
1197 if (!Policy.SuppressStrongLifetime)
1198 S += "__strong";
1199 break;
1200
1201 case Qualifiers::OCL_Weak: S += "__weak"; break;
1202 case Qualifiers::OCL_Autoreleasing: S += "__autoreleasing"; break;
1203 }
1204 }
Douglas Gregorfee8a3c2009-11-10 00:39:07 +00001205}
1206
John McCall49f4e1c2010-12-10 11:01:00 +00001207std::string QualType::getAsString(const Type *ty, Qualifiers qs) {
1208 std::string buffer;
1209 LangOptions options;
1210 getAsStringInternal(ty, qs, buffer, PrintingPolicy(options));
1211 return buffer;
Douglas Gregorfee8a3c2009-11-10 00:39:07 +00001212}
1213
John McCall49f4e1c2010-12-10 11:01:00 +00001214void QualType::getAsStringInternal(const Type *ty, Qualifiers qs,
1215 std::string &buffer,
1216 const PrintingPolicy &policy) {
1217 TypePrinter(policy).print(ty, qs, buffer);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +00001218}