blob: 35a7e096994dff3bb2fbb247fd94655e37296fa8 [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();
Douglas Gregorfee8a3c2009-11-10 00:39:07 +000069 if (!Quals.empty()) {
70 std::string TQS;
71 Quals.getAsStringInternal(TQS, Policy);
72
73 if (!S.empty()) {
74 TQS += ' ';
75 TQS += S;
76 }
77 std::swap(S, TQS);
78 }
79
80 switch (T->getTypeClass()) {
81#define ABSTRACT_TYPE(CLASS, PARENT)
82#define TYPE(CLASS, PARENT) case Type::CLASS: \
83 Print##CLASS(cast<CLASS##Type>(T.getTypePtr()), S); \
84 break;
85#include "clang/AST/TypeNodes.def"
86 }
87}
88
89void TypePrinter::PrintBuiltin(const BuiltinType *T, std::string &S) {
90 if (S.empty()) {
91 S = T->getName(Policy.LangOpts);
92 } else {
93 // Prefix the basic type, e.g. 'int X'.
94 S = ' ' + S;
95 S = T->getName(Policy.LangOpts) + S;
96 }
97}
98
Douglas Gregorfee8a3c2009-11-10 00:39:07 +000099void TypePrinter::PrintComplex(const ComplexType *T, std::string &S) {
100 Print(T->getElementType(), S);
101 S = "_Complex " + S;
102}
103
104void TypePrinter::PrintPointer(const PointerType *T, std::string &S) {
105 S = '*' + S;
106
107 // Handle things like 'int (*A)[4];' correctly.
108 // FIXME: this should include vectors, but vectors use attributes I guess.
109 if (isa<ArrayType>(T->getPointeeType()))
110 S = '(' + S + ')';
111
112 Print(T->getPointeeType(), S);
113}
114
115void TypePrinter::PrintBlockPointer(const BlockPointerType *T, std::string &S) {
116 S = '^' + S;
117 Print(T->getPointeeType(), S);
118}
119
120void TypePrinter::PrintLValueReference(const LValueReferenceType *T,
121 std::string &S) {
122 S = '&' + S;
123
124 // Handle things like 'int (&A)[4];' correctly.
125 // FIXME: this should include vectors, but vectors use attributes I guess.
126 if (isa<ArrayType>(T->getPointeeTypeAsWritten()))
127 S = '(' + S + ')';
128
129 Print(T->getPointeeTypeAsWritten(), S);
130}
131
132void TypePrinter::PrintRValueReference(const RValueReferenceType *T,
133 std::string &S) {
134 S = "&&" + S;
135
136 // Handle things like 'int (&&A)[4];' correctly.
137 // FIXME: this should include vectors, but vectors use attributes I guess.
138 if (isa<ArrayType>(T->getPointeeTypeAsWritten()))
139 S = '(' + S + ')';
140
141 Print(T->getPointeeTypeAsWritten(), S);
142}
143
144void TypePrinter::PrintMemberPointer(const MemberPointerType *T,
145 std::string &S) {
146 std::string C;
147 Print(QualType(T->getClass(), 0), C);
148 C += "::*";
149 S = C + S;
150
151 // Handle things like 'int (Cls::*A)[4];' correctly.
152 // FIXME: this should include vectors, but vectors use attributes I guess.
153 if (isa<ArrayType>(T->getPointeeType()))
154 S = '(' + S + ')';
155
156 Print(T->getPointeeType(), S);
157}
158
159void TypePrinter::PrintConstantArray(const ConstantArrayType *T,
160 std::string &S) {
161 S += '[';
162 S += llvm::utostr(T->getSize().getZExtValue());
163 S += ']';
164
165 Print(T->getElementType(), S);
166}
167
168void TypePrinter::PrintIncompleteArray(const IncompleteArrayType *T,
169 std::string &S) {
170 S += "[]";
171 Print(T->getElementType(), S);
172}
173
174void TypePrinter::PrintVariableArray(const VariableArrayType *T,
175 std::string &S) {
176 S += '[';
177
178 if (T->getIndexTypeQualifiers().hasQualifiers()) {
179 AppendTypeQualList(S, T->getIndexTypeCVRQualifiers());
180 S += ' ';
181 }
182
183 if (T->getSizeModifier() == VariableArrayType::Static)
184 S += "static";
185 else if (T->getSizeModifier() == VariableArrayType::Star)
186 S += '*';
187
188 if (T->getSizeExpr()) {
189 std::string SStr;
190 llvm::raw_string_ostream s(SStr);
191 T->getSizeExpr()->printPretty(s, 0, Policy);
192 S += s.str();
193 }
194 S += ']';
195
196 Print(T->getElementType(), S);
197}
198
199void TypePrinter::PrintDependentSizedArray(const DependentSizedArrayType *T,
200 std::string &S) {
201 S += '[';
202
203 if (T->getSizeExpr()) {
204 std::string SStr;
205 llvm::raw_string_ostream s(SStr);
206 T->getSizeExpr()->printPretty(s, 0, Policy);
207 S += s.str();
208 }
209 S += ']';
210
211 Print(T->getElementType(), S);
212}
213
214void TypePrinter::PrintDependentSizedExtVector(
215 const DependentSizedExtVectorType *T,
216 std::string &S) {
217 Print(T->getElementType(), S);
218
219 S += " __attribute__((ext_vector_type(";
220 if (T->getSizeExpr()) {
221 std::string SStr;
222 llvm::raw_string_ostream s(SStr);
223 T->getSizeExpr()->printPretty(s, 0, Policy);
224 S += s.str();
225 }
226 S += ")))";
227}
228
229void TypePrinter::PrintVector(const VectorType *T, std::string &S) {
John Thompson82287d12010-02-05 00:12:22 +0000230 if (T->isAltiVec()) {
231 if (T->isPixel())
232 S = "__vector __pixel " + S;
233 else {
234 Print(T->getElementType(), S);
235 S = "__vector " + S;
236 }
237 } else {
238 // FIXME: We prefer to print the size directly here, but have no way
239 // to get the size of the type.
240 Print(T->getElementType(), S);
241 std::string V = "__attribute__((__vector_size__(";
242 V += llvm::utostr_32(T->getNumElements()); // convert back to bytes.
243 std::string ET;
244 Print(T->getElementType(), ET);
245 V += " * sizeof(" + ET + ")))) ";
246 S = V + S;
247 }
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000248}
249
250void TypePrinter::PrintExtVector(const ExtVectorType *T, std::string &S) {
251 S += " __attribute__((ext_vector_type(";
252 S += llvm::utostr_32(T->getNumElements());
253 S += ")))";
254 Print(T->getElementType(), S);
255}
256
257void TypePrinter::PrintFunctionProto(const FunctionProtoType *T,
258 std::string &S) {
259 // If needed for precedence reasons, wrap the inner part in grouping parens.
260 if (!S.empty())
261 S = "(" + S + ")";
262
263 S += "(";
264 std::string Tmp;
265 PrintingPolicy ParamPolicy(Policy);
266 ParamPolicy.SuppressSpecifiers = false;
267 for (unsigned i = 0, e = T->getNumArgs(); i != e; ++i) {
268 if (i) S += ", ";
269 Print(T->getArgType(i), Tmp);
270 S += Tmp;
271 Tmp.clear();
272 }
273
274 if (T->isVariadic()) {
275 if (T->getNumArgs())
276 S += ", ";
277 S += "...";
278 } else if (T->getNumArgs() == 0 && !Policy.LangOpts.CPlusPlus) {
279 // Do not emit int() if we have a proto, emit 'int(void)'.
280 S += "void";
281 }
282
283 S += ")";
Douglas Gregor0ae7b3f2009-12-08 17:45:32 +0000284
Rafael Espindola264ba482010-03-30 20:24:48 +0000285 FunctionType::ExtInfo Info = T->getExtInfo();
286 switch(Info.getCC()) {
John McCallf82b4e82010-02-04 05:44:44 +0000287 case CC_Default:
288 default: break;
289 case CC_C:
290 S += " __attribute__((cdecl))";
291 break;
292 case CC_X86StdCall:
293 S += " __attribute__((stdcall))";
294 break;
295 case CC_X86FastCall:
296 S += " __attribute__((fastcall))";
297 break;
Douglas Gregorf813a2c2010-05-18 16:57:00 +0000298 case CC_X86ThisCall:
299 S += " __attribute__((thiscall))";
300 break;
John McCallf82b4e82010-02-04 05:44:44 +0000301 }
Rafael Espindola264ba482010-03-30 20:24:48 +0000302 if (Info.getNoReturn())
Douglas Gregor48026d22010-01-11 18:40:55 +0000303 S += " __attribute__((noreturn))";
Rafael Espindola425ef722010-03-30 22:15:11 +0000304 if (Info.getRegParm())
305 S += " __attribute__((regparm (" +
306 llvm::utostr_32(Info.getRegParm()) + ")))";
Douglas Gregor48026d22010-01-11 18:40:55 +0000307
Douglas Gregor0ae7b3f2009-12-08 17:45:32 +0000308 if (T->hasExceptionSpec()) {
309 S += " throw(";
310 if (T->hasAnyExceptionSpec())
311 S += "...";
312 else
313 for (unsigned I = 0, N = T->getNumExceptions(); I != N; ++I) {
314 if (I)
315 S += ", ";
316
317 std::string ExceptionType;
318 Print(T->getExceptionType(I), ExceptionType);
319 S += ExceptionType;
320 }
321 S += ")";
322 }
323
Douglas Gregor48026d22010-01-11 18:40:55 +0000324 AppendTypeQualList(S, T->getTypeQuals());
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000325
Douglas Gregor48026d22010-01-11 18:40:55 +0000326 Print(T->getResultType(), S);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000327}
328
329void TypePrinter::PrintFunctionNoProto(const FunctionNoProtoType *T,
330 std::string &S) {
331 // If needed for precedence reasons, wrap the inner part in grouping parens.
332 if (!S.empty())
333 S = "(" + S + ")";
334
335 S += "()";
336 if (T->getNoReturnAttr())
337 S += " __attribute__((noreturn))";
338 Print(T->getResultType(), S);
339}
340
John McCall3cb0ebd2010-03-10 03:28:59 +0000341static void PrintTypeSpec(const NamedDecl *D, std::string &S) {
342 IdentifierInfo *II = D->getIdentifier();
John McCalled976492009-12-04 22:46:56 +0000343 if (S.empty())
344 S = II->getName().str();
345 else
346 S = II->getName().str() + ' ' + S;
347}
348
John McCall3cb0ebd2010-03-10 03:28:59 +0000349void TypePrinter::PrintUnresolvedUsing(const UnresolvedUsingType *T,
350 std::string &S) {
351 PrintTypeSpec(T->getDecl(), S);
352}
353
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000354void TypePrinter::PrintTypedef(const TypedefType *T, std::string &S) {
John McCall3cb0ebd2010-03-10 03:28:59 +0000355 PrintTypeSpec(T->getDecl(), S);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000356}
357
358void TypePrinter::PrintTypeOfExpr(const TypeOfExprType *T, std::string &S) {
359 if (!S.empty()) // Prefix the basic type, e.g. 'typeof(e) X'.
360 S = ' ' + S;
361 std::string Str;
362 llvm::raw_string_ostream s(Str);
363 T->getUnderlyingExpr()->printPretty(s, 0, Policy);
364 S = "typeof " + s.str() + S;
365}
366
367void TypePrinter::PrintTypeOf(const TypeOfType *T, std::string &S) {
368 if (!S.empty()) // Prefix the basic type, e.g. 'typeof(t) X'.
369 S = ' ' + S;
370 std::string Tmp;
371 Print(T->getUnderlyingType(), Tmp);
372 S = "typeof(" + Tmp + ")" + S;
373}
374
375void TypePrinter::PrintDecltype(const DecltypeType *T, std::string &S) {
376 if (!S.empty()) // Prefix the basic type, e.g. 'decltype(t) X'.
377 S = ' ' + S;
378 std::string Str;
379 llvm::raw_string_ostream s(Str);
380 T->getUnderlyingExpr()->printPretty(s, 0, Policy);
381 S = "decltype(" + s.str() + ")" + S;
382}
383
John McCall7c2342d2010-03-10 11:27:22 +0000384/// Appends the given scope to the end of a string.
385void TypePrinter::AppendScope(DeclContext *DC, std::string &Buffer) {
386 if (DC->isTranslationUnit()) return;
387 AppendScope(DC->getParent(), Buffer);
388
389 unsigned OldSize = Buffer.size();
390
391 if (NamespaceDecl *NS = dyn_cast<NamespaceDecl>(DC)) {
392 if (NS->getIdentifier())
393 Buffer += NS->getNameAsString();
394 else
395 Buffer += "<anonymous>";
396 } else if (ClassTemplateSpecializationDecl *Spec
397 = dyn_cast<ClassTemplateSpecializationDecl>(DC)) {
398 const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs();
399 std::string TemplateArgsStr
400 = TemplateSpecializationType::PrintTemplateArgumentList(
401 TemplateArgs.getFlatArgumentList(),
402 TemplateArgs.flat_size(),
403 Policy);
404 Buffer += Spec->getIdentifier()->getName();
405 Buffer += TemplateArgsStr;
406 } else if (TagDecl *Tag = dyn_cast<TagDecl>(DC)) {
407 if (TypedefDecl *Typedef = Tag->getTypedefForAnonDecl())
408 Buffer += Typedef->getIdentifier()->getName();
409 else if (Tag->getIdentifier())
410 Buffer += Tag->getIdentifier()->getName();
411 }
412
413 if (Buffer.size() != OldSize)
414 Buffer += "::";
415}
416
John McCall3cb0ebd2010-03-10 03:28:59 +0000417void TypePrinter::PrintTag(TagDecl *D, std::string &InnerString) {
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000418 if (Policy.SuppressTag)
419 return;
John McCall7c2342d2010-03-10 11:27:22 +0000420
421 std::string Buffer;
John McCall73061d02010-03-19 07:56:44 +0000422 bool HasKindDecoration = false;
John McCall7c2342d2010-03-10 11:27:22 +0000423
424 // We don't print tags unless this is an elaborated type.
425 // In C, we just assume every RecordType is an elaborated type.
426 if (!Policy.LangOpts.CPlusPlus && !D->getTypedefForAnonDecl()) {
John McCall73061d02010-03-19 07:56:44 +0000427 HasKindDecoration = true;
John McCall7c2342d2010-03-10 11:27:22 +0000428 Buffer += D->getKindName();
429 Buffer += ' ';
430 }
431
432 if (!Policy.SuppressScope)
433 // Compute the full nested-name-specifier for this type. In C,
434 // this will always be empty.
435 AppendScope(D->getDeclContext(), Buffer);
436
John McCall3cb0ebd2010-03-10 03:28:59 +0000437 if (const IdentifierInfo *II = D->getIdentifier())
John McCall73061d02010-03-19 07:56:44 +0000438 Buffer += II->getNameStart();
John McCall3cb0ebd2010-03-10 03:28:59 +0000439 else if (TypedefDecl *Typedef = D->getTypedefForAnonDecl()) {
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000440 assert(Typedef->getIdentifier() && "Typedef without identifier?");
John McCall73061d02010-03-19 07:56:44 +0000441 Buffer += Typedef->getIdentifier()->getNameStart();
442 } else {
443 // Make an unambiguous representation for anonymous types, e.g.
444 // <anonymous enum at /usr/include/string.h:120:9>
445 llvm::raw_string_ostream OS(Buffer);
446 OS << "<anonymous";
447
Douglas Gregor84139d62010-04-05 21:25:31 +0000448 if (Policy.AnonymousTagLocations) {
449 // Suppress the redundant tag keyword if we just printed one.
450 // We don't have to worry about ElaboratedTypes here because you can't
451 // refer to an anonymous type with one.
452 if (!HasKindDecoration)
453 OS << " " << D->getKindName();
John McCall73061d02010-03-19 07:56:44 +0000454
Douglas Gregor84139d62010-04-05 21:25:31 +0000455 PresumedLoc PLoc = D->getASTContext().getSourceManager().getPresumedLoc(
456 D->getLocation());
457 OS << " at " << PLoc.getFilename()
458 << ':' << PLoc.getLine()
459 << ':' << PLoc.getColumn();
460 }
461
462 OS << '>';
John McCall73061d02010-03-19 07:56:44 +0000463 OS.flush();
464 }
John McCall7c2342d2010-03-10 11:27:22 +0000465
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000466 // If this is a class template specialization, print the template
467 // arguments.
468 if (ClassTemplateSpecializationDecl *Spec
John McCall7c2342d2010-03-10 11:27:22 +0000469 = dyn_cast<ClassTemplateSpecializationDecl>(D)) {
John McCall3cb0ebd2010-03-10 03:28:59 +0000470 const TemplateArgument *Args;
471 unsigned NumArgs;
472 if (TypeSourceInfo *TAW = Spec->getTypeAsWritten()) {
473 const TemplateSpecializationType *TST =
474 cast<TemplateSpecializationType>(TAW->getType());
475 Args = TST->getArgs();
476 NumArgs = TST->getNumArgs();
477 } else {
478 const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs();
479 Args = TemplateArgs.getFlatArgumentList();
480 NumArgs = TemplateArgs.flat_size();
481 }
John McCall7c2342d2010-03-10 11:27:22 +0000482 Buffer += TemplateSpecializationType::PrintTemplateArgumentList(Args,
483 NumArgs,
484 Policy);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000485 }
John McCall7c2342d2010-03-10 11:27:22 +0000486
487 if (!InnerString.empty()) {
488 Buffer += ' ';
489 Buffer += InnerString;
490 }
491
492 std::swap(Buffer, InnerString);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000493}
494
495void TypePrinter::PrintRecord(const RecordType *T, std::string &S) {
John McCall3cb0ebd2010-03-10 03:28:59 +0000496 PrintTag(T->getDecl(), S);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000497}
498
499void TypePrinter::PrintEnum(const EnumType *T, std::string &S) {
John McCall3cb0ebd2010-03-10 03:28:59 +0000500 PrintTag(T->getDecl(), S);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000501}
502
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000503void TypePrinter::PrintTemplateTypeParm(const TemplateTypeParmType *T,
504 std::string &S) {
505 if (!S.empty()) // Prefix the basic type, e.g. 'parmname X'.
506 S = ' ' + S;
507
508 if (!T->getName())
509 S = "type-parameter-" + llvm::utostr_32(T->getDepth()) + '-' +
510 llvm::utostr_32(T->getIndex()) + S;
511 else
512 S = T->getName()->getName().str() + S;
513}
514
515void TypePrinter::PrintSubstTemplateTypeParm(const SubstTemplateTypeParmType *T,
516 std::string &S) {
517 Print(T->getReplacementType(), S);
518}
519
520void TypePrinter::PrintTemplateSpecialization(
521 const TemplateSpecializationType *T,
522 std::string &S) {
523 std::string SpecString;
524
525 {
526 llvm::raw_string_ostream OS(SpecString);
527 T->getTemplateName().print(OS, Policy);
528 }
529
530 SpecString += TemplateSpecializationType::PrintTemplateArgumentList(
531 T->getArgs(),
532 T->getNumArgs(),
533 Policy);
534 if (S.empty())
535 S.swap(SpecString);
536 else
537 S = SpecString + ' ' + S;
538}
539
John McCall3cb0ebd2010-03-10 03:28:59 +0000540void TypePrinter::PrintInjectedClassName(const InjectedClassNameType *T,
541 std::string &S) {
John McCall31f17ec2010-04-27 00:57:59 +0000542 PrintTemplateSpecialization(T->getInjectedTST(), S);
John McCall3cb0ebd2010-03-10 03:28:59 +0000543}
544
Abramo Bagnara465d41b2010-05-11 21:36:43 +0000545void TypePrinter::PrintElaborated(const ElaboratedType *T, std::string &S) {
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000546 std::string MyString;
547
548 {
549 llvm::raw_string_ostream OS(MyString);
Abramo Bagnara465d41b2010-05-11 21:36:43 +0000550 OS << TypeWithKeyword::getKeywordName(T->getKeyword());
551 if (T->getKeyword() != ETK_None)
552 OS << " ";
553 NestedNameSpecifier* Qualifier = T->getQualifier();
554 if (Qualifier)
555 Qualifier->print(OS, Policy);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000556 }
557
558 std::string TypeStr;
559 PrintingPolicy InnerPolicy(Policy);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000560 InnerPolicy.SuppressScope = true;
561 TypePrinter(InnerPolicy).Print(T->getNamedType(), TypeStr);
562
563 MyString += TypeStr;
564 if (S.empty())
565 S.swap(MyString);
566 else
567 S = MyString + ' ' + S;
568}
569
Douglas Gregor4714c122010-03-31 17:34:00 +0000570void TypePrinter::PrintDependentName(const DependentNameType *T, std::string &S) {
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000571 std::string MyString;
572
573 {
574 llvm::raw_string_ostream OS(MyString);
Abramo Bagnara465d41b2010-05-11 21:36:43 +0000575 OS << TypeWithKeyword::getKeywordName(T->getKeyword());
576 if (T->getKeyword() != ETK_None)
577 OS << " ";
Douglas Gregor4a2023f2010-03-31 20:19:30 +0000578
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000579 T->getQualifier()->print(OS, Policy);
580
581 if (const IdentifierInfo *Ident = T->getIdentifier())
582 OS << Ident->getName();
583 else if (const TemplateSpecializationType *Spec = T->getTemplateId()) {
584 Spec->getTemplateName().print(OS, Policy, true);
585 OS << TemplateSpecializationType::PrintTemplateArgumentList(
586 Spec->getArgs(),
587 Spec->getNumArgs(),
588 Policy);
589 }
590 }
591
592 if (S.empty())
593 S.swap(MyString);
594 else
595 S = MyString + ' ' + S;
596}
597
598void TypePrinter::PrintObjCInterface(const ObjCInterfaceType *T,
599 std::string &S) {
600 if (!S.empty()) // Prefix the basic type, e.g. 'typedefname X'.
601 S = ' ' + S;
John McCallc12c5bb2010-05-15 11:32:37 +0000602
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000603 std::string ObjCQIString = T->getDecl()->getNameAsString();
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000604 S = ObjCQIString + S;
605}
606
John McCallc12c5bb2010-05-15 11:32:37 +0000607void TypePrinter::PrintObjCObject(const ObjCObjectType *T,
608 std::string &S) {
609 if (T->qual_empty())
610 return Print(T->getBaseType(), S);
611
612 std::string tmp;
613 Print(T->getBaseType(), tmp);
614 tmp += '<';
615 bool isFirst = true;
616 for (ObjCObjectType::qual_iterator
617 I = T->qual_begin(), E = T->qual_end(); I != E; ++I) {
618 if (isFirst)
619 isFirst = false;
620 else
621 tmp += ',';
622 tmp += (*I)->getNameAsString();
623 }
624 tmp += '>';
625
626 if (!S.empty()) {
627 tmp += ' ';
628 tmp += S;
629 }
630 std::swap(tmp, S);
631}
632
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000633void TypePrinter::PrintObjCObjectPointer(const ObjCObjectPointerType *T,
634 std::string &S) {
635 std::string ObjCQIString;
636
637 if (T->isObjCIdType() || T->isObjCQualifiedIdType())
638 ObjCQIString = "id";
639 else if (T->isObjCClassType() || T->isObjCQualifiedClassType())
640 ObjCQIString = "Class";
Fariborz Jahanian13dcd002009-11-21 19:53:08 +0000641 else if (T->isObjCSelType())
642 ObjCQIString = "SEL";
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000643 else
644 ObjCQIString = T->getInterfaceDecl()->getNameAsString();
645
646 if (!T->qual_empty()) {
647 ObjCQIString += '<';
648 for (ObjCObjectPointerType::qual_iterator I = T->qual_begin(),
649 E = T->qual_end();
650 I != E; ++I) {
651 ObjCQIString += (*I)->getNameAsString();
652 if (I+1 != E)
653 ObjCQIString += ',';
654 }
655 ObjCQIString += '>';
656 }
657
Douglas Gregora4923eb2009-11-16 21:35:15 +0000658 T->getPointeeType().getLocalQualifiers().getAsStringInternal(ObjCQIString,
659 Policy);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000660
661 if (!T->isObjCIdType() && !T->isObjCQualifiedIdType())
662 ObjCQIString += " *"; // Don't forget the implicit pointer.
663 else if (!S.empty()) // Prefix the basic type, e.g. 'typedefname X'.
664 S = ' ' + S;
665
666 S = ObjCQIString + S;
667}
668
669static void PrintTemplateArgument(std::string &Buffer,
670 const TemplateArgument &Arg,
671 const PrintingPolicy &Policy) {
672 switch (Arg.getKind()) {
673 case TemplateArgument::Null:
674 assert(false && "Null template argument");
675 break;
676
677 case TemplateArgument::Type:
678 Arg.getAsType().getAsStringInternal(Buffer, Policy);
679 break;
680
681 case TemplateArgument::Declaration:
682 Buffer = cast<NamedDecl>(Arg.getAsDecl())->getNameAsString();
683 break;
684
Douglas Gregor788cd062009-11-11 01:00:40 +0000685 case TemplateArgument::Template: {
686 llvm::raw_string_ostream s(Buffer);
687 Arg.getAsTemplate().print(s, Policy);
Douglas Gregorfb898e12009-11-12 16:20:59 +0000688 break;
Douglas Gregor788cd062009-11-11 01:00:40 +0000689 }
690
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000691 case TemplateArgument::Integral:
692 Buffer = Arg.getAsIntegral()->toString(10, true);
693 break;
694
695 case TemplateArgument::Expression: {
696 llvm::raw_string_ostream s(Buffer);
697 Arg.getAsExpr()->printPretty(s, 0, Policy);
698 break;
699 }
700
701 case TemplateArgument::Pack:
702 assert(0 && "FIXME: Implement!");
703 break;
704 }
705}
706
John McCalld5532b62009-11-23 01:53:49 +0000707std::string TemplateSpecializationType::
708 PrintTemplateArgumentList(const TemplateArgumentListInfo &Args,
709 const PrintingPolicy &Policy) {
710 return PrintTemplateArgumentList(Args.getArgumentArray(),
711 Args.size(),
712 Policy);
713}
714
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000715std::string
716TemplateSpecializationType::PrintTemplateArgumentList(
717 const TemplateArgument *Args,
718 unsigned NumArgs,
719 const PrintingPolicy &Policy) {
720 std::string SpecString;
721 SpecString += '<';
722 for (unsigned Arg = 0; Arg < NumArgs; ++Arg) {
723 if (Arg)
724 SpecString += ", ";
725
726 // Print the argument into a string.
727 std::string ArgString;
728 PrintTemplateArgument(ArgString, Args[Arg], Policy);
729
730 // If this is the first argument and its string representation
731 // begins with the global scope specifier ('::foo'), add a space
732 // to avoid printing the diagraph '<:'.
733 if (!Arg && !ArgString.empty() && ArgString[0] == ':')
734 SpecString += ' ';
735
736 SpecString += ArgString;
737 }
738
739 // If the last character of our string is '>', add another space to
740 // keep the two '>''s separate tokens. We don't *have* to do this in
741 // C++0x, but it's still good hygiene.
742 if (SpecString[SpecString.size() - 1] == '>')
743 SpecString += ' ';
744
745 SpecString += '>';
746
747 return SpecString;
748}
749
750// Sadly, repeat all that with TemplateArgLoc.
751std::string TemplateSpecializationType::
752PrintTemplateArgumentList(const TemplateArgumentLoc *Args, unsigned NumArgs,
753 const PrintingPolicy &Policy) {
754 std::string SpecString;
755 SpecString += '<';
756 for (unsigned Arg = 0; Arg < NumArgs; ++Arg) {
757 if (Arg)
758 SpecString += ", ";
759
760 // Print the argument into a string.
761 std::string ArgString;
762 PrintTemplateArgument(ArgString, Args[Arg].getArgument(), Policy);
763
764 // If this is the first argument and its string representation
765 // begins with the global scope specifier ('::foo'), add a space
766 // to avoid printing the diagraph '<:'.
767 if (!Arg && !ArgString.empty() && ArgString[0] == ':')
768 SpecString += ' ';
769
770 SpecString += ArgString;
771 }
772
773 // If the last character of our string is '>', add another space to
774 // keep the two '>''s separate tokens. We don't *have* to do this in
775 // C++0x, but it's still good hygiene.
776 if (SpecString[SpecString.size() - 1] == '>')
777 SpecString += ' ';
778
779 SpecString += '>';
780
781 return SpecString;
782}
783
784void QualType::dump(const char *msg) const {
785 std::string R = "identifier";
786 LangOptions LO;
787 getAsStringInternal(R, PrintingPolicy(LO));
788 if (msg)
Daniel Dunbare7cb7e42009-12-03 09:14:02 +0000789 llvm::errs() << msg << ": ";
790 llvm::errs() << R << "\n";
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000791}
792void QualType::dump() const {
793 dump("");
794}
795
796void Type::dump() const {
797 QualType(this, 0).dump();
798}
799
800std::string Qualifiers::getAsString() const {
801 LangOptions LO;
802 return getAsString(PrintingPolicy(LO));
803}
804
805// Appends qualifiers to the given string, separated by spaces. Will
806// prefix a space if the string is non-empty. Will not append a final
807// space.
808void Qualifiers::getAsStringInternal(std::string &S,
809 const PrintingPolicy&) const {
810 AppendTypeQualList(S, getCVRQualifiers());
811 if (unsigned AddressSpace = getAddressSpace()) {
812 if (!S.empty()) S += ' ';
813 S += "__attribute__((address_space(";
814 S += llvm::utostr_32(AddressSpace);
815 S += ")))";
816 }
817 if (Qualifiers::GC GCAttrType = getObjCGCAttr()) {
818 if (!S.empty()) S += ' ';
819 S += "__attribute__((objc_gc(";
820 if (GCAttrType == Qualifiers::Weak)
821 S += "weak";
822 else
823 S += "strong";
824 S += ")))";
825 }
826}
827
828std::string QualType::getAsString() const {
829 std::string S;
830 LangOptions LO;
831 getAsStringInternal(S, PrintingPolicy(LO));
832 return S;
833}
834
835void QualType::getAsStringInternal(std::string &S,
836 const PrintingPolicy &Policy) const {
837 TypePrinter Printer(Policy);
838 Printer.Print(*this, S);
839}