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::BTFTagAttributed:
246 case Type::HLSLAttributedResource:
247 case Type::HLSLInlineSpirv:
248 case Type::PredefinedSugar:
249 CanPrefixQualifiers = true;
250 break;
251
252 case Type::ObjCObjectPointer:
253 CanPrefixQualifiers = T->isObjCIdType() || T->isObjCClassType() ||
254 T->isObjCQualifiedIdType() || T->isObjCQualifiedClassType();
255 break;
256
257 case Type::VariableArray:
258 case Type::DependentSizedArray:
259 NeedARCStrongQualifier = true;
260 [[fallthrough]];
261
262 case Type::ConstantArray:
263 case Type::IncompleteArray:
264 return canPrefixQualifiers(
265 T: cast<ArrayType>(Val: UnderlyingType)->getElementType().getTypePtr(),
266 NeedARCStrongQualifier);
267
268 case Type::Adjusted:
269 case Type::Decayed:
270 case Type::ArrayParameter:
271 case Type::Pointer:
272 case Type::BlockPointer:
273 case Type::LValueReference:
274 case Type::RValueReference:
275 case Type::MemberPointer:
276 case Type::DependentAddressSpace:
277 case Type::DependentVector:
278 case Type::DependentSizedExtVector:
279 case Type::Vector:
280 case Type::ExtVector:
281 case Type::ConstantMatrix:
282 case Type::DependentSizedMatrix:
283 case Type::FunctionProto:
284 case Type::FunctionNoProto:
285 case Type::Paren:
286 case Type::PackExpansion:
287 case Type::SubstTemplateTypeParm:
288 case Type::MacroQualified:
289 case Type::OverflowBehavior:
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 OS << "decltype(";
1363 if (const Expr *E = T->getUnderlyingExpr()) {
1364 PrintingPolicy ExprPolicy = Policy;
1365 ExprPolicy.PrintAsCanonical = T->isCanonicalUnqualified();
1366 E->printPretty(OS, Helper: nullptr, Policy: ExprPolicy);
1367 }
1368 OS << ')';
1369 spaceBeforePlaceHolder(OS);
1370}
1371
1372void TypePrinter::printPackIndexingBefore(const PackIndexingType *T,
1373 raw_ostream &OS) {
1374 if (T->hasSelectedType()) {
1375 OS << T->getSelectedType();
1376 } else {
1377 OS << T->getPattern() << "...[";
1378 T->getIndexExpr()->printPretty(OS, Helper: nullptr, Policy);
1379 OS << "]";
1380 }
1381 spaceBeforePlaceHolder(OS);
1382}
1383
1384void TypePrinter::printPackIndexingAfter(const PackIndexingType *T,
1385 raw_ostream &OS) {}
1386
1387void TypePrinter::printDecltypeAfter(const DecltypeType *T, raw_ostream &OS) {}
1388
1389void TypePrinter::printUnaryTransformBefore(const UnaryTransformType *T,
1390 raw_ostream &OS) {
1391 IncludeStrongLifetimeRAII Strong(Policy);
1392
1393 static const llvm::DenseMap<int, const char *> Transformation = {{
1394#define TRANSFORM_TYPE_TRAIT_DEF(Enum, Trait) \
1395 {UnaryTransformType::Enum, "__" #Trait},
1396#include "clang/Basic/BuiltinTraits.inc"
1397 }};
1398 OS << Transformation.lookup(Val: T->getUTTKind()) << '(';
1399 print(t: T->getBaseType(), OS, PlaceHolder: StringRef());
1400 OS << ')';
1401 spaceBeforePlaceHolder(OS);
1402}
1403
1404void TypePrinter::printUnaryTransformAfter(const UnaryTransformType *T,
1405 raw_ostream &OS) {}
1406
1407void TypePrinter::printAutoBefore(const AutoType *T, raw_ostream &OS) {
1408 // If the type has been deduced, do not print 'auto'.
1409 if (!T->getDeducedType().isNull()) {
1410 printBefore(T: T->getDeducedType(), OS);
1411 } else {
1412 if (T->isConstrained()) {
1413 // FIXME: Track a TypeConstraint as type sugar, so that we can print the
1414 // type as it was written.
1415 TemplateName Concept = T->getTypeConstraintConcept();
1416 Concept.print(OS, Policy, Qual: TemplateName::Qualified::None);
1417 auto Args = T->getTypeConstraintArguments();
1418 if (!Args.empty()) {
1419 const TemplateDecl *TD = Concept.getAsTemplateDecl();
1420 if (!TD)
1421 TD = Concept.getAsTemplateTemplateParmDecl();
1422 printTemplateArgumentList(OS, Args, Policy,
1423 TPL: TD->getTemplateParameters());
1424 }
1425 OS << ' ';
1426 }
1427 switch (T->getKeyword()) {
1428 case AutoTypeKeyword::Auto: OS << "auto"; break;
1429 case AutoTypeKeyword::DecltypeAuto: OS << "decltype(auto)"; break;
1430 case AutoTypeKeyword::GNUAutoType: OS << "__auto_type"; break;
1431 }
1432 spaceBeforePlaceHolder(OS);
1433 }
1434}
1435
1436void TypePrinter::printAutoAfter(const AutoType *T, raw_ostream &OS) {
1437 // If the type has been deduced, do not print 'auto'.
1438 if (!T->getDeducedType().isNull())
1439 printAfter(t: T->getDeducedType(), OS);
1440}
1441
1442void TypePrinter::printDeducedTemplateSpecializationBefore(
1443 const DeducedTemplateSpecializationType *T, raw_ostream &OS) {
1444 if (ElaboratedTypeKeyword Keyword = T->getKeyword();
1445 T->getKeyword() != ElaboratedTypeKeyword::None)
1446 OS << KeywordHelpers::getKeywordName(Keyword) << ' ';
1447
1448 TemplateName Name = T->getTemplateName();
1449
1450 // If the type has been deduced, print the template arguments, as if this was
1451 // printing the deduced type, but including elaboration and template name
1452 // qualification.
1453 // FIXME: There should probably be a policy which controls this.
1454 // We would probably want to do this on diagnostics, but not on -ast-print.
1455 ArrayRef<TemplateArgument> Args;
1456 TemplateDecl *DeducedTD = nullptr;
1457 if (!T->getDeducedType().isNull()) {
1458 if (const auto *TST =
1459 dyn_cast<TemplateSpecializationType>(Val: T->getDeducedType())) {
1460 DeducedTD = TST->getTemplateName().getAsTemplateDecl(
1461 /*IgnoreDeduced=*/true);
1462 Args = TST->template_arguments();
1463 } else {
1464 // Should only get here for canonical types.
1465 const auto *CD = cast<ClassTemplateSpecializationDecl>(
1466 Val: cast<RecordType>(Val: T->getDeducedType())->getDecl());
1467 DeducedTD = CD->getSpecializedTemplate();
1468 Args = CD->getTemplateArgs().asArray();
1469 }
1470
1471 // FIXME: Workaround for alias template CTAD not producing guides which
1472 // include the alias template specialization type.
1473 // Purposefully disregard qualification when building this TemplateName;
1474 // any qualification we might have, might not make sense in the
1475 // context this was deduced.
1476 if (!declaresSameEntity(D1: DeducedTD, D2: Name.getAsTemplateDecl(
1477 /*IgnoreDeduced=*/true)))
1478 Name = TemplateName(DeducedTD);
1479 }
1480
1481 {
1482 IncludeStrongLifetimeRAII Strong(Policy);
1483 Name.print(OS, Policy);
1484 }
1485 if (DeducedTD) {
1486 printTemplateArgumentList(OS, Args, Policy,
1487 TPL: DeducedTD->getTemplateParameters());
1488 }
1489
1490 spaceBeforePlaceHolder(OS);
1491}
1492
1493void TypePrinter::printDeducedTemplateSpecializationAfter(
1494 const DeducedTemplateSpecializationType *T, raw_ostream &OS) {
1495 // If the type has been deduced, print the deduced type.
1496 if (!T->getDeducedType().isNull())
1497 printAfter(t: T->getDeducedType(), OS);
1498}
1499
1500void TypePrinter::printAtomicBefore(const AtomicType *T, raw_ostream &OS) {
1501 IncludeStrongLifetimeRAII Strong(Policy);
1502
1503 OS << "_Atomic(";
1504 print(t: T->getValueType(), OS, PlaceHolder: StringRef());
1505 OS << ')';
1506 spaceBeforePlaceHolder(OS);
1507}
1508
1509void TypePrinter::printAtomicAfter(const AtomicType *T, raw_ostream &OS) {}
1510
1511void TypePrinter::printPipeBefore(const PipeType *T, raw_ostream &OS) {
1512 IncludeStrongLifetimeRAII Strong(Policy);
1513
1514 if (T->isReadOnly())
1515 OS << "read_only ";
1516 else
1517 OS << "write_only ";
1518 OS << "pipe ";
1519 print(t: T->getElementType(), OS, PlaceHolder: StringRef());
1520 spaceBeforePlaceHolder(OS);
1521}
1522
1523void TypePrinter::printPipeAfter(const PipeType *T, raw_ostream &OS) {}
1524
1525void TypePrinter::printBitIntBefore(const BitIntType *T, raw_ostream &OS) {
1526 if (T->isUnsigned())
1527 OS << "unsigned ";
1528 OS << "_BitInt(" << T->getNumBits() << ")";
1529 spaceBeforePlaceHolder(OS);
1530}
1531
1532void TypePrinter::printBitIntAfter(const BitIntType *T, raw_ostream &OS) {}
1533
1534void TypePrinter::printDependentBitIntBefore(const DependentBitIntType *T,
1535 raw_ostream &OS) {
1536 if (T->isUnsigned())
1537 OS << "unsigned ";
1538 OS << "_BitInt(";
1539 T->getNumBitsExpr()->printPretty(OS, Helper: nullptr, Policy);
1540 OS << ")";
1541 spaceBeforePlaceHolder(OS);
1542}
1543
1544void TypePrinter::printDependentBitIntAfter(const DependentBitIntType *T,
1545 raw_ostream &OS) {}
1546
1547void TypePrinter::printPredefinedSugarBefore(const PredefinedSugarType *T,
1548 raw_ostream &OS) {
1549 OS << T->getIdentifier()->getName();
1550 spaceBeforePlaceHolder(OS);
1551}
1552
1553void TypePrinter::printPredefinedSugarAfter(const PredefinedSugarType *T,
1554 raw_ostream &OS) {}
1555
1556void TypePrinter::printTagType(const TagType *T, raw_ostream &OS) {
1557 TagDecl *D = T->getDecl();
1558
1559 if (Policy.IncludeTagDefinition && T->isTagOwned()) {
1560 D->print(Out&: OS, Policy, Indentation);
1561 spaceBeforePlaceHolder(OS);
1562 return;
1563 }
1564
1565 bool PrintedKindDecoration = false;
1566 if (T->isCanonicalUnqualified()) {
1567 if (!Policy.SuppressTagKeyword && !D->getTypedefNameForAnonDecl()) {
1568 PrintedKindDecoration = true;
1569 OS << D->getKindName();
1570 OS << ' ';
1571 }
1572 } else {
1573 OS << TypeWithKeyword::getKeywordName(Keyword: T->getKeyword());
1574 if (T->getKeyword() != ElaboratedTypeKeyword::None) {
1575 PrintedKindDecoration = true;
1576 OS << ' ';
1577 }
1578 }
1579
1580 if (!Policy.FullyQualifiedName && !T->isCanonicalUnqualified()) {
1581 T->getQualifier().print(OS, Policy);
1582 } else if (!Policy.SuppressScope) {
1583 // Compute the full nested-name-specifier for this type.
1584 // In C, this will always be empty except when the type
1585 // being printed is anonymous within other Record.
1586 D->printNestedNameSpecifier(OS, Policy);
1587 }
1588
1589 if (const IdentifierInfo *II = D->getIdentifier())
1590 OS << II->getName();
1591 else {
1592 clang::PrintingPolicy Copy(Policy);
1593
1594 // Suppress the redundant tag keyword if we just printed one.
1595 if (PrintedKindDecoration) {
1596 Copy.SuppressTagKeywordInAnonNames = true;
1597 Copy.SuppressTagKeyword = true;
1598 }
1599
1600 D->printName(OS, Policy: Copy);
1601 }
1602
1603 // If this is a class template specialization, print the template
1604 // arguments.
1605 if (auto *S = dyn_cast<ClassTemplateSpecializationDecl>(Val: D)) {
1606 const TemplateParameterList *TParams =
1607 S->getSpecializedTemplate()->getTemplateParameters();
1608 const ASTTemplateArgumentListInfo *TArgAsWritten =
1609 S->getTemplateArgsAsWritten();
1610 IncludeStrongLifetimeRAII Strong(Policy);
1611 if (TArgAsWritten && !Policy.PrintAsCanonical)
1612 printTemplateArgumentList(OS, Args: TArgAsWritten->arguments(), Policy,
1613 TPL: TParams);
1614 else
1615 printTemplateArgumentList(OS, Args: S->getTemplateArgs().asArray(), Policy,
1616 TPL: TParams);
1617 }
1618
1619 spaceBeforePlaceHolder(OS);
1620}
1621
1622void TypePrinter::printRecordBefore(const RecordType *T, raw_ostream &OS) {
1623 // Print the preferred name if we have one for this type.
1624 if (Policy.UsePreferredNames) {
1625 for (const auto *PNA : T->getDecl()
1626 ->getMostRecentDecl()
1627 ->specific_attrs<PreferredNameAttr>()) {
1628 if (!declaresSameEntity(D1: PNA->getTypedefType()->getAsCXXRecordDecl(),
1629 D2: T->getDecl()))
1630 continue;
1631 // Find the outermost typedef or alias template.
1632 QualType T = PNA->getTypedefType();
1633 while (true) {
1634 if (auto *TT = dyn_cast<TypedefType>(Val&: T))
1635 return printTypeSpec(D: TT->getDecl(), OS);
1636 if (auto *TST = dyn_cast<TemplateSpecializationType>(Val&: T))
1637 return printTemplateId(T: TST, OS, /*FullyQualify=*/true);
1638 T = T->getLocallyUnqualifiedSingleStepDesugaredType();
1639 }
1640 }
1641 }
1642
1643 printTagType(T, OS);
1644}
1645
1646void TypePrinter::printRecordAfter(const RecordType *T, raw_ostream &OS) {}
1647
1648void TypePrinter::printEnumBefore(const EnumType *T, raw_ostream &OS) {
1649 printTagType(T, OS);
1650}
1651
1652void TypePrinter::printEnumAfter(const EnumType *T, raw_ostream &OS) {}
1653
1654void TypePrinter::printInjectedClassNameBefore(const InjectedClassNameType *T,
1655 raw_ostream &OS) {
1656 const ASTContext &Ctx = T->getDecl()->getASTContext();
1657 IncludeStrongLifetimeRAII Strong(Policy);
1658 T->getTemplateName(Ctx).print(OS, Policy);
1659 if (Policy.PrintInjectedClassNameWithArguments) {
1660 auto *Decl = T->getDecl();
1661 // FIXME: Use T->getTemplateArgs(Ctx) when that supports as-written
1662 // arguments.
1663 if (auto *RD = dyn_cast<ClassTemplateSpecializationDecl>(Val: Decl)) {
1664 printTemplateArgumentList(OS, Args: RD->getTemplateArgsAsWritten()->arguments(),
1665 Policy,
1666 TPL: T->getTemplateDecl()->getTemplateParameters());
1667 } else {
1668 ClassTemplateDecl *TD = Decl->getDescribedClassTemplate();
1669 assert(TD);
1670 printTemplateArgumentList(
1671 OS, Args: TD->getTemplateParameters()->getInjectedTemplateArgs(Context: Ctx), Policy,
1672 TPL: T->getTemplateDecl()->getTemplateParameters());
1673 }
1674 }
1675 spaceBeforePlaceHolder(OS);
1676}
1677
1678void TypePrinter::printInjectedClassNameAfter(const InjectedClassNameType *T,
1679 raw_ostream &OS) {}
1680
1681void TypePrinter::printTemplateTypeParmBefore(const TemplateTypeParmType *T,
1682 raw_ostream &OS) {
1683 TemplateTypeParmDecl *D = T->getDecl();
1684 if (D && D->isImplicit()) {
1685 if (auto *TC = D->getTypeConstraint()) {
1686 TC->print(OS, Policy);
1687 OS << ' ';
1688 }
1689 OS << "auto";
1690 } else if (IdentifierInfo *Id = T->getIdentifier())
1691 OS << (Policy.CleanUglifiedParameters ? Id->deuglifiedName()
1692 : Id->getName());
1693 else
1694 OS << "type-parameter-" << T->getDepth() << '-' << T->getIndex();
1695
1696 spaceBeforePlaceHolder(OS);
1697}
1698
1699void TypePrinter::printTemplateTypeParmAfter(const TemplateTypeParmType *T,
1700 raw_ostream &OS) {}
1701
1702void TypePrinter::printSubstTemplateTypeParmBefore(
1703 const SubstTemplateTypeParmType *T,
1704 raw_ostream &OS) {
1705 IncludeStrongLifetimeRAII Strong(Policy);
1706 printBefore(T: T->getReplacementType(), OS);
1707}
1708
1709void TypePrinter::printSubstTemplateTypeParmAfter(
1710 const SubstTemplateTypeParmType *T,
1711 raw_ostream &OS) {
1712 IncludeStrongLifetimeRAII Strong(Policy);
1713 printAfter(t: T->getReplacementType(), OS);
1714}
1715
1716void TypePrinter::printSubstBuiltinTemplatePackBefore(
1717 const SubstBuiltinTemplatePackType *T, raw_ostream &OS) {
1718 IncludeStrongLifetimeRAII Strong(Policy);
1719 OS << "type-pack";
1720}
1721
1722void TypePrinter::printSubstBuiltinTemplatePackAfter(
1723 const SubstBuiltinTemplatePackType *T, raw_ostream &OS) {}
1724
1725void TypePrinter::printSubstTemplateTypeParmPackBefore(
1726 const SubstTemplateTypeParmPackType *T,
1727 raw_ostream &OS) {
1728 IncludeStrongLifetimeRAII Strong(Policy);
1729 if (const TemplateTypeParmDecl *D = T->getReplacedParameter()) {
1730 if (D && D->isImplicit()) {
1731 if (auto *TC = D->getTypeConstraint()) {
1732 TC->print(OS, Policy);
1733 OS << ' ';
1734 }
1735 OS << "auto";
1736 } else if (IdentifierInfo *Id = D->getIdentifier())
1737 OS << (Policy.CleanUglifiedParameters ? Id->deuglifiedName()
1738 : Id->getName());
1739 else
1740 OS << "type-parameter-" << D->getDepth() << '-' << D->getIndex();
1741
1742 spaceBeforePlaceHolder(OS);
1743 }
1744}
1745
1746void TypePrinter::printSubstTemplateTypeParmPackAfter(
1747 const SubstTemplateTypeParmPackType *T,
1748 raw_ostream &OS) {
1749 IncludeStrongLifetimeRAII Strong(Policy);
1750}
1751
1752void TypePrinter::printTemplateId(const TemplateSpecializationType *T,
1753 raw_ostream &OS, bool FullyQualify) {
1754 IncludeStrongLifetimeRAII Strong(Policy);
1755
1756 if (ElaboratedTypeKeyword K = T->getKeyword();
1757 K != ElaboratedTypeKeyword::None)
1758 OS << TypeWithKeyword::getKeywordName(Keyword: K) << ' ';
1759
1760 TemplateDecl *TD =
1761 T->getTemplateName().getAsTemplateDecl(/*IgnoreDeduced=*/true);
1762 // FIXME: Null TD never exercised in test suite.
1763 if (FullyQualify && TD) {
1764 if (!Policy.SuppressScope)
1765 TD->printNestedNameSpecifier(OS, Policy);
1766
1767 OS << TD->getName();
1768 } else {
1769 T->getTemplateName().print(OS, Policy,
1770 Qual: !Policy.SuppressScope
1771 ? TemplateName::Qualified::AsWritten
1772 : TemplateName::Qualified::None);
1773 }
1774
1775 DefaultTemplateArgsPolicyRAII TemplateArgs(Policy);
1776 const TemplateParameterList *TPL = TD ? TD->getTemplateParameters() : nullptr;
1777 printTemplateArgumentList(OS, Args: T->template_arguments(), Policy, TPL);
1778 spaceBeforePlaceHolder(OS);
1779}
1780
1781void TypePrinter::printTemplateSpecializationBefore(
1782 const TemplateSpecializationType *T,
1783 raw_ostream &OS) {
1784 printTemplateId(T, OS, FullyQualify: Policy.FullyQualifiedName);
1785}
1786
1787void TypePrinter::printTemplateSpecializationAfter(
1788 const TemplateSpecializationType *T,
1789 raw_ostream &OS) {}
1790
1791void TypePrinter::printParenBefore(const ParenType *T, raw_ostream &OS) {
1792 if (!HasEmptyPlaceHolder && !isa<FunctionType>(Val: T->getInnerType())) {
1793 printBefore(T: T->getInnerType(), OS);
1794 OS << '(';
1795 } else
1796 printBefore(T: T->getInnerType(), OS);
1797}
1798
1799void TypePrinter::printParenAfter(const ParenType *T, raw_ostream &OS) {
1800 if (!HasEmptyPlaceHolder && !isa<FunctionType>(Val: T->getInnerType())) {
1801 OS << ')';
1802 printAfter(t: T->getInnerType(), OS);
1803 } else
1804 printAfter(t: T->getInnerType(), OS);
1805}
1806
1807void TypePrinter::printDependentNameBefore(const DependentNameType *T,
1808 raw_ostream &OS) {
1809 OS << TypeWithKeyword::getKeywordName(Keyword: T->getKeyword());
1810 if (T->getKeyword() != ElaboratedTypeKeyword::None)
1811 OS << " ";
1812 T->getQualifier().print(OS, Policy);
1813 OS << T->getIdentifier()->getName();
1814 spaceBeforePlaceHolder(OS);
1815}
1816
1817void TypePrinter::printDependentNameAfter(const DependentNameType *T,
1818 raw_ostream &OS) {}
1819
1820void TypePrinter::printPackExpansionBefore(const PackExpansionType *T,
1821 raw_ostream &OS) {
1822 printBefore(T: T->getPattern(), OS);
1823}
1824
1825void TypePrinter::printPackExpansionAfter(const PackExpansionType *T,
1826 raw_ostream &OS) {
1827 printAfter(t: T->getPattern(), OS);
1828 OS << "...";
1829}
1830
1831static void printCountAttributedImpl(const CountAttributedType *T,
1832 raw_ostream &OS,
1833 const PrintingPolicy &Policy) {
1834 OS << ' ';
1835 if (T->isCountInBytes() && T->isOrNull())
1836 OS << "__sized_by_or_null(";
1837 else if (T->isCountInBytes())
1838 OS << "__sized_by(";
1839 else if (T->isOrNull())
1840 OS << "__counted_by_or_null(";
1841 else
1842 OS << "__counted_by(";
1843 if (T->getCountExpr())
1844 T->getCountExpr()->printPretty(OS, Helper: nullptr, Policy);
1845 OS << ')';
1846}
1847
1848void TypePrinter::printCountAttributedBefore(const CountAttributedType *T,
1849 raw_ostream &OS) {
1850 printBefore(T: T->desugar(), OS);
1851 if (!T->isArrayType())
1852 printCountAttributedImpl(T, OS, Policy);
1853}
1854
1855void TypePrinter::printCountAttributedAfter(const CountAttributedType *T,
1856 raw_ostream &OS) {
1857 printAfter(t: T->desugar(), OS);
1858 if (T->isArrayType())
1859 printCountAttributedImpl(T, OS, Policy);
1860}
1861
1862void TypePrinter::printLateParsedAttrBefore(const LateParsedAttrType *T,
1863 raw_ostream &OS) {
1864 // LateParsedAttrType is a transient placeholder that should not appear
1865 // in user-facing output. Just print the wrapped type.
1866 printBefore(T: T->getWrappedType(), OS);
1867}
1868
1869void TypePrinter::printLateParsedAttrAfter(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 printAfter(t: T->getWrappedType(), OS);
1874}
1875
1876void TypePrinter::printAttributedBefore(const AttributedType *T,
1877 raw_ostream &OS) {
1878 // FIXME: Generate this with TableGen.
1879
1880 // Prefer the macro forms of the GC and ownership qualifiers.
1881 if (T->getAttrKind() == attr::ObjCGC ||
1882 T->getAttrKind() == attr::ObjCOwnership)
1883 return printBefore(T: T->getEquivalentType(), OS);
1884
1885 if (T->getAttrKind() == attr::ObjCKindOf)
1886 OS << "__kindof ";
1887
1888 if (T->getAttrKind() == attr::PreserveNone) {
1889 OS << "__attribute__((preserve_none)) ";
1890 spaceBeforePlaceHolder(OS);
1891 } else if (T->getAttrKind() == attr::PreserveMost) {
1892 OS << "__attribute__((preserve_most)) ";
1893 spaceBeforePlaceHolder(OS);
1894 } else if (T->getAttrKind() == attr::PreserveAll) {
1895 OS << "__attribute__((preserve_all)) ";
1896 spaceBeforePlaceHolder(OS);
1897 }
1898
1899 if (T->getAttrKind() == attr::AddressSpace)
1900 printBefore(T: T->getEquivalentType(), OS);
1901 else
1902 printBefore(T: T->getModifiedType(), OS);
1903
1904 if (T->isMSTypeSpec()) {
1905 switch (T->getAttrKind()) {
1906 default: return;
1907 case attr::Ptr32: OS << " __ptr32"; break;
1908 case attr::Ptr64: OS << " __ptr64"; break;
1909 case attr::SPtr: OS << " __sptr"; break;
1910 case attr::UPtr: OS << " __uptr"; break;
1911 }
1912 spaceBeforePlaceHolder(OS);
1913 }
1914
1915 if (T->isWebAssemblyFuncrefSpec())
1916 OS << "__funcref";
1917
1918 // Print nullability type specifiers.
1919 if (T->getImmediateNullability()) {
1920 if (T->getAttrKind() == attr::TypeNonNull)
1921 OS << " _Nonnull";
1922 else if (T->getAttrKind() == attr::TypeNullable)
1923 OS << " _Nullable";
1924 else if (T->getAttrKind() == attr::TypeNullUnspecified)
1925 OS << " _Null_unspecified";
1926 else if (T->getAttrKind() == attr::TypeNullableResult)
1927 OS << " _Nullable_result";
1928 else
1929 llvm_unreachable("unhandled nullability");
1930 spaceBeforePlaceHolder(OS);
1931 }
1932}
1933
1934void TypePrinter::printAttributedAfter(const AttributedType *T,
1935 raw_ostream &OS) {
1936 // FIXME: Generate this with TableGen.
1937
1938 // Prefer the macro forms of the GC and ownership qualifiers.
1939 if (T->getAttrKind() == attr::ObjCGC ||
1940 T->getAttrKind() == attr::ObjCOwnership)
1941 return printAfter(t: T->getEquivalentType(), OS);
1942
1943 // If this is a calling convention attribute, don't print the implicit CC from
1944 // the modified type.
1945 SaveAndRestore MaybeSuppressCC(InsideCCAttribute, T->isCallingConv());
1946
1947 printAfter(t: T->getModifiedType(), OS);
1948
1949 // Some attributes are printed as qualifiers before the type, so we have
1950 // nothing left to do.
1951 if (T->getAttrKind() == attr::ObjCKindOf || T->isMSTypeSpec() ||
1952 T->getImmediateNullability() || T->isWebAssemblyFuncrefSpec())
1953 return;
1954
1955 // Don't print the inert __unsafe_unretained attribute at all.
1956 if (T->getAttrKind() == attr::ObjCInertUnsafeUnretained)
1957 return;
1958
1959 // Don't print ns_returns_retained unless it had an effect.
1960 if (T->getAttrKind() == attr::NSReturnsRetained &&
1961 !T->getEquivalentType()->castAs<FunctionType>()
1962 ->getExtInfo().getProducesResult())
1963 return;
1964
1965 if (T->getAttrKind() == attr::LifetimeBound) {
1966 OS << " [[clang::lifetimebound]]";
1967 return;
1968 }
1969 if (T->getAttrKind() == attr::LifetimeCaptureBy) {
1970 OS << " [[clang::lifetime_capture_by(";
1971 if (auto *attr = dyn_cast_or_null<LifetimeCaptureByAttr>(Val: T->getAttr()))
1972 llvm::interleaveComma(c: attr->getArgIdents(), os&: OS,
1973 each_fn: [&](auto it) { OS << it->getName(); });
1974 OS << ")]]";
1975 return;
1976 }
1977
1978 // The printing of the address_space attribute is handled by the qualifier
1979 // since it is still stored in the qualifier. Return early to prevent printing
1980 // this twice.
1981 if (T->getAttrKind() == attr::AddressSpace)
1982 return;
1983
1984 if (T->getAttrKind() == attr::AnnotateType) {
1985 // FIXME: Print the attribute arguments once we have a way to retrieve these
1986 // here. For the meantime, we just print `[[clang::annotate_type(...)]]`
1987 // without the arguments so that we know at least that we had _some_
1988 // annotation on the type.
1989 OS << " [[clang::annotate_type(...)]]";
1990 return;
1991 }
1992
1993 if (T->getAttrKind() == attr::ArmStreaming) {
1994 OS << "__arm_streaming";
1995 return;
1996 }
1997 if (T->getAttrKind() == attr::ArmStreamingCompatible) {
1998 OS << "__arm_streaming_compatible";
1999 return;
2000 }
2001
2002 if (T->getAttrKind() == attr::SwiftAttr) {
2003 if (auto *swiftAttr = dyn_cast_or_null<SwiftAttrAttr>(Val: T->getAttr())) {
2004 OS << " __attribute__((swift_attr(\"" << swiftAttr->getAttribute()
2005 << "\")))";
2006 }
2007 return;
2008 }
2009
2010 if (T->getAttrKind() == attr::PreserveAll ||
2011 T->getAttrKind() == attr::PreserveMost ||
2012 T->getAttrKind() == attr::PreserveNone) {
2013 // This has to be printed before the type.
2014 return;
2015 }
2016
2017 OS << " __attribute__((";
2018 switch (T->getAttrKind()) {
2019#define TYPE_ATTR(NAME)
2020#define DECL_OR_TYPE_ATTR(NAME)
2021#define ATTR(NAME) case attr::NAME:
2022#include "clang/Basic/AttrList.inc"
2023 llvm_unreachable("non-type attribute attached to type");
2024
2025 case attr::BTFTypeTag:
2026 llvm_unreachable("BTFTypeTag attribute handled separately");
2027
2028 case attr::HLSLResourceClass:
2029 case attr::HLSLIsROV:
2030 case attr::HLSLRawBuffer:
2031 case attr::HLSLContainedType:
2032 case attr::HLSLIsCounter:
2033 case attr::HLSLResourceDimension:
2034 case attr::HLSLIsArray:
2035 case attr::HLSLIsMultiSampled:
2036 llvm_unreachable("HLSL resource type attributes handled separately");
2037
2038 case attr::OpenCLPrivateAddressSpace:
2039 case attr::OpenCLGlobalAddressSpace:
2040 case attr::OpenCLGlobalDeviceAddressSpace:
2041 case attr::OpenCLGlobalHostAddressSpace:
2042 case attr::OpenCLLocalAddressSpace:
2043 case attr::OpenCLConstantAddressSpace:
2044 case attr::OpenCLGenericAddressSpace:
2045 case attr::HLSLGroupSharedAddressSpace:
2046 // FIXME: Update printAttributedBefore to print these once we generate
2047 // AttributedType nodes for them.
2048 break;
2049
2050 case attr::CountedBy:
2051 case attr::CountedByOrNull:
2052 case attr::SizedBy:
2053 case attr::SizedByOrNull:
2054 case attr::LifetimeBound:
2055 case attr::LifetimeCaptureBy:
2056 case attr::TypeNonNull:
2057 case attr::TypeNullable:
2058 case attr::TypeNullableResult:
2059 case attr::TypeNullUnspecified:
2060 case attr::ObjCGC:
2061 case attr::ObjCInertUnsafeUnretained:
2062 case attr::ObjCKindOf:
2063 case attr::ObjCOwnership:
2064 case attr::Ptr32:
2065 case attr::Ptr64:
2066 case attr::SPtr:
2067 case attr::UPtr:
2068 case attr::PointerAuth:
2069 case attr::AddressSpace:
2070 case attr::CmseNSCall:
2071 case attr::AnnotateType:
2072 case attr::WebAssemblyFuncref:
2073 case attr::ArmAgnostic:
2074 case attr::ArmStreaming:
2075 case attr::ArmStreamingCompatible:
2076 case attr::ArmIn:
2077 case attr::ArmOut:
2078 case attr::ArmInOut:
2079 case attr::ArmPreserves:
2080 case attr::NonBlocking:
2081 case attr::NonAllocating:
2082 case attr::Blocking:
2083 case attr::Allocating:
2084 case attr::SwiftAttr:
2085 case attr::PreserveAll:
2086 case attr::PreserveMost:
2087 case attr::PreserveNone:
2088 case attr::OverflowBehavior:
2089 llvm_unreachable("This attribute should have been handled already");
2090
2091 case attr::NSReturnsRetained:
2092 OS << "ns_returns_retained";
2093 break;
2094
2095 case attr::HLSLRowMajor:
2096 OS << "row_major";
2097 break;
2098 case attr::HLSLColumnMajor:
2099 OS << "column_major";
2100 break;
2101
2102 // FIXME: When Sema learns to form this AttributedType, avoid printing the
2103 // attribute again in printFunctionProtoAfter.
2104 case attr::AnyX86NoCfCheck: OS << "nocf_check"; break;
2105 case attr::CDecl: OS << "cdecl"; break;
2106 case attr::FastCall: OS << "fastcall"; break;
2107 case attr::StdCall: OS << "stdcall"; break;
2108 case attr::ThisCall: OS << "thiscall"; break;
2109 case attr::SwiftCall: OS << "swiftcall"; break;
2110 case attr::SwiftAsyncCall: OS << "swiftasynccall"; break;
2111 case attr::VectorCall: OS << "vectorcall"; break;
2112 case attr::Pascal: OS << "pascal"; break;
2113 case attr::MSABI: OS << "ms_abi"; break;
2114 case attr::SysVABI: OS << "sysv_abi"; break;
2115 case attr::RegCall: OS << "regcall"; break;
2116 case attr::Pcs: {
2117 OS << "pcs(";
2118 QualType t = T->getEquivalentType();
2119 while (!t->isFunctionType())
2120 t = t->getPointeeType();
2121 OS << (t->castAs<FunctionType>()->getCallConv() == CC_AAPCS ?
2122 "\"aapcs\"" : "\"aapcs-vfp\"");
2123 OS << ')';
2124 break;
2125 }
2126 case attr::AArch64VectorPcs: OS << "aarch64_vector_pcs"; break;
2127 case attr::AArch64SVEPcs: OS << "aarch64_sve_pcs"; break;
2128 case attr::IntelOclBicc:
2129 OS << "inteloclbicc";
2130 break;
2131 case attr::M68kRTD:
2132 OS << "m68k_rtd";
2133 break;
2134 case attr::RISCVVectorCC:
2135 OS << "riscv_vector_cc";
2136 break;
2137 case attr::RISCVVLSCC:
2138 OS << "riscv_vls_cc";
2139 break;
2140 case attr::NoDeref:
2141 OS << "noderef";
2142 break;
2143 case attr::CFIUncheckedCallee:
2144 OS << "cfi_unchecked_callee";
2145 break;
2146 case attr::AcquireHandle:
2147 OS << "acquire_handle";
2148 break;
2149 case attr::ArmMveStrictPolymorphism:
2150 OS << "__clang_arm_mve_strict_polymorphism";
2151 break;
2152 case attr::ExtVectorType:
2153 OS << "ext_vector_type";
2154 break;
2155 case attr::CFISalt:
2156 OS << "cfi_salt(\"" << cast<CFISaltAttr>(Val: T->getAttr())->getSalt() << "\")";
2157 break;
2158 case attr::NoFieldProtection:
2159 OS << "no_field_protection";
2160 break;
2161 case attr::PointerFieldProtection:
2162 OS << "pointer_field_protection";
2163 break;
2164 }
2165 OS << "))";
2166}
2167
2168void TypePrinter::printBTFTagAttributedBefore(const BTFTagAttributedType *T,
2169 raw_ostream &OS) {
2170 printBefore(T: T->getWrappedType(), OS);
2171 OS << " __attribute__((btf_type_tag(\"" << T->getAttr()->getBTFTypeTag() << "\")))";
2172}
2173
2174void TypePrinter::printBTFTagAttributedAfter(const BTFTagAttributedType *T,
2175 raw_ostream &OS) {
2176 printAfter(t: T->getWrappedType(), OS);
2177}
2178
2179void TypePrinter::printOverflowBehaviorBefore(const OverflowBehaviorType *T,
2180 raw_ostream &OS) {
2181 switch (T->getBehaviorKind()) {
2182 case clang::OverflowBehaviorType::OverflowBehaviorKind::Wrap:
2183 OS << "__ob_wrap ";
2184 break;
2185 case clang::OverflowBehaviorType::OverflowBehaviorKind::Trap:
2186 OS << "__ob_trap ";
2187 break;
2188 }
2189 printBefore(T: T->getUnderlyingType(), OS);
2190}
2191
2192void TypePrinter::printOverflowBehaviorAfter(const OverflowBehaviorType *T,
2193 raw_ostream &OS) {
2194 printAfter(t: T->getUnderlyingType(), OS);
2195}
2196
2197void TypePrinter::printHLSLAttributedResourceBefore(
2198 const HLSLAttributedResourceType *T, raw_ostream &OS) {
2199 printBefore(T: T->getWrappedType(), OS);
2200}
2201
2202void TypePrinter::printHLSLAttributedResourceAfter(
2203 const HLSLAttributedResourceType *T, raw_ostream &OS) {
2204 printAfter(t: T->getWrappedType(), OS);
2205 const HLSLAttributedResourceType::Attributes &Attrs = T->getAttrs();
2206 OS << " [[hlsl::resource_class(\""
2207 << HLSLResourceClassAttr::ConvertResourceClassToStr(Val: Attrs.ResourceClass)
2208 << "\")]]";
2209 if (Attrs.IsROV)
2210 OS << " [[hlsl::is_rov]]";
2211 if (Attrs.RawBuffer)
2212 OS << " [[hlsl::raw_buffer]]";
2213 if (Attrs.IsCounter)
2214 OS << " [[hlsl::is_counter]]";
2215 if (Attrs.IsArray)
2216 OS << " [[hlsl::is_array]]";
2217 if (Attrs.isMultiSampled())
2218 OS << " [[hlsl::is_ms]]";
2219
2220 QualType ContainedTy = T->getContainedType();
2221 if (!ContainedTy.isNull()) {
2222 OS << " [[hlsl::contained_type(";
2223 printBefore(T: ContainedTy, OS);
2224 printAfter(t: ContainedTy, OS);
2225 OS << ")]]";
2226 }
2227
2228 if (Attrs.ResourceDimension != llvm::dxil::ResourceDimension::Unknown)
2229 OS << " [[hlsl::dimension(\""
2230 << HLSLResourceDimensionAttr::ConvertResourceDimensionToStr(
2231 Val: Attrs.ResourceDimension)
2232 << "\")]]";
2233}
2234
2235void TypePrinter::printHLSLInlineSpirvBefore(const HLSLInlineSpirvType *T,
2236 raw_ostream &OS) {
2237 OS << "__hlsl_spirv_type<" << T->getOpcode();
2238
2239 OS << ", " << T->getSize();
2240 OS << ", " << T->getAlignment();
2241
2242 for (auto &Operand : T->getOperands()) {
2243 using SpirvOperandKind = SpirvOperand::SpirvOperandKind;
2244
2245 OS << ", ";
2246 switch (Operand.getKind()) {
2247 case SpirvOperandKind::ConstantId: {
2248 QualType ConstantType = Operand.getResultType();
2249 OS << "vk::integral_constant<";
2250 printBefore(T: ConstantType, OS);
2251 printAfter(t: ConstantType, OS);
2252 OS << ", ";
2253 OS << Operand.getValue();
2254 OS << ">";
2255 break;
2256 }
2257 case SpirvOperandKind::Literal:
2258 OS << "vk::Literal<vk::integral_constant<uint, ";
2259 OS << Operand.getValue();
2260 OS << ">>";
2261 break;
2262 case SpirvOperandKind::TypeId: {
2263 QualType Type = Operand.getResultType();
2264 printBefore(T: Type, OS);
2265 printAfter(t: Type, OS);
2266 break;
2267 }
2268 default:
2269 llvm_unreachable("Invalid SpirvOperand kind!");
2270 break;
2271 }
2272 }
2273
2274 OS << ">";
2275}
2276
2277void TypePrinter::printHLSLInlineSpirvAfter(const HLSLInlineSpirvType *T,
2278 raw_ostream &OS) {
2279 // nothing to do
2280}
2281
2282void TypePrinter::printObjCInterfaceBefore(const ObjCInterfaceType *T,
2283 raw_ostream &OS) {
2284 OS << T->getDecl()->getName();
2285 spaceBeforePlaceHolder(OS);
2286}
2287
2288void TypePrinter::printObjCInterfaceAfter(const ObjCInterfaceType *T,
2289 raw_ostream &OS) {}
2290
2291void TypePrinter::printObjCTypeParamBefore(const ObjCTypeParamType *T,
2292 raw_ostream &OS) {
2293 OS << T->getDecl()->getName();
2294 if (!T->qual_empty()) {
2295 bool isFirst = true;
2296 OS << '<';
2297 for (const auto *I : T->quals()) {
2298 if (isFirst)
2299 isFirst = false;
2300 else
2301 OS << ',';
2302 OS << I->getName();
2303 }
2304 OS << '>';
2305 }
2306
2307 spaceBeforePlaceHolder(OS);
2308}
2309
2310void TypePrinter::printObjCTypeParamAfter(const ObjCTypeParamType *T,
2311 raw_ostream &OS) {}
2312
2313void TypePrinter::printObjCObjectBefore(const ObjCObjectType *T,
2314 raw_ostream &OS) {
2315 if (T->qual_empty() && T->isUnspecializedAsWritten() &&
2316 !T->isKindOfTypeAsWritten())
2317 return printBefore(T: T->getBaseType(), OS);
2318
2319 if (T->isKindOfTypeAsWritten())
2320 OS << "__kindof ";
2321
2322 print(t: T->getBaseType(), OS, PlaceHolder: StringRef());
2323
2324 if (T->isSpecializedAsWritten()) {
2325 bool isFirst = true;
2326 OS << '<';
2327 for (auto typeArg : T->getTypeArgsAsWritten()) {
2328 if (isFirst)
2329 isFirst = false;
2330 else
2331 OS << ",";
2332
2333 print(t: typeArg, OS, PlaceHolder: StringRef());
2334 }
2335 OS << '>';
2336 }
2337
2338 if (!T->qual_empty()) {
2339 bool isFirst = true;
2340 OS << '<';
2341 for (const auto *I : T->quals()) {
2342 if (isFirst)
2343 isFirst = false;
2344 else
2345 OS << ',';
2346 OS << I->getName();
2347 }
2348 OS << '>';
2349 }
2350
2351 spaceBeforePlaceHolder(OS);
2352}
2353
2354void TypePrinter::printObjCObjectAfter(const ObjCObjectType *T,
2355 raw_ostream &OS) {
2356 if (T->qual_empty() && T->isUnspecializedAsWritten() &&
2357 !T->isKindOfTypeAsWritten())
2358 return printAfter(t: T->getBaseType(), OS);
2359}
2360
2361void TypePrinter::printObjCObjectPointerBefore(const ObjCObjectPointerType *T,
2362 raw_ostream &OS) {
2363 printBefore(T: T->getPointeeType(), OS);
2364
2365 // If we need to print the pointer, print it now.
2366 if (!T->isObjCIdType() && !T->isObjCQualifiedIdType() &&
2367 !T->isObjCClassType() && !T->isObjCQualifiedClassType()) {
2368 if (HasEmptyPlaceHolder)
2369 OS << ' ';
2370 OS << '*';
2371 }
2372}
2373
2374void TypePrinter::printObjCObjectPointerAfter(const ObjCObjectPointerType *T,
2375 raw_ostream &OS) {}
2376
2377static
2378const TemplateArgument &getArgument(const TemplateArgument &A) { return A; }
2379
2380static const TemplateArgument &getArgument(const TemplateArgumentLoc &A) {
2381 return A.getArgument();
2382}
2383
2384static void printArgument(const TemplateArgument &A, const PrintingPolicy &PP,
2385 llvm::raw_ostream &OS, bool IncludeType) {
2386 A.print(Policy: PP, Out&: OS, IncludeType);
2387}
2388
2389static void printArgument(const TemplateArgumentLoc &A,
2390 const PrintingPolicy &PP, llvm::raw_ostream &OS,
2391 bool IncludeType) {
2392 const TemplateArgument::ArgKind &Kind = A.getArgument().getKind();
2393 if (Kind == TemplateArgument::ArgKind::Type)
2394 return A.getTypeSourceInfo()->getType().print(OS, Policy: PP);
2395 return A.getArgument().print(Policy: PP, Out&: OS, IncludeType);
2396}
2397
2398static bool isSubstitutedTemplateArgument(ASTContext &Ctx, TemplateArgument Arg,
2399 TemplateArgument Pattern,
2400 ArrayRef<TemplateArgument> Args,
2401 unsigned Depth);
2402
2403static bool isSubstitutedType(ASTContext &Ctx, QualType T, QualType Pattern,
2404 ArrayRef<TemplateArgument> Args, unsigned Depth) {
2405 if (Ctx.hasSameType(T1: T, T2: Pattern))
2406 return true;
2407
2408 // A type parameter matches its argument.
2409 if (auto *TTPT = Pattern->getAsCanonical<TemplateTypeParmType>()) {
2410 if (TTPT->getDepth() == Depth && TTPT->getIndex() < Args.size() &&
2411 Args[TTPT->getIndex()].getKind() == TemplateArgument::Type) {
2412 QualType SubstArg = Ctx.getQualifiedType(
2413 T: Args[TTPT->getIndex()].getAsType(), Qs: Pattern.getQualifiers());
2414 return Ctx.hasSameType(T1: SubstArg, T2: T);
2415 }
2416 return false;
2417 }
2418
2419 // FIXME: Recurse into array types.
2420
2421 // All other cases will need the types to be identically qualified.
2422 Qualifiers TQual, PatQual;
2423 T = Ctx.getUnqualifiedArrayType(T, Quals&: TQual);
2424 Pattern = Ctx.getUnqualifiedArrayType(T: Pattern, Quals&: PatQual);
2425 if (TQual != PatQual)
2426 return false;
2427
2428 // Recurse into pointer-like types.
2429 {
2430 QualType TPointee = T->getPointeeType();
2431 QualType PPointee = Pattern->getPointeeType();
2432 if (!TPointee.isNull() && !PPointee.isNull())
2433 return T->getTypeClass() == Pattern->getTypeClass() &&
2434 isSubstitutedType(Ctx, T: TPointee, Pattern: PPointee, Args, Depth);
2435 }
2436
2437 // Recurse into template specialization types.
2438 if (auto *PTST =
2439 Pattern.getCanonicalType()->getAs<TemplateSpecializationType>()) {
2440 TemplateName Template;
2441 ArrayRef<TemplateArgument> TemplateArgs;
2442 if (auto *TTST = T->getAs<TemplateSpecializationType>()) {
2443 Template = TTST->getTemplateName();
2444 TemplateArgs = TTST->template_arguments();
2445 } else if (auto *CTSD = dyn_cast_or_null<ClassTemplateSpecializationDecl>(
2446 Val: T->getAsCXXRecordDecl())) {
2447 Template = TemplateName(CTSD->getSpecializedTemplate());
2448 TemplateArgs = CTSD->getTemplateArgs().asArray();
2449 } else {
2450 return false;
2451 }
2452
2453 if (!isSubstitutedTemplateArgument(Ctx, Arg: Template, Pattern: PTST->getTemplateName(),
2454 Args, Depth))
2455 return false;
2456 if (TemplateArgs.size() != PTST->template_arguments().size())
2457 return false;
2458 for (unsigned I = 0, N = TemplateArgs.size(); I != N; ++I)
2459 if (!isSubstitutedTemplateArgument(
2460 Ctx, Arg: TemplateArgs[I], Pattern: PTST->template_arguments()[I], Args, Depth))
2461 return false;
2462 return true;
2463 }
2464
2465 // FIXME: Handle more cases.
2466 return false;
2467}
2468
2469/// Evaluates the expression template argument 'Pattern' and returns true
2470/// if 'Arg' evaluates to the same result.
2471static bool templateArgumentExpressionsEqual(ASTContext const &Ctx,
2472 TemplateArgument const &Pattern,
2473 TemplateArgument const &Arg) {
2474 if (Pattern.getKind() != TemplateArgument::Expression)
2475 return false;
2476
2477 // Can't evaluate value-dependent expressions so bail early
2478 Expr const *pattern_expr = Pattern.getAsExpr();
2479 if (pattern_expr->isValueDependent() ||
2480 !pattern_expr->isIntegerConstantExpr(Ctx))
2481 return false;
2482
2483 if (Arg.getKind() == TemplateArgument::Integral)
2484 return llvm::APSInt::isSameValue(I1: pattern_expr->EvaluateKnownConstInt(Ctx),
2485 I2: Arg.getAsIntegral());
2486
2487 if (Arg.getKind() == TemplateArgument::Expression) {
2488 Expr const *args_expr = Arg.getAsExpr();
2489 if (args_expr->isValueDependent() || !args_expr->isIntegerConstantExpr(Ctx))
2490 return false;
2491
2492 return llvm::APSInt::isSameValue(I1: args_expr->EvaluateKnownConstInt(Ctx),
2493 I2: pattern_expr->EvaluateKnownConstInt(Ctx));
2494 }
2495
2496 return false;
2497}
2498
2499static bool isSubstitutedTemplateArgument(ASTContext &Ctx, TemplateArgument Arg,
2500 TemplateArgument Pattern,
2501 ArrayRef<TemplateArgument> Args,
2502 unsigned Depth) {
2503 Arg = Ctx.getCanonicalTemplateArgument(Arg);
2504 Pattern = Ctx.getCanonicalTemplateArgument(Arg: Pattern);
2505 if (Arg.structurallyEquals(Other: Pattern))
2506 return true;
2507
2508 if (Pattern.getKind() == TemplateArgument::Expression) {
2509 if (auto *DRE =
2510 dyn_cast<DeclRefExpr>(Val: Pattern.getAsExpr()->IgnoreParenImpCasts())) {
2511 if (auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(Val: DRE->getDecl()))
2512 return NTTP->getDepth() == Depth && Args.size() > NTTP->getIndex() &&
2513 Args[NTTP->getIndex()].structurallyEquals(Other: Arg);
2514 }
2515 }
2516
2517 if (templateArgumentExpressionsEqual(Ctx, Pattern, Arg))
2518 return true;
2519
2520 if (Arg.getKind() != Pattern.getKind())
2521 return false;
2522
2523 if (Arg.getKind() == TemplateArgument::Type)
2524 return isSubstitutedType(Ctx, T: Arg.getAsType(), Pattern: Pattern.getAsType(), Args,
2525 Depth);
2526
2527 if (Arg.getKind() == TemplateArgument::Template) {
2528 TemplateDecl *PatTD = Pattern.getAsTemplate().getAsTemplateDecl();
2529 if (auto *TTPD = dyn_cast_or_null<TemplateTemplateParmDecl>(Val: PatTD))
2530 return TTPD->getDepth() == Depth && Args.size() > TTPD->getIndex() &&
2531 Ctx.getCanonicalTemplateArgument(Arg: Args[TTPD->getIndex()])
2532 .structurallyEquals(Other: Arg);
2533 }
2534
2535 // FIXME: Handle more cases.
2536 return false;
2537}
2538
2539bool clang::isSubstitutedDefaultArgument(ASTContext &Ctx, TemplateArgument Arg,
2540 const NamedDecl *Param,
2541 ArrayRef<TemplateArgument> Args,
2542 unsigned Depth) {
2543 // An empty pack is equivalent to not providing a pack argument.
2544 if (Arg.getKind() == TemplateArgument::Pack && Arg.pack_size() == 0)
2545 return true;
2546
2547 if (auto *TTPD = dyn_cast<TemplateTypeParmDecl>(Val: Param)) {
2548 return TTPD->hasDefaultArgument() &&
2549 isSubstitutedTemplateArgument(
2550 Ctx, Arg, Pattern: TTPD->getDefaultArgument().getArgument(), Args, Depth);
2551 } else if (auto *TTPD = dyn_cast<TemplateTemplateParmDecl>(Val: Param)) {
2552 return TTPD->hasDefaultArgument() &&
2553 isSubstitutedTemplateArgument(
2554 Ctx, Arg, Pattern: TTPD->getDefaultArgument().getArgument(), Args, Depth);
2555 } else if (auto *NTTPD = dyn_cast<NonTypeTemplateParmDecl>(Val: Param)) {
2556 return NTTPD->hasDefaultArgument() &&
2557 isSubstitutedTemplateArgument(
2558 Ctx, Arg, Pattern: NTTPD->getDefaultArgument().getArgument(), Args,
2559 Depth);
2560 }
2561 return false;
2562}
2563
2564template <typename TA>
2565static void
2566printTo(raw_ostream &OS, ArrayRef<TA> Args, const PrintingPolicy &Policy,
2567 const TemplateParameterList *TPL, bool IsPack, unsigned ParmIndex) {
2568 // Drop trailing template arguments that match default arguments.
2569 if (TPL && Policy.SuppressDefaultTemplateArgs && !Policy.PrintAsCanonical &&
2570 !Args.empty() && !IsPack && Args.size() <= TPL->size()) {
2571 llvm::SmallVector<TemplateArgument, 8> OrigArgs;
2572 for (const TA &A : Args)
2573 OrigArgs.push_back(Elt: getArgument(A));
2574 while (!Args.empty() && getArgument(Args.back()).getIsDefaulted())
2575 Args = Args.drop_back();
2576 }
2577
2578 const char *Comma = Policy.MSVCFormatting ? "," : ", ";
2579 if (!IsPack)
2580 OS << '<';
2581
2582 bool NeedSpace = false;
2583 bool FirstArg = true;
2584 for (const auto &Arg : Args) {
2585 // Print the argument into a string.
2586 SmallString<128> Buf;
2587 llvm::raw_svector_ostream ArgOS(Buf);
2588 const TemplateArgument &Argument = getArgument(Arg);
2589 if (Argument.getKind() == TemplateArgument::Pack) {
2590 if (Argument.pack_size() && !FirstArg)
2591 OS << Comma;
2592 printTo(OS&: ArgOS, Args: Argument.getPackAsArray(), Policy, TPL,
2593 /*IsPack*/ true, ParmIndex);
2594 } else {
2595 if (!FirstArg)
2596 OS << Comma;
2597 // Tries to print the argument with location info if exists.
2598 printArgument(Arg, Policy, ArgOS,
2599 TemplateParameterList::shouldIncludeTypeForArgument(
2600 Policy, TPL, Idx: ParmIndex));
2601 }
2602 StringRef ArgString = ArgOS.str();
2603
2604 // If this is the first argument and its string representation
2605 // begins with the global scope specifier ('::foo'), add a space
2606 // to avoid printing the diagraph '<:'.
2607 if (FirstArg && ArgString.starts_with(Prefix: ":"))
2608 OS << ' ';
2609
2610 OS << ArgString;
2611
2612 // If the last character of our string is '>', add another space to
2613 // keep the two '>''s separate tokens.
2614 if (!ArgString.empty()) {
2615 NeedSpace = Policy.SplitTemplateClosers && ArgString.back() == '>';
2616 FirstArg = false;
2617 }
2618
2619 // Use same template parameter for all elements of Pack
2620 if (!IsPack)
2621 ParmIndex++;
2622 }
2623
2624 if (!IsPack) {
2625 if (NeedSpace)
2626 OS << ' ';
2627 OS << '>';
2628 }
2629}
2630
2631void clang::printTemplateArgumentList(raw_ostream &OS,
2632 const TemplateArgumentListInfo &Args,
2633 const PrintingPolicy &Policy,
2634 const TemplateParameterList *TPL) {
2635 printTemplateArgumentList(OS, Args: Args.arguments(), Policy, TPL);
2636}
2637
2638void clang::printTemplateArgumentList(raw_ostream &OS,
2639 ArrayRef<TemplateArgument> Args,
2640 const PrintingPolicy &Policy,
2641 const TemplateParameterList *TPL) {
2642 PrintingPolicy InnerPolicy = Policy;
2643 InnerPolicy.SuppressScope = false;
2644 printTo(OS, Args, Policy: InnerPolicy, TPL, /*isPack*/ IsPack: false, /*parmIndex*/ ParmIndex: 0);
2645}
2646
2647void clang::printTemplateArgumentList(raw_ostream &OS,
2648 ArrayRef<TemplateArgumentLoc> Args,
2649 const PrintingPolicy &Policy,
2650 const TemplateParameterList *TPL) {
2651 PrintingPolicy InnerPolicy = Policy;
2652 InnerPolicy.SuppressScope = false;
2653 printTo(OS, Args, Policy: InnerPolicy, TPL, /*isPack*/ IsPack: false, /*parmIndex*/ ParmIndex: 0);
2654}
2655
2656std::string PointerAuthQualifier::getAsString() const {
2657 LangOptions LO;
2658 return getAsString(Policy: PrintingPolicy(LO));
2659}
2660
2661std::string PointerAuthQualifier::getAsString(const PrintingPolicy &P) const {
2662 SmallString<64> Buf;
2663 llvm::raw_svector_ostream StrOS(Buf);
2664 print(OS&: StrOS, Policy: P);
2665 return StrOS.str().str();
2666}
2667
2668bool PointerAuthQualifier::isEmptyWhenPrinted(const PrintingPolicy &P) const {
2669 return !isPresent();
2670}
2671
2672void PointerAuthQualifier::print(raw_ostream &OS,
2673 const PrintingPolicy &P) const {
2674 if (!isPresent())
2675 return;
2676
2677 OS << "__ptrauth(";
2678 OS << getKey();
2679 OS << "," << unsigned(isAddressDiscriminated()) << ","
2680 << getExtraDiscriminator() << ")";
2681}
2682
2683std::string Qualifiers::getAsString() const {
2684 LangOptions LO;
2685 return getAsString(Policy: PrintingPolicy(LO));
2686}
2687
2688// Appends qualifiers to the given string, separated by spaces. Will
2689// prefix a space if the string is non-empty. Will not append a final
2690// space.
2691std::string Qualifiers::getAsString(const PrintingPolicy &Policy) const {
2692 SmallString<64> Buf;
2693 llvm::raw_svector_ostream StrOS(Buf);
2694 print(OS&: StrOS, Policy);
2695 return std::string(StrOS.str());
2696}
2697
2698bool Qualifiers::isEmptyWhenPrinted(const PrintingPolicy &Policy) const {
2699 if (getCVRQualifiers())
2700 return false;
2701
2702 if (getAddressSpace() != LangAS::Default)
2703 return false;
2704
2705 if (getObjCGCAttr())
2706 return false;
2707
2708 if (Qualifiers::ObjCLifetime lifetime = getObjCLifetime())
2709 if (!(lifetime == Qualifiers::OCL_Strong && Policy.SuppressStrongLifetime))
2710 return false;
2711
2712 if (PointerAuthQualifier PointerAuth = getPointerAuth();
2713 PointerAuth && !PointerAuth.isEmptyWhenPrinted(P: Policy))
2714 return false;
2715
2716 return true;
2717}
2718
2719std::string Qualifiers::getAddrSpaceAsString(LangAS AS) {
2720 switch (AS) {
2721 case LangAS::Default:
2722 return "";
2723 case LangAS::opencl_global:
2724 case LangAS::sycl_global:
2725 return "__global";
2726 case LangAS::opencl_local:
2727 case LangAS::sycl_local:
2728 return "__local";
2729 case LangAS::opencl_private:
2730 case LangAS::sycl_private:
2731 return "__private";
2732 case LangAS::opencl_constant:
2733 return "__constant";
2734 case LangAS::opencl_generic:
2735 return "__generic";
2736 case LangAS::opencl_global_device:
2737 case LangAS::sycl_global_device:
2738 return "__global_device";
2739 case LangAS::opencl_global_host:
2740 case LangAS::sycl_global_host:
2741 return "__global_host";
2742 case LangAS::cuda_device:
2743 return "__device__";
2744 case LangAS::cuda_constant:
2745 return "__constant__";
2746 case LangAS::cuda_shared:
2747 return "__shared__";
2748 case LangAS::ptr32_sptr:
2749 return "__sptr __ptr32";
2750 case LangAS::ptr32_uptr:
2751 return "__uptr __ptr32";
2752 case LangAS::ptr64:
2753 return "__ptr64";
2754 case LangAS::hlsl_groupshared:
2755 return "groupshared";
2756 case LangAS::hlsl_constant:
2757 return "hlsl_constant";
2758 case LangAS::hlsl_private:
2759 return "hlsl_private";
2760 case LangAS::hlsl_device:
2761 return "hlsl_device";
2762 case LangAS::hlsl_input:
2763 return "hlsl_input";
2764 case LangAS::hlsl_output:
2765 return "hlsl_output";
2766 case LangAS::hlsl_push_constant:
2767 return "hlsl_push_constant";
2768 case LangAS::wasm_funcref:
2769 return "__funcref";
2770 case LangAS::amdgpu_barrier:
2771 return "amdgpu_barrier";
2772 default:
2773 return std::to_string(val: toTargetAddressSpace(AS));
2774 }
2775}
2776
2777// Appends qualifiers to the given string, separated by spaces. Will
2778// prefix a space if the string is non-empty. Will not append a final
2779// space.
2780void Qualifiers::print(raw_ostream &OS, const PrintingPolicy& Policy,
2781 bool appendSpaceIfNonEmpty) const {
2782 bool addSpace = false;
2783
2784 unsigned quals = getCVRQualifiers();
2785 if (quals) {
2786 AppendTypeQualList(OS, TypeQuals: quals, HasRestrictKeyword: Policy.Restrict);
2787 addSpace = true;
2788 }
2789 if (hasUnaligned()) {
2790 if (addSpace)
2791 OS << ' ';
2792 OS << "__unaligned";
2793 addSpace = true;
2794 }
2795 auto ASStr = getAddrSpaceAsString(AS: getAddressSpace());
2796 if (!ASStr.empty()) {
2797 if (addSpace)
2798 OS << ' ';
2799 addSpace = true;
2800 // Wrap target address space into an attribute syntax
2801 if (isTargetAddressSpace(AS: getAddressSpace()))
2802 OS << "__attribute__((address_space(" << ASStr << ")))";
2803 else
2804 OS << ASStr;
2805 }
2806
2807 if (Qualifiers::GC gc = getObjCGCAttr()) {
2808 if (addSpace)
2809 OS << ' ';
2810 addSpace = true;
2811 if (gc == Qualifiers::Weak)
2812 OS << "__weak";
2813 else
2814 OS << "__strong";
2815 }
2816 if (Qualifiers::ObjCLifetime lifetime = getObjCLifetime()) {
2817 if (!(lifetime == Qualifiers::OCL_Strong && Policy.SuppressStrongLifetime)){
2818 if (addSpace)
2819 OS << ' ';
2820 addSpace = true;
2821 }
2822
2823 switch (lifetime) {
2824 case Qualifiers::OCL_None: llvm_unreachable("none but true");
2825 case Qualifiers::OCL_ExplicitNone: OS << "__unsafe_unretained"; break;
2826 case Qualifiers::OCL_Strong:
2827 if (!Policy.SuppressStrongLifetime)
2828 OS << "__strong";
2829 break;
2830
2831 case Qualifiers::OCL_Weak: OS << "__weak"; break;
2832 case Qualifiers::OCL_Autoreleasing: OS << "__autoreleasing"; break;
2833 }
2834 }
2835
2836 if (PointerAuthQualifier PointerAuth = getPointerAuth()) {
2837 if (addSpace)
2838 OS << ' ';
2839 addSpace = true;
2840
2841 PointerAuth.print(OS, P: Policy);
2842 }
2843
2844 if (appendSpaceIfNonEmpty && addSpace)
2845 OS << ' ';
2846}
2847
2848std::string QualType::getAsString() const {
2849 return getAsString(split: split(), Policy: LangOptions());
2850}
2851
2852std::string QualType::getAsString(const PrintingPolicy &Policy) const {
2853 std::string S;
2854 getAsStringInternal(Str&: S, Policy);
2855 return S;
2856}
2857
2858std::string QualType::getAsString(const Type *ty, Qualifiers qs,
2859 const PrintingPolicy &Policy) {
2860 std::string buffer;
2861 getAsStringInternal(ty, qs, out&: buffer, policy: Policy);
2862 return buffer;
2863}
2864
2865void QualType::print(raw_ostream &OS, const PrintingPolicy &Policy,
2866 const Twine &PlaceHolder, unsigned Indentation) const {
2867 print(split: splitAccordingToPolicy(QT: *this, Policy), OS, policy: Policy, PlaceHolder,
2868 Indentation);
2869}
2870
2871void QualType::print(const Type *ty, Qualifiers qs,
2872 raw_ostream &OS, const PrintingPolicy &policy,
2873 const Twine &PlaceHolder, unsigned Indentation) {
2874 SmallString<128> PHBuf;
2875 StringRef PH = PlaceHolder.toStringRef(Out&: PHBuf);
2876
2877 TypePrinter(policy, Indentation).print(T: ty, Quals: qs, OS, PlaceHolder: PH);
2878}
2879
2880void QualType::getAsStringInternal(std::string &Str,
2881 const PrintingPolicy &Policy) const {
2882 return getAsStringInternal(split: splitAccordingToPolicy(QT: *this, Policy), out&: Str,
2883 policy: Policy);
2884}
2885
2886void QualType::getAsStringInternal(const Type *ty, Qualifiers qs,
2887 std::string &buffer,
2888 const PrintingPolicy &policy) {
2889 SmallString<256> Buf;
2890 llvm::raw_svector_ostream StrOS(Buf);
2891 TypePrinter(policy).print(T: ty, Quals: qs, OS&: StrOS, PlaceHolder: buffer);
2892 std::string str = std::string(StrOS.str());
2893 buffer.swap(s&: str);
2894}
2895
2896raw_ostream &clang::operator<<(raw_ostream &OS, QualType QT) {
2897 SplitQualType S = QT.split();
2898 TypePrinter(LangOptions()).print(T: S.Ty, Quals: S.Quals, OS, /*PlaceHolder=*/"");
2899 return OS;
2900}
2901