1//===- TypePrinter.cpp - Pretty-Print Clang Types -------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This contains code to print types from Clang's type system.
10//
11//===----------------------------------------------------------------------===//
12
13#include "clang/AST/ASTContext.h"
14#include "clang/AST/Attr.h"
15#include "clang/AST/Decl.h"
16#include "clang/AST/DeclBase.h"
17#include "clang/AST/DeclCXX.h"
18#include "clang/AST/DeclObjC.h"
19#include "clang/AST/DeclTemplate.h"
20#include "clang/AST/Expr.h"
21#include "clang/AST/NestedNameSpecifier.h"
22#include "clang/AST/PrettyPrinter.h"
23#include "clang/AST/TemplateBase.h"
24#include "clang/AST/TemplateName.h"
25#include "clang/AST/TextNodeDumper.h"
26#include "clang/AST/Type.h"
27#include "clang/Basic/AddressSpaces.h"
28#include "clang/Basic/ExceptionSpecificationType.h"
29#include "clang/Basic/IdentifierTable.h"
30#include "clang/Basic/LLVM.h"
31#include "clang/Basic/LangOptions.h"
32#include "clang/Basic/SourceLocation.h"
33#include "clang/Basic/SourceManager.h"
34#include "clang/Basic/Specifiers.h"
35#include "llvm/ADT/ArrayRef.h"
36#include "llvm/ADT/DenseMap.h"
37#include "llvm/ADT/SmallString.h"
38#include "llvm/ADT/StringRef.h"
39#include "llvm/ADT/Twine.h"
40#include "llvm/Support/Casting.h"
41#include "llvm/Support/Compiler.h"
42#include "llvm/Support/ErrorHandling.h"
43#include "llvm/Support/SaveAndRestore.h"
44#include "llvm/Support/raw_ostream.h"
45#include <cassert>
46#include <string>
47
48using namespace clang;
49
50namespace {
51
52/// RAII object that enables printing of the ARC __strong lifetime
53/// qualifier.
54class IncludeStrongLifetimeRAII {
55 PrintingPolicy &Policy;
56 bool Old;
57
58public:
59 explicit IncludeStrongLifetimeRAII(PrintingPolicy &Policy)
60 : Policy(Policy), Old(Policy.SuppressStrongLifetime) {
61 if (!Policy.SuppressLifetimeQualifiers)
62 Policy.SuppressStrongLifetime = false;
63 }
64
65 ~IncludeStrongLifetimeRAII() { Policy.SuppressStrongLifetime = Old; }
66};
67
68class ParamPolicyRAII {
69 PrintingPolicy &Policy;
70 bool Old;
71
72public:
73 explicit ParamPolicyRAII(PrintingPolicy &Policy)
74 : Policy(Policy), Old(Policy.SuppressSpecifiers) {
75 Policy.SuppressSpecifiers = false;
76 }
77
78 ~ParamPolicyRAII() { Policy.SuppressSpecifiers = Old; }
79};
80
81class DefaultTemplateArgsPolicyRAII {
82 PrintingPolicy &Policy;
83 bool Old;
84
85public:
86 explicit DefaultTemplateArgsPolicyRAII(PrintingPolicy &Policy)
87 : Policy(Policy), Old(Policy.SuppressDefaultTemplateArgs) {
88 Policy.SuppressDefaultTemplateArgs = false;
89 }
90
91 ~DefaultTemplateArgsPolicyRAII() { Policy.SuppressDefaultTemplateArgs = Old; }
92};
93
94class ElaboratedTypePolicyRAII {
95 PrintingPolicy &Policy;
96 bool SuppressTagKeyword;
97 bool SuppressScope;
98
99public:
100 explicit ElaboratedTypePolicyRAII(PrintingPolicy &Policy) : Policy(Policy) {
101 SuppressTagKeyword = Policy.SuppressTagKeyword;
102 SuppressScope = Policy.SuppressScope;
103 Policy.SuppressTagKeyword = true;
104 Policy.SuppressScope = true;
105 }
106
107 ~ElaboratedTypePolicyRAII() {
108 Policy.SuppressTagKeyword = SuppressTagKeyword;
109 Policy.SuppressScope = SuppressScope;
110 }
111};
112
113class TypePrinter {
114 PrintingPolicy Policy;
115 unsigned Indentation;
116 bool HasEmptyPlaceHolder = false;
117 bool InsideCCAttribute = false;
118
119public:
120 explicit TypePrinter(const PrintingPolicy &Policy, unsigned Indentation = 0)
121 : Policy(Policy), Indentation(Indentation) {}
122
123 void print(const Type *ty, Qualifiers qs, raw_ostream &OS,
124 StringRef PlaceHolder);
125 void print(QualType T, raw_ostream &OS, StringRef PlaceHolder);
126
127 static bool canPrefixQualifiers(const Type *T, bool &NeedARCStrongQualifier);
128 void spaceBeforePlaceHolder(raw_ostream &OS);
129 void printTypeSpec(NamedDecl *D, raw_ostream &OS);
130 void printTemplateId(const TemplateSpecializationType *T, raw_ostream &OS,
131 bool FullyQualify);
132
133 void printBefore(QualType T, raw_ostream &OS);
134 void printAfter(QualType T, raw_ostream &OS);
135 void AppendScope(DeclContext *DC, raw_ostream &OS,
136 DeclarationName NameInScope);
137 void printTag(TagDecl *T, raw_ostream &OS);
138 void printFunctionAfter(const FunctionType::ExtInfo &Info, raw_ostream &OS);
139#define ABSTRACT_TYPE(CLASS, PARENT)
140#define TYPE(CLASS, PARENT) \
141 void print##CLASS##Before(const CLASS##Type *T, raw_ostream &OS); \
142 void print##CLASS##After(const CLASS##Type *T, raw_ostream &OS);
143#include "clang/AST/TypeNodes.inc"
144
145private:
146 void printBefore(const Type *ty, Qualifiers qs, raw_ostream &OS);
147 void printAfter(const Type *ty, Qualifiers qs, raw_ostream &OS);
148};
149
150} // namespace
151
152static void AppendTypeQualList(raw_ostream &OS, unsigned TypeQuals,
153 bool HasRestrictKeyword) {
154 bool appendSpace = false;
155 if (TypeQuals & Qualifiers::Const) {
156 OS << "const";
157 appendSpace = true;
158 }
159 if (TypeQuals & Qualifiers::Volatile) {
160 if (appendSpace) OS << ' ';
161 OS << "volatile";
162 appendSpace = true;
163 }
164 if (TypeQuals & Qualifiers::Restrict) {
165 if (appendSpace) OS << ' ';
166 if (HasRestrictKeyword) {
167 OS << "restrict";
168 } else {
169 OS << "__restrict";
170 }
171 }
172}
173
174void TypePrinter::spaceBeforePlaceHolder(raw_ostream &OS) {
175 if (!HasEmptyPlaceHolder)
176 OS << ' ';
177}
178
179static SplitQualType splitAccordingToPolicy(QualType QT,
180 const PrintingPolicy &Policy) {
181 if (Policy.PrintCanonicalTypes)
182 QT = QT.getCanonicalType();
183 return QT.split();
184}
185
186void TypePrinter::print(QualType t, raw_ostream &OS, StringRef PlaceHolder) {
187 SplitQualType split = splitAccordingToPolicy(QT: t, Policy);
188 print(ty: split.Ty, qs: split.Quals, OS, PlaceHolder);
189}
190
191void TypePrinter::print(const Type *T, Qualifiers Quals, raw_ostream &OS,
192 StringRef PlaceHolder) {
193 if (!T) {
194 OS << "NULL TYPE";
195 return;
196 }
197
198 SaveAndRestore PHVal(HasEmptyPlaceHolder, PlaceHolder.empty());
199
200 printBefore(ty: T, qs: Quals, OS);
201 OS << PlaceHolder;
202 printAfter(ty: T, qs: Quals, OS);
203}
204
205bool TypePrinter::canPrefixQualifiers(const Type *T,
206 bool &NeedARCStrongQualifier) {
207 // CanPrefixQualifiers - We prefer to print type qualifiers before the type,
208 // so that we get "const int" instead of "int const", but we can't do this if
209 // the type is complex. For example if the type is "int*", we *must* print
210 // "int * const", printing "const int *" is different. Only do this when the
211 // type expands to a simple string.
212 bool CanPrefixQualifiers = false;
213 NeedARCStrongQualifier = false;
214 const Type *UnderlyingType = T;
215 if (const auto *AT = dyn_cast<AutoType>(Val: T))
216 UnderlyingType = AT->desugar().getTypePtr();
217 if (const auto *Subst = dyn_cast<SubstTemplateTypeParmType>(Val: T))
218 UnderlyingType = Subst->getReplacementType().getTypePtr();
219 Type::TypeClass TC = UnderlyingType->getTypeClass();
220
221 switch (TC) {
222 case Type::Auto:
223 case Type::Builtin:
224 case Type::Complex:
225 case Type::UnresolvedUsing:
226 case Type::Using:
227 case Type::Typedef:
228 case Type::TypeOfExpr:
229 case Type::TypeOf:
230 case Type::Decltype:
231 case Type::UnaryTransform:
232 case Type::Record:
233 case Type::Enum:
234 case Type::Elaborated:
235 case Type::TemplateTypeParm:
236 case Type::SubstTemplateTypeParmPack:
237 case Type::DeducedTemplateSpecialization:
238 case Type::TemplateSpecialization:
239 case Type::InjectedClassName:
240 case Type::DependentName:
241 case Type::DependentTemplateSpecialization:
242 case Type::ObjCObject:
243 case Type::ObjCTypeParam:
244 case Type::ObjCInterface:
245 case Type::Atomic:
246 case Type::Pipe:
247 case Type::BitInt:
248 case Type::DependentBitInt:
249 case Type::BTFTagAttributed:
250 CanPrefixQualifiers = true;
251 break;
252
253 case Type::ObjCObjectPointer:
254 CanPrefixQualifiers = T->isObjCIdType() || T->isObjCClassType() ||
255 T->isObjCQualifiedIdType() || T->isObjCQualifiedClassType();
256 break;
257
258 case Type::VariableArray:
259 case Type::DependentSizedArray:
260 NeedARCStrongQualifier = true;
261 [[fallthrough]];
262
263 case Type::ConstantArray:
264 case Type::IncompleteArray:
265 return canPrefixQualifiers(
266 T: cast<ArrayType>(Val: UnderlyingType)->getElementType().getTypePtr(),
267 NeedARCStrongQualifier);
268
269 case Type::Adjusted:
270 case Type::Decayed:
271 case Type::Pointer:
272 case Type::BlockPointer:
273 case Type::LValueReference:
274 case Type::RValueReference:
275 case Type::MemberPointer:
276 case Type::DependentAddressSpace:
277 case Type::DependentVector:
278 case Type::DependentSizedExtVector:
279 case Type::Vector:
280 case Type::ExtVector:
281 case Type::ConstantMatrix:
282 case Type::DependentSizedMatrix:
283 case Type::FunctionProto:
284 case Type::FunctionNoProto:
285 case Type::Paren:
286 case Type::PackExpansion:
287 case Type::SubstTemplateTypeParm:
288 case Type::MacroQualified:
289 CanPrefixQualifiers = false;
290 break;
291
292 case Type::Attributed: {
293 // We still want to print the address_space before the type if it is an
294 // address_space attribute.
295 const auto *AttrTy = cast<AttributedType>(Val: UnderlyingType);
296 CanPrefixQualifiers = AttrTy->getAttrKind() == attr::AddressSpace;
297 break;
298 }
299 case Type::PackIndexing: {
300 return canPrefixQualifiers(
301 T: cast<PackIndexingType>(Val: UnderlyingType)->getPattern().getTypePtr(),
302 NeedARCStrongQualifier);
303 }
304 }
305
306 return CanPrefixQualifiers;
307}
308
309void TypePrinter::printBefore(QualType T, raw_ostream &OS) {
310 SplitQualType Split = splitAccordingToPolicy(QT: T, Policy);
311
312 // If we have cv1 T, where T is substituted for cv2 U, only print cv1 - cv2
313 // at this level.
314 Qualifiers Quals = Split.Quals;
315 if (const auto *Subst = dyn_cast<SubstTemplateTypeParmType>(Val: Split.Ty))
316 Quals -= QualType(Subst, 0).getQualifiers();
317
318 printBefore(ty: Split.Ty, qs: Quals, OS);
319}
320
321/// Prints the part of the type string before an identifier, e.g. for
322/// "int foo[10]" it prints "int ".
323void TypePrinter::printBefore(const Type *T,Qualifiers Quals, raw_ostream &OS) {
324 if (Policy.SuppressSpecifiers && T->isSpecifierType())
325 return;
326
327 SaveAndRestore PrevPHIsEmpty(HasEmptyPlaceHolder);
328
329 // Print qualifiers as appropriate.
330
331 bool CanPrefixQualifiers = false;
332 bool NeedARCStrongQualifier = false;
333 CanPrefixQualifiers = canPrefixQualifiers(T, NeedARCStrongQualifier);
334
335 if (CanPrefixQualifiers && !Quals.empty()) {
336 if (NeedARCStrongQualifier) {
337 IncludeStrongLifetimeRAII Strong(Policy);
338 Quals.print(OS, Policy, /*appendSpaceIfNonEmpty=*/true);
339 } else {
340 Quals.print(OS, Policy, /*appendSpaceIfNonEmpty=*/true);
341 }
342 }
343
344 bool hasAfterQuals = false;
345 if (!CanPrefixQualifiers && !Quals.empty()) {
346 hasAfterQuals = !Quals.isEmptyWhenPrinted(Policy);
347 if (hasAfterQuals)
348 HasEmptyPlaceHolder = false;
349 }
350
351 switch (T->getTypeClass()) {
352#define ABSTRACT_TYPE(CLASS, PARENT)
353#define TYPE(CLASS, PARENT) case Type::CLASS: \
354 print##CLASS##Before(cast<CLASS##Type>(T), OS); \
355 break;
356#include "clang/AST/TypeNodes.inc"
357 }
358
359 if (hasAfterQuals) {
360 if (NeedARCStrongQualifier) {
361 IncludeStrongLifetimeRAII Strong(Policy);
362 Quals.print(OS, Policy, /*appendSpaceIfNonEmpty=*/!PrevPHIsEmpty.get());
363 } else {
364 Quals.print(OS, Policy, /*appendSpaceIfNonEmpty=*/!PrevPHIsEmpty.get());
365 }
366 }
367}
368
369void TypePrinter::printAfter(QualType t, raw_ostream &OS) {
370 SplitQualType split = splitAccordingToPolicy(QT: t, Policy);
371 printAfter(ty: split.Ty, qs: split.Quals, OS);
372}
373
374/// Prints the part of the type string after an identifier, e.g. for
375/// "int foo[10]" it prints "[10]".
376void TypePrinter::printAfter(const Type *T, Qualifiers Quals, raw_ostream &OS) {
377 switch (T->getTypeClass()) {
378#define ABSTRACT_TYPE(CLASS, PARENT)
379#define TYPE(CLASS, PARENT) case Type::CLASS: \
380 print##CLASS##After(cast<CLASS##Type>(T), OS); \
381 break;
382#include "clang/AST/TypeNodes.inc"
383 }
384}
385
386void TypePrinter::printBuiltinBefore(const BuiltinType *T, raw_ostream &OS) {
387 OS << T->getName(Policy);
388 spaceBeforePlaceHolder(OS);
389}
390
391void TypePrinter::printBuiltinAfter(const BuiltinType *T, raw_ostream &OS) {}
392
393void TypePrinter::printComplexBefore(const ComplexType *T, raw_ostream &OS) {
394 OS << "_Complex ";
395 printBefore(T: T->getElementType(), OS);
396}
397
398void TypePrinter::printComplexAfter(const ComplexType *T, raw_ostream &OS) {
399 printAfter(t: T->getElementType(), OS);
400}
401
402void TypePrinter::printPointerBefore(const PointerType *T, raw_ostream &OS) {
403 IncludeStrongLifetimeRAII Strong(Policy);
404 SaveAndRestore NonEmptyPH(HasEmptyPlaceHolder, false);
405 printBefore(T: T->getPointeeType(), OS);
406 // Handle things like 'int (*A)[4];' correctly.
407 // FIXME: this should include vectors, but vectors use attributes I guess.
408 if (isa<ArrayType>(Val: T->getPointeeType()))
409 OS << '(';
410 OS << '*';
411}
412
413void TypePrinter::printPointerAfter(const PointerType *T, raw_ostream &OS) {
414 IncludeStrongLifetimeRAII Strong(Policy);
415 SaveAndRestore NonEmptyPH(HasEmptyPlaceHolder, false);
416 // Handle things like 'int (*A)[4];' correctly.
417 // FIXME: this should include vectors, but vectors use attributes I guess.
418 if (isa<ArrayType>(Val: T->getPointeeType()))
419 OS << ')';
420 printAfter(t: T->getPointeeType(), OS);
421}
422
423void TypePrinter::printBlockPointerBefore(const BlockPointerType *T,
424 raw_ostream &OS) {
425 SaveAndRestore NonEmptyPH(HasEmptyPlaceHolder, false);
426 printBefore(T: T->getPointeeType(), OS);
427 OS << '^';
428}
429
430void TypePrinter::printBlockPointerAfter(const BlockPointerType *T,
431 raw_ostream &OS) {
432 SaveAndRestore NonEmptyPH(HasEmptyPlaceHolder, false);
433 printAfter(t: T->getPointeeType(), OS);
434}
435
436// When printing a reference, the referenced type might also be a reference.
437// If so, we want to skip that before printing the inner type.
438static QualType skipTopLevelReferences(QualType T) {
439 if (auto *Ref = T->getAs<ReferenceType>())
440 return skipTopLevelReferences(T: Ref->getPointeeTypeAsWritten());
441 return T;
442}
443
444void TypePrinter::printLValueReferenceBefore(const LValueReferenceType *T,
445 raw_ostream &OS) {
446 IncludeStrongLifetimeRAII Strong(Policy);
447 SaveAndRestore NonEmptyPH(HasEmptyPlaceHolder, false);
448 QualType Inner = skipTopLevelReferences(T->getPointeeTypeAsWritten());
449 printBefore(T: Inner, OS);
450 // Handle things like 'int (&A)[4];' correctly.
451 // FIXME: this should include vectors, but vectors use attributes I guess.
452 if (isa<ArrayType>(Val: Inner))
453 OS << '(';
454 OS << '&';
455}
456
457void TypePrinter::printLValueReferenceAfter(const LValueReferenceType *T,
458 raw_ostream &OS) {
459 IncludeStrongLifetimeRAII Strong(Policy);
460 SaveAndRestore NonEmptyPH(HasEmptyPlaceHolder, false);
461 QualType Inner = skipTopLevelReferences(T->getPointeeTypeAsWritten());
462 // Handle things like 'int (&A)[4];' correctly.
463 // FIXME: this should include vectors, but vectors use attributes I guess.
464 if (isa<ArrayType>(Val: Inner))
465 OS << ')';
466 printAfter(t: Inner, OS);
467}
468
469void TypePrinter::printRValueReferenceBefore(const RValueReferenceType *T,
470 raw_ostream &OS) {
471 IncludeStrongLifetimeRAII Strong(Policy);
472 SaveAndRestore NonEmptyPH(HasEmptyPlaceHolder, false);
473 QualType Inner = skipTopLevelReferences(T->getPointeeTypeAsWritten());
474 printBefore(T: Inner, OS);
475 // Handle things like 'int (&&A)[4];' correctly.
476 // FIXME: this should include vectors, but vectors use attributes I guess.
477 if (isa<ArrayType>(Val: Inner))
478 OS << '(';
479 OS << "&&";
480}
481
482void TypePrinter::printRValueReferenceAfter(const RValueReferenceType *T,
483 raw_ostream &OS) {
484 IncludeStrongLifetimeRAII Strong(Policy);
485 SaveAndRestore NonEmptyPH(HasEmptyPlaceHolder, false);
486 QualType Inner = skipTopLevelReferences(T->getPointeeTypeAsWritten());
487 // Handle things like 'int (&&A)[4];' correctly.
488 // FIXME: this should include vectors, but vectors use attributes I guess.
489 if (isa<ArrayType>(Val: Inner))
490 OS << ')';
491 printAfter(t: Inner, OS);
492}
493
494void TypePrinter::printMemberPointerBefore(const MemberPointerType *T,
495 raw_ostream &OS) {
496 IncludeStrongLifetimeRAII Strong(Policy);
497 SaveAndRestore NonEmptyPH(HasEmptyPlaceHolder, false);
498 printBefore(T: T->getPointeeType(), OS);
499 // Handle things like 'int (Cls::*A)[4];' correctly.
500 // FIXME: this should include vectors, but vectors use attributes I guess.
501 if (isa<ArrayType>(Val: T->getPointeeType()))
502 OS << '(';
503
504 PrintingPolicy InnerPolicy(Policy);
505 InnerPolicy.IncludeTagDefinition = false;
506 TypePrinter(InnerPolicy).print(t: QualType(T->getClass(), 0), OS, PlaceHolder: StringRef());
507
508 OS << "::*";
509}
510
511void TypePrinter::printMemberPointerAfter(const MemberPointerType *T,
512 raw_ostream &OS) {
513 IncludeStrongLifetimeRAII Strong(Policy);
514 SaveAndRestore NonEmptyPH(HasEmptyPlaceHolder, false);
515 // Handle things like 'int (Cls::*A)[4];' correctly.
516 // FIXME: this should include vectors, but vectors use attributes I guess.
517 if (isa<ArrayType>(Val: T->getPointeeType()))
518 OS << ')';
519 printAfter(t: T->getPointeeType(), OS);
520}
521
522void TypePrinter::printConstantArrayBefore(const ConstantArrayType *T,
523 raw_ostream &OS) {
524 IncludeStrongLifetimeRAII Strong(Policy);
525 printBefore(T->getElementType(), OS);
526}
527
528void TypePrinter::printConstantArrayAfter(const ConstantArrayType *T,
529 raw_ostream &OS) {
530 OS << '[';
531 if (T->getIndexTypeQualifiers().hasQualifiers()) {
532 AppendTypeQualList(OS, T->getIndexTypeCVRQualifiers(),
533 Policy.Restrict);
534 OS << ' ';
535 }
536
537 if (T->getSizeModifier() == ArraySizeModifier::Static)
538 OS << "static ";
539
540 OS << T->getSize().getZExtValue() << ']';
541 printAfter(T->getElementType(), OS);
542}
543
544void TypePrinter::printIncompleteArrayBefore(const IncompleteArrayType *T,
545 raw_ostream &OS) {
546 IncludeStrongLifetimeRAII Strong(Policy);
547 printBefore(T->getElementType(), OS);
548}
549
550void TypePrinter::printIncompleteArrayAfter(const IncompleteArrayType *T,
551 raw_ostream &OS) {
552 OS << "[]";
553 printAfter(T->getElementType(), OS);
554}
555
556void TypePrinter::printVariableArrayBefore(const VariableArrayType *T,
557 raw_ostream &OS) {
558 IncludeStrongLifetimeRAII Strong(Policy);
559 printBefore(T->getElementType(), OS);
560}
561
562void TypePrinter::printVariableArrayAfter(const VariableArrayType *T,
563 raw_ostream &OS) {
564 OS << '[';
565 if (T->getIndexTypeQualifiers().hasQualifiers()) {
566 AppendTypeQualList(OS, T->getIndexTypeCVRQualifiers(), Policy.Restrict);
567 OS << ' ';
568 }
569
570 if (T->getSizeModifier() == ArraySizeModifier::Static)
571 OS << "static ";
572 else if (T->getSizeModifier() == ArraySizeModifier::Star)
573 OS << '*';
574
575 if (T->getSizeExpr())
576 T->getSizeExpr()->printPretty(OS, nullptr, Policy);
577 OS << ']';
578
579 printAfter(T->getElementType(), OS);
580}
581
582void TypePrinter::printAdjustedBefore(const AdjustedType *T, raw_ostream &OS) {
583 // Print the adjusted representation, otherwise the adjustment will be
584 // invisible.
585 printBefore(T: T->getAdjustedType(), OS);
586}
587
588void TypePrinter::printAdjustedAfter(const AdjustedType *T, raw_ostream &OS) {
589 printAfter(t: T->getAdjustedType(), OS);
590}
591
592void TypePrinter::printDecayedBefore(const DecayedType *T, raw_ostream &OS) {
593 // Print as though it's a pointer.
594 printAdjustedBefore(T, OS);
595}
596
597void TypePrinter::printDecayedAfter(const DecayedType *T, raw_ostream &OS) {
598 printAdjustedAfter(T, OS);
599}
600
601void TypePrinter::printDependentSizedArrayBefore(
602 const DependentSizedArrayType *T,
603 raw_ostream &OS) {
604 IncludeStrongLifetimeRAII Strong(Policy);
605 printBefore(T->getElementType(), OS);
606}
607
608void TypePrinter::printDependentSizedArrayAfter(
609 const DependentSizedArrayType *T,
610 raw_ostream &OS) {
611 OS << '[';
612 if (T->getSizeExpr())
613 T->getSizeExpr()->printPretty(OS, nullptr, Policy);
614 OS << ']';
615 printAfter(T->getElementType(), OS);
616}
617
618void TypePrinter::printDependentAddressSpaceBefore(
619 const DependentAddressSpaceType *T, raw_ostream &OS) {
620 printBefore(T: T->getPointeeType(), OS);
621}
622
623void TypePrinter::printDependentAddressSpaceAfter(
624 const DependentAddressSpaceType *T, raw_ostream &OS) {
625 OS << " __attribute__((address_space(";
626 if (T->getAddrSpaceExpr())
627 T->getAddrSpaceExpr()->printPretty(OS, nullptr, Policy);
628 OS << ")))";
629 printAfter(t: T->getPointeeType(), OS);
630}
631
632void TypePrinter::printDependentSizedExtVectorBefore(
633 const DependentSizedExtVectorType *T,
634 raw_ostream &OS) {
635 printBefore(T: T->getElementType(), OS);
636}
637
638void TypePrinter::printDependentSizedExtVectorAfter(
639 const DependentSizedExtVectorType *T,
640 raw_ostream &OS) {
641 OS << " __attribute__((ext_vector_type(";
642 if (T->getSizeExpr())
643 T->getSizeExpr()->printPretty(OS, nullptr, Policy);
644 OS << ")))";
645 printAfter(t: T->getElementType(), OS);
646}
647
648void TypePrinter::printVectorBefore(const VectorType *T, raw_ostream &OS) {
649 switch (T->getVectorKind()) {
650 case VectorKind::AltiVecPixel:
651 OS << "__vector __pixel ";
652 break;
653 case VectorKind::AltiVecBool:
654 OS << "__vector __bool ";
655 printBefore(T: T->getElementType(), OS);
656 break;
657 case VectorKind::AltiVecVector:
658 OS << "__vector ";
659 printBefore(T: T->getElementType(), OS);
660 break;
661 case VectorKind::Neon:
662 OS << "__attribute__((neon_vector_type("
663 << T->getNumElements() << "))) ";
664 printBefore(T: T->getElementType(), OS);
665 break;
666 case VectorKind::NeonPoly:
667 OS << "__attribute__((neon_polyvector_type(" <<
668 T->getNumElements() << "))) ";
669 printBefore(T: T->getElementType(), OS);
670 break;
671 case VectorKind::Generic: {
672 // FIXME: We prefer to print the size directly here, but have no way
673 // to get the size of the type.
674 OS << "__attribute__((__vector_size__("
675 << T->getNumElements()
676 << " * sizeof(";
677 print(t: T->getElementType(), OS, PlaceHolder: StringRef());
678 OS << ")))) ";
679 printBefore(T: T->getElementType(), OS);
680 break;
681 }
682 case VectorKind::SveFixedLengthData:
683 case VectorKind::SveFixedLengthPredicate:
684 // FIXME: We prefer to print the size directly here, but have no way
685 // to get the size of the type.
686 OS << "__attribute__((__arm_sve_vector_bits__(";
687
688 if (T->getVectorKind() == VectorKind::SveFixedLengthPredicate)
689 // Predicates take a bit per byte of the vector size, multiply by 8 to
690 // get the number of bits passed to the attribute.
691 OS << T->getNumElements() * 8;
692 else
693 OS << T->getNumElements();
694
695 OS << " * sizeof(";
696 print(t: T->getElementType(), OS, PlaceHolder: StringRef());
697 // Multiply by 8 for the number of bits.
698 OS << ") * 8))) ";
699 printBefore(T: T->getElementType(), OS);
700 break;
701 case VectorKind::RVVFixedLengthData:
702 case VectorKind::RVVFixedLengthMask:
703 // FIXME: We prefer to print the size directly here, but have no way
704 // to get the size of the type.
705 OS << "__attribute__((__riscv_rvv_vector_bits__(";
706
707 OS << T->getNumElements();
708
709 OS << " * sizeof(";
710 print(t: T->getElementType(), OS, PlaceHolder: StringRef());
711 // Multiply by 8 for the number of bits.
712 OS << ") * 8))) ";
713 printBefore(T: T->getElementType(), OS);
714 break;
715 }
716}
717
718void TypePrinter::printVectorAfter(const VectorType *T, raw_ostream &OS) {
719 printAfter(t: T->getElementType(), OS);
720}
721
722void TypePrinter::printDependentVectorBefore(
723 const DependentVectorType *T, raw_ostream &OS) {
724 switch (T->getVectorKind()) {
725 case VectorKind::AltiVecPixel:
726 OS << "__vector __pixel ";
727 break;
728 case VectorKind::AltiVecBool:
729 OS << "__vector __bool ";
730 printBefore(T: T->getElementType(), OS);
731 break;
732 case VectorKind::AltiVecVector:
733 OS << "__vector ";
734 printBefore(T: T->getElementType(), OS);
735 break;
736 case VectorKind::Neon:
737 OS << "__attribute__((neon_vector_type(";
738 if (T->getSizeExpr())
739 T->getSizeExpr()->printPretty(OS, nullptr, Policy);
740 OS << "))) ";
741 printBefore(T: T->getElementType(), OS);
742 break;
743 case VectorKind::NeonPoly:
744 OS << "__attribute__((neon_polyvector_type(";
745 if (T->getSizeExpr())
746 T->getSizeExpr()->printPretty(OS, nullptr, Policy);
747 OS << "))) ";
748 printBefore(T: T->getElementType(), OS);
749 break;
750 case VectorKind::Generic: {
751 // FIXME: We prefer to print the size directly here, but have no way
752 // to get the size of the type.
753 OS << "__attribute__((__vector_size__(";
754 if (T->getSizeExpr())
755 T->getSizeExpr()->printPretty(OS, nullptr, Policy);
756 OS << " * sizeof(";
757 print(t: T->getElementType(), OS, PlaceHolder: StringRef());
758 OS << ")))) ";
759 printBefore(T: T->getElementType(), OS);
760 break;
761 }
762 case VectorKind::SveFixedLengthData:
763 case VectorKind::SveFixedLengthPredicate:
764 // FIXME: We prefer to print the size directly here, but have no way
765 // to get the size of the type.
766 OS << "__attribute__((__arm_sve_vector_bits__(";
767 if (T->getSizeExpr()) {
768 T->getSizeExpr()->printPretty(OS, nullptr, Policy);
769 if (T->getVectorKind() == VectorKind::SveFixedLengthPredicate)
770 // Predicates take a bit per byte of the vector size, multiply by 8 to
771 // get the number of bits passed to the attribute.
772 OS << " * 8";
773 OS << " * sizeof(";
774 print(t: T->getElementType(), OS, PlaceHolder: StringRef());
775 // Multiply by 8 for the number of bits.
776 OS << ") * 8";
777 }
778 OS << "))) ";
779 printBefore(T: T->getElementType(), OS);
780 break;
781 case VectorKind::RVVFixedLengthData:
782 case VectorKind::RVVFixedLengthMask:
783 // FIXME: We prefer to print the size directly here, but have no way
784 // to get the size of the type.
785 OS << "__attribute__((__riscv_rvv_vector_bits__(";
786 if (T->getSizeExpr()) {
787 T->getSizeExpr()->printPretty(OS, nullptr, Policy);
788 OS << " * sizeof(";
789 print(t: T->getElementType(), OS, PlaceHolder: StringRef());
790 // Multiply by 8 for the number of bits.
791 OS << ") * 8";
792 }
793 OS << "))) ";
794 printBefore(T: T->getElementType(), OS);
795 break;
796 }
797}
798
799void TypePrinter::printDependentVectorAfter(
800 const DependentVectorType *T, raw_ostream &OS) {
801 printAfter(t: T->getElementType(), OS);
802}
803
804void TypePrinter::printExtVectorBefore(const ExtVectorType *T,
805 raw_ostream &OS) {
806 printBefore(T->getElementType(), OS);
807}
808
809void TypePrinter::printExtVectorAfter(const ExtVectorType *T, raw_ostream &OS) {
810 printAfter(T->getElementType(), OS);
811 OS << " __attribute__((ext_vector_type(";
812 OS << T->getNumElements();
813 OS << ")))";
814}
815
816void TypePrinter::printConstantMatrixBefore(const ConstantMatrixType *T,
817 raw_ostream &OS) {
818 printBefore(T->getElementType(), OS);
819 OS << " __attribute__((matrix_type(";
820 OS << T->getNumRows() << ", " << T->getNumColumns();
821 OS << ")))";
822}
823
824void TypePrinter::printConstantMatrixAfter(const ConstantMatrixType *T,
825 raw_ostream &OS) {
826 printAfter(T->getElementType(), OS);
827}
828
829void TypePrinter::printDependentSizedMatrixBefore(
830 const DependentSizedMatrixType *T, raw_ostream &OS) {
831 printBefore(T->getElementType(), OS);
832 OS << " __attribute__((matrix_type(";
833 if (T->getRowExpr()) {
834 T->getRowExpr()->printPretty(OS, nullptr, Policy);
835 }
836 OS << ", ";
837 if (T->getColumnExpr()) {
838 T->getColumnExpr()->printPretty(OS, nullptr, Policy);
839 }
840 OS << ")))";
841}
842
843void TypePrinter::printDependentSizedMatrixAfter(
844 const DependentSizedMatrixType *T, raw_ostream &OS) {
845 printAfter(T->getElementType(), OS);
846}
847
848void
849FunctionProtoType::printExceptionSpecification(raw_ostream &OS,
850 const PrintingPolicy &Policy)
851 const {
852 if (hasDynamicExceptionSpec()) {
853 OS << " throw(";
854 if (getExceptionSpecType() == EST_MSAny)
855 OS << "...";
856 else
857 for (unsigned I = 0, N = getNumExceptions(); I != N; ++I) {
858 if (I)
859 OS << ", ";
860
861 OS << getExceptionType(i: I).stream(Policy);
862 }
863 OS << ')';
864 } else if (EST_NoThrow == getExceptionSpecType()) {
865 OS << " __attribute__((nothrow))";
866 } else if (isNoexceptExceptionSpec(ESpecType: getExceptionSpecType())) {
867 OS << " noexcept";
868 // FIXME:Is it useful to print out the expression for a non-dependent
869 // noexcept specification?
870 if (isComputedNoexcept(ESpecType: getExceptionSpecType())) {
871 OS << '(';
872 if (getNoexceptExpr())
873 getNoexceptExpr()->printPretty(OS, nullptr, Policy);
874 OS << ')';
875 }
876 }
877}
878
879void TypePrinter::printFunctionProtoBefore(const FunctionProtoType *T,
880 raw_ostream &OS) {
881 if (T->hasTrailingReturn()) {
882 OS << "auto ";
883 if (!HasEmptyPlaceHolder)
884 OS << '(';
885 } else {
886 // If needed for precedence reasons, wrap the inner part in grouping parens.
887 SaveAndRestore PrevPHIsEmpty(HasEmptyPlaceHolder, false);
888 printBefore(T->getReturnType(), OS);
889 if (!PrevPHIsEmpty.get())
890 OS << '(';
891 }
892}
893
894StringRef clang::getParameterABISpelling(ParameterABI ABI) {
895 switch (ABI) {
896 case ParameterABI::Ordinary:
897 llvm_unreachable("asking for spelling of ordinary parameter ABI");
898 case ParameterABI::SwiftContext:
899 return "swift_context";
900 case ParameterABI::SwiftAsyncContext:
901 return "swift_async_context";
902 case ParameterABI::SwiftErrorResult:
903 return "swift_error_result";
904 case ParameterABI::SwiftIndirectResult:
905 return "swift_indirect_result";
906 }
907 llvm_unreachable("bad parameter ABI kind");
908}
909
910void TypePrinter::printFunctionProtoAfter(const FunctionProtoType *T,
911 raw_ostream &OS) {
912 // If needed for precedence reasons, wrap the inner part in grouping parens.
913 if (!HasEmptyPlaceHolder)
914 OS << ')';
915 SaveAndRestore NonEmptyPH(HasEmptyPlaceHolder, false);
916
917 OS << '(';
918 {
919 ParamPolicyRAII ParamPolicy(Policy);
920 for (unsigned i = 0, e = T->getNumParams(); i != e; ++i) {
921 if (i) OS << ", ";
922
923 auto EPI = T->getExtParameterInfo(I: i);
924 if (EPI.isConsumed()) OS << "__attribute__((ns_consumed)) ";
925 if (EPI.isNoEscape())
926 OS << "__attribute__((noescape)) ";
927 auto ABI = EPI.getABI();
928 if (ABI != ParameterABI::Ordinary)
929 OS << "__attribute__((" << getParameterABISpelling(ABI) << ")) ";
930
931 print(t: T->getParamType(i), OS, PlaceHolder: StringRef());
932 }
933 }
934
935 if (T->isVariadic()) {
936 if (T->getNumParams())
937 OS << ", ";
938 OS << "...";
939 } else if (T->getNumParams() == 0 && Policy.UseVoidForZeroParams) {
940 // Do not emit int() if we have a proto, emit 'int(void)'.
941 OS << "void";
942 }
943
944 OS << ')';
945
946 FunctionType::ExtInfo Info = T->getExtInfo();
947 unsigned SMEBits = T->getAArch64SMEAttributes();
948
949 if (SMEBits & FunctionType::SME_PStateSMCompatibleMask)
950 OS << " __arm_streaming_compatible";
951 if (SMEBits & FunctionType::SME_PStateSMEnabledMask)
952 OS << " __arm_streaming";
953 if (FunctionType::getArmZAState(AttrBits: SMEBits) == FunctionType::ARM_Preserves)
954 OS << " __arm_preserves(\"za\")";
955 if (FunctionType::getArmZAState(AttrBits: SMEBits) == FunctionType::ARM_In)
956 OS << " __arm_in(\"za\")";
957 if (FunctionType::getArmZAState(AttrBits: SMEBits) == FunctionType::ARM_Out)
958 OS << " __arm_out(\"za\")";
959 if (FunctionType::getArmZAState(AttrBits: SMEBits) == FunctionType::ARM_InOut)
960 OS << " __arm_inout(\"za\")";
961 if (FunctionType::getArmZT0State(AttrBits: SMEBits) == FunctionType::ARM_Preserves)
962 OS << " __arm_preserves(\"zt0\")";
963 if (FunctionType::getArmZT0State(AttrBits: SMEBits) == FunctionType::ARM_In)
964 OS << " __arm_in(\"zt0\")";
965 if (FunctionType::getArmZT0State(AttrBits: SMEBits) == FunctionType::ARM_Out)
966 OS << " __arm_out(\"zt0\")";
967 if (FunctionType::getArmZT0State(AttrBits: SMEBits) == FunctionType::ARM_InOut)
968 OS << " __arm_inout(\"zt0\")";
969
970 printFunctionAfter(Info, OS);
971
972 if (!T->getMethodQuals().empty())
973 OS << " " << T->getMethodQuals().getAsString();
974
975 switch (T->getRefQualifier()) {
976 case RQ_None:
977 break;
978
979 case RQ_LValue:
980 OS << " &";
981 break;
982
983 case RQ_RValue:
984 OS << " &&";
985 break;
986 }
987 T->printExceptionSpecification(OS, Policy);
988
989 if (T->hasTrailingReturn()) {
990 OS << " -> ";
991 print(T->getReturnType(), OS, StringRef());
992 } else
993 printAfter(T->getReturnType(), OS);
994}
995
996void TypePrinter::printFunctionAfter(const FunctionType::ExtInfo &Info,
997 raw_ostream &OS) {
998 if (!InsideCCAttribute) {
999 switch (Info.getCC()) {
1000 case CC_C:
1001 // The C calling convention is the default on the vast majority of platforms
1002 // we support. If the user wrote it explicitly, it will usually be printed
1003 // while traversing the AttributedType. If the type has been desugared, let
1004 // the canonical spelling be the implicit calling convention.
1005 // FIXME: It would be better to be explicit in certain contexts, such as a
1006 // cdecl function typedef used to declare a member function with the
1007 // Microsoft C++ ABI.
1008 break;
1009 case CC_X86StdCall:
1010 OS << " __attribute__((stdcall))";
1011 break;
1012 case CC_X86FastCall:
1013 OS << " __attribute__((fastcall))";
1014 break;
1015 case CC_X86ThisCall:
1016 OS << " __attribute__((thiscall))";
1017 break;
1018 case CC_X86VectorCall:
1019 OS << " __attribute__((vectorcall))";
1020 break;
1021 case CC_X86Pascal:
1022 OS << " __attribute__((pascal))";
1023 break;
1024 case CC_AAPCS:
1025 OS << " __attribute__((pcs(\"aapcs\")))";
1026 break;
1027 case CC_AAPCS_VFP:
1028 OS << " __attribute__((pcs(\"aapcs-vfp\")))";
1029 break;
1030 case CC_AArch64VectorCall:
1031 OS << "__attribute__((aarch64_vector_pcs))";
1032 break;
1033 case CC_AArch64SVEPCS:
1034 OS << "__attribute__((aarch64_sve_pcs))";
1035 break;
1036 case CC_AMDGPUKernelCall:
1037 OS << "__attribute__((amdgpu_kernel))";
1038 break;
1039 case CC_IntelOclBicc:
1040 OS << " __attribute__((intel_ocl_bicc))";
1041 break;
1042 case CC_Win64:
1043 OS << " __attribute__((ms_abi))";
1044 break;
1045 case CC_X86_64SysV:
1046 OS << " __attribute__((sysv_abi))";
1047 break;
1048 case CC_X86RegCall:
1049 OS << " __attribute__((regcall))";
1050 break;
1051 case CC_SpirFunction:
1052 case CC_OpenCLKernel:
1053 // Do nothing. These CCs are not available as attributes.
1054 break;
1055 case CC_Swift:
1056 OS << " __attribute__((swiftcall))";
1057 break;
1058 case CC_SwiftAsync:
1059 OS << "__attribute__((swiftasynccall))";
1060 break;
1061 case CC_PreserveMost:
1062 OS << " __attribute__((preserve_most))";
1063 break;
1064 case CC_PreserveAll:
1065 OS << " __attribute__((preserve_all))";
1066 break;
1067 case CC_M68kRTD:
1068 OS << " __attribute__((m68k_rtd))";
1069 break;
1070 case CC_PreserveNone:
1071 OS << " __attribute__((preserve_none))";
1072 break;
1073 }
1074 }
1075
1076 if (Info.getNoReturn())
1077 OS << " __attribute__((noreturn))";
1078 if (Info.getCmseNSCall())
1079 OS << " __attribute__((cmse_nonsecure_call))";
1080 if (Info.getProducesResult())
1081 OS << " __attribute__((ns_returns_retained))";
1082 if (Info.getRegParm())
1083 OS << " __attribute__((regparm ("
1084 << Info.getRegParm() << ")))";
1085 if (Info.getNoCallerSavedRegs())
1086 OS << " __attribute__((no_caller_saved_registers))";
1087 if (Info.getNoCfCheck())
1088 OS << " __attribute__((nocf_check))";
1089}
1090
1091void TypePrinter::printFunctionNoProtoBefore(const FunctionNoProtoType *T,
1092 raw_ostream &OS) {
1093 // If needed for precedence reasons, wrap the inner part in grouping parens.
1094 SaveAndRestore PrevPHIsEmpty(HasEmptyPlaceHolder, false);
1095 printBefore(T->getReturnType(), OS);
1096 if (!PrevPHIsEmpty.get())
1097 OS << '(';
1098}
1099
1100void TypePrinter::printFunctionNoProtoAfter(const FunctionNoProtoType *T,
1101 raw_ostream &OS) {
1102 // If needed for precedence reasons, wrap the inner part in grouping parens.
1103 if (!HasEmptyPlaceHolder)
1104 OS << ')';
1105 SaveAndRestore NonEmptyPH(HasEmptyPlaceHolder, false);
1106
1107 OS << "()";
1108 printFunctionAfter(Info: T->getExtInfo(), OS);
1109 printAfter(T->getReturnType(), OS);
1110}
1111
1112void TypePrinter::printTypeSpec(NamedDecl *D, raw_ostream &OS) {
1113
1114 // Compute the full nested-name-specifier for this type.
1115 // In C, this will always be empty except when the type
1116 // being printed is anonymous within other Record.
1117 if (!Policy.SuppressScope)
1118 AppendScope(DC: D->getDeclContext(), OS, NameInScope: D->getDeclName());
1119
1120 IdentifierInfo *II = D->getIdentifier();
1121 OS << II->getName();
1122 spaceBeforePlaceHolder(OS);
1123}
1124
1125void TypePrinter::printUnresolvedUsingBefore(const UnresolvedUsingType *T,
1126 raw_ostream &OS) {
1127 printTypeSpec(T->getDecl(), OS);
1128}
1129
1130void TypePrinter::printUnresolvedUsingAfter(const UnresolvedUsingType *T,
1131 raw_ostream &OS) {}
1132
1133void TypePrinter::printUsingBefore(const UsingType *T, raw_ostream &OS) {
1134 // After `namespace b { using a::X }`, is the type X within B a::X or b::X?
1135 //
1136 // - b::X is more formally correct given the UsingType model
1137 // - b::X makes sense if "re-exporting" a symbol in a new namespace
1138 // - a::X makes sense if "importing" a symbol for convenience
1139 //
1140 // The "importing" use seems much more common, so we print a::X.
1141 // This could be a policy option, but the right choice seems to rest more
1142 // with the intent of the code than the caller.
1143 printTypeSpec(D: T->getFoundDecl()->getUnderlyingDecl(), OS);
1144}
1145
1146void TypePrinter::printUsingAfter(const UsingType *T, raw_ostream &OS) {}
1147
1148void TypePrinter::printTypedefBefore(const TypedefType *T, raw_ostream &OS) {
1149 printTypeSpec(T->getDecl(), OS);
1150}
1151
1152void TypePrinter::printMacroQualifiedBefore(const MacroQualifiedType *T,
1153 raw_ostream &OS) {
1154 StringRef MacroName = T->getMacroIdentifier()->getName();
1155 OS << MacroName << " ";
1156
1157 // Since this type is meant to print the macro instead of the whole attribute,
1158 // we trim any attributes and go directly to the original modified type.
1159 printBefore(T: T->getModifiedType(), OS);
1160}
1161
1162void TypePrinter::printMacroQualifiedAfter(const MacroQualifiedType *T,
1163 raw_ostream &OS) {
1164 printAfter(t: T->getModifiedType(), OS);
1165}
1166
1167void TypePrinter::printTypedefAfter(const TypedefType *T, raw_ostream &OS) {}
1168
1169void TypePrinter::printTypeOfExprBefore(const TypeOfExprType *T,
1170 raw_ostream &OS) {
1171 OS << (T->getKind() == TypeOfKind::Unqualified ? "typeof_unqual "
1172 : "typeof ");
1173 if (T->getUnderlyingExpr())
1174 T->getUnderlyingExpr()->printPretty(OS, nullptr, Policy);
1175 spaceBeforePlaceHolder(OS);
1176}
1177
1178void TypePrinter::printTypeOfExprAfter(const TypeOfExprType *T,
1179 raw_ostream &OS) {}
1180
1181void TypePrinter::printTypeOfBefore(const TypeOfType *T, raw_ostream &OS) {
1182 OS << (T->getKind() == TypeOfKind::Unqualified ? "typeof_unqual("
1183 : "typeof(");
1184 print(t: T->getUnmodifiedType(), OS, PlaceHolder: StringRef());
1185 OS << ')';
1186 spaceBeforePlaceHolder(OS);
1187}
1188
1189void TypePrinter::printTypeOfAfter(const TypeOfType *T, raw_ostream &OS) {}
1190
1191void TypePrinter::printDecltypeBefore(const DecltypeType *T, raw_ostream &OS) {
1192 OS << "decltype(";
1193 if (T->getUnderlyingExpr())
1194 T->getUnderlyingExpr()->printPretty(OS, nullptr, Policy);
1195 OS << ')';
1196 spaceBeforePlaceHolder(OS);
1197}
1198
1199void TypePrinter::printPackIndexingBefore(const PackIndexingType *T,
1200 raw_ostream &OS) {
1201 if (T->hasSelectedType())
1202 OS << T->getSelectedType();
1203 else
1204 OS << T->getPattern() << "...[" << T->getIndexExpr() << "]";
1205 spaceBeforePlaceHolder(OS);
1206}
1207
1208void TypePrinter::printPackIndexingAfter(const PackIndexingType *T,
1209 raw_ostream &OS) {}
1210
1211void TypePrinter::printDecltypeAfter(const DecltypeType *T, raw_ostream &OS) {}
1212
1213void TypePrinter::printUnaryTransformBefore(const UnaryTransformType *T,
1214 raw_ostream &OS) {
1215 IncludeStrongLifetimeRAII Strong(Policy);
1216
1217 static llvm::DenseMap<int, const char *> Transformation = {{
1218#define TRANSFORM_TYPE_TRAIT_DEF(Enum, Trait) \
1219 {UnaryTransformType::Enum, "__" #Trait},
1220#include "clang/Basic/TransformTypeTraits.def"
1221 }};
1222 OS << Transformation[T->getUTTKind()] << '(';
1223 print(t: T->getBaseType(), OS, PlaceHolder: StringRef());
1224 OS << ')';
1225 spaceBeforePlaceHolder(OS);
1226}
1227
1228void TypePrinter::printUnaryTransformAfter(const UnaryTransformType *T,
1229 raw_ostream &OS) {}
1230
1231void TypePrinter::printAutoBefore(const AutoType *T, raw_ostream &OS) {
1232 // If the type has been deduced, do not print 'auto'.
1233 if (!T->getDeducedType().isNull()) {
1234 printBefore(T->getDeducedType(), OS);
1235 } else {
1236 if (T->isConstrained()) {
1237 // FIXME: Track a TypeConstraint as type sugar, so that we can print the
1238 // type as it was written.
1239 T->getTypeConstraintConcept()->getDeclName().print(OS, Policy);
1240 auto Args = T->getTypeConstraintArguments();
1241 if (!Args.empty())
1242 printTemplateArgumentList(
1243 OS, Args, Policy,
1244 T->getTypeConstraintConcept()->getTemplateParameters());
1245 OS << ' ';
1246 }
1247 switch (T->getKeyword()) {
1248 case AutoTypeKeyword::Auto: OS << "auto"; break;
1249 case AutoTypeKeyword::DecltypeAuto: OS << "decltype(auto)"; break;
1250 case AutoTypeKeyword::GNUAutoType: OS << "__auto_type"; break;
1251 }
1252 spaceBeforePlaceHolder(OS);
1253 }
1254}
1255
1256void TypePrinter::printAutoAfter(const AutoType *T, raw_ostream &OS) {
1257 // If the type has been deduced, do not print 'auto'.
1258 if (!T->getDeducedType().isNull())
1259 printAfter(T->getDeducedType(), OS);
1260}
1261
1262void TypePrinter::printDeducedTemplateSpecializationBefore(
1263 const DeducedTemplateSpecializationType *T, raw_ostream &OS) {
1264 // If the type has been deduced, print the deduced type.
1265 if (!T->getDeducedType().isNull()) {
1266 printBefore(T->getDeducedType(), OS);
1267 } else {
1268 IncludeStrongLifetimeRAII Strong(Policy);
1269 T->getTemplateName().print(OS, Policy);
1270 spaceBeforePlaceHolder(OS);
1271 }
1272}
1273
1274void TypePrinter::printDeducedTemplateSpecializationAfter(
1275 const DeducedTemplateSpecializationType *T, raw_ostream &OS) {
1276 // If the type has been deduced, print the deduced type.
1277 if (!T->getDeducedType().isNull())
1278 printAfter(T->getDeducedType(), OS);
1279}
1280
1281void TypePrinter::printAtomicBefore(const AtomicType *T, raw_ostream &OS) {
1282 IncludeStrongLifetimeRAII Strong(Policy);
1283
1284 OS << "_Atomic(";
1285 print(t: T->getValueType(), OS, PlaceHolder: StringRef());
1286 OS << ')';
1287 spaceBeforePlaceHolder(OS);
1288}
1289
1290void TypePrinter::printAtomicAfter(const AtomicType *T, raw_ostream &OS) {}
1291
1292void TypePrinter::printPipeBefore(const PipeType *T, raw_ostream &OS) {
1293 IncludeStrongLifetimeRAII Strong(Policy);
1294
1295 if (T->isReadOnly())
1296 OS << "read_only ";
1297 else
1298 OS << "write_only ";
1299 OS << "pipe ";
1300 print(t: T->getElementType(), OS, PlaceHolder: StringRef());
1301 spaceBeforePlaceHolder(OS);
1302}
1303
1304void TypePrinter::printPipeAfter(const PipeType *T, raw_ostream &OS) {}
1305
1306void TypePrinter::printBitIntBefore(const BitIntType *T, raw_ostream &OS) {
1307 if (T->isUnsigned())
1308 OS << "unsigned ";
1309 OS << "_BitInt(" << T->getNumBits() << ")";
1310 spaceBeforePlaceHolder(OS);
1311}
1312
1313void TypePrinter::printBitIntAfter(const BitIntType *T, raw_ostream &OS) {}
1314
1315void TypePrinter::printDependentBitIntBefore(const DependentBitIntType *T,
1316 raw_ostream &OS) {
1317 if (T->isUnsigned())
1318 OS << "unsigned ";
1319 OS << "_BitInt(";
1320 T->getNumBitsExpr()->printPretty(OS, nullptr, Policy);
1321 OS << ")";
1322 spaceBeforePlaceHolder(OS);
1323}
1324
1325void TypePrinter::printDependentBitIntAfter(const DependentBitIntType *T,
1326 raw_ostream &OS) {}
1327
1328/// Appends the given scope to the end of a string.
1329void TypePrinter::AppendScope(DeclContext *DC, raw_ostream &OS,
1330 DeclarationName NameInScope) {
1331 if (DC->isTranslationUnit())
1332 return;
1333
1334 // FIXME: Consider replacing this with NamedDecl::printNestedNameSpecifier,
1335 // which can also print names for function and method scopes.
1336 if (DC->isFunctionOrMethod())
1337 return;
1338
1339 if (Policy.Callbacks && Policy.Callbacks->isScopeVisible(DC))
1340 return;
1341
1342 if (const auto *NS = dyn_cast<NamespaceDecl>(Val: DC)) {
1343 if (Policy.SuppressUnwrittenScope && NS->isAnonymousNamespace())
1344 return AppendScope(DC: DC->getParent(), OS, NameInScope);
1345
1346 // Only suppress an inline namespace if the name has the same lookup
1347 // results in the enclosing namespace.
1348 if (Policy.SuppressInlineNamespace && NS->isInline() && NameInScope &&
1349 NS->isRedundantInlineQualifierFor(Name: NameInScope))
1350 return AppendScope(DC: DC->getParent(), OS, NameInScope);
1351
1352 AppendScope(DC: DC->getParent(), OS, NameInScope: NS->getDeclName());
1353 if (NS->getIdentifier())
1354 OS << NS->getName() << "::";
1355 else
1356 OS << "(anonymous namespace)::";
1357 } else if (const auto *Spec = dyn_cast<ClassTemplateSpecializationDecl>(Val: DC)) {
1358 AppendScope(DC: DC->getParent(), OS, NameInScope: Spec->getDeclName());
1359 IncludeStrongLifetimeRAII Strong(Policy);
1360 OS << Spec->getIdentifier()->getName();
1361 const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs();
1362 printTemplateArgumentList(
1363 OS, TemplateArgs.asArray(), Policy,
1364 Spec->getSpecializedTemplate()->getTemplateParameters());
1365 OS << "::";
1366 } else if (const auto *Tag = dyn_cast<TagDecl>(Val: DC)) {
1367 AppendScope(DC: DC->getParent(), OS, NameInScope: Tag->getDeclName());
1368 if (TypedefNameDecl *Typedef = Tag->getTypedefNameForAnonDecl())
1369 OS << Typedef->getIdentifier()->getName() << "::";
1370 else if (Tag->getIdentifier())
1371 OS << Tag->getIdentifier()->getName() << "::";
1372 else
1373 return;
1374 } else {
1375 AppendScope(DC: DC->getParent(), OS, NameInScope);
1376 }
1377}
1378
1379void TypePrinter::printTag(TagDecl *D, raw_ostream &OS) {
1380 if (Policy.IncludeTagDefinition) {
1381 PrintingPolicy SubPolicy = Policy;
1382 SubPolicy.IncludeTagDefinition = false;
1383 D->print(OS, SubPolicy, Indentation);
1384 spaceBeforePlaceHolder(OS);
1385 return;
1386 }
1387
1388 bool HasKindDecoration = false;
1389
1390 // We don't print tags unless this is an elaborated type.
1391 // In C, we just assume every RecordType is an elaborated type.
1392 if (!Policy.SuppressTagKeyword && !D->getTypedefNameForAnonDecl()) {
1393 HasKindDecoration = true;
1394 OS << D->getKindName();
1395 OS << ' ';
1396 }
1397
1398 // Compute the full nested-name-specifier for this type.
1399 // In C, this will always be empty except when the type
1400 // being printed is anonymous within other Record.
1401 if (!Policy.SuppressScope)
1402 AppendScope(DC: D->getDeclContext(), OS, NameInScope: D->getDeclName());
1403
1404 if (const IdentifierInfo *II = D->getIdentifier())
1405 OS << II->getName();
1406 else if (TypedefNameDecl *Typedef = D->getTypedefNameForAnonDecl()) {
1407 assert(Typedef->getIdentifier() && "Typedef without identifier?");
1408 OS << Typedef->getIdentifier()->getName();
1409 } else {
1410 // Make an unambiguous representation for anonymous types, e.g.
1411 // (anonymous enum at /usr/include/string.h:120:9)
1412 OS << (Policy.MSVCFormatting ? '`' : '(');
1413
1414 if (isa<CXXRecordDecl>(Val: D) && cast<CXXRecordDecl>(Val: D)->isLambda()) {
1415 OS << "lambda";
1416 HasKindDecoration = true;
1417 } else if ((isa<RecordDecl>(Val: D) && cast<RecordDecl>(Val: D)->isAnonymousStructOrUnion())) {
1418 OS << "anonymous";
1419 } else {
1420 OS << "unnamed";
1421 }
1422
1423 if (Policy.AnonymousTagLocations) {
1424 // Suppress the redundant tag keyword if we just printed one.
1425 // We don't have to worry about ElaboratedTypes here because you can't
1426 // refer to an anonymous type with one.
1427 if (!HasKindDecoration)
1428 OS << " " << D->getKindName();
1429
1430 PresumedLoc PLoc = D->getASTContext().getSourceManager().getPresumedLoc(
1431 D->getLocation());
1432 if (PLoc.isValid()) {
1433 OS << " at ";
1434 StringRef File = PLoc.getFilename();
1435 llvm::SmallString<1024> WrittenFile(File);
1436 if (auto *Callbacks = Policy.Callbacks)
1437 WrittenFile = Callbacks->remapPath(Path: File);
1438 // Fix inconsistent path separator created by
1439 // clang::DirectoryLookup::LookupFile when the file path is relative
1440 // path.
1441 llvm::sys::path::Style Style =
1442 llvm::sys::path::is_absolute(path: WrittenFile)
1443 ? llvm::sys::path::Style::native
1444 : (Policy.MSVCFormatting
1445 ? llvm::sys::path::Style::windows_backslash
1446 : llvm::sys::path::Style::posix);
1447 llvm::sys::path::native(path&: WrittenFile, style: Style);
1448 OS << WrittenFile << ':' << PLoc.getLine() << ':' << PLoc.getColumn();
1449 }
1450 }
1451
1452 OS << (Policy.MSVCFormatting ? '\'' : ')');
1453 }
1454
1455 // If this is a class template specialization, print the template
1456 // arguments.
1457 if (const auto *Spec = dyn_cast<ClassTemplateSpecializationDecl>(Val: D)) {
1458 ArrayRef<TemplateArgument> Args;
1459 TypeSourceInfo *TAW = Spec->getTypeAsWritten();
1460 if (!Policy.PrintCanonicalTypes && TAW) {
1461 const TemplateSpecializationType *TST =
1462 cast<TemplateSpecializationType>(Val: TAW->getType());
1463 Args = TST->template_arguments();
1464 } else {
1465 const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs();
1466 Args = TemplateArgs.asArray();
1467 }
1468 IncludeStrongLifetimeRAII Strong(Policy);
1469 printTemplateArgumentList(
1470 OS, Args, Policy,
1471 Spec->getSpecializedTemplate()->getTemplateParameters());
1472 }
1473
1474 spaceBeforePlaceHolder(OS);
1475}
1476
1477void TypePrinter::printRecordBefore(const RecordType *T, raw_ostream &OS) {
1478 // Print the preferred name if we have one for this type.
1479 if (Policy.UsePreferredNames) {
1480 for (const auto *PNA : T->getDecl()->specific_attrs<PreferredNameAttr>()) {
1481 if (!declaresSameEntity(PNA->getTypedefType()->getAsCXXRecordDecl(),
1482 T->getDecl()))
1483 continue;
1484 // Find the outermost typedef or alias template.
1485 QualType T = PNA->getTypedefType();
1486 while (true) {
1487 if (auto *TT = dyn_cast<TypedefType>(T))
1488 return printTypeSpec(TT->getDecl(), OS);
1489 if (auto *TST = dyn_cast<TemplateSpecializationType>(T))
1490 return printTemplateId(TST, OS, /*FullyQualify=*/true);
1491 T = T->getLocallyUnqualifiedSingleStepDesugaredType();
1492 }
1493 }
1494 }
1495
1496 printTag(T->getDecl(), OS);
1497}
1498
1499void TypePrinter::printRecordAfter(const RecordType *T, raw_ostream &OS) {}
1500
1501void TypePrinter::printEnumBefore(const EnumType *T, raw_ostream &OS) {
1502 printTag(T->getDecl(), OS);
1503}
1504
1505void TypePrinter::printEnumAfter(const EnumType *T, raw_ostream &OS) {}
1506
1507void TypePrinter::printTemplateTypeParmBefore(const TemplateTypeParmType *T,
1508 raw_ostream &OS) {
1509 TemplateTypeParmDecl *D = T->getDecl();
1510 if (D && D->isImplicit()) {
1511 if (auto *TC = D->getTypeConstraint()) {
1512 TC->print(OS, Policy);
1513 OS << ' ';
1514 }
1515 OS << "auto";
1516 } else if (IdentifierInfo *Id = T->getIdentifier())
1517 OS << (Policy.CleanUglifiedParameters ? Id->deuglifiedName()
1518 : Id->getName());
1519 else
1520 OS << "type-parameter-" << T->getDepth() << '-' << T->getIndex();
1521
1522 spaceBeforePlaceHolder(OS);
1523}
1524
1525void TypePrinter::printTemplateTypeParmAfter(const TemplateTypeParmType *T,
1526 raw_ostream &OS) {}
1527
1528void TypePrinter::printSubstTemplateTypeParmBefore(
1529 const SubstTemplateTypeParmType *T,
1530 raw_ostream &OS) {
1531 IncludeStrongLifetimeRAII Strong(Policy);
1532 printBefore(T: T->getReplacementType(), OS);
1533}
1534
1535void TypePrinter::printSubstTemplateTypeParmAfter(
1536 const SubstTemplateTypeParmType *T,
1537 raw_ostream &OS) {
1538 IncludeStrongLifetimeRAII Strong(Policy);
1539 printAfter(t: T->getReplacementType(), OS);
1540}
1541
1542void TypePrinter::printSubstTemplateTypeParmPackBefore(
1543 const SubstTemplateTypeParmPackType *T,
1544 raw_ostream &OS) {
1545 IncludeStrongLifetimeRAII Strong(Policy);
1546 if (const TemplateTypeParmDecl *D = T->getReplacedParameter()) {
1547 if (D && D->isImplicit()) {
1548 if (auto *TC = D->getTypeConstraint()) {
1549 TC->print(OS, Policy);
1550 OS << ' ';
1551 }
1552 OS << "auto";
1553 } else if (IdentifierInfo *Id = D->getIdentifier())
1554 OS << (Policy.CleanUglifiedParameters ? Id->deuglifiedName()
1555 : Id->getName());
1556 else
1557 OS << "type-parameter-" << D->getDepth() << '-' << D->getIndex();
1558
1559 spaceBeforePlaceHolder(OS);
1560 }
1561}
1562
1563void TypePrinter::printSubstTemplateTypeParmPackAfter(
1564 const SubstTemplateTypeParmPackType *T,
1565 raw_ostream &OS) {
1566 IncludeStrongLifetimeRAII Strong(Policy);
1567}
1568
1569void TypePrinter::printTemplateId(const TemplateSpecializationType *T,
1570 raw_ostream &OS, bool FullyQualify) {
1571 IncludeStrongLifetimeRAII Strong(Policy);
1572
1573 TemplateDecl *TD = T->getTemplateName().getAsTemplateDecl();
1574 // FIXME: Null TD never excercised in test suite.
1575 if (FullyQualify && TD) {
1576 if (!Policy.SuppressScope)
1577 AppendScope(DC: TD->getDeclContext(), OS, NameInScope: TD->getDeclName());
1578
1579 OS << TD->getName();
1580 } else {
1581 T->getTemplateName().print(OS, Policy);
1582 }
1583
1584 DefaultTemplateArgsPolicyRAII TemplateArgs(Policy);
1585 const TemplateParameterList *TPL = TD ? TD->getTemplateParameters() : nullptr;
1586 printTemplateArgumentList(OS, Args: T->template_arguments(), Policy, TPL);
1587 spaceBeforePlaceHolder(OS);
1588}
1589
1590void TypePrinter::printTemplateSpecializationBefore(
1591 const TemplateSpecializationType *T,
1592 raw_ostream &OS) {
1593 printTemplateId(T, OS, FullyQualify: Policy.FullyQualifiedName);
1594}
1595
1596void TypePrinter::printTemplateSpecializationAfter(
1597 const TemplateSpecializationType *T,
1598 raw_ostream &OS) {}
1599
1600void TypePrinter::printInjectedClassNameBefore(const InjectedClassNameType *T,
1601 raw_ostream &OS) {
1602 if (Policy.PrintInjectedClassNameWithArguments)
1603 return printTemplateSpecializationBefore(T->getInjectedTST(), OS);
1604
1605 IncludeStrongLifetimeRAII Strong(Policy);
1606 T->getTemplateName().print(OS, Policy);
1607 spaceBeforePlaceHolder(OS);
1608}
1609
1610void TypePrinter::printInjectedClassNameAfter(const InjectedClassNameType *T,
1611 raw_ostream &OS) {}
1612
1613void TypePrinter::printElaboratedBefore(const ElaboratedType *T,
1614 raw_ostream &OS) {
1615 if (Policy.IncludeTagDefinition && T->getOwnedTagDecl()) {
1616 TagDecl *OwnedTagDecl = T->getOwnedTagDecl();
1617 assert(OwnedTagDecl->getTypeForDecl() == T->getNamedType().getTypePtr() &&
1618 "OwnedTagDecl expected to be a declaration for the type");
1619 PrintingPolicy SubPolicy = Policy;
1620 SubPolicy.IncludeTagDefinition = false;
1621 OwnedTagDecl->print(OS, SubPolicy, Indentation);
1622 spaceBeforePlaceHolder(OS);
1623 return;
1624 }
1625
1626 if (Policy.SuppressElaboration) {
1627 printBefore(T: T->getNamedType(), OS);
1628 return;
1629 }
1630
1631 // The tag definition will take care of these.
1632 if (!Policy.IncludeTagDefinition)
1633 {
1634 OS << TypeWithKeyword::getKeywordName(Keyword: T->getKeyword());
1635 if (T->getKeyword() != ElaboratedTypeKeyword::None)
1636 OS << " ";
1637 NestedNameSpecifier *Qualifier = T->getQualifier();
1638 if (Qualifier)
1639 Qualifier->print(OS, Policy);
1640 }
1641
1642 ElaboratedTypePolicyRAII PolicyRAII(Policy);
1643 printBefore(T: T->getNamedType(), OS);
1644}
1645
1646void TypePrinter::printElaboratedAfter(const ElaboratedType *T,
1647 raw_ostream &OS) {
1648 if (Policy.IncludeTagDefinition && T->getOwnedTagDecl())
1649 return;
1650
1651 if (Policy.SuppressElaboration) {
1652 printAfter(t: T->getNamedType(), OS);
1653 return;
1654 }
1655
1656 ElaboratedTypePolicyRAII PolicyRAII(Policy);
1657 printAfter(t: T->getNamedType(), OS);
1658}
1659
1660void TypePrinter::printParenBefore(const ParenType *T, raw_ostream &OS) {
1661 if (!HasEmptyPlaceHolder && !isa<FunctionType>(Val: T->getInnerType())) {
1662 printBefore(T: T->getInnerType(), OS);
1663 OS << '(';
1664 } else
1665 printBefore(T: T->getInnerType(), OS);
1666}
1667
1668void TypePrinter::printParenAfter(const ParenType *T, raw_ostream &OS) {
1669 if (!HasEmptyPlaceHolder && !isa<FunctionType>(Val: T->getInnerType())) {
1670 OS << ')';
1671 printAfter(t: T->getInnerType(), OS);
1672 } else
1673 printAfter(t: T->getInnerType(), OS);
1674}
1675
1676void TypePrinter::printDependentNameBefore(const DependentNameType *T,
1677 raw_ostream &OS) {
1678 OS << TypeWithKeyword::getKeywordName(Keyword: T->getKeyword());
1679 if (T->getKeyword() != ElaboratedTypeKeyword::None)
1680 OS << " ";
1681
1682 T->getQualifier()->print(OS, Policy);
1683
1684 OS << T->getIdentifier()->getName();
1685 spaceBeforePlaceHolder(OS);
1686}
1687
1688void TypePrinter::printDependentNameAfter(const DependentNameType *T,
1689 raw_ostream &OS) {}
1690
1691void TypePrinter::printDependentTemplateSpecializationBefore(
1692 const DependentTemplateSpecializationType *T, raw_ostream &OS) {
1693 IncludeStrongLifetimeRAII Strong(Policy);
1694
1695 OS << TypeWithKeyword::getKeywordName(Keyword: T->getKeyword());
1696 if (T->getKeyword() != ElaboratedTypeKeyword::None)
1697 OS << " ";
1698
1699 if (T->getQualifier())
1700 T->getQualifier()->print(OS, Policy);
1701 OS << "template " << T->getIdentifier()->getName();
1702 printTemplateArgumentList(OS, Args: T->template_arguments(), Policy);
1703 spaceBeforePlaceHolder(OS);
1704}
1705
1706void TypePrinter::printDependentTemplateSpecializationAfter(
1707 const DependentTemplateSpecializationType *T, raw_ostream &OS) {}
1708
1709void TypePrinter::printPackExpansionBefore(const PackExpansionType *T,
1710 raw_ostream &OS) {
1711 printBefore(T: T->getPattern(), OS);
1712}
1713
1714void TypePrinter::printPackExpansionAfter(const PackExpansionType *T,
1715 raw_ostream &OS) {
1716 printAfter(t: T->getPattern(), OS);
1717 OS << "...";
1718}
1719
1720void TypePrinter::printAttributedBefore(const AttributedType *T,
1721 raw_ostream &OS) {
1722 // FIXME: Generate this with TableGen.
1723
1724 // Prefer the macro forms of the GC and ownership qualifiers.
1725 if (T->getAttrKind() == attr::ObjCGC ||
1726 T->getAttrKind() == attr::ObjCOwnership)
1727 return printBefore(T: T->getEquivalentType(), OS);
1728
1729 if (T->getAttrKind() == attr::ObjCKindOf)
1730 OS << "__kindof ";
1731
1732 if (T->getAttrKind() == attr::AddressSpace)
1733 printBefore(T: T->getEquivalentType(), OS);
1734 else
1735 printBefore(T: T->getModifiedType(), OS);
1736
1737 if (T->isMSTypeSpec()) {
1738 switch (T->getAttrKind()) {
1739 default: return;
1740 case attr::Ptr32: OS << " __ptr32"; break;
1741 case attr::Ptr64: OS << " __ptr64"; break;
1742 case attr::SPtr: OS << " __sptr"; break;
1743 case attr::UPtr: OS << " __uptr"; break;
1744 }
1745 spaceBeforePlaceHolder(OS);
1746 }
1747
1748 if (T->isWebAssemblyFuncrefSpec())
1749 OS << "__funcref";
1750
1751 // Print nullability type specifiers.
1752 if (T->getImmediateNullability()) {
1753 if (T->getAttrKind() == attr::TypeNonNull)
1754 OS << " _Nonnull";
1755 else if (T->getAttrKind() == attr::TypeNullable)
1756 OS << " _Nullable";
1757 else if (T->getAttrKind() == attr::TypeNullUnspecified)
1758 OS << " _Null_unspecified";
1759 else if (T->getAttrKind() == attr::TypeNullableResult)
1760 OS << " _Nullable_result";
1761 else
1762 llvm_unreachable("unhandled nullability");
1763 spaceBeforePlaceHolder(OS);
1764 }
1765}
1766
1767void TypePrinter::printAttributedAfter(const AttributedType *T,
1768 raw_ostream &OS) {
1769 // FIXME: Generate this with TableGen.
1770
1771 // Prefer the macro forms of the GC and ownership qualifiers.
1772 if (T->getAttrKind() == attr::ObjCGC ||
1773 T->getAttrKind() == attr::ObjCOwnership)
1774 return printAfter(t: T->getEquivalentType(), OS);
1775
1776 // If this is a calling convention attribute, don't print the implicit CC from
1777 // the modified type.
1778 SaveAndRestore MaybeSuppressCC(InsideCCAttribute, T->isCallingConv());
1779
1780 printAfter(t: T->getModifiedType(), OS);
1781
1782 // Some attributes are printed as qualifiers before the type, so we have
1783 // nothing left to do.
1784 if (T->getAttrKind() == attr::ObjCKindOf || T->isMSTypeSpec() ||
1785 T->getImmediateNullability() || T->isWebAssemblyFuncrefSpec())
1786 return;
1787
1788 // Don't print the inert __unsafe_unretained attribute at all.
1789 if (T->getAttrKind() == attr::ObjCInertUnsafeUnretained)
1790 return;
1791
1792 // Don't print ns_returns_retained unless it had an effect.
1793 if (T->getAttrKind() == attr::NSReturnsRetained &&
1794 !T->getEquivalentType()->castAs<FunctionType>()
1795 ->getExtInfo().getProducesResult())
1796 return;
1797
1798 if (T->getAttrKind() == attr::LifetimeBound) {
1799 OS << " [[clang::lifetimebound]]";
1800 return;
1801 }
1802
1803 // The printing of the address_space attribute is handled by the qualifier
1804 // since it is still stored in the qualifier. Return early to prevent printing
1805 // this twice.
1806 if (T->getAttrKind() == attr::AddressSpace)
1807 return;
1808
1809 if (T->getAttrKind() == attr::AnnotateType) {
1810 // FIXME: Print the attribute arguments once we have a way to retrieve these
1811 // here. For the meantime, we just print `[[clang::annotate_type(...)]]`
1812 // without the arguments so that we know at least that we had _some_
1813 // annotation on the type.
1814 OS << " [[clang::annotate_type(...)]]";
1815 return;
1816 }
1817
1818 if (T->getAttrKind() == attr::ArmStreaming) {
1819 OS << "__arm_streaming";
1820 return;
1821 }
1822 if (T->getAttrKind() == attr::ArmStreamingCompatible) {
1823 OS << "__arm_streaming_compatible";
1824 return;
1825 }
1826
1827 OS << " __attribute__((";
1828 switch (T->getAttrKind()) {
1829#define TYPE_ATTR(NAME)
1830#define DECL_OR_TYPE_ATTR(NAME)
1831#define ATTR(NAME) case attr::NAME:
1832#include "clang/Basic/AttrList.inc"
1833 llvm_unreachable("non-type attribute attached to type");
1834
1835 case attr::BTFTypeTag:
1836 llvm_unreachable("BTFTypeTag attribute handled separately");
1837
1838 case attr::OpenCLPrivateAddressSpace:
1839 case attr::OpenCLGlobalAddressSpace:
1840 case attr::OpenCLGlobalDeviceAddressSpace:
1841 case attr::OpenCLGlobalHostAddressSpace:
1842 case attr::OpenCLLocalAddressSpace:
1843 case attr::OpenCLConstantAddressSpace:
1844 case attr::OpenCLGenericAddressSpace:
1845 case attr::HLSLGroupSharedAddressSpace:
1846 // FIXME: Update printAttributedBefore to print these once we generate
1847 // AttributedType nodes for them.
1848 break;
1849
1850 case attr::LifetimeBound:
1851 case attr::TypeNonNull:
1852 case attr::TypeNullable:
1853 case attr::TypeNullableResult:
1854 case attr::TypeNullUnspecified:
1855 case attr::ObjCGC:
1856 case attr::ObjCInertUnsafeUnretained:
1857 case attr::ObjCKindOf:
1858 case attr::ObjCOwnership:
1859 case attr::Ptr32:
1860 case attr::Ptr64:
1861 case attr::SPtr:
1862 case attr::UPtr:
1863 case attr::AddressSpace:
1864 case attr::CmseNSCall:
1865 case attr::AnnotateType:
1866 case attr::WebAssemblyFuncref:
1867 case attr::ArmStreaming:
1868 case attr::ArmStreamingCompatible:
1869 case attr::ArmIn:
1870 case attr::ArmOut:
1871 case attr::ArmInOut:
1872 case attr::ArmPreserves:
1873 llvm_unreachable("This attribute should have been handled already");
1874
1875 case attr::NSReturnsRetained:
1876 OS << "ns_returns_retained";
1877 break;
1878
1879 // FIXME: When Sema learns to form this AttributedType, avoid printing the
1880 // attribute again in printFunctionProtoAfter.
1881 case attr::AnyX86NoCfCheck: OS << "nocf_check"; break;
1882 case attr::CDecl: OS << "cdecl"; break;
1883 case attr::FastCall: OS << "fastcall"; break;
1884 case attr::StdCall: OS << "stdcall"; break;
1885 case attr::ThisCall: OS << "thiscall"; break;
1886 case attr::SwiftCall: OS << "swiftcall"; break;
1887 case attr::SwiftAsyncCall: OS << "swiftasynccall"; break;
1888 case attr::VectorCall: OS << "vectorcall"; break;
1889 case attr::Pascal: OS << "pascal"; break;
1890 case attr::MSABI: OS << "ms_abi"; break;
1891 case attr::SysVABI: OS << "sysv_abi"; break;
1892 case attr::RegCall: OS << "regcall"; break;
1893 case attr::Pcs: {
1894 OS << "pcs(";
1895 QualType t = T->getEquivalentType();
1896 while (!t->isFunctionType())
1897 t = t->getPointeeType();
1898 OS << (t->castAs<FunctionType>()->getCallConv() == CC_AAPCS ?
1899 "\"aapcs\"" : "\"aapcs-vfp\"");
1900 OS << ')';
1901 break;
1902 }
1903 case attr::AArch64VectorPcs: OS << "aarch64_vector_pcs"; break;
1904 case attr::AArch64SVEPcs: OS << "aarch64_sve_pcs"; break;
1905 case attr::AMDGPUKernelCall: OS << "amdgpu_kernel"; break;
1906 case attr::IntelOclBicc: OS << "inteloclbicc"; break;
1907 case attr::PreserveMost:
1908 OS << "preserve_most";
1909 break;
1910
1911 case attr::PreserveAll:
1912 OS << "preserve_all";
1913 break;
1914 case attr::M68kRTD:
1915 OS << "m68k_rtd";
1916 break;
1917 case attr::PreserveNone:
1918 OS << "preserve_none";
1919 break;
1920 case attr::NoDeref:
1921 OS << "noderef";
1922 break;
1923 case attr::AcquireHandle:
1924 OS << "acquire_handle";
1925 break;
1926 case attr::ArmMveStrictPolymorphism:
1927 OS << "__clang_arm_mve_strict_polymorphism";
1928 break;
1929
1930 // Nothing to print for this attribute.
1931 case attr::HLSLParamModifier:
1932 break;
1933 }
1934 OS << "))";
1935}
1936
1937void TypePrinter::printBTFTagAttributedBefore(const BTFTagAttributedType *T,
1938 raw_ostream &OS) {
1939 printBefore(T: T->getWrappedType(), OS);
1940 OS << " __attribute__((btf_type_tag(\"" << T->getAttr()->getBTFTypeTag() << "\")))";
1941}
1942
1943void TypePrinter::printBTFTagAttributedAfter(const BTFTagAttributedType *T,
1944 raw_ostream &OS) {
1945 printAfter(t: T->getWrappedType(), OS);
1946}
1947
1948void TypePrinter::printObjCInterfaceBefore(const ObjCInterfaceType *T,
1949 raw_ostream &OS) {
1950 OS << T->getDecl()->getName();
1951 spaceBeforePlaceHolder(OS);
1952}
1953
1954void TypePrinter::printObjCInterfaceAfter(const ObjCInterfaceType *T,
1955 raw_ostream &OS) {}
1956
1957void TypePrinter::printObjCTypeParamBefore(const ObjCTypeParamType *T,
1958 raw_ostream &OS) {
1959 OS << T->getDecl()->getName();
1960 if (!T->qual_empty()) {
1961 bool isFirst = true;
1962 OS << '<';
1963 for (const auto *I : T->quals()) {
1964 if (isFirst)
1965 isFirst = false;
1966 else
1967 OS << ',';
1968 OS << I->getName();
1969 }
1970 OS << '>';
1971 }
1972
1973 spaceBeforePlaceHolder(OS);
1974}
1975
1976void TypePrinter::printObjCTypeParamAfter(const ObjCTypeParamType *T,
1977 raw_ostream &OS) {}
1978
1979void TypePrinter::printObjCObjectBefore(const ObjCObjectType *T,
1980 raw_ostream &OS) {
1981 if (T->qual_empty() && T->isUnspecializedAsWritten() &&
1982 !T->isKindOfTypeAsWritten())
1983 return printBefore(T: T->getBaseType(), OS);
1984
1985 if (T->isKindOfTypeAsWritten())
1986 OS << "__kindof ";
1987
1988 print(t: T->getBaseType(), OS, PlaceHolder: StringRef());
1989
1990 if (T->isSpecializedAsWritten()) {
1991 bool isFirst = true;
1992 OS << '<';
1993 for (auto typeArg : T->getTypeArgsAsWritten()) {
1994 if (isFirst)
1995 isFirst = false;
1996 else
1997 OS << ",";
1998
1999 print(t: typeArg, OS, PlaceHolder: StringRef());
2000 }
2001 OS << '>';
2002 }
2003
2004 if (!T->qual_empty()) {
2005 bool isFirst = true;
2006 OS << '<';
2007 for (const auto *I : T->quals()) {
2008 if (isFirst)
2009 isFirst = false;
2010 else
2011 OS << ',';
2012 OS << I->getName();
2013 }
2014 OS << '>';
2015 }
2016
2017 spaceBeforePlaceHolder(OS);
2018}
2019
2020void TypePrinter::printObjCObjectAfter(const ObjCObjectType *T,
2021 raw_ostream &OS) {
2022 if (T->qual_empty() && T->isUnspecializedAsWritten() &&
2023 !T->isKindOfTypeAsWritten())
2024 return printAfter(t: T->getBaseType(), OS);
2025}
2026
2027void TypePrinter::printObjCObjectPointerBefore(const ObjCObjectPointerType *T,
2028 raw_ostream &OS) {
2029 printBefore(T: T->getPointeeType(), OS);
2030
2031 // If we need to print the pointer, print it now.
2032 if (!T->isObjCIdType() && !T->isObjCQualifiedIdType() &&
2033 !T->isObjCClassType() && !T->isObjCQualifiedClassType()) {
2034 if (HasEmptyPlaceHolder)
2035 OS << ' ';
2036 OS << '*';
2037 }
2038}
2039
2040void TypePrinter::printObjCObjectPointerAfter(const ObjCObjectPointerType *T,
2041 raw_ostream &OS) {}
2042
2043static
2044const TemplateArgument &getArgument(const TemplateArgument &A) { return A; }
2045
2046static const TemplateArgument &getArgument(const TemplateArgumentLoc &A) {
2047 return A.getArgument();
2048}
2049
2050static void printArgument(const TemplateArgument &A, const PrintingPolicy &PP,
2051 llvm::raw_ostream &OS, bool IncludeType) {
2052 A.print(Policy: PP, Out&: OS, IncludeType);
2053}
2054
2055static void printArgument(const TemplateArgumentLoc &A,
2056 const PrintingPolicy &PP, llvm::raw_ostream &OS,
2057 bool IncludeType) {
2058 const TemplateArgument::ArgKind &Kind = A.getArgument().getKind();
2059 if (Kind == TemplateArgument::ArgKind::Type)
2060 return A.getTypeSourceInfo()->getType().print(OS, Policy: PP);
2061 return A.getArgument().print(Policy: PP, Out&: OS, IncludeType);
2062}
2063
2064static bool isSubstitutedTemplateArgument(ASTContext &Ctx, TemplateArgument Arg,
2065 TemplateArgument Pattern,
2066 ArrayRef<TemplateArgument> Args,
2067 unsigned Depth);
2068
2069static bool isSubstitutedType(ASTContext &Ctx, QualType T, QualType Pattern,
2070 ArrayRef<TemplateArgument> Args, unsigned Depth) {
2071 if (Ctx.hasSameType(T1: T, T2: Pattern))
2072 return true;
2073
2074 // A type parameter matches its argument.
2075 if (auto *TTPT = Pattern->getAs<TemplateTypeParmType>()) {
2076 if (TTPT->getDepth() == Depth && TTPT->getIndex() < Args.size() &&
2077 Args[TTPT->getIndex()].getKind() == TemplateArgument::Type) {
2078 QualType SubstArg = Ctx.getQualifiedType(
2079 T: Args[TTPT->getIndex()].getAsType(), Qs: Pattern.getQualifiers());
2080 return Ctx.hasSameType(T1: SubstArg, T2: T);
2081 }
2082 return false;
2083 }
2084
2085 // FIXME: Recurse into array types.
2086
2087 // All other cases will need the types to be identically qualified.
2088 Qualifiers TQual, PatQual;
2089 T = Ctx.getUnqualifiedArrayType(T, Quals&: TQual);
2090 Pattern = Ctx.getUnqualifiedArrayType(T: Pattern, Quals&: PatQual);
2091 if (TQual != PatQual)
2092 return false;
2093
2094 // Recurse into pointer-like types.
2095 {
2096 QualType TPointee = T->getPointeeType();
2097 QualType PPointee = Pattern->getPointeeType();
2098 if (!TPointee.isNull() && !PPointee.isNull())
2099 return T->getTypeClass() == Pattern->getTypeClass() &&
2100 isSubstitutedType(Ctx, T: TPointee, Pattern: PPointee, Args, Depth);
2101 }
2102
2103 // Recurse into template specialization types.
2104 if (auto *PTST =
2105 Pattern.getCanonicalType()->getAs<TemplateSpecializationType>()) {
2106 TemplateName Template;
2107 ArrayRef<TemplateArgument> TemplateArgs;
2108 if (auto *TTST = T->getAs<TemplateSpecializationType>()) {
2109 Template = TTST->getTemplateName();
2110 TemplateArgs = TTST->template_arguments();
2111 } else if (auto *CTSD = dyn_cast_or_null<ClassTemplateSpecializationDecl>(
2112 Val: T->getAsCXXRecordDecl())) {
2113 Template = TemplateName(CTSD->getSpecializedTemplate());
2114 TemplateArgs = CTSD->getTemplateArgs().asArray();
2115 } else {
2116 return false;
2117 }
2118
2119 if (!isSubstitutedTemplateArgument(Ctx, Arg: Template, Pattern: PTST->getTemplateName(),
2120 Args, Depth))
2121 return false;
2122 if (TemplateArgs.size() != PTST->template_arguments().size())
2123 return false;
2124 for (unsigned I = 0, N = TemplateArgs.size(); I != N; ++I)
2125 if (!isSubstitutedTemplateArgument(
2126 Ctx, Arg: TemplateArgs[I], Pattern: PTST->template_arguments()[I], Args, Depth))
2127 return false;
2128 return true;
2129 }
2130
2131 // FIXME: Handle more cases.
2132 return false;
2133}
2134
2135/// Evaluates the expression template argument 'Pattern' and returns true
2136/// if 'Arg' evaluates to the same result.
2137static bool templateArgumentExpressionsEqual(ASTContext const &Ctx,
2138 TemplateArgument const &Pattern,
2139 TemplateArgument const &Arg) {
2140 if (Pattern.getKind() != TemplateArgument::Expression)
2141 return false;
2142
2143 // Can't evaluate value-dependent expressions so bail early
2144 Expr const *pattern_expr = Pattern.getAsExpr();
2145 if (pattern_expr->isValueDependent() ||
2146 !pattern_expr->isIntegerConstantExpr(Ctx))
2147 return false;
2148
2149 if (Arg.getKind() == TemplateArgument::Integral)
2150 return llvm::APSInt::isSameValue(I1: pattern_expr->EvaluateKnownConstInt(Ctx),
2151 I2: Arg.getAsIntegral());
2152
2153 if (Arg.getKind() == TemplateArgument::Expression) {
2154 Expr const *args_expr = Arg.getAsExpr();
2155 if (args_expr->isValueDependent() || !args_expr->isIntegerConstantExpr(Ctx))
2156 return false;
2157
2158 return llvm::APSInt::isSameValue(I1: args_expr->EvaluateKnownConstInt(Ctx),
2159 I2: pattern_expr->EvaluateKnownConstInt(Ctx));
2160 }
2161
2162 return false;
2163}
2164
2165static bool isSubstitutedTemplateArgument(ASTContext &Ctx, TemplateArgument Arg,
2166 TemplateArgument Pattern,
2167 ArrayRef<TemplateArgument> Args,
2168 unsigned Depth) {
2169 Arg = Ctx.getCanonicalTemplateArgument(Arg);
2170 Pattern = Ctx.getCanonicalTemplateArgument(Arg: Pattern);
2171 if (Arg.structurallyEquals(Other: Pattern))
2172 return true;
2173
2174 if (Pattern.getKind() == TemplateArgument::Expression) {
2175 if (auto *DRE =
2176 dyn_cast<DeclRefExpr>(Val: Pattern.getAsExpr()->IgnoreParenImpCasts())) {
2177 if (auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(Val: DRE->getDecl()))
2178 return NTTP->getDepth() == Depth && Args.size() > NTTP->getIndex() &&
2179 Args[NTTP->getIndex()].structurallyEquals(Arg);
2180 }
2181 }
2182
2183 if (templateArgumentExpressionsEqual(Ctx, Pattern, Arg))
2184 return true;
2185
2186 if (Arg.getKind() != Pattern.getKind())
2187 return false;
2188
2189 if (Arg.getKind() == TemplateArgument::Type)
2190 return isSubstitutedType(Ctx, T: Arg.getAsType(), Pattern: Pattern.getAsType(), Args,
2191 Depth);
2192
2193 if (Arg.getKind() == TemplateArgument::Template) {
2194 TemplateDecl *PatTD = Pattern.getAsTemplate().getAsTemplateDecl();
2195 if (auto *TTPD = dyn_cast_or_null<TemplateTemplateParmDecl>(Val: PatTD))
2196 return TTPD->getDepth() == Depth && Args.size() > TTPD->getIndex() &&
2197 Ctx.getCanonicalTemplateArgument(Arg: Args[TTPD->getIndex()])
2198 .structurallyEquals(Arg);
2199 }
2200
2201 // FIXME: Handle more cases.
2202 return false;
2203}
2204
2205bool clang::isSubstitutedDefaultArgument(ASTContext &Ctx, TemplateArgument Arg,
2206 const NamedDecl *Param,
2207 ArrayRef<TemplateArgument> Args,
2208 unsigned Depth) {
2209 // An empty pack is equivalent to not providing a pack argument.
2210 if (Arg.getKind() == TemplateArgument::Pack && Arg.pack_size() == 0)
2211 return true;
2212
2213 if (auto *TTPD = dyn_cast<TemplateTypeParmDecl>(Val: Param)) {
2214 return TTPD->hasDefaultArgument() &&
2215 isSubstitutedTemplateArgument(Ctx, Arg, Pattern: TTPD->getDefaultArgument(),
2216 Args, Depth);
2217 } else if (auto *TTPD = dyn_cast<TemplateTemplateParmDecl>(Val: Param)) {
2218 return TTPD->hasDefaultArgument() &&
2219 isSubstitutedTemplateArgument(
2220 Ctx, Arg, Pattern: TTPD->getDefaultArgument().getArgument(), Args, Depth);
2221 } else if (auto *NTTPD = dyn_cast<NonTypeTemplateParmDecl>(Val: Param)) {
2222 return NTTPD->hasDefaultArgument() &&
2223 isSubstitutedTemplateArgument(Ctx, Arg, Pattern: NTTPD->getDefaultArgument(),
2224 Args, Depth);
2225 }
2226 return false;
2227}
2228
2229template <typename TA>
2230static void
2231printTo(raw_ostream &OS, ArrayRef<TA> Args, const PrintingPolicy &Policy,
2232 const TemplateParameterList *TPL, bool IsPack, unsigned ParmIndex) {
2233 // Drop trailing template arguments that match default arguments.
2234 if (TPL && Policy.SuppressDefaultTemplateArgs &&
2235 !Policy.PrintCanonicalTypes && !Args.empty() && !IsPack &&
2236 Args.size() <= TPL->size()) {
2237 llvm::SmallVector<TemplateArgument, 8> OrigArgs;
2238 for (const TA &A : Args)
2239 OrigArgs.push_back(Elt: getArgument(A));
2240 while (!Args.empty() && getArgument(Args.back()).getIsDefaulted())
2241 Args = Args.drop_back();
2242 }
2243
2244 const char *Comma = Policy.MSVCFormatting ? "," : ", ";
2245 if (!IsPack)
2246 OS << '<';
2247
2248 bool NeedSpace = false;
2249 bool FirstArg = true;
2250 for (const auto &Arg : Args) {
2251 // Print the argument into a string.
2252 SmallString<128> Buf;
2253 llvm::raw_svector_ostream ArgOS(Buf);
2254 const TemplateArgument &Argument = getArgument(Arg);
2255 if (Argument.getKind() == TemplateArgument::Pack) {
2256 if (Argument.pack_size() && !FirstArg)
2257 OS << Comma;
2258 printTo(OS&: ArgOS, Args: Argument.getPackAsArray(), Policy, TPL,
2259 /*IsPack*/ true, ParmIndex);
2260 } else {
2261 if (!FirstArg)
2262 OS << Comma;
2263 // Tries to print the argument with location info if exists.
2264 printArgument(Arg, Policy, ArgOS,
2265 TemplateParameterList::shouldIncludeTypeForArgument(
2266 Policy, TPL, Idx: ParmIndex));
2267 }
2268 StringRef ArgString = ArgOS.str();
2269
2270 // If this is the first argument and its string representation
2271 // begins with the global scope specifier ('::foo'), add a space
2272 // to avoid printing the diagraph '<:'.
2273 if (FirstArg && ArgString.starts_with(Prefix: ":"))
2274 OS << ' ';
2275
2276 OS << ArgString;
2277
2278 // If the last character of our string is '>', add another space to
2279 // keep the two '>''s separate tokens.
2280 if (!ArgString.empty()) {
2281 NeedSpace = Policy.SplitTemplateClosers && ArgString.back() == '>';
2282 FirstArg = false;
2283 }
2284
2285 // Use same template parameter for all elements of Pack
2286 if (!IsPack)
2287 ParmIndex++;
2288 }
2289
2290 if (!IsPack) {
2291 if (NeedSpace)
2292 OS << ' ';
2293 OS << '>';
2294 }
2295}
2296
2297void clang::printTemplateArgumentList(raw_ostream &OS,
2298 const TemplateArgumentListInfo &Args,
2299 const PrintingPolicy &Policy,
2300 const TemplateParameterList *TPL) {
2301 printTemplateArgumentList(OS, Args: Args.arguments(), Policy, TPL);
2302}
2303
2304void clang::printTemplateArgumentList(raw_ostream &OS,
2305 ArrayRef<TemplateArgument> Args,
2306 const PrintingPolicy &Policy,
2307 const TemplateParameterList *TPL) {
2308 printTo(OS, Args, Policy, TPL, /*isPack*/ IsPack: false, /*parmIndex*/ ParmIndex: 0);
2309}
2310
2311void clang::printTemplateArgumentList(raw_ostream &OS,
2312 ArrayRef<TemplateArgumentLoc> Args,
2313 const PrintingPolicy &Policy,
2314 const TemplateParameterList *TPL) {
2315 printTo(OS, Args, Policy, TPL, /*isPack*/ IsPack: false, /*parmIndex*/ ParmIndex: 0);
2316}
2317
2318std::string Qualifiers::getAsString() const {
2319 LangOptions LO;
2320 return getAsString(Policy: PrintingPolicy(LO));
2321}
2322
2323// Appends qualifiers to the given string, separated by spaces. Will
2324// prefix a space if the string is non-empty. Will not append a final
2325// space.
2326std::string Qualifiers::getAsString(const PrintingPolicy &Policy) const {
2327 SmallString<64> Buf;
2328 llvm::raw_svector_ostream StrOS(Buf);
2329 print(OS&: StrOS, Policy);
2330 return std::string(StrOS.str());
2331}
2332
2333bool Qualifiers::isEmptyWhenPrinted(const PrintingPolicy &Policy) const {
2334 if (getCVRQualifiers())
2335 return false;
2336
2337 if (getAddressSpace() != LangAS::Default)
2338 return false;
2339
2340 if (getObjCGCAttr())
2341 return false;
2342
2343 if (Qualifiers::ObjCLifetime lifetime = getObjCLifetime())
2344 if (!(lifetime == Qualifiers::OCL_Strong && Policy.SuppressStrongLifetime))
2345 return false;
2346
2347 return true;
2348}
2349
2350std::string Qualifiers::getAddrSpaceAsString(LangAS AS) {
2351 switch (AS) {
2352 case LangAS::Default:
2353 return "";
2354 case LangAS::opencl_global:
2355 case LangAS::sycl_global:
2356 return "__global";
2357 case LangAS::opencl_local:
2358 case LangAS::sycl_local:
2359 return "__local";
2360 case LangAS::opencl_private:
2361 case LangAS::sycl_private:
2362 return "__private";
2363 case LangAS::opencl_constant:
2364 return "__constant";
2365 case LangAS::opencl_generic:
2366 return "__generic";
2367 case LangAS::opencl_global_device:
2368 case LangAS::sycl_global_device:
2369 return "__global_device";
2370 case LangAS::opencl_global_host:
2371 case LangAS::sycl_global_host:
2372 return "__global_host";
2373 case LangAS::cuda_device:
2374 return "__device__";
2375 case LangAS::cuda_constant:
2376 return "__constant__";
2377 case LangAS::cuda_shared:
2378 return "__shared__";
2379 case LangAS::ptr32_sptr:
2380 return "__sptr __ptr32";
2381 case LangAS::ptr32_uptr:
2382 return "__uptr __ptr32";
2383 case LangAS::ptr64:
2384 return "__ptr64";
2385 case LangAS::wasm_funcref:
2386 return "__funcref";
2387 case LangAS::hlsl_groupshared:
2388 return "groupshared";
2389 default:
2390 return std::to_string(val: toTargetAddressSpace(AS));
2391 }
2392}
2393
2394// Appends qualifiers to the given string, separated by spaces. Will
2395// prefix a space if the string is non-empty. Will not append a final
2396// space.
2397void Qualifiers::print(raw_ostream &OS, const PrintingPolicy& Policy,
2398 bool appendSpaceIfNonEmpty) const {
2399 bool addSpace = false;
2400
2401 unsigned quals = getCVRQualifiers();
2402 if (quals) {
2403 AppendTypeQualList(OS, TypeQuals: quals, HasRestrictKeyword: Policy.Restrict);
2404 addSpace = true;
2405 }
2406 if (hasUnaligned()) {
2407 if (addSpace)
2408 OS << ' ';
2409 OS << "__unaligned";
2410 addSpace = true;
2411 }
2412 auto ASStr = getAddrSpaceAsString(AS: getAddressSpace());
2413 if (!ASStr.empty()) {
2414 if (addSpace)
2415 OS << ' ';
2416 addSpace = true;
2417 // Wrap target address space into an attribute syntax
2418 if (isTargetAddressSpace(AS: getAddressSpace()))
2419 OS << "__attribute__((address_space(" << ASStr << ")))";
2420 else
2421 OS << ASStr;
2422 }
2423
2424 if (Qualifiers::GC gc = getObjCGCAttr()) {
2425 if (addSpace)
2426 OS << ' ';
2427 addSpace = true;
2428 if (gc == Qualifiers::Weak)
2429 OS << "__weak";
2430 else
2431 OS << "__strong";
2432 }
2433 if (Qualifiers::ObjCLifetime lifetime = getObjCLifetime()) {
2434 if (!(lifetime == Qualifiers::OCL_Strong && Policy.SuppressStrongLifetime)){
2435 if (addSpace)
2436 OS << ' ';
2437 addSpace = true;
2438 }
2439
2440 switch (lifetime) {
2441 case Qualifiers::OCL_None: llvm_unreachable("none but true");
2442 case Qualifiers::OCL_ExplicitNone: OS << "__unsafe_unretained"; break;
2443 case Qualifiers::OCL_Strong:
2444 if (!Policy.SuppressStrongLifetime)
2445 OS << "__strong";
2446 break;
2447
2448 case Qualifiers::OCL_Weak: OS << "__weak"; break;
2449 case Qualifiers::OCL_Autoreleasing: OS << "__autoreleasing"; break;
2450 }
2451 }
2452
2453 if (appendSpaceIfNonEmpty && addSpace)
2454 OS << ' ';
2455}
2456
2457std::string QualType::getAsString() const {
2458 return getAsString(split: split(), Policy: LangOptions());
2459}
2460
2461std::string QualType::getAsString(const PrintingPolicy &Policy) const {
2462 std::string S;
2463 getAsStringInternal(Str&: S, Policy);
2464 return S;
2465}
2466
2467std::string QualType::getAsString(const Type *ty, Qualifiers qs,
2468 const PrintingPolicy &Policy) {
2469 std::string buffer;
2470 getAsStringInternal(ty, qs, out&: buffer, policy: Policy);
2471 return buffer;
2472}
2473
2474void QualType::print(raw_ostream &OS, const PrintingPolicy &Policy,
2475 const Twine &PlaceHolder, unsigned Indentation) const {
2476 print(split: splitAccordingToPolicy(QT: *this, Policy), OS, policy: Policy, PlaceHolder,
2477 Indentation);
2478}
2479
2480void QualType::print(const Type *ty, Qualifiers qs,
2481 raw_ostream &OS, const PrintingPolicy &policy,
2482 const Twine &PlaceHolder, unsigned Indentation) {
2483 SmallString<128> PHBuf;
2484 StringRef PH = PlaceHolder.toStringRef(Out&: PHBuf);
2485
2486 TypePrinter(policy, Indentation).print(T: ty, Quals: qs, OS, PlaceHolder: PH);
2487}
2488
2489void QualType::getAsStringInternal(std::string &Str,
2490 const PrintingPolicy &Policy) const {
2491 return getAsStringInternal(split: splitAccordingToPolicy(QT: *this, Policy), out&: Str,
2492 policy: Policy);
2493}
2494
2495void QualType::getAsStringInternal(const Type *ty, Qualifiers qs,
2496 std::string &buffer,
2497 const PrintingPolicy &policy) {
2498 SmallString<256> Buf;
2499 llvm::raw_svector_ostream StrOS(Buf);
2500 TypePrinter(policy).print(T: ty, Quals: qs, OS&: StrOS, PlaceHolder: buffer);
2501 std::string str = std::string(StrOS.str());
2502 buffer.swap(s&: str);
2503}
2504
2505raw_ostream &clang::operator<<(raw_ostream &OS, QualType QT) {
2506 SplitQualType S = QT.split();
2507 TypePrinter(LangOptions()).print(T: S.Ty, Quals: S.Quals, OS, /*PlaceHolder=*/"");
2508 return OS;
2509}
2510

source code of clang/lib/AST/TypePrinter.cpp