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