blob: 037bc14e7a9199ce5dedb5993ea1a4b9324f9abd [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"
21#include "llvm/ADT/StringExtras.h"
22#include "llvm/Support/raw_ostream.h"
23using namespace clang;
24
25namespace {
26 class TypePrinter {
27 PrintingPolicy Policy;
28
29 public:
30 explicit TypePrinter(const PrintingPolicy &Policy) : Policy(Policy) { }
31
32 void Print(QualType T, std::string &S);
John McCall7c2342d2010-03-10 11:27:22 +000033 void AppendScope(DeclContext *DC, std::string &S);
John McCall3cb0ebd2010-03-10 03:28:59 +000034 void PrintTag(TagDecl *T, std::string &S);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +000035#define ABSTRACT_TYPE(CLASS, PARENT)
36#define TYPE(CLASS, PARENT) \
37 void Print##CLASS(const CLASS##Type *T, std::string &S);
38#include "clang/AST/TypeNodes.def"
39 };
40}
41
42static void AppendTypeQualList(std::string &S, unsigned TypeQuals) {
43 if (TypeQuals & Qualifiers::Const) {
44 if (!S.empty()) S += ' ';
45 S += "const";
46 }
47 if (TypeQuals & Qualifiers::Volatile) {
48 if (!S.empty()) S += ' ';
49 S += "volatile";
50 }
51 if (TypeQuals & Qualifiers::Restrict) {
52 if (!S.empty()) S += ' ';
53 S += "restrict";
54 }
55}
56
57void TypePrinter::Print(QualType T, std::string &S) {
58 if (T.isNull()) {
59 S += "NULL TYPE";
60 return;
61 }
62
63 if (Policy.SuppressSpecifiers && T->isSpecifierType())
64 return;
65
66 // Print qualifiers as appropriate.
Douglas Gregora4923eb2009-11-16 21:35:15 +000067 Qualifiers Quals = T.getLocalQualifiers();
Douglas Gregorfee8a3c2009-11-10 00:39:07 +000068 if (!Quals.empty()) {
69 std::string TQS;
70 Quals.getAsStringInternal(TQS, Policy);
71
72 if (!S.empty()) {
73 TQS += ' ';
74 TQS += S;
75 }
76 std::swap(S, TQS);
77 }
78
79 switch (T->getTypeClass()) {
80#define ABSTRACT_TYPE(CLASS, PARENT)
81#define TYPE(CLASS, PARENT) case Type::CLASS: \
82 Print##CLASS(cast<CLASS##Type>(T.getTypePtr()), S); \
83 break;
84#include "clang/AST/TypeNodes.def"
85 }
86}
87
88void TypePrinter::PrintBuiltin(const BuiltinType *T, std::string &S) {
89 if (S.empty()) {
90 S = T->getName(Policy.LangOpts);
91 } else {
92 // Prefix the basic type, e.g. 'int X'.
93 S = ' ' + S;
94 S = T->getName(Policy.LangOpts) + S;
95 }
96}
97
Douglas Gregorfee8a3c2009-11-10 00:39:07 +000098void TypePrinter::PrintComplex(const ComplexType *T, std::string &S) {
99 Print(T->getElementType(), S);
100 S = "_Complex " + S;
101}
102
103void TypePrinter::PrintPointer(const PointerType *T, std::string &S) {
104 S = '*' + S;
105
106 // Handle things like 'int (*A)[4];' correctly.
107 // FIXME: this should include vectors, but vectors use attributes I guess.
108 if (isa<ArrayType>(T->getPointeeType()))
109 S = '(' + S + ')';
110
111 Print(T->getPointeeType(), S);
112}
113
114void TypePrinter::PrintBlockPointer(const BlockPointerType *T, std::string &S) {
115 S = '^' + S;
116 Print(T->getPointeeType(), S);
117}
118
119void TypePrinter::PrintLValueReference(const LValueReferenceType *T,
120 std::string &S) {
121 S = '&' + S;
122
123 // Handle things like 'int (&A)[4];' correctly.
124 // FIXME: this should include vectors, but vectors use attributes I guess.
125 if (isa<ArrayType>(T->getPointeeTypeAsWritten()))
126 S = '(' + S + ')';
127
128 Print(T->getPointeeTypeAsWritten(), S);
129}
130
131void TypePrinter::PrintRValueReference(const RValueReferenceType *T,
132 std::string &S) {
133 S = "&&" + S;
134
135 // Handle things like 'int (&&A)[4];' correctly.
136 // FIXME: this should include vectors, but vectors use attributes I guess.
137 if (isa<ArrayType>(T->getPointeeTypeAsWritten()))
138 S = '(' + S + ')';
139
140 Print(T->getPointeeTypeAsWritten(), S);
141}
142
143void TypePrinter::PrintMemberPointer(const MemberPointerType *T,
144 std::string &S) {
145 std::string C;
146 Print(QualType(T->getClass(), 0), C);
147 C += "::*";
148 S = C + S;
149
150 // Handle things like 'int (Cls::*A)[4];' correctly.
151 // FIXME: this should include vectors, but vectors use attributes I guess.
152 if (isa<ArrayType>(T->getPointeeType()))
153 S = '(' + S + ')';
154
155 Print(T->getPointeeType(), S);
156}
157
158void TypePrinter::PrintConstantArray(const ConstantArrayType *T,
159 std::string &S) {
160 S += '[';
161 S += llvm::utostr(T->getSize().getZExtValue());
162 S += ']';
163
164 Print(T->getElementType(), S);
165}
166
167void TypePrinter::PrintIncompleteArray(const IncompleteArrayType *T,
168 std::string &S) {
169 S += "[]";
170 Print(T->getElementType(), S);
171}
172
173void TypePrinter::PrintVariableArray(const VariableArrayType *T,
174 std::string &S) {
175 S += '[';
176
177 if (T->getIndexTypeQualifiers().hasQualifiers()) {
178 AppendTypeQualList(S, T->getIndexTypeCVRQualifiers());
179 S += ' ';
180 }
181
182 if (T->getSizeModifier() == VariableArrayType::Static)
183 S += "static";
184 else if (T->getSizeModifier() == VariableArrayType::Star)
185 S += '*';
186
187 if (T->getSizeExpr()) {
188 std::string SStr;
189 llvm::raw_string_ostream s(SStr);
190 T->getSizeExpr()->printPretty(s, 0, Policy);
191 S += s.str();
192 }
193 S += ']';
194
195 Print(T->getElementType(), S);
196}
197
198void TypePrinter::PrintDependentSizedArray(const DependentSizedArrayType *T,
199 std::string &S) {
200 S += '[';
201
202 if (T->getSizeExpr()) {
203 std::string SStr;
204 llvm::raw_string_ostream s(SStr);
205 T->getSizeExpr()->printPretty(s, 0, Policy);
206 S += s.str();
207 }
208 S += ']';
209
210 Print(T->getElementType(), S);
211}
212
213void TypePrinter::PrintDependentSizedExtVector(
214 const DependentSizedExtVectorType *T,
215 std::string &S) {
216 Print(T->getElementType(), S);
217
218 S += " __attribute__((ext_vector_type(";
219 if (T->getSizeExpr()) {
220 std::string SStr;
221 llvm::raw_string_ostream s(SStr);
222 T->getSizeExpr()->printPretty(s, 0, Policy);
223 S += s.str();
224 }
225 S += ")))";
226}
227
228void TypePrinter::PrintVector(const VectorType *T, std::string &S) {
John Thompson82287d12010-02-05 00:12:22 +0000229 if (T->isAltiVec()) {
230 if (T->isPixel())
231 S = "__vector __pixel " + S;
232 else {
233 Print(T->getElementType(), S);
234 S = "__vector " + S;
235 }
236 } else {
237 // FIXME: We prefer to print the size directly here, but have no way
238 // to get the size of the type.
239 Print(T->getElementType(), S);
240 std::string V = "__attribute__((__vector_size__(";
241 V += llvm::utostr_32(T->getNumElements()); // convert back to bytes.
242 std::string ET;
243 Print(T->getElementType(), ET);
244 V += " * sizeof(" + ET + ")))) ";
245 S = V + S;
246 }
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000247}
248
249void TypePrinter::PrintExtVector(const ExtVectorType *T, std::string &S) {
250 S += " __attribute__((ext_vector_type(";
251 S += llvm::utostr_32(T->getNumElements());
252 S += ")))";
253 Print(T->getElementType(), S);
254}
255
256void TypePrinter::PrintFunctionProto(const FunctionProtoType *T,
257 std::string &S) {
258 // If needed for precedence reasons, wrap the inner part in grouping parens.
259 if (!S.empty())
260 S = "(" + S + ")";
261
262 S += "(";
263 std::string Tmp;
264 PrintingPolicy ParamPolicy(Policy);
265 ParamPolicy.SuppressSpecifiers = false;
266 for (unsigned i = 0, e = T->getNumArgs(); i != e; ++i) {
267 if (i) S += ", ";
268 Print(T->getArgType(i), Tmp);
269 S += Tmp;
270 Tmp.clear();
271 }
272
273 if (T->isVariadic()) {
274 if (T->getNumArgs())
275 S += ", ";
276 S += "...";
277 } else if (T->getNumArgs() == 0 && !Policy.LangOpts.CPlusPlus) {
278 // Do not emit int() if we have a proto, emit 'int(void)'.
279 S += "void";
280 }
281
282 S += ")";
Douglas Gregor0ae7b3f2009-12-08 17:45:32 +0000283
John McCallf82b4e82010-02-04 05:44:44 +0000284 switch(T->getCallConv()) {
285 case CC_Default:
286 default: break;
287 case CC_C:
288 S += " __attribute__((cdecl))";
289 break;
290 case CC_X86StdCall:
291 S += " __attribute__((stdcall))";
292 break;
293 case CC_X86FastCall:
294 S += " __attribute__((fastcall))";
295 break;
296 }
Douglas Gregor48026d22010-01-11 18:40:55 +0000297 if (T->getNoReturnAttr())
298 S += " __attribute__((noreturn))";
299
300
Douglas Gregor0ae7b3f2009-12-08 17:45:32 +0000301 if (T->hasExceptionSpec()) {
302 S += " throw(";
303 if (T->hasAnyExceptionSpec())
304 S += "...";
305 else
306 for (unsigned I = 0, N = T->getNumExceptions(); I != N; ++I) {
307 if (I)
308 S += ", ";
309
310 std::string ExceptionType;
311 Print(T->getExceptionType(I), ExceptionType);
312 S += ExceptionType;
313 }
314 S += ")";
315 }
316
Douglas Gregor48026d22010-01-11 18:40:55 +0000317 AppendTypeQualList(S, T->getTypeQuals());
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000318
Douglas Gregor48026d22010-01-11 18:40:55 +0000319 Print(T->getResultType(), S);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000320}
321
322void TypePrinter::PrintFunctionNoProto(const FunctionNoProtoType *T,
323 std::string &S) {
324 // If needed for precedence reasons, wrap the inner part in grouping parens.
325 if (!S.empty())
326 S = "(" + S + ")";
327
328 S += "()";
329 if (T->getNoReturnAttr())
330 S += " __attribute__((noreturn))";
331 Print(T->getResultType(), S);
332}
333
John McCall3cb0ebd2010-03-10 03:28:59 +0000334static void PrintTypeSpec(const NamedDecl *D, std::string &S) {
335 IdentifierInfo *II = D->getIdentifier();
John McCalled976492009-12-04 22:46:56 +0000336 if (S.empty())
337 S = II->getName().str();
338 else
339 S = II->getName().str() + ' ' + S;
340}
341
John McCall3cb0ebd2010-03-10 03:28:59 +0000342void TypePrinter::PrintUnresolvedUsing(const UnresolvedUsingType *T,
343 std::string &S) {
344 PrintTypeSpec(T->getDecl(), S);
345}
346
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000347void TypePrinter::PrintTypedef(const TypedefType *T, std::string &S) {
John McCall3cb0ebd2010-03-10 03:28:59 +0000348 PrintTypeSpec(T->getDecl(), S);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000349}
350
351void TypePrinter::PrintTypeOfExpr(const TypeOfExprType *T, std::string &S) {
352 if (!S.empty()) // Prefix the basic type, e.g. 'typeof(e) X'.
353 S = ' ' + S;
354 std::string Str;
355 llvm::raw_string_ostream s(Str);
356 T->getUnderlyingExpr()->printPretty(s, 0, Policy);
357 S = "typeof " + s.str() + S;
358}
359
360void TypePrinter::PrintTypeOf(const TypeOfType *T, std::string &S) {
361 if (!S.empty()) // Prefix the basic type, e.g. 'typeof(t) X'.
362 S = ' ' + S;
363 std::string Tmp;
364 Print(T->getUnderlyingType(), Tmp);
365 S = "typeof(" + Tmp + ")" + S;
366}
367
368void TypePrinter::PrintDecltype(const DecltypeType *T, std::string &S) {
369 if (!S.empty()) // Prefix the basic type, e.g. 'decltype(t) X'.
370 S = ' ' + S;
371 std::string Str;
372 llvm::raw_string_ostream s(Str);
373 T->getUnderlyingExpr()->printPretty(s, 0, Policy);
374 S = "decltype(" + s.str() + ")" + S;
375}
376
John McCall7c2342d2010-03-10 11:27:22 +0000377/// Appends the given scope to the end of a string.
378void TypePrinter::AppendScope(DeclContext *DC, std::string &Buffer) {
379 if (DC->isTranslationUnit()) return;
380 AppendScope(DC->getParent(), Buffer);
381
382 unsigned OldSize = Buffer.size();
383
384 if (NamespaceDecl *NS = dyn_cast<NamespaceDecl>(DC)) {
385 if (NS->getIdentifier())
386 Buffer += NS->getNameAsString();
387 else
388 Buffer += "<anonymous>";
389 } else if (ClassTemplateSpecializationDecl *Spec
390 = dyn_cast<ClassTemplateSpecializationDecl>(DC)) {
391 const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs();
392 std::string TemplateArgsStr
393 = TemplateSpecializationType::PrintTemplateArgumentList(
394 TemplateArgs.getFlatArgumentList(),
395 TemplateArgs.flat_size(),
396 Policy);
397 Buffer += Spec->getIdentifier()->getName();
398 Buffer += TemplateArgsStr;
399 } else if (TagDecl *Tag = dyn_cast<TagDecl>(DC)) {
400 if (TypedefDecl *Typedef = Tag->getTypedefForAnonDecl())
401 Buffer += Typedef->getIdentifier()->getName();
402 else if (Tag->getIdentifier())
403 Buffer += Tag->getIdentifier()->getName();
404 }
405
406 if (Buffer.size() != OldSize)
407 Buffer += "::";
408}
409
John McCall3cb0ebd2010-03-10 03:28:59 +0000410void TypePrinter::PrintTag(TagDecl *D, std::string &InnerString) {
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000411 if (Policy.SuppressTag)
412 return;
John McCall7c2342d2010-03-10 11:27:22 +0000413
414 std::string Buffer;
415
416 // We don't print tags unless this is an elaborated type.
417 // In C, we just assume every RecordType is an elaborated type.
418 if (!Policy.LangOpts.CPlusPlus && !D->getTypedefForAnonDecl()) {
419 Buffer += D->getKindName();
420 Buffer += ' ';
421 }
422
423 if (!Policy.SuppressScope)
424 // Compute the full nested-name-specifier for this type. In C,
425 // this will always be empty.
426 AppendScope(D->getDeclContext(), Buffer);
427
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000428 const char *ID;
John McCall3cb0ebd2010-03-10 03:28:59 +0000429 if (const IdentifierInfo *II = D->getIdentifier())
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000430 ID = II->getNameStart();
John McCall3cb0ebd2010-03-10 03:28:59 +0000431 else if (TypedefDecl *Typedef = D->getTypedefForAnonDecl()) {
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000432 assert(Typedef->getIdentifier() && "Typedef without identifier?");
433 ID = Typedef->getIdentifier()->getNameStart();
434 } else
435 ID = "<anonymous>";
John McCall7c2342d2010-03-10 11:27:22 +0000436 Buffer += ID;
437
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000438 // If this is a class template specialization, print the template
439 // arguments.
440 if (ClassTemplateSpecializationDecl *Spec
John McCall7c2342d2010-03-10 11:27:22 +0000441 = dyn_cast<ClassTemplateSpecializationDecl>(D)) {
John McCall3cb0ebd2010-03-10 03:28:59 +0000442 const TemplateArgument *Args;
443 unsigned NumArgs;
444 if (TypeSourceInfo *TAW = Spec->getTypeAsWritten()) {
445 const TemplateSpecializationType *TST =
446 cast<TemplateSpecializationType>(TAW->getType());
447 Args = TST->getArgs();
448 NumArgs = TST->getNumArgs();
449 } else {
450 const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs();
451 Args = TemplateArgs.getFlatArgumentList();
452 NumArgs = TemplateArgs.flat_size();
453 }
John McCall7c2342d2010-03-10 11:27:22 +0000454 Buffer += TemplateSpecializationType::PrintTemplateArgumentList(Args,
455 NumArgs,
456 Policy);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000457 }
John McCall7c2342d2010-03-10 11:27:22 +0000458
459 if (!InnerString.empty()) {
460 Buffer += ' ';
461 Buffer += InnerString;
462 }
463
464 std::swap(Buffer, InnerString);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000465}
466
467void TypePrinter::PrintRecord(const RecordType *T, std::string &S) {
John McCall3cb0ebd2010-03-10 03:28:59 +0000468 PrintTag(T->getDecl(), S);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000469}
470
471void TypePrinter::PrintEnum(const EnumType *T, std::string &S) {
John McCall3cb0ebd2010-03-10 03:28:59 +0000472 PrintTag(T->getDecl(), S);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000473}
474
475void TypePrinter::PrintElaborated(const ElaboratedType *T, std::string &S) {
John McCall7c2342d2010-03-10 11:27:22 +0000476 Print(T->getUnderlyingType(), S);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000477 S = std::string(T->getNameForTagKind(T->getTagKind())) + ' ' + S;
478}
479
480void TypePrinter::PrintTemplateTypeParm(const TemplateTypeParmType *T,
481 std::string &S) {
482 if (!S.empty()) // Prefix the basic type, e.g. 'parmname X'.
483 S = ' ' + S;
484
485 if (!T->getName())
486 S = "type-parameter-" + llvm::utostr_32(T->getDepth()) + '-' +
487 llvm::utostr_32(T->getIndex()) + S;
488 else
489 S = T->getName()->getName().str() + S;
490}
491
492void TypePrinter::PrintSubstTemplateTypeParm(const SubstTemplateTypeParmType *T,
493 std::string &S) {
494 Print(T->getReplacementType(), S);
495}
496
497void TypePrinter::PrintTemplateSpecialization(
498 const TemplateSpecializationType *T,
499 std::string &S) {
500 std::string SpecString;
501
502 {
503 llvm::raw_string_ostream OS(SpecString);
504 T->getTemplateName().print(OS, Policy);
505 }
506
507 SpecString += TemplateSpecializationType::PrintTemplateArgumentList(
508 T->getArgs(),
509 T->getNumArgs(),
510 Policy);
511 if (S.empty())
512 S.swap(SpecString);
513 else
514 S = SpecString + ' ' + S;
515}
516
John McCall3cb0ebd2010-03-10 03:28:59 +0000517void TypePrinter::PrintInjectedClassName(const InjectedClassNameType *T,
518 std::string &S) {
John McCall7c2342d2010-03-10 11:27:22 +0000519 PrintTemplateSpecialization(T->getUnderlyingTST(), S);
John McCall3cb0ebd2010-03-10 03:28:59 +0000520}
521
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000522void TypePrinter::PrintQualifiedName(const QualifiedNameType *T,
523 std::string &S) {
524 std::string MyString;
525
526 {
527 llvm::raw_string_ostream OS(MyString);
528 T->getQualifier()->print(OS, Policy);
529 }
530
531 std::string TypeStr;
532 PrintingPolicy InnerPolicy(Policy);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000533 InnerPolicy.SuppressScope = true;
534 TypePrinter(InnerPolicy).Print(T->getNamedType(), TypeStr);
535
536 MyString += TypeStr;
537 if (S.empty())
538 S.swap(MyString);
539 else
540 S = MyString + ' ' + S;
541}
542
543void TypePrinter::PrintTypename(const TypenameType *T, std::string &S) {
544 std::string MyString;
545
546 {
547 llvm::raw_string_ostream OS(MyString);
548 OS << "typename ";
549 T->getQualifier()->print(OS, Policy);
550
551 if (const IdentifierInfo *Ident = T->getIdentifier())
552 OS << Ident->getName();
553 else if (const TemplateSpecializationType *Spec = T->getTemplateId()) {
554 Spec->getTemplateName().print(OS, Policy, true);
555 OS << TemplateSpecializationType::PrintTemplateArgumentList(
556 Spec->getArgs(),
557 Spec->getNumArgs(),
558 Policy);
559 }
560 }
561
562 if (S.empty())
563 S.swap(MyString);
564 else
565 S = MyString + ' ' + S;
566}
567
568void TypePrinter::PrintObjCInterface(const ObjCInterfaceType *T,
569 std::string &S) {
570 if (!S.empty()) // Prefix the basic type, e.g. 'typedefname X'.
571 S = ' ' + S;
572
573 std::string ObjCQIString = T->getDecl()->getNameAsString();
574 if (T->getNumProtocols()) {
575 ObjCQIString += '<';
576 bool isFirst = true;
577 for (ObjCInterfaceType::qual_iterator I = T->qual_begin(),
578 E = T->qual_end();
579 I != E; ++I) {
580 if (isFirst)
581 isFirst = false;
582 else
583 ObjCQIString += ',';
584 ObjCQIString += (*I)->getNameAsString();
585 }
586 ObjCQIString += '>';
587 }
588 S = ObjCQIString + S;
589}
590
591void TypePrinter::PrintObjCObjectPointer(const ObjCObjectPointerType *T,
592 std::string &S) {
593 std::string ObjCQIString;
594
595 if (T->isObjCIdType() || T->isObjCQualifiedIdType())
596 ObjCQIString = "id";
597 else if (T->isObjCClassType() || T->isObjCQualifiedClassType())
598 ObjCQIString = "Class";
Fariborz Jahanian13dcd002009-11-21 19:53:08 +0000599 else if (T->isObjCSelType())
600 ObjCQIString = "SEL";
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000601 else
602 ObjCQIString = T->getInterfaceDecl()->getNameAsString();
603
604 if (!T->qual_empty()) {
605 ObjCQIString += '<';
606 for (ObjCObjectPointerType::qual_iterator I = T->qual_begin(),
607 E = T->qual_end();
608 I != E; ++I) {
609 ObjCQIString += (*I)->getNameAsString();
610 if (I+1 != E)
611 ObjCQIString += ',';
612 }
613 ObjCQIString += '>';
614 }
615
Douglas Gregora4923eb2009-11-16 21:35:15 +0000616 T->getPointeeType().getLocalQualifiers().getAsStringInternal(ObjCQIString,
617 Policy);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000618
619 if (!T->isObjCIdType() && !T->isObjCQualifiedIdType())
620 ObjCQIString += " *"; // Don't forget the implicit pointer.
621 else if (!S.empty()) // Prefix the basic type, e.g. 'typedefname X'.
622 S = ' ' + S;
623
624 S = ObjCQIString + S;
625}
626
627static void PrintTemplateArgument(std::string &Buffer,
628 const TemplateArgument &Arg,
629 const PrintingPolicy &Policy) {
630 switch (Arg.getKind()) {
631 case TemplateArgument::Null:
632 assert(false && "Null template argument");
633 break;
634
635 case TemplateArgument::Type:
636 Arg.getAsType().getAsStringInternal(Buffer, Policy);
637 break;
638
639 case TemplateArgument::Declaration:
640 Buffer = cast<NamedDecl>(Arg.getAsDecl())->getNameAsString();
641 break;
642
Douglas Gregor788cd062009-11-11 01:00:40 +0000643 case TemplateArgument::Template: {
644 llvm::raw_string_ostream s(Buffer);
645 Arg.getAsTemplate().print(s, Policy);
Douglas Gregorfb898e12009-11-12 16:20:59 +0000646 break;
Douglas Gregor788cd062009-11-11 01:00:40 +0000647 }
648
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000649 case TemplateArgument::Integral:
650 Buffer = Arg.getAsIntegral()->toString(10, true);
651 break;
652
653 case TemplateArgument::Expression: {
654 llvm::raw_string_ostream s(Buffer);
655 Arg.getAsExpr()->printPretty(s, 0, Policy);
656 break;
657 }
658
659 case TemplateArgument::Pack:
660 assert(0 && "FIXME: Implement!");
661 break;
662 }
663}
664
John McCalld5532b62009-11-23 01:53:49 +0000665std::string TemplateSpecializationType::
666 PrintTemplateArgumentList(const TemplateArgumentListInfo &Args,
667 const PrintingPolicy &Policy) {
668 return PrintTemplateArgumentList(Args.getArgumentArray(),
669 Args.size(),
670 Policy);
671}
672
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000673std::string
674TemplateSpecializationType::PrintTemplateArgumentList(
675 const TemplateArgument *Args,
676 unsigned NumArgs,
677 const PrintingPolicy &Policy) {
678 std::string SpecString;
679 SpecString += '<';
680 for (unsigned Arg = 0; Arg < NumArgs; ++Arg) {
681 if (Arg)
682 SpecString += ", ";
683
684 // Print the argument into a string.
685 std::string ArgString;
686 PrintTemplateArgument(ArgString, Args[Arg], Policy);
687
688 // If this is the first argument and its string representation
689 // begins with the global scope specifier ('::foo'), add a space
690 // to avoid printing the diagraph '<:'.
691 if (!Arg && !ArgString.empty() && ArgString[0] == ':')
692 SpecString += ' ';
693
694 SpecString += ArgString;
695 }
696
697 // If the last character of our string is '>', add another space to
698 // keep the two '>''s separate tokens. We don't *have* to do this in
699 // C++0x, but it's still good hygiene.
700 if (SpecString[SpecString.size() - 1] == '>')
701 SpecString += ' ';
702
703 SpecString += '>';
704
705 return SpecString;
706}
707
708// Sadly, repeat all that with TemplateArgLoc.
709std::string TemplateSpecializationType::
710PrintTemplateArgumentList(const TemplateArgumentLoc *Args, unsigned NumArgs,
711 const PrintingPolicy &Policy) {
712 std::string SpecString;
713 SpecString += '<';
714 for (unsigned Arg = 0; Arg < NumArgs; ++Arg) {
715 if (Arg)
716 SpecString += ", ";
717
718 // Print the argument into a string.
719 std::string ArgString;
720 PrintTemplateArgument(ArgString, Args[Arg].getArgument(), Policy);
721
722 // If this is the first argument and its string representation
723 // begins with the global scope specifier ('::foo'), add a space
724 // to avoid printing the diagraph '<:'.
725 if (!Arg && !ArgString.empty() && ArgString[0] == ':')
726 SpecString += ' ';
727
728 SpecString += ArgString;
729 }
730
731 // If the last character of our string is '>', add another space to
732 // keep the two '>''s separate tokens. We don't *have* to do this in
733 // C++0x, but it's still good hygiene.
734 if (SpecString[SpecString.size() - 1] == '>')
735 SpecString += ' ';
736
737 SpecString += '>';
738
739 return SpecString;
740}
741
742void QualType::dump(const char *msg) const {
743 std::string R = "identifier";
744 LangOptions LO;
745 getAsStringInternal(R, PrintingPolicy(LO));
746 if (msg)
Daniel Dunbare7cb7e42009-12-03 09:14:02 +0000747 llvm::errs() << msg << ": ";
748 llvm::errs() << R << "\n";
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000749}
750void QualType::dump() const {
751 dump("");
752}
753
754void Type::dump() const {
755 QualType(this, 0).dump();
756}
757
758std::string Qualifiers::getAsString() const {
759 LangOptions LO;
760 return getAsString(PrintingPolicy(LO));
761}
762
763// Appends qualifiers to the given string, separated by spaces. Will
764// prefix a space if the string is non-empty. Will not append a final
765// space.
766void Qualifiers::getAsStringInternal(std::string &S,
767 const PrintingPolicy&) const {
768 AppendTypeQualList(S, getCVRQualifiers());
769 if (unsigned AddressSpace = getAddressSpace()) {
770 if (!S.empty()) S += ' ';
771 S += "__attribute__((address_space(";
772 S += llvm::utostr_32(AddressSpace);
773 S += ")))";
774 }
775 if (Qualifiers::GC GCAttrType = getObjCGCAttr()) {
776 if (!S.empty()) S += ' ';
777 S += "__attribute__((objc_gc(";
778 if (GCAttrType == Qualifiers::Weak)
779 S += "weak";
780 else
781 S += "strong";
782 S += ")))";
783 }
784}
785
786std::string QualType::getAsString() const {
787 std::string S;
788 LangOptions LO;
789 getAsStringInternal(S, PrintingPolicy(LO));
790 return S;
791}
792
793void QualType::getAsStringInternal(std::string &S,
794 const PrintingPolicy &Policy) const {
795 TypePrinter Printer(Policy);
796 Printer.Print(*this, S);
797}
798