blob: c42117c82bf5a36b265f81f844c67c8810c1facf [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
Benjamin Kramer471c8b42012-07-04 20:19:54 +000014#include "clang/AST/ASTContext.h"
Douglas Gregorfee8a3c2009-11-10 00:39:07 +000015#include "clang/AST/Decl.h"
16#include "clang/AST/DeclObjC.h"
17#include "clang/AST/DeclTemplate.h"
18#include "clang/AST/Expr.h"
19#include "clang/AST/Type.h"
20#include "clang/AST/PrettyPrinter.h"
21#include "clang/Basic/LangOptions.h"
John McCall73061d02010-03-19 07:56:44 +000022#include "clang/Basic/SourceManager.h"
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +000023#include "llvm/ADT/SmallString.h"
Douglas Gregorfee8a3c2009-11-10 00:39:07 +000024#include "llvm/ADT/StringExtras.h"
25#include "llvm/Support/raw_ostream.h"
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +000026#include "llvm/Support/SaveAndRestore.h"
Douglas Gregorfee8a3c2009-11-10 00:39:07 +000027using namespace clang;
28
29namespace {
John McCallf85e1932011-06-15 23:02:42 +000030 /// \brief RAII object that enables printing of the ARC __strong lifetime
31 /// qualifier.
32 class IncludeStrongLifetimeRAII {
33 PrintingPolicy &Policy;
34 bool Old;
35
36 public:
37 explicit IncludeStrongLifetimeRAII(PrintingPolicy &Policy)
38 : Policy(Policy), Old(Policy.SuppressStrongLifetime) {
39 Policy.SuppressStrongLifetime = false;
40 }
41
42 ~IncludeStrongLifetimeRAII() {
43 Policy.SuppressStrongLifetime = Old;
44 }
45 };
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +000046
47 class ParamPolicyRAII {
48 PrintingPolicy &Policy;
49 bool Old;
50
51 public:
52 explicit ParamPolicyRAII(PrintingPolicy &Policy)
53 : Policy(Policy), Old(Policy.SuppressSpecifiers) {
54 Policy.SuppressSpecifiers = false;
55 }
56
57 ~ParamPolicyRAII() {
58 Policy.SuppressSpecifiers = Old;
59 }
60 };
61
62 class ElaboratedTypePolicyRAII {
63 PrintingPolicy &Policy;
64 bool SuppressTagKeyword;
65 bool SuppressScope;
66
67 public:
68 explicit ElaboratedTypePolicyRAII(PrintingPolicy &Policy) : Policy(Policy) {
69 SuppressTagKeyword = Policy.SuppressTagKeyword;
70 SuppressScope = Policy.SuppressScope;
71 Policy.SuppressTagKeyword = true;
72 Policy.SuppressScope = true;
73 }
74
75 ~ElaboratedTypePolicyRAII() {
76 Policy.SuppressTagKeyword = SuppressTagKeyword;
77 Policy.SuppressScope = SuppressScope;
78 }
79 };
John McCallf85e1932011-06-15 23:02:42 +000080
Douglas Gregorfee8a3c2009-11-10 00:39:07 +000081 class TypePrinter {
82 PrintingPolicy Policy;
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +000083 bool HasEmptyPlaceHolder;
Douglas Gregorfee8a3c2009-11-10 00:39:07 +000084
85 public:
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +000086 explicit TypePrinter(const PrintingPolicy &Policy)
87 : Policy(Policy), HasEmptyPlaceHolder(false) { }
Abramo Bagnara493ec512010-04-27 21:08:25 +000088
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +000089 void print(const Type *ty, Qualifiers qs, raw_ostream &OS,
90 StringRef PlaceHolder);
91 void print(QualType T, raw_ostream &OS, StringRef PlaceHolder);
92
93 static bool canPrefixQualifiers(const Type *T, bool &NeedARCStrongQualifier);
94 void spaceBeforePlaceHolder(raw_ostream &OS);
95 void printTypeSpec(const NamedDecl *D, raw_ostream &OS);
96
97 void printBefore(const Type *ty, Qualifiers qs, raw_ostream &OS);
98 void printBefore(QualType T, raw_ostream &OS);
99 void printAfter(const Type *ty, Qualifiers qs, raw_ostream &OS);
100 void printAfter(QualType T, raw_ostream &OS);
101 void AppendScope(DeclContext *DC, raw_ostream &OS);
102 void printTag(TagDecl *T, raw_ostream &OS);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000103#define ABSTRACT_TYPE(CLASS, PARENT)
104#define TYPE(CLASS, PARENT) \
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000105 void print##CLASS##Before(const CLASS##Type *T, raw_ostream &OS); \
106 void print##CLASS##After(const CLASS##Type *T, raw_ostream &OS);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000107#include "clang/AST/TypeNodes.def"
108 };
109}
110
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000111static void AppendTypeQualList(raw_ostream &OS, unsigned TypeQuals) {
112 bool appendSpace = false;
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000113 if (TypeQuals & Qualifiers::Const) {
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000114 OS << "const";
115 appendSpace = true;
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000116 }
117 if (TypeQuals & Qualifiers::Volatile) {
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000118 if (appendSpace) OS << ' ';
119 OS << "volatile";
120 appendSpace = true;
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000121 }
122 if (TypeQuals & Qualifiers::Restrict) {
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000123 if (appendSpace) OS << ' ';
124 OS << "restrict";
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000125 }
126}
127
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000128void TypePrinter::spaceBeforePlaceHolder(raw_ostream &OS) {
129 if (!HasEmptyPlaceHolder)
130 OS << ' ';
John McCall49f4e1c2010-12-10 11:01:00 +0000131}
132
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000133void TypePrinter::print(QualType t, raw_ostream &OS, StringRef PlaceHolder) {
134 SplitQualType split = t.split();
135 print(split.Ty, split.Quals, OS, PlaceHolder);
136}
137
138void TypePrinter::print(const Type *T, Qualifiers Quals, raw_ostream &OS,
139 StringRef PlaceHolder) {
John McCall49f4e1c2010-12-10 11:01:00 +0000140 if (!T) {
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000141 OS << "NULL TYPE";
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000142 return;
143 }
144
145 if (Policy.SuppressSpecifiers && T->isSpecifierType())
146 return;
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000147
148 SaveAndRestore<bool> PHVal(HasEmptyPlaceHolder, PlaceHolder.empty());
149
150 printBefore(T, Quals, OS);
151 OS << PlaceHolder;
152 printAfter(T, Quals, OS);
153}
154
155bool TypePrinter::canPrefixQualifiers(const Type *T,
156 bool &NeedARCStrongQualifier) {
Chris Lattner58f9e132010-09-05 00:04:01 +0000157 // CanPrefixQualifiers - We prefer to print type qualifiers before the type,
158 // so that we get "const int" instead of "int const", but we can't do this if
159 // the type is complex. For example if the type is "int*", we *must* print
160 // "int * const", printing "const int *" is different. Only do this when the
161 // type expands to a simple string.
Douglas Gregorc6daf0b2011-02-17 06:52:25 +0000162 bool CanPrefixQualifiers = false;
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000163 NeedARCStrongQualifier = false;
Douglas Gregorc6daf0b2011-02-17 06:52:25 +0000164 Type::TypeClass TC = T->getTypeClass();
Richard Smith34b41d92011-02-20 03:19:35 +0000165 if (const AutoType *AT = dyn_cast<AutoType>(T))
166 TC = AT->desugar()->getTypeClass();
Douglas Gregorc6daf0b2011-02-17 06:52:25 +0000167 if (const SubstTemplateTypeParmType *Subst
168 = dyn_cast<SubstTemplateTypeParmType>(T))
169 TC = Subst->getReplacementType()->getTypeClass();
170
171 switch (TC) {
172 case Type::Builtin:
173 case Type::Complex:
174 case Type::UnresolvedUsing:
175 case Type::Typedef:
176 case Type::TypeOfExpr:
177 case Type::TypeOf:
178 case Type::Decltype:
Sean Huntca63c202011-05-24 22:41:36 +0000179 case Type::UnaryTransform:
Douglas Gregorc6daf0b2011-02-17 06:52:25 +0000180 case Type::Record:
181 case Type::Enum:
182 case Type::Elaborated:
183 case Type::TemplateTypeParm:
184 case Type::SubstTemplateTypeParmPack:
185 case Type::TemplateSpecialization:
186 case Type::InjectedClassName:
187 case Type::DependentName:
188 case Type::DependentTemplateSpecialization:
189 case Type::ObjCObject:
190 case Type::ObjCInterface:
Eli Friedmanb001de72011-10-06 23:00:33 +0000191 case Type::Atomic:
Douglas Gregorc6daf0b2011-02-17 06:52:25 +0000192 CanPrefixQualifiers = true;
193 break;
194
195 case Type::ObjCObjectPointer:
196 CanPrefixQualifiers = T->isObjCIdType() || T->isObjCClassType() ||
197 T->isObjCQualifiedIdType() || T->isObjCQualifiedClassType();
198 break;
199
John McCallf85e1932011-06-15 23:02:42 +0000200 case Type::ConstantArray:
201 case Type::IncompleteArray:
202 case Type::VariableArray:
203 case Type::DependentSizedArray:
204 NeedARCStrongQualifier = true;
205 // Fall through
206
Douglas Gregorc6daf0b2011-02-17 06:52:25 +0000207 case Type::Pointer:
208 case Type::BlockPointer:
209 case Type::LValueReference:
210 case Type::RValueReference:
211 case Type::MemberPointer:
Douglas Gregorc6daf0b2011-02-17 06:52:25 +0000212 case Type::DependentSizedExtVector:
213 case Type::Vector:
214 case Type::ExtVector:
215 case Type::FunctionProto:
216 case Type::FunctionNoProto:
217 case Type::Paren:
218 case Type::Attributed:
219 case Type::PackExpansion:
220 case Type::SubstTemplateTypeParm:
Richard Smith34b41d92011-02-20 03:19:35 +0000221 case Type::Auto:
Douglas Gregorc6daf0b2011-02-17 06:52:25 +0000222 CanPrefixQualifiers = false;
223 break;
224 }
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000225
226 return CanPrefixQualifiers;
227}
228
Richard Smith838925d2012-07-13 04:12:04 +0000229void TypePrinter::printBefore(QualType T, raw_ostream &OS) {
230 SplitQualType Split = T.split();
231
232 // If we have cv1 T, where T is substituted for cv2 U, only print cv1 - cv2
233 // at this level.
234 Qualifiers Quals = Split.Quals;
235 if (const SubstTemplateTypeParmType *Subst =
236 dyn_cast<SubstTemplateTypeParmType>(Split.Ty))
237 Quals -= QualType(Subst, 0).getQualifiers();
238
239 printBefore(Split.Ty, Quals, OS);
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000240}
241
242/// \brief Prints the part of the type string before an identifier, e.g. for
243/// "int foo[10]" it prints "int ".
244void TypePrinter::printBefore(const Type *T,Qualifiers Quals, raw_ostream &OS) {
245 if (Policy.SuppressSpecifiers && T->isSpecifierType())
246 return;
247
248 SaveAndRestore<bool> PrevPHIsEmpty(HasEmptyPlaceHolder);
249
250 // Print qualifiers as appropriate.
251
252 bool CanPrefixQualifiers = false;
253 bool NeedARCStrongQualifier = false;
254 CanPrefixQualifiers = canPrefixQualifiers(T, NeedARCStrongQualifier);
255
256 if (CanPrefixQualifiers && !Quals.empty()) {
John McCallf85e1932011-06-15 23:02:42 +0000257 if (NeedARCStrongQualifier) {
258 IncludeStrongLifetimeRAII Strong(Policy);
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000259 Quals.print(OS, Policy, /*appendSpaceIfNonEmpty=*/true);
John McCallf85e1932011-06-15 23:02:42 +0000260 } else {
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000261 Quals.print(OS, Policy, /*appendSpaceIfNonEmpty=*/true);
John McCallf85e1932011-06-15 23:02:42 +0000262 }
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000263 }
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000264
265 bool hasAfterQuals = false;
266 if (!CanPrefixQualifiers && !Quals.empty()) {
267 hasAfterQuals = !Quals.isEmptyWhenPrinted(Policy);
268 if (hasAfterQuals)
269 HasEmptyPlaceHolder = false;
270 }
271
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000272 switch (T->getTypeClass()) {
273#define ABSTRACT_TYPE(CLASS, PARENT)
John McCall49f4e1c2010-12-10 11:01:00 +0000274#define TYPE(CLASS, PARENT) case Type::CLASS: \
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000275 print##CLASS##Before(cast<CLASS##Type>(T), OS); \
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000276 break;
277#include "clang/AST/TypeNodes.def"
278 }
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000279
280 if (hasAfterQuals) {
John McCallf85e1932011-06-15 23:02:42 +0000281 if (NeedARCStrongQualifier) {
282 IncludeStrongLifetimeRAII Strong(Policy);
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000283 Quals.print(OS, Policy, /*appendSpaceIfNonEmpty=*/!PrevPHIsEmpty.get());
John McCallf85e1932011-06-15 23:02:42 +0000284 } else {
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000285 Quals.print(OS, Policy, /*appendSpaceIfNonEmpty=*/!PrevPHIsEmpty.get());
John McCallf85e1932011-06-15 23:02:42 +0000286 }
Chris Lattner58f9e132010-09-05 00:04:01 +0000287 }
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000288}
289
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000290void TypePrinter::printAfter(QualType t, raw_ostream &OS) {
291 SplitQualType split = t.split();
292 printAfter(split.Ty, split.Quals, OS);
293}
294
295/// \brief Prints the part of the type string after an identifier, e.g. for
296/// "int foo[10]" it prints "[10]".
297void TypePrinter::printAfter(const Type *T, Qualifiers Quals, raw_ostream &OS) {
298 switch (T->getTypeClass()) {
299#define ABSTRACT_TYPE(CLASS, PARENT)
300#define TYPE(CLASS, PARENT) case Type::CLASS: \
301 print##CLASS##After(cast<CLASS##Type>(T), OS); \
302 break;
303#include "clang/AST/TypeNodes.def"
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000304 }
305}
306
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000307void TypePrinter::printBuiltinBefore(const BuiltinType *T, raw_ostream &OS) {
308 OS << T->getName(Policy);
309 spaceBeforePlaceHolder(OS);
310}
311void TypePrinter::printBuiltinAfter(const BuiltinType *T, raw_ostream &OS) { }
312
313void TypePrinter::printComplexBefore(const ComplexType *T, raw_ostream &OS) {
314 OS << "_Complex ";
315 printBefore(T->getElementType(), OS);
316}
317void TypePrinter::printComplexAfter(const ComplexType *T, raw_ostream &OS) {
318 printAfter(T->getElementType(), OS);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000319}
320
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000321void TypePrinter::printPointerBefore(const PointerType *T, raw_ostream &OS) {
322 IncludeStrongLifetimeRAII Strong(Policy);
323 SaveAndRestore<bool> NonEmptyPH(HasEmptyPlaceHolder, false);
324 printBefore(T->getPointeeType(), OS);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000325 // Handle things like 'int (*A)[4];' correctly.
326 // FIXME: this should include vectors, but vectors use attributes I guess.
327 if (isa<ArrayType>(T->getPointeeType()))
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000328 OS << '(';
329 OS << '*';
330}
331void TypePrinter::printPointerAfter(const PointerType *T, raw_ostream &OS) {
John McCallf85e1932011-06-15 23:02:42 +0000332 IncludeStrongLifetimeRAII Strong(Policy);
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000333 SaveAndRestore<bool> NonEmptyPH(HasEmptyPlaceHolder, false);
334 // Handle things like 'int (*A)[4];' correctly.
335 // FIXME: this should include vectors, but vectors use attributes I guess.
336 if (isa<ArrayType>(T->getPointeeType()))
337 OS << ')';
338 printAfter(T->getPointeeType(), OS);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000339}
340
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000341void TypePrinter::printBlockPointerBefore(const BlockPointerType *T,
342 raw_ostream &OS) {
343 SaveAndRestore<bool> NonEmptyPH(HasEmptyPlaceHolder, false);
344 printBefore(T->getPointeeType(), OS);
345 OS << '^';
346}
347void TypePrinter::printBlockPointerAfter(const BlockPointerType *T,
348 raw_ostream &OS) {
349 SaveAndRestore<bool> NonEmptyPH(HasEmptyPlaceHolder, false);
350 printAfter(T->getPointeeType(), OS);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000351}
352
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000353void TypePrinter::printLValueReferenceBefore(const LValueReferenceType *T,
354 raw_ostream &OS) {
355 IncludeStrongLifetimeRAII Strong(Policy);
356 SaveAndRestore<bool> NonEmptyPH(HasEmptyPlaceHolder, false);
357 printBefore(T->getPointeeTypeAsWritten(), OS);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000358 // Handle things like 'int (&A)[4];' correctly.
359 // FIXME: this should include vectors, but vectors use attributes I guess.
360 if (isa<ArrayType>(T->getPointeeTypeAsWritten()))
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000361 OS << '(';
362 OS << '&';
363}
364void TypePrinter::printLValueReferenceAfter(const LValueReferenceType *T,
365 raw_ostream &OS) {
John McCallf85e1932011-06-15 23:02:42 +0000366 IncludeStrongLifetimeRAII Strong(Policy);
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000367 SaveAndRestore<bool> NonEmptyPH(HasEmptyPlaceHolder, false);
368 // Handle things like 'int (&A)[4];' correctly.
369 // FIXME: this should include vectors, but vectors use attributes I guess.
370 if (isa<ArrayType>(T->getPointeeTypeAsWritten()))
371 OS << ')';
372 printAfter(T->getPointeeTypeAsWritten(), OS);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000373}
374
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000375void TypePrinter::printRValueReferenceBefore(const RValueReferenceType *T,
376 raw_ostream &OS) {
377 IncludeStrongLifetimeRAII Strong(Policy);
378 SaveAndRestore<bool> NonEmptyPH(HasEmptyPlaceHolder, false);
379 printBefore(T->getPointeeTypeAsWritten(), OS);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000380 // Handle things like 'int (&&A)[4];' correctly.
381 // FIXME: this should include vectors, but vectors use attributes I guess.
382 if (isa<ArrayType>(T->getPointeeTypeAsWritten()))
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000383 OS << '(';
384 OS << "&&";
385}
386void TypePrinter::printRValueReferenceAfter(const RValueReferenceType *T,
387 raw_ostream &OS) {
John McCallf85e1932011-06-15 23:02:42 +0000388 IncludeStrongLifetimeRAII Strong(Policy);
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000389 SaveAndRestore<bool> NonEmptyPH(HasEmptyPlaceHolder, false);
390 // Handle things like 'int (&&A)[4];' correctly.
391 // FIXME: this should include vectors, but vectors use attributes I guess.
392 if (isa<ArrayType>(T->getPointeeTypeAsWritten()))
393 OS << ')';
394 printAfter(T->getPointeeTypeAsWritten(), OS);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000395}
396
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000397void TypePrinter::printMemberPointerBefore(const MemberPointerType *T,
398 raw_ostream &OS) {
399 IncludeStrongLifetimeRAII Strong(Policy);
400 SaveAndRestore<bool> NonEmptyPH(HasEmptyPlaceHolder, false);
401 printBefore(T->getPointeeType(), OS);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000402 // Handle things like 'int (Cls::*A)[4];' correctly.
403 // FIXME: this should include vectors, but vectors use attributes I guess.
404 if (isa<ArrayType>(T->getPointeeType()))
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000405 OS << '(';
406
407 PrintingPolicy InnerPolicy(Policy);
408 InnerPolicy.SuppressTag = false;
409 TypePrinter(InnerPolicy).print(QualType(T->getClass(), 0), OS, StringRef());
410
411 OS << "::*";
412}
413void TypePrinter::printMemberPointerAfter(const MemberPointerType *T,
414 raw_ostream &OS) {
John McCallf85e1932011-06-15 23:02:42 +0000415 IncludeStrongLifetimeRAII Strong(Policy);
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000416 SaveAndRestore<bool> NonEmptyPH(HasEmptyPlaceHolder, false);
417 // Handle things like 'int (Cls::*A)[4];' correctly.
418 // FIXME: this should include vectors, but vectors use attributes I guess.
419 if (isa<ArrayType>(T->getPointeeType()))
420 OS << ')';
421 printAfter(T->getPointeeType(), OS);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000422}
423
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000424void TypePrinter::printConstantArrayBefore(const ConstantArrayType *T,
425 raw_ostream &OS) {
John McCallf85e1932011-06-15 23:02:42 +0000426 IncludeStrongLifetimeRAII Strong(Policy);
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000427 SaveAndRestore<bool> NonEmptyPH(HasEmptyPlaceHolder, false);
428 printBefore(T->getElementType(), OS);
429}
430void TypePrinter::printConstantArrayAfter(const ConstantArrayType *T,
431 raw_ostream &OS) {
432 OS << '[' << T->getSize().getZExtValue() << ']';
433 printAfter(T->getElementType(), OS);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000434}
435
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000436void TypePrinter::printIncompleteArrayBefore(const IncompleteArrayType *T,
437 raw_ostream &OS) {
John McCallf85e1932011-06-15 23:02:42 +0000438 IncludeStrongLifetimeRAII Strong(Policy);
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000439 SaveAndRestore<bool> NonEmptyPH(HasEmptyPlaceHolder, false);
440 printBefore(T->getElementType(), OS);
441}
442void TypePrinter::printIncompleteArrayAfter(const IncompleteArrayType *T,
443 raw_ostream &OS) {
444 OS << "[]";
445 printAfter(T->getElementType(), OS);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000446}
447
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000448void TypePrinter::printVariableArrayBefore(const VariableArrayType *T,
449 raw_ostream &OS) {
450 IncludeStrongLifetimeRAII Strong(Policy);
451 SaveAndRestore<bool> NonEmptyPH(HasEmptyPlaceHolder, false);
452 printBefore(T->getElementType(), OS);
453}
454void TypePrinter::printVariableArrayAfter(const VariableArrayType *T,
455 raw_ostream &OS) {
456 OS << '[';
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000457 if (T->getIndexTypeQualifiers().hasQualifiers()) {
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000458 AppendTypeQualList(OS, T->getIndexTypeCVRQualifiers());
459 OS << ' ';
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000460 }
Axel Naumann16d00782012-06-29 07:30:33 +0000461
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000462 if (T->getSizeModifier() == VariableArrayType::Static)
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000463 OS << "static";
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000464 else if (T->getSizeModifier() == VariableArrayType::Star)
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000465 OS << '*';
Axel Naumann16d00782012-06-29 07:30:33 +0000466
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000467 if (T->getSizeExpr())
468 T->getSizeExpr()->printPretty(OS, 0, Policy);
469 OS << ']';
470
471 printAfter(T->getElementType(), OS);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000472}
473
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000474void TypePrinter::printDependentSizedArrayBefore(
475 const DependentSizedArrayType *T,
476 raw_ostream &OS) {
John McCallf85e1932011-06-15 23:02:42 +0000477 IncludeStrongLifetimeRAII Strong(Policy);
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000478 SaveAndRestore<bool> NonEmptyPH(HasEmptyPlaceHolder, false);
479 printBefore(T->getElementType(), OS);
480}
481void TypePrinter::printDependentSizedArrayAfter(
482 const DependentSizedArrayType *T,
483 raw_ostream &OS) {
484 OS << '[';
485 if (T->getSizeExpr())
486 T->getSizeExpr()->printPretty(OS, 0, Policy);
487 OS << ']';
488 printAfter(T->getElementType(), OS);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000489}
490
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000491void TypePrinter::printDependentSizedExtVectorBefore(
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000492 const DependentSizedExtVectorType *T,
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000493 raw_ostream &OS) {
494 printBefore(T->getElementType(), OS);
495}
496void TypePrinter::printDependentSizedExtVectorAfter(
497 const DependentSizedExtVectorType *T,
498 raw_ostream &OS) {
499 OS << " __attribute__((ext_vector_type(";
500 if (T->getSizeExpr())
501 T->getSizeExpr()->printPretty(OS, 0, Policy);
502 OS << ")))";
503 printAfter(T->getElementType(), OS);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000504}
505
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000506void TypePrinter::printVectorBefore(const VectorType *T, raw_ostream &OS) {
Bob Wilsonec33cbe2010-11-16 00:32:26 +0000507 switch (T->getVectorKind()) {
508 case VectorType::AltiVecPixel:
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000509 OS << "__vector __pixel ";
Bob Wilsonec33cbe2010-11-16 00:32:26 +0000510 break;
511 case VectorType::AltiVecBool:
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000512 OS << "__vector __bool ";
513 printBefore(T->getElementType(), OS);
Bob Wilsonec33cbe2010-11-16 00:32:26 +0000514 break;
515 case VectorType::AltiVecVector:
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000516 OS << "__vector ";
517 printBefore(T->getElementType(), OS);
Bob Wilsonec33cbe2010-11-16 00:32:26 +0000518 break;
519 case VectorType::NeonVector:
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000520 OS << "__attribute__((neon_vector_type("
521 << T->getNumElements() << "))) ";
522 printBefore(T->getElementType(), OS);
Bob Wilsonec33cbe2010-11-16 00:32:26 +0000523 break;
524 case VectorType::NeonPolyVector:
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000525 OS << "__attribute__((neon_polyvector_type(" <<
526 T->getNumElements() << "))) ";
527 printBefore(T->getElementType(), OS);
Bob Wilsonec33cbe2010-11-16 00:32:26 +0000528 break;
529 case VectorType::GenericVector: {
John Thompson82287d12010-02-05 00:12:22 +0000530 // FIXME: We prefer to print the size directly here, but have no way
531 // to get the size of the type.
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000532 OS << "__attribute__((__vector_size__("
533 << T->getNumElements()
534 << " * sizeof(";
535 print(T->getElementType(), OS, StringRef());
536 OS << ")))) ";
537 printBefore(T->getElementType(), OS);
Bob Wilsonec33cbe2010-11-16 00:32:26 +0000538 break;
539 }
John Thompson82287d12010-02-05 00:12:22 +0000540 }
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000541}
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000542void TypePrinter::printVectorAfter(const VectorType *T, raw_ostream &OS) {
543 printAfter(T->getElementType(), OS);
544}
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000545
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000546void TypePrinter::printExtVectorBefore(const ExtVectorType *T,
547 raw_ostream &OS) {
548 printBefore(T->getElementType(), OS);
549}
550void TypePrinter::printExtVectorAfter(const ExtVectorType *T, raw_ostream &OS) {
551 printAfter(T->getElementType(), OS);
552 OS << " __attribute__((ext_vector_type(";
553 OS << T->getNumElements();
554 OS << ")))";
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000555}
556
Douglas Gregor01d08012012-02-07 10:09:13 +0000557void
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000558FunctionProtoType::printExceptionSpecification(raw_ostream &OS,
Douglas Gregor01d08012012-02-07 10:09:13 +0000559 PrintingPolicy Policy) const {
560
561 if (hasDynamicExceptionSpec()) {
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000562 OS << " throw(";
Douglas Gregor01d08012012-02-07 10:09:13 +0000563 if (getExceptionSpecType() == EST_MSAny)
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000564 OS << "...";
Douglas Gregor01d08012012-02-07 10:09:13 +0000565 else
566 for (unsigned I = 0, N = getNumExceptions(); I != N; ++I) {
567 if (I)
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000568 OS << ", ";
Douglas Gregor01d08012012-02-07 10:09:13 +0000569
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000570 OS << getExceptionType(I).stream(Policy);
Douglas Gregor01d08012012-02-07 10:09:13 +0000571 }
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000572 OS << ')';
Douglas Gregor01d08012012-02-07 10:09:13 +0000573 } else if (isNoexceptExceptionSpec(getExceptionSpecType())) {
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000574 OS << " noexcept";
Douglas Gregor01d08012012-02-07 10:09:13 +0000575 if (getExceptionSpecType() == EST_ComputedNoexcept) {
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000576 OS << '(';
577 getNoexceptExpr()->printPretty(OS, 0, Policy);
578 OS << ')';
Douglas Gregor01d08012012-02-07 10:09:13 +0000579 }
580 }
581}
582
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000583void TypePrinter::printFunctionProtoBefore(const FunctionProtoType *T,
584 raw_ostream &OS) {
585 if (T->hasTrailingReturn()) {
586 OS << "auto ";
587 if (!HasEmptyPlaceHolder)
588 OS << '(';
589 } else {
590 // If needed for precedence reasons, wrap the inner part in grouping parens.
591 SaveAndRestore<bool> PrevPHIsEmpty(HasEmptyPlaceHolder, false);
592 printBefore(T->getResultType(), OS);
593 if (!PrevPHIsEmpty.get())
594 OS << '(';
595 }
596}
597
598void TypePrinter::printFunctionProtoAfter(const FunctionProtoType *T,
599 raw_ostream &OS) {
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000600 // If needed for precedence reasons, wrap the inner part in grouping parens.
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000601 if (!HasEmptyPlaceHolder)
602 OS << ')';
603 SaveAndRestore<bool> NonEmptyPH(HasEmptyPlaceHolder, false);
604
605 OS << '(';
606 {
607 ParamPolicyRAII ParamPolicy(Policy);
608 for (unsigned i = 0, e = T->getNumArgs(); i != e; ++i) {
609 if (i) OS << ", ";
610 print(T->getArgType(i), OS, StringRef());
611 }
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000612 }
613
614 if (T->isVariadic()) {
615 if (T->getNumArgs())
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000616 OS << ", ";
617 OS << "...";
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000618 } else if (T->getNumArgs() == 0 && !Policy.LangOpts.CPlusPlus) {
619 // Do not emit int() if we have a proto, emit 'int(void)'.
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000620 OS << "void";
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000621 }
622
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000623 OS << ')';
Douglas Gregor0ae7b3f2009-12-08 17:45:32 +0000624
Rafael Espindola264ba482010-03-30 20:24:48 +0000625 FunctionType::ExtInfo Info = T->getExtInfo();
626 switch(Info.getCC()) {
David Blaikie561d3ab2012-01-17 02:30:50 +0000627 case CC_Default: break;
John McCallf82b4e82010-02-04 05:44:44 +0000628 case CC_C:
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000629 OS << " __attribute__((cdecl))";
John McCallf82b4e82010-02-04 05:44:44 +0000630 break;
631 case CC_X86StdCall:
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000632 OS << " __attribute__((stdcall))";
John McCallf82b4e82010-02-04 05:44:44 +0000633 break;
634 case CC_X86FastCall:
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000635 OS << " __attribute__((fastcall))";
John McCallf82b4e82010-02-04 05:44:44 +0000636 break;
Douglas Gregorf813a2c2010-05-18 16:57:00 +0000637 case CC_X86ThisCall:
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000638 OS << " __attribute__((thiscall))";
Douglas Gregorf813a2c2010-05-18 16:57:00 +0000639 break;
Dawn Perchik52fc3142010-09-03 01:29:35 +0000640 case CC_X86Pascal:
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000641 OS << " __attribute__((pascal))";
Dawn Perchik52fc3142010-09-03 01:29:35 +0000642 break;
Anton Korobeynikov414d8962011-04-14 20:06:49 +0000643 case CC_AAPCS:
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000644 OS << " __attribute__((pcs(\"aapcs\")))";
Anton Korobeynikov414d8962011-04-14 20:06:49 +0000645 break;
646 case CC_AAPCS_VFP:
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000647 OS << " __attribute__((pcs(\"aapcs-vfp\")))";
Anton Korobeynikov414d8962011-04-14 20:06:49 +0000648 break;
John McCallf82b4e82010-02-04 05:44:44 +0000649 }
Rafael Espindola264ba482010-03-30 20:24:48 +0000650 if (Info.getNoReturn())
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000651 OS << " __attribute__((noreturn))";
Rafael Espindola425ef722010-03-30 22:15:11 +0000652 if (Info.getRegParm())
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000653 OS << " __attribute__((regparm ("
654 << Info.getRegParm() << ")))";
655
656 if (unsigned quals = T->getTypeQuals()) {
657 OS << ' ';
658 AppendTypeQualList(OS, quals);
659 }
Douglas Gregorc938c162011-01-26 05:01:58 +0000660
661 switch (T->getRefQualifier()) {
662 case RQ_None:
663 break;
664
665 case RQ_LValue:
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000666 OS << " &";
Douglas Gregorc938c162011-01-26 05:01:58 +0000667 break;
668
669 case RQ_RValue:
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000670 OS << " &&";
Douglas Gregorc938c162011-01-26 05:01:58 +0000671 break;
672 }
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000673 T->printExceptionSpecification(OS, Policy);
674
Richard Smitheefb3d52012-02-10 09:58:53 +0000675 if (T->hasTrailingReturn()) {
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000676 OS << " -> ";
677 print(T->getResultType(), OS, StringRef());
Richard Smitheefb3d52012-02-10 09:58:53 +0000678 } else
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000679 printAfter(T->getResultType(), OS);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000680}
681
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000682void TypePrinter::printFunctionNoProtoBefore(const FunctionNoProtoType *T,
683 raw_ostream &OS) {
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000684 // If needed for precedence reasons, wrap the inner part in grouping parens.
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000685 SaveAndRestore<bool> PrevPHIsEmpty(HasEmptyPlaceHolder, false);
686 printBefore(T->getResultType(), OS);
687 if (!PrevPHIsEmpty.get())
688 OS << '(';
689}
690void TypePrinter::printFunctionNoProtoAfter(const FunctionNoProtoType *T,
691 raw_ostream &OS) {
692 // If needed for precedence reasons, wrap the inner part in grouping parens.
693 if (!HasEmptyPlaceHolder)
694 OS << ')';
695 SaveAndRestore<bool> NonEmptyPH(HasEmptyPlaceHolder, false);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000696
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000697 OS << "()";
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000698 if (T->getNoReturnAttr())
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000699 OS << " __attribute__((noreturn))";
700 printAfter(T->getResultType(), OS);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000701}
702
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000703void TypePrinter::printTypeSpec(const NamedDecl *D, raw_ostream &OS) {
John McCall3cb0ebd2010-03-10 03:28:59 +0000704 IdentifierInfo *II = D->getIdentifier();
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000705 OS << II->getName();
706 spaceBeforePlaceHolder(OS);
John McCalled976492009-12-04 22:46:56 +0000707}
708
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000709void TypePrinter::printUnresolvedUsingBefore(const UnresolvedUsingType *T,
710 raw_ostream &OS) {
711 printTypeSpec(T->getDecl(), OS);
John McCall3cb0ebd2010-03-10 03:28:59 +0000712}
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000713void TypePrinter::printUnresolvedUsingAfter(const UnresolvedUsingType *T,
714 raw_ostream &OS) { }
John McCall3cb0ebd2010-03-10 03:28:59 +0000715
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000716void TypePrinter::printTypedefBefore(const TypedefType *T, raw_ostream &OS) {
717 printTypeSpec(T->getDecl(), OS);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000718}
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000719void TypePrinter::printTypedefAfter(const TypedefType *T, raw_ostream &OS) { }
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000720
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000721void TypePrinter::printTypeOfExprBefore(const TypeOfExprType *T,
722 raw_ostream &OS) {
723 OS << "typeof ";
724 T->getUnderlyingExpr()->printPretty(OS, 0, Policy);
725 spaceBeforePlaceHolder(OS);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000726}
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000727void TypePrinter::printTypeOfExprAfter(const TypeOfExprType *T,
728 raw_ostream &OS) { }
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000729
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000730void TypePrinter::printTypeOfBefore(const TypeOfType *T, raw_ostream &OS) {
731 OS << "typeof(";
732 print(T->getUnderlyingType(), OS, StringRef());
733 OS << ')';
734 spaceBeforePlaceHolder(OS);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000735}
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000736void TypePrinter::printTypeOfAfter(const TypeOfType *T, raw_ostream &OS) { }
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000737
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000738void TypePrinter::printDecltypeBefore(const DecltypeType *T, raw_ostream &OS) {
739 OS << "decltype(";
740 T->getUnderlyingExpr()->printPretty(OS, 0, Policy);
741 OS << ')';
742 spaceBeforePlaceHolder(OS);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000743}
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000744void TypePrinter::printDecltypeAfter(const DecltypeType *T, raw_ostream &OS) { }
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000745
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000746void TypePrinter::printUnaryTransformBefore(const UnaryTransformType *T,
747 raw_ostream &OS) {
John McCallf85e1932011-06-15 23:02:42 +0000748 IncludeStrongLifetimeRAII Strong(Policy);
Sean Huntca63c202011-05-24 22:41:36 +0000749
750 switch (T->getUTTKind()) {
751 case UnaryTransformType::EnumUnderlyingType:
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000752 OS << "__underlying_type(";
753 print(T->getBaseType(), OS, StringRef());
754 OS << ')';
755 spaceBeforePlaceHolder(OS);
756 return;
Sean Huntca63c202011-05-24 22:41:36 +0000757 }
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000758
759 printBefore(T->getBaseType(), OS);
760}
761void TypePrinter::printUnaryTransformAfter(const UnaryTransformType *T,
762 raw_ostream &OS) {
763 IncludeStrongLifetimeRAII Strong(Policy);
764
765 switch (T->getUTTKind()) {
766 case UnaryTransformType::EnumUnderlyingType:
767 return;
768 }
769
770 printAfter(T->getBaseType(), OS);
Sean Huntca63c202011-05-24 22:41:36 +0000771}
772
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000773void TypePrinter::printAutoBefore(const AutoType *T, raw_ostream &OS) {
Richard Smith34b41d92011-02-20 03:19:35 +0000774 // If the type has been deduced, do not print 'auto'.
775 if (T->isDeduced()) {
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000776 printBefore(T->getDeducedType(), OS);
Richard Smith34b41d92011-02-20 03:19:35 +0000777 } else {
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000778 OS << "auto";
779 spaceBeforePlaceHolder(OS);
Richard Smith34b41d92011-02-20 03:19:35 +0000780 }
781}
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000782void TypePrinter::printAutoAfter(const AutoType *T, raw_ostream &OS) {
783 // If the type has been deduced, do not print 'auto'.
784 if (T->isDeduced())
785 printAfter(T->getDeducedType(), OS);
Eli Friedmanb001de72011-10-06 23:00:33 +0000786}
787
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000788void TypePrinter::printAtomicBefore(const AtomicType *T, raw_ostream &OS) {
789 IncludeStrongLifetimeRAII Strong(Policy);
John McCall7c2342d2010-03-10 11:27:22 +0000790
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000791 OS << "_Atomic(";
792 print(T->getValueType(), OS, StringRef());
793 OS << ')';
794 spaceBeforePlaceHolder(OS);
795}
796void TypePrinter::printAtomicAfter(const AtomicType *T, raw_ostream &OS) { }
797
798/// Appends the given scope to the end of a string.
799void TypePrinter::AppendScope(DeclContext *DC, raw_ostream &OS) {
800 if (DC->isTranslationUnit()) return;
801 AppendScope(DC->getParent(), OS);
John McCall7c2342d2010-03-10 11:27:22 +0000802
803 if (NamespaceDecl *NS = dyn_cast<NamespaceDecl>(DC)) {
Douglas Gregor25270b62011-11-03 00:16:13 +0000804 if (Policy.SuppressUnwrittenScope &&
805 (NS->isAnonymousNamespace() || NS->isInline()))
806 return;
John McCall7c2342d2010-03-10 11:27:22 +0000807 if (NS->getIdentifier())
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000808 OS << NS->getName() << "::";
John McCall7c2342d2010-03-10 11:27:22 +0000809 else
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000810 OS << "<anonymous>::";
John McCall7c2342d2010-03-10 11:27:22 +0000811 } else if (ClassTemplateSpecializationDecl *Spec
812 = dyn_cast<ClassTemplateSpecializationDecl>(DC)) {
John McCallf85e1932011-06-15 23:02:42 +0000813 IncludeStrongLifetimeRAII Strong(Policy);
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000814 OS << Spec->getIdentifier()->getName();
John McCall7c2342d2010-03-10 11:27:22 +0000815 const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs();
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000816 TemplateSpecializationType::PrintTemplateArgumentList(OS,
Douglas Gregor910f8002010-11-07 23:05:16 +0000817 TemplateArgs.data(),
818 TemplateArgs.size(),
John McCall7c2342d2010-03-10 11:27:22 +0000819 Policy);
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000820 OS << "::";
John McCall7c2342d2010-03-10 11:27:22 +0000821 } else if (TagDecl *Tag = dyn_cast<TagDecl>(DC)) {
Richard Smith162e1c12011-04-15 14:24:37 +0000822 if (TypedefNameDecl *Typedef = Tag->getTypedefNameForAnonDecl())
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000823 OS << Typedef->getIdentifier()->getName() << "::";
John McCall7c2342d2010-03-10 11:27:22 +0000824 else if (Tag->getIdentifier())
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000825 OS << Tag->getIdentifier()->getName() << "::";
Douglas Gregor25270b62011-11-03 00:16:13 +0000826 else
827 return;
John McCall7c2342d2010-03-10 11:27:22 +0000828 }
John McCall7c2342d2010-03-10 11:27:22 +0000829}
830
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000831void TypePrinter::printTag(TagDecl *D, raw_ostream &OS) {
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000832 if (Policy.SuppressTag)
833 return;
John McCall7c2342d2010-03-10 11:27:22 +0000834
John McCall73061d02010-03-19 07:56:44 +0000835 bool HasKindDecoration = false;
John McCall7c2342d2010-03-10 11:27:22 +0000836
Abramo Bagnara0daaf322011-03-16 20:16:18 +0000837 // bool SuppressTagKeyword
838 // = Policy.LangOpts.CPlusPlus || Policy.SuppressTagKeyword;
839
John McCall7c2342d2010-03-10 11:27:22 +0000840 // We don't print tags unless this is an elaborated type.
841 // In C, we just assume every RecordType is an elaborated type.
Abramo Bagnara0daaf322011-03-16 20:16:18 +0000842 if (!(Policy.LangOpts.CPlusPlus || Policy.SuppressTagKeyword ||
Richard Smith162e1c12011-04-15 14:24:37 +0000843 D->getTypedefNameForAnonDecl())) {
John McCall73061d02010-03-19 07:56:44 +0000844 HasKindDecoration = true;
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000845 OS << D->getKindName();
846 OS << ' ';
John McCall7c2342d2010-03-10 11:27:22 +0000847 }
848
Chris Lattnerc7acc662010-08-28 16:26:18 +0000849 // Compute the full nested-name-specifier for this type.
850 // In C, this will always be empty except when the type
851 // being printed is anonymous within other Record.
John McCall7c2342d2010-03-10 11:27:22 +0000852 if (!Policy.SuppressScope)
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000853 AppendScope(D->getDeclContext(), OS);
John McCall7c2342d2010-03-10 11:27:22 +0000854
John McCall3cb0ebd2010-03-10 03:28:59 +0000855 if (const IdentifierInfo *II = D->getIdentifier())
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000856 OS << II->getName();
Richard Smith162e1c12011-04-15 14:24:37 +0000857 else if (TypedefNameDecl *Typedef = D->getTypedefNameForAnonDecl()) {
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000858 assert(Typedef->getIdentifier() && "Typedef without identifier?");
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000859 OS << Typedef->getIdentifier()->getName();
John McCall73061d02010-03-19 07:56:44 +0000860 } else {
861 // Make an unambiguous representation for anonymous types, e.g.
862 // <anonymous enum at /usr/include/string.h:120:9>
Douglas Gregore4e68d42012-02-15 19:33:52 +0000863
864 if (isa<CXXRecordDecl>(D) && cast<CXXRecordDecl>(D)->isLambda()) {
865 OS << "<lambda";
866 HasKindDecoration = true;
867 } else {
868 OS << "<anonymous";
869 }
870
Douglas Gregor84139d62010-04-05 21:25:31 +0000871 if (Policy.AnonymousTagLocations) {
872 // Suppress the redundant tag keyword if we just printed one.
873 // We don't have to worry about ElaboratedTypes here because you can't
874 // refer to an anonymous type with one.
875 if (!HasKindDecoration)
876 OS << " " << D->getKindName();
John McCall73061d02010-03-19 07:56:44 +0000877
Douglas Gregorcb7b1e12010-11-12 07:15:47 +0000878 PresumedLoc PLoc = D->getASTContext().getSourceManager().getPresumedLoc(
Douglas Gregor16834e82010-05-28 21:47:04 +0000879 D->getLocation());
Douglas Gregorcb7b1e12010-11-12 07:15:47 +0000880 if (PLoc.isValid()) {
Douglas Gregor16834e82010-05-28 21:47:04 +0000881 OS << " at " << PLoc.getFilename()
882 << ':' << PLoc.getLine()
883 << ':' << PLoc.getColumn();
884 }
Douglas Gregor84139d62010-04-05 21:25:31 +0000885 }
886
887 OS << '>';
John McCall73061d02010-03-19 07:56:44 +0000888 }
John McCall7c2342d2010-03-10 11:27:22 +0000889
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000890 // If this is a class template specialization, print the template
891 // arguments.
892 if (ClassTemplateSpecializationDecl *Spec
John McCall7c2342d2010-03-10 11:27:22 +0000893 = dyn_cast<ClassTemplateSpecializationDecl>(D)) {
John McCall3cb0ebd2010-03-10 03:28:59 +0000894 const TemplateArgument *Args;
895 unsigned NumArgs;
896 if (TypeSourceInfo *TAW = Spec->getTypeAsWritten()) {
897 const TemplateSpecializationType *TST =
898 cast<TemplateSpecializationType>(TAW->getType());
899 Args = TST->getArgs();
900 NumArgs = TST->getNumArgs();
901 } else {
902 const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs();
Douglas Gregor910f8002010-11-07 23:05:16 +0000903 Args = TemplateArgs.data();
904 NumArgs = TemplateArgs.size();
John McCall3cb0ebd2010-03-10 03:28:59 +0000905 }
John McCallf85e1932011-06-15 23:02:42 +0000906 IncludeStrongLifetimeRAII Strong(Policy);
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000907 TemplateSpecializationType::PrintTemplateArgumentList(OS,
908 Args, NumArgs,
909 Policy);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000910 }
John McCall7c2342d2010-03-10 11:27:22 +0000911
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000912 spaceBeforePlaceHolder(OS);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000913}
914
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000915void TypePrinter::printRecordBefore(const RecordType *T, raw_ostream &OS) {
916 printTag(T->getDecl(), OS);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000917}
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000918void TypePrinter::printRecordAfter(const RecordType *T, raw_ostream &OS) { }
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000919
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000920void TypePrinter::printEnumBefore(const EnumType *T, raw_ostream &OS) {
921 printTag(T->getDecl(), OS);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000922}
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000923void TypePrinter::printEnumAfter(const EnumType *T, raw_ostream &OS) { }
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000924
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000925void TypePrinter::printTemplateTypeParmBefore(const TemplateTypeParmType *T,
926 raw_ostream &OS) {
Chandler Carruthb7efff42011-05-01 01:05:51 +0000927 if (IdentifierInfo *Id = T->getIdentifier())
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000928 OS << Id->getName();
Chandler Carruth4fb86f82011-05-01 00:51:33 +0000929 else
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000930 OS << "type-parameter-" << T->getDepth() << '-' << T->getIndex();
931 spaceBeforePlaceHolder(OS);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000932}
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000933void TypePrinter::printTemplateTypeParmAfter(const TemplateTypeParmType *T,
934 raw_ostream &OS) { }
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000935
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000936void TypePrinter::printSubstTemplateTypeParmBefore(
937 const SubstTemplateTypeParmType *T,
938 raw_ostream &OS) {
John McCallf85e1932011-06-15 23:02:42 +0000939 IncludeStrongLifetimeRAII Strong(Policy);
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000940 printBefore(T->getReplacementType(), OS);
941}
942void TypePrinter::printSubstTemplateTypeParmAfter(
943 const SubstTemplateTypeParmType *T,
944 raw_ostream &OS) {
945 IncludeStrongLifetimeRAII Strong(Policy);
946 printAfter(T->getReplacementType(), OS);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000947}
948
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000949void TypePrinter::printSubstTemplateTypeParmPackBefore(
Douglas Gregorc3069d62011-01-14 02:55:32 +0000950 const SubstTemplateTypeParmPackType *T,
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000951 raw_ostream &OS) {
John McCallf85e1932011-06-15 23:02:42 +0000952 IncludeStrongLifetimeRAII Strong(Policy);
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000953 printTemplateTypeParmBefore(T->getReplacedParameter(), OS);
954}
955void TypePrinter::printSubstTemplateTypeParmPackAfter(
956 const SubstTemplateTypeParmPackType *T,
957 raw_ostream &OS) {
958 IncludeStrongLifetimeRAII Strong(Policy);
959 printTemplateTypeParmAfter(T->getReplacedParameter(), OS);
Douglas Gregorc3069d62011-01-14 02:55:32 +0000960}
961
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000962void TypePrinter::printTemplateSpecializationBefore(
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000963 const TemplateSpecializationType *T,
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000964 raw_ostream &OS) {
John McCallf85e1932011-06-15 23:02:42 +0000965 IncludeStrongLifetimeRAII Strong(Policy);
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000966 T->getTemplateName().print(OS, Policy);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000967
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000968 TemplateSpecializationType::PrintTemplateArgumentList(OS,
969 T->getArgs(),
970 T->getNumArgs(),
971 Policy);
972 spaceBeforePlaceHolder(OS);
973}
974void TypePrinter::printTemplateSpecializationAfter(
975 const TemplateSpecializationType *T,
976 raw_ostream &OS) { }
977
978void TypePrinter::printInjectedClassNameBefore(const InjectedClassNameType *T,
979 raw_ostream &OS) {
980 printTemplateSpecializationBefore(T->getInjectedTST(), OS);
981}
982void TypePrinter::printInjectedClassNameAfter(const InjectedClassNameType *T,
983 raw_ostream &OS) { }
984
985void TypePrinter::printElaboratedBefore(const ElaboratedType *T,
986 raw_ostream &OS) {
987 OS << TypeWithKeyword::getKeywordName(T->getKeyword());
988 if (T->getKeyword() != ETK_None)
989 OS << " ";
990 NestedNameSpecifier* Qualifier = T->getQualifier();
991 if (Qualifier)
992 Qualifier->print(OS, Policy);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000993
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +0000994 ElaboratedTypePolicyRAII PolicyRAII(Policy);
995 printBefore(T->getNamedType(), OS);
996}
997void TypePrinter::printElaboratedAfter(const ElaboratedType *T,
998 raw_ostream &OS) {
999 ElaboratedTypePolicyRAII PolicyRAII(Policy);
1000 printAfter(T->getNamedType(), OS);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +00001001}
1002
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +00001003void TypePrinter::printParenBefore(const ParenType *T, raw_ostream &OS) {
1004 if (!HasEmptyPlaceHolder && !isa<FunctionType>(T->getInnerType())) {
1005 printBefore(T->getInnerType(), OS);
1006 OS << '(';
1007 } else
1008 printBefore(T->getInnerType(), OS);
1009}
1010void TypePrinter::printParenAfter(const ParenType *T, raw_ostream &OS) {
1011 if (!HasEmptyPlaceHolder && !isa<FunctionType>(T->getInnerType())) {
1012 OS << ')';
1013 printAfter(T->getInnerType(), OS);
1014 } else
1015 printAfter(T->getInnerType(), OS);
John McCall3cb0ebd2010-03-10 03:28:59 +00001016}
1017
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +00001018void TypePrinter::printDependentNameBefore(const DependentNameType *T,
1019 raw_ostream &OS) {
1020 OS << TypeWithKeyword::getKeywordName(T->getKeyword());
1021 if (T->getKeyword() != ETK_None)
1022 OS << " ";
Douglas Gregorfee8a3c2009-11-10 00:39:07 +00001023
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +00001024 T->getQualifier()->print(OS, Policy);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +00001025
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +00001026 OS << T->getIdentifier()->getName();
1027 spaceBeforePlaceHolder(OS);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +00001028}
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +00001029void TypePrinter::printDependentNameAfter(const DependentNameType *T,
1030 raw_ostream &OS) { }
Douglas Gregorfee8a3c2009-11-10 00:39:07 +00001031
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +00001032void TypePrinter::printDependentTemplateSpecializationBefore(
1033 const DependentTemplateSpecializationType *T, raw_ostream &OS) {
John McCallf85e1932011-06-15 23:02:42 +00001034 IncludeStrongLifetimeRAII Strong(Policy);
John McCall33500952010-06-11 00:33:02 +00001035
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +00001036 OS << TypeWithKeyword::getKeywordName(T->getKeyword());
1037 if (T->getKeyword() != ETK_None)
1038 OS << " ";
Douglas Gregorfee8a3c2009-11-10 00:39:07 +00001039
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +00001040 if (T->getQualifier())
1041 T->getQualifier()->print(OS, Policy);
1042 OS << T->getIdentifier()->getName();
1043 TemplateSpecializationType::PrintTemplateArgumentList(OS,
1044 T->getArgs(),
1045 T->getNumArgs(),
1046 Policy);
1047 spaceBeforePlaceHolder(OS);
1048}
1049void TypePrinter::printDependentTemplateSpecializationAfter(
1050 const DependentTemplateSpecializationType *T, raw_ostream &OS) { }
1051
1052void TypePrinter::printPackExpansionBefore(const PackExpansionType *T,
1053 raw_ostream &OS) {
1054 printBefore(T->getPattern(), OS);
1055}
1056void TypePrinter::printPackExpansionAfter(const PackExpansionType *T,
1057 raw_ostream &OS) {
1058 printAfter(T->getPattern(), OS);
1059 OS << "...";
Douglas Gregorfee8a3c2009-11-10 00:39:07 +00001060}
1061
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +00001062void TypePrinter::printAttributedBefore(const AttributedType *T,
1063 raw_ostream &OS) {
Argyrios Kyrtzidisb8b03132011-06-24 00:08:59 +00001064 // Prefer the macro forms of the GC and ownership qualifiers.
John McCallf85e1932011-06-15 23:02:42 +00001065 if (T->getAttrKind() == AttributedType::attr_objc_gc ||
Argyrios Kyrtzidisb8b03132011-06-24 00:08:59 +00001066 T->getAttrKind() == AttributedType::attr_objc_ownership)
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +00001067 return printBefore(T->getEquivalentType(), OS);
John McCall14aa2172011-03-04 04:00:19 +00001068
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +00001069 printBefore(T->getModifiedType(), OS);
1070}
1071
1072void TypePrinter::printAttributedAfter(const AttributedType *T,
1073 raw_ostream &OS) {
1074 // Prefer the macro forms of the GC and ownership qualifiers.
1075 if (T->getAttrKind() == AttributedType::attr_objc_gc ||
1076 T->getAttrKind() == AttributedType::attr_objc_ownership)
1077 return printAfter(T->getEquivalentType(), OS);
John McCall9d156a72011-01-06 01:58:22 +00001078
1079 // TODO: not all attributes are GCC-style attributes.
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +00001080 OS << " __attribute__((";
John McCall9d156a72011-01-06 01:58:22 +00001081 switch (T->getAttrKind()) {
Francois Pichet170464b2011-01-07 03:17:31 +00001082 case AttributedType::attr_address_space:
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +00001083 OS << "address_space(";
1084 OS << T->getEquivalentType().getAddressSpace();
1085 OS << ')';
John McCall9d156a72011-01-06 01:58:22 +00001086 break;
1087
Francois Pichet170464b2011-01-07 03:17:31 +00001088 case AttributedType::attr_vector_size: {
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +00001089 OS << "__vector_size__(";
John McCall9d156a72011-01-06 01:58:22 +00001090 if (const VectorType *vector =T->getEquivalentType()->getAs<VectorType>()) {
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +00001091 OS << vector->getNumElements();
1092 OS << " * sizeof(";
1093 print(vector->getElementType(), OS, StringRef());
1094 OS << ')';
John McCall9d156a72011-01-06 01:58:22 +00001095 }
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +00001096 OS << ')';
John McCall9d156a72011-01-06 01:58:22 +00001097 break;
1098 }
1099
Francois Pichet170464b2011-01-07 03:17:31 +00001100 case AttributedType::attr_neon_vector_type:
1101 case AttributedType::attr_neon_polyvector_type: {
1102 if (T->getAttrKind() == AttributedType::attr_neon_vector_type)
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +00001103 OS << "neon_vector_type(";
John McCall9d156a72011-01-06 01:58:22 +00001104 else
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +00001105 OS << "neon_polyvector_type(";
John McCall9d156a72011-01-06 01:58:22 +00001106 const VectorType *vector = T->getEquivalentType()->getAs<VectorType>();
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +00001107 OS << vector->getNumElements();
1108 OS << ')';
John McCall9d156a72011-01-06 01:58:22 +00001109 break;
1110 }
1111
Francois Pichet170464b2011-01-07 03:17:31 +00001112 case AttributedType::attr_regparm: {
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +00001113 OS << "regparm(";
John McCall9d156a72011-01-06 01:58:22 +00001114 QualType t = T->getEquivalentType();
1115 while (!t->isFunctionType())
1116 t = t->getPointeeType();
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +00001117 OS << t->getAs<FunctionType>()->getRegParmType();
1118 OS << ')';
John McCall9d156a72011-01-06 01:58:22 +00001119 break;
1120 }
1121
Francois Pichet170464b2011-01-07 03:17:31 +00001122 case AttributedType::attr_objc_gc: {
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +00001123 OS << "objc_gc(";
John McCall9d156a72011-01-06 01:58:22 +00001124
1125 QualType tmp = T->getEquivalentType();
1126 while (tmp.getObjCGCAttr() == Qualifiers::GCNone) {
1127 QualType next = tmp->getPointeeType();
1128 if (next == tmp) break;
1129 tmp = next;
1130 }
1131
1132 if (tmp.isObjCGCWeak())
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +00001133 OS << "weak";
John McCall9d156a72011-01-06 01:58:22 +00001134 else
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +00001135 OS << "strong";
1136 OS << ')';
John McCall9d156a72011-01-06 01:58:22 +00001137 break;
1138 }
1139
Argyrios Kyrtzidisb8b03132011-06-24 00:08:59 +00001140 case AttributedType::attr_objc_ownership:
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +00001141 OS << "objc_ownership(";
John McCallf85e1932011-06-15 23:02:42 +00001142 switch (T->getEquivalentType().getObjCLifetime()) {
David Blaikie30263482012-01-20 21:50:17 +00001143 case Qualifiers::OCL_None: llvm_unreachable("no ownership!");
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +00001144 case Qualifiers::OCL_ExplicitNone: OS << "none"; break;
1145 case Qualifiers::OCL_Strong: OS << "strong"; break;
1146 case Qualifiers::OCL_Weak: OS << "weak"; break;
1147 case Qualifiers::OCL_Autoreleasing: OS << "autoreleasing"; break;
John McCallf85e1932011-06-15 23:02:42 +00001148 }
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +00001149 OS << ')';
John McCallf85e1932011-06-15 23:02:42 +00001150 break;
1151
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +00001152 case AttributedType::attr_noreturn: OS << "noreturn"; break;
1153 case AttributedType::attr_cdecl: OS << "cdecl"; break;
1154 case AttributedType::attr_fastcall: OS << "fastcall"; break;
1155 case AttributedType::attr_stdcall: OS << "stdcall"; break;
1156 case AttributedType::attr_thiscall: OS << "thiscall"; break;
1157 case AttributedType::attr_pascal: OS << "pascal"; break;
Anton Korobeynikov414d8962011-04-14 20:06:49 +00001158 case AttributedType::attr_pcs: {
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +00001159 OS << "pcs(";
Anton Korobeynikov414d8962011-04-14 20:06:49 +00001160 QualType t = T->getEquivalentType();
1161 while (!t->isFunctionType())
1162 t = t->getPointeeType();
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +00001163 OS << (t->getAs<FunctionType>()->getCallConv() == CC_AAPCS ?
Anton Korobeynikov414d8962011-04-14 20:06:49 +00001164 "\"aapcs\"" : "\"aapcs-vfp\"");
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +00001165 OS << ')';
Anton Korobeynikov414d8962011-04-14 20:06:49 +00001166 break;
1167 }
John McCall9d156a72011-01-06 01:58:22 +00001168 }
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +00001169 OS << "))";
John McCall9d156a72011-01-06 01:58:22 +00001170}
1171
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +00001172void TypePrinter::printObjCInterfaceBefore(const ObjCInterfaceType *T,
1173 raw_ostream &OS) {
1174 OS << T->getDecl()->getName();
1175 spaceBeforePlaceHolder(OS);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +00001176}
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +00001177void TypePrinter::printObjCInterfaceAfter(const ObjCInterfaceType *T,
1178 raw_ostream &OS) { }
Douglas Gregorfee8a3c2009-11-10 00:39:07 +00001179
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +00001180void TypePrinter::printObjCObjectBefore(const ObjCObjectType *T,
1181 raw_ostream &OS) {
John McCallc12c5bb2010-05-15 11:32:37 +00001182 if (T->qual_empty())
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +00001183 return printBefore(T->getBaseType(), OS);
John McCallc12c5bb2010-05-15 11:32:37 +00001184
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +00001185 print(T->getBaseType(), OS, StringRef());
1186 OS << '<';
John McCallc12c5bb2010-05-15 11:32:37 +00001187 bool isFirst = true;
1188 for (ObjCObjectType::qual_iterator
1189 I = T->qual_begin(), E = T->qual_end(); I != E; ++I) {
1190 if (isFirst)
1191 isFirst = false;
1192 else
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +00001193 OS << ',';
1194 OS << (*I)->getName();
John McCallc12c5bb2010-05-15 11:32:37 +00001195 }
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +00001196 OS << '>';
1197 spaceBeforePlaceHolder(OS);
1198}
1199void TypePrinter::printObjCObjectAfter(const ObjCObjectType *T,
1200 raw_ostream &OS) {
1201 if (T->qual_empty())
1202 return printAfter(T->getBaseType(), OS);
John McCallc12c5bb2010-05-15 11:32:37 +00001203}
1204
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +00001205void TypePrinter::printObjCObjectPointerBefore(const ObjCObjectPointerType *T,
1206 raw_ostream &OS) {
1207 T->getPointeeType().getLocalQualifiers().print(OS, Policy,
1208 /*appendSpaceIfNonEmpty=*/true);
1209
Douglas Gregorfee8a3c2009-11-10 00:39:07 +00001210 if (T->isObjCIdType() || T->isObjCQualifiedIdType())
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +00001211 OS << "id";
Douglas Gregorfee8a3c2009-11-10 00:39:07 +00001212 else if (T->isObjCClassType() || T->isObjCQualifiedClassType())
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +00001213 OS << "Class";
Fariborz Jahanian13dcd002009-11-21 19:53:08 +00001214 else if (T->isObjCSelType())
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +00001215 OS << "SEL";
Douglas Gregorfee8a3c2009-11-10 00:39:07 +00001216 else
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +00001217 OS << T->getInterfaceDecl()->getName();
Douglas Gregorfee8a3c2009-11-10 00:39:07 +00001218
1219 if (!T->qual_empty()) {
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +00001220 OS << '<';
Douglas Gregorfee8a3c2009-11-10 00:39:07 +00001221 for (ObjCObjectPointerType::qual_iterator I = T->qual_begin(),
1222 E = T->qual_end();
1223 I != E; ++I) {
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +00001224 OS << (*I)->getName();
Douglas Gregorfee8a3c2009-11-10 00:39:07 +00001225 if (I+1 != E)
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +00001226 OS << ',';
Douglas Gregorfee8a3c2009-11-10 00:39:07 +00001227 }
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +00001228 OS << '>';
Douglas Gregorfee8a3c2009-11-10 00:39:07 +00001229 }
1230
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +00001231 if (!T->isObjCIdType() && !T->isObjCQualifiedIdType()) {
1232 OS << " *"; // Don't forget the implicit pointer.
1233 } else {
1234 spaceBeforePlaceHolder(OS);
1235 }
1236}
1237void TypePrinter::printObjCObjectPointerAfter(const ObjCObjectPointerType *T,
1238 raw_ostream &OS) { }
1239
1240void TemplateSpecializationType::
1241 PrintTemplateArgumentList(raw_ostream &OS,
1242 const TemplateArgumentListInfo &Args,
1243 const PrintingPolicy &Policy) {
1244 return PrintTemplateArgumentList(OS,
1245 Args.getArgumentArray(),
1246 Args.size(),
1247 Policy);
1248}
1249
1250void
1251TemplateSpecializationType::PrintTemplateArgumentList(
1252 raw_ostream &OS,
1253 const TemplateArgument *Args,
1254 unsigned NumArgs,
1255 const PrintingPolicy &Policy,
1256 bool SkipBrackets) {
1257 if (!SkipBrackets)
1258 OS << '<';
Douglas Gregorfee8a3c2009-11-10 00:39:07 +00001259
Axel Naumann16d00782012-06-29 07:30:33 +00001260 bool needSpace = false;
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +00001261 for (unsigned Arg = 0; Arg < NumArgs; ++Arg) {
1262 if (Arg > 0)
1263 OS << ", ";
1264
1265 // Print the argument into a string.
1266 SmallString<128> Buf;
1267 llvm::raw_svector_ostream ArgOS(Buf);
1268 if (Args[Arg].getKind() == TemplateArgument::Pack) {
1269 PrintTemplateArgumentList(ArgOS,
1270 Args[Arg].pack_begin(),
1271 Args[Arg].pack_size(),
1272 Policy, true);
1273 } else {
1274 Args[Arg].print(Policy, ArgOS);
1275 }
1276 StringRef ArgString = ArgOS.str();
1277
1278 // If this is the first argument and its string representation
1279 // begins with the global scope specifier ('::foo'), add a space
1280 // to avoid printing the diagraph '<:'.
1281 if (!Arg && !ArgString.empty() && ArgString[0] == ':')
1282 OS << ' ';
Axel Naumann16d00782012-06-29 07:30:33 +00001283
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +00001284 OS << ArgString;
Axel Naumann16d00782012-06-29 07:30:33 +00001285
1286 needSpace = (!ArgString.empty() && ArgString.back() == '>');
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +00001287 }
1288
Axel Naumann16d00782012-06-29 07:30:33 +00001289 // If the last character of our string is '>', add another space to
1290 // keep the two '>''s separate tokens. We don't *have* to do this in
1291 // C++0x, but it's still good hygiene.
1292 if (needSpace)
1293 OS << ' ';
1294
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +00001295 if (!SkipBrackets)
1296 OS << '>';
1297}
1298
1299// Sadly, repeat all that with TemplateArgLoc.
1300void TemplateSpecializationType::
1301PrintTemplateArgumentList(raw_ostream &OS,
1302 const TemplateArgumentLoc *Args, unsigned NumArgs,
1303 const PrintingPolicy &Policy) {
1304 OS << '<';
Axel Naumann16d00782012-06-29 07:30:33 +00001305
1306 bool needSpace = false;
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +00001307 for (unsigned Arg = 0; Arg < NumArgs; ++Arg) {
1308 if (Arg > 0)
1309 OS << ", ";
1310
1311 // Print the argument into a string.
1312 SmallString<128> Buf;
1313 llvm::raw_svector_ostream ArgOS(Buf);
1314 if (Args[Arg].getArgument().getKind() == TemplateArgument::Pack) {
1315 PrintTemplateArgumentList(ArgOS,
1316 Args[Arg].getArgument().pack_begin(),
1317 Args[Arg].getArgument().pack_size(),
1318 Policy, true);
1319 } else {
1320 Args[Arg].getArgument().print(Policy, ArgOS);
1321 }
1322 StringRef ArgString = ArgOS.str();
1323
1324 // If this is the first argument and its string representation
1325 // begins with the global scope specifier ('::foo'), add a space
1326 // to avoid printing the diagraph '<:'.
1327 if (!Arg && !ArgString.empty() && ArgString[0] == ':')
1328 OS << ' ';
Axel Naumann16d00782012-06-29 07:30:33 +00001329
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +00001330 OS << ArgString;
Axel Naumann16d00782012-06-29 07:30:33 +00001331
1332 needSpace = (!ArgString.empty() && ArgString.back() == '>');
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +00001333 }
1334
Axel Naumann16d00782012-06-29 07:30:33 +00001335 // If the last character of our string is '>', add another space to
1336 // keep the two '>''s separate tokens. We don't *have* to do this in
1337 // C++0x, but it's still good hygiene.
1338 if (needSpace)
1339 OS << ' ';
1340
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +00001341 OS << '>';
1342}
1343
1344void
1345FunctionProtoType::printExceptionSpecification(std::string &S,
1346 PrintingPolicy Policy) const {
1347
1348 if (hasDynamicExceptionSpec()) {
1349 S += " throw(";
1350 if (getExceptionSpecType() == EST_MSAny)
1351 S += "...";
1352 else
1353 for (unsigned I = 0, N = getNumExceptions(); I != N; ++I) {
1354 if (I)
1355 S += ", ";
1356
1357 S += getExceptionType(I).getAsString(Policy);
1358 }
1359 S += ")";
1360 } else if (isNoexceptExceptionSpec(getExceptionSpecType())) {
1361 S += " noexcept";
1362 if (getExceptionSpecType() == EST_ComputedNoexcept) {
1363 S += "(";
1364 llvm::raw_string_ostream EOut(S);
1365 getNoexceptExpr()->printPretty(EOut, 0, Policy);
1366 EOut.flush();
1367 S += EOut.str();
1368 S += ")";
1369 }
1370 }
Douglas Gregorfee8a3c2009-11-10 00:39:07 +00001371}
1372
John McCalld5532b62009-11-23 01:53:49 +00001373std::string TemplateSpecializationType::
1374 PrintTemplateArgumentList(const TemplateArgumentListInfo &Args,
1375 const PrintingPolicy &Policy) {
1376 return PrintTemplateArgumentList(Args.getArgumentArray(),
1377 Args.size(),
1378 Policy);
1379}
1380
Douglas Gregorfee8a3c2009-11-10 00:39:07 +00001381std::string
1382TemplateSpecializationType::PrintTemplateArgumentList(
1383 const TemplateArgument *Args,
1384 unsigned NumArgs,
Douglas Gregordace95b2010-12-20 22:28:59 +00001385 const PrintingPolicy &Policy,
1386 bool SkipBrackets) {
Douglas Gregorfee8a3c2009-11-10 00:39:07 +00001387 std::string SpecString;
Douglas Gregordace95b2010-12-20 22:28:59 +00001388 if (!SkipBrackets)
1389 SpecString += '<';
1390
Douglas Gregorfee8a3c2009-11-10 00:39:07 +00001391 for (unsigned Arg = 0; Arg < NumArgs; ++Arg) {
Francois Pichet319b4a62011-05-25 16:07:10 +00001392 if (SpecString.size() > unsigned(!SkipBrackets))
Douglas Gregorfee8a3c2009-11-10 00:39:07 +00001393 SpecString += ", ";
1394
1395 // Print the argument into a string.
1396 std::string ArgString;
Douglas Gregordace95b2010-12-20 22:28:59 +00001397 if (Args[Arg].getKind() == TemplateArgument::Pack) {
1398 ArgString = PrintTemplateArgumentList(Args[Arg].pack_begin(),
1399 Args[Arg].pack_size(),
1400 Policy, true);
1401 } else {
Douglas Gregor87dd6972010-12-20 16:52:59 +00001402 llvm::raw_string_ostream ArgOut(ArgString);
1403 Args[Arg].print(Policy, ArgOut);
1404 }
1405
Douglas Gregorfee8a3c2009-11-10 00:39:07 +00001406 // If this is the first argument and its string representation
1407 // begins with the global scope specifier ('::foo'), add a space
1408 // to avoid printing the diagraph '<:'.
1409 if (!Arg && !ArgString.empty() && ArgString[0] == ':')
1410 SpecString += ' ';
1411
1412 SpecString += ArgString;
1413 }
1414
1415 // If the last character of our string is '>', add another space to
1416 // keep the two '>''s separate tokens. We don't *have* to do this in
1417 // C++0x, but it's still good hygiene.
Francois Pichetb5bc7d02011-01-09 22:32:25 +00001418 if (!SpecString.empty() && SpecString[SpecString.size() - 1] == '>')
Douglas Gregorfee8a3c2009-11-10 00:39:07 +00001419 SpecString += ' ';
1420
Douglas Gregordace95b2010-12-20 22:28:59 +00001421 if (!SkipBrackets)
1422 SpecString += '>';
Douglas Gregorfee8a3c2009-11-10 00:39:07 +00001423
1424 return SpecString;
1425}
1426
1427// Sadly, repeat all that with TemplateArgLoc.
1428std::string TemplateSpecializationType::
1429PrintTemplateArgumentList(const TemplateArgumentLoc *Args, unsigned NumArgs,
1430 const PrintingPolicy &Policy) {
1431 std::string SpecString;
1432 SpecString += '<';
1433 for (unsigned Arg = 0; Arg < NumArgs; ++Arg) {
Douglas Gregordace95b2010-12-20 22:28:59 +00001434 if (SpecString.size() > 1)
Douglas Gregorfee8a3c2009-11-10 00:39:07 +00001435 SpecString += ", ";
1436
1437 // Print the argument into a string.
1438 std::string ArgString;
Douglas Gregordace95b2010-12-20 22:28:59 +00001439 if (Args[Arg].getArgument().getKind() == TemplateArgument::Pack) {
1440 ArgString = PrintTemplateArgumentList(
1441 Args[Arg].getArgument().pack_begin(),
1442 Args[Arg].getArgument().pack_size(),
1443 Policy, true);
1444 } else {
Douglas Gregor87dd6972010-12-20 16:52:59 +00001445 llvm::raw_string_ostream ArgOut(ArgString);
1446 Args[Arg].getArgument().print(Policy, ArgOut);
1447 }
Douglas Gregorfee8a3c2009-11-10 00:39:07 +00001448
1449 // If this is the first argument and its string representation
1450 // begins with the global scope specifier ('::foo'), add a space
1451 // to avoid printing the diagraph '<:'.
1452 if (!Arg && !ArgString.empty() && ArgString[0] == ':')
1453 SpecString += ' ';
1454
1455 SpecString += ArgString;
1456 }
1457
1458 // If the last character of our string is '>', add another space to
1459 // keep the two '>''s separate tokens. We don't *have* to do this in
1460 // C++0x, but it's still good hygiene.
1461 if (SpecString[SpecString.size() - 1] == '>')
1462 SpecString += ' ';
1463
1464 SpecString += '>';
1465
1466 return SpecString;
1467}
1468
1469void QualType::dump(const char *msg) const {
Douglas Gregorfee8a3c2009-11-10 00:39:07 +00001470 if (msg)
Daniel Dunbare7cb7e42009-12-03 09:14:02 +00001471 llvm::errs() << msg << ": ";
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +00001472 LangOptions LO;
1473 print(llvm::errs(), PrintingPolicy(LO), "identifier");
1474 llvm::errs() << '\n';
Douglas Gregorfee8a3c2009-11-10 00:39:07 +00001475}
1476void QualType::dump() const {
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +00001477 dump(0);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +00001478}
1479
1480void Type::dump() const {
1481 QualType(this, 0).dump();
1482}
1483
1484std::string Qualifiers::getAsString() const {
1485 LangOptions LO;
1486 return getAsString(PrintingPolicy(LO));
1487}
1488
1489// Appends qualifiers to the given string, separated by spaces. Will
1490// prefix a space if the string is non-empty. Will not append a final
1491// space.
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +00001492std::string Qualifiers::getAsString(const PrintingPolicy &Policy) const {
1493 SmallString<64> Buf;
1494 llvm::raw_svector_ostream StrOS(Buf);
1495 print(StrOS, Policy);
1496 return StrOS.str();
1497}
1498
1499bool Qualifiers::isEmptyWhenPrinted(const PrintingPolicy &Policy) const {
1500 if (getCVRQualifiers())
1501 return false;
1502
1503 if (getAddressSpace())
1504 return false;
1505
1506 if (getObjCGCAttr())
1507 return false;
1508
1509 if (Qualifiers::ObjCLifetime lifetime = getObjCLifetime())
1510 if (!(lifetime == Qualifiers::OCL_Strong && Policy.SuppressStrongLifetime))
1511 return false;
1512
1513 return true;
1514}
1515
1516// Appends qualifiers to the given string, separated by spaces. Will
1517// prefix a space if the string is non-empty. Will not append a final
1518// space.
1519void Qualifiers::print(raw_ostream &OS, const PrintingPolicy& Policy,
1520 bool appendSpaceIfNonEmpty) const {
1521 bool addSpace = false;
1522
1523 unsigned quals = getCVRQualifiers();
1524 if (quals) {
1525 AppendTypeQualList(OS, quals);
1526 addSpace = true;
1527 }
John McCall14aa2172011-03-04 04:00:19 +00001528 if (unsigned addrspace = getAddressSpace()) {
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +00001529 if (addSpace)
1530 OS << ' ';
1531 addSpace = true;
Peter Collingbourne63cf68a2011-11-08 02:52:58 +00001532 switch (addrspace) {
1533 case LangAS::opencl_global:
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +00001534 OS << "__global";
Peter Collingbourne63cf68a2011-11-08 02:52:58 +00001535 break;
1536 case LangAS::opencl_local:
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +00001537 OS << "__local";
Peter Collingbourne63cf68a2011-11-08 02:52:58 +00001538 break;
1539 case LangAS::opencl_constant:
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +00001540 OS << "__constant";
Peter Collingbourne63cf68a2011-11-08 02:52:58 +00001541 break;
1542 default:
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +00001543 OS << "__attribute__((address_space(";
1544 OS << addrspace;
1545 OS << ")))";
Peter Collingbourne63cf68a2011-11-08 02:52:58 +00001546 }
Douglas Gregorfee8a3c2009-11-10 00:39:07 +00001547 }
John McCall14aa2172011-03-04 04:00:19 +00001548 if (Qualifiers::GC gc = getObjCGCAttr()) {
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +00001549 if (addSpace)
1550 OS << ' ';
1551 addSpace = true;
John McCall14aa2172011-03-04 04:00:19 +00001552 if (gc == Qualifiers::Weak)
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +00001553 OS << "__weak";
Douglas Gregorfee8a3c2009-11-10 00:39:07 +00001554 else
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +00001555 OS << "__strong";
Douglas Gregorfee8a3c2009-11-10 00:39:07 +00001556 }
John McCallf85e1932011-06-15 23:02:42 +00001557 if (Qualifiers::ObjCLifetime lifetime = getObjCLifetime()) {
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +00001558 if (!(lifetime == Qualifiers::OCL_Strong && Policy.SuppressStrongLifetime)){
1559 if (addSpace)
1560 OS << ' ';
1561 addSpace = true;
1562 }
Axel Naumann16d00782012-06-29 07:30:33 +00001563
John McCallf85e1932011-06-15 23:02:42 +00001564 switch (lifetime) {
1565 case Qualifiers::OCL_None: llvm_unreachable("none but true");
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +00001566 case Qualifiers::OCL_ExplicitNone: OS << "__unsafe_unretained"; break;
John McCallf85e1932011-06-15 23:02:42 +00001567 case Qualifiers::OCL_Strong:
1568 if (!Policy.SuppressStrongLifetime)
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +00001569 OS << "__strong";
John McCallf85e1932011-06-15 23:02:42 +00001570 break;
1571
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +00001572 case Qualifiers::OCL_Weak: OS << "__weak"; break;
1573 case Qualifiers::OCL_Autoreleasing: OS << "__autoreleasing"; break;
John McCallf85e1932011-06-15 23:02:42 +00001574 }
1575 }
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +00001576
1577 if (appendSpaceIfNonEmpty && addSpace)
1578 OS << ' ';
1579}
1580
1581std::string QualType::getAsString(const PrintingPolicy &Policy) const {
1582 std::string S;
1583 getAsStringInternal(S, Policy);
1584 return S;
Douglas Gregorfee8a3c2009-11-10 00:39:07 +00001585}
1586
John McCall49f4e1c2010-12-10 11:01:00 +00001587std::string QualType::getAsString(const Type *ty, Qualifiers qs) {
1588 std::string buffer;
1589 LangOptions options;
1590 getAsStringInternal(ty, qs, buffer, PrintingPolicy(options));
1591 return buffer;
Douglas Gregorfee8a3c2009-11-10 00:39:07 +00001592}
1593
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +00001594void QualType::print(const Type *ty, Qualifiers qs,
1595 raw_ostream &OS, const PrintingPolicy &policy,
1596 const Twine &PlaceHolder) {
1597 SmallString<128> PHBuf;
1598 StringRef PH;
1599 if (PlaceHolder.isSingleStringRef())
1600 PH = PlaceHolder.getSingleStringRef();
1601 else
1602 PH = PlaceHolder.toStringRef(PHBuf);
1603
1604 TypePrinter(policy).print(ty, qs, OS, PH);
1605}
1606
John McCall49f4e1c2010-12-10 11:01:00 +00001607void QualType::getAsStringInternal(const Type *ty, Qualifiers qs,
1608 std::string &buffer,
1609 const PrintingPolicy &policy) {
Argyrios Kyrtzidis7ad5c992012-05-05 04:20:37 +00001610 SmallString<256> Buf;
1611 llvm::raw_svector_ostream StrOS(Buf);
1612 TypePrinter(policy).print(ty, qs, StrOS, buffer);
1613 std::string str = StrOS.str();
1614 buffer.swap(str);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +00001615}