blob: e21f9ac3ae4f448684511fb27ea6cfcb3d0e7547 [file] [log] [blame]
Douglas Gregorfee8a3c2009-11-10 00:39:07 +00001//===--- TypePrinter.cpp - Pretty-Print Clang Types -----------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This contains code to print types from Clang's type system.
11//
12//===----------------------------------------------------------------------===//
13
14#include "clang/AST/Decl.h"
15#include "clang/AST/DeclObjC.h"
16#include "clang/AST/DeclTemplate.h"
17#include "clang/AST/Expr.h"
18#include "clang/AST/Type.h"
19#include "clang/AST/PrettyPrinter.h"
20#include "clang/Basic/LangOptions.h"
John McCall73061d02010-03-19 07:56:44 +000021#include "clang/Basic/SourceManager.h"
Douglas Gregorfee8a3c2009-11-10 00:39:07 +000022#include "llvm/ADT/StringExtras.h"
23#include "llvm/Support/raw_ostream.h"
24using namespace clang;
25
26namespace {
27 class TypePrinter {
28 PrintingPolicy Policy;
29
30 public:
31 explicit TypePrinter(const PrintingPolicy &Policy) : Policy(Policy) { }
Abramo Bagnara493ec512010-04-27 21:08:25 +000032
Douglas Gregorfee8a3c2009-11-10 00:39:07 +000033 void Print(QualType T, std::string &S);
John McCall7c2342d2010-03-10 11:27:22 +000034 void AppendScope(DeclContext *DC, std::string &S);
John McCall3cb0ebd2010-03-10 03:28:59 +000035 void PrintTag(TagDecl *T, std::string &S);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +000036#define ABSTRACT_TYPE(CLASS, PARENT)
37#define TYPE(CLASS, PARENT) \
38 void Print##CLASS(const CLASS##Type *T, std::string &S);
39#include "clang/AST/TypeNodes.def"
40 };
41}
42
43static void AppendTypeQualList(std::string &S, unsigned TypeQuals) {
44 if (TypeQuals & Qualifiers::Const) {
45 if (!S.empty()) S += ' ';
46 S += "const";
47 }
48 if (TypeQuals & Qualifiers::Volatile) {
49 if (!S.empty()) S += ' ';
50 S += "volatile";
51 }
52 if (TypeQuals & Qualifiers::Restrict) {
53 if (!S.empty()) S += ' ';
54 S += "restrict";
55 }
56}
57
58void TypePrinter::Print(QualType T, std::string &S) {
59 if (T.isNull()) {
60 S += "NULL TYPE";
61 return;
62 }
63
64 if (Policy.SuppressSpecifiers && T->isSpecifierType())
65 return;
66
67 // Print qualifiers as appropriate.
Douglas Gregora4923eb2009-11-16 21:35:15 +000068 Qualifiers Quals = T.getLocalQualifiers();
Chris Lattner58f9e132010-09-05 00:04:01 +000069
70 // CanPrefixQualifiers - We prefer to print type qualifiers before the type,
71 // so that we get "const int" instead of "int const", but we can't do this if
72 // the type is complex. For example if the type is "int*", we *must* print
73 // "int * const", printing "const int *" is different. Only do this when the
74 // type expands to a simple string.
75 bool CanPrefixQualifiers = isa<BuiltinType>(T);
76
77 if (!CanPrefixQualifiers && !Quals.empty()) {
Douglas Gregorfee8a3c2009-11-10 00:39:07 +000078 std::string TQS;
79 Quals.getAsStringInternal(TQS, Policy);
80
81 if (!S.empty()) {
82 TQS += ' ';
83 TQS += S;
84 }
85 std::swap(S, TQS);
86 }
87
88 switch (T->getTypeClass()) {
89#define ABSTRACT_TYPE(CLASS, PARENT)
90#define TYPE(CLASS, PARENT) case Type::CLASS: \
91 Print##CLASS(cast<CLASS##Type>(T.getTypePtr()), S); \
92 break;
93#include "clang/AST/TypeNodes.def"
94 }
Chris Lattner58f9e132010-09-05 00:04:01 +000095
96 // If we're adding the qualifiers as a prefix, do it now.
97 if (CanPrefixQualifiers && !Quals.empty()) {
98 std::string TQS;
99 Quals.getAsStringInternal(TQS, Policy);
100
101 if (!S.empty()) {
102 TQS += ' ';
103 TQS += S;
104 }
105 std::swap(S, TQS);
106 }
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000107}
108
109void TypePrinter::PrintBuiltin(const BuiltinType *T, std::string &S) {
110 if (S.empty()) {
111 S = T->getName(Policy.LangOpts);
112 } else {
113 // Prefix the basic type, e.g. 'int X'.
Chris Lattner59742de2010-09-04 23:43:40 +0000114 S = ' ' + S;
115 S = T->getName(Policy.LangOpts) + S;
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000116 }
117}
118
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000119void TypePrinter::PrintComplex(const ComplexType *T, std::string &S) {
120 Print(T->getElementType(), S);
121 S = "_Complex " + S;
122}
123
124void TypePrinter::PrintPointer(const PointerType *T, std::string &S) {
125 S = '*' + S;
126
127 // Handle things like 'int (*A)[4];' correctly.
128 // FIXME: this should include vectors, but vectors use attributes I guess.
129 if (isa<ArrayType>(T->getPointeeType()))
130 S = '(' + S + ')';
131
132 Print(T->getPointeeType(), S);
133}
134
135void TypePrinter::PrintBlockPointer(const BlockPointerType *T, std::string &S) {
136 S = '^' + S;
137 Print(T->getPointeeType(), S);
138}
139
140void TypePrinter::PrintLValueReference(const LValueReferenceType *T,
141 std::string &S) {
142 S = '&' + S;
143
144 // Handle things like 'int (&A)[4];' correctly.
145 // FIXME: this should include vectors, but vectors use attributes I guess.
146 if (isa<ArrayType>(T->getPointeeTypeAsWritten()))
147 S = '(' + S + ')';
148
149 Print(T->getPointeeTypeAsWritten(), S);
150}
151
152void TypePrinter::PrintRValueReference(const RValueReferenceType *T,
153 std::string &S) {
154 S = "&&" + S;
155
156 // Handle things like 'int (&&A)[4];' correctly.
157 // FIXME: this should include vectors, but vectors use attributes I guess.
158 if (isa<ArrayType>(T->getPointeeTypeAsWritten()))
159 S = '(' + S + ')';
160
161 Print(T->getPointeeTypeAsWritten(), S);
162}
163
164void TypePrinter::PrintMemberPointer(const MemberPointerType *T,
165 std::string &S) {
166 std::string C;
167 Print(QualType(T->getClass(), 0), C);
168 C += "::*";
169 S = C + S;
170
171 // Handle things like 'int (Cls::*A)[4];' correctly.
172 // FIXME: this should include vectors, but vectors use attributes I guess.
173 if (isa<ArrayType>(T->getPointeeType()))
174 S = '(' + S + ')';
175
176 Print(T->getPointeeType(), S);
177}
178
179void TypePrinter::PrintConstantArray(const ConstantArrayType *T,
180 std::string &S) {
181 S += '[';
182 S += llvm::utostr(T->getSize().getZExtValue());
183 S += ']';
184
185 Print(T->getElementType(), S);
186}
187
188void TypePrinter::PrintIncompleteArray(const IncompleteArrayType *T,
189 std::string &S) {
190 S += "[]";
191 Print(T->getElementType(), S);
192}
193
194void TypePrinter::PrintVariableArray(const VariableArrayType *T,
195 std::string &S) {
196 S += '[';
197
198 if (T->getIndexTypeQualifiers().hasQualifiers()) {
199 AppendTypeQualList(S, T->getIndexTypeCVRQualifiers());
200 S += ' ';
201 }
202
203 if (T->getSizeModifier() == VariableArrayType::Static)
204 S += "static";
205 else if (T->getSizeModifier() == VariableArrayType::Star)
206 S += '*';
207
208 if (T->getSizeExpr()) {
209 std::string SStr;
210 llvm::raw_string_ostream s(SStr);
211 T->getSizeExpr()->printPretty(s, 0, Policy);
212 S += s.str();
213 }
214 S += ']';
215
216 Print(T->getElementType(), S);
217}
218
219void TypePrinter::PrintDependentSizedArray(const DependentSizedArrayType *T,
220 std::string &S) {
221 S += '[';
222
223 if (T->getSizeExpr()) {
224 std::string SStr;
225 llvm::raw_string_ostream s(SStr);
226 T->getSizeExpr()->printPretty(s, 0, Policy);
227 S += s.str();
228 }
229 S += ']';
230
231 Print(T->getElementType(), S);
232}
233
234void TypePrinter::PrintDependentSizedExtVector(
235 const DependentSizedExtVectorType *T,
236 std::string &S) {
237 Print(T->getElementType(), S);
238
239 S += " __attribute__((ext_vector_type(";
240 if (T->getSizeExpr()) {
241 std::string SStr;
242 llvm::raw_string_ostream s(SStr);
243 T->getSizeExpr()->printPretty(s, 0, Policy);
244 S += s.str();
245 }
246 S += ")))";
247}
248
249void TypePrinter::PrintVector(const VectorType *T, std::string &S) {
Chris Lattner788b0fd2010-06-23 06:00:24 +0000250 if (T->getAltiVecSpecific() != VectorType::NotAltiVec) {
251 if (T->getAltiVecSpecific() == VectorType::Pixel)
John Thompson82287d12010-02-05 00:12:22 +0000252 S = "__vector __pixel " + S;
253 else {
254 Print(T->getElementType(), S);
Chris Lattner788b0fd2010-06-23 06:00:24 +0000255 S = ((T->getAltiVecSpecific() == VectorType::Bool)
256 ? "__vector __bool " : "__vector ") + S;
John Thompson82287d12010-02-05 00:12:22 +0000257 }
258 } else {
259 // FIXME: We prefer to print the size directly here, but have no way
260 // to get the size of the type.
261 Print(T->getElementType(), S);
262 std::string V = "__attribute__((__vector_size__(";
263 V += llvm::utostr_32(T->getNumElements()); // convert back to bytes.
264 std::string ET;
265 Print(T->getElementType(), ET);
266 V += " * sizeof(" + ET + ")))) ";
267 S = V + S;
268 }
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000269}
270
271void TypePrinter::PrintExtVector(const ExtVectorType *T, std::string &S) {
272 S += " __attribute__((ext_vector_type(";
273 S += llvm::utostr_32(T->getNumElements());
274 S += ")))";
275 Print(T->getElementType(), S);
276}
277
278void TypePrinter::PrintFunctionProto(const FunctionProtoType *T,
279 std::string &S) {
280 // If needed for precedence reasons, wrap the inner part in grouping parens.
281 if (!S.empty())
282 S = "(" + S + ")";
283
284 S += "(";
285 std::string Tmp;
286 PrintingPolicy ParamPolicy(Policy);
287 ParamPolicy.SuppressSpecifiers = false;
288 for (unsigned i = 0, e = T->getNumArgs(); i != e; ++i) {
289 if (i) S += ", ";
290 Print(T->getArgType(i), Tmp);
291 S += Tmp;
292 Tmp.clear();
293 }
294
295 if (T->isVariadic()) {
296 if (T->getNumArgs())
297 S += ", ";
298 S += "...";
299 } else if (T->getNumArgs() == 0 && !Policy.LangOpts.CPlusPlus) {
300 // Do not emit int() if we have a proto, emit 'int(void)'.
301 S += "void";
302 }
303
304 S += ")";
Douglas Gregor0ae7b3f2009-12-08 17:45:32 +0000305
Rafael Espindola264ba482010-03-30 20:24:48 +0000306 FunctionType::ExtInfo Info = T->getExtInfo();
307 switch(Info.getCC()) {
John McCallf82b4e82010-02-04 05:44:44 +0000308 case CC_Default:
309 default: break;
310 case CC_C:
311 S += " __attribute__((cdecl))";
312 break;
313 case CC_X86StdCall:
314 S += " __attribute__((stdcall))";
315 break;
316 case CC_X86FastCall:
317 S += " __attribute__((fastcall))";
318 break;
Douglas Gregorf813a2c2010-05-18 16:57:00 +0000319 case CC_X86ThisCall:
320 S += " __attribute__((thiscall))";
321 break;
Dawn Perchik52fc3142010-09-03 01:29:35 +0000322 case CC_X86Pascal:
323 S += " __attribute__((pascal))";
324 break;
John McCallf82b4e82010-02-04 05:44:44 +0000325 }
Rafael Espindola264ba482010-03-30 20:24:48 +0000326 if (Info.getNoReturn())
Douglas Gregor48026d22010-01-11 18:40:55 +0000327 S += " __attribute__((noreturn))";
Rafael Espindola425ef722010-03-30 22:15:11 +0000328 if (Info.getRegParm())
329 S += " __attribute__((regparm (" +
330 llvm::utostr_32(Info.getRegParm()) + ")))";
Douglas Gregor48026d22010-01-11 18:40:55 +0000331
Douglas Gregor0ae7b3f2009-12-08 17:45:32 +0000332 if (T->hasExceptionSpec()) {
333 S += " throw(";
334 if (T->hasAnyExceptionSpec())
335 S += "...";
336 else
337 for (unsigned I = 0, N = T->getNumExceptions(); I != N; ++I) {
338 if (I)
339 S += ", ";
340
341 std::string ExceptionType;
342 Print(T->getExceptionType(I), ExceptionType);
343 S += ExceptionType;
344 }
345 S += ")";
346 }
347
Douglas Gregor48026d22010-01-11 18:40:55 +0000348 AppendTypeQualList(S, T->getTypeQuals());
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000349
Douglas Gregor48026d22010-01-11 18:40:55 +0000350 Print(T->getResultType(), S);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000351}
352
353void TypePrinter::PrintFunctionNoProto(const FunctionNoProtoType *T,
354 std::string &S) {
355 // If needed for precedence reasons, wrap the inner part in grouping parens.
356 if (!S.empty())
357 S = "(" + S + ")";
358
359 S += "()";
360 if (T->getNoReturnAttr())
361 S += " __attribute__((noreturn))";
362 Print(T->getResultType(), S);
363}
364
John McCall3cb0ebd2010-03-10 03:28:59 +0000365static void PrintTypeSpec(const NamedDecl *D, std::string &S) {
366 IdentifierInfo *II = D->getIdentifier();
John McCalled976492009-12-04 22:46:56 +0000367 if (S.empty())
368 S = II->getName().str();
369 else
370 S = II->getName().str() + ' ' + S;
371}
372
John McCall3cb0ebd2010-03-10 03:28:59 +0000373void TypePrinter::PrintUnresolvedUsing(const UnresolvedUsingType *T,
374 std::string &S) {
375 PrintTypeSpec(T->getDecl(), S);
376}
377
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000378void TypePrinter::PrintTypedef(const TypedefType *T, std::string &S) {
John McCall3cb0ebd2010-03-10 03:28:59 +0000379 PrintTypeSpec(T->getDecl(), S);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000380}
381
382void TypePrinter::PrintTypeOfExpr(const TypeOfExprType *T, std::string &S) {
383 if (!S.empty()) // Prefix the basic type, e.g. 'typeof(e) X'.
384 S = ' ' + S;
385 std::string Str;
386 llvm::raw_string_ostream s(Str);
387 T->getUnderlyingExpr()->printPretty(s, 0, Policy);
388 S = "typeof " + s.str() + S;
389}
390
391void TypePrinter::PrintTypeOf(const TypeOfType *T, std::string &S) {
392 if (!S.empty()) // Prefix the basic type, e.g. 'typeof(t) X'.
393 S = ' ' + S;
394 std::string Tmp;
395 Print(T->getUnderlyingType(), Tmp);
396 S = "typeof(" + Tmp + ")" + S;
397}
398
399void TypePrinter::PrintDecltype(const DecltypeType *T, std::string &S) {
400 if (!S.empty()) // Prefix the basic type, e.g. 'decltype(t) X'.
401 S = ' ' + S;
402 std::string Str;
403 llvm::raw_string_ostream s(Str);
404 T->getUnderlyingExpr()->printPretty(s, 0, Policy);
405 S = "decltype(" + s.str() + ")" + S;
406}
407
John McCall7c2342d2010-03-10 11:27:22 +0000408/// Appends the given scope to the end of a string.
409void TypePrinter::AppendScope(DeclContext *DC, std::string &Buffer) {
410 if (DC->isTranslationUnit()) return;
411 AppendScope(DC->getParent(), Buffer);
412
413 unsigned OldSize = Buffer.size();
414
415 if (NamespaceDecl *NS = dyn_cast<NamespaceDecl>(DC)) {
416 if (NS->getIdentifier())
417 Buffer += NS->getNameAsString();
418 else
419 Buffer += "<anonymous>";
420 } else if (ClassTemplateSpecializationDecl *Spec
421 = dyn_cast<ClassTemplateSpecializationDecl>(DC)) {
422 const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs();
423 std::string TemplateArgsStr
424 = TemplateSpecializationType::PrintTemplateArgumentList(
425 TemplateArgs.getFlatArgumentList(),
426 TemplateArgs.flat_size(),
427 Policy);
428 Buffer += Spec->getIdentifier()->getName();
429 Buffer += TemplateArgsStr;
430 } else if (TagDecl *Tag = dyn_cast<TagDecl>(DC)) {
431 if (TypedefDecl *Typedef = Tag->getTypedefForAnonDecl())
432 Buffer += Typedef->getIdentifier()->getName();
433 else if (Tag->getIdentifier())
434 Buffer += Tag->getIdentifier()->getName();
435 }
436
437 if (Buffer.size() != OldSize)
438 Buffer += "::";
439}
440
John McCall3cb0ebd2010-03-10 03:28:59 +0000441void TypePrinter::PrintTag(TagDecl *D, std::string &InnerString) {
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000442 if (Policy.SuppressTag)
443 return;
John McCall7c2342d2010-03-10 11:27:22 +0000444
445 std::string Buffer;
John McCall73061d02010-03-19 07:56:44 +0000446 bool HasKindDecoration = false;
John McCall7c2342d2010-03-10 11:27:22 +0000447
448 // We don't print tags unless this is an elaborated type.
449 // In C, we just assume every RecordType is an elaborated type.
450 if (!Policy.LangOpts.CPlusPlus && !D->getTypedefForAnonDecl()) {
John McCall73061d02010-03-19 07:56:44 +0000451 HasKindDecoration = true;
John McCall7c2342d2010-03-10 11:27:22 +0000452 Buffer += D->getKindName();
453 Buffer += ' ';
454 }
455
Chris Lattnerc7acc662010-08-28 16:26:18 +0000456 // Compute the full nested-name-specifier for this type.
457 // In C, this will always be empty except when the type
458 // being printed is anonymous within other Record.
John McCall7c2342d2010-03-10 11:27:22 +0000459 if (!Policy.SuppressScope)
John McCall7c2342d2010-03-10 11:27:22 +0000460 AppendScope(D->getDeclContext(), Buffer);
461
John McCall3cb0ebd2010-03-10 03:28:59 +0000462 if (const IdentifierInfo *II = D->getIdentifier())
John McCall73061d02010-03-19 07:56:44 +0000463 Buffer += II->getNameStart();
John McCall3cb0ebd2010-03-10 03:28:59 +0000464 else if (TypedefDecl *Typedef = D->getTypedefForAnonDecl()) {
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000465 assert(Typedef->getIdentifier() && "Typedef without identifier?");
John McCall73061d02010-03-19 07:56:44 +0000466 Buffer += Typedef->getIdentifier()->getNameStart();
467 } else {
468 // Make an unambiguous representation for anonymous types, e.g.
469 // <anonymous enum at /usr/include/string.h:120:9>
470 llvm::raw_string_ostream OS(Buffer);
471 OS << "<anonymous";
472
Douglas Gregor84139d62010-04-05 21:25:31 +0000473 if (Policy.AnonymousTagLocations) {
474 // Suppress the redundant tag keyword if we just printed one.
475 // We don't have to worry about ElaboratedTypes here because you can't
476 // refer to an anonymous type with one.
477 if (!HasKindDecoration)
478 OS << " " << D->getKindName();
John McCall73061d02010-03-19 07:56:44 +0000479
Douglas Gregor16834e82010-05-28 21:47:04 +0000480 if (D->getLocation().isValid()) {
481 PresumedLoc PLoc = D->getASTContext().getSourceManager().getPresumedLoc(
482 D->getLocation());
483 OS << " at " << PLoc.getFilename()
484 << ':' << PLoc.getLine()
485 << ':' << PLoc.getColumn();
486 }
Douglas Gregor84139d62010-04-05 21:25:31 +0000487 }
488
489 OS << '>';
John McCall73061d02010-03-19 07:56:44 +0000490 }
John McCall7c2342d2010-03-10 11:27:22 +0000491
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000492 // If this is a class template specialization, print the template
493 // arguments.
494 if (ClassTemplateSpecializationDecl *Spec
John McCall7c2342d2010-03-10 11:27:22 +0000495 = dyn_cast<ClassTemplateSpecializationDecl>(D)) {
John McCall3cb0ebd2010-03-10 03:28:59 +0000496 const TemplateArgument *Args;
497 unsigned NumArgs;
498 if (TypeSourceInfo *TAW = Spec->getTypeAsWritten()) {
499 const TemplateSpecializationType *TST =
500 cast<TemplateSpecializationType>(TAW->getType());
501 Args = TST->getArgs();
502 NumArgs = TST->getNumArgs();
503 } else {
504 const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs();
505 Args = TemplateArgs.getFlatArgumentList();
506 NumArgs = TemplateArgs.flat_size();
507 }
John McCall7c2342d2010-03-10 11:27:22 +0000508 Buffer += TemplateSpecializationType::PrintTemplateArgumentList(Args,
509 NumArgs,
510 Policy);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000511 }
John McCall7c2342d2010-03-10 11:27:22 +0000512
513 if (!InnerString.empty()) {
514 Buffer += ' ';
515 Buffer += InnerString;
516 }
517
518 std::swap(Buffer, InnerString);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000519}
520
521void TypePrinter::PrintRecord(const RecordType *T, std::string &S) {
John McCall3cb0ebd2010-03-10 03:28:59 +0000522 PrintTag(T->getDecl(), S);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000523}
524
525void TypePrinter::PrintEnum(const EnumType *T, std::string &S) {
John McCall3cb0ebd2010-03-10 03:28:59 +0000526 PrintTag(T->getDecl(), S);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000527}
528
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000529void TypePrinter::PrintTemplateTypeParm(const TemplateTypeParmType *T,
530 std::string &S) {
531 if (!S.empty()) // Prefix the basic type, e.g. 'parmname X'.
532 S = ' ' + S;
Douglas Gregorefed5c82010-06-16 15:23:05 +0000533
534 if (!T->getName())
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000535 S = "type-parameter-" + llvm::utostr_32(T->getDepth()) + '-' +
536 llvm::utostr_32(T->getIndex()) + S;
Douglas Gregorefed5c82010-06-16 15:23:05 +0000537 else
538 S = T->getName()->getName().str() + S;
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000539}
540
541void TypePrinter::PrintSubstTemplateTypeParm(const SubstTemplateTypeParmType *T,
542 std::string &S) {
543 Print(T->getReplacementType(), S);
544}
545
546void TypePrinter::PrintTemplateSpecialization(
547 const TemplateSpecializationType *T,
548 std::string &S) {
549 std::string SpecString;
550
551 {
552 llvm::raw_string_ostream OS(SpecString);
553 T->getTemplateName().print(OS, Policy);
554 }
555
556 SpecString += TemplateSpecializationType::PrintTemplateArgumentList(
557 T->getArgs(),
558 T->getNumArgs(),
559 Policy);
560 if (S.empty())
561 S.swap(SpecString);
562 else
563 S = SpecString + ' ' + S;
564}
565
John McCall3cb0ebd2010-03-10 03:28:59 +0000566void TypePrinter::PrintInjectedClassName(const InjectedClassNameType *T,
567 std::string &S) {
John McCall31f17ec2010-04-27 00:57:59 +0000568 PrintTemplateSpecialization(T->getInjectedTST(), S);
John McCall3cb0ebd2010-03-10 03:28:59 +0000569}
570
Abramo Bagnara465d41b2010-05-11 21:36:43 +0000571void TypePrinter::PrintElaborated(const ElaboratedType *T, std::string &S) {
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000572 std::string MyString;
573
574 {
575 llvm::raw_string_ostream OS(MyString);
Abramo Bagnara465d41b2010-05-11 21:36:43 +0000576 OS << TypeWithKeyword::getKeywordName(T->getKeyword());
577 if (T->getKeyword() != ETK_None)
578 OS << " ";
579 NestedNameSpecifier* Qualifier = T->getQualifier();
580 if (Qualifier)
581 Qualifier->print(OS, Policy);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000582 }
583
584 std::string TypeStr;
585 PrintingPolicy InnerPolicy(Policy);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000586 InnerPolicy.SuppressScope = true;
587 TypePrinter(InnerPolicy).Print(T->getNamedType(), TypeStr);
588
589 MyString += TypeStr;
590 if (S.empty())
591 S.swap(MyString);
592 else
593 S = MyString + ' ' + S;
594}
595
Douglas Gregor4714c122010-03-31 17:34:00 +0000596void TypePrinter::PrintDependentName(const DependentNameType *T, std::string &S) {
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000597 std::string MyString;
598
599 {
600 llvm::raw_string_ostream OS(MyString);
Abramo Bagnara465d41b2010-05-11 21:36:43 +0000601 OS << TypeWithKeyword::getKeywordName(T->getKeyword());
602 if (T->getKeyword() != ETK_None)
603 OS << " ";
Douglas Gregor4a2023f2010-03-31 20:19:30 +0000604
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000605 T->getQualifier()->print(OS, Policy);
606
John McCall33500952010-06-11 00:33:02 +0000607 OS << T->getIdentifier()->getName();
608 }
609
610 if (S.empty())
611 S.swap(MyString);
612 else
613 S = MyString + ' ' + S;
614}
615
616void TypePrinter::PrintDependentTemplateSpecialization(
617 const DependentTemplateSpecializationType *T, std::string &S) {
618 std::string MyString;
619 {
620 llvm::raw_string_ostream OS(MyString);
621
622 OS << TypeWithKeyword::getKeywordName(T->getKeyword());
623 if (T->getKeyword() != ETK_None)
624 OS << " ";
625
626 T->getQualifier()->print(OS, Policy);
627 OS << T->getIdentifier()->getName();
628 OS << TemplateSpecializationType::PrintTemplateArgumentList(
629 T->getArgs(),
630 T->getNumArgs(),
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000631 Policy);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000632 }
633
634 if (S.empty())
635 S.swap(MyString);
636 else
637 S = MyString + ' ' + S;
638}
639
640void TypePrinter::PrintObjCInterface(const ObjCInterfaceType *T,
641 std::string &S) {
642 if (!S.empty()) // Prefix the basic type, e.g. 'typedefname X'.
643 S = ' ' + S;
John McCallc12c5bb2010-05-15 11:32:37 +0000644
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000645 std::string ObjCQIString = T->getDecl()->getNameAsString();
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000646 S = ObjCQIString + S;
647}
648
John McCallc12c5bb2010-05-15 11:32:37 +0000649void TypePrinter::PrintObjCObject(const ObjCObjectType *T,
650 std::string &S) {
651 if (T->qual_empty())
652 return Print(T->getBaseType(), S);
653
654 std::string tmp;
655 Print(T->getBaseType(), tmp);
656 tmp += '<';
657 bool isFirst = true;
658 for (ObjCObjectType::qual_iterator
659 I = T->qual_begin(), E = T->qual_end(); I != E; ++I) {
660 if (isFirst)
661 isFirst = false;
662 else
663 tmp += ',';
664 tmp += (*I)->getNameAsString();
665 }
666 tmp += '>';
667
668 if (!S.empty()) {
669 tmp += ' ';
670 tmp += S;
671 }
672 std::swap(tmp, S);
673}
674
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000675void TypePrinter::PrintObjCObjectPointer(const ObjCObjectPointerType *T,
676 std::string &S) {
677 std::string ObjCQIString;
678
679 if (T->isObjCIdType() || T->isObjCQualifiedIdType())
680 ObjCQIString = "id";
681 else if (T->isObjCClassType() || T->isObjCQualifiedClassType())
682 ObjCQIString = "Class";
Fariborz Jahanian13dcd002009-11-21 19:53:08 +0000683 else if (T->isObjCSelType())
684 ObjCQIString = "SEL";
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000685 else
686 ObjCQIString = T->getInterfaceDecl()->getNameAsString();
687
688 if (!T->qual_empty()) {
689 ObjCQIString += '<';
690 for (ObjCObjectPointerType::qual_iterator I = T->qual_begin(),
691 E = T->qual_end();
692 I != E; ++I) {
693 ObjCQIString += (*I)->getNameAsString();
694 if (I+1 != E)
695 ObjCQIString += ',';
696 }
697 ObjCQIString += '>';
698 }
699
Douglas Gregora4923eb2009-11-16 21:35:15 +0000700 T->getPointeeType().getLocalQualifiers().getAsStringInternal(ObjCQIString,
701 Policy);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000702
703 if (!T->isObjCIdType() && !T->isObjCQualifiedIdType())
704 ObjCQIString += " *"; // Don't forget the implicit pointer.
705 else if (!S.empty()) // Prefix the basic type, e.g. 'typedefname X'.
706 S = ' ' + S;
707
708 S = ObjCQIString + S;
709}
710
711static void PrintTemplateArgument(std::string &Buffer,
712 const TemplateArgument &Arg,
713 const PrintingPolicy &Policy) {
714 switch (Arg.getKind()) {
715 case TemplateArgument::Null:
716 assert(false && "Null template argument");
717 break;
718
719 case TemplateArgument::Type:
720 Arg.getAsType().getAsStringInternal(Buffer, Policy);
721 break;
722
723 case TemplateArgument::Declaration:
724 Buffer = cast<NamedDecl>(Arg.getAsDecl())->getNameAsString();
725 break;
726
Douglas Gregor788cd062009-11-11 01:00:40 +0000727 case TemplateArgument::Template: {
728 llvm::raw_string_ostream s(Buffer);
729 Arg.getAsTemplate().print(s, Policy);
Douglas Gregorfb898e12009-11-12 16:20:59 +0000730 break;
Douglas Gregor788cd062009-11-11 01:00:40 +0000731 }
732
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000733 case TemplateArgument::Integral:
734 Buffer = Arg.getAsIntegral()->toString(10, true);
735 break;
736
737 case TemplateArgument::Expression: {
738 llvm::raw_string_ostream s(Buffer);
739 Arg.getAsExpr()->printPretty(s, 0, Policy);
740 break;
741 }
742
743 case TemplateArgument::Pack:
744 assert(0 && "FIXME: Implement!");
745 break;
746 }
747}
748
John McCalld5532b62009-11-23 01:53:49 +0000749std::string TemplateSpecializationType::
750 PrintTemplateArgumentList(const TemplateArgumentListInfo &Args,
751 const PrintingPolicy &Policy) {
752 return PrintTemplateArgumentList(Args.getArgumentArray(),
753 Args.size(),
754 Policy);
755}
756
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000757std::string
758TemplateSpecializationType::PrintTemplateArgumentList(
759 const TemplateArgument *Args,
760 unsigned NumArgs,
761 const PrintingPolicy &Policy) {
762 std::string SpecString;
763 SpecString += '<';
764 for (unsigned Arg = 0; Arg < NumArgs; ++Arg) {
765 if (Arg)
766 SpecString += ", ";
767
768 // Print the argument into a string.
769 std::string ArgString;
770 PrintTemplateArgument(ArgString, Args[Arg], Policy);
771
772 // If this is the first argument and its string representation
773 // begins with the global scope specifier ('::foo'), add a space
774 // to avoid printing the diagraph '<:'.
775 if (!Arg && !ArgString.empty() && ArgString[0] == ':')
776 SpecString += ' ';
777
778 SpecString += ArgString;
779 }
780
781 // If the last character of our string is '>', add another space to
782 // keep the two '>''s separate tokens. We don't *have* to do this in
783 // C++0x, but it's still good hygiene.
784 if (SpecString[SpecString.size() - 1] == '>')
785 SpecString += ' ';
786
787 SpecString += '>';
788
789 return SpecString;
790}
791
792// Sadly, repeat all that with TemplateArgLoc.
793std::string TemplateSpecializationType::
794PrintTemplateArgumentList(const TemplateArgumentLoc *Args, unsigned NumArgs,
795 const PrintingPolicy &Policy) {
796 std::string SpecString;
797 SpecString += '<';
798 for (unsigned Arg = 0; Arg < NumArgs; ++Arg) {
799 if (Arg)
800 SpecString += ", ";
801
802 // Print the argument into a string.
803 std::string ArgString;
804 PrintTemplateArgument(ArgString, Args[Arg].getArgument(), Policy);
805
806 // If this is the first argument and its string representation
807 // begins with the global scope specifier ('::foo'), add a space
808 // to avoid printing the diagraph '<:'.
809 if (!Arg && !ArgString.empty() && ArgString[0] == ':')
810 SpecString += ' ';
811
812 SpecString += ArgString;
813 }
814
815 // If the last character of our string is '>', add another space to
816 // keep the two '>''s separate tokens. We don't *have* to do this in
817 // C++0x, but it's still good hygiene.
818 if (SpecString[SpecString.size() - 1] == '>')
819 SpecString += ' ';
820
821 SpecString += '>';
822
823 return SpecString;
824}
825
826void QualType::dump(const char *msg) const {
827 std::string R = "identifier";
828 LangOptions LO;
829 getAsStringInternal(R, PrintingPolicy(LO));
830 if (msg)
Daniel Dunbare7cb7e42009-12-03 09:14:02 +0000831 llvm::errs() << msg << ": ";
832 llvm::errs() << R << "\n";
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000833}
834void QualType::dump() const {
835 dump("");
836}
837
838void Type::dump() const {
839 QualType(this, 0).dump();
840}
841
842std::string Qualifiers::getAsString() const {
843 LangOptions LO;
844 return getAsString(PrintingPolicy(LO));
845}
846
847// Appends qualifiers to the given string, separated by spaces. Will
848// prefix a space if the string is non-empty. Will not append a final
849// space.
850void Qualifiers::getAsStringInternal(std::string &S,
851 const PrintingPolicy&) const {
852 AppendTypeQualList(S, getCVRQualifiers());
853 if (unsigned AddressSpace = getAddressSpace()) {
854 if (!S.empty()) S += ' ';
855 S += "__attribute__((address_space(";
856 S += llvm::utostr_32(AddressSpace);
857 S += ")))";
858 }
859 if (Qualifiers::GC GCAttrType = getObjCGCAttr()) {
860 if (!S.empty()) S += ' ';
861 S += "__attribute__((objc_gc(";
862 if (GCAttrType == Qualifiers::Weak)
863 S += "weak";
864 else
865 S += "strong";
866 S += ")))";
867 }
868}
869
870std::string QualType::getAsString() const {
871 std::string S;
872 LangOptions LO;
873 getAsStringInternal(S, PrintingPolicy(LO));
874 return S;
875}
876
877void QualType::getAsStringInternal(std::string &S,
878 const PrintingPolicy &Policy) const {
879 TypePrinter Printer(Policy);
880 Printer.Print(*this, S);
881}