blob: b8ce77b7f8fe102954647e1d6364bcaa24727fc7 [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();
Chris Lattner58f9e132010-09-05 00:04:01 +000069
70 // CanPrefixQualifiers - We prefer to print type qualifiers before the type,
71 // so that we get "const int" instead of "int const", but we can't do this if
72 // the type is complex. For example if the type is "int*", we *must* print
73 // "int * const", printing "const int *" is different. Only do this when the
74 // type expands to a simple string.
Chris Lattner66cf2d12010-09-05 00:07:29 +000075 bool CanPrefixQualifiers =
Chris Lattner219b9e42010-09-05 00:22:25 +000076 isa<BuiltinType>(T) || isa<TypedefType>(T) || isa<TagType>(T) ||
Chris Lattner78643b02010-09-05 00:36:44 +000077 isa<ComplexType>(T) || isa<TemplateSpecializationType>(T) ||
78 isa<ObjCObjectType>(T) || isa<ObjCInterfaceType>(T) ||
79 T->isObjCIdType() || T->isObjCQualifiedIdType();
Chris Lattner58f9e132010-09-05 00:04:01 +000080
81 if (!CanPrefixQualifiers && !Quals.empty()) {
Douglas Gregorfee8a3c2009-11-10 00:39:07 +000082 std::string TQS;
83 Quals.getAsStringInternal(TQS, Policy);
84
85 if (!S.empty()) {
86 TQS += ' ';
87 TQS += S;
88 }
89 std::swap(S, TQS);
90 }
91
92 switch (T->getTypeClass()) {
93#define ABSTRACT_TYPE(CLASS, PARENT)
94#define TYPE(CLASS, PARENT) case Type::CLASS: \
95 Print##CLASS(cast<CLASS##Type>(T.getTypePtr()), S); \
96 break;
97#include "clang/AST/TypeNodes.def"
98 }
Chris Lattner58f9e132010-09-05 00:04:01 +000099
100 // If we're adding the qualifiers as a prefix, do it now.
101 if (CanPrefixQualifiers && !Quals.empty()) {
102 std::string TQS;
103 Quals.getAsStringInternal(TQS, Policy);
104
105 if (!S.empty()) {
106 TQS += ' ';
107 TQS += S;
108 }
109 std::swap(S, TQS);
110 }
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000111}
112
113void TypePrinter::PrintBuiltin(const BuiltinType *T, std::string &S) {
114 if (S.empty()) {
115 S = T->getName(Policy.LangOpts);
116 } else {
117 // Prefix the basic type, e.g. 'int X'.
Chris Lattner59742de2010-09-04 23:43:40 +0000118 S = ' ' + S;
119 S = T->getName(Policy.LangOpts) + S;
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000120 }
121}
122
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000123void TypePrinter::PrintComplex(const ComplexType *T, std::string &S) {
124 Print(T->getElementType(), S);
125 S = "_Complex " + S;
126}
127
128void TypePrinter::PrintPointer(const PointerType *T, std::string &S) {
129 S = '*' + S;
130
131 // Handle things like 'int (*A)[4];' correctly.
132 // FIXME: this should include vectors, but vectors use attributes I guess.
133 if (isa<ArrayType>(T->getPointeeType()))
134 S = '(' + S + ')';
135
136 Print(T->getPointeeType(), S);
137}
138
139void TypePrinter::PrintBlockPointer(const BlockPointerType *T, std::string &S) {
140 S = '^' + S;
141 Print(T->getPointeeType(), S);
142}
143
144void TypePrinter::PrintLValueReference(const LValueReferenceType *T,
145 std::string &S) {
146 S = '&' + S;
147
148 // Handle things like 'int (&A)[4];' correctly.
149 // FIXME: this should include vectors, but vectors use attributes I guess.
150 if (isa<ArrayType>(T->getPointeeTypeAsWritten()))
151 S = '(' + S + ')';
152
153 Print(T->getPointeeTypeAsWritten(), S);
154}
155
156void TypePrinter::PrintRValueReference(const RValueReferenceType *T,
157 std::string &S) {
158 S = "&&" + S;
159
160 // Handle things like 'int (&&A)[4];' correctly.
161 // FIXME: this should include vectors, but vectors use attributes I guess.
162 if (isa<ArrayType>(T->getPointeeTypeAsWritten()))
163 S = '(' + S + ')';
164
165 Print(T->getPointeeTypeAsWritten(), S);
166}
167
168void TypePrinter::PrintMemberPointer(const MemberPointerType *T,
169 std::string &S) {
170 std::string C;
171 Print(QualType(T->getClass(), 0), C);
172 C += "::*";
173 S = C + S;
174
175 // Handle things like 'int (Cls::*A)[4];' correctly.
176 // FIXME: this should include vectors, but vectors use attributes I guess.
177 if (isa<ArrayType>(T->getPointeeType()))
178 S = '(' + S + ')';
179
180 Print(T->getPointeeType(), S);
181}
182
183void TypePrinter::PrintConstantArray(const ConstantArrayType *T,
184 std::string &S) {
185 S += '[';
186 S += llvm::utostr(T->getSize().getZExtValue());
187 S += ']';
188
189 Print(T->getElementType(), S);
190}
191
192void TypePrinter::PrintIncompleteArray(const IncompleteArrayType *T,
193 std::string &S) {
194 S += "[]";
195 Print(T->getElementType(), S);
196}
197
198void TypePrinter::PrintVariableArray(const VariableArrayType *T,
199 std::string &S) {
200 S += '[';
201
202 if (T->getIndexTypeQualifiers().hasQualifiers()) {
203 AppendTypeQualList(S, T->getIndexTypeCVRQualifiers());
204 S += ' ';
205 }
206
207 if (T->getSizeModifier() == VariableArrayType::Static)
208 S += "static";
209 else if (T->getSizeModifier() == VariableArrayType::Star)
210 S += '*';
211
212 if (T->getSizeExpr()) {
213 std::string SStr;
214 llvm::raw_string_ostream s(SStr);
215 T->getSizeExpr()->printPretty(s, 0, Policy);
216 S += s.str();
217 }
218 S += ']';
219
220 Print(T->getElementType(), S);
221}
222
223void TypePrinter::PrintDependentSizedArray(const DependentSizedArrayType *T,
224 std::string &S) {
225 S += '[';
226
227 if (T->getSizeExpr()) {
228 std::string SStr;
229 llvm::raw_string_ostream s(SStr);
230 T->getSizeExpr()->printPretty(s, 0, Policy);
231 S += s.str();
232 }
233 S += ']';
234
235 Print(T->getElementType(), S);
236}
237
238void TypePrinter::PrintDependentSizedExtVector(
239 const DependentSizedExtVectorType *T,
240 std::string &S) {
241 Print(T->getElementType(), S);
242
243 S += " __attribute__((ext_vector_type(";
244 if (T->getSizeExpr()) {
245 std::string SStr;
246 llvm::raw_string_ostream s(SStr);
247 T->getSizeExpr()->printPretty(s, 0, Policy);
248 S += s.str();
249 }
250 S += ")))";
251}
252
253void TypePrinter::PrintVector(const VectorType *T, std::string &S) {
Chris Lattner788b0fd2010-06-23 06:00:24 +0000254 if (T->getAltiVecSpecific() != VectorType::NotAltiVec) {
255 if (T->getAltiVecSpecific() == VectorType::Pixel)
John Thompson82287d12010-02-05 00:12:22 +0000256 S = "__vector __pixel " + S;
257 else {
258 Print(T->getElementType(), S);
Chris Lattner788b0fd2010-06-23 06:00:24 +0000259 S = ((T->getAltiVecSpecific() == VectorType::Bool)
260 ? "__vector __bool " : "__vector ") + S;
John Thompson82287d12010-02-05 00:12:22 +0000261 }
262 } else {
263 // FIXME: We prefer to print the size directly here, but have no way
264 // to get the size of the type.
265 Print(T->getElementType(), S);
266 std::string V = "__attribute__((__vector_size__(";
267 V += llvm::utostr_32(T->getNumElements()); // convert back to bytes.
268 std::string ET;
269 Print(T->getElementType(), ET);
270 V += " * sizeof(" + ET + ")))) ";
271 S = V + S;
272 }
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000273}
274
275void TypePrinter::PrintExtVector(const ExtVectorType *T, std::string &S) {
276 S += " __attribute__((ext_vector_type(";
277 S += llvm::utostr_32(T->getNumElements());
278 S += ")))";
279 Print(T->getElementType(), S);
280}
281
282void TypePrinter::PrintFunctionProto(const FunctionProtoType *T,
283 std::string &S) {
284 // If needed for precedence reasons, wrap the inner part in grouping parens.
285 if (!S.empty())
286 S = "(" + S + ")";
287
288 S += "(";
289 std::string Tmp;
290 PrintingPolicy ParamPolicy(Policy);
291 ParamPolicy.SuppressSpecifiers = false;
292 for (unsigned i = 0, e = T->getNumArgs(); i != e; ++i) {
293 if (i) S += ", ";
294 Print(T->getArgType(i), Tmp);
295 S += Tmp;
296 Tmp.clear();
297 }
298
299 if (T->isVariadic()) {
300 if (T->getNumArgs())
301 S += ", ";
302 S += "...";
303 } else if (T->getNumArgs() == 0 && !Policy.LangOpts.CPlusPlus) {
304 // Do not emit int() if we have a proto, emit 'int(void)'.
305 S += "void";
306 }
307
308 S += ")";
Douglas Gregor0ae7b3f2009-12-08 17:45:32 +0000309
Rafael Espindola264ba482010-03-30 20:24:48 +0000310 FunctionType::ExtInfo Info = T->getExtInfo();
311 switch(Info.getCC()) {
John McCallf82b4e82010-02-04 05:44:44 +0000312 case CC_Default:
313 default: break;
314 case CC_C:
315 S += " __attribute__((cdecl))";
316 break;
317 case CC_X86StdCall:
318 S += " __attribute__((stdcall))";
319 break;
320 case CC_X86FastCall:
321 S += " __attribute__((fastcall))";
322 break;
Douglas Gregorf813a2c2010-05-18 16:57:00 +0000323 case CC_X86ThisCall:
324 S += " __attribute__((thiscall))";
325 break;
Dawn Perchik52fc3142010-09-03 01:29:35 +0000326 case CC_X86Pascal:
327 S += " __attribute__((pascal))";
328 break;
John McCallf82b4e82010-02-04 05:44:44 +0000329 }
Rafael Espindola264ba482010-03-30 20:24:48 +0000330 if (Info.getNoReturn())
Douglas Gregor48026d22010-01-11 18:40:55 +0000331 S += " __attribute__((noreturn))";
Rafael Espindola425ef722010-03-30 22:15:11 +0000332 if (Info.getRegParm())
333 S += " __attribute__((regparm (" +
334 llvm::utostr_32(Info.getRegParm()) + ")))";
Douglas Gregor48026d22010-01-11 18:40:55 +0000335
Douglas Gregor0ae7b3f2009-12-08 17:45:32 +0000336 if (T->hasExceptionSpec()) {
337 S += " throw(";
338 if (T->hasAnyExceptionSpec())
339 S += "...";
340 else
341 for (unsigned I = 0, N = T->getNumExceptions(); I != N; ++I) {
342 if (I)
343 S += ", ";
344
345 std::string ExceptionType;
346 Print(T->getExceptionType(I), ExceptionType);
347 S += ExceptionType;
348 }
349 S += ")";
350 }
351
Douglas Gregor48026d22010-01-11 18:40:55 +0000352 AppendTypeQualList(S, T->getTypeQuals());
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000353
Douglas Gregor48026d22010-01-11 18:40:55 +0000354 Print(T->getResultType(), S);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000355}
356
357void TypePrinter::PrintFunctionNoProto(const FunctionNoProtoType *T,
358 std::string &S) {
359 // If needed for precedence reasons, wrap the inner part in grouping parens.
360 if (!S.empty())
361 S = "(" + S + ")";
362
363 S += "()";
364 if (T->getNoReturnAttr())
365 S += " __attribute__((noreturn))";
366 Print(T->getResultType(), S);
367}
368
John McCall3cb0ebd2010-03-10 03:28:59 +0000369static void PrintTypeSpec(const NamedDecl *D, std::string &S) {
370 IdentifierInfo *II = D->getIdentifier();
John McCalled976492009-12-04 22:46:56 +0000371 if (S.empty())
372 S = II->getName().str();
373 else
374 S = II->getName().str() + ' ' + S;
375}
376
John McCall3cb0ebd2010-03-10 03:28:59 +0000377void TypePrinter::PrintUnresolvedUsing(const UnresolvedUsingType *T,
378 std::string &S) {
379 PrintTypeSpec(T->getDecl(), S);
380}
381
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000382void TypePrinter::PrintTypedef(const TypedefType *T, std::string &S) {
John McCall3cb0ebd2010-03-10 03:28:59 +0000383 PrintTypeSpec(T->getDecl(), S);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000384}
385
386void TypePrinter::PrintTypeOfExpr(const TypeOfExprType *T, std::string &S) {
387 if (!S.empty()) // Prefix the basic type, e.g. 'typeof(e) X'.
388 S = ' ' + S;
389 std::string Str;
390 llvm::raw_string_ostream s(Str);
391 T->getUnderlyingExpr()->printPretty(s, 0, Policy);
392 S = "typeof " + s.str() + S;
393}
394
395void TypePrinter::PrintTypeOf(const TypeOfType *T, std::string &S) {
396 if (!S.empty()) // Prefix the basic type, e.g. 'typeof(t) X'.
397 S = ' ' + S;
398 std::string Tmp;
399 Print(T->getUnderlyingType(), Tmp);
400 S = "typeof(" + Tmp + ")" + S;
401}
402
403void TypePrinter::PrintDecltype(const DecltypeType *T, std::string &S) {
404 if (!S.empty()) // Prefix the basic type, e.g. 'decltype(t) X'.
405 S = ' ' + S;
406 std::string Str;
407 llvm::raw_string_ostream s(Str);
408 T->getUnderlyingExpr()->printPretty(s, 0, Policy);
409 S = "decltype(" + s.str() + ")" + S;
410}
411
John McCall7c2342d2010-03-10 11:27:22 +0000412/// Appends the given scope to the end of a string.
413void TypePrinter::AppendScope(DeclContext *DC, std::string &Buffer) {
414 if (DC->isTranslationUnit()) return;
415 AppendScope(DC->getParent(), Buffer);
416
417 unsigned OldSize = Buffer.size();
418
419 if (NamespaceDecl *NS = dyn_cast<NamespaceDecl>(DC)) {
420 if (NS->getIdentifier())
421 Buffer += NS->getNameAsString();
422 else
423 Buffer += "<anonymous>";
424 } else if (ClassTemplateSpecializationDecl *Spec
425 = dyn_cast<ClassTemplateSpecializationDecl>(DC)) {
426 const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs();
427 std::string TemplateArgsStr
428 = TemplateSpecializationType::PrintTemplateArgumentList(
429 TemplateArgs.getFlatArgumentList(),
430 TemplateArgs.flat_size(),
431 Policy);
432 Buffer += Spec->getIdentifier()->getName();
433 Buffer += TemplateArgsStr;
434 } else if (TagDecl *Tag = dyn_cast<TagDecl>(DC)) {
435 if (TypedefDecl *Typedef = Tag->getTypedefForAnonDecl())
436 Buffer += Typedef->getIdentifier()->getName();
437 else if (Tag->getIdentifier())
438 Buffer += Tag->getIdentifier()->getName();
439 }
440
441 if (Buffer.size() != OldSize)
442 Buffer += "::";
443}
444
John McCall3cb0ebd2010-03-10 03:28:59 +0000445void TypePrinter::PrintTag(TagDecl *D, std::string &InnerString) {
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000446 if (Policy.SuppressTag)
447 return;
John McCall7c2342d2010-03-10 11:27:22 +0000448
449 std::string Buffer;
John McCall73061d02010-03-19 07:56:44 +0000450 bool HasKindDecoration = false;
John McCall7c2342d2010-03-10 11:27:22 +0000451
452 // We don't print tags unless this is an elaborated type.
453 // In C, we just assume every RecordType is an elaborated type.
454 if (!Policy.LangOpts.CPlusPlus && !D->getTypedefForAnonDecl()) {
John McCall73061d02010-03-19 07:56:44 +0000455 HasKindDecoration = true;
John McCall7c2342d2010-03-10 11:27:22 +0000456 Buffer += D->getKindName();
457 Buffer += ' ';
458 }
459
Chris Lattnerc7acc662010-08-28 16:26:18 +0000460 // Compute the full nested-name-specifier for this type.
461 // In C, this will always be empty except when the type
462 // being printed is anonymous within other Record.
John McCall7c2342d2010-03-10 11:27:22 +0000463 if (!Policy.SuppressScope)
John McCall7c2342d2010-03-10 11:27:22 +0000464 AppendScope(D->getDeclContext(), Buffer);
465
John McCall3cb0ebd2010-03-10 03:28:59 +0000466 if (const IdentifierInfo *II = D->getIdentifier())
John McCall73061d02010-03-19 07:56:44 +0000467 Buffer += II->getNameStart();
John McCall3cb0ebd2010-03-10 03:28:59 +0000468 else if (TypedefDecl *Typedef = D->getTypedefForAnonDecl()) {
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000469 assert(Typedef->getIdentifier() && "Typedef without identifier?");
John McCall73061d02010-03-19 07:56:44 +0000470 Buffer += Typedef->getIdentifier()->getNameStart();
471 } else {
472 // Make an unambiguous representation for anonymous types, e.g.
473 // <anonymous enum at /usr/include/string.h:120:9>
474 llvm::raw_string_ostream OS(Buffer);
475 OS << "<anonymous";
476
Douglas Gregor84139d62010-04-05 21:25:31 +0000477 if (Policy.AnonymousTagLocations) {
478 // Suppress the redundant tag keyword if we just printed one.
479 // We don't have to worry about ElaboratedTypes here because you can't
480 // refer to an anonymous type with one.
481 if (!HasKindDecoration)
482 OS << " " << D->getKindName();
John McCall73061d02010-03-19 07:56:44 +0000483
Douglas Gregor16834e82010-05-28 21:47:04 +0000484 if (D->getLocation().isValid()) {
485 PresumedLoc PLoc = D->getASTContext().getSourceManager().getPresumedLoc(
486 D->getLocation());
487 OS << " at " << PLoc.getFilename()
488 << ':' << PLoc.getLine()
489 << ':' << PLoc.getColumn();
490 }
Douglas Gregor84139d62010-04-05 21:25:31 +0000491 }
492
493 OS << '>';
John McCall73061d02010-03-19 07:56:44 +0000494 }
John McCall7c2342d2010-03-10 11:27:22 +0000495
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000496 // If this is a class template specialization, print the template
497 // arguments.
498 if (ClassTemplateSpecializationDecl *Spec
John McCall7c2342d2010-03-10 11:27:22 +0000499 = dyn_cast<ClassTemplateSpecializationDecl>(D)) {
John McCall3cb0ebd2010-03-10 03:28:59 +0000500 const TemplateArgument *Args;
501 unsigned NumArgs;
502 if (TypeSourceInfo *TAW = Spec->getTypeAsWritten()) {
503 const TemplateSpecializationType *TST =
504 cast<TemplateSpecializationType>(TAW->getType());
505 Args = TST->getArgs();
506 NumArgs = TST->getNumArgs();
507 } else {
508 const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs();
509 Args = TemplateArgs.getFlatArgumentList();
510 NumArgs = TemplateArgs.flat_size();
511 }
John McCall7c2342d2010-03-10 11:27:22 +0000512 Buffer += TemplateSpecializationType::PrintTemplateArgumentList(Args,
513 NumArgs,
514 Policy);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000515 }
John McCall7c2342d2010-03-10 11:27:22 +0000516
517 if (!InnerString.empty()) {
518 Buffer += ' ';
519 Buffer += InnerString;
520 }
521
522 std::swap(Buffer, InnerString);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000523}
524
525void TypePrinter::PrintRecord(const RecordType *T, std::string &S) {
John McCall3cb0ebd2010-03-10 03:28:59 +0000526 PrintTag(T->getDecl(), S);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000527}
528
529void TypePrinter::PrintEnum(const EnumType *T, std::string &S) {
John McCall3cb0ebd2010-03-10 03:28:59 +0000530 PrintTag(T->getDecl(), S);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000531}
532
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000533void TypePrinter::PrintTemplateTypeParm(const TemplateTypeParmType *T,
534 std::string &S) {
535 if (!S.empty()) // Prefix the basic type, e.g. 'parmname X'.
536 S = ' ' + S;
Douglas Gregorefed5c82010-06-16 15:23:05 +0000537
538 if (!T->getName())
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000539 S = "type-parameter-" + llvm::utostr_32(T->getDepth()) + '-' +
540 llvm::utostr_32(T->getIndex()) + S;
Douglas Gregorefed5c82010-06-16 15:23:05 +0000541 else
542 S = T->getName()->getName().str() + S;
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000543}
544
545void TypePrinter::PrintSubstTemplateTypeParm(const SubstTemplateTypeParmType *T,
546 std::string &S) {
547 Print(T->getReplacementType(), S);
548}
549
550void TypePrinter::PrintTemplateSpecialization(
551 const TemplateSpecializationType *T,
552 std::string &S) {
553 std::string SpecString;
554
555 {
556 llvm::raw_string_ostream OS(SpecString);
557 T->getTemplateName().print(OS, Policy);
558 }
559
560 SpecString += TemplateSpecializationType::PrintTemplateArgumentList(
561 T->getArgs(),
562 T->getNumArgs(),
563 Policy);
564 if (S.empty())
565 S.swap(SpecString);
566 else
567 S = SpecString + ' ' + S;
568}
569
John McCall3cb0ebd2010-03-10 03:28:59 +0000570void TypePrinter::PrintInjectedClassName(const InjectedClassNameType *T,
571 std::string &S) {
John McCall31f17ec2010-04-27 00:57:59 +0000572 PrintTemplateSpecialization(T->getInjectedTST(), S);
John McCall3cb0ebd2010-03-10 03:28:59 +0000573}
574
Abramo Bagnara465d41b2010-05-11 21:36:43 +0000575void TypePrinter::PrintElaborated(const ElaboratedType *T, std::string &S) {
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000576 std::string MyString;
577
578 {
579 llvm::raw_string_ostream OS(MyString);
Abramo Bagnara465d41b2010-05-11 21:36:43 +0000580 OS << TypeWithKeyword::getKeywordName(T->getKeyword());
581 if (T->getKeyword() != ETK_None)
582 OS << " ";
583 NestedNameSpecifier* Qualifier = T->getQualifier();
584 if (Qualifier)
585 Qualifier->print(OS, Policy);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000586 }
587
588 std::string TypeStr;
589 PrintingPolicy InnerPolicy(Policy);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000590 InnerPolicy.SuppressScope = true;
591 TypePrinter(InnerPolicy).Print(T->getNamedType(), TypeStr);
592
593 MyString += TypeStr;
594 if (S.empty())
595 S.swap(MyString);
596 else
597 S = MyString + ' ' + S;
598}
599
Douglas Gregor4714c122010-03-31 17:34:00 +0000600void TypePrinter::PrintDependentName(const DependentNameType *T, std::string &S) {
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000601 std::string MyString;
602
603 {
604 llvm::raw_string_ostream OS(MyString);
Abramo Bagnara465d41b2010-05-11 21:36:43 +0000605 OS << TypeWithKeyword::getKeywordName(T->getKeyword());
606 if (T->getKeyword() != ETK_None)
607 OS << " ";
Douglas Gregor4a2023f2010-03-31 20:19:30 +0000608
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000609 T->getQualifier()->print(OS, Policy);
610
John McCall33500952010-06-11 00:33:02 +0000611 OS << T->getIdentifier()->getName();
612 }
613
614 if (S.empty())
615 S.swap(MyString);
616 else
617 S = MyString + ' ' + S;
618}
619
620void TypePrinter::PrintDependentTemplateSpecialization(
621 const DependentTemplateSpecializationType *T, std::string &S) {
622 std::string MyString;
623 {
624 llvm::raw_string_ostream OS(MyString);
625
626 OS << TypeWithKeyword::getKeywordName(T->getKeyword());
627 if (T->getKeyword() != ETK_None)
628 OS << " ";
629
630 T->getQualifier()->print(OS, Policy);
631 OS << T->getIdentifier()->getName();
632 OS << TemplateSpecializationType::PrintTemplateArgumentList(
633 T->getArgs(),
634 T->getNumArgs(),
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000635 Policy);
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000636 }
637
638 if (S.empty())
639 S.swap(MyString);
640 else
641 S = MyString + ' ' + S;
642}
643
644void TypePrinter::PrintObjCInterface(const ObjCInterfaceType *T,
645 std::string &S) {
646 if (!S.empty()) // Prefix the basic type, e.g. 'typedefname X'.
647 S = ' ' + S;
John McCallc12c5bb2010-05-15 11:32:37 +0000648
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000649 std::string ObjCQIString = T->getDecl()->getNameAsString();
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000650 S = ObjCQIString + S;
651}
652
John McCallc12c5bb2010-05-15 11:32:37 +0000653void TypePrinter::PrintObjCObject(const ObjCObjectType *T,
654 std::string &S) {
655 if (T->qual_empty())
656 return Print(T->getBaseType(), S);
657
658 std::string tmp;
659 Print(T->getBaseType(), tmp);
660 tmp += '<';
661 bool isFirst = true;
662 for (ObjCObjectType::qual_iterator
663 I = T->qual_begin(), E = T->qual_end(); I != E; ++I) {
664 if (isFirst)
665 isFirst = false;
666 else
667 tmp += ',';
668 tmp += (*I)->getNameAsString();
669 }
670 tmp += '>';
671
672 if (!S.empty()) {
673 tmp += ' ';
674 tmp += S;
675 }
676 std::swap(tmp, S);
677}
678
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000679void TypePrinter::PrintObjCObjectPointer(const ObjCObjectPointerType *T,
680 std::string &S) {
681 std::string ObjCQIString;
682
Chris Lattnerd7e52b82010-09-05 00:43:21 +0000683 T->getPointeeType().getLocalQualifiers().getAsStringInternal(ObjCQIString,
684 Policy);
685 if (!ObjCQIString.empty())
686 ObjCQIString += ' ';
687
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000688 if (T->isObjCIdType() || T->isObjCQualifiedIdType())
Chris Lattnerd7e52b82010-09-05 00:43:21 +0000689 ObjCQIString += "id";
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000690 else if (T->isObjCClassType() || T->isObjCQualifiedClassType())
Chris Lattnerd7e52b82010-09-05 00:43:21 +0000691 ObjCQIString += "Class";
Fariborz Jahanian13dcd002009-11-21 19:53:08 +0000692 else if (T->isObjCSelType())
Chris Lattnerd7e52b82010-09-05 00:43:21 +0000693 ObjCQIString += "SEL";
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000694 else
Chris Lattnerd7e52b82010-09-05 00:43:21 +0000695 ObjCQIString += T->getInterfaceDecl()->getNameAsString();
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000696
697 if (!T->qual_empty()) {
698 ObjCQIString += '<';
699 for (ObjCObjectPointerType::qual_iterator I = T->qual_begin(),
700 E = T->qual_end();
701 I != E; ++I) {
702 ObjCQIString += (*I)->getNameAsString();
703 if (I+1 != E)
704 ObjCQIString += ',';
705 }
706 ObjCQIString += '>';
707 }
708
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000709 if (!T->isObjCIdType() && !T->isObjCQualifiedIdType())
710 ObjCQIString += " *"; // Don't forget the implicit pointer.
711 else if (!S.empty()) // Prefix the basic type, e.g. 'typedefname X'.
712 S = ' ' + S;
713
714 S = ObjCQIString + S;
715}
716
717static void PrintTemplateArgument(std::string &Buffer,
718 const TemplateArgument &Arg,
719 const PrintingPolicy &Policy) {
720 switch (Arg.getKind()) {
721 case TemplateArgument::Null:
722 assert(false && "Null template argument");
723 break;
724
725 case TemplateArgument::Type:
726 Arg.getAsType().getAsStringInternal(Buffer, Policy);
727 break;
728
729 case TemplateArgument::Declaration:
730 Buffer = cast<NamedDecl>(Arg.getAsDecl())->getNameAsString();
731 break;
732
Douglas Gregor788cd062009-11-11 01:00:40 +0000733 case TemplateArgument::Template: {
734 llvm::raw_string_ostream s(Buffer);
735 Arg.getAsTemplate().print(s, Policy);
Douglas Gregorfb898e12009-11-12 16:20:59 +0000736 break;
Douglas Gregor788cd062009-11-11 01:00:40 +0000737 }
738
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000739 case TemplateArgument::Integral:
740 Buffer = Arg.getAsIntegral()->toString(10, true);
741 break;
742
743 case TemplateArgument::Expression: {
744 llvm::raw_string_ostream s(Buffer);
745 Arg.getAsExpr()->printPretty(s, 0, Policy);
746 break;
747 }
748
749 case TemplateArgument::Pack:
750 assert(0 && "FIXME: Implement!");
751 break;
752 }
753}
754
John McCalld5532b62009-11-23 01:53:49 +0000755std::string TemplateSpecializationType::
756 PrintTemplateArgumentList(const TemplateArgumentListInfo &Args,
757 const PrintingPolicy &Policy) {
758 return PrintTemplateArgumentList(Args.getArgumentArray(),
759 Args.size(),
760 Policy);
761}
762
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000763std::string
764TemplateSpecializationType::PrintTemplateArgumentList(
765 const TemplateArgument *Args,
766 unsigned NumArgs,
767 const PrintingPolicy &Policy) {
768 std::string SpecString;
769 SpecString += '<';
770 for (unsigned Arg = 0; Arg < NumArgs; ++Arg) {
771 if (Arg)
772 SpecString += ", ";
773
774 // Print the argument into a string.
775 std::string ArgString;
776 PrintTemplateArgument(ArgString, Args[Arg], Policy);
777
778 // If this is the first argument and its string representation
779 // begins with the global scope specifier ('::foo'), add a space
780 // to avoid printing the diagraph '<:'.
781 if (!Arg && !ArgString.empty() && ArgString[0] == ':')
782 SpecString += ' ';
783
784 SpecString += ArgString;
785 }
786
787 // If the last character of our string is '>', add another space to
788 // keep the two '>''s separate tokens. We don't *have* to do this in
789 // C++0x, but it's still good hygiene.
790 if (SpecString[SpecString.size() - 1] == '>')
791 SpecString += ' ';
792
793 SpecString += '>';
794
795 return SpecString;
796}
797
798// Sadly, repeat all that with TemplateArgLoc.
799std::string TemplateSpecializationType::
800PrintTemplateArgumentList(const TemplateArgumentLoc *Args, unsigned NumArgs,
801 const PrintingPolicy &Policy) {
802 std::string SpecString;
803 SpecString += '<';
804 for (unsigned Arg = 0; Arg < NumArgs; ++Arg) {
805 if (Arg)
806 SpecString += ", ";
807
808 // Print the argument into a string.
809 std::string ArgString;
810 PrintTemplateArgument(ArgString, Args[Arg].getArgument(), Policy);
811
812 // If this is the first argument and its string representation
813 // begins with the global scope specifier ('::foo'), add a space
814 // to avoid printing the diagraph '<:'.
815 if (!Arg && !ArgString.empty() && ArgString[0] == ':')
816 SpecString += ' ';
817
818 SpecString += ArgString;
819 }
820
821 // If the last character of our string is '>', add another space to
822 // keep the two '>''s separate tokens. We don't *have* to do this in
823 // C++0x, but it's still good hygiene.
824 if (SpecString[SpecString.size() - 1] == '>')
825 SpecString += ' ';
826
827 SpecString += '>';
828
829 return SpecString;
830}
831
832void QualType::dump(const char *msg) const {
833 std::string R = "identifier";
834 LangOptions LO;
835 getAsStringInternal(R, PrintingPolicy(LO));
836 if (msg)
Daniel Dunbare7cb7e42009-12-03 09:14:02 +0000837 llvm::errs() << msg << ": ";
838 llvm::errs() << R << "\n";
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000839}
840void QualType::dump() const {
841 dump("");
842}
843
844void Type::dump() const {
845 QualType(this, 0).dump();
846}
847
848std::string Qualifiers::getAsString() const {
849 LangOptions LO;
850 return getAsString(PrintingPolicy(LO));
851}
852
853// Appends qualifiers to the given string, separated by spaces. Will
854// prefix a space if the string is non-empty. Will not append a final
855// space.
856void Qualifiers::getAsStringInternal(std::string &S,
857 const PrintingPolicy&) const {
858 AppendTypeQualList(S, getCVRQualifiers());
859 if (unsigned AddressSpace = getAddressSpace()) {
860 if (!S.empty()) S += ' ';
861 S += "__attribute__((address_space(";
862 S += llvm::utostr_32(AddressSpace);
863 S += ")))";
864 }
865 if (Qualifiers::GC GCAttrType = getObjCGCAttr()) {
866 if (!S.empty()) S += ' ';
867 S += "__attribute__((objc_gc(";
868 if (GCAttrType == Qualifiers::Weak)
869 S += "weak";
870 else
871 S += "strong";
872 S += ")))";
873 }
874}
875
876std::string QualType::getAsString() const {
877 std::string S;
878 LangOptions LO;
879 getAsStringInternal(S, PrintingPolicy(LO));
880 return S;
881}
882
883void QualType::getAsStringInternal(std::string &S,
884 const PrintingPolicy &Policy) const {
885 TypePrinter Printer(Policy);
886 Printer.Print(*this, S);
887}