blob: 5dfad6c900564e9e70c6d88417493d76a42b1bef [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.
Chris Lattner66cf2d12010-09-05 00:07:29 +000075 bool CanPrefixQualifiers =
Chris Lattner219b9e42010-09-05 00:22:25 +000076 isa<BuiltinType>(T) || isa<TypedefType>(T) || isa<TagType>(T) ||
Chris Lattner78643b02010-09-05 00:36:44 +000077 isa<ComplexType>(T) || isa<TemplateSpecializationType>(T) ||
78 isa<ObjCObjectType>(T) || isa<ObjCInterfaceType>(T) ||
79 T->isObjCIdType() || T->isObjCQualifiedIdType();
Chris Lattner58f9e132010-09-05 00:04:01 +000080
81 if (!CanPrefixQualifiers && !Quals.empty()) {
Douglas Gregorfee8a3c2009-11-10 00:39:07 +000082 std::string TQS;
83 Quals.getAsStringInternal(TQS, Policy);
84
85 if (!S.empty()) {
86 TQS += ' ';
87 TQS += S;
88 }
89 std::swap(S, TQS);
90 }
91
92 switch (T->getTypeClass()) {
93#define ABSTRACT_TYPE(CLASS, PARENT)
94#define TYPE(CLASS, PARENT) case Type::CLASS: \
95 Print##CLASS(cast<CLASS##Type>(T.getTypePtr()), S); \
96 break;
97#include "clang/AST/TypeNodes.def"
98 }
Chris Lattner58f9e132010-09-05 00:04:01 +000099
100 // If we're adding the qualifiers as a prefix, do it now.
101 if (CanPrefixQualifiers && !Quals.empty()) {
102 std::string TQS;
103 Quals.getAsStringInternal(TQS, Policy);
104
105 if (!S.empty()) {
106 TQS += ' ';
107 TQS += S;
108 }
109 std::swap(S, TQS);
110 }
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000111}
112
113void TypePrinter::PrintBuiltin(const BuiltinType *T, std::string &S) {
114 if (S.empty()) {
115 S = T->getName(Policy.LangOpts);
116 } else {
117 // Prefix the basic type, e.g. 'int X'.
Chris Lattner59742de2010-09-04 23:43:40 +0000118 S = ' ' + S;
119 S = T->getName(Policy.LangOpts) + S;
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000120 }
121}
122
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000123void TypePrinter::PrintComplex(const ComplexType *T, std::string &S) {
124 Print(T->getElementType(), S);
125 S = "_Complex " + S;
126}
127
128void TypePrinter::PrintPointer(const PointerType *T, std::string &S) {
129 S = '*' + S;
130
131 // Handle things like 'int (*A)[4];' correctly.
132 // FIXME: this should include vectors, but vectors use attributes I guess.
133 if (isa<ArrayType>(T->getPointeeType()))
134 S = '(' + S + ')';
135
136 Print(T->getPointeeType(), S);
137}
138
139void TypePrinter::PrintBlockPointer(const BlockPointerType *T, std::string &S) {
140 S = '^' + S;
141 Print(T->getPointeeType(), S);
142}
143
144void TypePrinter::PrintLValueReference(const LValueReferenceType *T,
145 std::string &S) {
146 S = '&' + S;
147
148 // Handle things like 'int (&A)[4];' correctly.
149 // FIXME: this should include vectors, but vectors use attributes I guess.
150 if (isa<ArrayType>(T->getPointeeTypeAsWritten()))
151 S = '(' + S + ')';
152
153 Print(T->getPointeeTypeAsWritten(), S);
154}
155
156void TypePrinter::PrintRValueReference(const RValueReferenceType *T,
157 std::string &S) {
158 S = "&&" + S;
159
160 // Handle things like 'int (&&A)[4];' correctly.
161 // FIXME: this should include vectors, but vectors use attributes I guess.
162 if (isa<ArrayType>(T->getPointeeTypeAsWritten()))
163 S = '(' + S + ')';
164
165 Print(T->getPointeeTypeAsWritten(), S);
166}
167
168void TypePrinter::PrintMemberPointer(const MemberPointerType *T,
169 std::string &S) {
170 std::string C;
171 Print(QualType(T->getClass(), 0), C);
172 C += "::*";
173 S = C + S;
174
175 // Handle things like 'int (Cls::*A)[4];' correctly.
176 // FIXME: this should include vectors, but vectors use attributes I guess.
177 if (isa<ArrayType>(T->getPointeeType()))
178 S = '(' + S + ')';
179
180 Print(T->getPointeeType(), S);
181}
182
183void TypePrinter::PrintConstantArray(const ConstantArrayType *T,
184 std::string &S) {
185 S += '[';
186 S += llvm::utostr(T->getSize().getZExtValue());
187 S += ']';
188
189 Print(T->getElementType(), S);
190}
191
192void TypePrinter::PrintIncompleteArray(const IncompleteArrayType *T,
193 std::string &S) {
194 S += "[]";
195 Print(T->getElementType(), S);
196}
197
198void TypePrinter::PrintVariableArray(const VariableArrayType *T,
199 std::string &S) {
200 S += '[';
201
202 if (T->getIndexTypeQualifiers().hasQualifiers()) {
203 AppendTypeQualList(S, T->getIndexTypeCVRQualifiers());
204 S += ' ';
205 }
206
207 if (T->getSizeModifier() == VariableArrayType::Static)
208 S += "static";
209 else if (T->getSizeModifier() == VariableArrayType::Star)
210 S += '*';
211
212 if (T->getSizeExpr()) {
213 std::string SStr;
214 llvm::raw_string_ostream s(SStr);
215 T->getSizeExpr()->printPretty(s, 0, Policy);
216 S += s.str();
217 }
218 S += ']';
219
220 Print(T->getElementType(), S);
221}
222
223void TypePrinter::PrintDependentSizedArray(const DependentSizedArrayType *T,
224 std::string &S) {
225 S += '[';
226
227 if (T->getSizeExpr()) {
228 std::string SStr;
229 llvm::raw_string_ostream s(SStr);
230 T->getSizeExpr()->printPretty(s, 0, Policy);
231 S += s.str();
232 }
233 S += ']';
234
235 Print(T->getElementType(), S);
236}
237
238void TypePrinter::PrintDependentSizedExtVector(
239 const DependentSizedExtVectorType *T,
240 std::string &S) {
241 Print(T->getElementType(), S);
242
243 S += " __attribute__((ext_vector_type(";
244 if (T->getSizeExpr()) {
245 std::string SStr;
246 llvm::raw_string_ostream s(SStr);
247 T->getSizeExpr()->printPretty(s, 0, Policy);
248 S += s.str();
249 }
250 S += ")))";
251}
252
253void TypePrinter::PrintVector(const VectorType *T, std::string &S) {
Bob Wilsonec33cbe2010-11-16 00:32:26 +0000254 switch (T->getVectorKind()) {
255 case VectorType::AltiVecPixel:
256 S = "__vector __pixel " + S;
257 break;
258 case VectorType::AltiVecBool:
259 Print(T->getElementType(), S);
260 S = "__vector __bool " + S;
261 break;
262 case VectorType::AltiVecVector:
263 Print(T->getElementType(), S);
264 S = "__vector " + S;
265 break;
266 case VectorType::NeonVector:
267 Print(T->getElementType(), S);
268 S = ("__attribute__((neon_vector_type(" +
269 llvm::utostr_32(T->getNumElements()) + "))) " + S);
270 break;
271 case VectorType::NeonPolyVector:
272 Print(T->getElementType(), S);
273 S = ("__attribute__((neon_polyvector_type(" +
274 llvm::utostr_32(T->getNumElements()) + "))) " + S);
275 break;
276 case VectorType::GenericVector: {
John Thompson82287d12010-02-05 00:12:22 +0000277 // FIXME: We prefer to print the size directly here, but have no way
278 // to get the size of the type.
279 Print(T->getElementType(), S);
280 std::string V = "__attribute__((__vector_size__(";
281 V += llvm::utostr_32(T->getNumElements()); // convert back to bytes.
282 std::string ET;
283 Print(T->getElementType(), ET);
284 V += " * sizeof(" + ET + ")))) ";
285 S = V + S;
Bob Wilsonec33cbe2010-11-16 00:32:26 +0000286 break;
287 }
John Thompson82287d12010-02-05 00:12:22 +0000288 }
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000289}
290
291void TypePrinter::PrintExtVector(const ExtVectorType *T, std::string &S) {
292 S += " __attribute__((ext_vector_type(";
293 S += llvm::utostr_32(T->getNumElements());
294 S += ")))";
295 Print(T->getElementType(), S);
296}
297
298void TypePrinter::PrintFunctionProto(const FunctionProtoType *T,
299 std::string &S) {
300 // If needed for precedence reasons, wrap the inner part in grouping parens.
301 if (!S.empty())
302 S = "(" + S + ")";
303
304 S += "(";
305 std::string Tmp;
306 PrintingPolicy ParamPolicy(Policy);
307 ParamPolicy.SuppressSpecifiers = false;
308 for (unsigned i = 0, e = T->getNumArgs(); i != e; ++i) {
309 if (i) S += ", ";
310 Print(T->getArgType(i), Tmp);
311 S += Tmp;
312 Tmp.clear();
313 }
314
315 if (T->isVariadic()) {
316 if (T->getNumArgs())
317 S += ", ";
318 S += "...";
319 } else if (T->getNumArgs() == 0 && !Policy.LangOpts.CPlusPlus) {
320 // Do not emit int() if we have a proto, emit 'int(void)'.
321 S += "void";
322 }
323
324 S += ")";
Douglas Gregor0ae7b3f2009-12-08 17:45:32 +0000325
Rafael Espindola264ba482010-03-30 20:24:48 +0000326 FunctionType::ExtInfo Info = T->getExtInfo();
327 switch(Info.getCC()) {
John McCallf82b4e82010-02-04 05:44:44 +0000328 case CC_Default:
329 default: break;
330 case CC_C:
331 S += " __attribute__((cdecl))";
332 break;
333 case CC_X86StdCall:
334 S += " __attribute__((stdcall))";
335 break;
336 case CC_X86FastCall:
337 S += " __attribute__((fastcall))";
338 break;
Douglas Gregorf813a2c2010-05-18 16:57:00 +0000339 case CC_X86ThisCall:
340 S += " __attribute__((thiscall))";
341 break;
Dawn Perchik52fc3142010-09-03 01:29:35 +0000342 case CC_X86Pascal:
343 S += " __attribute__((pascal))";
344 break;
John McCallf82b4e82010-02-04 05:44:44 +0000345 }
Rafael Espindola264ba482010-03-30 20:24:48 +0000346 if (Info.getNoReturn())
Douglas Gregor48026d22010-01-11 18:40:55 +0000347 S += " __attribute__((noreturn))";
Rafael Espindola425ef722010-03-30 22:15:11 +0000348 if (Info.getRegParm())
349 S += " __attribute__((regparm (" +
350 llvm::utostr_32(Info.getRegParm()) + ")))";
Douglas Gregor48026d22010-01-11 18:40:55 +0000351
Douglas Gregor0ae7b3f2009-12-08 17:45:32 +0000352 if (T->hasExceptionSpec()) {
353 S += " throw(";
354 if (T->hasAnyExceptionSpec())
355 S += "...";
356 else
357 for (unsigned I = 0, N = T->getNumExceptions(); I != N; ++I) {
358 if (I)
359 S += ", ";
360
361 std::string ExceptionType;
362 Print(T->getExceptionType(I), ExceptionType);
363 S += ExceptionType;
364 }
365 S += ")";
366 }
367
Douglas Gregor48026d22010-01-11 18:40:55 +0000368 AppendTypeQualList(S, T->getTypeQuals());
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000369
Douglas Gregor48026d22010-01-11 18:40:55 +0000370 Print(T->getResultType(), S);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000371}
372
373void TypePrinter::PrintFunctionNoProto(const FunctionNoProtoType *T,
374 std::string &S) {
375 // If needed for precedence reasons, wrap the inner part in grouping parens.
376 if (!S.empty())
377 S = "(" + S + ")";
378
379 S += "()";
380 if (T->getNoReturnAttr())
381 S += " __attribute__((noreturn))";
382 Print(T->getResultType(), S);
383}
384
John McCall3cb0ebd2010-03-10 03:28:59 +0000385static void PrintTypeSpec(const NamedDecl *D, std::string &S) {
386 IdentifierInfo *II = D->getIdentifier();
John McCalled976492009-12-04 22:46:56 +0000387 if (S.empty())
388 S = II->getName().str();
389 else
390 S = II->getName().str() + ' ' + S;
391}
392
John McCall3cb0ebd2010-03-10 03:28:59 +0000393void TypePrinter::PrintUnresolvedUsing(const UnresolvedUsingType *T,
394 std::string &S) {
395 PrintTypeSpec(T->getDecl(), S);
396}
397
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000398void TypePrinter::PrintTypedef(const TypedefType *T, std::string &S) {
John McCall3cb0ebd2010-03-10 03:28:59 +0000399 PrintTypeSpec(T->getDecl(), S);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000400}
401
402void TypePrinter::PrintTypeOfExpr(const TypeOfExprType *T, std::string &S) {
403 if (!S.empty()) // Prefix the basic type, e.g. 'typeof(e) X'.
404 S = ' ' + S;
405 std::string Str;
406 llvm::raw_string_ostream s(Str);
407 T->getUnderlyingExpr()->printPretty(s, 0, Policy);
408 S = "typeof " + s.str() + S;
409}
410
411void TypePrinter::PrintTypeOf(const TypeOfType *T, std::string &S) {
412 if (!S.empty()) // Prefix the basic type, e.g. 'typeof(t) X'.
413 S = ' ' + S;
414 std::string Tmp;
415 Print(T->getUnderlyingType(), Tmp);
416 S = "typeof(" + Tmp + ")" + S;
417}
418
419void TypePrinter::PrintDecltype(const DecltypeType *T, std::string &S) {
420 if (!S.empty()) // Prefix the basic type, e.g. 'decltype(t) X'.
421 S = ' ' + S;
422 std::string Str;
423 llvm::raw_string_ostream s(Str);
424 T->getUnderlyingExpr()->printPretty(s, 0, Policy);
425 S = "decltype(" + s.str() + ")" + S;
426}
427
John McCall7c2342d2010-03-10 11:27:22 +0000428/// Appends the given scope to the end of a string.
429void TypePrinter::AppendScope(DeclContext *DC, std::string &Buffer) {
430 if (DC->isTranslationUnit()) return;
431 AppendScope(DC->getParent(), Buffer);
432
433 unsigned OldSize = Buffer.size();
434
435 if (NamespaceDecl *NS = dyn_cast<NamespaceDecl>(DC)) {
436 if (NS->getIdentifier())
437 Buffer += NS->getNameAsString();
438 else
439 Buffer += "<anonymous>";
440 } else if (ClassTemplateSpecializationDecl *Spec
441 = dyn_cast<ClassTemplateSpecializationDecl>(DC)) {
442 const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs();
443 std::string TemplateArgsStr
444 = TemplateSpecializationType::PrintTemplateArgumentList(
Douglas Gregor910f8002010-11-07 23:05:16 +0000445 TemplateArgs.data(),
446 TemplateArgs.size(),
John McCall7c2342d2010-03-10 11:27:22 +0000447 Policy);
448 Buffer += Spec->getIdentifier()->getName();
449 Buffer += TemplateArgsStr;
450 } else if (TagDecl *Tag = dyn_cast<TagDecl>(DC)) {
451 if (TypedefDecl *Typedef = Tag->getTypedefForAnonDecl())
452 Buffer += Typedef->getIdentifier()->getName();
453 else if (Tag->getIdentifier())
454 Buffer += Tag->getIdentifier()->getName();
455 }
456
457 if (Buffer.size() != OldSize)
458 Buffer += "::";
459}
460
John McCall3cb0ebd2010-03-10 03:28:59 +0000461void TypePrinter::PrintTag(TagDecl *D, std::string &InnerString) {
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000462 if (Policy.SuppressTag)
463 return;
John McCall7c2342d2010-03-10 11:27:22 +0000464
465 std::string Buffer;
John McCall73061d02010-03-19 07:56:44 +0000466 bool HasKindDecoration = false;
John McCall7c2342d2010-03-10 11:27:22 +0000467
468 // We don't print tags unless this is an elaborated type.
469 // In C, we just assume every RecordType is an elaborated type.
470 if (!Policy.LangOpts.CPlusPlus && !D->getTypedefForAnonDecl()) {
John McCall73061d02010-03-19 07:56:44 +0000471 HasKindDecoration = true;
John McCall7c2342d2010-03-10 11:27:22 +0000472 Buffer += D->getKindName();
473 Buffer += ' ';
474 }
475
Chris Lattnerc7acc662010-08-28 16:26:18 +0000476 // Compute the full nested-name-specifier for this type.
477 // In C, this will always be empty except when the type
478 // being printed is anonymous within other Record.
John McCall7c2342d2010-03-10 11:27:22 +0000479 if (!Policy.SuppressScope)
John McCall7c2342d2010-03-10 11:27:22 +0000480 AppendScope(D->getDeclContext(), Buffer);
481
John McCall3cb0ebd2010-03-10 03:28:59 +0000482 if (const IdentifierInfo *II = D->getIdentifier())
John McCall73061d02010-03-19 07:56:44 +0000483 Buffer += II->getNameStart();
John McCall3cb0ebd2010-03-10 03:28:59 +0000484 else if (TypedefDecl *Typedef = D->getTypedefForAnonDecl()) {
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000485 assert(Typedef->getIdentifier() && "Typedef without identifier?");
John McCall73061d02010-03-19 07:56:44 +0000486 Buffer += Typedef->getIdentifier()->getNameStart();
487 } else {
488 // Make an unambiguous representation for anonymous types, e.g.
489 // <anonymous enum at /usr/include/string.h:120:9>
490 llvm::raw_string_ostream OS(Buffer);
491 OS << "<anonymous";
492
Douglas Gregor84139d62010-04-05 21:25:31 +0000493 if (Policy.AnonymousTagLocations) {
494 // Suppress the redundant tag keyword if we just printed one.
495 // We don't have to worry about ElaboratedTypes here because you can't
496 // refer to an anonymous type with one.
497 if (!HasKindDecoration)
498 OS << " " << D->getKindName();
John McCall73061d02010-03-19 07:56:44 +0000499
Douglas Gregorcb7b1e12010-11-12 07:15:47 +0000500 PresumedLoc PLoc = D->getASTContext().getSourceManager().getPresumedLoc(
Douglas Gregor16834e82010-05-28 21:47:04 +0000501 D->getLocation());
Douglas Gregorcb7b1e12010-11-12 07:15:47 +0000502 if (PLoc.isValid()) {
Douglas Gregor16834e82010-05-28 21:47:04 +0000503 OS << " at " << PLoc.getFilename()
504 << ':' << PLoc.getLine()
505 << ':' << PLoc.getColumn();
506 }
Douglas Gregor84139d62010-04-05 21:25:31 +0000507 }
508
509 OS << '>';
John McCall73061d02010-03-19 07:56:44 +0000510 }
John McCall7c2342d2010-03-10 11:27:22 +0000511
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000512 // If this is a class template specialization, print the template
513 // arguments.
514 if (ClassTemplateSpecializationDecl *Spec
John McCall7c2342d2010-03-10 11:27:22 +0000515 = dyn_cast<ClassTemplateSpecializationDecl>(D)) {
John McCall3cb0ebd2010-03-10 03:28:59 +0000516 const TemplateArgument *Args;
517 unsigned NumArgs;
518 if (TypeSourceInfo *TAW = Spec->getTypeAsWritten()) {
519 const TemplateSpecializationType *TST =
520 cast<TemplateSpecializationType>(TAW->getType());
521 Args = TST->getArgs();
522 NumArgs = TST->getNumArgs();
523 } else {
524 const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs();
Douglas Gregor910f8002010-11-07 23:05:16 +0000525 Args = TemplateArgs.data();
526 NumArgs = TemplateArgs.size();
John McCall3cb0ebd2010-03-10 03:28:59 +0000527 }
John McCall7c2342d2010-03-10 11:27:22 +0000528 Buffer += TemplateSpecializationType::PrintTemplateArgumentList(Args,
529 NumArgs,
530 Policy);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000531 }
John McCall7c2342d2010-03-10 11:27:22 +0000532
533 if (!InnerString.empty()) {
534 Buffer += ' ';
535 Buffer += InnerString;
536 }
537
538 std::swap(Buffer, InnerString);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000539}
540
541void TypePrinter::PrintRecord(const RecordType *T, std::string &S) {
John McCall3cb0ebd2010-03-10 03:28:59 +0000542 PrintTag(T->getDecl(), S);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000543}
544
545void TypePrinter::PrintEnum(const EnumType *T, std::string &S) {
John McCall3cb0ebd2010-03-10 03:28:59 +0000546 PrintTag(T->getDecl(), S);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000547}
548
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000549void TypePrinter::PrintTemplateTypeParm(const TemplateTypeParmType *T,
550 std::string &S) {
551 if (!S.empty()) // Prefix the basic type, e.g. 'parmname X'.
552 S = ' ' + S;
Douglas Gregorefed5c82010-06-16 15:23:05 +0000553
554 if (!T->getName())
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000555 S = "type-parameter-" + llvm::utostr_32(T->getDepth()) + '-' +
556 llvm::utostr_32(T->getIndex()) + S;
Douglas Gregorefed5c82010-06-16 15:23:05 +0000557 else
558 S = T->getName()->getName().str() + S;
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000559}
560
561void TypePrinter::PrintSubstTemplateTypeParm(const SubstTemplateTypeParmType *T,
562 std::string &S) {
563 Print(T->getReplacementType(), S);
564}
565
566void TypePrinter::PrintTemplateSpecialization(
567 const TemplateSpecializationType *T,
568 std::string &S) {
569 std::string SpecString;
570
571 {
572 llvm::raw_string_ostream OS(SpecString);
573 T->getTemplateName().print(OS, Policy);
574 }
575
576 SpecString += TemplateSpecializationType::PrintTemplateArgumentList(
577 T->getArgs(),
578 T->getNumArgs(),
579 Policy);
580 if (S.empty())
581 S.swap(SpecString);
582 else
583 S = SpecString + ' ' + S;
584}
585
John McCall3cb0ebd2010-03-10 03:28:59 +0000586void TypePrinter::PrintInjectedClassName(const InjectedClassNameType *T,
587 std::string &S) {
John McCall31f17ec2010-04-27 00:57:59 +0000588 PrintTemplateSpecialization(T->getInjectedTST(), S);
John McCall3cb0ebd2010-03-10 03:28:59 +0000589}
590
Abramo Bagnara465d41b2010-05-11 21:36:43 +0000591void TypePrinter::PrintElaborated(const ElaboratedType *T, std::string &S) {
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000592 std::string MyString;
593
594 {
595 llvm::raw_string_ostream OS(MyString);
Abramo Bagnara465d41b2010-05-11 21:36:43 +0000596 OS << TypeWithKeyword::getKeywordName(T->getKeyword());
597 if (T->getKeyword() != ETK_None)
598 OS << " ";
599 NestedNameSpecifier* Qualifier = T->getQualifier();
600 if (Qualifier)
601 Qualifier->print(OS, Policy);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000602 }
603
604 std::string TypeStr;
605 PrintingPolicy InnerPolicy(Policy);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000606 InnerPolicy.SuppressScope = true;
607 TypePrinter(InnerPolicy).Print(T->getNamedType(), TypeStr);
608
609 MyString += TypeStr;
610 if (S.empty())
611 S.swap(MyString);
612 else
613 S = MyString + ' ' + S;
614}
615
Douglas Gregor4714c122010-03-31 17:34:00 +0000616void TypePrinter::PrintDependentName(const DependentNameType *T, std::string &S) {
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000617 std::string MyString;
618
619 {
620 llvm::raw_string_ostream OS(MyString);
Abramo Bagnara465d41b2010-05-11 21:36:43 +0000621 OS << TypeWithKeyword::getKeywordName(T->getKeyword());
622 if (T->getKeyword() != ETK_None)
623 OS << " ";
Douglas Gregor4a2023f2010-03-31 20:19:30 +0000624
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000625 T->getQualifier()->print(OS, Policy);
626
John McCall33500952010-06-11 00:33:02 +0000627 OS << T->getIdentifier()->getName();
628 }
629
630 if (S.empty())
631 S.swap(MyString);
632 else
633 S = MyString + ' ' + S;
634}
635
636void TypePrinter::PrintDependentTemplateSpecialization(
637 const DependentTemplateSpecializationType *T, std::string &S) {
638 std::string MyString;
639 {
640 llvm::raw_string_ostream OS(MyString);
641
642 OS << TypeWithKeyword::getKeywordName(T->getKeyword());
643 if (T->getKeyword() != ETK_None)
644 OS << " ";
645
646 T->getQualifier()->print(OS, Policy);
647 OS << T->getIdentifier()->getName();
648 OS << TemplateSpecializationType::PrintTemplateArgumentList(
649 T->getArgs(),
650 T->getNumArgs(),
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000651 Policy);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000652 }
653
654 if (S.empty())
655 S.swap(MyString);
656 else
657 S = MyString + ' ' + S;
658}
659
660void TypePrinter::PrintObjCInterface(const ObjCInterfaceType *T,
661 std::string &S) {
662 if (!S.empty()) // Prefix the basic type, e.g. 'typedefname X'.
663 S = ' ' + S;
John McCallc12c5bb2010-05-15 11:32:37 +0000664
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000665 std::string ObjCQIString = T->getDecl()->getNameAsString();
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000666 S = ObjCQIString + S;
667}
668
John McCallc12c5bb2010-05-15 11:32:37 +0000669void TypePrinter::PrintObjCObject(const ObjCObjectType *T,
670 std::string &S) {
671 if (T->qual_empty())
672 return Print(T->getBaseType(), S);
673
674 std::string tmp;
675 Print(T->getBaseType(), tmp);
676 tmp += '<';
677 bool isFirst = true;
678 for (ObjCObjectType::qual_iterator
679 I = T->qual_begin(), E = T->qual_end(); I != E; ++I) {
680 if (isFirst)
681 isFirst = false;
682 else
683 tmp += ',';
684 tmp += (*I)->getNameAsString();
685 }
686 tmp += '>';
687
688 if (!S.empty()) {
689 tmp += ' ';
690 tmp += S;
691 }
692 std::swap(tmp, S);
693}
694
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000695void TypePrinter::PrintObjCObjectPointer(const ObjCObjectPointerType *T,
696 std::string &S) {
697 std::string ObjCQIString;
698
Chris Lattnerd7e52b82010-09-05 00:43:21 +0000699 T->getPointeeType().getLocalQualifiers().getAsStringInternal(ObjCQIString,
700 Policy);
701 if (!ObjCQIString.empty())
702 ObjCQIString += ' ';
703
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000704 if (T->isObjCIdType() || T->isObjCQualifiedIdType())
Chris Lattnerd7e52b82010-09-05 00:43:21 +0000705 ObjCQIString += "id";
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000706 else if (T->isObjCClassType() || T->isObjCQualifiedClassType())
Chris Lattnerd7e52b82010-09-05 00:43:21 +0000707 ObjCQIString += "Class";
Fariborz Jahanian13dcd002009-11-21 19:53:08 +0000708 else if (T->isObjCSelType())
Chris Lattnerd7e52b82010-09-05 00:43:21 +0000709 ObjCQIString += "SEL";
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000710 else
Chris Lattnerd7e52b82010-09-05 00:43:21 +0000711 ObjCQIString += T->getInterfaceDecl()->getNameAsString();
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000712
713 if (!T->qual_empty()) {
714 ObjCQIString += '<';
715 for (ObjCObjectPointerType::qual_iterator I = T->qual_begin(),
716 E = T->qual_end();
717 I != E; ++I) {
718 ObjCQIString += (*I)->getNameAsString();
719 if (I+1 != E)
720 ObjCQIString += ',';
721 }
722 ObjCQIString += '>';
723 }
724
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000725 if (!T->isObjCIdType() && !T->isObjCQualifiedIdType())
726 ObjCQIString += " *"; // Don't forget the implicit pointer.
727 else if (!S.empty()) // Prefix the basic type, e.g. 'typedefname X'.
728 S = ' ' + S;
729
730 S = ObjCQIString + S;
731}
732
733static void PrintTemplateArgument(std::string &Buffer,
734 const TemplateArgument &Arg,
735 const PrintingPolicy &Policy) {
736 switch (Arg.getKind()) {
737 case TemplateArgument::Null:
738 assert(false && "Null template argument");
739 break;
740
741 case TemplateArgument::Type:
742 Arg.getAsType().getAsStringInternal(Buffer, Policy);
743 break;
744
745 case TemplateArgument::Declaration:
746 Buffer = cast<NamedDecl>(Arg.getAsDecl())->getNameAsString();
747 break;
748
Douglas Gregor788cd062009-11-11 01:00:40 +0000749 case TemplateArgument::Template: {
750 llvm::raw_string_ostream s(Buffer);
751 Arg.getAsTemplate().print(s, Policy);
Douglas Gregorfb898e12009-11-12 16:20:59 +0000752 break;
Douglas Gregor788cd062009-11-11 01:00:40 +0000753 }
754
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000755 case TemplateArgument::Integral:
756 Buffer = Arg.getAsIntegral()->toString(10, true);
757 break;
758
759 case TemplateArgument::Expression: {
760 llvm::raw_string_ostream s(Buffer);
761 Arg.getAsExpr()->printPretty(s, 0, Policy);
762 break;
763 }
764
765 case TemplateArgument::Pack:
766 assert(0 && "FIXME: Implement!");
767 break;
768 }
769}
770
John McCalld5532b62009-11-23 01:53:49 +0000771std::string TemplateSpecializationType::
772 PrintTemplateArgumentList(const TemplateArgumentListInfo &Args,
773 const PrintingPolicy &Policy) {
774 return PrintTemplateArgumentList(Args.getArgumentArray(),
775 Args.size(),
776 Policy);
777}
778
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000779std::string
780TemplateSpecializationType::PrintTemplateArgumentList(
781 const TemplateArgument *Args,
782 unsigned NumArgs,
783 const PrintingPolicy &Policy) {
784 std::string SpecString;
785 SpecString += '<';
786 for (unsigned Arg = 0; Arg < NumArgs; ++Arg) {
787 if (Arg)
788 SpecString += ", ";
789
790 // Print the argument into a string.
791 std::string ArgString;
792 PrintTemplateArgument(ArgString, Args[Arg], Policy);
793
794 // If this is the first argument and its string representation
795 // begins with the global scope specifier ('::foo'), add a space
796 // to avoid printing the diagraph '<:'.
797 if (!Arg && !ArgString.empty() && ArgString[0] == ':')
798 SpecString += ' ';
799
800 SpecString += ArgString;
801 }
802
803 // If the last character of our string is '>', add another space to
804 // keep the two '>''s separate tokens. We don't *have* to do this in
805 // C++0x, but it's still good hygiene.
806 if (SpecString[SpecString.size() - 1] == '>')
807 SpecString += ' ';
808
809 SpecString += '>';
810
811 return SpecString;
812}
813
814// Sadly, repeat all that with TemplateArgLoc.
815std::string TemplateSpecializationType::
816PrintTemplateArgumentList(const TemplateArgumentLoc *Args, unsigned NumArgs,
817 const PrintingPolicy &Policy) {
818 std::string SpecString;
819 SpecString += '<';
820 for (unsigned Arg = 0; Arg < NumArgs; ++Arg) {
821 if (Arg)
822 SpecString += ", ";
823
824 // Print the argument into a string.
825 std::string ArgString;
826 PrintTemplateArgument(ArgString, Args[Arg].getArgument(), Policy);
827
828 // If this is the first argument and its string representation
829 // begins with the global scope specifier ('::foo'), add a space
830 // to avoid printing the diagraph '<:'.
831 if (!Arg && !ArgString.empty() && ArgString[0] == ':')
832 SpecString += ' ';
833
834 SpecString += ArgString;
835 }
836
837 // If the last character of our string is '>', add another space to
838 // keep the two '>''s separate tokens. We don't *have* to do this in
839 // C++0x, but it's still good hygiene.
840 if (SpecString[SpecString.size() - 1] == '>')
841 SpecString += ' ';
842
843 SpecString += '>';
844
845 return SpecString;
846}
847
848void QualType::dump(const char *msg) const {
849 std::string R = "identifier";
850 LangOptions LO;
851 getAsStringInternal(R, PrintingPolicy(LO));
852 if (msg)
Daniel Dunbare7cb7e42009-12-03 09:14:02 +0000853 llvm::errs() << msg << ": ";
854 llvm::errs() << R << "\n";
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000855}
856void QualType::dump() const {
857 dump("");
858}
859
860void Type::dump() const {
861 QualType(this, 0).dump();
862}
863
864std::string Qualifiers::getAsString() const {
865 LangOptions LO;
866 return getAsString(PrintingPolicy(LO));
867}
868
869// Appends qualifiers to the given string, separated by spaces. Will
870// prefix a space if the string is non-empty. Will not append a final
871// space.
872void Qualifiers::getAsStringInternal(std::string &S,
873 const PrintingPolicy&) const {
874 AppendTypeQualList(S, getCVRQualifiers());
875 if (unsigned AddressSpace = getAddressSpace()) {
876 if (!S.empty()) S += ' ';
877 S += "__attribute__((address_space(";
878 S += llvm::utostr_32(AddressSpace);
879 S += ")))";
880 }
881 if (Qualifiers::GC GCAttrType = getObjCGCAttr()) {
882 if (!S.empty()) S += ' ';
883 S += "__attribute__((objc_gc(";
884 if (GCAttrType == Qualifiers::Weak)
885 S += "weak";
886 else
887 S += "strong";
888 S += ")))";
889 }
890}
891
892std::string QualType::getAsString() const {
893 std::string S;
894 LangOptions LO;
895 getAsStringInternal(S, PrintingPolicy(LO));
896 return S;
897}
898
899void QualType::getAsStringInternal(std::string &S,
900 const PrintingPolicy &Policy) const {
901 TypePrinter Printer(Policy);
902 Printer.Print(*this, S);
903}