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/Type.h"
26#include "clang/Basic/AddressSpaces.h"
27#include "clang/Basic/AttrKinds.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/Compiler.h"
41#include "llvm/Support/ErrorHandling.h"
42#include "llvm/Support/SaveAndRestore.h"
43#include "llvm/Support/raw_ostream.h"
44#include <cassert>
45#include <string>
46
47using namespace clang;
48
49namespace {
50
51/// RAII object that enables printing of the ARC __strong lifetime
52/// qualifier.
53class IncludeStrongLifetimeRAII {
54 PrintingPolicy &Policy;
55 bool Old;
56
57public:
58 explicit IncludeStrongLifetimeRAII(PrintingPolicy &Policy)
59 : Policy(Policy), Old(Policy.SuppressStrongLifetime) {
60 if (!Policy.SuppressLifetimeQualifiers)
61 Policy.SuppressStrongLifetime = false;
62 }
63
64 ~IncludeStrongLifetimeRAII() { Policy.SuppressStrongLifetime = Old; }
65};
66
67class ParamPolicyRAII {
68 PrintingPolicy &Policy;
69 bool Old;
70
71public:
72 explicit ParamPolicyRAII(PrintingPolicy &Policy)
73 : Policy(Policy), Old(Policy.SuppressSpecifiers) {
74 Policy.SuppressSpecifiers = false;
75 }
76
77 ~ParamPolicyRAII() { Policy.SuppressSpecifiers = Old; }
78};
79
80class DefaultTemplateArgsPolicyRAII {
81 PrintingPolicy &Policy;
82 bool Old;
83
84public:
85 explicit DefaultTemplateArgsPolicyRAII(PrintingPolicy &Policy)
86 : Policy(Policy), Old(Policy.SuppressDefaultTemplateArgs) {
87 Policy.SuppressDefaultTemplateArgs = false;
88 }
89
90 ~DefaultTemplateArgsPolicyRAII() { Policy.SuppressDefaultTemplateArgs = Old; }
91};
92
93class ElaboratedTypePolicyRAII {
94 PrintingPolicy &Policy;
95 bool SuppressTagKeyword;
96 bool SuppressScope;
97
98public:
99 explicit ElaboratedTypePolicyRAII(PrintingPolicy &Policy) : Policy(Policy) {
100 SuppressTagKeyword = Policy.SuppressTagKeyword;
101 SuppressScope = Policy.SuppressScope;
102 Policy.SuppressTagKeyword = true;
103 Policy.SuppressScope = true;
104 }
105
106 ~ElaboratedTypePolicyRAII() {
107 Policy.SuppressTagKeyword = SuppressTagKeyword;
108 Policy.SuppressScope = SuppressScope;
109 }
110};
111
112class TypePrinter {
113 PrintingPolicy Policy;
114 unsigned Indentation;
115 bool HasEmptyPlaceHolder = false;
116 bool InsideCCAttribute = false;
117
118public:
119 explicit TypePrinter(const PrintingPolicy &Policy, unsigned Indentation = 0)
120 : Policy(Policy), Indentation(Indentation) {}
121
122 void print(const Type *ty, Qualifiers qs, raw_ostream &OS,
123 StringRef PlaceHolder);
124 void print(QualType T, raw_ostream &OS, StringRef PlaceHolder);
125
126 static bool canPrefixQualifiers(const Type *T, bool &NeedARCStrongQualifier);
127 void spaceBeforePlaceHolder(raw_ostream &OS);
128 void printTypeSpec(NamedDecl *D, raw_ostream &OS);
129 void printTemplateId(const TemplateSpecializationType *T, raw_ostream &OS,
130 bool FullyQualify);
131
132 void printBefore(QualType T, raw_ostream &OS);
133 void printAfter(QualType T, raw_ostream &OS);
134 void printTagType(const TagType *T, raw_ostream &OS);
135 void printFunctionAfter(const FunctionType::ExtInfo &Info, raw_ostream &OS);
136#define ABSTRACT_TYPE(CLASS, PARENT)
137#define TYPE(CLASS, PARENT) \
138 void print##CLASS##Before(const CLASS##Type *T, raw_ostream &OS); \
139 void print##CLASS##After(const CLASS##Type *T, raw_ostream &OS);
140#include "clang/AST/TypeNodes.inc"
141
142private:
143 void printBefore(const Type *ty, Qualifiers qs, raw_ostream &OS);
144 void printAfter(const Type *ty, Qualifiers qs, raw_ostream &OS);
145};
146
147} // namespace
148
149static void AppendTypeQualList(raw_ostream &OS, unsigned TypeQuals,
150 bool HasRestrictKeyword) {
151 bool appendSpace = false;
152 if (TypeQuals & Qualifiers::Const) {
153 OS << "const";
154 appendSpace = true;
155 }
156 if (TypeQuals & Qualifiers::Volatile) {
157 if (appendSpace) OS << ' ';
158 OS << "volatile";
159 appendSpace = true;
160 }
161 if (TypeQuals & Qualifiers::Restrict) {
162 if (appendSpace) OS << ' ';
163 if (HasRestrictKeyword) {
164 OS << "restrict";
165 } else {
166 OS << "__restrict";
167 }
168 }
169}
170
171void TypePrinter::spaceBeforePlaceHolder(raw_ostream &OS) {
172 if (!HasEmptyPlaceHolder)
173 OS << ' ';
174}
175
176static SplitQualType splitAccordingToPolicy(QualType QT,
177 const PrintingPolicy &Policy) {
178 if (Policy.PrintAsCanonical)
179 QT = QT.getCanonicalType();
180 return QT.split();
181}
182
183void TypePrinter::print(QualType t, raw_ostream &OS, StringRef PlaceHolder) {
184 SplitQualType split = splitAccordingToPolicy(QT: t, Policy);
185 print(ty: split.Ty, qs: split.Quals, OS, PlaceHolder);
186}
187
188void TypePrinter::print(const Type *T, Qualifiers Quals, raw_ostream &OS,
189 StringRef PlaceHolder) {
190 if (!T) {
191 OS << "NULL TYPE";
192 return;
193 }
194
195 SaveAndRestore PHVal(HasEmptyPlaceHolder, PlaceHolder.empty());
196
197 printBefore(ty: T, qs: Quals, OS);
198 OS << PlaceHolder;
199 printAfter(ty: T, qs: Quals, OS);
200}
201
202bool TypePrinter::canPrefixQualifiers(const Type *T,
203 bool &NeedARCStrongQualifier) {
204 // CanPrefixQualifiers - We prefer to print type qualifiers before the type,
205 // so that we get "const int" instead of "int const", but we can't do this if
206 // the type is complex. For example if the type is "int*", we *must* print
207 // "int * const", printing "const int *" is different. Only do this when the
208 // type expands to a simple string.
209 bool CanPrefixQualifiers = false;
210 NeedARCStrongQualifier = false;
211 const Type *UnderlyingType = T;
212 if (const auto *AT = dyn_cast<AutoType>(Val: T))
213 UnderlyingType = AT->desugar().getTypePtr();
214 if (const auto *Subst = dyn_cast<SubstTemplateTypeParmType>(Val: T))
215 UnderlyingType = Subst->getReplacementType().getTypePtr();
216 Type::TypeClass TC = UnderlyingType->getTypeClass();
217
218 switch (TC) {
219 case Type::Auto:
220 case Type::Builtin:
221 case Type::Complex:
222 case Type::UnresolvedUsing:
223 case Type::Using:
224 case Type::Typedef:
225 case Type::TypeOfExpr:
226 case Type::TypeOf:
227 case Type::Decltype:
228 case Type::UnaryTransform:
229 case Type::Record:
230 case Type::Enum:
231 case Type::TemplateTypeParm:
232 case Type::SubstTemplateTypeParmPack:
233 case Type::SubstBuiltinTemplatePack:
234 case Type::DeducedTemplateSpecialization:
235 case Type::TemplateSpecialization:
236 case Type::InjectedClassName:
237 case Type::DependentName:
238 case Type::ObjCObject:
239 case Type::ObjCTypeParam:
240 case Type::ObjCInterface:
241 case Type::Atomic:
242 case Type::Pipe:
243 case Type::BitInt:
244 case Type::DependentBitInt:
245 case Type::OverflowBehavior:
246 case Type::BTFTagAttributed:
247 case Type::HLSLAttributedResource:
248 case Type::HLSLInlineSpirv:
249 case Type::PredefinedSugar:
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::ArrayParameter:
272 case Type::Pointer:
273 case Type::BlockPointer:
274 case Type::LValueReference:
275 case Type::RValueReference:
276 case Type::MemberPointer:
277 case Type::DependentAddressSpace:
278 case Type::DependentVector:
279 case Type::DependentSizedExtVector:
280 case Type::Vector:
281 case Type::ExtVector:
282 case Type::ConstantMatrix:
283 case Type::DependentSizedMatrix:
284 case Type::FunctionProto:
285 case Type::FunctionNoProto:
286 case Type::Paren:
287 case Type::PackExpansion:
288 case Type::SubstTemplateTypeParm:
289 case Type::MacroQualified:
290 case Type::CountAttributed:
291 case Type::LateParsedAttr:
292 CanPrefixQualifiers = false;
293 break;
294
295 case Type::Attributed: {
296 // We still want to print the address_space before the type if it is an
297 // address_space attribute.
298 const auto *AttrTy = cast<AttributedType>(Val: UnderlyingType);
299 CanPrefixQualifiers = AttrTy->getAttrKind() == attr::AddressSpace;
300 break;
301 }
302 case Type::PackIndexing: {
303 return canPrefixQualifiers(
304 T: cast<PackIndexingType>(Val: UnderlyingType)->getPattern().getTypePtr(),
305 NeedARCStrongQualifier);
306 }
307 }
308
309 return CanPrefixQualifiers;
310}
311
312void TypePrinter::printBefore(QualType T, raw_ostream &OS) {
313 SplitQualType Split = splitAccordingToPolicy(QT: T, Policy);
314
315 // If we have cv1 T, where T is substituted for cv2 U, only print cv1 - cv2
316 // at this level.
317 Qualifiers Quals = Split.Quals;
318 if (const auto *Subst = dyn_cast<SubstTemplateTypeParmType>(Val: Split.Ty))
319 Quals -= QualType(Subst, 0).getQualifiers();
320
321 printBefore(ty: Split.Ty, qs: Quals, OS);
322}
323
324/// Prints the part of the type string before an identifier, e.g. for
325/// "int foo[10]" it prints "int ".
326void TypePrinter::printBefore(const Type *T,Qualifiers Quals, raw_ostream &OS) {
327 if (Policy.SuppressSpecifiers && T->isSpecifierType())
328 return;
329
330 SaveAndRestore PrevPHIsEmpty(HasEmptyPlaceHolder);
331
332 // Print qualifiers as appropriate.
333
334 bool CanPrefixQualifiers = false;
335 bool NeedARCStrongQualifier = false;
336 CanPrefixQualifiers = canPrefixQualifiers(T, NeedARCStrongQualifier);
337
338 if (CanPrefixQualifiers && !Quals.empty()) {
339 if (NeedARCStrongQualifier) {
340 IncludeStrongLifetimeRAII Strong(Policy);
341 Quals.print(OS, Policy, /*appendSpaceIfNonEmpty=*/true);
342 } else {
343 Quals.print(OS, Policy, /*appendSpaceIfNonEmpty=*/true);
344 }
345 }
346
347 bool hasAfterQuals = false;
348 if (!CanPrefixQualifiers && !Quals.empty()) {
349 hasAfterQuals = !Quals.isEmptyWhenPrinted(Policy);
350 if (hasAfterQuals)
351 HasEmptyPlaceHolder = false;
352 }
353
354 switch (T->getTypeClass()) {
355#define ABSTRACT_TYPE(CLASS, PARENT)
356#define TYPE(CLASS, PARENT) case Type::CLASS: \
357 print##CLASS##Before(cast<CLASS##Type>(T), OS); \
358 break;
359#include "clang/AST/TypeNodes.inc"
360 }
361
362 if (hasAfterQuals) {
363 if (NeedARCStrongQualifier) {
364 IncludeStrongLifetimeRAII Strong(Policy);
365 Quals.print(OS, Policy, /*appendSpaceIfNonEmpty=*/!PrevPHIsEmpty.get());
366 } else {
367 Quals.print(OS, Policy, /*appendSpaceIfNonEmpty=*/!PrevPHIsEmpty.get());
368 }
369 }
370}
371
372void TypePrinter::printAfter(QualType t, raw_ostream &OS) {
373 SplitQualType split = splitAccordingToPolicy(QT: t, Policy);
374 printAfter(ty: split.Ty, qs: split.Quals, OS);
375}
376
377/// Prints the part of the type string after an identifier, e.g. for
378/// "int foo[10]" it prints "[10]".
379void TypePrinter::printAfter(const Type *T, Qualifiers Quals, raw_ostream &OS) {
380 switch (T->getTypeClass()) {
381#define ABSTRACT_TYPE(CLASS, PARENT)
382#define TYPE(CLASS, PARENT) case Type::CLASS: \
383 print##CLASS##After(cast<CLASS##Type>(T), OS); \
384 break;
385#include "clang/AST/TypeNodes.inc"
386 }
387}
388
389void TypePrinter::printBuiltinBefore(const BuiltinType *T, raw_ostream &OS) {
390 OS << T->getName(Policy);
391 spaceBeforePlaceHolder(OS);
392}
393
394void TypePrinter::printBuiltinAfter(const BuiltinType *T, raw_ostream &OS) {}
395
396void TypePrinter::printComplexBefore(const ComplexType *T, raw_ostream &OS) {
397 OS << "_Complex ";
398 printBefore(T: T->getElementType(), OS);
399}
400
401void TypePrinter::printComplexAfter(const ComplexType *T, raw_ostream &OS) {
402 printAfter(t: T->getElementType(), OS);
403}
404
405void TypePrinter::printPointerBefore(const PointerType *T, raw_ostream &OS) {
406 IncludeStrongLifetimeRAII Strong(Policy);
407 SaveAndRestore NonEmptyPH(HasEmptyPlaceHolder, false);
408 printBefore(T: T->getPointeeType(), OS);
409 // Handle things like 'int (*A)[4];' correctly.
410 // FIXME: this should include vectors, but vectors use attributes I guess.
411 if (isa<ArrayType>(Val: T->getPointeeType()))
412 OS << '(';
413 OS << '*';
414}
415
416void TypePrinter::printPointerAfter(const PointerType *T, raw_ostream &OS) {
417 IncludeStrongLifetimeRAII Strong(Policy);
418 SaveAndRestore NonEmptyPH(HasEmptyPlaceHolder, false);
419 // Handle things like 'int (*A)[4];' correctly.
420 // FIXME: this should include vectors, but vectors use attributes I guess.
421 if (isa<ArrayType>(Val: T->getPointeeType()))
422 OS << ')';
423 printAfter(t: T->getPointeeType(), OS);
424}
425
426void TypePrinter::printBlockPointerBefore(const BlockPointerType *T,
427 raw_ostream &OS) {
428 SaveAndRestore NonEmptyPH(HasEmptyPlaceHolder, false);
429 printBefore(T: T->getPointeeType(), OS);
430 OS << '^';
431}
432
433void TypePrinter::printBlockPointerAfter(const BlockPointerType *T,
434 raw_ostream &OS) {
435 SaveAndRestore NonEmptyPH(HasEmptyPlaceHolder, false);
436 printAfter(t: T->getPointeeType(), OS);
437}
438
439// When printing a reference, the referenced type might also be a reference.
440// If so, we want to skip that before printing the inner type.
441static QualType skipTopLevelReferences(QualType T) {
442 if (auto *Ref = T->getAs<ReferenceType>())
443 return skipTopLevelReferences(T: Ref->getPointeeTypeAsWritten());
444 return T;
445}
446
447void TypePrinter::printLValueReferenceBefore(const LValueReferenceType *T,
448 raw_ostream &OS) {
449 IncludeStrongLifetimeRAII Strong(Policy);
450 SaveAndRestore NonEmptyPH(HasEmptyPlaceHolder, false);
451 QualType Inner = skipTopLevelReferences(T: T->getPointeeTypeAsWritten());
452 printBefore(T: Inner, OS);
453 // Handle things like 'int (&A)[4];' correctly.
454 // FIXME: this should include vectors, but vectors use attributes I guess.
455 if (isa<ArrayType>(Val: Inner))
456 OS << '(';
457 OS << '&';
458}
459
460void TypePrinter::printLValueReferenceAfter(const LValueReferenceType *T,
461 raw_ostream &OS) {
462 IncludeStrongLifetimeRAII Strong(Policy);
463 SaveAndRestore NonEmptyPH(HasEmptyPlaceHolder, false);
464 QualType Inner = skipTopLevelReferences(T: T->getPointeeTypeAsWritten());
465 // Handle things like 'int (&A)[4];' correctly.
466 // FIXME: this should include vectors, but vectors use attributes I guess.
467 if (isa<ArrayType>(Val: Inner))
468 OS << ')';
469 printAfter(t: Inner, OS);
470}
471
472void TypePrinter::printRValueReferenceBefore(const RValueReferenceType *T,
473 raw_ostream &OS) {
474 IncludeStrongLifetimeRAII Strong(Policy);
475 SaveAndRestore NonEmptyPH(HasEmptyPlaceHolder, false);
476 QualType Inner = skipTopLevelReferences(T: T->getPointeeTypeAsWritten());
477 printBefore(T: Inner, OS);
478 // Handle things like 'int (&&A)[4];' correctly.
479 // FIXME: this should include vectors, but vectors use attributes I guess.
480 if (isa<ArrayType>(Val: Inner))
481 OS << '(';
482 OS << "&&";
483}
484
485void TypePrinter::printRValueReferenceAfter(const RValueReferenceType *T,
486 raw_ostream &OS) {
487 IncludeStrongLifetimeRAII Strong(Policy);
488 SaveAndRestore NonEmptyPH(HasEmptyPlaceHolder, false);
489 QualType Inner = skipTopLevelReferences(T: T->getPointeeTypeAsWritten());
490 // Handle things like 'int (&&A)[4];' correctly.
491 // FIXME: this should include vectors, but vectors use attributes I guess.
492 if (isa<ArrayType>(Val: Inner))
493 OS << ')';
494 printAfter(t: Inner, OS);
495}
496
497void TypePrinter::printMemberPointerBefore(const MemberPointerType *T,
498 raw_ostream &OS) {
499 IncludeStrongLifetimeRAII Strong(Policy);
500 SaveAndRestore NonEmptyPH(HasEmptyPlaceHolder, false);
501 printBefore(T: T->getPointeeType(), OS);
502 // Handle things like 'int (Cls::*A)[4];' correctly.
503 // FIXME: this should include vectors, but vectors use attributes I guess.
504 if (isa<ArrayType>(Val: T->getPointeeType()))
505 OS << '(';
506 T->getQualifier().print(OS, Policy);
507 OS << "*";
508}
509
510void TypePrinter::printMemberPointerAfter(const MemberPointerType *T,
511 raw_ostream &OS) {
512 IncludeStrongLifetimeRAII Strong(Policy);
513 SaveAndRestore NonEmptyPH(HasEmptyPlaceHolder, false);
514 // Handle things like 'int (Cls::*A)[4];' correctly.
515 // FIXME: this should include vectors, but vectors use attributes I guess.
516 if (isa<ArrayType>(Val: T->getPointeeType()))
517 OS << ')';
518 printAfter(t: T->getPointeeType(), OS);
519}
520
521void TypePrinter::printConstantArrayBefore(const ConstantArrayType *T,
522 raw_ostream &OS) {
523 IncludeStrongLifetimeRAII Strong(Policy);
524 printBefore(T: T->getElementType(), OS);
525}
526
527void TypePrinter::printConstantArrayAfter(const ConstantArrayType *T,
528 raw_ostream &OS) {
529 OS << '[';
530 if (T->getIndexTypeQualifiers().hasQualifiers()) {
531 AppendTypeQualList(OS, TypeQuals: T->getIndexTypeCVRQualifiers(),
532 HasRestrictKeyword: Policy.Restrict);
533 OS << ' ';
534 }
535
536 if (T->getSizeModifier() == ArraySizeModifier::Static)
537 OS << "static ";
538
539 OS << T->getZExtSize() << ']';
540 printAfter(t: T->getElementType(), OS);
541}
542
543void TypePrinter::printIncompleteArrayBefore(const IncompleteArrayType *T,
544 raw_ostream &OS) {
545 IncludeStrongLifetimeRAII Strong(Policy);
546 printBefore(T: T->getElementType(), OS);
547}
548
549void TypePrinter::printIncompleteArrayAfter(const IncompleteArrayType *T,
550 raw_ostream &OS) {
551 OS << "[]";
552 printAfter(t: T->getElementType(), OS);
553}
554
555void TypePrinter::printVariableArrayBefore(const VariableArrayType *T,
556 raw_ostream &OS) {
557 IncludeStrongLifetimeRAII Strong(Policy);
558 printBefore(T: T->getElementType(), OS);
559}
560
561void TypePrinter::printVariableArrayAfter(const VariableArrayType *T,
562 raw_ostream &OS) {
563 OS << '[';
564 if (T->getIndexTypeQualifiers().hasQualifiers()) {
565 AppendTypeQualList(OS, TypeQuals: T->getIndexTypeCVRQualifiers(), HasRestrictKeyword: Policy.Restrict);
566 OS << ' ';
567 }
568
569 if (T->getSizeModifier() == ArraySizeModifier::Static)
570 OS << "static ";
571 else if (T->getSizeModifier() == ArraySizeModifier::Star)
572 OS << '*';
573
574 if (T->getSizeExpr())
575 T->getSizeExpr()->printPretty(OS, Helper: nullptr, Policy);
576 OS << ']';
577
578 printAfter(t: T->getElementType(), OS);
579}
580
581void TypePrinter::printAdjustedBefore(const AdjustedType *T, raw_ostream &OS) {
582 // Print the adjusted representation, otherwise the adjustment will be
583 // invisible.
584 printBefore(T: T->getAdjustedType(), OS);
585}
586
587void TypePrinter::printAdjustedAfter(const AdjustedType *T, raw_ostream &OS) {
588 printAfter(t: T->getAdjustedType(), OS);
589}
590
591void TypePrinter::printDecayedBefore(const DecayedType *T, raw_ostream &OS) {
592 // Print as though it's a pointer.
593 printAdjustedBefore(T, OS);
594}
595
596void TypePrinter::printArrayParameterAfter(const ArrayParameterType *T,
597 raw_ostream &OS) {
598 printConstantArrayAfter(T, OS);
599}
600
601void TypePrinter::printArrayParameterBefore(const ArrayParameterType *T,
602 raw_ostream &OS) {
603 printConstantArrayBefore(T, OS);
604}
605
606void TypePrinter::printDecayedAfter(const DecayedType *T, raw_ostream &OS) {
607 printAdjustedAfter(T, OS);
608}
609
610void TypePrinter::printDependentSizedArrayBefore(
611 const DependentSizedArrayType *T,
612 raw_ostream &OS) {
613 IncludeStrongLifetimeRAII Strong(Policy);
614 printBefore(T: T->getElementType(), OS);
615}
616
617void TypePrinter::printDependentSizedArrayAfter(
618 const DependentSizedArrayType *T,
619 raw_ostream &OS) {
620 OS << '[';
621 if (T->getSizeExpr())
622 T->getSizeExpr()->printPretty(OS, Helper: nullptr, Policy);
623 OS << ']';
624 printAfter(t: T->getElementType(), OS);
625}
626
627void TypePrinter::printDependentAddressSpaceBefore(
628 const DependentAddressSpaceType *T, raw_ostream &OS) {
629 printBefore(T: T->getPointeeType(), OS);
630}
631
632void TypePrinter::printDependentAddressSpaceAfter(
633 const DependentAddressSpaceType *T, raw_ostream &OS) {
634 OS << " __attribute__((address_space(";
635 if (T->getAddrSpaceExpr())
636 T->getAddrSpaceExpr()->printPretty(OS, Helper: nullptr, Policy);
637 OS << ")))";
638 printAfter(t: T->getPointeeType(), OS);
639}
640
641void TypePrinter::printDependentSizedExtVectorBefore(
642 const DependentSizedExtVectorType *T, raw_ostream &OS) {
643 if (Policy.UseHLSLTypes) {
644 OS << "vector<";
645 print(t: T->getElementType(), OS, PlaceHolder: StringRef());
646 OS << ", ";
647 if (T->getSizeExpr())
648 T->getSizeExpr()->printPretty(OS, Helper: nullptr, Policy);
649 OS << ">";
650 spaceBeforePlaceHolder(OS);
651 } else {
652 printBefore(T: T->getElementType(), OS);
653 }
654}
655
656void TypePrinter::printDependentSizedExtVectorAfter(
657 const DependentSizedExtVectorType *T, raw_ostream &OS) {
658 if (Policy.UseHLSLTypes)
659 return;
660
661 OS << " __attribute__((ext_vector_type(";
662 if (T->getSizeExpr())
663 T->getSizeExpr()->printPretty(OS, Helper: nullptr, Policy);
664 OS << ")))";
665 printAfter(t: T->getElementType(), OS);
666}
667
668void TypePrinter::printVectorBefore(const VectorType *T, raw_ostream &OS) {
669 switch (T->getVectorKind()) {
670 case VectorKind::AltiVecPixel:
671 OS << "__vector __pixel ";
672 break;
673 case VectorKind::AltiVecBool:
674 OS << "__vector __bool ";
675 printBefore(T: T->getElementType(), OS);
676 break;
677 case VectorKind::AltiVecVector:
678 OS << "__vector ";
679 printBefore(T: T->getElementType(), OS);
680 break;
681 case VectorKind::Neon:
682 OS << "__attribute__((neon_vector_type("
683 << T->getNumElements() << "))) ";
684 printBefore(T: T->getElementType(), OS);
685 break;
686 case VectorKind::NeonPoly:
687 OS << "__attribute__((neon_polyvector_type(" <<
688 T->getNumElements() << "))) ";
689 printBefore(T: T->getElementType(), OS);
690 break;
691 case VectorKind::Generic: {
692 // FIXME: We prefer to print the size directly here, but have no way
693 // to get the size of the type.
694 OS << "__attribute__((__vector_size__("
695 << T->getNumElements()
696 << " * sizeof(";
697 print(t: T->getElementType(), OS, PlaceHolder: StringRef());
698 OS << ")))) ";
699 printBefore(T: T->getElementType(), OS);
700 break;
701 }
702 case VectorKind::SveFixedLengthData:
703 case VectorKind::SveFixedLengthPredicate:
704 // FIXME: We prefer to print the size directly here, but have no way
705 // to get the size of the type.
706 OS << "__attribute__((__arm_sve_vector_bits__(";
707
708 if (T->getVectorKind() == VectorKind::SveFixedLengthPredicate)
709 // Predicates take a bit per byte of the vector size, multiply by 8 to
710 // get the number of bits passed to the attribute.
711 OS << T->getNumElements() * 8;
712 else
713 OS << T->getNumElements();
714
715 OS << " * sizeof(";
716 print(t: T->getElementType(), OS, PlaceHolder: StringRef());
717 // Multiply by 8 for the number of bits.
718 OS << ") * 8))) ";
719 printBefore(T: T->getElementType(), OS);
720 break;
721 case VectorKind::RVVFixedLengthData:
722 case VectorKind::RVVFixedLengthMask:
723 case VectorKind::RVVFixedLengthMask_1:
724 case VectorKind::RVVFixedLengthMask_2:
725 case VectorKind::RVVFixedLengthMask_4:
726 // FIXME: We prefer to print the size directly here, but have no way
727 // to get the size of the type.
728 OS << "__attribute__((__riscv_rvv_vector_bits__(";
729 switch (T->getVectorKind()) {
730 case VectorKind::RVVFixedLengthMask_1:
731 OS << '1';
732 break;
733 case VectorKind::RVVFixedLengthMask_2:
734 OS << '2';
735 break;
736 case VectorKind::RVVFixedLengthMask_4:
737 OS << '4';
738 break;
739 default:
740 OS << T->getNumElements();
741 OS << " * sizeof(";
742 print(t: T->getElementType(), OS, PlaceHolder: StringRef());
743 // Multiply by 8 for the number of bits.
744 OS << ") * 8";
745 break;
746 }
747 OS << "))) ";
748 printBefore(T: T->getElementType(), OS);
749 break;
750 }
751}
752
753void TypePrinter::printVectorAfter(const VectorType *T, raw_ostream &OS) {
754 printAfter(t: T->getElementType(), OS);
755}
756
757void TypePrinter::printDependentVectorBefore(
758 const DependentVectorType *T, raw_ostream &OS) {
759 switch (T->getVectorKind()) {
760 case VectorKind::AltiVecPixel:
761 OS << "__vector __pixel ";
762 break;
763 case VectorKind::AltiVecBool:
764 OS << "__vector __bool ";
765 printBefore(T: T->getElementType(), OS);
766 break;
767 case VectorKind::AltiVecVector:
768 OS << "__vector ";
769 printBefore(T: T->getElementType(), OS);
770 break;
771 case VectorKind::Neon:
772 OS << "__attribute__((neon_vector_type(";
773 if (T->getSizeExpr())
774 T->getSizeExpr()->printPretty(OS, Helper: nullptr, Policy);
775 OS << "))) ";
776 printBefore(T: T->getElementType(), OS);
777 break;
778 case VectorKind::NeonPoly:
779 OS << "__attribute__((neon_polyvector_type(";
780 if (T->getSizeExpr())
781 T->getSizeExpr()->printPretty(OS, Helper: nullptr, Policy);
782 OS << "))) ";
783 printBefore(T: T->getElementType(), OS);
784 break;
785 case VectorKind::Generic: {
786 // FIXME: We prefer to print the size directly here, but have no way
787 // to get the size of the type.
788 OS << "__attribute__((__vector_size__(";
789 if (T->getSizeExpr())
790 T->getSizeExpr()->printPretty(OS, Helper: nullptr, Policy);
791 OS << " * sizeof(";
792 print(t: T->getElementType(), OS, PlaceHolder: StringRef());
793 OS << ")))) ";
794 printBefore(T: T->getElementType(), OS);
795 break;
796 }
797 case VectorKind::SveFixedLengthData:
798 case VectorKind::SveFixedLengthPredicate:
799 // FIXME: We prefer to print the size directly here, but have no way
800 // to get the size of the type.
801 OS << "__attribute__((__arm_sve_vector_bits__(";
802 if (T->getSizeExpr()) {
803 T->getSizeExpr()->printPretty(OS, Helper: nullptr, Policy);
804 if (T->getVectorKind() == VectorKind::SveFixedLengthPredicate)
805 // Predicates take a bit per byte of the vector size, multiply by 8 to
806 // get the number of bits passed to the attribute.
807 OS << " * 8";
808 OS << " * sizeof(";
809 print(t: T->getElementType(), OS, PlaceHolder: StringRef());
810 // Multiply by 8 for the number of bits.
811 OS << ") * 8";
812 }
813 OS << "))) ";
814 printBefore(T: T->getElementType(), OS);
815 break;
816 case VectorKind::RVVFixedLengthData:
817 case VectorKind::RVVFixedLengthMask:
818 case VectorKind::RVVFixedLengthMask_1:
819 case VectorKind::RVVFixedLengthMask_2:
820 case VectorKind::RVVFixedLengthMask_4:
821 // FIXME: We prefer to print the size directly here, but have no way
822 // to get the size of the type.
823 OS << "__attribute__((__riscv_rvv_vector_bits__(";
824 switch (T->getVectorKind()) {
825 case VectorKind::RVVFixedLengthMask_1:
826 OS << '1';
827 break;
828 case VectorKind::RVVFixedLengthMask_2:
829 OS << '2';
830 break;
831 case VectorKind::RVVFixedLengthMask_4:
832 OS << '4';
833 break;
834 default:
835 if (T->getSizeExpr()) {
836 T->getSizeExpr()->printPretty(OS, Helper: nullptr, Policy);
837 OS << " * sizeof(";
838 print(t: T->getElementType(), OS, PlaceHolder: StringRef());
839 // Multiply by 8 for the number of bits.
840 OS << ") * 8";
841 }
842 break;
843 }
844 OS << "))) ";
845 printBefore(T: T->getElementType(), OS);
846 break;
847 }
848}
849
850void TypePrinter::printDependentVectorAfter(
851 const DependentVectorType *T, raw_ostream &OS) {
852 printAfter(t: T->getElementType(), OS);
853}
854
855void TypePrinter::printExtVectorBefore(const ExtVectorType *T,
856 raw_ostream &OS) {
857 if (Policy.UseHLSLTypes) {
858 OS << "vector<";
859 print(t: T->getElementType(), OS, PlaceHolder: StringRef());
860 OS << ", " << T->getNumElements() << ">";
861 spaceBeforePlaceHolder(OS);
862 } else {
863 printBefore(T: T->getElementType(), OS);
864 }
865}
866
867void TypePrinter::printExtVectorAfter(const ExtVectorType *T, raw_ostream &OS) {
868 if (Policy.UseHLSLTypes)
869 return;
870
871 printAfter(t: T->getElementType(), OS);
872 OS << " __attribute__((ext_vector_type(";
873 OS << T->getNumElements();
874 OS << ")))";
875}
876
877static void printDims(const ConstantMatrixType *T, raw_ostream &OS) {
878 OS << T->getNumRows() << ", " << T->getNumColumns();
879}
880
881static void printHLSLMatrixBefore(TypePrinter &TP, const ConstantMatrixType *T,
882 raw_ostream &OS) {
883 OS << "matrix<";
884 TP.print(t: T->getElementType(), OS, PlaceHolder: StringRef());
885 OS << ", ";
886 printDims(T, OS);
887 OS << ">";
888 TP.spaceBeforePlaceHolder(OS);
889}
890
891static void printHLSLMatrixAfter(const ConstantMatrixType *T, raw_ostream &OS) {
892}
893
894static void printClangMatrixBefore(TypePrinter &TP, const ConstantMatrixType *T,
895 raw_ostream &OS) {
896 TP.printBefore(T: T->getElementType(), OS);
897 OS << " __attribute__((matrix_type(";
898 printDims(T, OS);
899 OS << ")))";
900}
901
902void TypePrinter::printConstantMatrixBefore(const ConstantMatrixType *T,
903 raw_ostream &OS) {
904 if (Policy.UseHLSLTypes) {
905 printHLSLMatrixBefore(TP&: *this, T, OS);
906 return;
907 }
908 printClangMatrixBefore(TP&: *this, T, OS);
909}
910
911void TypePrinter::printConstantMatrixAfter(const ConstantMatrixType *T,
912 raw_ostream &OS) {
913 if (Policy.UseHLSLTypes) {
914 printHLSLMatrixAfter(T, OS);
915 return;
916 }
917 printAfter(t: T->getElementType(), OS);
918}
919
920void TypePrinter::printDependentSizedMatrixBefore(
921 const DependentSizedMatrixType *T, raw_ostream &OS) {
922 if (Policy.UseHLSLTypes) {
923 OS << "matrix<";
924 print(t: T->getElementType(), OS, PlaceHolder: StringRef());
925 OS << ", ";
926 if (T->getRowExpr())
927 T->getRowExpr()->printPretty(OS, Helper: nullptr, Policy);
928 OS << ", ";
929 if (T->getColumnExpr())
930 T->getColumnExpr()->printPretty(OS, Helper: nullptr, Policy);
931 OS << ">";
932 spaceBeforePlaceHolder(OS);
933 } else {
934 printBefore(T: T->getElementType(), OS);
935 OS << " __attribute__((matrix_type(";
936 if (T->getRowExpr())
937 T->getRowExpr()->printPretty(OS, Helper: nullptr, Policy);
938 OS << ", ";
939 if (T->getColumnExpr())
940 T->getColumnExpr()->printPretty(OS, Helper: nullptr, Policy);
941 OS << ")))";
942 }
943}
944
945void TypePrinter::printDependentSizedMatrixAfter(
946 const DependentSizedMatrixType *T, raw_ostream &OS) {
947 if (!Policy.UseHLSLTypes)
948 printAfter(t: T->getElementType(), OS);
949}
950
951void
952FunctionProtoType::printExceptionSpecification(raw_ostream &OS,
953 const PrintingPolicy &Policy)
954 const {
955 if (hasDynamicExceptionSpec()) {
956 OS << " throw(";
957 if (getExceptionSpecType() == EST_MSAny)
958 OS << "...";
959 else
960 for (unsigned I = 0, N = getNumExceptions(); I != N; ++I) {
961 if (I)
962 OS << ", ";
963
964 OS << getExceptionType(i: I).stream(Policy);
965 }
966 OS << ')';
967 } else if (EST_NoThrow == getExceptionSpecType()) {
968 OS << " __attribute__((nothrow))";
969 } else if (isNoexceptExceptionSpec(ESpecType: getExceptionSpecType())) {
970 OS << " noexcept";
971 // FIXME:Is it useful to print out the expression for a non-dependent
972 // noexcept specification?
973 if (isComputedNoexcept(ESpecType: getExceptionSpecType())) {
974 OS << '(';
975 if (getNoexceptExpr())
976 getNoexceptExpr()->printPretty(OS, Helper: nullptr, Policy);
977 OS << ')';
978 }
979 }
980}
981
982void TypePrinter::printFunctionProtoBefore(const FunctionProtoType *T,
983 raw_ostream &OS) {
984 if (T->hasTrailingReturn()) {
985 OS << "auto ";
986 if (!HasEmptyPlaceHolder)
987 OS << '(';
988 } else {
989 // If needed for precedence reasons, wrap the inner part in grouping parens.
990 SaveAndRestore PrevPHIsEmpty(HasEmptyPlaceHolder, false);
991 printBefore(T: T->getReturnType(), OS);
992 if (!PrevPHIsEmpty.get())
993 OS << '(';
994 }
995}
996
997StringRef clang::getParameterABISpelling(ParameterABI ABI) {
998 switch (ABI) {
999 case ParameterABI::Ordinary:
1000 llvm_unreachable("asking for spelling of ordinary parameter ABI");
1001 case ParameterABI::SwiftContext:
1002 return "swift_context";
1003 case ParameterABI::SwiftAsyncContext:
1004 return "swift_async_context";
1005 case ParameterABI::SwiftErrorResult:
1006 return "swift_error_result";
1007 case ParameterABI::SwiftIndirectResult:
1008 return "swift_indirect_result";
1009 case ParameterABI::HLSLOut:
1010 return "out";
1011 case ParameterABI::HLSLInOut:
1012 return "inout";
1013 }
1014 llvm_unreachable("bad parameter ABI kind");
1015}
1016
1017void TypePrinter::printFunctionProtoAfter(const FunctionProtoType *T,
1018 raw_ostream &OS) {
1019 // If needed for precedence reasons, wrap the inner part in grouping parens.
1020 if (!HasEmptyPlaceHolder)
1021 OS << ')';
1022 SaveAndRestore NonEmptyPH(HasEmptyPlaceHolder, false);
1023
1024 OS << '(';
1025 {
1026 ParamPolicyRAII ParamPolicy(Policy);
1027 for (unsigned i = 0, e = T->getNumParams(); i != e; ++i) {
1028 if (i) OS << ", ";
1029
1030 auto EPI = T->getExtParameterInfo(I: i);
1031 if (EPI.isConsumed()) OS << "__attribute__((ns_consumed)) ";
1032 if (EPI.isNoEscape())
1033 OS << "__attribute__((noescape)) ";
1034 auto ABI = EPI.getABI();
1035 if (ABI == ParameterABI::HLSLInOut || ABI == ParameterABI::HLSLOut) {
1036 OS << getParameterABISpelling(ABI) << " ";
1037 if (Policy.UseHLSLTypes) {
1038 // This is a bit of a hack because we _do_ use reference types in the
1039 // AST for representing inout and out parameters so that code
1040 // generation is sane, but when re-printing these for HLSL we need to
1041 // skip the reference.
1042 print(t: T->getParamType(i).getNonReferenceType(), OS, PlaceHolder: StringRef());
1043 continue;
1044 }
1045 } else if (ABI != ParameterABI::Ordinary)
1046 OS << "__attribute__((" << getParameterABISpelling(ABI) << ")) ";
1047
1048 print(t: T->getParamType(i), OS, PlaceHolder: StringRef());
1049 }
1050 }
1051
1052 if (T->isVariadic()) {
1053 if (T->getNumParams())
1054 OS << ", ";
1055 OS << "...";
1056 } else if (T->getNumParams() == 0 && Policy.UseVoidForZeroParams) {
1057 // Do not emit int() if we have a proto, emit 'int(void)'.
1058 OS << "void";
1059 }
1060
1061 OS << ')';
1062
1063 FunctionType::ExtInfo Info = T->getExtInfo();
1064 unsigned SMEBits = T->getAArch64SMEAttributes();
1065
1066 if (SMEBits & FunctionType::SME_PStateSMCompatibleMask)
1067 OS << " __arm_streaming_compatible";
1068 if (SMEBits & FunctionType::SME_PStateSMEnabledMask)
1069 OS << " __arm_streaming";
1070 if (SMEBits & FunctionType::SME_AgnosticZAStateMask)
1071 OS << "__arm_agnostic(\"sme_za_state\")";
1072 if (FunctionType::getArmZAState(AttrBits: SMEBits) == FunctionType::ARM_Preserves)
1073 OS << " __arm_preserves(\"za\")";
1074 if (FunctionType::getArmZAState(AttrBits: SMEBits) == FunctionType::ARM_In)
1075 OS << " __arm_in(\"za\")";
1076 if (FunctionType::getArmZAState(AttrBits: SMEBits) == FunctionType::ARM_Out)
1077 OS << " __arm_out(\"za\")";
1078 if (FunctionType::getArmZAState(AttrBits: SMEBits) == FunctionType::ARM_InOut)
1079 OS << " __arm_inout(\"za\")";
1080 if (FunctionType::getArmZT0State(AttrBits: SMEBits) == FunctionType::ARM_Preserves)
1081 OS << " __arm_preserves(\"zt0\")";
1082 if (FunctionType::getArmZT0State(AttrBits: SMEBits) == FunctionType::ARM_In)
1083 OS << " __arm_in(\"zt0\")";
1084 if (FunctionType::getArmZT0State(AttrBits: SMEBits) == FunctionType::ARM_Out)
1085 OS << " __arm_out(\"zt0\")";
1086 if (FunctionType::getArmZT0State(AttrBits: SMEBits) == FunctionType::ARM_InOut)
1087 OS << " __arm_inout(\"zt0\")";
1088
1089 printFunctionAfter(Info, OS);
1090
1091 if (!T->getMethodQuals().empty())
1092 OS << " " << T->getMethodQuals().getAsString();
1093
1094 switch (T->getRefQualifier()) {
1095 case RQ_None:
1096 break;
1097
1098 case RQ_LValue:
1099 OS << " &";
1100 break;
1101
1102 case RQ_RValue:
1103 OS << " &&";
1104 break;
1105 }
1106 T->printExceptionSpecification(OS, Policy);
1107
1108 const FunctionEffectsRef FX = T->getFunctionEffects();
1109 for (const auto &CFE : FX) {
1110 OS << " __attribute__((" << CFE.Effect.name();
1111 if (const Expr *E = CFE.Cond.getCondition()) {
1112 OS << '(';
1113 E->printPretty(OS, Helper: nullptr, Policy);
1114 OS << ')';
1115 }
1116 OS << "))";
1117 }
1118
1119 if (T->hasCFIUncheckedCallee())
1120 OS << " __attribute__((cfi_unchecked_callee))";
1121
1122 if (T->hasTrailingReturn()) {
1123 OS << " -> ";
1124 print(t: T->getReturnType(), OS, PlaceHolder: StringRef());
1125 } else
1126 printAfter(t: T->getReturnType(), OS);
1127}
1128
1129void TypePrinter::printFunctionAfter(const FunctionType::ExtInfo &Info,
1130 raw_ostream &OS) {
1131 if (!InsideCCAttribute) {
1132 switch (Info.getCC()) {
1133 case CC_C:
1134 // The C calling convention is the default on the vast majority of platforms
1135 // we support. If the user wrote it explicitly, it will usually be printed
1136 // while traversing the AttributedType. If the type has been desugared, let
1137 // the canonical spelling be the implicit calling convention.
1138 // FIXME: It would be better to be explicit in certain contexts, such as a
1139 // cdecl function typedef used to declare a member function with the
1140 // Microsoft C++ ABI.
1141 break;
1142 case CC_X86StdCall:
1143 OS << " __attribute__((stdcall))";
1144 break;
1145 case CC_X86FastCall:
1146 OS << " __attribute__((fastcall))";
1147 break;
1148 case CC_X86ThisCall:
1149 OS << " __attribute__((thiscall))";
1150 break;
1151 case CC_X86VectorCall:
1152 OS << " __attribute__((vectorcall))";
1153 break;
1154 case CC_X86Pascal:
1155 OS << " __attribute__((pascal))";
1156 break;
1157 case CC_AAPCS:
1158 OS << " __attribute__((pcs(\"aapcs\")))";
1159 break;
1160 case CC_AAPCS_VFP:
1161 OS << " __attribute__((pcs(\"aapcs-vfp\")))";
1162 break;
1163 case CC_AArch64VectorCall:
1164 OS << " __attribute__((aarch64_vector_pcs))";
1165 break;
1166 case CC_AArch64SVEPCS:
1167 OS << " __attribute__((aarch64_sve_pcs))";
1168 break;
1169 case CC_DeviceKernel:
1170 OS << " __attribute__((device_kernel))";
1171 break;
1172 case CC_IntelOclBicc:
1173 OS << " __attribute__((intel_ocl_bicc))";
1174 break;
1175 case CC_Win64:
1176 OS << " __attribute__((ms_abi))";
1177 break;
1178 case CC_X86_64SysV:
1179 OS << " __attribute__((sysv_abi))";
1180 break;
1181 case CC_X86RegCall:
1182 OS << " __attribute__((regcall))";
1183 break;
1184 case CC_Swift:
1185 OS << " __attribute__((swiftcall))";
1186 break;
1187 case CC_SwiftAsync:
1188 OS << "__attribute__((swiftasynccall))";
1189 break;
1190 case CC_PreserveMost:
1191 OS << " __attribute__((preserve_most))";
1192 break;
1193 case CC_PreserveAll:
1194 OS << " __attribute__((preserve_all))";
1195 break;
1196 case CC_M68kRTD:
1197 OS << " __attribute__((m68k_rtd))";
1198 break;
1199 case CC_PreserveNone:
1200 OS << " __attribute__((preserve_none))";
1201 break;
1202 case CC_RISCVVectorCall:
1203 OS << "__attribute__((riscv_vector_cc))";
1204 break;
1205#define CC_VLS_CASE(ABI_VLEN) \
1206 case CC_RISCVVLSCall_##ABI_VLEN: \
1207 OS << "__attribute__((riscv_vls_cc" #ABI_VLEN "))"; \
1208 break;
1209 CC_VLS_CASE(32)
1210 CC_VLS_CASE(64)
1211 CC_VLS_CASE(128)
1212 CC_VLS_CASE(256)
1213 CC_VLS_CASE(512)
1214 CC_VLS_CASE(1024)
1215 CC_VLS_CASE(2048)
1216 CC_VLS_CASE(4096)
1217 CC_VLS_CASE(8192)
1218 CC_VLS_CASE(16384)
1219 CC_VLS_CASE(32768)
1220 CC_VLS_CASE(65536)
1221#undef CC_VLS_CASE
1222 }
1223 }
1224
1225 if (Info.getNoReturn())
1226 OS << " __attribute__((noreturn))";
1227 if (Info.getCmseNSCall())
1228 OS << " __attribute__((cmse_nonsecure_call))";
1229 if (Info.getProducesResult())
1230 OS << " __attribute__((ns_returns_retained))";
1231 if (Info.getRegParm())
1232 OS << " __attribute__((regparm ("
1233 << Info.getRegParm() << ")))";
1234 if (Info.getNoCallerSavedRegs())
1235 OS << " __attribute__((no_caller_saved_registers))";
1236 if (Info.getNoCfCheck())
1237 OS << " __attribute__((nocf_check))";
1238}
1239
1240void TypePrinter::printFunctionNoProtoBefore(const FunctionNoProtoType *T,
1241 raw_ostream &OS) {
1242 // If needed for precedence reasons, wrap the inner part in grouping parens.
1243 SaveAndRestore PrevPHIsEmpty(HasEmptyPlaceHolder, false);
1244 printBefore(T: T->getReturnType(), OS);
1245 if (!PrevPHIsEmpty.get())
1246 OS << '(';
1247}
1248
1249void TypePrinter::printFunctionNoProtoAfter(const FunctionNoProtoType *T,
1250 raw_ostream &OS) {
1251 // If needed for precedence reasons, wrap the inner part in grouping parens.
1252 if (!HasEmptyPlaceHolder)
1253 OS << ')';
1254 SaveAndRestore NonEmptyPH(HasEmptyPlaceHolder, false);
1255
1256 OS << "()";
1257 printFunctionAfter(Info: T->getExtInfo(), OS);
1258 printAfter(t: T->getReturnType(), OS);
1259}
1260
1261void TypePrinter::printTypeSpec(NamedDecl *D, raw_ostream &OS) {
1262
1263 // Compute the full nested-name-specifier for this type.
1264 // In C, this will always be empty except when the type
1265 // being printed is anonymous within other Record.
1266 if (!Policy.SuppressScope)
1267 D->printNestedNameSpecifier(OS, Policy);
1268
1269 IdentifierInfo *II = D->getIdentifier();
1270 OS << II->getName();
1271 spaceBeforePlaceHolder(OS);
1272}
1273
1274void TypePrinter::printUnresolvedUsingBefore(const UnresolvedUsingType *T,
1275 raw_ostream &OS) {
1276 OS << TypeWithKeyword::getKeywordName(Keyword: T->getKeyword());
1277 if (T->getKeyword() != ElaboratedTypeKeyword::None)
1278 OS << ' ';
1279 auto *D = T->getDecl();
1280 if (Policy.FullyQualifiedName || T->isCanonicalUnqualified()) {
1281 D->printNestedNameSpecifier(OS, Policy);
1282 } else {
1283 T->getQualifier().print(OS, Policy);
1284 }
1285 OS << D->getIdentifier()->getName();
1286 spaceBeforePlaceHolder(OS);
1287}
1288
1289void TypePrinter::printUnresolvedUsingAfter(const UnresolvedUsingType *T,
1290 raw_ostream &OS) {}
1291
1292void TypePrinter::printUsingBefore(const UsingType *T, raw_ostream &OS) {
1293 OS << TypeWithKeyword::getKeywordName(Keyword: T->getKeyword());
1294 if (T->getKeyword() != ElaboratedTypeKeyword::None)
1295 OS << ' ';
1296 auto *D = T->getDecl();
1297 if (Policy.FullyQualifiedName) {
1298 D->printNestedNameSpecifier(OS, Policy);
1299 } else {
1300 T->getQualifier().print(OS, Policy);
1301 }
1302 OS << D->getIdentifier()->getName();
1303 spaceBeforePlaceHolder(OS);
1304}
1305
1306void TypePrinter::printUsingAfter(const UsingType *T, raw_ostream &OS) {}
1307
1308void TypePrinter::printTypedefBefore(const TypedefType *T, raw_ostream &OS) {
1309 OS << TypeWithKeyword::getKeywordName(Keyword: T->getKeyword());
1310 if (T->getKeyword() != ElaboratedTypeKeyword::None)
1311 OS << ' ';
1312 auto *D = T->getDecl();
1313 if (Policy.FullyQualifiedName) {
1314 D->printNestedNameSpecifier(OS, Policy);
1315 } else {
1316 T->getQualifier().print(OS, Policy);
1317 }
1318 OS << D->getIdentifier()->getName();
1319 spaceBeforePlaceHolder(OS);
1320}
1321
1322void TypePrinter::printMacroQualifiedBefore(const MacroQualifiedType *T,
1323 raw_ostream &OS) {
1324 StringRef MacroName = T->getMacroIdentifier()->getName();
1325 OS << MacroName << " ";
1326
1327 // Since this type is meant to print the macro instead of the whole attribute,
1328 // we trim any attributes and go directly to the original modified type.
1329 printBefore(T: T->getModifiedType(), OS);
1330}
1331
1332void TypePrinter::printMacroQualifiedAfter(const MacroQualifiedType *T,
1333 raw_ostream &OS) {
1334 printAfter(t: T->getModifiedType(), OS);
1335}
1336
1337void TypePrinter::printTypedefAfter(const TypedefType *T, raw_ostream &OS) {}
1338
1339void TypePrinter::printTypeOfExprBefore(const TypeOfExprType *T,
1340 raw_ostream &OS) {
1341 OS << (T->getKind() == TypeOfKind::Unqualified ? "typeof_unqual "
1342 : "typeof ");
1343 if (T->getUnderlyingExpr())
1344 T->getUnderlyingExpr()->printPretty(OS, Helper: nullptr, Policy);
1345 spaceBeforePlaceHolder(OS);
1346}
1347
1348void TypePrinter::printTypeOfExprAfter(const TypeOfExprType *T,
1349 raw_ostream &OS) {}
1350
1351void TypePrinter::printTypeOfBefore(const TypeOfType *T, raw_ostream &OS) {
1352 OS << (T->getKind() == TypeOfKind::Unqualified ? "typeof_unqual("
1353 : "typeof(");
1354 print(t: T->getUnmodifiedType(), OS, PlaceHolder: StringRef());
1355 OS << ')';
1356 spaceBeforePlaceHolder(OS);
1357}
1358
1359void TypePrinter::printTypeOfAfter(const TypeOfType *T, raw_ostream &OS) {}
1360
1361void TypePrinter::printDecltypeBefore(const DecltypeType *T, raw_ostream &OS) {
1362 if (Policy.ResolveDecltype && T->isSugared()) {
1363 printBefore(T: T->desugar(), OS);
1364 return;
1365 }
1366 OS << "decltype(";
1367 if (const Expr *E = T->getUnderlyingExpr()) {
1368 PrintingPolicy ExprPolicy = Policy;
1369 ExprPolicy.PrintAsCanonical = T->isCanonicalUnqualified();
1370 E->printPretty(OS, Helper: nullptr, Policy: ExprPolicy);
1371 }
1372 OS << ')';
1373 spaceBeforePlaceHolder(OS);
1374}
1375
1376void TypePrinter::printPackIndexingBefore(const PackIndexingType *T,
1377 raw_ostream &OS) {
1378 if (T->hasSelectedType()) {
1379 OS << T->getSelectedType();
1380 } else {
1381 OS << T->getPattern() << "...[";
1382 T->getIndexExpr()->printPretty(OS, Helper: nullptr, Policy);
1383 OS << "]";
1384 }
1385 spaceBeforePlaceHolder(OS);
1386}
1387
1388void TypePrinter::printPackIndexingAfter(const PackIndexingType *T,
1389 raw_ostream &OS) {}
1390
1391void TypePrinter::printDecltypeAfter(const DecltypeType *T, raw_ostream &OS) {
1392 if (Policy.ResolveDecltype && T->isSugared())
1393 printAfter(t: T->desugar(), OS);
1394}
1395
1396void TypePrinter::printUnaryTransformBefore(const UnaryTransformType *T,
1397 raw_ostream &OS) {
1398 IncludeStrongLifetimeRAII Strong(Policy);
1399
1400 static const llvm::DenseMap<int, const char *> Transformation = {{
1401#define TRANSFORM_TYPE_TRAIT_DEF(Enum, Trait) \
1402 {UnaryTransformType::Enum, "__" #Trait},
1403#include "clang/Basic/BuiltinTraits.inc"
1404 }};
1405 OS << Transformation.lookup(Val: T->getUTTKind()) << '(';
1406 print(t: T->getBaseType(), OS, PlaceHolder: StringRef());
1407 OS << ')';
1408 spaceBeforePlaceHolder(OS);
1409}
1410
1411void TypePrinter::printUnaryTransformAfter(const UnaryTransformType *T,
1412 raw_ostream &OS) {}
1413
1414void TypePrinter::printAutoBefore(const AutoType *T, raw_ostream &OS) {
1415 // If the type has been deduced, do not print 'auto'.
1416 if (!T->getDeducedType().isNull()) {
1417 printBefore(T: T->getDeducedType(), OS);
1418 } else {
1419 if (T->isConstrained()) {
1420 // FIXME: Track a TypeConstraint as type sugar, so that we can print the
1421 // type as it was written.
1422 TemplateName Concept = T->getTypeConstraintConcept();
1423 Concept.print(OS, Policy, Qual: TemplateName::Qualified::None);
1424 auto Args = T->getTypeConstraintArguments();
1425 if (!Args.empty()) {
1426 const TemplateDecl *TD = Concept.getAsTemplateDecl();
1427 if (!TD)
1428 TD = Concept.getAsTemplateTemplateParmDecl();
1429 printTemplateArgumentList(OS, Args, Policy,
1430 TPL: TD->getTemplateParameters());
1431 }
1432 OS << ' ';
1433 }
1434 switch (T->getKeyword()) {
1435 case AutoTypeKeyword::Auto: OS << "auto"; break;
1436 case AutoTypeKeyword::DecltypeAuto: OS << "decltype(auto)"; break;
1437 case AutoTypeKeyword::GNUAutoType: OS << "__auto_type"; break;
1438 }
1439 spaceBeforePlaceHolder(OS);
1440 }
1441}
1442
1443void TypePrinter::printAutoAfter(const AutoType *T, raw_ostream &OS) {
1444 // If the type has been deduced, do not print 'auto'.
1445 if (!T->getDeducedType().isNull())
1446 printAfter(t: T->getDeducedType(), OS);
1447}
1448
1449void TypePrinter::printDeducedTemplateSpecializationBefore(
1450 const DeducedTemplateSpecializationType *T, raw_ostream &OS) {
1451 if (ElaboratedTypeKeyword Keyword = T->getKeyword();
1452 T->getKeyword() != ElaboratedTypeKeyword::None)
1453 OS << KeywordHelpers::getKeywordName(Keyword) << ' ';
1454
1455 TemplateName Name = T->getTemplateName();
1456
1457 // If the type has been deduced, print the template arguments, as if this was
1458 // printing the deduced type, but including elaboration and template name
1459 // qualification.
1460 // FIXME: There should probably be a policy which controls this.
1461 // We would probably want to do this on diagnostics, but not on -ast-print.
1462 ArrayRef<TemplateArgument> Args;
1463 TemplateDecl *DeducedTD = nullptr;
1464 if (!T->getDeducedType().isNull()) {
1465 if (const auto *TST =
1466 dyn_cast<TemplateSpecializationType>(Val: T->getDeducedType())) {
1467 DeducedTD = TST->getTemplateName().getAsTemplateDecl(
1468 /*IgnoreDeduced=*/true);
1469 Args = TST->template_arguments();
1470 } else {
1471 // Should only get here for canonical types.
1472 const auto *CD = cast<ClassTemplateSpecializationDecl>(
1473 Val: cast<RecordType>(Val: T->getDeducedType())->getDecl());
1474 DeducedTD = CD->getSpecializedTemplate();
1475 Args = CD->getTemplateArgs().asArray();
1476 }
1477
1478 // FIXME: Workaround for alias template CTAD not producing guides which
1479 // include the alias template specialization type.
1480 // Purposefully disregard qualification when building this TemplateName;
1481 // any qualification we might have, might not make sense in the
1482 // context this was deduced.
1483 if (!declaresSameEntity(D1: DeducedTD, D2: Name.getAsTemplateDecl(
1484 /*IgnoreDeduced=*/true)))
1485 Name = TemplateName(DeducedTD);
1486 }
1487
1488 {
1489 IncludeStrongLifetimeRAII Strong(Policy);
1490 Name.print(OS, Policy);
1491 }
1492 if (DeducedTD) {
1493 printTemplateArgumentList(OS, Args, Policy,
1494 TPL: DeducedTD->getTemplateParameters());
1495 }
1496
1497 spaceBeforePlaceHolder(OS);
1498}
1499
1500void TypePrinter::printDeducedTemplateSpecializationAfter(
1501 const DeducedTemplateSpecializationType *T, raw_ostream &OS) {
1502 // If the type has been deduced, print the deduced type.
1503 if (!T->getDeducedType().isNull())
1504 printAfter(t: T->getDeducedType(), OS);
1505}
1506
1507void TypePrinter::printAtomicBefore(const AtomicType *T, raw_ostream &OS) {
1508 IncludeStrongLifetimeRAII Strong(Policy);
1509
1510 OS << "_Atomic(";
1511 print(t: T->getValueType(), OS, PlaceHolder: StringRef());
1512 OS << ')';
1513 spaceBeforePlaceHolder(OS);
1514}
1515
1516void TypePrinter::printAtomicAfter(const AtomicType *T, raw_ostream &OS) {}
1517
1518void TypePrinter::printPipeBefore(const PipeType *T, raw_ostream &OS) {
1519 IncludeStrongLifetimeRAII Strong(Policy);
1520
1521 if (T->isReadOnly())
1522 OS << "read_only ";
1523 else
1524 OS << "write_only ";
1525 OS << "pipe ";
1526 print(t: T->getElementType(), OS, PlaceHolder: StringRef());
1527 spaceBeforePlaceHolder(OS);
1528}
1529
1530void TypePrinter::printPipeAfter(const PipeType *T, raw_ostream &OS) {}
1531
1532void TypePrinter::printBitIntBefore(const BitIntType *T, raw_ostream &OS) {
1533 if (T->isUnsigned())
1534 OS << "unsigned ";
1535 OS << "_BitInt(" << T->getNumBits() << ")";
1536 spaceBeforePlaceHolder(OS);
1537}
1538
1539void TypePrinter::printBitIntAfter(const BitIntType *T, raw_ostream &OS) {}
1540
1541void TypePrinter::printDependentBitIntBefore(const DependentBitIntType *T,
1542 raw_ostream &OS) {
1543 if (T->isUnsigned())
1544 OS << "unsigned ";
1545 OS << "_BitInt(";
1546 T->getNumBitsExpr()->printPretty(OS, Helper: nullptr, Policy);
1547 OS << ")";
1548 spaceBeforePlaceHolder(OS);
1549}
1550
1551void TypePrinter::printDependentBitIntAfter(const DependentBitIntType *T,
1552 raw_ostream &OS) {}
1553
1554void TypePrinter::printPredefinedSugarBefore(const PredefinedSugarType *T,
1555 raw_ostream &OS) {
1556 OS << T->getIdentifier()->getName();
1557 spaceBeforePlaceHolder(OS);
1558}
1559
1560void TypePrinter::printPredefinedSugarAfter(const PredefinedSugarType *T,
1561 raw_ostream &OS) {}
1562
1563void TypePrinter::printTagType(const TagType *T, raw_ostream &OS) {
1564 TagDecl *D = T->getDecl();
1565
1566 if (Policy.IncludeTagDefinition && T->isTagOwned()) {
1567 D->print(Out&: OS, Policy, Indentation);
1568 spaceBeforePlaceHolder(OS);
1569 return;
1570 }
1571
1572 bool PrintedKindDecoration = false;
1573 if (T->isCanonicalUnqualified()) {
1574 if (!Policy.SuppressTagKeyword && !D->getTypedefNameForAnonDecl()) {
1575 PrintedKindDecoration = true;
1576 OS << D->getKindName();
1577 OS << ' ';
1578 }
1579 } else {
1580 OS << TypeWithKeyword::getKeywordName(Keyword: T->getKeyword());
1581 if (T->getKeyword() != ElaboratedTypeKeyword::None) {
1582 PrintedKindDecoration = true;
1583 OS << ' ';
1584 }
1585 }
1586
1587 if (!Policy.FullyQualifiedName && !T->isCanonicalUnqualified()) {
1588 T->getQualifier().print(OS, Policy);
1589 } else if (!Policy.SuppressScope) {
1590 // Compute the full nested-name-specifier for this type.
1591 // In C, this will always be empty except when the type
1592 // being printed is anonymous within other Record.
1593 D->printNestedNameSpecifier(OS, Policy);
1594 }
1595
1596 if (const IdentifierInfo *II = D->getIdentifier())
1597 OS << II->getName();
1598 else {
1599 clang::PrintingPolicy Copy(Policy);
1600
1601 // Suppress the redundant tag keyword if we just printed one.
1602 if (PrintedKindDecoration) {
1603 Copy.SuppressTagKeywordInAnonNames = true;
1604 Copy.SuppressTagKeyword = true;
1605 }
1606
1607 D->printName(OS, Policy: Copy);
1608 }
1609
1610 // If this is a class template specialization, print the template
1611 // arguments.
1612 if (auto *S = dyn_cast<ClassTemplateSpecializationDecl>(Val: D)) {
1613 const TemplateParameterList *TParams =
1614 S->getSpecializedTemplate()->getTemplateParameters();
1615 const ASTTemplateArgumentListInfo *TArgAsWritten =
1616 S->getTemplateArgsAsWritten();
1617 IncludeStrongLifetimeRAII Strong(Policy);
1618 if (TArgAsWritten && !Policy.PrintAsCanonical)
1619 printTemplateArgumentList(OS, Args: TArgAsWritten->arguments(), Policy,
1620 TPL: TParams);
1621 else
1622 printTemplateArgumentList(OS, Args: S->getTemplateArgs().asArray(), Policy,
1623 TPL: TParams);
1624 }
1625
1626 spaceBeforePlaceHolder(OS);
1627}
1628
1629void TypePrinter::printRecordBefore(const RecordType *T, raw_ostream &OS) {
1630 // Print the preferred name if we have one for this type.
1631 if (Policy.UsePreferredNames) {
1632 for (const auto *PNA : T->getDecl()
1633 ->getMostRecentDecl()
1634 ->specific_attrs<PreferredNameAttr>()) {
1635 if (!declaresSameEntity(D1: PNA->getTypedefType()->getAsCXXRecordDecl(),
1636 D2: T->getDecl()))
1637 continue;
1638 // Find the outermost typedef or alias template.
1639 QualType T = PNA->getTypedefType();
1640 while (true) {
1641 if (auto *TT = dyn_cast<TypedefType>(Val&: T))
1642 return printTypeSpec(D: TT->getDecl(), OS);
1643 if (auto *TST = dyn_cast<TemplateSpecializationType>(Val&: T))
1644 return printTemplateId(T: TST, OS, /*FullyQualify=*/true);
1645 T = T->getLocallyUnqualifiedSingleStepDesugaredType();
1646 }
1647 }
1648 }
1649
1650 printTagType(T, OS);
1651}
1652
1653void TypePrinter::printRecordAfter(const RecordType *T, raw_ostream &OS) {}
1654
1655void TypePrinter::printEnumBefore(const EnumType *T, raw_ostream &OS) {
1656 printTagType(T, OS);
1657}
1658
1659void TypePrinter::printEnumAfter(const EnumType *T, raw_ostream &OS) {}
1660
1661void TypePrinter::printInjectedClassNameBefore(const InjectedClassNameType *T,
1662 raw_ostream &OS) {
1663 const ASTContext &Ctx = T->getDecl()->getASTContext();
1664 IncludeStrongLifetimeRAII Strong(Policy);
1665 T->getTemplateName(Ctx).print(OS, Policy);
1666 if (Policy.PrintInjectedClassNameWithArguments) {
1667 auto *Decl = T->getDecl();
1668 // FIXME: Use T->getTemplateArgs(Ctx) when that supports as-written
1669 // arguments.
1670 if (auto *RD = dyn_cast<ClassTemplateSpecializationDecl>(Val: Decl)) {
1671 printTemplateArgumentList(OS, Args: RD->getTemplateArgsAsWritten()->arguments(),
1672 Policy,
1673 TPL: T->getTemplateDecl()->getTemplateParameters());
1674 } else {
1675 ClassTemplateDecl *TD = Decl->getDescribedClassTemplate();
1676 assert(TD);
1677 printTemplateArgumentList(
1678 OS, Args: TD->getTemplateParameters()->getInjectedTemplateArgs(Context: Ctx), Policy,
1679 TPL: T->getTemplateDecl()->getTemplateParameters());
1680 }
1681 }
1682 spaceBeforePlaceHolder(OS);
1683}
1684
1685void TypePrinter::printInjectedClassNameAfter(const InjectedClassNameType *T,
1686 raw_ostream &OS) {}
1687
1688void TypePrinter::printTemplateTypeParmBefore(const TemplateTypeParmType *T,
1689 raw_ostream &OS) {
1690 TemplateTypeParmDecl *D = T->getDecl();
1691 if (D && D->isImplicit()) {
1692 if (auto *TC = D->getTypeConstraint()) {
1693 TC->print(OS, Policy);
1694 OS << ' ';
1695 }
1696 OS << "auto";
1697 } else if (IdentifierInfo *Id = T->getIdentifier())
1698 OS << (Policy.CleanUglifiedParameters ? Id->deuglifiedName()
1699 : Id->getName());
1700 else
1701 OS << "type-parameter-" << T->getDepth() << '-' << T->getIndex();
1702
1703 spaceBeforePlaceHolder(OS);
1704}
1705
1706void TypePrinter::printTemplateTypeParmAfter(const TemplateTypeParmType *T,
1707 raw_ostream &OS) {}
1708
1709void TypePrinter::printSubstTemplateTypeParmBefore(
1710 const SubstTemplateTypeParmType *T,
1711 raw_ostream &OS) {
1712 IncludeStrongLifetimeRAII Strong(Policy);
1713 printBefore(T: T->getReplacementType(), OS);
1714}
1715
1716void TypePrinter::printSubstTemplateTypeParmAfter(
1717 const SubstTemplateTypeParmType *T,
1718 raw_ostream &OS) {
1719 IncludeStrongLifetimeRAII Strong(Policy);
1720 printAfter(t: T->getReplacementType(), OS);
1721}
1722
1723void TypePrinter::printSubstBuiltinTemplatePackBefore(
1724 const SubstBuiltinTemplatePackType *T, raw_ostream &OS) {
1725 IncludeStrongLifetimeRAII Strong(Policy);
1726 OS << "type-pack";
1727}
1728
1729void TypePrinter::printSubstBuiltinTemplatePackAfter(
1730 const SubstBuiltinTemplatePackType *T, raw_ostream &OS) {}
1731
1732void TypePrinter::printSubstTemplateTypeParmPackBefore(
1733 const SubstTemplateTypeParmPackType *T,
1734 raw_ostream &OS) {
1735 IncludeStrongLifetimeRAII Strong(Policy);
1736 if (const TemplateTypeParmDecl *D = T->getReplacedParameter()) {
1737 if (D && D->isImplicit()) {
1738 if (auto *TC = D->getTypeConstraint()) {
1739 TC->print(OS, Policy);
1740 OS << ' ';
1741 }
1742 OS << "auto";
1743 } else if (IdentifierInfo *Id = D->getIdentifier())
1744 OS << (Policy.CleanUglifiedParameters ? Id->deuglifiedName()
1745 : Id->getName());
1746 else
1747 OS << "type-parameter-" << D->getDepth() << '-' << D->getIndex();
1748
1749 spaceBeforePlaceHolder(OS);
1750 }
1751}
1752
1753void TypePrinter::printSubstTemplateTypeParmPackAfter(
1754 const SubstTemplateTypeParmPackType *T,
1755 raw_ostream &OS) {
1756 IncludeStrongLifetimeRAII Strong(Policy);
1757}
1758
1759void TypePrinter::printTemplateId(const TemplateSpecializationType *T,
1760 raw_ostream &OS, bool FullyQualify) {
1761 IncludeStrongLifetimeRAII Strong(Policy);
1762
1763 if (ElaboratedTypeKeyword K = T->getKeyword();
1764 K != ElaboratedTypeKeyword::None)
1765 OS << TypeWithKeyword::getKeywordName(Keyword: K) << ' ';
1766
1767 TemplateDecl *TD =
1768 T->getTemplateName().getAsTemplateDecl(/*IgnoreDeduced=*/true);
1769 // FIXME: Null TD never exercised in test suite.
1770 if (FullyQualify && TD) {
1771 if (!Policy.SuppressScope)
1772 TD->printNestedNameSpecifier(OS, Policy);
1773
1774 OS << TD->getName();
1775 } else {
1776 T->getTemplateName().print(OS, Policy,
1777 Qual: !Policy.SuppressScope
1778 ? TemplateName::Qualified::AsWritten
1779 : TemplateName::Qualified::None);
1780 }
1781
1782 DefaultTemplateArgsPolicyRAII TemplateArgs(Policy);
1783 const TemplateParameterList *TPL = TD ? TD->getTemplateParameters() : nullptr;
1784 printTemplateArgumentList(OS, Args: T->template_arguments(), Policy, TPL);
1785 spaceBeforePlaceHolder(OS);
1786}
1787
1788void TypePrinter::printTemplateSpecializationBefore(
1789 const TemplateSpecializationType *T,
1790 raw_ostream &OS) {
1791 printTemplateId(T, OS, FullyQualify: Policy.FullyQualifiedName);
1792}
1793
1794void TypePrinter::printTemplateSpecializationAfter(
1795 const TemplateSpecializationType *T,
1796 raw_ostream &OS) {}
1797
1798void TypePrinter::printParenBefore(const ParenType *T, raw_ostream &OS) {
1799 if (!HasEmptyPlaceHolder && !isa<FunctionType>(Val: T->getInnerType())) {
1800 printBefore(T: T->getInnerType(), OS);
1801 OS << '(';
1802 } else
1803 printBefore(T: T->getInnerType(), OS);
1804}
1805
1806void TypePrinter::printParenAfter(const ParenType *T, raw_ostream &OS) {
1807 if (!HasEmptyPlaceHolder && !isa<FunctionType>(Val: T->getInnerType())) {
1808 OS << ')';
1809 printAfter(t: T->getInnerType(), OS);
1810 } else
1811 printAfter(t: T->getInnerType(), OS);
1812}
1813
1814void TypePrinter::printDependentNameBefore(const DependentNameType *T,
1815 raw_ostream &OS) {
1816 OS << TypeWithKeyword::getKeywordName(Keyword: T->getKeyword());
1817 if (T->getKeyword() != ElaboratedTypeKeyword::None)
1818 OS << " ";
1819 T->getQualifier().print(OS, Policy);
1820 OS << T->getIdentifier()->getName();
1821 spaceBeforePlaceHolder(OS);
1822}
1823
1824void TypePrinter::printDependentNameAfter(const DependentNameType *T,
1825 raw_ostream &OS) {}
1826
1827void TypePrinter::printPackExpansionBefore(const PackExpansionType *T,
1828 raw_ostream &OS) {
1829 printBefore(T: T->getPattern(), OS);
1830}
1831
1832void TypePrinter::printPackExpansionAfter(const PackExpansionType *T,
1833 raw_ostream &OS) {
1834 printAfter(t: T->getPattern(), OS);
1835 OS << "...";
1836}
1837
1838static void printCountAttributedImpl(const CountAttributedType *T,
1839 raw_ostream &OS,
1840 const PrintingPolicy &Policy) {
1841 OS << ' ';
1842 if (T->isCountInBytes() && T->isOrNull())
1843 OS << "__sized_by_or_null(";
1844 else if (T->isCountInBytes())
1845 OS << "__sized_by(";
1846 else if (T->isOrNull())
1847 OS << "__counted_by_or_null(";
1848 else
1849 OS << "__counted_by(";
1850 if (T->getCountExpr())
1851 T->getCountExpr()->printPretty(OS, Helper: nullptr, Policy);
1852 OS << ')';
1853}
1854
1855void TypePrinter::printCountAttributedBefore(const CountAttributedType *T,
1856 raw_ostream &OS) {
1857 printBefore(T: T->desugar(), OS);
1858 if (!T->isArrayType())
1859 printCountAttributedImpl(T, OS, Policy);
1860}
1861
1862void TypePrinter::printCountAttributedAfter(const CountAttributedType *T,
1863 raw_ostream &OS) {
1864 printAfter(t: T->desugar(), OS);
1865 if (T->isArrayType())
1866 printCountAttributedImpl(T, OS, Policy);
1867}
1868
1869void TypePrinter::printLateParsedAttrBefore(const LateParsedAttrType *T,
1870 raw_ostream &OS) {
1871 // LateParsedAttrType is a transient placeholder that should not appear
1872 // in user-facing output. Just print the wrapped type.
1873 printBefore(T: T->getWrappedType(), OS);
1874}
1875
1876void TypePrinter::printLateParsedAttrAfter(const LateParsedAttrType *T,
1877 raw_ostream &OS) {
1878 // LateParsedAttrType is a transient placeholder that should not appear
1879 // in user-facing output. Just print the wrapped type.
1880 printAfter(t: T->getWrappedType(), OS);
1881}
1882
1883void TypePrinter::printAttributedBefore(const AttributedType *T,
1884 raw_ostream &OS) {
1885 // FIXME: Generate this with TableGen.
1886
1887 // Prefer the macro forms of the GC and ownership qualifiers.
1888 if (T->getAttrKind() == attr::ObjCGC ||
1889 T->getAttrKind() == attr::ObjCOwnership)
1890 return printBefore(T: T->getEquivalentType(), OS);
1891
1892 if (T->getAttrKind() == attr::ObjCKindOf)
1893 OS << "__kindof ";
1894
1895 if (T->getAttrKind() == attr::PreserveNone) {
1896 OS << "__attribute__((preserve_none)) ";
1897 spaceBeforePlaceHolder(OS);
1898 } else if (T->getAttrKind() == attr::PreserveMost) {
1899 OS << "__attribute__((preserve_most)) ";
1900 spaceBeforePlaceHolder(OS);
1901 } else if (T->getAttrKind() == attr::PreserveAll) {
1902 OS << "__attribute__((preserve_all)) ";
1903 spaceBeforePlaceHolder(OS);
1904 }
1905
1906 if (T->getAttrKind() == attr::AddressSpace)
1907 printBefore(T: T->getEquivalentType(), OS);
1908 else
1909 printBefore(T: T->getModifiedType(), OS);
1910
1911 if (T->isMSTypeSpec()) {
1912 switch (T->getAttrKind()) {
1913 default: return;
1914 case attr::Ptr32: OS << " __ptr32"; break;
1915 case attr::Ptr64: OS << " __ptr64"; break;
1916 case attr::SPtr: OS << " __sptr"; break;
1917 case attr::UPtr: OS << " __uptr"; break;
1918 }
1919 spaceBeforePlaceHolder(OS);
1920 }
1921
1922 if (T->isWebAssemblyFuncrefSpec())
1923 OS << "__funcref";
1924
1925 // Print nullability type specifiers.
1926 if (T->getImmediateNullability()) {
1927 if (T->getAttrKind() == attr::TypeNonNull)
1928 OS << " _Nonnull";
1929 else if (T->getAttrKind() == attr::TypeNullable)
1930 OS << " _Nullable";
1931 else if (T->getAttrKind() == attr::TypeNullUnspecified)
1932 OS << " _Null_unspecified";
1933 else if (T->getAttrKind() == attr::TypeNullableResult)
1934 OS << " _Nullable_result";
1935 else
1936 llvm_unreachable("unhandled nullability");
1937 spaceBeforePlaceHolder(OS);
1938 }
1939}
1940
1941void TypePrinter::printAttributedAfter(const AttributedType *T,
1942 raw_ostream &OS) {
1943 // FIXME: Generate this with TableGen.
1944
1945 // Prefer the macro forms of the GC and ownership qualifiers.
1946 if (T->getAttrKind() == attr::ObjCGC ||
1947 T->getAttrKind() == attr::ObjCOwnership)
1948 return printAfter(t: T->getEquivalentType(), OS);
1949
1950 // If this is a calling convention attribute, don't print the implicit CC from
1951 // the modified type.
1952 SaveAndRestore MaybeSuppressCC(InsideCCAttribute, T->isCallingConv());
1953
1954 printAfter(t: T->getModifiedType(), OS);
1955
1956 // Some attributes are printed as qualifiers before the type, so we have
1957 // nothing left to do.
1958 if (T->getAttrKind() == attr::ObjCKindOf || T->isMSTypeSpec() ||
1959 T->getImmediateNullability() || T->isWebAssemblyFuncrefSpec())
1960 return;
1961
1962 // Don't print the inert __unsafe_unretained attribute at all.
1963 if (T->getAttrKind() == attr::ObjCInertUnsafeUnretained)
1964 return;
1965
1966 // Don't print ns_returns_retained unless it had an effect.
1967 if (T->getAttrKind() == attr::NSReturnsRetained &&
1968 !T->getEquivalentType()->castAs<FunctionType>()
1969 ->getExtInfo().getProducesResult())
1970 return;
1971
1972 if (T->getAttrKind() == attr::LifetimeBound) {
1973 OS << " [[clang::lifetimebound]]";
1974 return;
1975 }
1976 if (T->getAttrKind() == attr::LifetimeCaptureBy) {
1977 OS << " [[clang::lifetime_capture_by(";
1978 if (auto *attr = dyn_cast_or_null<LifetimeCaptureByAttr>(Val: T->getAttr()))
1979 llvm::interleaveComma(c: attr->getArgIdents(), os&: OS,
1980 each_fn: [&](auto it) { OS << it->getName(); });
1981 OS << ")]]";
1982 return;
1983 }
1984
1985 // The printing of the address_space attribute is handled by the qualifier
1986 // since it is still stored in the qualifier. Return early to prevent printing
1987 // this twice.
1988 if (T->getAttrKind() == attr::AddressSpace)
1989 return;
1990
1991 if (T->getAttrKind() == attr::AnnotateType) {
1992 // FIXME: Print the attribute arguments once we have a way to retrieve these
1993 // here. For the meantime, we just print `[[clang::annotate_type(...)]]`
1994 // without the arguments so that we know at least that we had _some_
1995 // annotation on the type.
1996 OS << " [[clang::annotate_type(...)]]";
1997 return;
1998 }
1999
2000 if (T->getAttrKind() == attr::ArmStreaming) {
2001 OS << "__arm_streaming";
2002 return;
2003 }
2004 if (T->getAttrKind() == attr::ArmStreamingCompatible) {
2005 OS << "__arm_streaming_compatible";
2006 return;
2007 }
2008
2009 if (T->getAttrKind() == attr::SwiftAttr) {
2010 if (auto *swiftAttr = dyn_cast_or_null<SwiftAttrAttr>(Val: T->getAttr())) {
2011 OS << " __attribute__((swift_attr(\"" << swiftAttr->getAttribute()
2012 << "\")))";
2013 }
2014 return;
2015 }
2016
2017 if (T->getAttrKind() == attr::PreserveAll ||
2018 T->getAttrKind() == attr::PreserveMost ||
2019 T->getAttrKind() == attr::PreserveNone) {
2020 // This has to be printed before the type.
2021 return;
2022 }
2023
2024 OS << " __attribute__((";
2025 switch (T->getAttrKind()) {
2026#define TYPE_ATTR(NAME)
2027#define DECL_OR_TYPE_ATTR(NAME)
2028#define ATTR(NAME) case attr::NAME:
2029#include "clang/Basic/AttrList.inc"
2030 llvm_unreachable("non-type attribute attached to type");
2031
2032 case attr::BTFTypeTag:
2033 llvm_unreachable("BTFTypeTag attribute handled separately");
2034
2035 case attr::HLSLResourceClass:
2036 case attr::HLSLIsROV:
2037 case attr::HLSLRawBuffer:
2038 case attr::HLSLContainedType:
2039 case attr::HLSLIsCounter:
2040 case attr::HLSLResourceDimension:
2041 case attr::HLSLIsArray:
2042 case attr::HLSLIsMultiSampled:
2043 llvm_unreachable("HLSL resource type attributes handled separately");
2044
2045 case attr::OpenCLPrivateAddressSpace:
2046 case attr::OpenCLGlobalAddressSpace:
2047 case attr::OpenCLGlobalDeviceAddressSpace:
2048 case attr::OpenCLGlobalHostAddressSpace:
2049 case attr::OpenCLLocalAddressSpace:
2050 case attr::OpenCLConstantAddressSpace:
2051 case attr::OpenCLGenericAddressSpace:
2052 case attr::HLSLGroupSharedAddressSpace:
2053 case attr::SYCLPrivateAddressSpace:
2054 case attr::SYCLGlobalAddressSpace:
2055 case attr::SYCLLocalAddressSpace:
2056 case attr::SYCLConstantAddressSpace:
2057 case attr::SYCLGenericAddressSpace:
2058 // FIXME: Update printAttributedBefore to print these once we generate
2059 // AttributedType nodes for them.
2060 llvm_unreachable("Address space attributes handled separately");
2061 case attr::CountedBy:
2062 case attr::CountedByOrNull:
2063 case attr::SizedBy:
2064 case attr::SizedByOrNull:
2065 case attr::LifetimeBound:
2066 case attr::LifetimeCaptureBy:
2067 case attr::TypeNonNull:
2068 case attr::TypeNullable:
2069 case attr::TypeNullableResult:
2070 case attr::TypeNullUnspecified:
2071 case attr::ObjCGC:
2072 case attr::ObjCInertUnsafeUnretained:
2073 case attr::ObjCKindOf:
2074 case attr::ObjCOwnership:
2075 case attr::Ptr32:
2076 case attr::Ptr64:
2077 case attr::SPtr:
2078 case attr::UPtr:
2079 case attr::PointerAuth:
2080 case attr::AddressSpace:
2081 case attr::CmseNSCall:
2082 case attr::AnnotateType:
2083 case attr::WebAssemblyFuncref:
2084 case attr::ArmAgnostic:
2085 case attr::ArmStreaming:
2086 case attr::ArmStreamingCompatible:
2087 case attr::ArmIn:
2088 case attr::ArmOut:
2089 case attr::ArmInOut:
2090 case attr::ArmPreserves:
2091 case attr::NonBlocking:
2092 case attr::NonAllocating:
2093 case attr::Blocking:
2094 case attr::Allocating:
2095 case attr::SwiftAttr:
2096 case attr::PreserveAll:
2097 case attr::PreserveMost:
2098 case attr::PreserveNone:
2099 case attr::OverflowBehavior:
2100 llvm_unreachable("This attribute should have been handled already");
2101
2102 case attr::NSReturnsRetained:
2103 OS << "ns_returns_retained";
2104 break;
2105
2106 case attr::HLSLRowMajor:
2107 OS << "row_major";
2108 break;
2109 case attr::HLSLColumnMajor:
2110 OS << "column_major";
2111 break;
2112
2113 // FIXME: When Sema learns to form this AttributedType, avoid printing the
2114 // attribute again in printFunctionProtoAfter.
2115 case attr::AnyX86NoCfCheck: OS << "nocf_check"; break;
2116 case attr::CDecl: OS << "cdecl"; break;
2117 case attr::FastCall: OS << "fastcall"; break;
2118 case attr::StdCall: OS << "stdcall"; break;
2119 case attr::ThisCall: OS << "thiscall"; break;
2120 case attr::SwiftCall: OS << "swiftcall"; break;
2121 case attr::SwiftAsyncCall: OS << "swiftasynccall"; break;
2122 case attr::VectorCall: OS << "vectorcall"; break;
2123 case attr::Pascal: OS << "pascal"; break;
2124 case attr::MSABI: OS << "ms_abi"; break;
2125 case attr::SysVABI: OS << "sysv_abi"; break;
2126 case attr::RegCall: OS << "regcall"; break;
2127 case attr::Pcs: {
2128 OS << "pcs(";
2129 QualType t = T->getEquivalentType();
2130 while (!t->isFunctionType())
2131 t = t->getPointeeType();
2132 OS << (t->castAs<FunctionType>()->getCallConv() == CC_AAPCS ?
2133 "\"aapcs\"" : "\"aapcs-vfp\"");
2134 OS << ')';
2135 break;
2136 }
2137 case attr::AArch64VectorPcs: OS << "aarch64_vector_pcs"; break;
2138 case attr::AArch64SVEPcs: OS << "aarch64_sve_pcs"; break;
2139 case attr::IntelOclBicc:
2140 OS << "inteloclbicc";
2141 break;
2142 case attr::M68kRTD:
2143 OS << "m68k_rtd";
2144 break;
2145 case attr::RISCVVectorCC:
2146 OS << "riscv_vector_cc";
2147 break;
2148 case attr::RISCVVLSCC:
2149 OS << "riscv_vls_cc";
2150 break;
2151 case attr::NoDeref:
2152 OS << "noderef";
2153 break;
2154 case attr::CFIUncheckedCallee:
2155 OS << "cfi_unchecked_callee";
2156 break;
2157 case attr::AcquireHandle:
2158 OS << "acquire_handle";
2159 break;
2160 case attr::ArmMveStrictPolymorphism:
2161 OS << "__clang_arm_mve_strict_polymorphism";
2162 break;
2163 case attr::ExtVectorType:
2164 OS << "ext_vector_type";
2165 break;
2166 case attr::CFISalt:
2167 OS << "cfi_salt(\"" << cast<CFISaltAttr>(Val: T->getAttr())->getSalt() << "\")";
2168 break;
2169 case attr::NoFieldProtection:
2170 OS << "no_field_protection";
2171 break;
2172 case attr::PointerFieldProtection:
2173 OS << "pointer_field_protection";
2174 break;
2175 }
2176 OS << "))";
2177}
2178
2179void TypePrinter::printBTFTagAttributedBefore(const BTFTagAttributedType *T,
2180 raw_ostream &OS) {
2181 printBefore(T: T->getWrappedType(), OS);
2182 OS << " __attribute__((btf_type_tag(\"" << T->getAttr()->getBTFTypeTag() << "\")))";
2183}
2184
2185void TypePrinter::printBTFTagAttributedAfter(const BTFTagAttributedType *T,
2186 raw_ostream &OS) {
2187 printAfter(t: T->getWrappedType(), OS);
2188}
2189
2190void TypePrinter::printOverflowBehaviorBefore(const OverflowBehaviorType *T,
2191 raw_ostream &OS) {
2192 switch (T->getBehaviorKind()) {
2193 case clang::OverflowBehaviorType::OverflowBehaviorKind::Wrap:
2194 OS << "__ob_wrap ";
2195 break;
2196 case clang::OverflowBehaviorType::OverflowBehaviorKind::Trap:
2197 OS << "__ob_trap ";
2198 break;
2199 }
2200 printBefore(T: T->getUnderlyingType(), OS);
2201}
2202
2203void TypePrinter::printOverflowBehaviorAfter(const OverflowBehaviorType *T,
2204 raw_ostream &OS) {
2205 printAfter(t: T->getUnderlyingType(), OS);
2206}
2207
2208void TypePrinter::printHLSLAttributedResourceBefore(
2209 const HLSLAttributedResourceType *T, raw_ostream &OS) {
2210 printBefore(T: T->getWrappedType(), OS);
2211}
2212
2213void TypePrinter::printHLSLAttributedResourceAfter(
2214 const HLSLAttributedResourceType *T, raw_ostream &OS) {
2215 printAfter(t: T->getWrappedType(), OS);
2216 const HLSLAttributedResourceType::Attributes &Attrs = T->getAttrs();
2217 OS << " [[hlsl::resource_class(\""
2218 << HLSLResourceClassAttr::ConvertResourceClassToStr(Val: Attrs.ResourceClass)
2219 << "\")]]";
2220 if (Attrs.IsROV)
2221 OS << " [[hlsl::is_rov]]";
2222 if (Attrs.RawBuffer)
2223 OS << " [[hlsl::raw_buffer]]";
2224 if (Attrs.IsCounter)
2225 OS << " [[hlsl::is_counter]]";
2226 if (Attrs.IsArray)
2227 OS << " [[hlsl::is_array]]";
2228 if (Attrs.isMultiSampled())
2229 OS << " [[hlsl::is_ms]]";
2230
2231 QualType ContainedTy = T->getContainedType();
2232 if (!ContainedTy.isNull()) {
2233 OS << " [[hlsl::contained_type(";
2234 printBefore(T: ContainedTy, OS);
2235 printAfter(t: ContainedTy, OS);
2236 OS << ")]]";
2237 }
2238
2239 if (Attrs.ResourceDimension != llvm::dxil::ResourceDimension::Unknown)
2240 OS << " [[hlsl::dimension(\""
2241 << HLSLResourceDimensionAttr::ConvertResourceDimensionToStr(
2242 Val: Attrs.ResourceDimension)
2243 << "\")]]";
2244}
2245
2246void TypePrinter::printHLSLInlineSpirvBefore(const HLSLInlineSpirvType *T,
2247 raw_ostream &OS) {
2248 OS << "__hlsl_spirv_type<" << T->getOpcode();
2249
2250 OS << ", " << T->getSize();
2251 OS << ", " << T->getAlignment();
2252
2253 for (auto &Operand : T->getOperands()) {
2254 using SpirvOperandKind = SpirvOperand::SpirvOperandKind;
2255
2256 OS << ", ";
2257 switch (Operand.getKind()) {
2258 case SpirvOperandKind::ConstantId: {
2259 QualType ConstantType = Operand.getResultType();
2260 OS << "vk::integral_constant<";
2261 printBefore(T: ConstantType, OS);
2262 printAfter(t: ConstantType, OS);
2263 OS << ", ";
2264 OS << Operand.getValue();
2265 OS << ">";
2266 break;
2267 }
2268 case SpirvOperandKind::Literal:
2269 OS << "vk::Literal<vk::integral_constant<uint, ";
2270 OS << Operand.getValue();
2271 OS << ">>";
2272 break;
2273 case SpirvOperandKind::TypeId: {
2274 QualType Type = Operand.getResultType();
2275 printBefore(T: Type, OS);
2276 printAfter(t: Type, OS);
2277 break;
2278 }
2279 default:
2280 llvm_unreachable("Invalid SpirvOperand kind!");
2281 break;
2282 }
2283 }
2284
2285 OS << ">";
2286}
2287
2288void TypePrinter::printHLSLInlineSpirvAfter(const HLSLInlineSpirvType *T,
2289 raw_ostream &OS) {
2290 // nothing to do
2291}
2292
2293void TypePrinter::printObjCInterfaceBefore(const ObjCInterfaceType *T,
2294 raw_ostream &OS) {
2295 OS << T->getDecl()->getName();
2296 spaceBeforePlaceHolder(OS);
2297}
2298
2299void TypePrinter::printObjCInterfaceAfter(const ObjCInterfaceType *T,
2300 raw_ostream &OS) {}
2301
2302void TypePrinter::printObjCTypeParamBefore(const ObjCTypeParamType *T,
2303 raw_ostream &OS) {
2304 OS << T->getDecl()->getName();
2305 if (!T->qual_empty()) {
2306 bool isFirst = true;
2307 OS << '<';
2308 for (const auto *I : T->quals()) {
2309 if (isFirst)
2310 isFirst = false;
2311 else
2312 OS << ',';
2313 OS << I->getName();
2314 }
2315 OS << '>';
2316 }
2317
2318 spaceBeforePlaceHolder(OS);
2319}
2320
2321void TypePrinter::printObjCTypeParamAfter(const ObjCTypeParamType *T,
2322 raw_ostream &OS) {}
2323
2324void TypePrinter::printObjCObjectBefore(const ObjCObjectType *T,
2325 raw_ostream &OS) {
2326 if (T->qual_empty() && T->isUnspecializedAsWritten() &&
2327 !T->isKindOfTypeAsWritten())
2328 return printBefore(T: T->getBaseType(), OS);
2329
2330 if (T->isKindOfTypeAsWritten())
2331 OS << "__kindof ";
2332
2333 print(t: T->getBaseType(), OS, PlaceHolder: StringRef());
2334
2335 if (T->isSpecializedAsWritten()) {
2336 bool isFirst = true;
2337 OS << '<';
2338 for (auto typeArg : T->getTypeArgsAsWritten()) {
2339 if (isFirst)
2340 isFirst = false;
2341 else
2342 OS << ",";
2343
2344 print(t: typeArg, OS, PlaceHolder: StringRef());
2345 }
2346 OS << '>';
2347 }
2348
2349 if (!T->qual_empty()) {
2350 bool isFirst = true;
2351 OS << '<';
2352 for (const auto *I : T->quals()) {
2353 if (isFirst)
2354 isFirst = false;
2355 else
2356 OS << ',';
2357 OS << I->getName();
2358 }
2359 OS << '>';
2360 }
2361
2362 spaceBeforePlaceHolder(OS);
2363}
2364
2365void TypePrinter::printObjCObjectAfter(const ObjCObjectType *T,
2366 raw_ostream &OS) {
2367 if (T->qual_empty() && T->isUnspecializedAsWritten() &&
2368 !T->isKindOfTypeAsWritten())
2369 return printAfter(t: T->getBaseType(), OS);
2370}
2371
2372void TypePrinter::printObjCObjectPointerBefore(const ObjCObjectPointerType *T,
2373 raw_ostream &OS) {
2374 printBefore(T: T->getPointeeType(), OS);
2375
2376 // If we need to print the pointer, print it now.
2377 if (!T->isObjCIdType() && !T->isObjCQualifiedIdType() &&
2378 !T->isObjCClassType() && !T->isObjCQualifiedClassType()) {
2379 if (HasEmptyPlaceHolder)
2380 OS << ' ';
2381 OS << '*';
2382 }
2383}
2384
2385void TypePrinter::printObjCObjectPointerAfter(const ObjCObjectPointerType *T,
2386 raw_ostream &OS) {}
2387
2388static
2389const TemplateArgument &getArgument(const TemplateArgument &A) { return A; }
2390
2391static const TemplateArgument &getArgument(const TemplateArgumentLoc &A) {
2392 return A.getArgument();
2393}
2394
2395static void printArgument(const TemplateArgument &A, const PrintingPolicy &PP,
2396 llvm::raw_ostream &OS, bool IncludeType) {
2397 A.print(Policy: PP, Out&: OS, IncludeType);
2398}
2399
2400static void printArgument(const TemplateArgumentLoc &A,
2401 const PrintingPolicy &PP, llvm::raw_ostream &OS,
2402 bool IncludeType) {
2403 const TemplateArgument::ArgKind &Kind = A.getArgument().getKind();
2404 if (Kind == TemplateArgument::ArgKind::Type)
2405 return A.getTypeSourceInfo()->getType().print(OS, Policy: PP);
2406 return A.getArgument().print(Policy: PP, Out&: OS, IncludeType);
2407}
2408
2409static bool isSubstitutedTemplateArgument(ASTContext &Ctx, TemplateArgument Arg,
2410 TemplateArgument Pattern,
2411 ArrayRef<TemplateArgument> Args,
2412 unsigned Depth);
2413
2414static bool isSubstitutedType(ASTContext &Ctx, QualType T, QualType Pattern,
2415 ArrayRef<TemplateArgument> Args, unsigned Depth) {
2416 if (Ctx.hasSameType(T1: T, T2: Pattern))
2417 return true;
2418
2419 // A type parameter matches its argument.
2420 if (auto *TTPT = Pattern->getAsCanonical<TemplateTypeParmType>()) {
2421 if (TTPT->getDepth() == Depth && TTPT->getIndex() < Args.size() &&
2422 Args[TTPT->getIndex()].getKind() == TemplateArgument::Type) {
2423 QualType SubstArg = Ctx.getQualifiedType(
2424 T: Args[TTPT->getIndex()].getAsType(), Qs: Pattern.getQualifiers());
2425 return Ctx.hasSameType(T1: SubstArg, T2: T);
2426 }
2427 return false;
2428 }
2429
2430 // FIXME: Recurse into array types.
2431
2432 // All other cases will need the types to be identically qualified.
2433 Qualifiers TQual, PatQual;
2434 T = Ctx.getUnqualifiedArrayType(T, Quals&: TQual);
2435 Pattern = Ctx.getUnqualifiedArrayType(T: Pattern, Quals&: PatQual);
2436 if (TQual != PatQual)
2437 return false;
2438
2439 // Recurse into pointer-like types.
2440 {
2441 QualType TPointee = T->getPointeeType();
2442 QualType PPointee = Pattern->getPointeeType();
2443 if (!TPointee.isNull() && !PPointee.isNull())
2444 return T->getTypeClass() == Pattern->getTypeClass() &&
2445 isSubstitutedType(Ctx, T: TPointee, Pattern: PPointee, Args, Depth);
2446 }
2447
2448 // Recurse into template specialization types.
2449 if (auto *PTST =
2450 Pattern.getCanonicalType()->getAs<TemplateSpecializationType>()) {
2451 TemplateName Template;
2452 ArrayRef<TemplateArgument> TemplateArgs;
2453 if (auto *TTST = T->getAs<TemplateSpecializationType>()) {
2454 Template = TTST->getTemplateName();
2455 TemplateArgs = TTST->template_arguments();
2456 } else if (auto *CTSD = dyn_cast_or_null<ClassTemplateSpecializationDecl>(
2457 Val: T->getAsCXXRecordDecl())) {
2458 Template = TemplateName(CTSD->getSpecializedTemplate());
2459 TemplateArgs = CTSD->getTemplateArgs().asArray();
2460 } else {
2461 return false;
2462 }
2463
2464 if (!isSubstitutedTemplateArgument(Ctx, Arg: Template, Pattern: PTST->getTemplateName(),
2465 Args, Depth))
2466 return false;
2467 if (TemplateArgs.size() != PTST->template_arguments().size())
2468 return false;
2469 for (unsigned I = 0, N = TemplateArgs.size(); I != N; ++I)
2470 if (!isSubstitutedTemplateArgument(
2471 Ctx, Arg: TemplateArgs[I], Pattern: PTST->template_arguments()[I], Args, Depth))
2472 return false;
2473 return true;
2474 }
2475
2476 // FIXME: Handle more cases.
2477 return false;
2478}
2479
2480/// Evaluates the expression template argument 'Pattern' and returns true
2481/// if 'Arg' evaluates to the same result.
2482static bool templateArgumentExpressionsEqual(ASTContext const &Ctx,
2483 TemplateArgument const &Pattern,
2484 TemplateArgument const &Arg) {
2485 if (Pattern.getKind() != TemplateArgument::Expression)
2486 return false;
2487
2488 // Can't evaluate value-dependent expressions so bail early
2489 Expr const *pattern_expr = Pattern.getAsExpr();
2490 if (pattern_expr->isValueDependent() ||
2491 !pattern_expr->isIntegerConstantExpr(Ctx))
2492 return false;
2493
2494 if (Arg.getKind() == TemplateArgument::Integral)
2495 return llvm::APSInt::isSameValue(I1: pattern_expr->EvaluateKnownConstInt(Ctx),
2496 I2: Arg.getAsIntegral());
2497
2498 if (Arg.getKind() == TemplateArgument::Expression) {
2499 Expr const *args_expr = Arg.getAsExpr();
2500 if (args_expr->isValueDependent() || !args_expr->isIntegerConstantExpr(Ctx))
2501 return false;
2502
2503 return llvm::APSInt::isSameValue(I1: args_expr->EvaluateKnownConstInt(Ctx),
2504 I2: pattern_expr->EvaluateKnownConstInt(Ctx));
2505 }
2506
2507 return false;
2508}
2509
2510static bool isSubstitutedTemplateArgument(ASTContext &Ctx, TemplateArgument Arg,
2511 TemplateArgument Pattern,
2512 ArrayRef<TemplateArgument> Args,
2513 unsigned Depth) {
2514 Arg = Ctx.getCanonicalTemplateArgument(Arg);
2515 Pattern = Ctx.getCanonicalTemplateArgument(Arg: Pattern);
2516 if (Arg.structurallyEquals(Other: Pattern))
2517 return true;
2518
2519 if (Pattern.getKind() == TemplateArgument::Expression) {
2520 if (auto *DRE =
2521 dyn_cast<DeclRefExpr>(Val: Pattern.getAsExpr()->IgnoreParenImpCasts())) {
2522 if (auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(Val: DRE->getDecl()))
2523 return NTTP->getDepth() == Depth && Args.size() > NTTP->getIndex() &&
2524 Args[NTTP->getIndex()].structurallyEquals(Other: Arg);
2525 }
2526 }
2527
2528 if (templateArgumentExpressionsEqual(Ctx, Pattern, Arg))
2529 return true;
2530
2531 if (Arg.getKind() != Pattern.getKind())
2532 return false;
2533
2534 if (Arg.getKind() == TemplateArgument::Type)
2535 return isSubstitutedType(Ctx, T: Arg.getAsType(), Pattern: Pattern.getAsType(), Args,
2536 Depth);
2537
2538 if (Arg.getKind() == TemplateArgument::Template) {
2539 TemplateDecl *PatTD = Pattern.getAsTemplate().getAsTemplateDecl();
2540 if (auto *TTPD = dyn_cast_or_null<TemplateTemplateParmDecl>(Val: PatTD))
2541 return TTPD->getDepth() == Depth && Args.size() > TTPD->getIndex() &&
2542 Ctx.getCanonicalTemplateArgument(Arg: Args[TTPD->getIndex()])
2543 .structurallyEquals(Other: Arg);
2544 }
2545
2546 // FIXME: Handle more cases.
2547 return false;
2548}
2549
2550bool clang::isSubstitutedDefaultArgument(ASTContext &Ctx, TemplateArgument Arg,
2551 const NamedDecl *Param,
2552 ArrayRef<TemplateArgument> Args,
2553 unsigned Depth) {
2554 // An empty pack is equivalent to not providing a pack argument.
2555 if (Arg.getKind() == TemplateArgument::Pack && Arg.pack_size() == 0)
2556 return true;
2557
2558 if (auto *TTPD = dyn_cast<TemplateTypeParmDecl>(Val: Param)) {
2559 return TTPD->hasDefaultArgument() &&
2560 isSubstitutedTemplateArgument(
2561 Ctx, Arg, Pattern: TTPD->getDefaultArgument().getArgument(), Args, Depth);
2562 } else if (auto *TTPD = dyn_cast<TemplateTemplateParmDecl>(Val: Param)) {
2563 return TTPD->hasDefaultArgument() &&
2564 isSubstitutedTemplateArgument(
2565 Ctx, Arg, Pattern: TTPD->getDefaultArgument().getArgument(), Args, Depth);
2566 } else if (auto *NTTPD = dyn_cast<NonTypeTemplateParmDecl>(Val: Param)) {
2567 return NTTPD->hasDefaultArgument() &&
2568 isSubstitutedTemplateArgument(
2569 Ctx, Arg, Pattern: NTTPD->getDefaultArgument().getArgument(), Args,
2570 Depth);
2571 }
2572 return false;
2573}
2574
2575template <typename TA>
2576static void
2577printTo(raw_ostream &OS, ArrayRef<TA> Args, const PrintingPolicy &Policy,
2578 const TemplateParameterList *TPL, bool IsPack, unsigned ParmIndex) {
2579 // Drop trailing template arguments that match default arguments.
2580 if (TPL && Policy.SuppressDefaultTemplateArgs && !Policy.PrintAsCanonical &&
2581 !Args.empty() && !IsPack && Args.size() <= TPL->size()) {
2582 llvm::SmallVector<TemplateArgument, 8> OrigArgs;
2583 for (const TA &A : Args)
2584 OrigArgs.push_back(Elt: getArgument(A));
2585 while (!Args.empty() && getArgument(Args.back()).getIsDefaulted())
2586 Args = Args.drop_back();
2587 }
2588
2589 const char *Comma = Policy.MSVCFormatting ? "," : ", ";
2590 if (!IsPack)
2591 OS << '<';
2592
2593 bool NeedSpace = false;
2594 bool FirstArg = true;
2595 for (const auto &Arg : Args) {
2596 // Print the argument into a string.
2597 SmallString<128> Buf;
2598 llvm::raw_svector_ostream ArgOS(Buf);
2599 const TemplateArgument &Argument = getArgument(Arg);
2600 if (Argument.getKind() == TemplateArgument::Pack) {
2601 if (Argument.pack_size() && !FirstArg)
2602 OS << Comma;
2603 printTo(OS&: ArgOS, Args: Argument.getPackAsArray(), Policy, TPL,
2604 /*IsPack*/ true, ParmIndex);
2605 } else {
2606 if (!FirstArg)
2607 OS << Comma;
2608 // Tries to print the argument with location info if exists.
2609 printArgument(Arg, Policy, ArgOS,
2610 TemplateParameterList::shouldIncludeTypeForArgument(
2611 Policy, TPL, Idx: ParmIndex));
2612 }
2613 StringRef ArgString = ArgOS.str();
2614
2615 // If this is the first argument and its string representation
2616 // begins with the global scope specifier ('::foo'), add a space
2617 // to avoid printing the diagraph '<:'.
2618 if (FirstArg && ArgString.starts_with(Prefix: ":"))
2619 OS << ' ';
2620
2621 OS << ArgString;
2622
2623 // If the last character of our string is '>', add another space to
2624 // keep the two '>''s separate tokens.
2625 if (!ArgString.empty()) {
2626 NeedSpace = Policy.SplitTemplateClosers && ArgString.back() == '>';
2627 FirstArg = false;
2628 }
2629
2630 // Use same template parameter for all elements of Pack
2631 if (!IsPack)
2632 ParmIndex++;
2633 }
2634
2635 if (!IsPack) {
2636 if (NeedSpace)
2637 OS << ' ';
2638 OS << '>';
2639 }
2640}
2641
2642void clang::printTemplateArgumentList(raw_ostream &OS,
2643 const TemplateArgumentListInfo &Args,
2644 const PrintingPolicy &Policy,
2645 const TemplateParameterList *TPL) {
2646 printTemplateArgumentList(OS, Args: Args.arguments(), Policy, TPL);
2647}
2648
2649void clang::printTemplateArgumentList(raw_ostream &OS,
2650 ArrayRef<TemplateArgument> Args,
2651 const PrintingPolicy &Policy,
2652 const TemplateParameterList *TPL) {
2653 PrintingPolicy InnerPolicy = Policy;
2654 InnerPolicy.SuppressScope = false;
2655 printTo(OS, Args, Policy: InnerPolicy, TPL, /*isPack*/ IsPack: false, /*parmIndex*/ ParmIndex: 0);
2656}
2657
2658void clang::printTemplateArgumentList(raw_ostream &OS,
2659 ArrayRef<TemplateArgumentLoc> Args,
2660 const PrintingPolicy &Policy,
2661 const TemplateParameterList *TPL) {
2662 PrintingPolicy InnerPolicy = Policy;
2663 InnerPolicy.SuppressScope = false;
2664 printTo(OS, Args, Policy: InnerPolicy, TPL, /*isPack*/ IsPack: false, /*parmIndex*/ ParmIndex: 0);
2665}
2666
2667std::string PointerAuthQualifier::getAsString() const {
2668 LangOptions LO;
2669 return getAsString(Policy: PrintingPolicy(LO));
2670}
2671
2672std::string PointerAuthQualifier::getAsString(const PrintingPolicy &P) const {
2673 SmallString<64> Buf;
2674 llvm::raw_svector_ostream StrOS(Buf);
2675 print(OS&: StrOS, Policy: P);
2676 return StrOS.str().str();
2677}
2678
2679bool PointerAuthQualifier::isEmptyWhenPrinted(const PrintingPolicy &P) const {
2680 return !isPresent();
2681}
2682
2683void PointerAuthQualifier::print(raw_ostream &OS,
2684 const PrintingPolicy &P) const {
2685 if (!isPresent())
2686 return;
2687
2688 OS << "__ptrauth(";
2689 OS << getKey();
2690 OS << "," << unsigned(isAddressDiscriminated()) << ","
2691 << getExtraDiscriminator() << ")";
2692}
2693
2694std::string Qualifiers::getAsString() const {
2695 LangOptions LO;
2696 return getAsString(Policy: PrintingPolicy(LO));
2697}
2698
2699// Appends qualifiers to the given string, separated by spaces. Will
2700// prefix a space if the string is non-empty. Will not append a final
2701// space.
2702std::string Qualifiers::getAsString(const PrintingPolicy &Policy) const {
2703 SmallString<64> Buf;
2704 llvm::raw_svector_ostream StrOS(Buf);
2705 print(OS&: StrOS, Policy);
2706 return std::string(StrOS.str());
2707}
2708
2709bool Qualifiers::isEmptyWhenPrinted(const PrintingPolicy &Policy) const {
2710 if (getCVRQualifiers())
2711 return false;
2712
2713 if (getAddressSpace() != LangAS::Default)
2714 return false;
2715
2716 if (getObjCGCAttr())
2717 return false;
2718
2719 if (Qualifiers::ObjCLifetime lifetime = getObjCLifetime())
2720 if (!(lifetime == Qualifiers::OCL_Strong && Policy.SuppressStrongLifetime))
2721 return false;
2722
2723 if (PointerAuthQualifier PointerAuth = getPointerAuth();
2724 PointerAuth && !PointerAuth.isEmptyWhenPrinted(P: Policy))
2725 return false;
2726
2727 return true;
2728}
2729
2730std::string Qualifiers::getAddrSpaceAsString(LangAS AS) {
2731 switch (AS) {
2732 case LangAS::Default:
2733 return "";
2734 case LangAS::opencl_global:
2735 return "__global";
2736 case LangAS::opencl_local:
2737 return "__local";
2738 case LangAS::opencl_private:
2739 return "__private";
2740 case LangAS::opencl_constant:
2741 return "__constant";
2742 case LangAS::opencl_generic:
2743 return "__generic";
2744 // TODO: Remove *_global_device and *_global_host after corresponding
2745 // attributes are deprecated for the required time.
2746 case LangAS::opencl_global_device:
2747 case LangAS::sycl_global_device:
2748 return "__global_device";
2749 case LangAS::opencl_global_host:
2750 case LangAS::sycl_global_host:
2751 return "__global_host";
2752 case LangAS::sycl_global:
2753 return "[[clang::sycl_global]]";
2754 case LangAS::sycl_local:
2755 return "[[clang::sycl_local]]";
2756 case LangAS::sycl_private:
2757 return "[[clang::sycl_private]]";
2758 case LangAS::sycl_generic:
2759 return "[[clang::sycl_generic]]";
2760 case LangAS::sycl_constant:
2761 return "[[clang::sycl_constant]]";
2762 case LangAS::cuda_device:
2763 return "__device__";
2764 case LangAS::cuda_constant:
2765 return "__constant__";
2766 case LangAS::cuda_shared:
2767 return "__shared__";
2768 case LangAS::ptr32_sptr:
2769 return "__sptr __ptr32";
2770 case LangAS::ptr32_uptr:
2771 return "__uptr __ptr32";
2772 case LangAS::ptr64:
2773 return "__ptr64";
2774 case LangAS::hlsl_groupshared:
2775 return "groupshared";
2776 case LangAS::hlsl_constant:
2777 return "hlsl_constant";
2778 case LangAS::hlsl_private:
2779 return "hlsl_private";
2780 case LangAS::hlsl_device:
2781 return "hlsl_device";
2782 case LangAS::hlsl_input:
2783 return "hlsl_input";
2784 case LangAS::hlsl_output:
2785 return "hlsl_output";
2786 case LangAS::hlsl_push_constant:
2787 return "hlsl_push_constant";
2788 case LangAS::wasm_funcref:
2789 return "__funcref";
2790 case LangAS::amdgpu_barrier:
2791 return "amdgpu_barrier";
2792 default:
2793 return std::to_string(val: toTargetAddressSpace(AS));
2794 }
2795}
2796
2797// Appends qualifiers to the given string, separated by spaces. Will
2798// prefix a space if the string is non-empty. Will not append a final
2799// space.
2800void Qualifiers::print(raw_ostream &OS, const PrintingPolicy& Policy,
2801 bool appendSpaceIfNonEmpty) const {
2802 bool addSpace = false;
2803
2804 unsigned quals = getCVRQualifiers();
2805 if (quals) {
2806 AppendTypeQualList(OS, TypeQuals: quals, HasRestrictKeyword: Policy.Restrict);
2807 addSpace = true;
2808 }
2809 if (hasUnaligned()) {
2810 if (addSpace)
2811 OS << ' ';
2812 OS << "__unaligned";
2813 addSpace = true;
2814 }
2815 auto ASStr = getAddrSpaceAsString(AS: getAddressSpace());
2816 if (!ASStr.empty()) {
2817 if (addSpace)
2818 OS << ' ';
2819 addSpace = true;
2820 // Wrap target address space into an attribute syntax
2821 if (isTargetAddressSpace(AS: getAddressSpace()))
2822 OS << "__attribute__((address_space(" << ASStr << ")))";
2823 else
2824 OS << ASStr;
2825 }
2826
2827 if (Qualifiers::GC gc = getObjCGCAttr()) {
2828 if (addSpace)
2829 OS << ' ';
2830 addSpace = true;
2831 if (gc == Qualifiers::Weak)
2832 OS << "__weak";
2833 else
2834 OS << "__strong";
2835 }
2836 if (Qualifiers::ObjCLifetime lifetime = getObjCLifetime()) {
2837 if (!(lifetime == Qualifiers::OCL_Strong && Policy.SuppressStrongLifetime)){
2838 if (addSpace)
2839 OS << ' ';
2840 addSpace = true;
2841 }
2842
2843 switch (lifetime) {
2844 case Qualifiers::OCL_None: llvm_unreachable("none but true");
2845 case Qualifiers::OCL_ExplicitNone: OS << "__unsafe_unretained"; break;
2846 case Qualifiers::OCL_Strong:
2847 if (!Policy.SuppressStrongLifetime)
2848 OS << "__strong";
2849 break;
2850
2851 case Qualifiers::OCL_Weak: OS << "__weak"; break;
2852 case Qualifiers::OCL_Autoreleasing: OS << "__autoreleasing"; break;
2853 }
2854 }
2855
2856 if (PointerAuthQualifier PointerAuth = getPointerAuth()) {
2857 if (addSpace)
2858 OS << ' ';
2859 addSpace = true;
2860
2861 PointerAuth.print(OS, P: Policy);
2862 }
2863
2864 if (appendSpaceIfNonEmpty && addSpace)
2865 OS << ' ';
2866}
2867
2868std::string QualType::getAsString() const {
2869 return getAsString(split: split(), Policy: LangOptions());
2870}
2871
2872std::string QualType::getAsString(const PrintingPolicy &Policy) const {
2873 std::string S;
2874 getAsStringInternal(Str&: S, Policy);
2875 return S;
2876}
2877
2878std::string QualType::getAsString(const Type *ty, Qualifiers qs,
2879 const PrintingPolicy &Policy) {
2880 std::string buffer;
2881 getAsStringInternal(ty, qs, out&: buffer, policy: Policy);
2882 return buffer;
2883}
2884
2885void QualType::print(raw_ostream &OS, const PrintingPolicy &Policy,
2886 const Twine &PlaceHolder, unsigned Indentation) const {
2887 print(split: splitAccordingToPolicy(QT: *this, Policy), OS, policy: Policy, PlaceHolder,
2888 Indentation);
2889}
2890
2891void QualType::print(const Type *ty, Qualifiers qs,
2892 raw_ostream &OS, const PrintingPolicy &policy,
2893 const Twine &PlaceHolder, unsigned Indentation) {
2894 SmallString<128> PHBuf;
2895 StringRef PH = PlaceHolder.toStringRef(Out&: PHBuf);
2896
2897 TypePrinter(policy, Indentation).print(T: ty, Quals: qs, OS, PlaceHolder: PH);
2898}
2899
2900void QualType::getAsStringInternal(std::string &Str,
2901 const PrintingPolicy &Policy) const {
2902 return getAsStringInternal(split: splitAccordingToPolicy(QT: *this, Policy), out&: Str,
2903 policy: Policy);
2904}
2905
2906void QualType::getAsStringInternal(const Type *ty, Qualifiers qs,
2907 std::string &buffer,
2908 const PrintingPolicy &policy) {
2909 SmallString<256> Buf;
2910 llvm::raw_svector_ostream StrOS(Buf);
2911 TypePrinter(policy).print(T: ty, Quals: qs, OS&: StrOS, PlaceHolder: buffer);
2912 std::string str = std::string(StrOS.str());
2913 buffer.swap(s&: str);
2914}
2915
2916raw_ostream &clang::operator<<(raw_ostream &OS, QualType QT) {
2917 SplitQualType S = QT.split();
2918 TypePrinter(LangOptions()).print(T: S.Ty, Quals: S.Quals, OS, /*PlaceHolder=*/"");
2919 return OS;
2920}
2921