1 //===--- 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/PrettyPrinter.h"
15 #include "clang/AST/ASTContext.h"
16 #include "clang/AST/Decl.h"
17 #include "clang/AST/DeclObjC.h"
18 #include "clang/AST/DeclTemplate.h"
19 #include "clang/AST/Expr.h"
20 #include "clang/AST/Type.h"
21 #include "clang/Basic/LangOptions.h"
22 #include "clang/Basic/SourceManager.h"
23 #include "llvm/ADT/SmallString.h"
24 #include "llvm/ADT/StringExtras.h"
25 #include "llvm/Support/SaveAndRestore.h"
26 #include "llvm/Support/raw_ostream.h"
27 using namespace clang;
28
29 namespace {
30 /// \brief RAII object that enables printing of the ARC __strong lifetime
31 /// qualifier.
32 class IncludeStrongLifetimeRAII {
33 PrintingPolicy &Policy;
34 bool Old;
35
36 public:
IncludeStrongLifetimeRAII(PrintingPolicy & Policy)37 explicit IncludeStrongLifetimeRAII(PrintingPolicy &Policy)
38 : Policy(Policy), Old(Policy.SuppressStrongLifetime) {
39 if (!Policy.SuppressLifetimeQualifiers)
40 Policy.SuppressStrongLifetime = false;
41 }
42
~IncludeStrongLifetimeRAII()43 ~IncludeStrongLifetimeRAII() {
44 Policy.SuppressStrongLifetime = Old;
45 }
46 };
47
48 class ParamPolicyRAII {
49 PrintingPolicy &Policy;
50 bool Old;
51
52 public:
ParamPolicyRAII(PrintingPolicy & Policy)53 explicit ParamPolicyRAII(PrintingPolicy &Policy)
54 : Policy(Policy), Old(Policy.SuppressSpecifiers) {
55 Policy.SuppressSpecifiers = false;
56 }
57
~ParamPolicyRAII()58 ~ParamPolicyRAII() {
59 Policy.SuppressSpecifiers = Old;
60 }
61 };
62
63 class ElaboratedTypePolicyRAII {
64 PrintingPolicy &Policy;
65 bool SuppressTagKeyword;
66 bool SuppressScope;
67
68 public:
ElaboratedTypePolicyRAII(PrintingPolicy & Policy)69 explicit ElaboratedTypePolicyRAII(PrintingPolicy &Policy) : Policy(Policy) {
70 SuppressTagKeyword = Policy.SuppressTagKeyword;
71 SuppressScope = Policy.SuppressScope;
72 Policy.SuppressTagKeyword = true;
73 Policy.SuppressScope = true;
74 }
75
~ElaboratedTypePolicyRAII()76 ~ElaboratedTypePolicyRAII() {
77 Policy.SuppressTagKeyword = SuppressTagKeyword;
78 Policy.SuppressScope = SuppressScope;
79 }
80 };
81
82 class TypePrinter {
83 PrintingPolicy Policy;
84 bool HasEmptyPlaceHolder;
85 bool InsideCCAttribute;
86
87 public:
TypePrinter(const PrintingPolicy & Policy)88 explicit TypePrinter(const PrintingPolicy &Policy)
89 : Policy(Policy), HasEmptyPlaceHolder(false), InsideCCAttribute(false) { }
90
91 void print(const Type *ty, Qualifiers qs, raw_ostream &OS,
92 StringRef PlaceHolder);
93 void print(QualType T, raw_ostream &OS, StringRef PlaceHolder);
94
95 static bool canPrefixQualifiers(const Type *T, bool &NeedARCStrongQualifier);
96 void spaceBeforePlaceHolder(raw_ostream &OS);
97 void printTypeSpec(const NamedDecl *D, raw_ostream &OS);
98
99 void printBefore(const Type *ty, Qualifiers qs, raw_ostream &OS);
100 void printBefore(QualType T, raw_ostream &OS);
101 void printAfter(const Type *ty, Qualifiers qs, raw_ostream &OS);
102 void printAfter(QualType T, raw_ostream &OS);
103 void AppendScope(DeclContext *DC, raw_ostream &OS);
104 void printTag(TagDecl *T, raw_ostream &OS);
105 #define ABSTRACT_TYPE(CLASS, PARENT)
106 #define TYPE(CLASS, PARENT) \
107 void print##CLASS##Before(const CLASS##Type *T, raw_ostream &OS); \
108 void print##CLASS##After(const CLASS##Type *T, raw_ostream &OS);
109 #include "clang/AST/TypeNodes.def"
110 };
111 }
112
AppendTypeQualList(raw_ostream & OS,unsigned TypeQuals,bool C99)113 static void AppendTypeQualList(raw_ostream &OS, unsigned TypeQuals, bool C99) {
114 bool appendSpace = false;
115 if (TypeQuals & Qualifiers::Const) {
116 OS << "const";
117 appendSpace = true;
118 }
119 if (TypeQuals & Qualifiers::Volatile) {
120 if (appendSpace) OS << ' ';
121 OS << "volatile";
122 appendSpace = true;
123 }
124 if (TypeQuals & Qualifiers::Restrict) {
125 if (appendSpace) OS << ' ';
126 if (C99) {
127 OS << "restrict";
128 } else {
129 OS << "__restrict";
130 }
131 }
132 }
133
spaceBeforePlaceHolder(raw_ostream & OS)134 void TypePrinter::spaceBeforePlaceHolder(raw_ostream &OS) {
135 if (!HasEmptyPlaceHolder)
136 OS << ' ';
137 }
138
print(QualType t,raw_ostream & OS,StringRef PlaceHolder)139 void TypePrinter::print(QualType t, raw_ostream &OS, StringRef PlaceHolder) {
140 SplitQualType split = t.split();
141 print(split.Ty, split.Quals, OS, PlaceHolder);
142 }
143
print(const Type * T,Qualifiers Quals,raw_ostream & OS,StringRef PlaceHolder)144 void TypePrinter::print(const Type *T, Qualifiers Quals, raw_ostream &OS,
145 StringRef PlaceHolder) {
146 if (!T) {
147 OS << "NULL TYPE";
148 return;
149 }
150
151 SaveAndRestore<bool> PHVal(HasEmptyPlaceHolder, PlaceHolder.empty());
152
153 printBefore(T, Quals, OS);
154 OS << PlaceHolder;
155 printAfter(T, Quals, OS);
156 }
157
canPrefixQualifiers(const Type * T,bool & NeedARCStrongQualifier)158 bool TypePrinter::canPrefixQualifiers(const Type *T,
159 bool &NeedARCStrongQualifier) {
160 // CanPrefixQualifiers - We prefer to print type qualifiers before the type,
161 // so that we get "const int" instead of "int const", but we can't do this if
162 // the type is complex. For example if the type is "int*", we *must* print
163 // "int * const", printing "const int *" is different. Only do this when the
164 // type expands to a simple string.
165 bool CanPrefixQualifiers = false;
166 NeedARCStrongQualifier = false;
167 Type::TypeClass TC = T->getTypeClass();
168 if (const AutoType *AT = dyn_cast<AutoType>(T))
169 TC = AT->desugar()->getTypeClass();
170 if (const SubstTemplateTypeParmType *Subst
171 = dyn_cast<SubstTemplateTypeParmType>(T))
172 TC = Subst->getReplacementType()->getTypeClass();
173
174 switch (TC) {
175 case Type::Auto:
176 case Type::Builtin:
177 case Type::Complex:
178 case Type::UnresolvedUsing:
179 case Type::Typedef:
180 case Type::TypeOfExpr:
181 case Type::TypeOf:
182 case Type::Decltype:
183 case Type::UnaryTransform:
184 case Type::Record:
185 case Type::Enum:
186 case Type::Elaborated:
187 case Type::TemplateTypeParm:
188 case Type::SubstTemplateTypeParmPack:
189 case Type::TemplateSpecialization:
190 case Type::InjectedClassName:
191 case Type::DependentName:
192 case Type::DependentTemplateSpecialization:
193 case Type::ObjCObject:
194 case Type::ObjCInterface:
195 case Type::Atomic:
196 CanPrefixQualifiers = true;
197 break;
198
199 case Type::ObjCObjectPointer:
200 CanPrefixQualifiers = T->isObjCIdType() || T->isObjCClassType() ||
201 T->isObjCQualifiedIdType() || T->isObjCQualifiedClassType();
202 break;
203
204 case Type::ConstantArray:
205 case Type::IncompleteArray:
206 case Type::VariableArray:
207 case Type::DependentSizedArray:
208 NeedARCStrongQualifier = true;
209 // Fall through
210
211 case Type::Adjusted:
212 case Type::Decayed:
213 case Type::Pointer:
214 case Type::BlockPointer:
215 case Type::LValueReference:
216 case Type::RValueReference:
217 case Type::MemberPointer:
218 case Type::DependentSizedExtVector:
219 case Type::Vector:
220 case Type::ExtVector:
221 case Type::FunctionProto:
222 case Type::FunctionNoProto:
223 case Type::Paren:
224 case Type::Attributed:
225 case Type::PackExpansion:
226 case Type::SubstTemplateTypeParm:
227 CanPrefixQualifiers = false;
228 break;
229 }
230
231 return CanPrefixQualifiers;
232 }
233
printBefore(QualType T,raw_ostream & OS)234 void TypePrinter::printBefore(QualType T, raw_ostream &OS) {
235 SplitQualType Split = T.split();
236
237 // If we have cv1 T, where T is substituted for cv2 U, only print cv1 - cv2
238 // at this level.
239 Qualifiers Quals = Split.Quals;
240 if (const SubstTemplateTypeParmType *Subst =
241 dyn_cast<SubstTemplateTypeParmType>(Split.Ty))
242 Quals -= QualType(Subst, 0).getQualifiers();
243
244 printBefore(Split.Ty, Quals, OS);
245 }
246
247 /// \brief Prints the part of the type string before an identifier, e.g. for
248 /// "int foo[10]" it prints "int ".
printBefore(const Type * T,Qualifiers Quals,raw_ostream & OS)249 void TypePrinter::printBefore(const Type *T,Qualifiers Quals, raw_ostream &OS) {
250 if (Policy.SuppressSpecifiers && T->isSpecifierType())
251 return;
252
253 SaveAndRestore<bool> PrevPHIsEmpty(HasEmptyPlaceHolder);
254
255 // Print qualifiers as appropriate.
256
257 bool CanPrefixQualifiers = false;
258 bool NeedARCStrongQualifier = false;
259 CanPrefixQualifiers = canPrefixQualifiers(T, NeedARCStrongQualifier);
260
261 if (CanPrefixQualifiers && !Quals.empty()) {
262 if (NeedARCStrongQualifier) {
263 IncludeStrongLifetimeRAII Strong(Policy);
264 Quals.print(OS, Policy, /*appendSpaceIfNonEmpty=*/true);
265 } else {
266 Quals.print(OS, Policy, /*appendSpaceIfNonEmpty=*/true);
267 }
268 }
269
270 bool hasAfterQuals = false;
271 if (!CanPrefixQualifiers && !Quals.empty()) {
272 hasAfterQuals = !Quals.isEmptyWhenPrinted(Policy);
273 if (hasAfterQuals)
274 HasEmptyPlaceHolder = false;
275 }
276
277 switch (T->getTypeClass()) {
278 #define ABSTRACT_TYPE(CLASS, PARENT)
279 #define TYPE(CLASS, PARENT) case Type::CLASS: \
280 print##CLASS##Before(cast<CLASS##Type>(T), OS); \
281 break;
282 #include "clang/AST/TypeNodes.def"
283 }
284
285 if (hasAfterQuals) {
286 if (NeedARCStrongQualifier) {
287 IncludeStrongLifetimeRAII Strong(Policy);
288 Quals.print(OS, Policy, /*appendSpaceIfNonEmpty=*/!PrevPHIsEmpty.get());
289 } else {
290 Quals.print(OS, Policy, /*appendSpaceIfNonEmpty=*/!PrevPHIsEmpty.get());
291 }
292 }
293 }
294
printAfter(QualType t,raw_ostream & OS)295 void TypePrinter::printAfter(QualType t, raw_ostream &OS) {
296 SplitQualType split = t.split();
297 printAfter(split.Ty, split.Quals, OS);
298 }
299
300 /// \brief Prints the part of the type string after an identifier, e.g. for
301 /// "int foo[10]" it prints "[10]".
printAfter(const Type * T,Qualifiers Quals,raw_ostream & OS)302 void TypePrinter::printAfter(const Type *T, Qualifiers Quals, raw_ostream &OS) {
303 switch (T->getTypeClass()) {
304 #define ABSTRACT_TYPE(CLASS, PARENT)
305 #define TYPE(CLASS, PARENT) case Type::CLASS: \
306 print##CLASS##After(cast<CLASS##Type>(T), OS); \
307 break;
308 #include "clang/AST/TypeNodes.def"
309 }
310 }
311
printBuiltinBefore(const BuiltinType * T,raw_ostream & OS)312 void TypePrinter::printBuiltinBefore(const BuiltinType *T, raw_ostream &OS) {
313 OS << T->getName(Policy);
314 spaceBeforePlaceHolder(OS);
315 }
printBuiltinAfter(const BuiltinType * T,raw_ostream & OS)316 void TypePrinter::printBuiltinAfter(const BuiltinType *T, raw_ostream &OS) { }
317
printComplexBefore(const ComplexType * T,raw_ostream & OS)318 void TypePrinter::printComplexBefore(const ComplexType *T, raw_ostream &OS) {
319 OS << "_Complex ";
320 printBefore(T->getElementType(), OS);
321 }
printComplexAfter(const ComplexType * T,raw_ostream & OS)322 void TypePrinter::printComplexAfter(const ComplexType *T, raw_ostream &OS) {
323 printAfter(T->getElementType(), OS);
324 }
325
printPointerBefore(const PointerType * T,raw_ostream & OS)326 void TypePrinter::printPointerBefore(const PointerType *T, raw_ostream &OS) {
327 IncludeStrongLifetimeRAII Strong(Policy);
328 SaveAndRestore<bool> NonEmptyPH(HasEmptyPlaceHolder, false);
329 printBefore(T->getPointeeType(), OS);
330 // Handle things like 'int (*A)[4];' correctly.
331 // FIXME: this should include vectors, but vectors use attributes I guess.
332 if (isa<ArrayType>(T->getPointeeType()))
333 OS << '(';
334 OS << '*';
335 }
printPointerAfter(const PointerType * T,raw_ostream & OS)336 void TypePrinter::printPointerAfter(const PointerType *T, raw_ostream &OS) {
337 IncludeStrongLifetimeRAII Strong(Policy);
338 SaveAndRestore<bool> NonEmptyPH(HasEmptyPlaceHolder, false);
339 // Handle things like 'int (*A)[4];' correctly.
340 // FIXME: this should include vectors, but vectors use attributes I guess.
341 if (isa<ArrayType>(T->getPointeeType()))
342 OS << ')';
343 printAfter(T->getPointeeType(), OS);
344 }
345
printBlockPointerBefore(const BlockPointerType * T,raw_ostream & OS)346 void TypePrinter::printBlockPointerBefore(const BlockPointerType *T,
347 raw_ostream &OS) {
348 SaveAndRestore<bool> NonEmptyPH(HasEmptyPlaceHolder, false);
349 printBefore(T->getPointeeType(), OS);
350 OS << '^';
351 }
printBlockPointerAfter(const BlockPointerType * T,raw_ostream & OS)352 void TypePrinter::printBlockPointerAfter(const BlockPointerType *T,
353 raw_ostream &OS) {
354 SaveAndRestore<bool> NonEmptyPH(HasEmptyPlaceHolder, false);
355 printAfter(T->getPointeeType(), OS);
356 }
357
printLValueReferenceBefore(const LValueReferenceType * T,raw_ostream & OS)358 void TypePrinter::printLValueReferenceBefore(const LValueReferenceType *T,
359 raw_ostream &OS) {
360 IncludeStrongLifetimeRAII Strong(Policy);
361 SaveAndRestore<bool> NonEmptyPH(HasEmptyPlaceHolder, false);
362 printBefore(T->getPointeeTypeAsWritten(), OS);
363 // Handle things like 'int (&A)[4];' correctly.
364 // FIXME: this should include vectors, but vectors use attributes I guess.
365 if (isa<ArrayType>(T->getPointeeTypeAsWritten()))
366 OS << '(';
367 OS << '&';
368 }
printLValueReferenceAfter(const LValueReferenceType * T,raw_ostream & OS)369 void TypePrinter::printLValueReferenceAfter(const LValueReferenceType *T,
370 raw_ostream &OS) {
371 IncludeStrongLifetimeRAII Strong(Policy);
372 SaveAndRestore<bool> NonEmptyPH(HasEmptyPlaceHolder, false);
373 // Handle things like 'int (&A)[4];' correctly.
374 // FIXME: this should include vectors, but vectors use attributes I guess.
375 if (isa<ArrayType>(T->getPointeeTypeAsWritten()))
376 OS << ')';
377 printAfter(T->getPointeeTypeAsWritten(), OS);
378 }
379
printRValueReferenceBefore(const RValueReferenceType * T,raw_ostream & OS)380 void TypePrinter::printRValueReferenceBefore(const RValueReferenceType *T,
381 raw_ostream &OS) {
382 IncludeStrongLifetimeRAII Strong(Policy);
383 SaveAndRestore<bool> NonEmptyPH(HasEmptyPlaceHolder, false);
384 printBefore(T->getPointeeTypeAsWritten(), OS);
385 // Handle things like 'int (&&A)[4];' correctly.
386 // FIXME: this should include vectors, but vectors use attributes I guess.
387 if (isa<ArrayType>(T->getPointeeTypeAsWritten()))
388 OS << '(';
389 OS << "&&";
390 }
printRValueReferenceAfter(const RValueReferenceType * T,raw_ostream & OS)391 void TypePrinter::printRValueReferenceAfter(const RValueReferenceType *T,
392 raw_ostream &OS) {
393 IncludeStrongLifetimeRAII Strong(Policy);
394 SaveAndRestore<bool> NonEmptyPH(HasEmptyPlaceHolder, false);
395 // Handle things like 'int (&&A)[4];' correctly.
396 // FIXME: this should include vectors, but vectors use attributes I guess.
397 if (isa<ArrayType>(T->getPointeeTypeAsWritten()))
398 OS << ')';
399 printAfter(T->getPointeeTypeAsWritten(), OS);
400 }
401
printMemberPointerBefore(const MemberPointerType * T,raw_ostream & OS)402 void TypePrinter::printMemberPointerBefore(const MemberPointerType *T,
403 raw_ostream &OS) {
404 IncludeStrongLifetimeRAII Strong(Policy);
405 SaveAndRestore<bool> NonEmptyPH(HasEmptyPlaceHolder, false);
406 printBefore(T->getPointeeType(), OS);
407 // Handle things like 'int (Cls::*A)[4];' correctly.
408 // FIXME: this should include vectors, but vectors use attributes I guess.
409 if (isa<ArrayType>(T->getPointeeType()))
410 OS << '(';
411
412 PrintingPolicy InnerPolicy(Policy);
413 InnerPolicy.SuppressTag = false;
414 TypePrinter(InnerPolicy).print(QualType(T->getClass(), 0), OS, StringRef());
415
416 OS << "::*";
417 }
printMemberPointerAfter(const MemberPointerType * T,raw_ostream & OS)418 void TypePrinter::printMemberPointerAfter(const MemberPointerType *T,
419 raw_ostream &OS) {
420 IncludeStrongLifetimeRAII Strong(Policy);
421 SaveAndRestore<bool> NonEmptyPH(HasEmptyPlaceHolder, false);
422 // Handle things like 'int (Cls::*A)[4];' correctly.
423 // FIXME: this should include vectors, but vectors use attributes I guess.
424 if (isa<ArrayType>(T->getPointeeType()))
425 OS << ')';
426 printAfter(T->getPointeeType(), OS);
427 }
428
printConstantArrayBefore(const ConstantArrayType * T,raw_ostream & OS)429 void TypePrinter::printConstantArrayBefore(const ConstantArrayType *T,
430 raw_ostream &OS) {
431 IncludeStrongLifetimeRAII Strong(Policy);
432 SaveAndRestore<bool> NonEmptyPH(HasEmptyPlaceHolder, false);
433 printBefore(T->getElementType(), OS);
434 }
printConstantArrayAfter(const ConstantArrayType * T,raw_ostream & OS)435 void TypePrinter::printConstantArrayAfter(const ConstantArrayType *T,
436 raw_ostream &OS) {
437 OS << '[';
438 if (T->getIndexTypeQualifiers().hasQualifiers()) {
439 AppendTypeQualList(OS, T->getIndexTypeCVRQualifiers(), Policy.LangOpts.C99);
440 OS << ' ';
441 }
442
443 if (T->getSizeModifier() == ArrayType::Static)
444 OS << "static ";
445
446 OS << T->getSize().getZExtValue() << ']';
447 printAfter(T->getElementType(), OS);
448 }
449
printIncompleteArrayBefore(const IncompleteArrayType * T,raw_ostream & OS)450 void TypePrinter::printIncompleteArrayBefore(const IncompleteArrayType *T,
451 raw_ostream &OS) {
452 IncludeStrongLifetimeRAII Strong(Policy);
453 SaveAndRestore<bool> NonEmptyPH(HasEmptyPlaceHolder, false);
454 printBefore(T->getElementType(), OS);
455 }
printIncompleteArrayAfter(const IncompleteArrayType * T,raw_ostream & OS)456 void TypePrinter::printIncompleteArrayAfter(const IncompleteArrayType *T,
457 raw_ostream &OS) {
458 OS << "[]";
459 printAfter(T->getElementType(), OS);
460 }
461
printVariableArrayBefore(const VariableArrayType * T,raw_ostream & OS)462 void TypePrinter::printVariableArrayBefore(const VariableArrayType *T,
463 raw_ostream &OS) {
464 IncludeStrongLifetimeRAII Strong(Policy);
465 SaveAndRestore<bool> NonEmptyPH(HasEmptyPlaceHolder, false);
466 printBefore(T->getElementType(), OS);
467 }
printVariableArrayAfter(const VariableArrayType * T,raw_ostream & OS)468 void TypePrinter::printVariableArrayAfter(const VariableArrayType *T,
469 raw_ostream &OS) {
470 OS << '[';
471 if (T->getIndexTypeQualifiers().hasQualifiers()) {
472 AppendTypeQualList(OS, T->getIndexTypeCVRQualifiers(), Policy.LangOpts.C99);
473 OS << ' ';
474 }
475
476 if (T->getSizeModifier() == VariableArrayType::Static)
477 OS << "static ";
478 else if (T->getSizeModifier() == VariableArrayType::Star)
479 OS << '*';
480
481 if (T->getSizeExpr())
482 T->getSizeExpr()->printPretty(OS, nullptr, Policy);
483 OS << ']';
484
485 printAfter(T->getElementType(), OS);
486 }
487
printAdjustedBefore(const AdjustedType * T,raw_ostream & OS)488 void TypePrinter::printAdjustedBefore(const AdjustedType *T, raw_ostream &OS) {
489 // Print the adjusted representation, otherwise the adjustment will be
490 // invisible.
491 printBefore(T->getAdjustedType(), OS);
492 }
printAdjustedAfter(const AdjustedType * T,raw_ostream & OS)493 void TypePrinter::printAdjustedAfter(const AdjustedType *T, raw_ostream &OS) {
494 printAfter(T->getAdjustedType(), OS);
495 }
496
printDecayedBefore(const DecayedType * T,raw_ostream & OS)497 void TypePrinter::printDecayedBefore(const DecayedType *T, raw_ostream &OS) {
498 // Print as though it's a pointer.
499 printAdjustedBefore(T, OS);
500 }
printDecayedAfter(const DecayedType * T,raw_ostream & OS)501 void TypePrinter::printDecayedAfter(const DecayedType *T, raw_ostream &OS) {
502 printAdjustedAfter(T, OS);
503 }
504
printDependentSizedArrayBefore(const DependentSizedArrayType * T,raw_ostream & OS)505 void TypePrinter::printDependentSizedArrayBefore(
506 const DependentSizedArrayType *T,
507 raw_ostream &OS) {
508 IncludeStrongLifetimeRAII Strong(Policy);
509 SaveAndRestore<bool> NonEmptyPH(HasEmptyPlaceHolder, false);
510 printBefore(T->getElementType(), OS);
511 }
printDependentSizedArrayAfter(const DependentSizedArrayType * T,raw_ostream & OS)512 void TypePrinter::printDependentSizedArrayAfter(
513 const DependentSizedArrayType *T,
514 raw_ostream &OS) {
515 OS << '[';
516 if (T->getSizeExpr())
517 T->getSizeExpr()->printPretty(OS, nullptr, Policy);
518 OS << ']';
519 printAfter(T->getElementType(), OS);
520 }
521
printDependentSizedExtVectorBefore(const DependentSizedExtVectorType * T,raw_ostream & OS)522 void TypePrinter::printDependentSizedExtVectorBefore(
523 const DependentSizedExtVectorType *T,
524 raw_ostream &OS) {
525 printBefore(T->getElementType(), OS);
526 }
printDependentSizedExtVectorAfter(const DependentSizedExtVectorType * T,raw_ostream & OS)527 void TypePrinter::printDependentSizedExtVectorAfter(
528 const DependentSizedExtVectorType *T,
529 raw_ostream &OS) {
530 OS << " __attribute__((ext_vector_type(";
531 if (T->getSizeExpr())
532 T->getSizeExpr()->printPretty(OS, nullptr, Policy);
533 OS << ")))";
534 printAfter(T->getElementType(), OS);
535 }
536
printVectorBefore(const VectorType * T,raw_ostream & OS)537 void TypePrinter::printVectorBefore(const VectorType *T, raw_ostream &OS) {
538 switch (T->getVectorKind()) {
539 case VectorType::AltiVecPixel:
540 OS << "__vector __pixel ";
541 break;
542 case VectorType::AltiVecBool:
543 OS << "__vector __bool ";
544 printBefore(T->getElementType(), OS);
545 break;
546 case VectorType::AltiVecVector:
547 OS << "__vector ";
548 printBefore(T->getElementType(), OS);
549 break;
550 case VectorType::NeonVector:
551 OS << "__attribute__((neon_vector_type("
552 << T->getNumElements() << "))) ";
553 printBefore(T->getElementType(), OS);
554 break;
555 case VectorType::NeonPolyVector:
556 OS << "__attribute__((neon_polyvector_type(" <<
557 T->getNumElements() << "))) ";
558 printBefore(T->getElementType(), OS);
559 break;
560 case VectorType::GenericVector: {
561 // FIXME: We prefer to print the size directly here, but have no way
562 // to get the size of the type.
563 OS << "__attribute__((__vector_size__("
564 << T->getNumElements()
565 << " * sizeof(";
566 print(T->getElementType(), OS, StringRef());
567 OS << ")))) ";
568 printBefore(T->getElementType(), OS);
569 break;
570 }
571 }
572 }
printVectorAfter(const VectorType * T,raw_ostream & OS)573 void TypePrinter::printVectorAfter(const VectorType *T, raw_ostream &OS) {
574 printAfter(T->getElementType(), OS);
575 }
576
printExtVectorBefore(const ExtVectorType * T,raw_ostream & OS)577 void TypePrinter::printExtVectorBefore(const ExtVectorType *T,
578 raw_ostream &OS) {
579 printBefore(T->getElementType(), OS);
580 }
printExtVectorAfter(const ExtVectorType * T,raw_ostream & OS)581 void TypePrinter::printExtVectorAfter(const ExtVectorType *T, raw_ostream &OS) {
582 printAfter(T->getElementType(), OS);
583 OS << " __attribute__((ext_vector_type(";
584 OS << T->getNumElements();
585 OS << ")))";
586 }
587
588 void
printExceptionSpecification(raw_ostream & OS,const PrintingPolicy & Policy) const589 FunctionProtoType::printExceptionSpecification(raw_ostream &OS,
590 const PrintingPolicy &Policy)
591 const {
592
593 if (hasDynamicExceptionSpec()) {
594 OS << " throw(";
595 if (getExceptionSpecType() == EST_MSAny)
596 OS << "...";
597 else
598 for (unsigned I = 0, N = getNumExceptions(); I != N; ++I) {
599 if (I)
600 OS << ", ";
601
602 OS << getExceptionType(I).stream(Policy);
603 }
604 OS << ')';
605 } else if (isNoexceptExceptionSpec(getExceptionSpecType())) {
606 OS << " noexcept";
607 if (getExceptionSpecType() == EST_ComputedNoexcept) {
608 OS << '(';
609 if (getNoexceptExpr())
610 getNoexceptExpr()->printPretty(OS, nullptr, Policy);
611 OS << ')';
612 }
613 }
614 }
615
printFunctionProtoBefore(const FunctionProtoType * T,raw_ostream & OS)616 void TypePrinter::printFunctionProtoBefore(const FunctionProtoType *T,
617 raw_ostream &OS) {
618 if (T->hasTrailingReturn()) {
619 OS << "auto ";
620 if (!HasEmptyPlaceHolder)
621 OS << '(';
622 } else {
623 // If needed for precedence reasons, wrap the inner part in grouping parens.
624 SaveAndRestore<bool> PrevPHIsEmpty(HasEmptyPlaceHolder, false);
625 printBefore(T->getReturnType(), OS);
626 if (!PrevPHIsEmpty.get())
627 OS << '(';
628 }
629 }
630
printFunctionProtoAfter(const FunctionProtoType * T,raw_ostream & OS)631 void TypePrinter::printFunctionProtoAfter(const FunctionProtoType *T,
632 raw_ostream &OS) {
633 // If needed for precedence reasons, wrap the inner part in grouping parens.
634 if (!HasEmptyPlaceHolder)
635 OS << ')';
636 SaveAndRestore<bool> NonEmptyPH(HasEmptyPlaceHolder, false);
637
638 OS << '(';
639 {
640 ParamPolicyRAII ParamPolicy(Policy);
641 for (unsigned i = 0, e = T->getNumParams(); i != e; ++i) {
642 if (i) OS << ", ";
643 print(T->getParamType(i), OS, StringRef());
644 }
645 }
646
647 if (T->isVariadic()) {
648 if (T->getNumParams())
649 OS << ", ";
650 OS << "...";
651 } else if (T->getNumParams() == 0 && !Policy.LangOpts.CPlusPlus) {
652 // Do not emit int() if we have a proto, emit 'int(void)'.
653 OS << "void";
654 }
655
656 OS << ')';
657
658 FunctionType::ExtInfo Info = T->getExtInfo();
659
660 if (!InsideCCAttribute) {
661 switch (Info.getCC()) {
662 case CC_C:
663 // The C calling convention is the default on the vast majority of platforms
664 // we support. If the user wrote it explicitly, it will usually be printed
665 // while traversing the AttributedType. If the type has been desugared, let
666 // the canonical spelling be the implicit calling convention.
667 // FIXME: It would be better to be explicit in certain contexts, such as a
668 // cdecl function typedef used to declare a member function with the
669 // Microsoft C++ ABI.
670 break;
671 case CC_X86StdCall:
672 OS << " __attribute__((stdcall))";
673 break;
674 case CC_X86FastCall:
675 OS << " __attribute__((fastcall))";
676 break;
677 case CC_X86ThisCall:
678 OS << " __attribute__((thiscall))";
679 break;
680 case CC_X86VectorCall:
681 OS << " __attribute__((vectorcall))";
682 break;
683 case CC_X86Pascal:
684 OS << " __attribute__((pascal))";
685 break;
686 case CC_AAPCS:
687 OS << " __attribute__((pcs(\"aapcs\")))";
688 break;
689 case CC_AAPCS_VFP:
690 OS << " __attribute__((pcs(\"aapcs-vfp\")))";
691 break;
692 case CC_IntelOclBicc:
693 OS << " __attribute__((intel_ocl_bicc))";
694 break;
695 case CC_X86_64Win64:
696 OS << " __attribute__((ms_abi))";
697 break;
698 case CC_X86_64SysV:
699 OS << " __attribute__((sysv_abi))";
700 break;
701 case CC_SpirFunction:
702 case CC_SpirKernel:
703 // Do nothing. These CCs are not available as attributes.
704 break;
705 }
706 }
707
708 if (Info.getNoReturn())
709 OS << " __attribute__((noreturn))";
710 if (Info.getRegParm())
711 OS << " __attribute__((regparm ("
712 << Info.getRegParm() << ")))";
713
714 if (unsigned quals = T->getTypeQuals()) {
715 OS << ' ';
716 AppendTypeQualList(OS, quals, Policy.LangOpts.C99);
717 }
718
719 switch (T->getRefQualifier()) {
720 case RQ_None:
721 break;
722
723 case RQ_LValue:
724 OS << " &";
725 break;
726
727 case RQ_RValue:
728 OS << " &&";
729 break;
730 }
731 T->printExceptionSpecification(OS, Policy);
732
733 if (T->hasTrailingReturn()) {
734 OS << " -> ";
735 print(T->getReturnType(), OS, StringRef());
736 } else
737 printAfter(T->getReturnType(), OS);
738 }
739
printFunctionNoProtoBefore(const FunctionNoProtoType * T,raw_ostream & OS)740 void TypePrinter::printFunctionNoProtoBefore(const FunctionNoProtoType *T,
741 raw_ostream &OS) {
742 // If needed for precedence reasons, wrap the inner part in grouping parens.
743 SaveAndRestore<bool> PrevPHIsEmpty(HasEmptyPlaceHolder, false);
744 printBefore(T->getReturnType(), OS);
745 if (!PrevPHIsEmpty.get())
746 OS << '(';
747 }
printFunctionNoProtoAfter(const FunctionNoProtoType * T,raw_ostream & OS)748 void TypePrinter::printFunctionNoProtoAfter(const FunctionNoProtoType *T,
749 raw_ostream &OS) {
750 // If needed for precedence reasons, wrap the inner part in grouping parens.
751 if (!HasEmptyPlaceHolder)
752 OS << ')';
753 SaveAndRestore<bool> NonEmptyPH(HasEmptyPlaceHolder, false);
754
755 OS << "()";
756 if (T->getNoReturnAttr())
757 OS << " __attribute__((noreturn))";
758 printAfter(T->getReturnType(), OS);
759 }
760
printTypeSpec(const NamedDecl * D,raw_ostream & OS)761 void TypePrinter::printTypeSpec(const NamedDecl *D, raw_ostream &OS) {
762 IdentifierInfo *II = D->getIdentifier();
763 OS << II->getName();
764 spaceBeforePlaceHolder(OS);
765 }
766
printUnresolvedUsingBefore(const UnresolvedUsingType * T,raw_ostream & OS)767 void TypePrinter::printUnresolvedUsingBefore(const UnresolvedUsingType *T,
768 raw_ostream &OS) {
769 printTypeSpec(T->getDecl(), OS);
770 }
printUnresolvedUsingAfter(const UnresolvedUsingType * T,raw_ostream & OS)771 void TypePrinter::printUnresolvedUsingAfter(const UnresolvedUsingType *T,
772 raw_ostream &OS) { }
773
printTypedefBefore(const TypedefType * T,raw_ostream & OS)774 void TypePrinter::printTypedefBefore(const TypedefType *T, raw_ostream &OS) {
775 printTypeSpec(T->getDecl(), OS);
776 }
printTypedefAfter(const TypedefType * T,raw_ostream & OS)777 void TypePrinter::printTypedefAfter(const TypedefType *T, raw_ostream &OS) { }
778
printTypeOfExprBefore(const TypeOfExprType * T,raw_ostream & OS)779 void TypePrinter::printTypeOfExprBefore(const TypeOfExprType *T,
780 raw_ostream &OS) {
781 OS << "typeof ";
782 if (T->getUnderlyingExpr())
783 T->getUnderlyingExpr()->printPretty(OS, nullptr, Policy);
784 spaceBeforePlaceHolder(OS);
785 }
printTypeOfExprAfter(const TypeOfExprType * T,raw_ostream & OS)786 void TypePrinter::printTypeOfExprAfter(const TypeOfExprType *T,
787 raw_ostream &OS) { }
788
printTypeOfBefore(const TypeOfType * T,raw_ostream & OS)789 void TypePrinter::printTypeOfBefore(const TypeOfType *T, raw_ostream &OS) {
790 OS << "typeof(";
791 print(T->getUnderlyingType(), OS, StringRef());
792 OS << ')';
793 spaceBeforePlaceHolder(OS);
794 }
printTypeOfAfter(const TypeOfType * T,raw_ostream & OS)795 void TypePrinter::printTypeOfAfter(const TypeOfType *T, raw_ostream &OS) { }
796
printDecltypeBefore(const DecltypeType * T,raw_ostream & OS)797 void TypePrinter::printDecltypeBefore(const DecltypeType *T, raw_ostream &OS) {
798 OS << "decltype(";
799 if (T->getUnderlyingExpr())
800 T->getUnderlyingExpr()->printPretty(OS, nullptr, Policy);
801 OS << ')';
802 spaceBeforePlaceHolder(OS);
803 }
printDecltypeAfter(const DecltypeType * T,raw_ostream & OS)804 void TypePrinter::printDecltypeAfter(const DecltypeType *T, raw_ostream &OS) { }
805
printUnaryTransformBefore(const UnaryTransformType * T,raw_ostream & OS)806 void TypePrinter::printUnaryTransformBefore(const UnaryTransformType *T,
807 raw_ostream &OS) {
808 IncludeStrongLifetimeRAII Strong(Policy);
809
810 switch (T->getUTTKind()) {
811 case UnaryTransformType::EnumUnderlyingType:
812 OS << "__underlying_type(";
813 print(T->getBaseType(), OS, StringRef());
814 OS << ')';
815 spaceBeforePlaceHolder(OS);
816 return;
817 }
818
819 printBefore(T->getBaseType(), OS);
820 }
printUnaryTransformAfter(const UnaryTransformType * T,raw_ostream & OS)821 void TypePrinter::printUnaryTransformAfter(const UnaryTransformType *T,
822 raw_ostream &OS) {
823 IncludeStrongLifetimeRAII Strong(Policy);
824
825 switch (T->getUTTKind()) {
826 case UnaryTransformType::EnumUnderlyingType:
827 return;
828 }
829
830 printAfter(T->getBaseType(), OS);
831 }
832
printAutoBefore(const AutoType * T,raw_ostream & OS)833 void TypePrinter::printAutoBefore(const AutoType *T, raw_ostream &OS) {
834 // If the type has been deduced, do not print 'auto'.
835 if (!T->getDeducedType().isNull()) {
836 printBefore(T->getDeducedType(), OS);
837 } else {
838 switch (T->getKeyword()) {
839 case AutoTypeKeyword::Auto: OS << "auto"; break;
840 case AutoTypeKeyword::DecltypeAuto: OS << "decltype(auto)"; break;
841 case AutoTypeKeyword::GNUAutoType: OS << "__auto_type"; break;
842 }
843 spaceBeforePlaceHolder(OS);
844 }
845 }
printAutoAfter(const AutoType * T,raw_ostream & OS)846 void TypePrinter::printAutoAfter(const AutoType *T, raw_ostream &OS) {
847 // If the type has been deduced, do not print 'auto'.
848 if (!T->getDeducedType().isNull())
849 printAfter(T->getDeducedType(), OS);
850 }
851
printAtomicBefore(const AtomicType * T,raw_ostream & OS)852 void TypePrinter::printAtomicBefore(const AtomicType *T, raw_ostream &OS) {
853 IncludeStrongLifetimeRAII Strong(Policy);
854
855 OS << "_Atomic(";
856 print(T->getValueType(), OS, StringRef());
857 OS << ')';
858 spaceBeforePlaceHolder(OS);
859 }
printAtomicAfter(const AtomicType * T,raw_ostream & OS)860 void TypePrinter::printAtomicAfter(const AtomicType *T, raw_ostream &OS) { }
861
862 /// Appends the given scope to the end of a string.
AppendScope(DeclContext * DC,raw_ostream & OS)863 void TypePrinter::AppendScope(DeclContext *DC, raw_ostream &OS) {
864 if (DC->isTranslationUnit()) return;
865 if (DC->isFunctionOrMethod()) return;
866 AppendScope(DC->getParent(), OS);
867
868 if (NamespaceDecl *NS = dyn_cast<NamespaceDecl>(DC)) {
869 if (Policy.SuppressUnwrittenScope &&
870 (NS->isAnonymousNamespace() || NS->isInline()))
871 return;
872 if (NS->getIdentifier())
873 OS << NS->getName() << "::";
874 else
875 OS << "(anonymous namespace)::";
876 } else if (ClassTemplateSpecializationDecl *Spec
877 = dyn_cast<ClassTemplateSpecializationDecl>(DC)) {
878 IncludeStrongLifetimeRAII Strong(Policy);
879 OS << Spec->getIdentifier()->getName();
880 const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs();
881 TemplateSpecializationType::PrintTemplateArgumentList(OS,
882 TemplateArgs.data(),
883 TemplateArgs.size(),
884 Policy);
885 OS << "::";
886 } else if (TagDecl *Tag = dyn_cast<TagDecl>(DC)) {
887 if (TypedefNameDecl *Typedef = Tag->getTypedefNameForAnonDecl())
888 OS << Typedef->getIdentifier()->getName() << "::";
889 else if (Tag->getIdentifier())
890 OS << Tag->getIdentifier()->getName() << "::";
891 else
892 return;
893 }
894 }
895
printTag(TagDecl * D,raw_ostream & OS)896 void TypePrinter::printTag(TagDecl *D, raw_ostream &OS) {
897 if (Policy.SuppressTag)
898 return;
899
900 bool HasKindDecoration = false;
901
902 // bool SuppressTagKeyword
903 // = Policy.LangOpts.CPlusPlus || Policy.SuppressTagKeyword;
904
905 // We don't print tags unless this is an elaborated type.
906 // In C, we just assume every RecordType is an elaborated type.
907 if (!(Policy.LangOpts.CPlusPlus || Policy.SuppressTagKeyword ||
908 D->getTypedefNameForAnonDecl())) {
909 HasKindDecoration = true;
910 OS << D->getKindName();
911 OS << ' ';
912 }
913
914 // Compute the full nested-name-specifier for this type.
915 // In C, this will always be empty except when the type
916 // being printed is anonymous within other Record.
917 if (!Policy.SuppressScope)
918 AppendScope(D->getDeclContext(), OS);
919
920 if (const IdentifierInfo *II = D->getIdentifier())
921 OS << II->getName();
922 else if (TypedefNameDecl *Typedef = D->getTypedefNameForAnonDecl()) {
923 assert(Typedef->getIdentifier() && "Typedef without identifier?");
924 OS << Typedef->getIdentifier()->getName();
925 } else {
926 // Make an unambiguous representation for anonymous types, e.g.
927 // (anonymous enum at /usr/include/string.h:120:9)
928 OS << (Policy.MSVCFormatting ? '`' : '(');
929
930 if (isa<CXXRecordDecl>(D) && cast<CXXRecordDecl>(D)->isLambda()) {
931 OS << "lambda";
932 HasKindDecoration = true;
933 } else {
934 OS << "anonymous";
935 }
936
937 if (Policy.AnonymousTagLocations) {
938 // Suppress the redundant tag keyword if we just printed one.
939 // We don't have to worry about ElaboratedTypes here because you can't
940 // refer to an anonymous type with one.
941 if (!HasKindDecoration)
942 OS << " " << D->getKindName();
943
944 PresumedLoc PLoc = D->getASTContext().getSourceManager().getPresumedLoc(
945 D->getLocation());
946 if (PLoc.isValid()) {
947 OS << " at " << PLoc.getFilename()
948 << ':' << PLoc.getLine()
949 << ':' << PLoc.getColumn();
950 }
951 }
952
953 OS << (Policy.MSVCFormatting ? '\'' : ')');
954 }
955
956 // If this is a class template specialization, print the template
957 // arguments.
958 if (ClassTemplateSpecializationDecl *Spec
959 = dyn_cast<ClassTemplateSpecializationDecl>(D)) {
960 const TemplateArgument *Args;
961 unsigned NumArgs;
962 if (TypeSourceInfo *TAW = Spec->getTypeAsWritten()) {
963 const TemplateSpecializationType *TST =
964 cast<TemplateSpecializationType>(TAW->getType());
965 Args = TST->getArgs();
966 NumArgs = TST->getNumArgs();
967 } else {
968 const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs();
969 Args = TemplateArgs.data();
970 NumArgs = TemplateArgs.size();
971 }
972 IncludeStrongLifetimeRAII Strong(Policy);
973 TemplateSpecializationType::PrintTemplateArgumentList(OS,
974 Args, NumArgs,
975 Policy);
976 }
977
978 spaceBeforePlaceHolder(OS);
979 }
980
printRecordBefore(const RecordType * T,raw_ostream & OS)981 void TypePrinter::printRecordBefore(const RecordType *T, raw_ostream &OS) {
982 printTag(T->getDecl(), OS);
983 }
printRecordAfter(const RecordType * T,raw_ostream & OS)984 void TypePrinter::printRecordAfter(const RecordType *T, raw_ostream &OS) { }
985
printEnumBefore(const EnumType * T,raw_ostream & OS)986 void TypePrinter::printEnumBefore(const EnumType *T, raw_ostream &OS) {
987 printTag(T->getDecl(), OS);
988 }
printEnumAfter(const EnumType * T,raw_ostream & OS)989 void TypePrinter::printEnumAfter(const EnumType *T, raw_ostream &OS) { }
990
printTemplateTypeParmBefore(const TemplateTypeParmType * T,raw_ostream & OS)991 void TypePrinter::printTemplateTypeParmBefore(const TemplateTypeParmType *T,
992 raw_ostream &OS) {
993 if (IdentifierInfo *Id = T->getIdentifier())
994 OS << Id->getName();
995 else
996 OS << "type-parameter-" << T->getDepth() << '-' << T->getIndex();
997 spaceBeforePlaceHolder(OS);
998 }
printTemplateTypeParmAfter(const TemplateTypeParmType * T,raw_ostream & OS)999 void TypePrinter::printTemplateTypeParmAfter(const TemplateTypeParmType *T,
1000 raw_ostream &OS) { }
1001
printSubstTemplateTypeParmBefore(const SubstTemplateTypeParmType * T,raw_ostream & OS)1002 void TypePrinter::printSubstTemplateTypeParmBefore(
1003 const SubstTemplateTypeParmType *T,
1004 raw_ostream &OS) {
1005 IncludeStrongLifetimeRAII Strong(Policy);
1006 printBefore(T->getReplacementType(), OS);
1007 }
printSubstTemplateTypeParmAfter(const SubstTemplateTypeParmType * T,raw_ostream & OS)1008 void TypePrinter::printSubstTemplateTypeParmAfter(
1009 const SubstTemplateTypeParmType *T,
1010 raw_ostream &OS) {
1011 IncludeStrongLifetimeRAII Strong(Policy);
1012 printAfter(T->getReplacementType(), OS);
1013 }
1014
printSubstTemplateTypeParmPackBefore(const SubstTemplateTypeParmPackType * T,raw_ostream & OS)1015 void TypePrinter::printSubstTemplateTypeParmPackBefore(
1016 const SubstTemplateTypeParmPackType *T,
1017 raw_ostream &OS) {
1018 IncludeStrongLifetimeRAII Strong(Policy);
1019 printTemplateTypeParmBefore(T->getReplacedParameter(), OS);
1020 }
printSubstTemplateTypeParmPackAfter(const SubstTemplateTypeParmPackType * T,raw_ostream & OS)1021 void TypePrinter::printSubstTemplateTypeParmPackAfter(
1022 const SubstTemplateTypeParmPackType *T,
1023 raw_ostream &OS) {
1024 IncludeStrongLifetimeRAII Strong(Policy);
1025 printTemplateTypeParmAfter(T->getReplacedParameter(), OS);
1026 }
1027
printTemplateSpecializationBefore(const TemplateSpecializationType * T,raw_ostream & OS)1028 void TypePrinter::printTemplateSpecializationBefore(
1029 const TemplateSpecializationType *T,
1030 raw_ostream &OS) {
1031 IncludeStrongLifetimeRAII Strong(Policy);
1032 T->getTemplateName().print(OS, Policy);
1033
1034 TemplateSpecializationType::PrintTemplateArgumentList(OS,
1035 T->getArgs(),
1036 T->getNumArgs(),
1037 Policy);
1038 spaceBeforePlaceHolder(OS);
1039 }
printTemplateSpecializationAfter(const TemplateSpecializationType * T,raw_ostream & OS)1040 void TypePrinter::printTemplateSpecializationAfter(
1041 const TemplateSpecializationType *T,
1042 raw_ostream &OS) { }
1043
printInjectedClassNameBefore(const InjectedClassNameType * T,raw_ostream & OS)1044 void TypePrinter::printInjectedClassNameBefore(const InjectedClassNameType *T,
1045 raw_ostream &OS) {
1046 printTemplateSpecializationBefore(T->getInjectedTST(), OS);
1047 }
printInjectedClassNameAfter(const InjectedClassNameType * T,raw_ostream & OS)1048 void TypePrinter::printInjectedClassNameAfter(const InjectedClassNameType *T,
1049 raw_ostream &OS) { }
1050
printElaboratedBefore(const ElaboratedType * T,raw_ostream & OS)1051 void TypePrinter::printElaboratedBefore(const ElaboratedType *T,
1052 raw_ostream &OS) {
1053 if (Policy.SuppressTag && isa<TagType>(T->getNamedType()))
1054 return;
1055 OS << TypeWithKeyword::getKeywordName(T->getKeyword());
1056 if (T->getKeyword() != ETK_None)
1057 OS << " ";
1058 NestedNameSpecifier* Qualifier = T->getQualifier();
1059 if (Qualifier)
1060 Qualifier->print(OS, Policy);
1061
1062 ElaboratedTypePolicyRAII PolicyRAII(Policy);
1063 printBefore(T->getNamedType(), OS);
1064 }
printElaboratedAfter(const ElaboratedType * T,raw_ostream & OS)1065 void TypePrinter::printElaboratedAfter(const ElaboratedType *T,
1066 raw_ostream &OS) {
1067 ElaboratedTypePolicyRAII PolicyRAII(Policy);
1068 printAfter(T->getNamedType(), OS);
1069 }
1070
printParenBefore(const ParenType * T,raw_ostream & OS)1071 void TypePrinter::printParenBefore(const ParenType *T, raw_ostream &OS) {
1072 if (!HasEmptyPlaceHolder && !isa<FunctionType>(T->getInnerType())) {
1073 printBefore(T->getInnerType(), OS);
1074 OS << '(';
1075 } else
1076 printBefore(T->getInnerType(), OS);
1077 }
printParenAfter(const ParenType * T,raw_ostream & OS)1078 void TypePrinter::printParenAfter(const ParenType *T, raw_ostream &OS) {
1079 if (!HasEmptyPlaceHolder && !isa<FunctionType>(T->getInnerType())) {
1080 OS << ')';
1081 printAfter(T->getInnerType(), OS);
1082 } else
1083 printAfter(T->getInnerType(), OS);
1084 }
1085
printDependentNameBefore(const DependentNameType * T,raw_ostream & OS)1086 void TypePrinter::printDependentNameBefore(const DependentNameType *T,
1087 raw_ostream &OS) {
1088 OS << TypeWithKeyword::getKeywordName(T->getKeyword());
1089 if (T->getKeyword() != ETK_None)
1090 OS << " ";
1091
1092 T->getQualifier()->print(OS, Policy);
1093
1094 OS << T->getIdentifier()->getName();
1095 spaceBeforePlaceHolder(OS);
1096 }
printDependentNameAfter(const DependentNameType * T,raw_ostream & OS)1097 void TypePrinter::printDependentNameAfter(const DependentNameType *T,
1098 raw_ostream &OS) { }
1099
printDependentTemplateSpecializationBefore(const DependentTemplateSpecializationType * T,raw_ostream & OS)1100 void TypePrinter::printDependentTemplateSpecializationBefore(
1101 const DependentTemplateSpecializationType *T, raw_ostream &OS) {
1102 IncludeStrongLifetimeRAII Strong(Policy);
1103
1104 OS << TypeWithKeyword::getKeywordName(T->getKeyword());
1105 if (T->getKeyword() != ETK_None)
1106 OS << " ";
1107
1108 if (T->getQualifier())
1109 T->getQualifier()->print(OS, Policy);
1110 OS << T->getIdentifier()->getName();
1111 TemplateSpecializationType::PrintTemplateArgumentList(OS,
1112 T->getArgs(),
1113 T->getNumArgs(),
1114 Policy);
1115 spaceBeforePlaceHolder(OS);
1116 }
printDependentTemplateSpecializationAfter(const DependentTemplateSpecializationType * T,raw_ostream & OS)1117 void TypePrinter::printDependentTemplateSpecializationAfter(
1118 const DependentTemplateSpecializationType *T, raw_ostream &OS) { }
1119
printPackExpansionBefore(const PackExpansionType * T,raw_ostream & OS)1120 void TypePrinter::printPackExpansionBefore(const PackExpansionType *T,
1121 raw_ostream &OS) {
1122 printBefore(T->getPattern(), OS);
1123 }
printPackExpansionAfter(const PackExpansionType * T,raw_ostream & OS)1124 void TypePrinter::printPackExpansionAfter(const PackExpansionType *T,
1125 raw_ostream &OS) {
1126 printAfter(T->getPattern(), OS);
1127 OS << "...";
1128 }
1129
printAttributedBefore(const AttributedType * T,raw_ostream & OS)1130 void TypePrinter::printAttributedBefore(const AttributedType *T,
1131 raw_ostream &OS) {
1132 // Prefer the macro forms of the GC and ownership qualifiers.
1133 if (T->getAttrKind() == AttributedType::attr_objc_gc ||
1134 T->getAttrKind() == AttributedType::attr_objc_ownership)
1135 return printBefore(T->getEquivalentType(), OS);
1136
1137 if (T->getAttrKind() == AttributedType::attr_objc_kindof)
1138 OS << "__kindof ";
1139
1140 printBefore(T->getModifiedType(), OS);
1141
1142 if (T->isMSTypeSpec()) {
1143 switch (T->getAttrKind()) {
1144 default: return;
1145 case AttributedType::attr_ptr32: OS << " __ptr32"; break;
1146 case AttributedType::attr_ptr64: OS << " __ptr64"; break;
1147 case AttributedType::attr_sptr: OS << " __sptr"; break;
1148 case AttributedType::attr_uptr: OS << " __uptr"; break;
1149 }
1150 spaceBeforePlaceHolder(OS);
1151 }
1152
1153 // Print nullability type specifiers.
1154 if (T->getAttrKind() == AttributedType::attr_nonnull ||
1155 T->getAttrKind() == AttributedType::attr_nullable ||
1156 T->getAttrKind() == AttributedType::attr_null_unspecified) {
1157 if (T->getAttrKind() == AttributedType::attr_nonnull)
1158 OS << " _Nonnull";
1159 else if (T->getAttrKind() == AttributedType::attr_nullable)
1160 OS << " _Nullable";
1161 else if (T->getAttrKind() == AttributedType::attr_null_unspecified)
1162 OS << " _Null_unspecified";
1163 else
1164 llvm_unreachable("unhandled nullability");
1165 spaceBeforePlaceHolder(OS);
1166 }
1167 }
1168
printAttributedAfter(const AttributedType * T,raw_ostream & OS)1169 void TypePrinter::printAttributedAfter(const AttributedType *T,
1170 raw_ostream &OS) {
1171 // Prefer the macro forms of the GC and ownership qualifiers.
1172 if (T->getAttrKind() == AttributedType::attr_objc_gc ||
1173 T->getAttrKind() == AttributedType::attr_objc_ownership)
1174 return printAfter(T->getEquivalentType(), OS);
1175
1176 if (T->getAttrKind() == AttributedType::attr_objc_kindof)
1177 return;
1178
1179 // TODO: not all attributes are GCC-style attributes.
1180 if (T->isMSTypeSpec())
1181 return;
1182
1183 // Nothing to print after.
1184 if (T->getAttrKind() == AttributedType::attr_nonnull ||
1185 T->getAttrKind() == AttributedType::attr_nullable ||
1186 T->getAttrKind() == AttributedType::attr_null_unspecified)
1187 return printAfter(T->getModifiedType(), OS);
1188
1189 // If this is a calling convention attribute, don't print the implicit CC from
1190 // the modified type.
1191 SaveAndRestore<bool> MaybeSuppressCC(InsideCCAttribute, T->isCallingConv());
1192
1193 printAfter(T->getModifiedType(), OS);
1194
1195 // Don't print the inert __unsafe_unretained attribute at all.
1196 if (T->getAttrKind() == AttributedType::attr_objc_inert_unsafe_unretained)
1197 return;
1198
1199 // Print nullability type specifiers that occur after
1200 if (T->getAttrKind() == AttributedType::attr_nonnull ||
1201 T->getAttrKind() == AttributedType::attr_nullable ||
1202 T->getAttrKind() == AttributedType::attr_null_unspecified) {
1203 if (T->getAttrKind() == AttributedType::attr_nonnull)
1204 OS << " _Nonnull";
1205 else if (T->getAttrKind() == AttributedType::attr_nullable)
1206 OS << " _Nullable";
1207 else if (T->getAttrKind() == AttributedType::attr_null_unspecified)
1208 OS << " _Null_unspecified";
1209 else
1210 llvm_unreachable("unhandled nullability");
1211
1212 return;
1213 }
1214
1215 OS << " __attribute__((";
1216 switch (T->getAttrKind()) {
1217 default: llvm_unreachable("This attribute should have been handled already");
1218 case AttributedType::attr_address_space:
1219 OS << "address_space(";
1220 OS << T->getEquivalentType().getAddressSpace();
1221 OS << ')';
1222 break;
1223
1224 case AttributedType::attr_vector_size: {
1225 OS << "__vector_size__(";
1226 if (const VectorType *vector =T->getEquivalentType()->getAs<VectorType>()) {
1227 OS << vector->getNumElements();
1228 OS << " * sizeof(";
1229 print(vector->getElementType(), OS, StringRef());
1230 OS << ')';
1231 }
1232 OS << ')';
1233 break;
1234 }
1235
1236 case AttributedType::attr_neon_vector_type:
1237 case AttributedType::attr_neon_polyvector_type: {
1238 if (T->getAttrKind() == AttributedType::attr_neon_vector_type)
1239 OS << "neon_vector_type(";
1240 else
1241 OS << "neon_polyvector_type(";
1242 const VectorType *vector = T->getEquivalentType()->getAs<VectorType>();
1243 OS << vector->getNumElements();
1244 OS << ')';
1245 break;
1246 }
1247
1248 case AttributedType::attr_regparm: {
1249 // FIXME: When Sema learns to form this AttributedType, avoid printing the
1250 // attribute again in printFunctionProtoAfter.
1251 OS << "regparm(";
1252 QualType t = T->getEquivalentType();
1253 while (!t->isFunctionType())
1254 t = t->getPointeeType();
1255 OS << t->getAs<FunctionType>()->getRegParmType();
1256 OS << ')';
1257 break;
1258 }
1259
1260 case AttributedType::attr_objc_gc: {
1261 OS << "objc_gc(";
1262
1263 QualType tmp = T->getEquivalentType();
1264 while (tmp.getObjCGCAttr() == Qualifiers::GCNone) {
1265 QualType next = tmp->getPointeeType();
1266 if (next == tmp) break;
1267 tmp = next;
1268 }
1269
1270 if (tmp.isObjCGCWeak())
1271 OS << "weak";
1272 else
1273 OS << "strong";
1274 OS << ')';
1275 break;
1276 }
1277
1278 case AttributedType::attr_objc_ownership:
1279 OS << "objc_ownership(";
1280 switch (T->getEquivalentType().getObjCLifetime()) {
1281 case Qualifiers::OCL_None: llvm_unreachable("no ownership!");
1282 case Qualifiers::OCL_ExplicitNone: OS << "none"; break;
1283 case Qualifiers::OCL_Strong: OS << "strong"; break;
1284 case Qualifiers::OCL_Weak: OS << "weak"; break;
1285 case Qualifiers::OCL_Autoreleasing: OS << "autoreleasing"; break;
1286 }
1287 OS << ')';
1288 break;
1289
1290 // FIXME: When Sema learns to form this AttributedType, avoid printing the
1291 // attribute again in printFunctionProtoAfter.
1292 case AttributedType::attr_noreturn: OS << "noreturn"; break;
1293
1294 case AttributedType::attr_cdecl: OS << "cdecl"; break;
1295 case AttributedType::attr_fastcall: OS << "fastcall"; break;
1296 case AttributedType::attr_stdcall: OS << "stdcall"; break;
1297 case AttributedType::attr_thiscall: OS << "thiscall"; break;
1298 case AttributedType::attr_vectorcall: OS << "vectorcall"; break;
1299 case AttributedType::attr_pascal: OS << "pascal"; break;
1300 case AttributedType::attr_ms_abi: OS << "ms_abi"; break;
1301 case AttributedType::attr_sysv_abi: OS << "sysv_abi"; break;
1302 case AttributedType::attr_pcs:
1303 case AttributedType::attr_pcs_vfp: {
1304 OS << "pcs(";
1305 QualType t = T->getEquivalentType();
1306 while (!t->isFunctionType())
1307 t = t->getPointeeType();
1308 OS << (t->getAs<FunctionType>()->getCallConv() == CC_AAPCS ?
1309 "\"aapcs\"" : "\"aapcs-vfp\"");
1310 OS << ')';
1311 break;
1312 }
1313 case AttributedType::attr_inteloclbicc: OS << "inteloclbicc"; break;
1314 }
1315 OS << "))";
1316 }
1317
printObjCInterfaceBefore(const ObjCInterfaceType * T,raw_ostream & OS)1318 void TypePrinter::printObjCInterfaceBefore(const ObjCInterfaceType *T,
1319 raw_ostream &OS) {
1320 OS << T->getDecl()->getName();
1321 spaceBeforePlaceHolder(OS);
1322 }
printObjCInterfaceAfter(const ObjCInterfaceType * T,raw_ostream & OS)1323 void TypePrinter::printObjCInterfaceAfter(const ObjCInterfaceType *T,
1324 raw_ostream &OS) { }
1325
printObjCObjectBefore(const ObjCObjectType * T,raw_ostream & OS)1326 void TypePrinter::printObjCObjectBefore(const ObjCObjectType *T,
1327 raw_ostream &OS) {
1328 if (T->qual_empty() && T->isUnspecializedAsWritten() &&
1329 !T->isKindOfTypeAsWritten())
1330 return printBefore(T->getBaseType(), OS);
1331
1332 if (T->isKindOfTypeAsWritten())
1333 OS << "__kindof ";
1334
1335 print(T->getBaseType(), OS, StringRef());
1336
1337 if (T->isSpecializedAsWritten()) {
1338 bool isFirst = true;
1339 OS << '<';
1340 for (auto typeArg : T->getTypeArgsAsWritten()) {
1341 if (isFirst)
1342 isFirst = false;
1343 else
1344 OS << ",";
1345
1346 print(typeArg, OS, StringRef());
1347 }
1348 OS << '>';
1349 }
1350
1351 if (!T->qual_empty()) {
1352 bool isFirst = true;
1353 OS << '<';
1354 for (const auto *I : T->quals()) {
1355 if (isFirst)
1356 isFirst = false;
1357 else
1358 OS << ',';
1359 OS << I->getName();
1360 }
1361 OS << '>';
1362 }
1363
1364 spaceBeforePlaceHolder(OS);
1365 }
printObjCObjectAfter(const ObjCObjectType * T,raw_ostream & OS)1366 void TypePrinter::printObjCObjectAfter(const ObjCObjectType *T,
1367 raw_ostream &OS) {
1368 if (T->qual_empty() && T->isUnspecializedAsWritten() &&
1369 !T->isKindOfTypeAsWritten())
1370 return printAfter(T->getBaseType(), OS);
1371 }
1372
printObjCObjectPointerBefore(const ObjCObjectPointerType * T,raw_ostream & OS)1373 void TypePrinter::printObjCObjectPointerBefore(const ObjCObjectPointerType *T,
1374 raw_ostream &OS) {
1375 printBefore(T->getPointeeType(), OS);
1376
1377 // If we need to print the pointer, print it now.
1378 if (!T->isObjCIdType() && !T->isObjCQualifiedIdType() &&
1379 !T->isObjCClassType() && !T->isObjCQualifiedClassType()) {
1380 if (HasEmptyPlaceHolder)
1381 OS << ' ';
1382 OS << '*';
1383 }
1384 }
printObjCObjectPointerAfter(const ObjCObjectPointerType * T,raw_ostream & OS)1385 void TypePrinter::printObjCObjectPointerAfter(const ObjCObjectPointerType *T,
1386 raw_ostream &OS) { }
1387
1388 void TemplateSpecializationType::
PrintTemplateArgumentList(raw_ostream & OS,const TemplateArgumentListInfo & Args,const PrintingPolicy & Policy)1389 PrintTemplateArgumentList(raw_ostream &OS,
1390 const TemplateArgumentListInfo &Args,
1391 const PrintingPolicy &Policy) {
1392 return PrintTemplateArgumentList(OS,
1393 Args.getArgumentArray(),
1394 Args.size(),
1395 Policy);
1396 }
1397
1398 void
PrintTemplateArgumentList(raw_ostream & OS,const TemplateArgument * Args,unsigned NumArgs,const PrintingPolicy & Policy,bool SkipBrackets)1399 TemplateSpecializationType::PrintTemplateArgumentList(
1400 raw_ostream &OS,
1401 const TemplateArgument *Args,
1402 unsigned NumArgs,
1403 const PrintingPolicy &Policy,
1404 bool SkipBrackets) {
1405 const char *Comma = Policy.MSVCFormatting ? "," : ", ";
1406 if (!SkipBrackets)
1407 OS << '<';
1408
1409 bool needSpace = false;
1410 for (unsigned Arg = 0; Arg < NumArgs; ++Arg) {
1411 // Print the argument into a string.
1412 SmallString<128> Buf;
1413 llvm::raw_svector_ostream ArgOS(Buf);
1414 if (Args[Arg].getKind() == TemplateArgument::Pack) {
1415 if (Args[Arg].pack_size() && Arg > 0)
1416 OS << Comma;
1417 PrintTemplateArgumentList(ArgOS,
1418 Args[Arg].pack_begin(),
1419 Args[Arg].pack_size(),
1420 Policy, true);
1421 } else {
1422 if (Arg > 0)
1423 OS << Comma;
1424 Args[Arg].print(Policy, ArgOS);
1425 }
1426 StringRef ArgString = ArgOS.str();
1427
1428 // If this is the first argument and its string representation
1429 // begins with the global scope specifier ('::foo'), add a space
1430 // to avoid printing the diagraph '<:'.
1431 if (!Arg && !ArgString.empty() && ArgString[0] == ':')
1432 OS << ' ';
1433
1434 OS << ArgString;
1435
1436 needSpace = (!ArgString.empty() && ArgString.back() == '>');
1437 }
1438
1439 // If the last character of our string is '>', add another space to
1440 // keep the two '>''s separate tokens. We don't *have* to do this in
1441 // C++0x, but it's still good hygiene.
1442 if (needSpace)
1443 OS << ' ';
1444
1445 if (!SkipBrackets)
1446 OS << '>';
1447 }
1448
1449 // Sadly, repeat all that with TemplateArgLoc.
1450 void TemplateSpecializationType::
PrintTemplateArgumentList(raw_ostream & OS,const TemplateArgumentLoc * Args,unsigned NumArgs,const PrintingPolicy & Policy)1451 PrintTemplateArgumentList(raw_ostream &OS,
1452 const TemplateArgumentLoc *Args, unsigned NumArgs,
1453 const PrintingPolicy &Policy) {
1454 OS << '<';
1455 const char *Comma = Policy.MSVCFormatting ? "," : ", ";
1456
1457 bool needSpace = false;
1458 for (unsigned Arg = 0; Arg < NumArgs; ++Arg) {
1459 if (Arg > 0)
1460 OS << Comma;
1461
1462 // Print the argument into a string.
1463 SmallString<128> Buf;
1464 llvm::raw_svector_ostream ArgOS(Buf);
1465 if (Args[Arg].getArgument().getKind() == TemplateArgument::Pack) {
1466 PrintTemplateArgumentList(ArgOS,
1467 Args[Arg].getArgument().pack_begin(),
1468 Args[Arg].getArgument().pack_size(),
1469 Policy, true);
1470 } else {
1471 Args[Arg].getArgument().print(Policy, ArgOS);
1472 }
1473 StringRef ArgString = ArgOS.str();
1474
1475 // If this is the first argument and its string representation
1476 // begins with the global scope specifier ('::foo'), add a space
1477 // to avoid printing the diagraph '<:'.
1478 if (!Arg && !ArgString.empty() && ArgString[0] == ':')
1479 OS << ' ';
1480
1481 OS << ArgString;
1482
1483 needSpace = (!ArgString.empty() && ArgString.back() == '>');
1484 }
1485
1486 // If the last character of our string is '>', add another space to
1487 // keep the two '>''s separate tokens. We don't *have* to do this in
1488 // C++0x, but it's still good hygiene.
1489 if (needSpace)
1490 OS << ' ';
1491
1492 OS << '>';
1493 }
1494
getAsString() const1495 std::string Qualifiers::getAsString() const {
1496 LangOptions LO;
1497 return getAsString(PrintingPolicy(LO));
1498 }
1499
1500 // Appends qualifiers to the given string, separated by spaces. Will
1501 // prefix a space if the string is non-empty. Will not append a final
1502 // space.
getAsString(const PrintingPolicy & Policy) const1503 std::string Qualifiers::getAsString(const PrintingPolicy &Policy) const {
1504 SmallString<64> Buf;
1505 llvm::raw_svector_ostream StrOS(Buf);
1506 print(StrOS, Policy);
1507 return StrOS.str();
1508 }
1509
isEmptyWhenPrinted(const PrintingPolicy & Policy) const1510 bool Qualifiers::isEmptyWhenPrinted(const PrintingPolicy &Policy) const {
1511 if (getCVRQualifiers())
1512 return false;
1513
1514 if (getAddressSpace())
1515 return false;
1516
1517 if (getObjCGCAttr())
1518 return false;
1519
1520 if (Qualifiers::ObjCLifetime lifetime = getObjCLifetime())
1521 if (!(lifetime == Qualifiers::OCL_Strong && Policy.SuppressStrongLifetime))
1522 return false;
1523
1524 return true;
1525 }
1526
1527 // Appends qualifiers to the given string, separated by spaces. Will
1528 // prefix a space if the string is non-empty. Will not append a final
1529 // space.
print(raw_ostream & OS,const PrintingPolicy & Policy,bool appendSpaceIfNonEmpty) const1530 void Qualifiers::print(raw_ostream &OS, const PrintingPolicy& Policy,
1531 bool appendSpaceIfNonEmpty) const {
1532 bool addSpace = false;
1533
1534 unsigned quals = getCVRQualifiers();
1535 if (quals) {
1536 AppendTypeQualList(OS, quals, Policy.LangOpts.C99);
1537 addSpace = true;
1538 }
1539 if (unsigned addrspace = getAddressSpace()) {
1540 if (addSpace)
1541 OS << ' ';
1542 addSpace = true;
1543 switch (addrspace) {
1544 case LangAS::opencl_global:
1545 OS << "__global";
1546 break;
1547 case LangAS::opencl_local:
1548 OS << "__local";
1549 break;
1550 case LangAS::opencl_constant:
1551 OS << "__constant";
1552 break;
1553 case LangAS::opencl_generic:
1554 OS << "__generic";
1555 break;
1556 default:
1557 OS << "__attribute__((address_space(";
1558 OS << addrspace;
1559 OS << ")))";
1560 }
1561 }
1562 if (Qualifiers::GC gc = getObjCGCAttr()) {
1563 if (addSpace)
1564 OS << ' ';
1565 addSpace = true;
1566 if (gc == Qualifiers::Weak)
1567 OS << "__weak";
1568 else
1569 OS << "__strong";
1570 }
1571 if (Qualifiers::ObjCLifetime lifetime = getObjCLifetime()) {
1572 if (!(lifetime == Qualifiers::OCL_Strong && Policy.SuppressStrongLifetime)){
1573 if (addSpace)
1574 OS << ' ';
1575 addSpace = true;
1576 }
1577
1578 switch (lifetime) {
1579 case Qualifiers::OCL_None: llvm_unreachable("none but true");
1580 case Qualifiers::OCL_ExplicitNone: OS << "__unsafe_unretained"; break;
1581 case Qualifiers::OCL_Strong:
1582 if (!Policy.SuppressStrongLifetime)
1583 OS << "__strong";
1584 break;
1585
1586 case Qualifiers::OCL_Weak: OS << "__weak"; break;
1587 case Qualifiers::OCL_Autoreleasing: OS << "__autoreleasing"; break;
1588 }
1589 }
1590
1591 if (appendSpaceIfNonEmpty && addSpace)
1592 OS << ' ';
1593 }
1594
getAsString(const PrintingPolicy & Policy) const1595 std::string QualType::getAsString(const PrintingPolicy &Policy) const {
1596 std::string S;
1597 getAsStringInternal(S, Policy);
1598 return S;
1599 }
1600
getAsString(const Type * ty,Qualifiers qs)1601 std::string QualType::getAsString(const Type *ty, Qualifiers qs) {
1602 std::string buffer;
1603 LangOptions options;
1604 getAsStringInternal(ty, qs, buffer, PrintingPolicy(options));
1605 return buffer;
1606 }
1607
print(const Type * ty,Qualifiers qs,raw_ostream & OS,const PrintingPolicy & policy,const Twine & PlaceHolder)1608 void QualType::print(const Type *ty, Qualifiers qs,
1609 raw_ostream &OS, const PrintingPolicy &policy,
1610 const Twine &PlaceHolder) {
1611 SmallString<128> PHBuf;
1612 StringRef PH = PlaceHolder.toStringRef(PHBuf);
1613
1614 TypePrinter(policy).print(ty, qs, OS, PH);
1615 }
1616
getAsStringInternal(const Type * ty,Qualifiers qs,std::string & buffer,const PrintingPolicy & policy)1617 void QualType::getAsStringInternal(const Type *ty, Qualifiers qs,
1618 std::string &buffer,
1619 const PrintingPolicy &policy) {
1620 SmallString<256> Buf;
1621 llvm::raw_svector_ostream StrOS(Buf);
1622 TypePrinter(policy).print(ty, qs, StrOS, buffer);
1623 std::string str = StrOS.str();
1624 buffer.swap(str);
1625 }
1626