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