blob: d3a6b645537c831240180ec749c22267eb21fe60 [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) {
Chris Lattner788b0fd2010-06-23 06:00:24 +0000230 if (T->getAltiVecSpecific() != VectorType::NotAltiVec) {
231 if (T->getAltiVecSpecific() == VectorType::Pixel)
John Thompson82287d12010-02-05 00:12:22 +0000232 S = "__vector __pixel " + S;
233 else {
234 Print(T->getElementType(), S);
Chris Lattner788b0fd2010-06-23 06:00:24 +0000235 S = ((T->getAltiVecSpecific() == VectorType::Bool)
236 ? "__vector __bool " : "__vector ") + S;
John Thompson82287d12010-02-05 00:12:22 +0000237 }
238 } else {
239 // FIXME: We prefer to print the size directly here, but have no way
240 // to get the size of the type.
241 Print(T->getElementType(), S);
242 std::string V = "__attribute__((__vector_size__(";
243 V += llvm::utostr_32(T->getNumElements()); // convert back to bytes.
244 std::string ET;
245 Print(T->getElementType(), ET);
246 V += " * sizeof(" + ET + ")))) ";
247 S = V + S;
248 }
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000249}
250
251void TypePrinter::PrintExtVector(const ExtVectorType *T, std::string &S) {
252 S += " __attribute__((ext_vector_type(";
253 S += llvm::utostr_32(T->getNumElements());
254 S += ")))";
255 Print(T->getElementType(), S);
256}
257
258void TypePrinter::PrintFunctionProto(const FunctionProtoType *T,
259 std::string &S) {
260 // If needed for precedence reasons, wrap the inner part in grouping parens.
261 if (!S.empty())
262 S = "(" + S + ")";
263
264 S += "(";
265 std::string Tmp;
266 PrintingPolicy ParamPolicy(Policy);
267 ParamPolicy.SuppressSpecifiers = false;
268 for (unsigned i = 0, e = T->getNumArgs(); i != e; ++i) {
269 if (i) S += ", ";
270 Print(T->getArgType(i), Tmp);
271 S += Tmp;
272 Tmp.clear();
273 }
274
275 if (T->isVariadic()) {
276 if (T->getNumArgs())
277 S += ", ";
278 S += "...";
279 } else if (T->getNumArgs() == 0 && !Policy.LangOpts.CPlusPlus) {
280 // Do not emit int() if we have a proto, emit 'int(void)'.
281 S += "void";
282 }
283
284 S += ")";
Douglas Gregor0ae7b3f2009-12-08 17:45:32 +0000285
Rafael Espindola264ba482010-03-30 20:24:48 +0000286 FunctionType::ExtInfo Info = T->getExtInfo();
287 switch(Info.getCC()) {
John McCallf82b4e82010-02-04 05:44:44 +0000288 case CC_Default:
289 default: break;
290 case CC_C:
291 S += " __attribute__((cdecl))";
292 break;
293 case CC_X86StdCall:
294 S += " __attribute__((stdcall))";
295 break;
296 case CC_X86FastCall:
297 S += " __attribute__((fastcall))";
298 break;
Douglas Gregorf813a2c2010-05-18 16:57:00 +0000299 case CC_X86ThisCall:
300 S += " __attribute__((thiscall))";
301 break;
Dawn Perchik52fc3142010-09-03 01:29:35 +0000302 case CC_X86Pascal:
303 S += " __attribute__((pascal))";
304 break;
John McCallf82b4e82010-02-04 05:44:44 +0000305 }
Rafael Espindola264ba482010-03-30 20:24:48 +0000306 if (Info.getNoReturn())
Douglas Gregor48026d22010-01-11 18:40:55 +0000307 S += " __attribute__((noreturn))";
Rafael Espindola425ef722010-03-30 22:15:11 +0000308 if (Info.getRegParm())
309 S += " __attribute__((regparm (" +
310 llvm::utostr_32(Info.getRegParm()) + ")))";
Douglas Gregor48026d22010-01-11 18:40:55 +0000311
Douglas Gregor0ae7b3f2009-12-08 17:45:32 +0000312 if (T->hasExceptionSpec()) {
313 S += " throw(";
314 if (T->hasAnyExceptionSpec())
315 S += "...";
316 else
317 for (unsigned I = 0, N = T->getNumExceptions(); I != N; ++I) {
318 if (I)
319 S += ", ";
320
321 std::string ExceptionType;
322 Print(T->getExceptionType(I), ExceptionType);
323 S += ExceptionType;
324 }
325 S += ")";
326 }
327
Douglas Gregor48026d22010-01-11 18:40:55 +0000328 AppendTypeQualList(S, T->getTypeQuals());
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000329
Douglas Gregor48026d22010-01-11 18:40:55 +0000330 Print(T->getResultType(), S);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000331}
332
333void TypePrinter::PrintFunctionNoProto(const FunctionNoProtoType *T,
334 std::string &S) {
335 // If needed for precedence reasons, wrap the inner part in grouping parens.
336 if (!S.empty())
337 S = "(" + S + ")";
338
339 S += "()";
340 if (T->getNoReturnAttr())
341 S += " __attribute__((noreturn))";
342 Print(T->getResultType(), S);
343}
344
John McCall3cb0ebd2010-03-10 03:28:59 +0000345static void PrintTypeSpec(const NamedDecl *D, std::string &S) {
346 IdentifierInfo *II = D->getIdentifier();
John McCalled976492009-12-04 22:46:56 +0000347 if (S.empty())
348 S = II->getName().str();
349 else
350 S = II->getName().str() + ' ' + S;
351}
352
John McCall3cb0ebd2010-03-10 03:28:59 +0000353void TypePrinter::PrintUnresolvedUsing(const UnresolvedUsingType *T,
354 std::string &S) {
355 PrintTypeSpec(T->getDecl(), S);
356}
357
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000358void TypePrinter::PrintTypedef(const TypedefType *T, std::string &S) {
John McCall3cb0ebd2010-03-10 03:28:59 +0000359 PrintTypeSpec(T->getDecl(), S);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000360}
361
362void TypePrinter::PrintTypeOfExpr(const TypeOfExprType *T, std::string &S) {
363 if (!S.empty()) // Prefix the basic type, e.g. 'typeof(e) X'.
364 S = ' ' + S;
365 std::string Str;
366 llvm::raw_string_ostream s(Str);
367 T->getUnderlyingExpr()->printPretty(s, 0, Policy);
368 S = "typeof " + s.str() + S;
369}
370
371void TypePrinter::PrintTypeOf(const TypeOfType *T, std::string &S) {
372 if (!S.empty()) // Prefix the basic type, e.g. 'typeof(t) X'.
373 S = ' ' + S;
374 std::string Tmp;
375 Print(T->getUnderlyingType(), Tmp);
376 S = "typeof(" + Tmp + ")" + S;
377}
378
379void TypePrinter::PrintDecltype(const DecltypeType *T, std::string &S) {
380 if (!S.empty()) // Prefix the basic type, e.g. 'decltype(t) X'.
381 S = ' ' + S;
382 std::string Str;
383 llvm::raw_string_ostream s(Str);
384 T->getUnderlyingExpr()->printPretty(s, 0, Policy);
385 S = "decltype(" + s.str() + ")" + S;
386}
387
John McCall7c2342d2010-03-10 11:27:22 +0000388/// Appends the given scope to the end of a string.
389void TypePrinter::AppendScope(DeclContext *DC, std::string &Buffer) {
390 if (DC->isTranslationUnit()) return;
391 AppendScope(DC->getParent(), Buffer);
392
393 unsigned OldSize = Buffer.size();
394
395 if (NamespaceDecl *NS = dyn_cast<NamespaceDecl>(DC)) {
396 if (NS->getIdentifier())
397 Buffer += NS->getNameAsString();
398 else
399 Buffer += "<anonymous>";
400 } else if (ClassTemplateSpecializationDecl *Spec
401 = dyn_cast<ClassTemplateSpecializationDecl>(DC)) {
402 const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs();
403 std::string TemplateArgsStr
404 = TemplateSpecializationType::PrintTemplateArgumentList(
405 TemplateArgs.getFlatArgumentList(),
406 TemplateArgs.flat_size(),
407 Policy);
408 Buffer += Spec->getIdentifier()->getName();
409 Buffer += TemplateArgsStr;
410 } else if (TagDecl *Tag = dyn_cast<TagDecl>(DC)) {
411 if (TypedefDecl *Typedef = Tag->getTypedefForAnonDecl())
412 Buffer += Typedef->getIdentifier()->getName();
413 else if (Tag->getIdentifier())
414 Buffer += Tag->getIdentifier()->getName();
415 }
416
417 if (Buffer.size() != OldSize)
418 Buffer += "::";
419}
420
John McCall3cb0ebd2010-03-10 03:28:59 +0000421void TypePrinter::PrintTag(TagDecl *D, std::string &InnerString) {
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000422 if (Policy.SuppressTag)
423 return;
John McCall7c2342d2010-03-10 11:27:22 +0000424
425 std::string Buffer;
John McCall73061d02010-03-19 07:56:44 +0000426 bool HasKindDecoration = false;
John McCall7c2342d2010-03-10 11:27:22 +0000427
428 // We don't print tags unless this is an elaborated type.
429 // In C, we just assume every RecordType is an elaborated type.
430 if (!Policy.LangOpts.CPlusPlus && !D->getTypedefForAnonDecl()) {
John McCall73061d02010-03-19 07:56:44 +0000431 HasKindDecoration = true;
John McCall7c2342d2010-03-10 11:27:22 +0000432 Buffer += D->getKindName();
433 Buffer += ' ';
434 }
435
Chris Lattnerc7acc662010-08-28 16:26:18 +0000436 // Compute the full nested-name-specifier for this type.
437 // In C, this will always be empty except when the type
438 // being printed is anonymous within other Record.
John McCall7c2342d2010-03-10 11:27:22 +0000439 if (!Policy.SuppressScope)
John McCall7c2342d2010-03-10 11:27:22 +0000440 AppendScope(D->getDeclContext(), Buffer);
441
John McCall3cb0ebd2010-03-10 03:28:59 +0000442 if (const IdentifierInfo *II = D->getIdentifier())
John McCall73061d02010-03-19 07:56:44 +0000443 Buffer += II->getNameStart();
John McCall3cb0ebd2010-03-10 03:28:59 +0000444 else if (TypedefDecl *Typedef = D->getTypedefForAnonDecl()) {
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000445 assert(Typedef->getIdentifier() && "Typedef without identifier?");
John McCall73061d02010-03-19 07:56:44 +0000446 Buffer += Typedef->getIdentifier()->getNameStart();
447 } else {
448 // Make an unambiguous representation for anonymous types, e.g.
449 // <anonymous enum at /usr/include/string.h:120:9>
450 llvm::raw_string_ostream OS(Buffer);
451 OS << "<anonymous";
452
Douglas Gregor84139d62010-04-05 21:25:31 +0000453 if (Policy.AnonymousTagLocations) {
454 // Suppress the redundant tag keyword if we just printed one.
455 // We don't have to worry about ElaboratedTypes here because you can't
456 // refer to an anonymous type with one.
457 if (!HasKindDecoration)
458 OS << " " << D->getKindName();
John McCall73061d02010-03-19 07:56:44 +0000459
Douglas Gregor16834e82010-05-28 21:47:04 +0000460 if (D->getLocation().isValid()) {
461 PresumedLoc PLoc = D->getASTContext().getSourceManager().getPresumedLoc(
462 D->getLocation());
463 OS << " at " << PLoc.getFilename()
464 << ':' << PLoc.getLine()
465 << ':' << PLoc.getColumn();
466 }
Douglas Gregor84139d62010-04-05 21:25:31 +0000467 }
468
469 OS << '>';
John McCall73061d02010-03-19 07:56:44 +0000470 }
John McCall7c2342d2010-03-10 11:27:22 +0000471
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000472 // If this is a class template specialization, print the template
473 // arguments.
474 if (ClassTemplateSpecializationDecl *Spec
John McCall7c2342d2010-03-10 11:27:22 +0000475 = dyn_cast<ClassTemplateSpecializationDecl>(D)) {
John McCall3cb0ebd2010-03-10 03:28:59 +0000476 const TemplateArgument *Args;
477 unsigned NumArgs;
478 if (TypeSourceInfo *TAW = Spec->getTypeAsWritten()) {
479 const TemplateSpecializationType *TST =
480 cast<TemplateSpecializationType>(TAW->getType());
481 Args = TST->getArgs();
482 NumArgs = TST->getNumArgs();
483 } else {
484 const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs();
485 Args = TemplateArgs.getFlatArgumentList();
486 NumArgs = TemplateArgs.flat_size();
487 }
John McCall7c2342d2010-03-10 11:27:22 +0000488 Buffer += TemplateSpecializationType::PrintTemplateArgumentList(Args,
489 NumArgs,
490 Policy);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000491 }
John McCall7c2342d2010-03-10 11:27:22 +0000492
493 if (!InnerString.empty()) {
494 Buffer += ' ';
495 Buffer += InnerString;
496 }
497
498 std::swap(Buffer, InnerString);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000499}
500
501void TypePrinter::PrintRecord(const RecordType *T, std::string &S) {
John McCall3cb0ebd2010-03-10 03:28:59 +0000502 PrintTag(T->getDecl(), S);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000503}
504
505void TypePrinter::PrintEnum(const EnumType *T, std::string &S) {
John McCall3cb0ebd2010-03-10 03:28:59 +0000506 PrintTag(T->getDecl(), S);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000507}
508
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000509void TypePrinter::PrintTemplateTypeParm(const TemplateTypeParmType *T,
510 std::string &S) {
511 if (!S.empty()) // Prefix the basic type, e.g. 'parmname X'.
512 S = ' ' + S;
Douglas Gregorefed5c82010-06-16 15:23:05 +0000513
514 if (!T->getName())
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000515 S = "type-parameter-" + llvm::utostr_32(T->getDepth()) + '-' +
516 llvm::utostr_32(T->getIndex()) + S;
Douglas Gregorefed5c82010-06-16 15:23:05 +0000517 else
518 S = T->getName()->getName().str() + S;
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000519}
520
521void TypePrinter::PrintSubstTemplateTypeParm(const SubstTemplateTypeParmType *T,
522 std::string &S) {
523 Print(T->getReplacementType(), S);
524}
525
526void TypePrinter::PrintTemplateSpecialization(
527 const TemplateSpecializationType *T,
528 std::string &S) {
529 std::string SpecString;
530
531 {
532 llvm::raw_string_ostream OS(SpecString);
533 T->getTemplateName().print(OS, Policy);
534 }
535
536 SpecString += TemplateSpecializationType::PrintTemplateArgumentList(
537 T->getArgs(),
538 T->getNumArgs(),
539 Policy);
540 if (S.empty())
541 S.swap(SpecString);
542 else
543 S = SpecString + ' ' + S;
544}
545
John McCall3cb0ebd2010-03-10 03:28:59 +0000546void TypePrinter::PrintInjectedClassName(const InjectedClassNameType *T,
547 std::string &S) {
John McCall31f17ec2010-04-27 00:57:59 +0000548 PrintTemplateSpecialization(T->getInjectedTST(), S);
John McCall3cb0ebd2010-03-10 03:28:59 +0000549}
550
Abramo Bagnara465d41b2010-05-11 21:36:43 +0000551void TypePrinter::PrintElaborated(const ElaboratedType *T, std::string &S) {
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000552 std::string MyString;
553
554 {
555 llvm::raw_string_ostream OS(MyString);
Abramo Bagnara465d41b2010-05-11 21:36:43 +0000556 OS << TypeWithKeyword::getKeywordName(T->getKeyword());
557 if (T->getKeyword() != ETK_None)
558 OS << " ";
559 NestedNameSpecifier* Qualifier = T->getQualifier();
560 if (Qualifier)
561 Qualifier->print(OS, Policy);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000562 }
563
564 std::string TypeStr;
565 PrintingPolicy InnerPolicy(Policy);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000566 InnerPolicy.SuppressScope = true;
567 TypePrinter(InnerPolicy).Print(T->getNamedType(), TypeStr);
568
569 MyString += TypeStr;
570 if (S.empty())
571 S.swap(MyString);
572 else
573 S = MyString + ' ' + S;
574}
575
Douglas Gregor4714c122010-03-31 17:34:00 +0000576void TypePrinter::PrintDependentName(const DependentNameType *T, std::string &S) {
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000577 std::string MyString;
578
579 {
580 llvm::raw_string_ostream OS(MyString);
Abramo Bagnara465d41b2010-05-11 21:36:43 +0000581 OS << TypeWithKeyword::getKeywordName(T->getKeyword());
582 if (T->getKeyword() != ETK_None)
583 OS << " ";
Douglas Gregor4a2023f2010-03-31 20:19:30 +0000584
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000585 T->getQualifier()->print(OS, Policy);
586
John McCall33500952010-06-11 00:33:02 +0000587 OS << T->getIdentifier()->getName();
588 }
589
590 if (S.empty())
591 S.swap(MyString);
592 else
593 S = MyString + ' ' + S;
594}
595
596void TypePrinter::PrintDependentTemplateSpecialization(
597 const DependentTemplateSpecializationType *T, std::string &S) {
598 std::string MyString;
599 {
600 llvm::raw_string_ostream OS(MyString);
601
602 OS << TypeWithKeyword::getKeywordName(T->getKeyword());
603 if (T->getKeyword() != ETK_None)
604 OS << " ";
605
606 T->getQualifier()->print(OS, Policy);
607 OS << T->getIdentifier()->getName();
608 OS << TemplateSpecializationType::PrintTemplateArgumentList(
609 T->getArgs(),
610 T->getNumArgs(),
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000611 Policy);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000612 }
613
614 if (S.empty())
615 S.swap(MyString);
616 else
617 S = MyString + ' ' + S;
618}
619
620void TypePrinter::PrintObjCInterface(const ObjCInterfaceType *T,
621 std::string &S) {
622 if (!S.empty()) // Prefix the basic type, e.g. 'typedefname X'.
623 S = ' ' + S;
John McCallc12c5bb2010-05-15 11:32:37 +0000624
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000625 std::string ObjCQIString = T->getDecl()->getNameAsString();
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000626 S = ObjCQIString + S;
627}
628
John McCallc12c5bb2010-05-15 11:32:37 +0000629void TypePrinter::PrintObjCObject(const ObjCObjectType *T,
630 std::string &S) {
631 if (T->qual_empty())
632 return Print(T->getBaseType(), S);
633
634 std::string tmp;
635 Print(T->getBaseType(), tmp);
636 tmp += '<';
637 bool isFirst = true;
638 for (ObjCObjectType::qual_iterator
639 I = T->qual_begin(), E = T->qual_end(); I != E; ++I) {
640 if (isFirst)
641 isFirst = false;
642 else
643 tmp += ',';
644 tmp += (*I)->getNameAsString();
645 }
646 tmp += '>';
647
648 if (!S.empty()) {
649 tmp += ' ';
650 tmp += S;
651 }
652 std::swap(tmp, S);
653}
654
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000655void TypePrinter::PrintObjCObjectPointer(const ObjCObjectPointerType *T,
656 std::string &S) {
657 std::string ObjCQIString;
658
659 if (T->isObjCIdType() || T->isObjCQualifiedIdType())
660 ObjCQIString = "id";
661 else if (T->isObjCClassType() || T->isObjCQualifiedClassType())
662 ObjCQIString = "Class";
Fariborz Jahanian13dcd002009-11-21 19:53:08 +0000663 else if (T->isObjCSelType())
664 ObjCQIString = "SEL";
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000665 else
666 ObjCQIString = T->getInterfaceDecl()->getNameAsString();
667
668 if (!T->qual_empty()) {
669 ObjCQIString += '<';
670 for (ObjCObjectPointerType::qual_iterator I = T->qual_begin(),
671 E = T->qual_end();
672 I != E; ++I) {
673 ObjCQIString += (*I)->getNameAsString();
674 if (I+1 != E)
675 ObjCQIString += ',';
676 }
677 ObjCQIString += '>';
678 }
679
Douglas Gregora4923eb2009-11-16 21:35:15 +0000680 T->getPointeeType().getLocalQualifiers().getAsStringInternal(ObjCQIString,
681 Policy);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000682
683 if (!T->isObjCIdType() && !T->isObjCQualifiedIdType())
684 ObjCQIString += " *"; // Don't forget the implicit pointer.
685 else if (!S.empty()) // Prefix the basic type, e.g. 'typedefname X'.
686 S = ' ' + S;
687
688 S = ObjCQIString + S;
689}
690
691static void PrintTemplateArgument(std::string &Buffer,
692 const TemplateArgument &Arg,
693 const PrintingPolicy &Policy) {
694 switch (Arg.getKind()) {
695 case TemplateArgument::Null:
696 assert(false && "Null template argument");
697 break;
698
699 case TemplateArgument::Type:
700 Arg.getAsType().getAsStringInternal(Buffer, Policy);
701 break;
702
703 case TemplateArgument::Declaration:
704 Buffer = cast<NamedDecl>(Arg.getAsDecl())->getNameAsString();
705 break;
706
Douglas Gregor788cd062009-11-11 01:00:40 +0000707 case TemplateArgument::Template: {
708 llvm::raw_string_ostream s(Buffer);
709 Arg.getAsTemplate().print(s, Policy);
Douglas Gregorfb898e12009-11-12 16:20:59 +0000710 break;
Douglas Gregor788cd062009-11-11 01:00:40 +0000711 }
712
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000713 case TemplateArgument::Integral:
714 Buffer = Arg.getAsIntegral()->toString(10, true);
715 break;
716
717 case TemplateArgument::Expression: {
718 llvm::raw_string_ostream s(Buffer);
719 Arg.getAsExpr()->printPretty(s, 0, Policy);
720 break;
721 }
722
723 case TemplateArgument::Pack:
724 assert(0 && "FIXME: Implement!");
725 break;
726 }
727}
728
John McCalld5532b62009-11-23 01:53:49 +0000729std::string TemplateSpecializationType::
730 PrintTemplateArgumentList(const TemplateArgumentListInfo &Args,
731 const PrintingPolicy &Policy) {
732 return PrintTemplateArgumentList(Args.getArgumentArray(),
733 Args.size(),
734 Policy);
735}
736
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000737std::string
738TemplateSpecializationType::PrintTemplateArgumentList(
739 const TemplateArgument *Args,
740 unsigned NumArgs,
741 const PrintingPolicy &Policy) {
742 std::string SpecString;
743 SpecString += '<';
744 for (unsigned Arg = 0; Arg < NumArgs; ++Arg) {
745 if (Arg)
746 SpecString += ", ";
747
748 // Print the argument into a string.
749 std::string ArgString;
750 PrintTemplateArgument(ArgString, Args[Arg], Policy);
751
752 // If this is the first argument and its string representation
753 // begins with the global scope specifier ('::foo'), add a space
754 // to avoid printing the diagraph '<:'.
755 if (!Arg && !ArgString.empty() && ArgString[0] == ':')
756 SpecString += ' ';
757
758 SpecString += ArgString;
759 }
760
761 // If the last character of our string is '>', add another space to
762 // keep the two '>''s separate tokens. We don't *have* to do this in
763 // C++0x, but it's still good hygiene.
764 if (SpecString[SpecString.size() - 1] == '>')
765 SpecString += ' ';
766
767 SpecString += '>';
768
769 return SpecString;
770}
771
772// Sadly, repeat all that with TemplateArgLoc.
773std::string TemplateSpecializationType::
774PrintTemplateArgumentList(const TemplateArgumentLoc *Args, unsigned NumArgs,
775 const PrintingPolicy &Policy) {
776 std::string SpecString;
777 SpecString += '<';
778 for (unsigned Arg = 0; Arg < NumArgs; ++Arg) {
779 if (Arg)
780 SpecString += ", ";
781
782 // Print the argument into a string.
783 std::string ArgString;
784 PrintTemplateArgument(ArgString, Args[Arg].getArgument(), Policy);
785
786 // If this is the first argument and its string representation
787 // begins with the global scope specifier ('::foo'), add a space
788 // to avoid printing the diagraph '<:'.
789 if (!Arg && !ArgString.empty() && ArgString[0] == ':')
790 SpecString += ' ';
791
792 SpecString += ArgString;
793 }
794
795 // If the last character of our string is '>', add another space to
796 // keep the two '>''s separate tokens. We don't *have* to do this in
797 // C++0x, but it's still good hygiene.
798 if (SpecString[SpecString.size() - 1] == '>')
799 SpecString += ' ';
800
801 SpecString += '>';
802
803 return SpecString;
804}
805
806void QualType::dump(const char *msg) const {
807 std::string R = "identifier";
808 LangOptions LO;
809 getAsStringInternal(R, PrintingPolicy(LO));
810 if (msg)
Daniel Dunbare7cb7e42009-12-03 09:14:02 +0000811 llvm::errs() << msg << ": ";
812 llvm::errs() << R << "\n";
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000813}
814void QualType::dump() const {
815 dump("");
816}
817
818void Type::dump() const {
819 QualType(this, 0).dump();
820}
821
822std::string Qualifiers::getAsString() const {
823 LangOptions LO;
824 return getAsString(PrintingPolicy(LO));
825}
826
827// Appends qualifiers to the given string, separated by spaces. Will
828// prefix a space if the string is non-empty. Will not append a final
829// space.
830void Qualifiers::getAsStringInternal(std::string &S,
831 const PrintingPolicy&) const {
832 AppendTypeQualList(S, getCVRQualifiers());
833 if (unsigned AddressSpace = getAddressSpace()) {
834 if (!S.empty()) S += ' ';
835 S += "__attribute__((address_space(";
836 S += llvm::utostr_32(AddressSpace);
837 S += ")))";
838 }
839 if (Qualifiers::GC GCAttrType = getObjCGCAttr()) {
840 if (!S.empty()) S += ' ';
841 S += "__attribute__((objc_gc(";
842 if (GCAttrType == Qualifiers::Weak)
843 S += "weak";
844 else
845 S += "strong";
846 S += ")))";
847 }
848}
849
850std::string QualType::getAsString() const {
851 std::string S;
852 LangOptions LO;
853 getAsStringInternal(S, PrintingPolicy(LO));
854 return S;
855}
856
857void QualType::getAsStringInternal(std::string &S,
858 const PrintingPolicy &Policy) const {
859 TypePrinter Printer(Policy);
860 Printer.Print(*this, S);
861}