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->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->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->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->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->getElementType(), OS);
529}
530
531void TypePrinter::printConstantArrayAfter(const ConstantArrayType *T,
532 raw_ostream &OS) {
533 OS << '[';
534 if (T->getIndexTypeQualifiers().hasQualifiers()) {
535 AppendTypeQualList(OS, T->getIndexTypeCVRQualifiers(),
536 Policy.Restrict);
537 OS << ' ';
538 }
539
540 if (T->getSizeModifier() == ArraySizeModifier::Static)
541 OS << "static ";
542
543 OS << T->getZExtSize() << ']';
544 printAfter(T->getElementType(), OS);
545}
546
547void TypePrinter::printIncompleteArrayBefore(const IncompleteArrayType *T,
548 raw_ostream &OS) {
549 IncludeStrongLifetimeRAII Strong(Policy);
550 printBefore(T->getElementType(), OS);
551}
552
553void TypePrinter::printIncompleteArrayAfter(const IncompleteArrayType *T,
554 raw_ostream &OS) {
555 OS << "[]";
556 printAfter(T->getElementType(), OS);
557}
558
559void TypePrinter::printVariableArrayBefore(const VariableArrayType *T,
560 raw_ostream &OS) {
561 IncludeStrongLifetimeRAII Strong(Policy);
562 printBefore(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, T->getIndexTypeCVRQualifiers(), 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, nullptr, Policy);
580 OS << ']';
581
582 printAfter(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->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, nullptr, Policy);
627 OS << ']';
628 printAfter(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, 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, nullptr, Policy);
660 OS << ">";
661 } else {
662 OS << " __attribute__((ext_vector_type(";
663 if (T->getSizeExpr())
664 T->getSizeExpr()->printPretty(OS, 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, 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, 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, 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, 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, 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->getElementType(), OS);
837}
838
839void TypePrinter::printExtVectorAfter(const ExtVectorType *T, raw_ostream &OS) {
840 printAfter(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->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->getElementType(), OS);
864}
865
866void TypePrinter::printDependentSizedMatrixBefore(
867 const DependentSizedMatrixType *T, raw_ostream &OS) {
868 printBefore(T->getElementType(), OS);
869 OS << " __attribute__((matrix_type(";
870 if (T->getRowExpr()) {
871 T->getRowExpr()->printPretty(OS, nullptr, Policy);
872 }
873 OS << ", ";
874 if (T->getColumnExpr()) {
875 T->getColumnExpr()->printPretty(OS, nullptr, Policy);
876 }
877 OS << ")))";
878}
879
880void TypePrinter::printDependentSizedMatrixAfter(
881 const DependentSizedMatrixType *T, raw_ostream &OS) {
882 printAfter(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, 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->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, 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->getReturnType(), OS, StringRef());
1059 } else
1060 printAfter(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->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->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(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(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, 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, nullptr, 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, 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->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 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->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->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->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, 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, TemplateArgs.asArray(), Policy,
1458 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(OS, 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 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(PNA->getTypedefType()->getAsCXXRecordDecl(),
1573 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>(T))
1579 return printTypeSpec(TT->getDecl(), OS);
1580 if (auto *TST = dyn_cast<TemplateSpecializationType>(T))
1581 return printTemplateId(TST, OS, /*FullyQualify=*/true);
1582 T = T->getLocallyUnqualifiedSingleStepDesugaredType();
1583 }
1584 }
1585 }
1586
1587 printTag(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(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->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(OS, 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, nullptr, Policy);
1835 OS << ')';
1836}
1837
1838void TypePrinter::printCountAttributedBefore(const CountAttributedType *T,
1839 raw_ostream &OS) {
1840 printBefore(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->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::AddressSpace)
1865 printBefore(T: T->getEquivalentType(), OS);
1866 else
1867 printBefore(T: T->getModifiedType(), OS);
1868
1869 if (T->isMSTypeSpec()) {
1870 switch (T->getAttrKind()) {
1871 default: return;
1872 case attr::Ptr32: OS << " __ptr32"; break;
1873 case attr::Ptr64: OS << " __ptr64"; break;
1874 case attr::SPtr: OS << " __sptr"; break;
1875 case attr::UPtr: OS << " __uptr"; break;
1876 }
1877 spaceBeforePlaceHolder(OS);
1878 }
1879
1880 if (T->isWebAssemblyFuncrefSpec())
1881 OS << "__funcref";
1882
1883 // Print nullability type specifiers.
1884 if (T->getImmediateNullability()) {
1885 if (T->getAttrKind() == attr::TypeNonNull)
1886 OS << " _Nonnull";
1887 else if (T->getAttrKind() == attr::TypeNullable)
1888 OS << " _Nullable";
1889 else if (T->getAttrKind() == attr::TypeNullUnspecified)
1890 OS << " _Null_unspecified";
1891 else if (T->getAttrKind() == attr::TypeNullableResult)
1892 OS << " _Nullable_result";
1893 else
1894 llvm_unreachable("unhandled nullability");
1895 spaceBeforePlaceHolder(OS);
1896 }
1897}
1898
1899void TypePrinter::printAttributedAfter(const AttributedType *T,
1900 raw_ostream &OS) {
1901 // FIXME: Generate this with TableGen.
1902
1903 // Prefer the macro forms of the GC and ownership qualifiers.
1904 if (T->getAttrKind() == attr::ObjCGC ||
1905 T->getAttrKind() == attr::ObjCOwnership)
1906 return printAfter(t: T->getEquivalentType(), OS);
1907
1908 // If this is a calling convention attribute, don't print the implicit CC from
1909 // the modified type.
1910 SaveAndRestore MaybeSuppressCC(InsideCCAttribute, T->isCallingConv());
1911
1912 printAfter(t: T->getModifiedType(), OS);
1913
1914 // Some attributes are printed as qualifiers before the type, so we have
1915 // nothing left to do.
1916 if (T->getAttrKind() == attr::ObjCKindOf || T->isMSTypeSpec() ||
1917 T->getImmediateNullability() || T->isWebAssemblyFuncrefSpec())
1918 return;
1919
1920 // Don't print the inert __unsafe_unretained attribute at all.
1921 if (T->getAttrKind() == attr::ObjCInertUnsafeUnretained)
1922 return;
1923
1924 // Don't print ns_returns_retained unless it had an effect.
1925 if (T->getAttrKind() == attr::NSReturnsRetained &&
1926 !T->getEquivalentType()->castAs<FunctionType>()
1927 ->getExtInfo().getProducesResult())
1928 return;
1929
1930 if (T->getAttrKind() == attr::LifetimeBound) {
1931 OS << " [[clang::lifetimebound]]";
1932 return;
1933 }
1934 if (T->getAttrKind() == attr::LifetimeCaptureBy) {
1935 OS << " [[clang::lifetime_capture_by(";
1936 if (auto *attr = dyn_cast_or_null<LifetimeCaptureByAttr>(T->getAttr()))
1937 llvm::interleaveComma(attr->getArgIdents(), OS,
1938 [&](auto it) { OS << it->getName(); });
1939 OS << ")]]";
1940 return;
1941 }
1942
1943 // The printing of the address_space attribute is handled by the qualifier
1944 // since it is still stored in the qualifier. Return early to prevent printing
1945 // this twice.
1946 if (T->getAttrKind() == attr::AddressSpace)
1947 return;
1948
1949 if (T->getAttrKind() == attr::AnnotateType) {
1950 // FIXME: Print the attribute arguments once we have a way to retrieve these
1951 // here. For the meantime, we just print `[[clang::annotate_type(...)]]`
1952 // without the arguments so that we know at least that we had _some_
1953 // annotation on the type.
1954 OS << " [[clang::annotate_type(...)]]";
1955 return;
1956 }
1957
1958 if (T->getAttrKind() == attr::ArmStreaming) {
1959 OS << "__arm_streaming";
1960 return;
1961 }
1962 if (T->getAttrKind() == attr::ArmStreamingCompatible) {
1963 OS << "__arm_streaming_compatible";
1964 return;
1965 }
1966
1967 if (T->getAttrKind() == attr::SwiftAttr) {
1968 if (auto *swiftAttr = dyn_cast_or_null<SwiftAttrAttr>(T->getAttr())) {
1969 OS << " __attribute__((swift_attr(\"" << swiftAttr->getAttribute()
1970 << "\")))";
1971 }
1972 return;
1973 }
1974
1975 OS << " __attribute__((";
1976 switch (T->getAttrKind()) {
1977#define TYPE_ATTR(NAME)
1978#define DECL_OR_TYPE_ATTR(NAME)
1979#define ATTR(NAME) case attr::NAME:
1980#include "clang/Basic/AttrList.inc"
1981 llvm_unreachable("non-type attribute attached to type");
1982
1983 case attr::BTFTypeTag:
1984 llvm_unreachable("BTFTypeTag attribute handled separately");
1985
1986 case attr::HLSLResourceClass:
1987 case attr::HLSLROV:
1988 case attr::HLSLRawBuffer:
1989 case attr::HLSLContainedType:
1990 llvm_unreachable("HLSL resource type attributes handled separately");
1991
1992 case attr::OpenCLPrivateAddressSpace:
1993 case attr::OpenCLGlobalAddressSpace:
1994 case attr::OpenCLGlobalDeviceAddressSpace:
1995 case attr::OpenCLGlobalHostAddressSpace:
1996 case attr::OpenCLLocalAddressSpace:
1997 case attr::OpenCLConstantAddressSpace:
1998 case attr::OpenCLGenericAddressSpace:
1999 case attr::HLSLGroupSharedAddressSpace:
2000 // FIXME: Update printAttributedBefore to print these once we generate
2001 // AttributedType nodes for them.
2002 break;
2003
2004 case attr::CountedBy:
2005 case attr::CountedByOrNull:
2006 case attr::SizedBy:
2007 case attr::SizedByOrNull:
2008 case attr::LifetimeBound:
2009 case attr::LifetimeCaptureBy:
2010 case attr::TypeNonNull:
2011 case attr::TypeNullable:
2012 case attr::TypeNullableResult:
2013 case attr::TypeNullUnspecified:
2014 case attr::ObjCGC:
2015 case attr::ObjCInertUnsafeUnretained:
2016 case attr::ObjCKindOf:
2017 case attr::ObjCOwnership:
2018 case attr::Ptr32:
2019 case attr::Ptr64:
2020 case attr::SPtr:
2021 case attr::UPtr:
2022 case attr::PointerAuth:
2023 case attr::AddressSpace:
2024 case attr::CmseNSCall:
2025 case attr::AnnotateType:
2026 case attr::WebAssemblyFuncref:
2027 case attr::ArmAgnostic:
2028 case attr::ArmStreaming:
2029 case attr::ArmStreamingCompatible:
2030 case attr::ArmIn:
2031 case attr::ArmOut:
2032 case attr::ArmInOut:
2033 case attr::ArmPreserves:
2034 case attr::NonBlocking:
2035 case attr::NonAllocating:
2036 case attr::Blocking:
2037 case attr::Allocating:
2038 case attr::SwiftAttr:
2039 llvm_unreachable("This attribute should have been handled already");
2040
2041 case attr::NSReturnsRetained:
2042 OS << "ns_returns_retained";
2043 break;
2044
2045 // FIXME: When Sema learns to form this AttributedType, avoid printing the
2046 // attribute again in printFunctionProtoAfter.
2047 case attr::AnyX86NoCfCheck: OS << "nocf_check"; break;
2048 case attr::CDecl: OS << "cdecl"; break;
2049 case attr::FastCall: OS << "fastcall"; break;
2050 case attr::StdCall: OS << "stdcall"; break;
2051 case attr::ThisCall: OS << "thiscall"; break;
2052 case attr::SwiftCall: OS << "swiftcall"; break;
2053 case attr::SwiftAsyncCall: OS << "swiftasynccall"; break;
2054 case attr::VectorCall: OS << "vectorcall"; break;
2055 case attr::Pascal: OS << "pascal"; break;
2056 case attr::MSABI: OS << "ms_abi"; break;
2057 case attr::SysVABI: OS << "sysv_abi"; break;
2058 case attr::RegCall: OS << "regcall"; break;
2059 case attr::Pcs: {
2060 OS << "pcs(";
2061 QualType t = T->getEquivalentType();
2062 while (!t->isFunctionType())
2063 t = t->getPointeeType();
2064 OS << (t->castAs<FunctionType>()->getCallConv() == CC_AAPCS ?
2065 "\"aapcs\"" : "\"aapcs-vfp\"");
2066 OS << ')';
2067 break;
2068 }
2069 case attr::AArch64VectorPcs: OS << "aarch64_vector_pcs"; break;
2070 case attr::AArch64SVEPcs: OS << "aarch64_sve_pcs"; break;
2071 case attr::DeviceKernel:
2072 OS << T->getAttr()->getSpelling();
2073 break;
2074 case attr::IntelOclBicc: OS << "inteloclbicc"; break;
2075 case attr::PreserveMost:
2076 OS << "preserve_most";
2077 break;
2078
2079 case attr::PreserveAll:
2080 OS << "preserve_all";
2081 break;
2082 case attr::M68kRTD:
2083 OS << "m68k_rtd";
2084 break;
2085 case attr::PreserveNone:
2086 OS << "preserve_none";
2087 break;
2088 case attr::RISCVVectorCC:
2089 OS << "riscv_vector_cc";
2090 break;
2091 case attr::RISCVVLSCC:
2092 OS << "riscv_vls_cc";
2093 break;
2094 case attr::NoDeref:
2095 OS << "noderef";
2096 break;
2097 case attr::CFIUncheckedCallee:
2098 OS << "cfi_unchecked_callee";
2099 break;
2100 case attr::AcquireHandle:
2101 OS << "acquire_handle";
2102 break;
2103 case attr::ArmMveStrictPolymorphism:
2104 OS << "__clang_arm_mve_strict_polymorphism";
2105 break;
2106 case attr::ExtVectorType:
2107 OS << "ext_vector_type";
2108 break;
2109 }
2110 OS << "))";
2111}
2112
2113void TypePrinter::printBTFTagAttributedBefore(const BTFTagAttributedType *T,
2114 raw_ostream &OS) {
2115 printBefore(T: T->getWrappedType(), OS);
2116 OS << " __attribute__((btf_type_tag(\"" << T->getAttr()->getBTFTypeTag() << "\")))";
2117}
2118
2119void TypePrinter::printBTFTagAttributedAfter(const BTFTagAttributedType *T,
2120 raw_ostream &OS) {
2121 printAfter(t: T->getWrappedType(), OS);
2122}
2123
2124void TypePrinter::printHLSLAttributedResourceBefore(
2125 const HLSLAttributedResourceType *T, raw_ostream &OS) {
2126 printBefore(T: T->getWrappedType(), OS);
2127}
2128
2129void TypePrinter::printHLSLAttributedResourceAfter(
2130 const HLSLAttributedResourceType *T, raw_ostream &OS) {
2131 printAfter(t: T->getWrappedType(), OS);
2132 const HLSLAttributedResourceType::Attributes &Attrs = T->getAttrs();
2133 OS << " [[hlsl::resource_class("
2134 << HLSLResourceClassAttr::ConvertResourceClassToStr(Attrs.ResourceClass)
2135 << ")]]";
2136 if (Attrs.IsROV)
2137 OS << " [[hlsl::is_rov]]";
2138 if (Attrs.RawBuffer)
2139 OS << " [[hlsl::raw_buffer]]";
2140
2141 QualType ContainedTy = T->getContainedType();
2142 if (!ContainedTy.isNull()) {
2143 OS << " [[hlsl::contained_type(";
2144 printBefore(T: ContainedTy, OS);
2145 printAfter(t: ContainedTy, OS);
2146 OS << ")]]";
2147 }
2148}
2149
2150void TypePrinter::printHLSLInlineSpirvBefore(const HLSLInlineSpirvType *T,
2151 raw_ostream &OS) {
2152 OS << "__hlsl_spirv_type<" << T->getOpcode();
2153
2154 OS << ", " << T->getSize();
2155 OS << ", " << T->getAlignment();
2156
2157 for (auto &Operand : T->getOperands()) {
2158 using SpirvOperandKind = SpirvOperand::SpirvOperandKind;
2159
2160 OS << ", ";
2161 switch (Operand.getKind()) {
2162 case SpirvOperandKind::ConstantId: {
2163 QualType ConstantType = Operand.getResultType();
2164 OS << "vk::integral_constant<";
2165 printBefore(T: ConstantType, OS);
2166 printAfter(t: ConstantType, OS);
2167 OS << ", ";
2168 OS << Operand.getValue();
2169 OS << ">";
2170 break;
2171 }
2172 case SpirvOperandKind::Literal:
2173 OS << "vk::Literal<vk::integral_constant<uint, ";
2174 OS << Operand.getValue();
2175 OS << ">>";
2176 break;
2177 case SpirvOperandKind::TypeId: {
2178 QualType Type = Operand.getResultType();
2179 printBefore(T: Type, OS);
2180 printAfter(t: Type, OS);
2181 break;
2182 }
2183 default:
2184 llvm_unreachable("Invalid SpirvOperand kind!");
2185 break;
2186 }
2187 }
2188
2189 OS << ">";
2190}
2191
2192void TypePrinter::printHLSLInlineSpirvAfter(const HLSLInlineSpirvType *T,
2193 raw_ostream &OS) {
2194 // nothing to do
2195}
2196
2197void TypePrinter::printObjCInterfaceBefore(const ObjCInterfaceType *T,
2198 raw_ostream &OS) {
2199 OS << T->getDecl()->getName();
2200 spaceBeforePlaceHolder(OS);
2201}
2202
2203void TypePrinter::printObjCInterfaceAfter(const ObjCInterfaceType *T,
2204 raw_ostream &OS) {}
2205
2206void TypePrinter::printObjCTypeParamBefore(const ObjCTypeParamType *T,
2207 raw_ostream &OS) {
2208 OS << T->getDecl()->getName();
2209 if (!T->qual_empty()) {
2210 bool isFirst = true;
2211 OS << '<';
2212 for (const auto *I : T->quals()) {
2213 if (isFirst)
2214 isFirst = false;
2215 else
2216 OS << ',';
2217 OS << I->getName();
2218 }
2219 OS << '>';
2220 }
2221
2222 spaceBeforePlaceHolder(OS);
2223}
2224
2225void TypePrinter::printObjCTypeParamAfter(const ObjCTypeParamType *T,
2226 raw_ostream &OS) {}
2227
2228void TypePrinter::printObjCObjectBefore(const ObjCObjectType *T,
2229 raw_ostream &OS) {
2230 if (T->qual_empty() && T->isUnspecializedAsWritten() &&
2231 !T->isKindOfTypeAsWritten())
2232 return printBefore(T: T->getBaseType(), OS);
2233
2234 if (T->isKindOfTypeAsWritten())
2235 OS << "__kindof ";
2236
2237 print(t: T->getBaseType(), OS, PlaceHolder: StringRef());
2238
2239 if (T->isSpecializedAsWritten()) {
2240 bool isFirst = true;
2241 OS << '<';
2242 for (auto typeArg : T->getTypeArgsAsWritten()) {
2243 if (isFirst)
2244 isFirst = false;
2245 else
2246 OS << ",";
2247
2248 print(t: typeArg, OS, PlaceHolder: StringRef());
2249 }
2250 OS << '>';
2251 }
2252
2253 if (!T->qual_empty()) {
2254 bool isFirst = true;
2255 OS << '<';
2256 for (const auto *I : T->quals()) {
2257 if (isFirst)
2258 isFirst = false;
2259 else
2260 OS << ',';
2261 OS << I->getName();
2262 }
2263 OS << '>';
2264 }
2265
2266 spaceBeforePlaceHolder(OS);
2267}
2268
2269void TypePrinter::printObjCObjectAfter(const ObjCObjectType *T,
2270 raw_ostream &OS) {
2271 if (T->qual_empty() && T->isUnspecializedAsWritten() &&
2272 !T->isKindOfTypeAsWritten())
2273 return printAfter(t: T->getBaseType(), OS);
2274}
2275
2276void TypePrinter::printObjCObjectPointerBefore(const ObjCObjectPointerType *T,
2277 raw_ostream &OS) {
2278 printBefore(T: T->getPointeeType(), OS);
2279
2280 // If we need to print the pointer, print it now.
2281 if (!T->isObjCIdType() && !T->isObjCQualifiedIdType() &&
2282 !T->isObjCClassType() && !T->isObjCQualifiedClassType()) {
2283 if (HasEmptyPlaceHolder)
2284 OS << ' ';
2285 OS << '*';
2286 }
2287}
2288
2289void TypePrinter::printObjCObjectPointerAfter(const ObjCObjectPointerType *T,
2290 raw_ostream &OS) {}
2291
2292static
2293const TemplateArgument &getArgument(const TemplateArgument &A) { return A; }
2294
2295static const TemplateArgument &getArgument(const TemplateArgumentLoc &A) {
2296 return A.getArgument();
2297}
2298
2299static void printArgument(const TemplateArgument &A, const PrintingPolicy &PP,
2300 llvm::raw_ostream &OS, bool IncludeType) {
2301 A.print(Policy: PP, Out&: OS, IncludeType);
2302}
2303
2304static void printArgument(const TemplateArgumentLoc &A,
2305 const PrintingPolicy &PP, llvm::raw_ostream &OS,
2306 bool IncludeType) {
2307 const TemplateArgument::ArgKind &Kind = A.getArgument().getKind();
2308 if (Kind == TemplateArgument::ArgKind::Type)
2309 return A.getTypeSourceInfo()->getType().print(OS, Policy: PP);
2310 return A.getArgument().print(Policy: PP, Out&: OS, IncludeType);
2311}
2312
2313static bool isSubstitutedTemplateArgument(ASTContext &Ctx, TemplateArgument Arg,
2314 TemplateArgument Pattern,
2315 ArrayRef<TemplateArgument> Args,
2316 unsigned Depth);
2317
2318static bool isSubstitutedType(ASTContext &Ctx, QualType T, QualType Pattern,
2319 ArrayRef<TemplateArgument> Args, unsigned Depth) {
2320 if (Ctx.hasSameType(T1: T, T2: Pattern))
2321 return true;
2322
2323 // A type parameter matches its argument.
2324 if (auto *TTPT = Pattern->getAs<TemplateTypeParmType>()) {
2325 if (TTPT->getDepth() == Depth && TTPT->getIndex() < Args.size() &&
2326 Args[TTPT->getIndex()].getKind() == TemplateArgument::Type) {
2327 QualType SubstArg = Ctx.getQualifiedType(
2328 T: Args[TTPT->getIndex()].getAsType(), Qs: Pattern.getQualifiers());
2329 return Ctx.hasSameType(T1: SubstArg, T2: T);
2330 }
2331 return false;
2332 }
2333
2334 // FIXME: Recurse into array types.
2335
2336 // All other cases will need the types to be identically qualified.
2337 Qualifiers TQual, PatQual;
2338 T = Ctx.getUnqualifiedArrayType(T, Quals&: TQual);
2339 Pattern = Ctx.getUnqualifiedArrayType(T: Pattern, Quals&: PatQual);
2340 if (TQual != PatQual)
2341 return false;
2342
2343 // Recurse into pointer-like types.
2344 {
2345 QualType TPointee = T->getPointeeType();
2346 QualType PPointee = Pattern->getPointeeType();
2347 if (!TPointee.isNull() && !PPointee.isNull())
2348 return T->getTypeClass() == Pattern->getTypeClass() &&
2349 isSubstitutedType(Ctx, T: TPointee, Pattern: PPointee, Args, Depth);
2350 }
2351
2352 // Recurse into template specialization types.
2353 if (auto *PTST =
2354 Pattern.getCanonicalType()->getAs<TemplateSpecializationType>()) {
2355 TemplateName Template;
2356 ArrayRef<TemplateArgument> TemplateArgs;
2357 if (auto *TTST = T->getAs<TemplateSpecializationType>()) {
2358 Template = TTST->getTemplateName();
2359 TemplateArgs = TTST->template_arguments();
2360 } else if (auto *CTSD = dyn_cast_or_null<ClassTemplateSpecializationDecl>(
2361 Val: T->getAsCXXRecordDecl())) {
2362 Template = TemplateName(CTSD->getSpecializedTemplate());
2363 TemplateArgs = CTSD->getTemplateArgs().asArray();
2364 } else {
2365 return false;
2366 }
2367
2368 if (!isSubstitutedTemplateArgument(Ctx, Arg: Template, Pattern: PTST->getTemplateName(),
2369 Args, Depth))
2370 return false;
2371 if (TemplateArgs.size() != PTST->template_arguments().size())
2372 return false;
2373 for (unsigned I = 0, N = TemplateArgs.size(); I != N; ++I)
2374 if (!isSubstitutedTemplateArgument(
2375 Ctx, Arg: TemplateArgs[I], Pattern: PTST->template_arguments()[I], Args, Depth))
2376 return false;
2377 return true;
2378 }
2379
2380 // FIXME: Handle more cases.
2381 return false;
2382}
2383
2384/// Evaluates the expression template argument 'Pattern' and returns true
2385/// if 'Arg' evaluates to the same result.
2386static bool templateArgumentExpressionsEqual(ASTContext const &Ctx,
2387 TemplateArgument const &Pattern,
2388 TemplateArgument const &Arg) {
2389 if (Pattern.getKind() != TemplateArgument::Expression)
2390 return false;
2391
2392 // Can't evaluate value-dependent expressions so bail early
2393 Expr const *pattern_expr = Pattern.getAsExpr();
2394 if (pattern_expr->isValueDependent() ||
2395 !pattern_expr->isIntegerConstantExpr(Ctx))
2396 return false;
2397
2398 if (Arg.getKind() == TemplateArgument::Integral)
2399 return llvm::APSInt::isSameValue(I1: pattern_expr->EvaluateKnownConstInt(Ctx),
2400 I2: Arg.getAsIntegral());
2401
2402 if (Arg.getKind() == TemplateArgument::Expression) {
2403 Expr const *args_expr = Arg.getAsExpr();
2404 if (args_expr->isValueDependent() || !args_expr->isIntegerConstantExpr(Ctx))
2405 return false;
2406
2407 return llvm::APSInt::isSameValue(I1: args_expr->EvaluateKnownConstInt(Ctx),
2408 I2: pattern_expr->EvaluateKnownConstInt(Ctx));
2409 }
2410
2411 return false;
2412}
2413
2414static bool isSubstitutedTemplateArgument(ASTContext &Ctx, TemplateArgument Arg,
2415 TemplateArgument Pattern,
2416 ArrayRef<TemplateArgument> Args,
2417 unsigned Depth) {
2418 Arg = Ctx.getCanonicalTemplateArgument(Arg);
2419 Pattern = Ctx.getCanonicalTemplateArgument(Arg: Pattern);
2420 if (Arg.structurallyEquals(Other: Pattern))
2421 return true;
2422
2423 if (Pattern.getKind() == TemplateArgument::Expression) {
2424 if (auto *DRE =
2425 dyn_cast<DeclRefExpr>(Val: Pattern.getAsExpr()->IgnoreParenImpCasts())) {
2426 if (auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(Val: DRE->getDecl()))
2427 return NTTP->getDepth() == Depth && Args.size() > NTTP->getIndex() &&
2428 Args[NTTP->getIndex()].structurallyEquals(Arg);
2429 }
2430 }
2431
2432 if (templateArgumentExpressionsEqual(Ctx, Pattern, Arg))
2433 return true;
2434
2435 if (Arg.getKind() != Pattern.getKind())
2436 return false;
2437
2438 if (Arg.getKind() == TemplateArgument::Type)
2439 return isSubstitutedType(Ctx, T: Arg.getAsType(), Pattern: Pattern.getAsType(), Args,
2440 Depth);
2441
2442 if (Arg.getKind() == TemplateArgument::Template) {
2443 TemplateDecl *PatTD = Pattern.getAsTemplate().getAsTemplateDecl();
2444 if (auto *TTPD = dyn_cast_or_null<TemplateTemplateParmDecl>(Val: PatTD))
2445 return TTPD->getDepth() == Depth && Args.size() > TTPD->getIndex() &&
2446 Ctx.getCanonicalTemplateArgument(Arg: Args[TTPD->getIndex()])
2447 .structurallyEquals(Arg);
2448 }
2449
2450 // FIXME: Handle more cases.
2451 return false;
2452}
2453
2454bool clang::isSubstitutedDefaultArgument(ASTContext &Ctx, TemplateArgument Arg,
2455 const NamedDecl *Param,
2456 ArrayRef<TemplateArgument> Args,
2457 unsigned Depth) {
2458 // An empty pack is equivalent to not providing a pack argument.
2459 if (Arg.getKind() == TemplateArgument::Pack && Arg.pack_size() == 0)
2460 return true;
2461
2462 if (auto *TTPD = dyn_cast<TemplateTypeParmDecl>(Val: Param)) {
2463 return TTPD->hasDefaultArgument() &&
2464 isSubstitutedTemplateArgument(
2465 Ctx, Arg, Pattern: TTPD->getDefaultArgument().getArgument(), Args, Depth);
2466 } else if (auto *TTPD = dyn_cast<TemplateTemplateParmDecl>(Val: Param)) {
2467 return TTPD->hasDefaultArgument() &&
2468 isSubstitutedTemplateArgument(
2469 Ctx, Arg, Pattern: TTPD->getDefaultArgument().getArgument(), Args, Depth);
2470 } else if (auto *NTTPD = dyn_cast<NonTypeTemplateParmDecl>(Val: Param)) {
2471 return NTTPD->hasDefaultArgument() &&
2472 isSubstitutedTemplateArgument(
2473 Ctx, Arg, Pattern: NTTPD->getDefaultArgument().getArgument(), Args,
2474 Depth);
2475 }
2476 return false;
2477}
2478
2479template <typename TA>
2480static void
2481printTo(raw_ostream &OS, ArrayRef<TA> Args, const PrintingPolicy &Policy,
2482 const TemplateParameterList *TPL, bool IsPack, unsigned ParmIndex) {
2483 // Drop trailing template arguments that match default arguments.
2484 if (TPL && Policy.SuppressDefaultTemplateArgs && !Policy.PrintAsCanonical &&
2485 !Args.empty() && !IsPack && Args.size() <= TPL->size()) {
2486 llvm::SmallVector<TemplateArgument, 8> OrigArgs;
2487 for (const TA &A : Args)
2488 OrigArgs.push_back(Elt: getArgument(A));
2489 while (!Args.empty() && getArgument(Args.back()).getIsDefaulted())
2490 Args = Args.drop_back();
2491 }
2492
2493 const char *Comma = Policy.MSVCFormatting ? "," : ", ";
2494 if (!IsPack)
2495 OS << '<';
2496
2497 bool NeedSpace = false;
2498 bool FirstArg = true;
2499 for (const auto &Arg : Args) {
2500 // Print the argument into a string.
2501 SmallString<128> Buf;
2502 llvm::raw_svector_ostream ArgOS(Buf);
2503 const TemplateArgument &Argument = getArgument(Arg);
2504 if (Argument.getKind() == TemplateArgument::Pack) {
2505 if (Argument.pack_size() && !FirstArg)
2506 OS << Comma;
2507 printTo(OS&: ArgOS, Args: Argument.getPackAsArray(), Policy, TPL,
2508 /*IsPack*/ true, ParmIndex);
2509 } else {
2510 if (!FirstArg)
2511 OS << Comma;
2512 // Tries to print the argument with location info if exists.
2513 printArgument(Arg, Policy, ArgOS,
2514 TemplateParameterList::shouldIncludeTypeForArgument(
2515 Policy, TPL, Idx: ParmIndex));
2516 }
2517 StringRef ArgString = ArgOS.str();
2518
2519 // If this is the first argument and its string representation
2520 // begins with the global scope specifier ('::foo'), add a space
2521 // to avoid printing the diagraph '<:'.
2522 if (FirstArg && ArgString.starts_with(Prefix: ":"))
2523 OS << ' ';
2524
2525 OS << ArgString;
2526
2527 // If the last character of our string is '>', add another space to
2528 // keep the two '>''s separate tokens.
2529 if (!ArgString.empty()) {
2530 NeedSpace = Policy.SplitTemplateClosers && ArgString.back() == '>';
2531 FirstArg = false;
2532 }
2533
2534 // Use same template parameter for all elements of Pack
2535 if (!IsPack)
2536 ParmIndex++;
2537 }
2538
2539 if (!IsPack) {
2540 if (NeedSpace)
2541 OS << ' ';
2542 OS << '>';
2543 }
2544}
2545
2546void clang::printTemplateArgumentList(raw_ostream &OS,
2547 const TemplateArgumentListInfo &Args,
2548 const PrintingPolicy &Policy,
2549 const TemplateParameterList *TPL) {
2550 printTemplateArgumentList(OS, Args: Args.arguments(), Policy, TPL);
2551}
2552
2553void clang::printTemplateArgumentList(raw_ostream &OS,
2554 ArrayRef<TemplateArgument> Args,
2555 const PrintingPolicy &Policy,
2556 const TemplateParameterList *TPL) {
2557 PrintingPolicy InnerPolicy = Policy;
2558 InnerPolicy.SuppressScope = false;
2559 printTo(OS, Args, Policy: InnerPolicy, TPL, /*isPack*/ IsPack: false, /*parmIndex*/ ParmIndex: 0);
2560}
2561
2562void clang::printTemplateArgumentList(raw_ostream &OS,
2563 ArrayRef<TemplateArgumentLoc> Args,
2564 const PrintingPolicy &Policy,
2565 const TemplateParameterList *TPL) {
2566 PrintingPolicy InnerPolicy = Policy;
2567 InnerPolicy.SuppressScope = false;
2568 printTo(OS, Args, Policy: InnerPolicy, TPL, /*isPack*/ IsPack: false, /*parmIndex*/ ParmIndex: 0);
2569}
2570
2571std::string PointerAuthQualifier::getAsString() const {
2572 LangOptions LO;
2573 return getAsString(Policy: PrintingPolicy(LO));
2574}
2575
2576std::string PointerAuthQualifier::getAsString(const PrintingPolicy &P) const {
2577 SmallString<64> Buf;
2578 llvm::raw_svector_ostream StrOS(Buf);
2579 print(OS&: StrOS, Policy: P);
2580 return StrOS.str().str();
2581}
2582
2583bool PointerAuthQualifier::isEmptyWhenPrinted(const PrintingPolicy &P) const {
2584 return !isPresent();
2585}
2586
2587void PointerAuthQualifier::print(raw_ostream &OS,
2588 const PrintingPolicy &P) const {
2589 if (!isPresent())
2590 return;
2591
2592 OS << "__ptrauth(";
2593 OS << getKey();
2594 OS << "," << unsigned(isAddressDiscriminated()) << ","
2595 << getExtraDiscriminator() << ")";
2596}
2597
2598std::string Qualifiers::getAsString() const {
2599 LangOptions LO;
2600 return getAsString(Policy: PrintingPolicy(LO));
2601}
2602
2603// Appends qualifiers to the given string, separated by spaces. Will
2604// prefix a space if the string is non-empty. Will not append a final
2605// space.
2606std::string Qualifiers::getAsString(const PrintingPolicy &Policy) const {
2607 SmallString<64> Buf;
2608 llvm::raw_svector_ostream StrOS(Buf);
2609 print(OS&: StrOS, Policy);
2610 return std::string(StrOS.str());
2611}
2612
2613bool Qualifiers::isEmptyWhenPrinted(const PrintingPolicy &Policy) const {
2614 if (getCVRQualifiers())
2615 return false;
2616
2617 if (getAddressSpace() != LangAS::Default)
2618 return false;
2619
2620 if (getObjCGCAttr())
2621 return false;
2622
2623 if (Qualifiers::ObjCLifetime lifetime = getObjCLifetime())
2624 if (!(lifetime == Qualifiers::OCL_Strong && Policy.SuppressStrongLifetime))
2625 return false;
2626
2627 if (PointerAuthQualifier PointerAuth = getPointerAuth();
2628 PointerAuth && !PointerAuth.isEmptyWhenPrinted(P: Policy))
2629 return false;
2630
2631 return true;
2632}
2633
2634std::string Qualifiers::getAddrSpaceAsString(LangAS AS) {
2635 switch (AS) {
2636 case LangAS::Default:
2637 return "";
2638 case LangAS::opencl_global:
2639 case LangAS::sycl_global:
2640 return "__global";
2641 case LangAS::opencl_local:
2642 case LangAS::sycl_local:
2643 return "__local";
2644 case LangAS::opencl_private:
2645 case LangAS::sycl_private:
2646 return "__private";
2647 case LangAS::opencl_constant:
2648 return "__constant";
2649 case LangAS::opencl_generic:
2650 return "__generic";
2651 case LangAS::opencl_global_device:
2652 case LangAS::sycl_global_device:
2653 return "__global_device";
2654 case LangAS::opencl_global_host:
2655 case LangAS::sycl_global_host:
2656 return "__global_host";
2657 case LangAS::cuda_device:
2658 return "__device__";
2659 case LangAS::cuda_constant:
2660 return "__constant__";
2661 case LangAS::cuda_shared:
2662 return "__shared__";
2663 case LangAS::ptr32_sptr:
2664 return "__sptr __ptr32";
2665 case LangAS::ptr32_uptr:
2666 return "__uptr __ptr32";
2667 case LangAS::ptr64:
2668 return "__ptr64";
2669 case LangAS::hlsl_groupshared:
2670 return "groupshared";
2671 case LangAS::hlsl_constant:
2672 return "hlsl_constant";
2673 case LangAS::hlsl_private:
2674 return "hlsl_private";
2675 case LangAS::hlsl_device:
2676 return "hlsl_device";
2677 case LangAS::hlsl_input:
2678 return "hlsl_input";
2679 case LangAS::wasm_funcref:
2680 return "__funcref";
2681 default:
2682 return std::to_string(val: toTargetAddressSpace(AS));
2683 }
2684}
2685
2686// Appends qualifiers to the given string, separated by spaces. Will
2687// prefix a space if the string is non-empty. Will not append a final
2688// space.
2689void Qualifiers::print(raw_ostream &OS, const PrintingPolicy& Policy,
2690 bool appendSpaceIfNonEmpty) const {
2691 bool addSpace = false;
2692
2693 unsigned quals = getCVRQualifiers();
2694 if (quals) {
2695 AppendTypeQualList(OS, TypeQuals: quals, HasRestrictKeyword: Policy.Restrict);
2696 addSpace = true;
2697 }
2698 if (hasUnaligned()) {
2699 if (addSpace)
2700 OS << ' ';
2701 OS << "__unaligned";
2702 addSpace = true;
2703 }
2704 auto ASStr = getAddrSpaceAsString(AS: getAddressSpace());
2705 if (!ASStr.empty()) {
2706 if (addSpace)
2707 OS << ' ';
2708 addSpace = true;
2709 // Wrap target address space into an attribute syntax
2710 if (isTargetAddressSpace(AS: getAddressSpace()))
2711 OS << "__attribute__((address_space(" << ASStr << ")))";
2712 else
2713 OS << ASStr;
2714 }
2715
2716 if (Qualifiers::GC gc = getObjCGCAttr()) {
2717 if (addSpace)
2718 OS << ' ';
2719 addSpace = true;
2720 if (gc == Qualifiers::Weak)
2721 OS << "__weak";
2722 else
2723 OS << "__strong";
2724 }
2725 if (Qualifiers::ObjCLifetime lifetime = getObjCLifetime()) {
2726 if (!(lifetime == Qualifiers::OCL_Strong && Policy.SuppressStrongLifetime)){
2727 if (addSpace)
2728 OS << ' ';
2729 addSpace = true;
2730 }
2731
2732 switch (lifetime) {
2733 case Qualifiers::OCL_None: llvm_unreachable("none but true");
2734 case Qualifiers::OCL_ExplicitNone: OS << "__unsafe_unretained"; break;
2735 case Qualifiers::OCL_Strong:
2736 if (!Policy.SuppressStrongLifetime)
2737 OS << "__strong";
2738 break;
2739
2740 case Qualifiers::OCL_Weak: OS << "__weak"; break;
2741 case Qualifiers::OCL_Autoreleasing: OS << "__autoreleasing"; break;
2742 }
2743 }
2744
2745 if (PointerAuthQualifier PointerAuth = getPointerAuth()) {
2746 if (addSpace)
2747 OS << ' ';
2748 addSpace = true;
2749
2750 PointerAuth.print(OS, P: Policy);
2751 }
2752
2753 if (appendSpaceIfNonEmpty && addSpace)
2754 OS << ' ';
2755}
2756
2757std::string QualType::getAsString() const {
2758 return getAsString(split: split(), Policy: LangOptions());
2759}
2760
2761std::string QualType::getAsString(const PrintingPolicy &Policy) const {
2762 std::string S;
2763 getAsStringInternal(Str&: S, Policy);
2764 return S;
2765}
2766
2767std::string QualType::getAsString(const Type *ty, Qualifiers qs,
2768 const PrintingPolicy &Policy) {
2769 std::string buffer;
2770 getAsStringInternal(ty, qs, out&: buffer, policy: Policy);
2771 return buffer;
2772}
2773
2774void QualType::print(raw_ostream &OS, const PrintingPolicy &Policy,
2775 const Twine &PlaceHolder, unsigned Indentation) const {
2776 print(split: splitAccordingToPolicy(QT: *this, Policy), OS, policy: Policy, PlaceHolder,
2777 Indentation);
2778}
2779
2780void QualType::print(const Type *ty, Qualifiers qs,
2781 raw_ostream &OS, const PrintingPolicy &policy,
2782 const Twine &PlaceHolder, unsigned Indentation) {
2783 SmallString<128> PHBuf;
2784 StringRef PH = PlaceHolder.toStringRef(Out&: PHBuf);
2785
2786 TypePrinter(policy, Indentation).print(T: ty, Quals: qs, OS, PlaceHolder: PH);
2787}
2788
2789void QualType::getAsStringInternal(std::string &Str,
2790 const PrintingPolicy &Policy) const {
2791 return getAsStringInternal(split: splitAccordingToPolicy(QT: *this, Policy), out&: Str,
2792 policy: Policy);
2793}
2794
2795void QualType::getAsStringInternal(const Type *ty, Qualifiers qs,
2796 std::string &buffer,
2797 const PrintingPolicy &policy) {
2798 SmallString<256> Buf;
2799 llvm::raw_svector_ostream StrOS(Buf);
2800 TypePrinter(policy).print(T: ty, Quals: qs, OS&: StrOS, PlaceHolder: buffer);
2801 std::string str = std::string(StrOS.str());
2802 buffer.swap(s&: str);
2803}
2804
2805raw_ostream &clang::operator<<(raw_ostream &OS, QualType QT) {
2806 SplitQualType S = QT.split();
2807 TypePrinter(LangOptions()).print(T: S.Ty, Quals: S.Quals, OS, /*PlaceHolder=*/"");
2808 return OS;
2809}
2810

Provided by KDAB

Privacy Policy
Update your C++ knowledge – Modern C++11/14/17 Training
Find out more

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