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

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