1341825Sdim//===- TypePrinter.cpp - Pretty-Print Clang Types -------------------------===//
2199482Srdivacky//
3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4353358Sdim// See https://llvm.org/LICENSE.txt for license information.
5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6199482Srdivacky//
7199482Srdivacky//===----------------------------------------------------------------------===//
8199482Srdivacky//
9199482Srdivacky// This contains code to print types from Clang's type system.
10199482Srdivacky//
11199482Srdivacky//===----------------------------------------------------------------------===//
12199482Srdivacky
13249423Sdim#include "clang/AST/PrettyPrinter.h"
14239462Sdim#include "clang/AST/ASTContext.h"
15199482Srdivacky#include "clang/AST/Decl.h"
16341825Sdim#include "clang/AST/DeclBase.h"
17341825Sdim#include "clang/AST/DeclCXX.h"
18199482Srdivacky#include "clang/AST/DeclObjC.h"
19199482Srdivacky#include "clang/AST/DeclTemplate.h"
20199482Srdivacky#include "clang/AST/Expr.h"
21341825Sdim#include "clang/AST/NestedNameSpecifier.h"
22341825Sdim#include "clang/AST/TemplateBase.h"
23341825Sdim#include "clang/AST/TemplateName.h"
24199482Srdivacky#include "clang/AST/Type.h"
25341825Sdim#include "clang/Basic/AddressSpaces.h"
26341825Sdim#include "clang/Basic/ExceptionSpecificationType.h"
27341825Sdim#include "clang/Basic/IdentifierTable.h"
28341825Sdim#include "clang/Basic/LLVM.h"
29199482Srdivacky#include "clang/Basic/LangOptions.h"
30341825Sdim#include "clang/Basic/SourceLocation.h"
31205408Srdivacky#include "clang/Basic/SourceManager.h"
32341825Sdim#include "clang/Basic/Specifiers.h"
33341825Sdim#include "llvm/ADT/ArrayRef.h"
34239462Sdim#include "llvm/ADT/SmallString.h"
35341825Sdim#include "llvm/ADT/StringRef.h"
36341825Sdim#include "llvm/ADT/Twine.h"
37341825Sdim#include "llvm/Support/Casting.h"
38341825Sdim#include "llvm/Support/Compiler.h"
39341825Sdim#include "llvm/Support/ErrorHandling.h"
40249423Sdim#include "llvm/Support/SaveAndRestore.h"
41199482Srdivacky#include "llvm/Support/raw_ostream.h"
42341825Sdim#include <cassert>
43341825Sdim#include <string>
44341825Sdim
45199482Srdivackyusing namespace clang;
46199482Srdivacky
47199482Srdivackynamespace {
48341825Sdim
49341825Sdim  /// RAII object that enables printing of the ARC __strong lifetime
50224145Sdim  /// qualifier.
51224145Sdim  class IncludeStrongLifetimeRAII {
52224145Sdim    PrintingPolicy &Policy;
53224145Sdim    bool Old;
54341825Sdim
55224145Sdim  public:
56341825Sdim    explicit IncludeStrongLifetimeRAII(PrintingPolicy &Policy)
57341825Sdim        : Policy(Policy), Old(Policy.SuppressStrongLifetime) {
58261991Sdim        if (!Policy.SuppressLifetimeQualifiers)
59261991Sdim          Policy.SuppressStrongLifetime = false;
60224145Sdim    }
61341825Sdim
62224145Sdim    ~IncludeStrongLifetimeRAII() {
63224145Sdim      Policy.SuppressStrongLifetime = Old;
64224145Sdim    }
65224145Sdim  };
66239462Sdim
67239462Sdim  class ParamPolicyRAII {
68239462Sdim    PrintingPolicy &Policy;
69239462Sdim    bool Old;
70341825Sdim
71239462Sdim  public:
72341825Sdim    explicit ParamPolicyRAII(PrintingPolicy &Policy)
73341825Sdim        : Policy(Policy), Old(Policy.SuppressSpecifiers) {
74239462Sdim      Policy.SuppressSpecifiers = false;
75239462Sdim    }
76341825Sdim
77239462Sdim    ~ParamPolicyRAII() {
78239462Sdim      Policy.SuppressSpecifiers = Old;
79239462Sdim    }
80239462Sdim  };
81239462Sdim
82239462Sdim  class ElaboratedTypePolicyRAII {
83239462Sdim    PrintingPolicy &Policy;
84239462Sdim    bool SuppressTagKeyword;
85239462Sdim    bool SuppressScope;
86341825Sdim
87239462Sdim  public:
88239462Sdim    explicit ElaboratedTypePolicyRAII(PrintingPolicy &Policy) : Policy(Policy) {
89239462Sdim      SuppressTagKeyword = Policy.SuppressTagKeyword;
90239462Sdim      SuppressScope = Policy.SuppressScope;
91239462Sdim      Policy.SuppressTagKeyword = true;
92239462Sdim      Policy.SuppressScope = true;
93239462Sdim    }
94341825Sdim
95239462Sdim    ~ElaboratedTypePolicyRAII() {
96239462Sdim      Policy.SuppressTagKeyword = SuppressTagKeyword;
97239462Sdim      Policy.SuppressScope = SuppressScope;
98239462Sdim    }
99239462Sdim  };
100341825Sdim
101199482Srdivacky  class TypePrinter {
102199482Srdivacky    PrintingPolicy Policy;
103309124Sdim    unsigned Indentation;
104341825Sdim    bool HasEmptyPlaceHolder = false;
105341825Sdim    bool InsideCCAttribute = false;
106199482Srdivacky
107199482Srdivacky  public:
108309124Sdim    explicit TypePrinter(const PrintingPolicy &Policy, unsigned Indentation = 0)
109341825Sdim        : Policy(Policy), Indentation(Indentation) {}
110207619Srdivacky
111239462Sdim    void print(const Type *ty, Qualifiers qs, raw_ostream &OS,
112239462Sdim               StringRef PlaceHolder);
113239462Sdim    void print(QualType T, raw_ostream &OS, StringRef PlaceHolder);
114239462Sdim
115239462Sdim    static bool canPrefixQualifiers(const Type *T, bool &NeedARCStrongQualifier);
116239462Sdim    void spaceBeforePlaceHolder(raw_ostream &OS);
117321369Sdim    void printTypeSpec(NamedDecl *D, raw_ostream &OS);
118239462Sdim
119239462Sdim    void printBefore(QualType T, raw_ostream &OS);
120239462Sdim    void printAfter(QualType T, raw_ostream &OS);
121239462Sdim    void AppendScope(DeclContext *DC, raw_ostream &OS);
122239462Sdim    void printTag(TagDecl *T, raw_ostream &OS);
123321369Sdim    void printFunctionAfter(const FunctionType::ExtInfo &Info, raw_ostream &OS);
124199482Srdivacky#define ABSTRACT_TYPE(CLASS, PARENT)
125199482Srdivacky#define TYPE(CLASS, PARENT) \
126239462Sdim    void print##CLASS##Before(const CLASS##Type *T, raw_ostream &OS); \
127239462Sdim    void print##CLASS##After(const CLASS##Type *T, raw_ostream &OS);
128360784Sdim#include "clang/AST/TypeNodes.inc"
129344779Sdim
130344779Sdim  private:
131344779Sdim    void printBefore(const Type *ty, Qualifiers qs, raw_ostream &OS);
132344779Sdim    void printAfter(const Type *ty, Qualifiers qs, raw_ostream &OS);
133199482Srdivacky  };
134199482Srdivacky
135341825Sdim} // namespace
136341825Sdim
137309124Sdimstatic void AppendTypeQualList(raw_ostream &OS, unsigned TypeQuals,
138309124Sdim                               bool HasRestrictKeyword) {
139239462Sdim  bool appendSpace = false;
140199482Srdivacky  if (TypeQuals & Qualifiers::Const) {
141239462Sdim    OS << "const";
142239462Sdim    appendSpace = true;
143199482Srdivacky  }
144199482Srdivacky  if (TypeQuals & Qualifiers::Volatile) {
145239462Sdim    if (appendSpace) OS << ' ';
146239462Sdim    OS << "volatile";
147239462Sdim    appendSpace = true;
148199482Srdivacky  }
149199482Srdivacky  if (TypeQuals & Qualifiers::Restrict) {
150239462Sdim    if (appendSpace) OS << ' ';
151309124Sdim    if (HasRestrictKeyword) {
152288943Sdim      OS << "restrict";
153288943Sdim    } else {
154288943Sdim      OS << "__restrict";
155288943Sdim    }
156199482Srdivacky  }
157199482Srdivacky}
158199482Srdivacky
159239462Sdimvoid TypePrinter::spaceBeforePlaceHolder(raw_ostream &OS) {
160239462Sdim  if (!HasEmptyPlaceHolder)
161239462Sdim    OS << ' ';
162239462Sdim}
163239462Sdim
164344779Sdimstatic SplitQualType splitAccordingToPolicy(QualType QT,
165344779Sdim                                            const PrintingPolicy &Policy) {
166344779Sdim  if (Policy.PrintCanonicalTypes)
167344779Sdim    QT = QT.getCanonicalType();
168344779Sdim  return QT.split();
169344779Sdim}
170344779Sdim
171239462Sdimvoid TypePrinter::print(QualType t, raw_ostream &OS, StringRef PlaceHolder) {
172344779Sdim  SplitQualType split = splitAccordingToPolicy(t, Policy);
173239462Sdim  print(split.Ty, split.Quals, OS, PlaceHolder);
174218893Sdim}
175218893Sdim
176239462Sdimvoid TypePrinter::print(const Type *T, Qualifiers Quals, raw_ostream &OS,
177239462Sdim                        StringRef PlaceHolder) {
178218893Sdim  if (!T) {
179239462Sdim    OS << "NULL TYPE";
180199482Srdivacky    return;
181199482Srdivacky  }
182239462Sdim
183239462Sdim  SaveAndRestore<bool> PHVal(HasEmptyPlaceHolder, PlaceHolder.empty());
184239462Sdim
185239462Sdim  printBefore(T, Quals, OS);
186239462Sdim  OS << PlaceHolder;
187239462Sdim  printAfter(T, Quals, OS);
188239462Sdim}
189239462Sdim
190239462Sdimbool TypePrinter::canPrefixQualifiers(const Type *T,
191239462Sdim                                      bool &NeedARCStrongQualifier) {
192218893Sdim  // CanPrefixQualifiers - We prefer to print type qualifiers before the type,
193218893Sdim  // so that we get "const int" instead of "int const", but we can't do this if
194218893Sdim  // the type is complex.  For example if the type is "int*", we *must* print
195218893Sdim  // "int * const", printing "const int *" is different.  Only do this when the
196218893Sdim  // type expands to a simple string.
197218893Sdim  bool CanPrefixQualifiers = false;
198239462Sdim  NeedARCStrongQualifier = false;
199218893Sdim  Type::TypeClass TC = T->getTypeClass();
200341825Sdim  if (const auto *AT = dyn_cast<AutoType>(T))
201218893Sdim    TC = AT->desugar()->getTypeClass();
202341825Sdim  if (const auto *Subst = dyn_cast<SubstTemplateTypeParmType>(T))
203218893Sdim    TC = Subst->getReplacementType()->getTypeClass();
204341825Sdim
205218893Sdim  switch (TC) {
206261991Sdim    case Type::Auto:
207218893Sdim    case Type::Builtin:
208218893Sdim    case Type::Complex:
209218893Sdim    case Type::UnresolvedUsing:
210218893Sdim    case Type::Typedef:
211218893Sdim    case Type::TypeOfExpr:
212218893Sdim    case Type::TypeOf:
213218893Sdim    case Type::Decltype:
214223017Sdim    case Type::UnaryTransform:
215218893Sdim    case Type::Record:
216218893Sdim    case Type::Enum:
217218893Sdim    case Type::Elaborated:
218218893Sdim    case Type::TemplateTypeParm:
219218893Sdim    case Type::SubstTemplateTypeParmPack:
220321369Sdim    case Type::DeducedTemplateSpecialization:
221218893Sdim    case Type::TemplateSpecialization:
222218893Sdim    case Type::InjectedClassName:
223218893Sdim    case Type::DependentName:
224218893Sdim    case Type::DependentTemplateSpecialization:
225218893Sdim    case Type::ObjCObject:
226314564Sdim    case Type::ObjCTypeParam:
227218893Sdim    case Type::ObjCInterface:
228226633Sdim    case Type::Atomic:
229296417Sdim    case Type::Pipe:
230218893Sdim      CanPrefixQualifiers = true;
231218893Sdim      break;
232341825Sdim
233218893Sdim    case Type::ObjCObjectPointer:
234218893Sdim      CanPrefixQualifiers = T->isObjCIdType() || T->isObjCClassType() ||
235218893Sdim        T->isObjCQualifiedIdType() || T->isObjCQualifiedClassType();
236218893Sdim      break;
237341825Sdim
238224145Sdim    case Type::ConstantArray:
239224145Sdim    case Type::IncompleteArray:
240224145Sdim    case Type::VariableArray:
241224145Sdim    case Type::DependentSizedArray:
242224145Sdim      NeedARCStrongQualifier = true;
243327952Sdim      LLVM_FALLTHROUGH;
244341825Sdim
245276479Sdim    case Type::Adjusted:
246261991Sdim    case Type::Decayed:
247218893Sdim    case Type::Pointer:
248218893Sdim    case Type::BlockPointer:
249218893Sdim    case Type::LValueReference:
250218893Sdim    case Type::RValueReference:
251218893Sdim    case Type::MemberPointer:
252327952Sdim    case Type::DependentAddressSpace:
253341825Sdim    case Type::DependentVector:
254218893Sdim    case Type::DependentSizedExtVector:
255218893Sdim    case Type::Vector:
256218893Sdim    case Type::ExtVector:
257218893Sdim    case Type::FunctionProto:
258218893Sdim    case Type::FunctionNoProto:
259218893Sdim    case Type::Paren:
260218893Sdim    case Type::PackExpansion:
261218893Sdim    case Type::SubstTemplateTypeParm:
262353358Sdim    case Type::MacroQualified:
263218893Sdim      CanPrefixQualifiers = false;
264218893Sdim      break;
265353358Sdim
266353358Sdim    case Type::Attributed: {
267353358Sdim      // We still want to print the address_space before the type if it is an
268353358Sdim      // address_space attribute.
269353358Sdim      const auto *AttrTy = cast<AttributedType>(T);
270353358Sdim      CanPrefixQualifiers = AttrTy->getAttrKind() == attr::AddressSpace;
271353358Sdim    }
272218893Sdim  }
273239462Sdim
274239462Sdim  return CanPrefixQualifiers;
275239462Sdim}
276239462Sdim
277239462Sdimvoid TypePrinter::printBefore(QualType T, raw_ostream &OS) {
278344779Sdim  SplitQualType Split = splitAccordingToPolicy(T, Policy);
279239462Sdim
280239462Sdim  // If we have cv1 T, where T is substituted for cv2 U, only print cv1 - cv2
281239462Sdim  // at this level.
282239462Sdim  Qualifiers Quals = Split.Quals;
283341825Sdim  if (const auto *Subst = dyn_cast<SubstTemplateTypeParmType>(Split.Ty))
284239462Sdim    Quals -= QualType(Subst, 0).getQualifiers();
285239462Sdim
286239462Sdim  printBefore(Split.Ty, Quals, OS);
287239462Sdim}
288239462Sdim
289341825Sdim/// Prints the part of the type string before an identifier, e.g. for
290239462Sdim/// "int foo[10]" it prints "int ".
291239462Sdimvoid TypePrinter::printBefore(const Type *T,Qualifiers Quals, raw_ostream &OS) {
292239462Sdim  if (Policy.SuppressSpecifiers && T->isSpecifierType())
293239462Sdim    return;
294239462Sdim
295239462Sdim  SaveAndRestore<bool> PrevPHIsEmpty(HasEmptyPlaceHolder);
296239462Sdim
297239462Sdim  // Print qualifiers as appropriate.
298239462Sdim
299239462Sdim  bool CanPrefixQualifiers = false;
300239462Sdim  bool NeedARCStrongQualifier = false;
301239462Sdim  CanPrefixQualifiers = canPrefixQualifiers(T, NeedARCStrongQualifier);
302239462Sdim
303239462Sdim  if (CanPrefixQualifiers && !Quals.empty()) {
304224145Sdim    if (NeedARCStrongQualifier) {
305224145Sdim      IncludeStrongLifetimeRAII Strong(Policy);
306239462Sdim      Quals.print(OS, Policy, /*appendSpaceIfNonEmpty=*/true);
307224145Sdim    } else {
308239462Sdim      Quals.print(OS, Policy, /*appendSpaceIfNonEmpty=*/true);
309224145Sdim    }
310199482Srdivacky  }
311239462Sdim
312239462Sdim  bool hasAfterQuals = false;
313239462Sdim  if (!CanPrefixQualifiers && !Quals.empty()) {
314239462Sdim    hasAfterQuals = !Quals.isEmptyWhenPrinted(Policy);
315239462Sdim    if (hasAfterQuals)
316239462Sdim      HasEmptyPlaceHolder = false;
317239462Sdim  }
318239462Sdim
319199482Srdivacky  switch (T->getTypeClass()) {
320199482Srdivacky#define ABSTRACT_TYPE(CLASS, PARENT)
321218893Sdim#define TYPE(CLASS, PARENT) case Type::CLASS: \
322239462Sdim    print##CLASS##Before(cast<CLASS##Type>(T), OS); \
323199482Srdivacky    break;
324360784Sdim#include "clang/AST/TypeNodes.inc"
325199482Srdivacky  }
326239462Sdim
327239462Sdim  if (hasAfterQuals) {
328224145Sdim    if (NeedARCStrongQualifier) {
329224145Sdim      IncludeStrongLifetimeRAII Strong(Policy);
330239462Sdim      Quals.print(OS, Policy, /*appendSpaceIfNonEmpty=*/!PrevPHIsEmpty.get());
331224145Sdim    } else {
332239462Sdim      Quals.print(OS, Policy, /*appendSpaceIfNonEmpty=*/!PrevPHIsEmpty.get());
333218893Sdim    }
334218893Sdim  }
335199482Srdivacky}
336199482Srdivacky
337239462Sdimvoid TypePrinter::printAfter(QualType t, raw_ostream &OS) {
338344779Sdim  SplitQualType split = splitAccordingToPolicy(t, Policy);
339239462Sdim  printAfter(split.Ty, split.Quals, OS);
340239462Sdim}
341239462Sdim
342341825Sdim/// Prints the part of the type string after an identifier, e.g. for
343239462Sdim/// "int foo[10]" it prints "[10]".
344239462Sdimvoid TypePrinter::printAfter(const Type *T, Qualifiers Quals, raw_ostream &OS) {
345239462Sdim  switch (T->getTypeClass()) {
346239462Sdim#define ABSTRACT_TYPE(CLASS, PARENT)
347239462Sdim#define TYPE(CLASS, PARENT) case Type::CLASS: \
348239462Sdim    print##CLASS##After(cast<CLASS##Type>(T), OS); \
349239462Sdim    break;
350360784Sdim#include "clang/AST/TypeNodes.inc"
351199482Srdivacky  }
352199482Srdivacky}
353199482Srdivacky
354239462Sdimvoid TypePrinter::printBuiltinBefore(const BuiltinType *T, raw_ostream &OS) {
355239462Sdim  OS << T->getName(Policy);
356239462Sdim  spaceBeforePlaceHolder(OS);
357199482Srdivacky}
358199482Srdivacky
359341825Sdimvoid TypePrinter::printBuiltinAfter(const BuiltinType *T, raw_ostream &OS) {}
360341825Sdim
361239462Sdimvoid TypePrinter::printComplexBefore(const ComplexType *T, raw_ostream &OS) {
362239462Sdim  OS << "_Complex ";
363239462Sdim  printBefore(T->getElementType(), OS);
364239462Sdim}
365341825Sdim
366239462Sdimvoid TypePrinter::printComplexAfter(const ComplexType *T, raw_ostream &OS) {
367239462Sdim  printAfter(T->getElementType(), OS);
368239462Sdim}
369239462Sdim
370239462Sdimvoid TypePrinter::printPointerBefore(const PointerType *T, raw_ostream &OS) {
371239462Sdim  IncludeStrongLifetimeRAII Strong(Policy);
372239462Sdim  SaveAndRestore<bool> NonEmptyPH(HasEmptyPlaceHolder, false);
373239462Sdim  printBefore(T->getPointeeType(), OS);
374199482Srdivacky  // Handle things like 'int (*A)[4];' correctly.
375199482Srdivacky  // FIXME: this should include vectors, but vectors use attributes I guess.
376199482Srdivacky  if (isa<ArrayType>(T->getPointeeType()))
377239462Sdim    OS << '(';
378239462Sdim  OS << '*';
379239462Sdim}
380341825Sdim
381239462Sdimvoid TypePrinter::printPointerAfter(const PointerType *T, raw_ostream &OS) {
382224145Sdim  IncludeStrongLifetimeRAII Strong(Policy);
383239462Sdim  SaveAndRestore<bool> NonEmptyPH(HasEmptyPlaceHolder, false);
384239462Sdim  // Handle things like 'int (*A)[4];' correctly.
385239462Sdim  // FIXME: this should include vectors, but vectors use attributes I guess.
386239462Sdim  if (isa<ArrayType>(T->getPointeeType()))
387239462Sdim    OS << ')';
388239462Sdim  printAfter(T->getPointeeType(), OS);
389199482Srdivacky}
390199482Srdivacky
391239462Sdimvoid TypePrinter::printBlockPointerBefore(const BlockPointerType *T,
392239462Sdim                                          raw_ostream &OS) {
393239462Sdim  SaveAndRestore<bool> NonEmptyPH(HasEmptyPlaceHolder, false);
394239462Sdim  printBefore(T->getPointeeType(), OS);
395239462Sdim  OS << '^';
396199482Srdivacky}
397341825Sdim
398239462Sdimvoid TypePrinter::printBlockPointerAfter(const BlockPointerType *T,
399239462Sdim                                          raw_ostream &OS) {
400239462Sdim  SaveAndRestore<bool> NonEmptyPH(HasEmptyPlaceHolder, false);
401239462Sdim  printAfter(T->getPointeeType(), OS);
402239462Sdim}
403199482Srdivacky
404341825Sdim// When printing a reference, the referenced type might also be a reference.
405341825Sdim// If so, we want to skip that before printing the inner type.
406341825Sdimstatic QualType skipTopLevelReferences(QualType T) {
407341825Sdim  if (auto *Ref = T->getAs<ReferenceType>())
408341825Sdim    return skipTopLevelReferences(Ref->getPointeeTypeAsWritten());
409341825Sdim  return T;
410341825Sdim}
411341825Sdim
412239462Sdimvoid TypePrinter::printLValueReferenceBefore(const LValueReferenceType *T,
413239462Sdim                                             raw_ostream &OS) {
414239462Sdim  IncludeStrongLifetimeRAII Strong(Policy);
415239462Sdim  SaveAndRestore<bool> NonEmptyPH(HasEmptyPlaceHolder, false);
416341825Sdim  QualType Inner = skipTopLevelReferences(T->getPointeeTypeAsWritten());
417341825Sdim  printBefore(Inner, OS);
418199482Srdivacky  // Handle things like 'int (&A)[4];' correctly.
419199482Srdivacky  // FIXME: this should include vectors, but vectors use attributes I guess.
420341825Sdim  if (isa<ArrayType>(Inner))
421239462Sdim    OS << '(';
422239462Sdim  OS << '&';
423239462Sdim}
424341825Sdim
425239462Sdimvoid TypePrinter::printLValueReferenceAfter(const LValueReferenceType *T,
426239462Sdim                                            raw_ostream &OS) {
427224145Sdim  IncludeStrongLifetimeRAII Strong(Policy);
428239462Sdim  SaveAndRestore<bool> NonEmptyPH(HasEmptyPlaceHolder, false);
429341825Sdim  QualType Inner = skipTopLevelReferences(T->getPointeeTypeAsWritten());
430239462Sdim  // Handle things like 'int (&A)[4];' correctly.
431239462Sdim  // FIXME: this should include vectors, but vectors use attributes I guess.
432341825Sdim  if (isa<ArrayType>(Inner))
433239462Sdim    OS << ')';
434341825Sdim  printAfter(Inner, OS);
435199482Srdivacky}
436199482Srdivacky
437239462Sdimvoid TypePrinter::printRValueReferenceBefore(const RValueReferenceType *T,
438239462Sdim                                             raw_ostream &OS) {
439239462Sdim  IncludeStrongLifetimeRAII Strong(Policy);
440239462Sdim  SaveAndRestore<bool> NonEmptyPH(HasEmptyPlaceHolder, false);
441341825Sdim  QualType Inner = skipTopLevelReferences(T->getPointeeTypeAsWritten());
442341825Sdim  printBefore(Inner, OS);
443199482Srdivacky  // Handle things like 'int (&&A)[4];' correctly.
444199482Srdivacky  // FIXME: this should include vectors, but vectors use attributes I guess.
445341825Sdim  if (isa<ArrayType>(Inner))
446239462Sdim    OS << '(';
447239462Sdim  OS << "&&";
448239462Sdim}
449341825Sdim
450239462Sdimvoid TypePrinter::printRValueReferenceAfter(const RValueReferenceType *T,
451239462Sdim                                            raw_ostream &OS) {
452224145Sdim  IncludeStrongLifetimeRAII Strong(Policy);
453239462Sdim  SaveAndRestore<bool> NonEmptyPH(HasEmptyPlaceHolder, false);
454341825Sdim  QualType Inner = skipTopLevelReferences(T->getPointeeTypeAsWritten());
455239462Sdim  // Handle things like 'int (&&A)[4];' correctly.
456239462Sdim  // FIXME: this should include vectors, but vectors use attributes I guess.
457341825Sdim  if (isa<ArrayType>(Inner))
458239462Sdim    OS << ')';
459341825Sdim  printAfter(Inner, OS);
460199482Srdivacky}
461199482Srdivacky
462341825Sdimvoid TypePrinter::printMemberPointerBefore(const MemberPointerType *T,
463341825Sdim                                           raw_ostream &OS) {
464239462Sdim  IncludeStrongLifetimeRAII Strong(Policy);
465239462Sdim  SaveAndRestore<bool> NonEmptyPH(HasEmptyPlaceHolder, false);
466239462Sdim  printBefore(T->getPointeeType(), OS);
467239462Sdim  // Handle things like 'int (Cls::*A)[4];' correctly.
468239462Sdim  // FIXME: this should include vectors, but vectors use attributes I guess.
469239462Sdim  if (isa<ArrayType>(T->getPointeeType()))
470239462Sdim    OS << '(';
471239462Sdim
472234353Sdim  PrintingPolicy InnerPolicy(Policy);
473309124Sdim  InnerPolicy.IncludeTagDefinition = false;
474239462Sdim  TypePrinter(InnerPolicy).print(QualType(T->getClass(), 0), OS, StringRef());
475239462Sdim
476239462Sdim  OS << "::*";
477239462Sdim}
478341825Sdim
479341825Sdimvoid TypePrinter::printMemberPointerAfter(const MemberPointerType *T,
480341825Sdim                                          raw_ostream &OS) {
481239462Sdim  IncludeStrongLifetimeRAII Strong(Policy);
482239462Sdim  SaveAndRestore<bool> NonEmptyPH(HasEmptyPlaceHolder, false);
483199482Srdivacky  // Handle things like 'int (Cls::*A)[4];' correctly.
484199482Srdivacky  // FIXME: this should include vectors, but vectors use attributes I guess.
485199482Srdivacky  if (isa<ArrayType>(T->getPointeeType()))
486239462Sdim    OS << ')';
487239462Sdim  printAfter(T->getPointeeType(), OS);
488239462Sdim}
489239462Sdim
490341825Sdimvoid TypePrinter::printConstantArrayBefore(const ConstantArrayType *T,
491239462Sdim                                           raw_ostream &OS) {
492224145Sdim  IncludeStrongLifetimeRAII Strong(Policy);
493239462Sdim  SaveAndRestore<bool> NonEmptyPH(HasEmptyPlaceHolder, false);
494239462Sdim  printBefore(T->getElementType(), OS);
495199482Srdivacky}
496341825Sdim
497341825Sdimvoid TypePrinter::printConstantArrayAfter(const ConstantArrayType *T,
498239462Sdim                                          raw_ostream &OS) {
499276479Sdim  OS << '[';
500276479Sdim  if (T->getIndexTypeQualifiers().hasQualifiers()) {
501309124Sdim    AppendTypeQualList(OS, T->getIndexTypeCVRQualifiers(),
502309124Sdim                       Policy.Restrict);
503276479Sdim    OS << ' ';
504276479Sdim  }
505276479Sdim
506276479Sdim  if (T->getSizeModifier() == ArrayType::Static)
507276479Sdim    OS << "static ";
508276479Sdim
509276479Sdim  OS << T->getSize().getZExtValue() << ']';
510239462Sdim  printAfter(T->getElementType(), OS);
511239462Sdim}
512199482Srdivacky
513341825Sdimvoid TypePrinter::printIncompleteArrayBefore(const IncompleteArrayType *T,
514239462Sdim                                             raw_ostream &OS) {
515224145Sdim  IncludeStrongLifetimeRAII Strong(Policy);
516239462Sdim  SaveAndRestore<bool> NonEmptyPH(HasEmptyPlaceHolder, false);
517239462Sdim  printBefore(T->getElementType(), OS);
518199482Srdivacky}
519341825Sdim
520341825Sdimvoid TypePrinter::printIncompleteArrayAfter(const IncompleteArrayType *T,
521239462Sdim                                            raw_ostream &OS) {
522239462Sdim  OS << "[]";
523239462Sdim  printAfter(T->getElementType(), OS);
524239462Sdim}
525199482Srdivacky
526341825Sdimvoid TypePrinter::printVariableArrayBefore(const VariableArrayType *T,
527239462Sdim                                           raw_ostream &OS) {
528224145Sdim  IncludeStrongLifetimeRAII Strong(Policy);
529239462Sdim  SaveAndRestore<bool> NonEmptyPH(HasEmptyPlaceHolder, false);
530239462Sdim  printBefore(T->getElementType(), OS);
531199482Srdivacky}
532341825Sdim
533341825Sdimvoid TypePrinter::printVariableArrayAfter(const VariableArrayType *T,
534239462Sdim                                          raw_ostream &OS) {
535239462Sdim  OS << '[';
536199482Srdivacky  if (T->getIndexTypeQualifiers().hasQualifiers()) {
537309124Sdim    AppendTypeQualList(OS, T->getIndexTypeCVRQualifiers(), Policy.Restrict);
538239462Sdim    OS << ' ';
539199482Srdivacky  }
540239462Sdim
541199482Srdivacky  if (T->getSizeModifier() == VariableArrayType::Static)
542276479Sdim    OS << "static ";
543199482Srdivacky  else if (T->getSizeModifier() == VariableArrayType::Star)
544239462Sdim    OS << '*';
545239462Sdim
546239462Sdim  if (T->getSizeExpr())
547276479Sdim    T->getSizeExpr()->printPretty(OS, nullptr, Policy);
548239462Sdim  OS << ']';
549239462Sdim
550239462Sdim  printAfter(T->getElementType(), OS);
551199482Srdivacky}
552199482Srdivacky
553276479Sdimvoid TypePrinter::printAdjustedBefore(const AdjustedType *T, raw_ostream &OS) {
554276479Sdim  // Print the adjusted representation, otherwise the adjustment will be
555276479Sdim  // invisible.
556276479Sdim  printBefore(T->getAdjustedType(), OS);
557276479Sdim}
558341825Sdim
559276479Sdimvoid TypePrinter::printAdjustedAfter(const AdjustedType *T, raw_ostream &OS) {
560276479Sdim  printAfter(T->getAdjustedType(), OS);
561276479Sdim}
562276479Sdim
563261991Sdimvoid TypePrinter::printDecayedBefore(const DecayedType *T, raw_ostream &OS) {
564261991Sdim  // Print as though it's a pointer.
565276479Sdim  printAdjustedBefore(T, OS);
566261991Sdim}
567341825Sdim
568261991Sdimvoid TypePrinter::printDecayedAfter(const DecayedType *T, raw_ostream &OS) {
569276479Sdim  printAdjustedAfter(T, OS);
570261991Sdim}
571261991Sdim
572239462Sdimvoid TypePrinter::printDependentSizedArrayBefore(
573341825Sdim                                               const DependentSizedArrayType *T,
574239462Sdim                                               raw_ostream &OS) {
575224145Sdim  IncludeStrongLifetimeRAII Strong(Policy);
576239462Sdim  SaveAndRestore<bool> NonEmptyPH(HasEmptyPlaceHolder, false);
577239462Sdim  printBefore(T->getElementType(), OS);
578199482Srdivacky}
579341825Sdim
580239462Sdimvoid TypePrinter::printDependentSizedArrayAfter(
581341825Sdim                                               const DependentSizedArrayType *T,
582239462Sdim                                               raw_ostream &OS) {
583239462Sdim  OS << '[';
584239462Sdim  if (T->getSizeExpr())
585276479Sdim    T->getSizeExpr()->printPretty(OS, nullptr, Policy);
586239462Sdim  OS << ']';
587239462Sdim  printAfter(T->getElementType(), OS);
588239462Sdim}
589199482Srdivacky
590327952Sdimvoid TypePrinter::printDependentAddressSpaceBefore(
591327952Sdim    const DependentAddressSpaceType *T, raw_ostream &OS) {
592327952Sdim  printBefore(T->getPointeeType(), OS);
593327952Sdim}
594341825Sdim
595327952Sdimvoid TypePrinter::printDependentAddressSpaceAfter(
596327952Sdim    const DependentAddressSpaceType *T, raw_ostream &OS) {
597327952Sdim  OS << " __attribute__((address_space(";
598327952Sdim  if (T->getAddrSpaceExpr())
599327952Sdim    T->getAddrSpaceExpr()->printPretty(OS, nullptr, Policy);
600327952Sdim  OS << ")))";
601327952Sdim  printAfter(T->getPointeeType(), OS);
602327952Sdim}
603327952Sdim
604239462Sdimvoid TypePrinter::printDependentSizedExtVectorBefore(
605341825Sdim                                          const DependentSizedExtVectorType *T,
606341825Sdim                                          raw_ostream &OS) {
607239462Sdim  printBefore(T->getElementType(), OS);
608199482Srdivacky}
609341825Sdim
610239462Sdimvoid TypePrinter::printDependentSizedExtVectorAfter(
611341825Sdim                                          const DependentSizedExtVectorType *T,
612341825Sdim                                          raw_ostream &OS) {
613239462Sdim  OS << " __attribute__((ext_vector_type(";
614239462Sdim  if (T->getSizeExpr())
615276479Sdim    T->getSizeExpr()->printPretty(OS, nullptr, Policy);
616341825Sdim  OS << ")))";
617239462Sdim  printAfter(T->getElementType(), OS);
618239462Sdim}
619199482Srdivacky
620341825Sdimvoid TypePrinter::printVectorBefore(const VectorType *T, raw_ostream &OS) {
621218893Sdim  switch (T->getVectorKind()) {
622218893Sdim  case VectorType::AltiVecPixel:
623239462Sdim    OS << "__vector __pixel ";
624218893Sdim    break;
625218893Sdim  case VectorType::AltiVecBool:
626239462Sdim    OS << "__vector __bool ";
627239462Sdim    printBefore(T->getElementType(), OS);
628218893Sdim    break;
629218893Sdim  case VectorType::AltiVecVector:
630239462Sdim    OS << "__vector ";
631239462Sdim    printBefore(T->getElementType(), OS);
632218893Sdim    break;
633218893Sdim  case VectorType::NeonVector:
634239462Sdim    OS << "__attribute__((neon_vector_type("
635239462Sdim       << T->getNumElements() << "))) ";
636239462Sdim    printBefore(T->getElementType(), OS);
637218893Sdim    break;
638218893Sdim  case VectorType::NeonPolyVector:
639239462Sdim    OS << "__attribute__((neon_polyvector_type(" <<
640239462Sdim          T->getNumElements() << "))) ";
641239462Sdim    printBefore(T->getElementType(), OS);
642218893Sdim    break;
643218893Sdim  case VectorType::GenericVector: {
644203955Srdivacky    // FIXME: We prefer to print the size directly here, but have no way
645203955Srdivacky    // to get the size of the type.
646239462Sdim    OS << "__attribute__((__vector_size__("
647239462Sdim       << T->getNumElements()
648239462Sdim       << " * sizeof(";
649239462Sdim    print(T->getElementType(), OS, StringRef());
650341825Sdim    OS << ")))) ";
651239462Sdim    printBefore(T->getElementType(), OS);
652218893Sdim    break;
653203955Srdivacky  }
654218893Sdim  }
655199482Srdivacky}
656341825Sdim
657239462Sdimvoid TypePrinter::printVectorAfter(const VectorType *T, raw_ostream &OS) {
658239462Sdim  printAfter(T->getElementType(), OS);
659341825Sdim}
660199482Srdivacky
661341825Sdimvoid TypePrinter::printDependentVectorBefore(
662341825Sdim    const DependentVectorType *T, raw_ostream &OS) {
663341825Sdim  switch (T->getVectorKind()) {
664341825Sdim  case VectorType::AltiVecPixel:
665341825Sdim    OS << "__vector __pixel ";
666341825Sdim    break;
667341825Sdim  case VectorType::AltiVecBool:
668341825Sdim    OS << "__vector __bool ";
669341825Sdim    printBefore(T->getElementType(), OS);
670341825Sdim    break;
671341825Sdim  case VectorType::AltiVecVector:
672341825Sdim    OS << "__vector ";
673341825Sdim    printBefore(T->getElementType(), OS);
674341825Sdim    break;
675341825Sdim  case VectorType::NeonVector:
676341825Sdim    OS << "__attribute__((neon_vector_type(";
677341825Sdim    if (T->getSizeExpr())
678341825Sdim      T->getSizeExpr()->printPretty(OS, nullptr, Policy);
679341825Sdim    OS << "))) ";
680341825Sdim    printBefore(T->getElementType(), OS);
681341825Sdim    break;
682341825Sdim  case VectorType::NeonPolyVector:
683341825Sdim    OS << "__attribute__((neon_polyvector_type(";
684341825Sdim    if (T->getSizeExpr())
685341825Sdim      T->getSizeExpr()->printPretty(OS, nullptr, Policy);
686341825Sdim    OS << "))) ";
687341825Sdim    printBefore(T->getElementType(), OS);
688341825Sdim    break;
689341825Sdim  case VectorType::GenericVector: {
690341825Sdim    // FIXME: We prefer to print the size directly here, but have no way
691341825Sdim    // to get the size of the type.
692341825Sdim    OS << "__attribute__((__vector_size__(";
693341825Sdim    if (T->getSizeExpr())
694341825Sdim      T->getSizeExpr()->printPretty(OS, nullptr, Policy);
695341825Sdim    OS << " * sizeof(";
696341825Sdim    print(T->getElementType(), OS, StringRef());
697341825Sdim    OS << ")))) ";
698341825Sdim    printBefore(T->getElementType(), OS);
699341825Sdim    break;
700341825Sdim  }
701341825Sdim  }
702341825Sdim}
703341825Sdim
704341825Sdimvoid TypePrinter::printDependentVectorAfter(
705341825Sdim    const DependentVectorType *T, raw_ostream &OS) {
706341825Sdim  printAfter(T->getElementType(), OS);
707341825Sdim}
708341825Sdim
709239462Sdimvoid TypePrinter::printExtVectorBefore(const ExtVectorType *T,
710341825Sdim                                       raw_ostream &OS) {
711239462Sdim  printBefore(T->getElementType(), OS);
712199482Srdivacky}
713341825Sdim
714341825Sdimvoid TypePrinter::printExtVectorAfter(const ExtVectorType *T, raw_ostream &OS) {
715239462Sdim  printAfter(T->getElementType(), OS);
716239462Sdim  OS << " __attribute__((ext_vector_type(";
717239462Sdim  OS << T->getNumElements();
718239462Sdim  OS << ")))";
719239462Sdim}
720199482Srdivacky
721341825Sdimvoid
722341825SdimFunctionProtoType::printExceptionSpecification(raw_ostream &OS,
723243830Sdim                                               const PrintingPolicy &Policy)
724243830Sdim                                                                         const {
725234353Sdim  if (hasDynamicExceptionSpec()) {
726239462Sdim    OS << " throw(";
727234353Sdim    if (getExceptionSpecType() == EST_MSAny)
728239462Sdim      OS << "...";
729234353Sdim    else
730234353Sdim      for (unsigned I = 0, N = getNumExceptions(); I != N; ++I) {
731234353Sdim        if (I)
732239462Sdim          OS << ", ";
733341825Sdim
734239462Sdim        OS << getExceptionType(I).stream(Policy);
735234353Sdim      }
736239462Sdim    OS << ')';
737353358Sdim  } else if (EST_NoThrow == getExceptionSpecType()) {
738353358Sdim    OS << " __attribute__((nothrow))";
739234353Sdim  } else if (isNoexceptExceptionSpec(getExceptionSpecType())) {
740239462Sdim    OS << " noexcept";
741341825Sdim    // FIXME:Is it useful to print out the expression for a non-dependent
742341825Sdim    // noexcept specification?
743341825Sdim    if (isComputedNoexcept(getExceptionSpecType())) {
744239462Sdim      OS << '(';
745276479Sdim      if (getNoexceptExpr())
746276479Sdim        getNoexceptExpr()->printPretty(OS, nullptr, Policy);
747239462Sdim      OS << ')';
748234353Sdim    }
749234353Sdim  }
750234353Sdim}
751234353Sdim
752341825Sdimvoid TypePrinter::printFunctionProtoBefore(const FunctionProtoType *T,
753239462Sdim                                           raw_ostream &OS) {
754239462Sdim  if (T->hasTrailingReturn()) {
755239462Sdim    OS << "auto ";
756239462Sdim    if (!HasEmptyPlaceHolder)
757239462Sdim      OS << '(';
758239462Sdim  } else {
759239462Sdim    // If needed for precedence reasons, wrap the inner part in grouping parens.
760239462Sdim    SaveAndRestore<bool> PrevPHIsEmpty(HasEmptyPlaceHolder, false);
761276479Sdim    printBefore(T->getReturnType(), OS);
762239462Sdim    if (!PrevPHIsEmpty.get())
763239462Sdim      OS << '(';
764239462Sdim  }
765239462Sdim}
766239462Sdim
767341825SdimStringRef clang::getParameterABISpelling(ParameterABI ABI) {
768309124Sdim  switch (ABI) {
769309124Sdim  case ParameterABI::Ordinary:
770309124Sdim    llvm_unreachable("asking for spelling of ordinary parameter ABI");
771309124Sdim  case ParameterABI::SwiftContext:
772309124Sdim    return "swift_context";
773309124Sdim  case ParameterABI::SwiftErrorResult:
774309124Sdim    return "swift_error_result";
775309124Sdim  case ParameterABI::SwiftIndirectResult:
776309124Sdim    return "swift_indirect_result";
777309124Sdim  }
778309124Sdim  llvm_unreachable("bad parameter ABI kind");
779309124Sdim}
780309124Sdim
781341825Sdimvoid TypePrinter::printFunctionProtoAfter(const FunctionProtoType *T,
782341825Sdim                                          raw_ostream &OS) {
783199482Srdivacky  // If needed for precedence reasons, wrap the inner part in grouping parens.
784239462Sdim  if (!HasEmptyPlaceHolder)
785239462Sdim    OS << ')';
786239462Sdim  SaveAndRestore<bool> NonEmptyPH(HasEmptyPlaceHolder, false);
787239462Sdim
788239462Sdim  OS << '(';
789239462Sdim  {
790239462Sdim    ParamPolicyRAII ParamPolicy(Policy);
791276479Sdim    for (unsigned i = 0, e = T->getNumParams(); i != e; ++i) {
792239462Sdim      if (i) OS << ", ";
793309124Sdim
794309124Sdim      auto EPI = T->getExtParameterInfo(i);
795309124Sdim      if (EPI.isConsumed()) OS << "__attribute__((ns_consumed)) ";
796327952Sdim      if (EPI.isNoEscape())
797327952Sdim        OS << "__attribute__((noescape)) ";
798309124Sdim      auto ABI = EPI.getABI();
799309124Sdim      if (ABI != ParameterABI::Ordinary)
800309124Sdim        OS << "__attribute__((" << getParameterABISpelling(ABI) << ")) ";
801309124Sdim
802276479Sdim      print(T->getParamType(i), OS, StringRef());
803239462Sdim    }
804199482Srdivacky  }
805341825Sdim
806199482Srdivacky  if (T->isVariadic()) {
807276479Sdim    if (T->getNumParams())
808239462Sdim      OS << ", ";
809239462Sdim    OS << "...";
810309124Sdim  } else if (T->getNumParams() == 0 && Policy.UseVoidForZeroParams) {
811199482Srdivacky    // Do not emit int() if we have a proto, emit 'int(void)'.
812239462Sdim    OS << "void";
813199482Srdivacky  }
814341825Sdim
815239462Sdim  OS << ')';
816200583Srdivacky
817206084Srdivacky  FunctionType::ExtInfo Info = T->getExtInfo();
818261991Sdim
819321369Sdim  printFunctionAfter(Info, OS);
820321369Sdim
821353358Sdim  if (!T->getMethodQuals().empty())
822353358Sdim    OS << " " << T->getMethodQuals().getAsString();
823321369Sdim
824321369Sdim  switch (T->getRefQualifier()) {
825321369Sdim  case RQ_None:
826321369Sdim    break;
827321369Sdim
828321369Sdim  case RQ_LValue:
829321369Sdim    OS << " &";
830321369Sdim    break;
831321369Sdim
832321369Sdim  case RQ_RValue:
833321369Sdim    OS << " &&";
834321369Sdim    break;
835321369Sdim  }
836321369Sdim  T->printExceptionSpecification(OS, Policy);
837321369Sdim
838321369Sdim  if (T->hasTrailingReturn()) {
839321369Sdim    OS << " -> ";
840321369Sdim    print(T->getReturnType(), OS, StringRef());
841321369Sdim  } else
842321369Sdim    printAfter(T->getReturnType(), OS);
843321369Sdim}
844321369Sdim
845321369Sdimvoid TypePrinter::printFunctionAfter(const FunctionType::ExtInfo &Info,
846321369Sdim                                     raw_ostream &OS) {
847261991Sdim  if (!InsideCCAttribute) {
848261991Sdim    switch (Info.getCC()) {
849261991Sdim    case CC_C:
850261991Sdim      // The C calling convention is the default on the vast majority of platforms
851261991Sdim      // we support.  If the user wrote it explicitly, it will usually be printed
852261991Sdim      // while traversing the AttributedType.  If the type has been desugared, let
853261991Sdim      // the canonical spelling be the implicit calling convention.
854261991Sdim      // FIXME: It would be better to be explicit in certain contexts, such as a
855261991Sdim      // cdecl function typedef used to declare a member function with the
856261991Sdim      // Microsoft C++ ABI.
857261991Sdim      break;
858261991Sdim    case CC_X86StdCall:
859261991Sdim      OS << " __attribute__((stdcall))";
860261991Sdim      break;
861261991Sdim    case CC_X86FastCall:
862261991Sdim      OS << " __attribute__((fastcall))";
863261991Sdim      break;
864261991Sdim    case CC_X86ThisCall:
865261991Sdim      OS << " __attribute__((thiscall))";
866261991Sdim      break;
867280031Sdim    case CC_X86VectorCall:
868280031Sdim      OS << " __attribute__((vectorcall))";
869280031Sdim      break;
870261991Sdim    case CC_X86Pascal:
871261991Sdim      OS << " __attribute__((pascal))";
872261991Sdim      break;
873261991Sdim    case CC_AAPCS:
874261991Sdim      OS << " __attribute__((pcs(\"aapcs\")))";
875261991Sdim      break;
876261991Sdim    case CC_AAPCS_VFP:
877261991Sdim      OS << " __attribute__((pcs(\"aapcs-vfp\")))";
878261991Sdim      break;
879344779Sdim    case CC_AArch64VectorCall:
880344779Sdim      OS << "__attribute__((aarch64_vector_pcs))";
881344779Sdim      break;
882261991Sdim    case CC_IntelOclBicc:
883261991Sdim      OS << " __attribute__((intel_ocl_bicc))";
884261991Sdim      break;
885321369Sdim    case CC_Win64:
886261991Sdim      OS << " __attribute__((ms_abi))";
887261991Sdim      break;
888261991Sdim    case CC_X86_64SysV:
889261991Sdim      OS << " __attribute__((sysv_abi))";
890261991Sdim      break;
891314564Sdim    case CC_X86RegCall:
892314564Sdim      OS << " __attribute__((regcall))";
893314564Sdim      break;
894288943Sdim    case CC_SpirFunction:
895309124Sdim    case CC_OpenCLKernel:
896288943Sdim      // Do nothing. These CCs are not available as attributes.
897288943Sdim      break;
898309124Sdim    case CC_Swift:
899309124Sdim      OS << " __attribute__((swiftcall))";
900309124Sdim      break;
901309124Sdim    case CC_PreserveMost:
902309124Sdim      OS << " __attribute__((preserve_most))";
903309124Sdim      break;
904309124Sdim    case CC_PreserveAll:
905309124Sdim      OS << " __attribute__((preserve_all))";
906309124Sdim      break;
907261991Sdim    }
908203955Srdivacky  }
909261991Sdim
910206084Srdivacky  if (Info.getNoReturn())
911239462Sdim    OS << " __attribute__((noreturn))";
912321369Sdim  if (Info.getProducesResult())
913321369Sdim    OS << " __attribute__((ns_returns_retained))";
914206084Srdivacky  if (Info.getRegParm())
915239462Sdim    OS << " __attribute__((regparm ("
916239462Sdim       << Info.getRegParm() << ")))";
917321369Sdim  if (Info.getNoCallerSavedRegs())
918321369Sdim    OS << " __attribute__((no_caller_saved_registers))";
919341825Sdim  if (Info.getNoCfCheck())
920341825Sdim    OS << " __attribute__((nocf_check))";
921199482Srdivacky}
922199482Srdivacky
923341825Sdimvoid TypePrinter::printFunctionNoProtoBefore(const FunctionNoProtoType *T,
924341825Sdim                                             raw_ostream &OS) {
925199482Srdivacky  // If needed for precedence reasons, wrap the inner part in grouping parens.
926239462Sdim  SaveAndRestore<bool> PrevPHIsEmpty(HasEmptyPlaceHolder, false);
927276479Sdim  printBefore(T->getReturnType(), OS);
928239462Sdim  if (!PrevPHIsEmpty.get())
929239462Sdim    OS << '(';
930239462Sdim}
931341825Sdim
932341825Sdimvoid TypePrinter::printFunctionNoProtoAfter(const FunctionNoProtoType *T,
933239462Sdim                                            raw_ostream &OS) {
934239462Sdim  // If needed for precedence reasons, wrap the inner part in grouping parens.
935239462Sdim  if (!HasEmptyPlaceHolder)
936239462Sdim    OS << ')';
937239462Sdim  SaveAndRestore<bool> NonEmptyPH(HasEmptyPlaceHolder, false);
938341825Sdim
939239462Sdim  OS << "()";
940321369Sdim  printFunctionAfter(T->getExtInfo(), OS);
941276479Sdim  printAfter(T->getReturnType(), OS);
942199482Srdivacky}
943199482Srdivacky
944321369Sdimvoid TypePrinter::printTypeSpec(NamedDecl *D, raw_ostream &OS) {
945321369Sdim
946321369Sdim  // Compute the full nested-name-specifier for this type.
947321369Sdim  // In C, this will always be empty except when the type
948321369Sdim  // being printed is anonymous within other Record.
949321369Sdim  if (!Policy.SuppressScope)
950321369Sdim    AppendScope(D->getDeclContext(), OS);
951321369Sdim
952204962Srdivacky  IdentifierInfo *II = D->getIdentifier();
953239462Sdim  OS << II->getName();
954239462Sdim  spaceBeforePlaceHolder(OS);
955200583Srdivacky}
956200583Srdivacky
957239462Sdimvoid TypePrinter::printUnresolvedUsingBefore(const UnresolvedUsingType *T,
958239462Sdim                                             raw_ostream &OS) {
959239462Sdim  printTypeSpec(T->getDecl(), OS);
960204962Srdivacky}
961341825Sdim
962239462Sdimvoid TypePrinter::printUnresolvedUsingAfter(const UnresolvedUsingType *T,
963341825Sdim                                            raw_ostream &OS) {}
964204962Srdivacky
965341825Sdimvoid TypePrinter::printTypedefBefore(const TypedefType *T, raw_ostream &OS) {
966239462Sdim  printTypeSpec(T->getDecl(), OS);
967199482Srdivacky}
968199482Srdivacky
969353358Sdimvoid TypePrinter::printMacroQualifiedBefore(const MacroQualifiedType *T,
970353358Sdim                                            raw_ostream &OS) {
971353358Sdim  StringRef MacroName = T->getMacroIdentifier()->getName();
972353358Sdim  OS << MacroName << " ";
973353358Sdim
974353358Sdim  // Since this type is meant to print the macro instead of the whole attribute,
975353358Sdim  // we trim any attributes and go directly to the original modified type.
976353358Sdim  printBefore(T->getModifiedType(), OS);
977353358Sdim}
978353358Sdim
979353358Sdimvoid TypePrinter::printMacroQualifiedAfter(const MacroQualifiedType *T,
980353358Sdim                                           raw_ostream &OS) {
981353358Sdim  printAfter(T->getModifiedType(), OS);
982353358Sdim}
983353358Sdim
984341825Sdimvoid TypePrinter::printTypedefAfter(const TypedefType *T, raw_ostream &OS) {}
985341825Sdim
986239462Sdimvoid TypePrinter::printTypeOfExprBefore(const TypeOfExprType *T,
987239462Sdim                                        raw_ostream &OS) {
988239462Sdim  OS << "typeof ";
989276479Sdim  if (T->getUnderlyingExpr())
990276479Sdim    T->getUnderlyingExpr()->printPretty(OS, nullptr, Policy);
991239462Sdim  spaceBeforePlaceHolder(OS);
992199482Srdivacky}
993341825Sdim
994239462Sdimvoid TypePrinter::printTypeOfExprAfter(const TypeOfExprType *T,
995341825Sdim                                       raw_ostream &OS) {}
996199482Srdivacky
997341825Sdimvoid TypePrinter::printTypeOfBefore(const TypeOfType *T, raw_ostream &OS) {
998239462Sdim  OS << "typeof(";
999239462Sdim  print(T->getUnderlyingType(), OS, StringRef());
1000239462Sdim  OS << ')';
1001239462Sdim  spaceBeforePlaceHolder(OS);
1002199482Srdivacky}
1003199482Srdivacky
1004341825Sdimvoid TypePrinter::printTypeOfAfter(const TypeOfType *T, raw_ostream &OS) {}
1005341825Sdim
1006341825Sdimvoid TypePrinter::printDecltypeBefore(const DecltypeType *T, raw_ostream &OS) {
1007239462Sdim  OS << "decltype(";
1008276479Sdim  if (T->getUnderlyingExpr())
1009276479Sdim    T->getUnderlyingExpr()->printPretty(OS, nullptr, Policy);
1010239462Sdim  OS << ')';
1011239462Sdim  spaceBeforePlaceHolder(OS);
1012199482Srdivacky}
1013199482Srdivacky
1014341825Sdimvoid TypePrinter::printDecltypeAfter(const DecltypeType *T, raw_ostream &OS) {}
1015341825Sdim
1016239462Sdimvoid TypePrinter::printUnaryTransformBefore(const UnaryTransformType *T,
1017239462Sdim                                            raw_ostream &OS) {
1018224145Sdim  IncludeStrongLifetimeRAII Strong(Policy);
1019223017Sdim
1020223017Sdim  switch (T->getUTTKind()) {
1021223017Sdim    case UnaryTransformType::EnumUnderlyingType:
1022239462Sdim      OS << "__underlying_type(";
1023239462Sdim      print(T->getBaseType(), OS, StringRef());
1024239462Sdim      OS << ')';
1025239462Sdim      spaceBeforePlaceHolder(OS);
1026239462Sdim      return;
1027223017Sdim  }
1028239462Sdim
1029239462Sdim  printBefore(T->getBaseType(), OS);
1030223017Sdim}
1031341825Sdim
1032239462Sdimvoid TypePrinter::printUnaryTransformAfter(const UnaryTransformType *T,
1033239462Sdim                                           raw_ostream &OS) {
1034239462Sdim  IncludeStrongLifetimeRAII Strong(Policy);
1035223017Sdim
1036239462Sdim  switch (T->getUTTKind()) {
1037239462Sdim    case UnaryTransformType::EnumUnderlyingType:
1038239462Sdim      return;
1039239462Sdim  }
1040239462Sdim
1041239462Sdim  printAfter(T->getBaseType(), OS);
1042239462Sdim}
1043239462Sdim
1044341825Sdimvoid TypePrinter::printAutoBefore(const AutoType *T, raw_ostream &OS) {
1045218893Sdim  // If the type has been deduced, do not print 'auto'.
1046251662Sdim  if (!T->getDeducedType().isNull()) {
1047239462Sdim    printBefore(T->getDeducedType(), OS);
1048218893Sdim  } else {
1049360784Sdim    if (T->isConstrained()) {
1050360784Sdim      OS << T->getTypeConstraintConcept()->getName();
1051360784Sdim      auto Args = T->getTypeConstraintArguments();
1052360784Sdim      if (!Args.empty())
1053360784Sdim        printTemplateArgumentList(OS, Args, Policy);
1054360784Sdim      OS << ' ';
1055360784Sdim    }
1056296417Sdim    switch (T->getKeyword()) {
1057296417Sdim    case AutoTypeKeyword::Auto: OS << "auto"; break;
1058296417Sdim    case AutoTypeKeyword::DecltypeAuto: OS << "decltype(auto)"; break;
1059296417Sdim    case AutoTypeKeyword::GNUAutoType: OS << "__auto_type"; break;
1060296417Sdim    }
1061239462Sdim    spaceBeforePlaceHolder(OS);
1062218893Sdim  }
1063218893Sdim}
1064341825Sdim
1065341825Sdimvoid TypePrinter::printAutoAfter(const AutoType *T, raw_ostream &OS) {
1066239462Sdim  // If the type has been deduced, do not print 'auto'.
1067251662Sdim  if (!T->getDeducedType().isNull())
1068239462Sdim    printAfter(T->getDeducedType(), OS);
1069239462Sdim}
1070218893Sdim
1071321369Sdimvoid TypePrinter::printDeducedTemplateSpecializationBefore(
1072321369Sdim    const DeducedTemplateSpecializationType *T, raw_ostream &OS) {
1073321369Sdim  // If the type has been deduced, print the deduced type.
1074321369Sdim  if (!T->getDeducedType().isNull()) {
1075321369Sdim    printBefore(T->getDeducedType(), OS);
1076321369Sdim  } else {
1077321369Sdim    IncludeStrongLifetimeRAII Strong(Policy);
1078321369Sdim    T->getTemplateName().print(OS, Policy);
1079321369Sdim    spaceBeforePlaceHolder(OS);
1080321369Sdim  }
1081321369Sdim}
1082341825Sdim
1083321369Sdimvoid TypePrinter::printDeducedTemplateSpecializationAfter(
1084321369Sdim    const DeducedTemplateSpecializationType *T, raw_ostream &OS) {
1085321369Sdim  // If the type has been deduced, print the deduced type.
1086321369Sdim  if (!T->getDeducedType().isNull())
1087321369Sdim    printAfter(T->getDeducedType(), OS);
1088321369Sdim}
1089321369Sdim
1090239462Sdimvoid TypePrinter::printAtomicBefore(const AtomicType *T, raw_ostream &OS) {
1091226633Sdim  IncludeStrongLifetimeRAII Strong(Policy);
1092226633Sdim
1093239462Sdim  OS << "_Atomic(";
1094239462Sdim  print(T->getValueType(), OS, StringRef());
1095239462Sdim  OS << ')';
1096239462Sdim  spaceBeforePlaceHolder(OS);
1097226633Sdim}
1098226633Sdim
1099341825Sdimvoid TypePrinter::printAtomicAfter(const AtomicType *T, raw_ostream &OS) {}
1100341825Sdim
1101296417Sdimvoid TypePrinter::printPipeBefore(const PipeType *T, raw_ostream &OS) {
1102296417Sdim  IncludeStrongLifetimeRAII Strong(Policy);
1103296417Sdim
1104314564Sdim  if (T->isReadOnly())
1105314564Sdim    OS << "read_only ";
1106314564Sdim  else
1107314564Sdim    OS << "write_only ";
1108309124Sdim  OS << "pipe ";
1109309124Sdim  print(T->getElementType(), OS, StringRef());
1110296417Sdim  spaceBeforePlaceHolder(OS);
1111296417Sdim}
1112296417Sdim
1113341825Sdimvoid TypePrinter::printPipeAfter(const PipeType *T, raw_ostream &OS) {}
1114341825Sdim
1115204962Srdivacky/// Appends the given scope to the end of a string.
1116239462Sdimvoid TypePrinter::AppendScope(DeclContext *DC, raw_ostream &OS) {
1117204962Srdivacky  if (DC->isTranslationUnit()) return;
1118243830Sdim  if (DC->isFunctionOrMethod()) return;
1119239462Sdim  AppendScope(DC->getParent(), OS);
1120204962Srdivacky
1121341825Sdim  if (const auto *NS = dyn_cast<NamespaceDecl>(DC)) {
1122341825Sdim    if (Policy.SuppressUnwrittenScope &&
1123234353Sdim        (NS->isAnonymousNamespace() || NS->isInline()))
1124234353Sdim      return;
1125204962Srdivacky    if (NS->getIdentifier())
1126239462Sdim      OS << NS->getName() << "::";
1127204962Srdivacky    else
1128276479Sdim      OS << "(anonymous namespace)::";
1129341825Sdim  } else if (const auto *Spec = dyn_cast<ClassTemplateSpecializationDecl>(DC)) {
1130224145Sdim    IncludeStrongLifetimeRAII Strong(Policy);
1131239462Sdim    OS << Spec->getIdentifier()->getName();
1132204962Srdivacky    const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs();
1133327952Sdim    printTemplateArgumentList(OS, TemplateArgs.asArray(), Policy);
1134239462Sdim    OS << "::";
1135341825Sdim  } else if (const auto *Tag = dyn_cast<TagDecl>(DC)) {
1136221345Sdim    if (TypedefNameDecl *Typedef = Tag->getTypedefNameForAnonDecl())
1137239462Sdim      OS << Typedef->getIdentifier()->getName() << "::";
1138204962Srdivacky    else if (Tag->getIdentifier())
1139239462Sdim      OS << Tag->getIdentifier()->getName() << "::";
1140234353Sdim    else
1141234353Sdim      return;
1142204962Srdivacky  }
1143204962Srdivacky}
1144204962Srdivacky
1145239462Sdimvoid TypePrinter::printTag(TagDecl *D, raw_ostream &OS) {
1146309124Sdim  if (Policy.IncludeTagDefinition) {
1147309124Sdim    PrintingPolicy SubPolicy = Policy;
1148309124Sdim    SubPolicy.IncludeTagDefinition = false;
1149309124Sdim    D->print(OS, SubPolicy, Indentation);
1150309124Sdim    spaceBeforePlaceHolder(OS);
1151199482Srdivacky    return;
1152309124Sdim  }
1153204962Srdivacky
1154205408Srdivacky  bool HasKindDecoration = false;
1155204962Srdivacky
1156204962Srdivacky  // We don't print tags unless this is an elaborated type.
1157204962Srdivacky  // In C, we just assume every RecordType is an elaborated type.
1158309124Sdim  if (!Policy.SuppressTagKeyword && !D->getTypedefNameForAnonDecl()) {
1159205408Srdivacky    HasKindDecoration = true;
1160239462Sdim    OS << D->getKindName();
1161239462Sdim    OS << ' ';
1162204962Srdivacky  }
1163204962Srdivacky
1164212904Sdim  // Compute the full nested-name-specifier for this type.
1165212904Sdim  // In C, this will always be empty except when the type
1166212904Sdim  // being printed is anonymous within other Record.
1167204962Srdivacky  if (!Policy.SuppressScope)
1168239462Sdim    AppendScope(D->getDeclContext(), OS);
1169204962Srdivacky
1170204962Srdivacky  if (const IdentifierInfo *II = D->getIdentifier())
1171239462Sdim    OS << II->getName();
1172221345Sdim  else if (TypedefNameDecl *Typedef = D->getTypedefNameForAnonDecl()) {
1173199482Srdivacky    assert(Typedef->getIdentifier() && "Typedef without identifier?");
1174239462Sdim    OS << Typedef->getIdentifier()->getName();
1175205408Srdivacky  } else {
1176205408Srdivacky    // Make an unambiguous representation for anonymous types, e.g.
1177276479Sdim    //   (anonymous enum at /usr/include/string.h:120:9)
1178296417Sdim    OS << (Policy.MSVCFormatting ? '`' : '(');
1179296417Sdim
1180234353Sdim    if (isa<CXXRecordDecl>(D) && cast<CXXRecordDecl>(D)->isLambda()) {
1181296417Sdim      OS << "lambda";
1182234353Sdim      HasKindDecoration = true;
1183234353Sdim    } else {
1184296417Sdim      OS << "anonymous";
1185234353Sdim    }
1186341825Sdim
1187206275Srdivacky    if (Policy.AnonymousTagLocations) {
1188206275Srdivacky      // Suppress the redundant tag keyword if we just printed one.
1189206275Srdivacky      // We don't have to worry about ElaboratedTypes here because you can't
1190206275Srdivacky      // refer to an anonymous type with one.
1191206275Srdivacky      if (!HasKindDecoration)
1192206275Srdivacky        OS << " " << D->getKindName();
1193205408Srdivacky
1194218893Sdim      PresumedLoc PLoc = D->getASTContext().getSourceManager().getPresumedLoc(
1195210299Sed          D->getLocation());
1196218893Sdim      if (PLoc.isValid()) {
1197344779Sdim        OS << " at ";
1198344779Sdim        StringRef File = PLoc.getFilename();
1199360784Sdim        if (auto *Callbacks = Policy.Callbacks)
1200360784Sdim          OS << Callbacks->remapPath(File);
1201344779Sdim        else
1202344779Sdim          OS << File;
1203344779Sdim        OS << ':' << PLoc.getLine() << ':' << PLoc.getColumn();
1204210299Sed      }
1205206275Srdivacky    }
1206296417Sdim
1207296417Sdim    OS << (Policy.MSVCFormatting ? '\'' : ')');
1208205408Srdivacky  }
1209205408Srdivacky
1210199482Srdivacky  // If this is a class template specialization, print the template
1211199482Srdivacky  // arguments.
1212341825Sdim  if (const auto *Spec = dyn_cast<ClassTemplateSpecializationDecl>(D)) {
1213309124Sdim    ArrayRef<TemplateArgument> Args;
1214360784Sdim    TypeSourceInfo *TAW = Spec->getTypeAsWritten();
1215360784Sdim    if (!Policy.PrintCanonicalTypes && TAW) {
1216204962Srdivacky      const TemplateSpecializationType *TST =
1217204962Srdivacky        cast<TemplateSpecializationType>(TAW->getType());
1218309124Sdim      Args = TST->template_arguments();
1219204962Srdivacky    } else {
1220204962Srdivacky      const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs();
1221309124Sdim      Args = TemplateArgs.asArray();
1222204962Srdivacky    }
1223224145Sdim    IncludeStrongLifetimeRAII Strong(Policy);
1224327952Sdim    printTemplateArgumentList(OS, Args, Policy);
1225199482Srdivacky  }
1226204962Srdivacky
1227239462Sdim  spaceBeforePlaceHolder(OS);
1228199482Srdivacky}
1229199482Srdivacky
1230239462Sdimvoid TypePrinter::printRecordBefore(const RecordType *T, raw_ostream &OS) {
1231239462Sdim  printTag(T->getDecl(), OS);
1232199482Srdivacky}
1233199482Srdivacky
1234341825Sdimvoid TypePrinter::printRecordAfter(const RecordType *T, raw_ostream &OS) {}
1235341825Sdim
1236341825Sdimvoid TypePrinter::printEnumBefore(const EnumType *T, raw_ostream &OS) {
1237239462Sdim  printTag(T->getDecl(), OS);
1238199482Srdivacky}
1239199482Srdivacky
1240341825Sdimvoid TypePrinter::printEnumAfter(const EnumType *T, raw_ostream &OS) {}
1241341825Sdim
1242341825Sdimvoid TypePrinter::printTemplateTypeParmBefore(const TemplateTypeParmType *T,
1243341825Sdim                                              raw_ostream &OS) {
1244360784Sdim  TemplateTypeParmDecl *D = T->getDecl();
1245360784Sdim  if (D && D->isImplicit()) {
1246360784Sdim    if (auto *TC = D->getTypeConstraint()) {
1247360784Sdim      TC->print(OS, Policy);
1248360784Sdim      OS << ' ';
1249360784Sdim    }
1250360784Sdim    OS << "auto";
1251360784Sdim  } else if (IdentifierInfo *Id = T->getIdentifier())
1252239462Sdim    OS << Id->getName();
1253360784Sdim  else
1254360784Sdim    OS << "type-parameter-" << T->getDepth() << '-' << T->getIndex();
1255353358Sdim
1256239462Sdim  spaceBeforePlaceHolder(OS);
1257199482Srdivacky}
1258199482Srdivacky
1259341825Sdimvoid TypePrinter::printTemplateTypeParmAfter(const TemplateTypeParmType *T,
1260341825Sdim                                             raw_ostream &OS) {}
1261341825Sdim
1262239462Sdimvoid TypePrinter::printSubstTemplateTypeParmBefore(
1263341825Sdim                                             const SubstTemplateTypeParmType *T,
1264341825Sdim                                             raw_ostream &OS) {
1265224145Sdim  IncludeStrongLifetimeRAII Strong(Policy);
1266239462Sdim  printBefore(T->getReplacementType(), OS);
1267199482Srdivacky}
1268341825Sdim
1269239462Sdimvoid TypePrinter::printSubstTemplateTypeParmAfter(
1270341825Sdim                                             const SubstTemplateTypeParmType *T,
1271341825Sdim                                             raw_ostream &OS) {
1272239462Sdim  IncludeStrongLifetimeRAII Strong(Policy);
1273239462Sdim  printAfter(T->getReplacementType(), OS);
1274239462Sdim}
1275199482Srdivacky
1276239462Sdimvoid TypePrinter::printSubstTemplateTypeParmPackBefore(
1277341825Sdim                                        const SubstTemplateTypeParmPackType *T,
1278341825Sdim                                        raw_ostream &OS) {
1279224145Sdim  IncludeStrongLifetimeRAII Strong(Policy);
1280239462Sdim  printTemplateTypeParmBefore(T->getReplacedParameter(), OS);
1281218893Sdim}
1282341825Sdim
1283239462Sdimvoid TypePrinter::printSubstTemplateTypeParmPackAfter(
1284341825Sdim                                        const SubstTemplateTypeParmPackType *T,
1285341825Sdim                                        raw_ostream &OS) {
1286239462Sdim  IncludeStrongLifetimeRAII Strong(Policy);
1287239462Sdim  printTemplateTypeParmAfter(T->getReplacedParameter(), OS);
1288239462Sdim}
1289218893Sdim
1290239462Sdimvoid TypePrinter::printTemplateSpecializationBefore(
1291341825Sdim                                            const TemplateSpecializationType *T,
1292341825Sdim                                            raw_ostream &OS) {
1293224145Sdim  IncludeStrongLifetimeRAII Strong(Policy);
1294239462Sdim  T->getTemplateName().print(OS, Policy);
1295309124Sdim
1296327952Sdim  printTemplateArgumentList(OS, T->template_arguments(), Policy);
1297239462Sdim  spaceBeforePlaceHolder(OS);
1298199482Srdivacky}
1299341825Sdim
1300239462Sdimvoid TypePrinter::printTemplateSpecializationAfter(
1301341825Sdim                                            const TemplateSpecializationType *T,
1302341825Sdim                                            raw_ostream &OS) {}
1303199482Srdivacky
1304239462Sdimvoid TypePrinter::printInjectedClassNameBefore(const InjectedClassNameType *T,
1305239462Sdim                                               raw_ostream &OS) {
1306239462Sdim  printTemplateSpecializationBefore(T->getInjectedTST(), OS);
1307204962Srdivacky}
1308341825Sdim
1309239462Sdimvoid TypePrinter::printInjectedClassNameAfter(const InjectedClassNameType *T,
1310341825Sdim                                               raw_ostream &OS) {}
1311204962Srdivacky
1312239462Sdimvoid TypePrinter::printElaboratedBefore(const ElaboratedType *T,
1313239462Sdim                                        raw_ostream &OS) {
1314341825Sdim  if (Policy.IncludeTagDefinition && T->getOwnedTagDecl()) {
1315341825Sdim    TagDecl *OwnedTagDecl = T->getOwnedTagDecl();
1316341825Sdim    assert(OwnedTagDecl->getTypeForDecl() == T->getNamedType().getTypePtr() &&
1317341825Sdim           "OwnedTagDecl expected to be a declaration for the type");
1318341825Sdim    PrintingPolicy SubPolicy = Policy;
1319341825Sdim    SubPolicy.IncludeTagDefinition = false;
1320341825Sdim    OwnedTagDecl->print(OS, SubPolicy, Indentation);
1321341825Sdim    spaceBeforePlaceHolder(OS);
1322341825Sdim    return;
1323341825Sdim  }
1324341825Sdim
1325309124Sdim  // The tag definition will take care of these.
1326309124Sdim  if (!Policy.IncludeTagDefinition)
1327309124Sdim  {
1328309124Sdim    OS << TypeWithKeyword::getKeywordName(T->getKeyword());
1329309124Sdim    if (T->getKeyword() != ETK_None)
1330309124Sdim      OS << " ";
1331341825Sdim    NestedNameSpecifier *Qualifier = T->getQualifier();
1332309124Sdim    if (Qualifier)
1333309124Sdim      Qualifier->print(OS, Policy);
1334309124Sdim  }
1335341825Sdim
1336239462Sdim  ElaboratedTypePolicyRAII PolicyRAII(Policy);
1337239462Sdim  printBefore(T->getNamedType(), OS);
1338199482Srdivacky}
1339341825Sdim
1340239462Sdimvoid TypePrinter::printElaboratedAfter(const ElaboratedType *T,
1341239462Sdim                                        raw_ostream &OS) {
1342341825Sdim  if (Policy.IncludeTagDefinition && T->getOwnedTagDecl())
1343341825Sdim    return;
1344239462Sdim  ElaboratedTypePolicyRAII PolicyRAII(Policy);
1345239462Sdim  printAfter(T->getNamedType(), OS);
1346239462Sdim}
1347199482Srdivacky
1348239462Sdimvoid TypePrinter::printParenBefore(const ParenType *T, raw_ostream &OS) {
1349239462Sdim  if (!HasEmptyPlaceHolder && !isa<FunctionType>(T->getInnerType())) {
1350239462Sdim    printBefore(T->getInnerType(), OS);
1351239462Sdim    OS << '(';
1352239462Sdim  } else
1353239462Sdim    printBefore(T->getInnerType(), OS);
1354218893Sdim}
1355341825Sdim
1356239462Sdimvoid TypePrinter::printParenAfter(const ParenType *T, raw_ostream &OS) {
1357239462Sdim  if (!HasEmptyPlaceHolder && !isa<FunctionType>(T->getInnerType())) {
1358239462Sdim    OS << ')';
1359239462Sdim    printAfter(T->getInnerType(), OS);
1360239462Sdim  } else
1361239462Sdim    printAfter(T->getInnerType(), OS);
1362239462Sdim}
1363218893Sdim
1364239462Sdimvoid TypePrinter::printDependentNameBefore(const DependentNameType *T,
1365341825Sdim                                           raw_ostream &OS) {
1366239462Sdim  OS << TypeWithKeyword::getKeywordName(T->getKeyword());
1367239462Sdim  if (T->getKeyword() != ETK_None)
1368239462Sdim    OS << " ";
1369341825Sdim
1370239462Sdim  T->getQualifier()->print(OS, Policy);
1371341825Sdim
1372239462Sdim  OS << T->getIdentifier()->getName();
1373239462Sdim  spaceBeforePlaceHolder(OS);
1374210299Sed}
1375341825Sdim
1376239462Sdimvoid TypePrinter::printDependentNameAfter(const DependentNameType *T,
1377341825Sdim                                          raw_ostream &OS) {}
1378210299Sed
1379239462Sdimvoid TypePrinter::printDependentTemplateSpecializationBefore(
1380341825Sdim        const DependentTemplateSpecializationType *T, raw_ostream &OS) {
1381224145Sdim  IncludeStrongLifetimeRAII Strong(Policy);
1382327952Sdim
1383239462Sdim  OS << TypeWithKeyword::getKeywordName(T->getKeyword());
1384239462Sdim  if (T->getKeyword() != ETK_None)
1385239462Sdim    OS << " ";
1386327952Sdim
1387239462Sdim  if (T->getQualifier())
1388327952Sdim    T->getQualifier()->print(OS, Policy);
1389239462Sdim  OS << T->getIdentifier()->getName();
1390327952Sdim  printTemplateArgumentList(OS, T->template_arguments(), Policy);
1391239462Sdim  spaceBeforePlaceHolder(OS);
1392199482Srdivacky}
1393327952Sdim
1394239462Sdimvoid TypePrinter::printDependentTemplateSpecializationAfter(
1395341825Sdim        const DependentTemplateSpecializationType *T, raw_ostream &OS) {}
1396199482Srdivacky
1397341825Sdimvoid TypePrinter::printPackExpansionBefore(const PackExpansionType *T,
1398239462Sdim                                           raw_ostream &OS) {
1399239462Sdim  printBefore(T->getPattern(), OS);
1400218893Sdim}
1401341825Sdim
1402341825Sdimvoid TypePrinter::printPackExpansionAfter(const PackExpansionType *T,
1403239462Sdim                                          raw_ostream &OS) {
1404239462Sdim  printAfter(T->getPattern(), OS);
1405239462Sdim  OS << "...";
1406239462Sdim}
1407218893Sdim
1408239462Sdimvoid TypePrinter::printAttributedBefore(const AttributedType *T,
1409239462Sdim                                        raw_ostream &OS) {
1410344779Sdim  // FIXME: Generate this with TableGen.
1411344779Sdim
1412224145Sdim  // Prefer the macro forms of the GC and ownership qualifiers.
1413344779Sdim  if (T->getAttrKind() == attr::ObjCGC ||
1414344779Sdim      T->getAttrKind() == attr::ObjCOwnership)
1415239462Sdim    return printBefore(T->getEquivalentType(), OS);
1416221345Sdim
1417344779Sdim  if (T->getAttrKind() == attr::ObjCKindOf)
1418288943Sdim    OS << "__kindof ";
1419288943Sdim
1420353358Sdim  if (T->getAttrKind() == attr::AddressSpace)
1421353358Sdim    printBefore(T->getEquivalentType(), OS);
1422353358Sdim  else
1423353358Sdim    printBefore(T->getModifiedType(), OS);
1424261991Sdim
1425261991Sdim  if (T->isMSTypeSpec()) {
1426261991Sdim    switch (T->getAttrKind()) {
1427261991Sdim    default: return;
1428344779Sdim    case attr::Ptr32: OS << " __ptr32"; break;
1429344779Sdim    case attr::Ptr64: OS << " __ptr64"; break;
1430344779Sdim    case attr::SPtr: OS << " __sptr"; break;
1431344779Sdim    case attr::UPtr: OS << " __uptr"; break;
1432261991Sdim    }
1433261991Sdim    spaceBeforePlaceHolder(OS);
1434261991Sdim  }
1435288943Sdim
1436288943Sdim  // Print nullability type specifiers.
1437344779Sdim  if (T->getImmediateNullability()) {
1438344779Sdim    if (T->getAttrKind() == attr::TypeNonNull)
1439288943Sdim      OS << " _Nonnull";
1440344779Sdim    else if (T->getAttrKind() == attr::TypeNullable)
1441288943Sdim      OS << " _Nullable";
1442344779Sdim    else if (T->getAttrKind() == attr::TypeNullUnspecified)
1443288943Sdim      OS << " _Null_unspecified";
1444288943Sdim    else
1445288943Sdim      llvm_unreachable("unhandled nullability");
1446288943Sdim    spaceBeforePlaceHolder(OS);
1447288943Sdim  }
1448239462Sdim}
1449218893Sdim
1450239462Sdimvoid TypePrinter::printAttributedAfter(const AttributedType *T,
1451239462Sdim                                       raw_ostream &OS) {
1452344779Sdim  // FIXME: Generate this with TableGen.
1453344779Sdim
1454239462Sdim  // Prefer the macro forms of the GC and ownership qualifiers.
1455344779Sdim  if (T->getAttrKind() == attr::ObjCGC ||
1456344779Sdim      T->getAttrKind() == attr::ObjCOwnership)
1457239462Sdim    return printAfter(T->getEquivalentType(), OS);
1458239462Sdim
1459261991Sdim  // If this is a calling convention attribute, don't print the implicit CC from
1460261991Sdim  // the modified type.
1461261991Sdim  SaveAndRestore<bool> MaybeSuppressCC(InsideCCAttribute, T->isCallingConv());
1462261991Sdim
1463261991Sdim  printAfter(T->getModifiedType(), OS);
1464261991Sdim
1465344779Sdim  // Some attributes are printed as qualifiers before the type, so we have
1466344779Sdim  // nothing left to do.
1467344779Sdim  if (T->getAttrKind() == attr::ObjCKindOf ||
1468344779Sdim      T->isMSTypeSpec() || T->getImmediateNullability())
1469344779Sdim    return;
1470344779Sdim
1471296417Sdim  // Don't print the inert __unsafe_unretained attribute at all.
1472344779Sdim  if (T->getAttrKind() == attr::ObjCInertUnsafeUnretained)
1473296417Sdim    return;
1474296417Sdim
1475321369Sdim  // Don't print ns_returns_retained unless it had an effect.
1476344779Sdim  if (T->getAttrKind() == attr::NSReturnsRetained &&
1477321369Sdim      !T->getEquivalentType()->castAs<FunctionType>()
1478321369Sdim                             ->getExtInfo().getProducesResult())
1479321369Sdim    return;
1480321369Sdim
1481344779Sdim  if (T->getAttrKind() == attr::LifetimeBound) {
1482344779Sdim    OS << " [[clang::lifetimebound]]";
1483288943Sdim    return;
1484288943Sdim  }
1485288943Sdim
1486344779Sdim  // The printing of the address_space attribute is handled by the qualifier
1487344779Sdim  // since it is still stored in the qualifier. Return early to prevent printing
1488344779Sdim  // this twice.
1489344779Sdim  if (T->getAttrKind() == attr::AddressSpace)
1490341825Sdim    return;
1491341825Sdim
1492239462Sdim  OS << " __attribute__((";
1493218893Sdim  switch (T->getAttrKind()) {
1494344779Sdim#define TYPE_ATTR(NAME)
1495344779Sdim#define DECL_OR_TYPE_ATTR(NAME)
1496344779Sdim#define ATTR(NAME) case attr::NAME:
1497344779Sdim#include "clang/Basic/AttrList.inc"
1498344779Sdim    llvm_unreachable("non-type attribute attached to type");
1499341825Sdim
1500344779Sdim  case attr::OpenCLPrivateAddressSpace:
1501344779Sdim  case attr::OpenCLGlobalAddressSpace:
1502344779Sdim  case attr::OpenCLLocalAddressSpace:
1503344779Sdim  case attr::OpenCLConstantAddressSpace:
1504344779Sdim  case attr::OpenCLGenericAddressSpace:
1505344779Sdim    // FIXME: Update printAttributedBefore to print these once we generate
1506344779Sdim    // AttributedType nodes for them.
1507218893Sdim    break;
1508218893Sdim
1509344779Sdim  case attr::LifetimeBound:
1510344779Sdim  case attr::TypeNonNull:
1511344779Sdim  case attr::TypeNullable:
1512344779Sdim  case attr::TypeNullUnspecified:
1513344779Sdim  case attr::ObjCGC:
1514344779Sdim  case attr::ObjCInertUnsafeUnretained:
1515344779Sdim  case attr::ObjCKindOf:
1516344779Sdim  case attr::ObjCOwnership:
1517344779Sdim  case attr::Ptr32:
1518344779Sdim  case attr::Ptr64:
1519344779Sdim  case attr::SPtr:
1520344779Sdim  case attr::UPtr:
1521344779Sdim  case attr::AddressSpace:
1522344779Sdim    llvm_unreachable("This attribute should have been handled already");
1523218893Sdim
1524344779Sdim  case attr::NSReturnsRetained:
1525321369Sdim    OS << "ns_returns_retained";
1526321369Sdim    break;
1527321369Sdim
1528261991Sdim  // FIXME: When Sema learns to form this AttributedType, avoid printing the
1529261991Sdim  // attribute again in printFunctionProtoAfter.
1530344779Sdim  case attr::AnyX86NoCfCheck: OS << "nocf_check"; break;
1531344779Sdim  case attr::CDecl: OS << "cdecl"; break;
1532344779Sdim  case attr::FastCall: OS << "fastcall"; break;
1533344779Sdim  case attr::StdCall: OS << "stdcall"; break;
1534344779Sdim  case attr::ThisCall: OS << "thiscall"; break;
1535344779Sdim  case attr::SwiftCall: OS << "swiftcall"; break;
1536344779Sdim  case attr::VectorCall: OS << "vectorcall"; break;
1537344779Sdim  case attr::Pascal: OS << "pascal"; break;
1538344779Sdim  case attr::MSABI: OS << "ms_abi"; break;
1539344779Sdim  case attr::SysVABI: OS << "sysv_abi"; break;
1540344779Sdim  case attr::RegCall: OS << "regcall"; break;
1541344779Sdim  case attr::Pcs: {
1542239462Sdim    OS << "pcs(";
1543221345Sdim   QualType t = T->getEquivalentType();
1544221345Sdim   while (!t->isFunctionType())
1545221345Sdim     t = t->getPointeeType();
1546360784Sdim   OS << (t->castAs<FunctionType>()->getCallConv() == CC_AAPCS ?
1547221345Sdim         "\"aapcs\"" : "\"aapcs-vfp\"");
1548239462Sdim   OS << ')';
1549221345Sdim   break;
1550218893Sdim  }
1551344779Sdim  case attr::AArch64VectorPcs: OS << "aarch64_vector_pcs"; break;
1552344779Sdim  case attr::IntelOclBicc: OS << "inteloclbicc"; break;
1553344779Sdim  case attr::PreserveMost:
1554309124Sdim    OS << "preserve_most";
1555309124Sdim    break;
1556341825Sdim
1557344779Sdim  case attr::PreserveAll:
1558309124Sdim    OS << "preserve_all";
1559309124Sdim    break;
1560344779Sdim  case attr::NoDeref:
1561344779Sdim    OS << "noderef";
1562344779Sdim    break;
1563360784Sdim  case attr::AcquireHandle:
1564360784Sdim    OS << "acquire_handle";
1565360784Sdim    break;
1566221345Sdim  }
1567239462Sdim  OS << "))";
1568218893Sdim}
1569218893Sdim
1570341825Sdimvoid TypePrinter::printObjCInterfaceBefore(const ObjCInterfaceType *T,
1571341825Sdim                                           raw_ostream &OS) {
1572239462Sdim  OS << T->getDecl()->getName();
1573239462Sdim  spaceBeforePlaceHolder(OS);
1574199482Srdivacky}
1575199482Srdivacky
1576341825Sdimvoid TypePrinter::printObjCInterfaceAfter(const ObjCInterfaceType *T,
1577341825Sdim                                          raw_ostream &OS) {}
1578341825Sdim
1579314564Sdimvoid TypePrinter::printObjCTypeParamBefore(const ObjCTypeParamType *T,
1580314564Sdim                                          raw_ostream &OS) {
1581314564Sdim  OS << T->getDecl()->getName();
1582314564Sdim  if (!T->qual_empty()) {
1583314564Sdim    bool isFirst = true;
1584314564Sdim    OS << '<';
1585314564Sdim    for (const auto *I : T->quals()) {
1586314564Sdim      if (isFirst)
1587314564Sdim        isFirst = false;
1588314564Sdim      else
1589314564Sdim        OS << ',';
1590314564Sdim      OS << I->getName();
1591314564Sdim    }
1592314564Sdim    OS << '>';
1593314564Sdim  }
1594314564Sdim
1595314564Sdim  spaceBeforePlaceHolder(OS);
1596314564Sdim}
1597314564Sdim
1598314564Sdimvoid TypePrinter::printObjCTypeParamAfter(const ObjCTypeParamType *T,
1599341825Sdim                                          raw_ostream &OS) {}
1600314564Sdim
1601239462Sdimvoid TypePrinter::printObjCObjectBefore(const ObjCObjectType *T,
1602239462Sdim                                        raw_ostream &OS) {
1603288943Sdim  if (T->qual_empty() && T->isUnspecializedAsWritten() &&
1604288943Sdim      !T->isKindOfTypeAsWritten())
1605239462Sdim    return printBefore(T->getBaseType(), OS);
1606208600Srdivacky
1607288943Sdim  if (T->isKindOfTypeAsWritten())
1608288943Sdim    OS << "__kindof ";
1609288943Sdim
1610239462Sdim  print(T->getBaseType(), OS, StringRef());
1611288943Sdim
1612288943Sdim  if (T->isSpecializedAsWritten()) {
1613288943Sdim    bool isFirst = true;
1614288943Sdim    OS << '<';
1615288943Sdim    for (auto typeArg : T->getTypeArgsAsWritten()) {
1616288943Sdim      if (isFirst)
1617288943Sdim        isFirst = false;
1618288943Sdim      else
1619288943Sdim        OS << ",";
1620288943Sdim
1621288943Sdim      print(typeArg, OS, StringRef());
1622288943Sdim    }
1623288943Sdim    OS << '>';
1624208600Srdivacky  }
1625288943Sdim
1626288943Sdim  if (!T->qual_empty()) {
1627288943Sdim    bool isFirst = true;
1628288943Sdim    OS << '<';
1629288943Sdim    for (const auto *I : T->quals()) {
1630288943Sdim      if (isFirst)
1631288943Sdim        isFirst = false;
1632288943Sdim      else
1633288943Sdim        OS << ',';
1634288943Sdim      OS << I->getName();
1635288943Sdim    }
1636288943Sdim    OS << '>';
1637288943Sdim  }
1638288943Sdim
1639239462Sdim  spaceBeforePlaceHolder(OS);
1640208600Srdivacky}
1641341825Sdim
1642239462Sdimvoid TypePrinter::printObjCObjectAfter(const ObjCObjectType *T,
1643239462Sdim                                        raw_ostream &OS) {
1644288943Sdim  if (T->qual_empty() && T->isUnspecializedAsWritten() &&
1645288943Sdim      !T->isKindOfTypeAsWritten())
1646239462Sdim    return printAfter(T->getBaseType(), OS);
1647239462Sdim}
1648208600Srdivacky
1649341825Sdimvoid TypePrinter::printObjCObjectPointerBefore(const ObjCObjectPointerType *T,
1650239462Sdim                                               raw_ostream &OS) {
1651288943Sdim  printBefore(T->getPointeeType(), OS);
1652239462Sdim
1653288943Sdim  // If we need to print the pointer, print it now.
1654276479Sdim  if (!T->isObjCIdType() && !T->isObjCQualifiedIdType() &&
1655276479Sdim      !T->isObjCClassType() && !T->isObjCQualifiedClassType()) {
1656288943Sdim    if (HasEmptyPlaceHolder)
1657288943Sdim      OS << ' ';
1658288943Sdim    OS << '*';
1659239462Sdim  }
1660239462Sdim}
1661327952Sdim
1662341825Sdimvoid TypePrinter::printObjCObjectPointerAfter(const ObjCObjectPointerType *T,
1663341825Sdim                                              raw_ostream &OS) {}
1664239462Sdim
1665327952Sdimstatic
1666327952Sdimconst TemplateArgument &getArgument(const TemplateArgument &A) { return A; }
1667327952Sdim
1668327952Sdimstatic const TemplateArgument &getArgument(const TemplateArgumentLoc &A) {
1669327952Sdim  return A.getArgument();
1670239462Sdim}
1671239462Sdim
1672353358Sdimstatic void printArgument(const TemplateArgument &A, const PrintingPolicy &PP,
1673353358Sdim                          llvm::raw_ostream &OS) {
1674353358Sdim  A.print(PP, OS);
1675353358Sdim}
1676353358Sdim
1677353358Sdimstatic void printArgument(const TemplateArgumentLoc &A,
1678353358Sdim                          const PrintingPolicy &PP, llvm::raw_ostream &OS) {
1679353358Sdim  const TemplateArgument::ArgKind &Kind = A.getArgument().getKind();
1680353358Sdim  if (Kind == TemplateArgument::ArgKind::Type)
1681353358Sdim    return A.getTypeSourceInfo()->getType().print(OS, PP);
1682353358Sdim  return A.getArgument().print(PP, OS);
1683353358Sdim}
1684353358Sdim
1685327952Sdimtemplate<typename TA>
1686327952Sdimstatic void printTo(raw_ostream &OS, ArrayRef<TA> Args,
1687327952Sdim                    const PrintingPolicy &Policy, bool SkipBrackets) {
1688296417Sdim  const char *Comma = Policy.MSVCFormatting ? "," : ", ";
1689239462Sdim  if (!SkipBrackets)
1690239462Sdim    OS << '<';
1691309124Sdim
1692327952Sdim  bool NeedSpace = false;
1693309124Sdim  bool FirstArg = true;
1694327952Sdim  for (const auto &Arg : Args) {
1695239462Sdim    // Print the argument into a string.
1696239462Sdim    SmallString<128> Buf;
1697239462Sdim    llvm::raw_svector_ostream ArgOS(Buf);
1698327952Sdim    const TemplateArgument &Argument = getArgument(Arg);
1699327952Sdim    if (Argument.getKind() == TemplateArgument::Pack) {
1700327952Sdim      if (Argument.pack_size() && !FirstArg)
1701296417Sdim        OS << Comma;
1702327952Sdim      printTo(ArgOS, Argument.getPackAsArray(), Policy, true);
1703239462Sdim    } else {
1704309124Sdim      if (!FirstArg)
1705296417Sdim        OS << Comma;
1706353358Sdim      // Tries to print the argument with location info if exists.
1707353358Sdim      printArgument(Arg, Policy, ArgOS);
1708239462Sdim    }
1709239462Sdim    StringRef ArgString = ArgOS.str();
1710239462Sdim
1711239462Sdim    // If this is the first argument and its string representation
1712239462Sdim    // begins with the global scope specifier ('::foo'), add a space
1713239462Sdim    // to avoid printing the diagraph '<:'.
1714309124Sdim    if (FirstArg && !ArgString.empty() && ArgString[0] == ':')
1715239462Sdim      OS << ' ';
1716239462Sdim
1717239462Sdim    OS << ArgString;
1718239462Sdim
1719327952Sdim    NeedSpace = (!ArgString.empty() && ArgString.back() == '>');
1720309124Sdim    FirstArg = false;
1721239462Sdim  }
1722239462Sdim
1723239462Sdim  // If the last character of our string is '>', add another space to
1724239462Sdim  // keep the two '>''s separate tokens. We don't *have* to do this in
1725239462Sdim  // C++0x, but it's still good hygiene.
1726327952Sdim  if (NeedSpace)
1727239462Sdim    OS << ' ';
1728239462Sdim
1729239462Sdim  if (!SkipBrackets)
1730239462Sdim    OS << '>';
1731199482Srdivacky}
1732199482Srdivacky
1733327952Sdimvoid clang::printTemplateArgumentList(raw_ostream &OS,
1734327952Sdim                                      const TemplateArgumentListInfo &Args,
1735327952Sdim                                      const PrintingPolicy &Policy) {
1736327952Sdim  return printTo(OS, Args.arguments(), Policy, false);
1737327952Sdim}
1738239462Sdim
1739327952Sdimvoid clang::printTemplateArgumentList(raw_ostream &OS,
1740327952Sdim                                      ArrayRef<TemplateArgument> Args,
1741327952Sdim                                      const PrintingPolicy &Policy) {
1742327952Sdim  printTo(OS, Args, Policy, false);
1743327952Sdim}
1744309124Sdim
1745327952Sdimvoid clang::printTemplateArgumentList(raw_ostream &OS,
1746327952Sdim                                      ArrayRef<TemplateArgumentLoc> Args,
1747327952Sdim                                      const PrintingPolicy &Policy) {
1748327952Sdim  printTo(OS, Args, Policy, false);
1749239462Sdim}
1750239462Sdim
1751199482Srdivackystd::string Qualifiers::getAsString() const {
1752199482Srdivacky  LangOptions LO;
1753199482Srdivacky  return getAsString(PrintingPolicy(LO));
1754199482Srdivacky}
1755199482Srdivacky
1756199482Srdivacky// Appends qualifiers to the given string, separated by spaces.  Will
1757199482Srdivacky// prefix a space if the string is non-empty.  Will not append a final
1758199482Srdivacky// space.
1759239462Sdimstd::string Qualifiers::getAsString(const PrintingPolicy &Policy) const {
1760239462Sdim  SmallString<64> Buf;
1761239462Sdim  llvm::raw_svector_ostream StrOS(Buf);
1762239462Sdim  print(StrOS, Policy);
1763239462Sdim  return StrOS.str();
1764239462Sdim}
1765239462Sdim
1766239462Sdimbool Qualifiers::isEmptyWhenPrinted(const PrintingPolicy &Policy) const {
1767239462Sdim  if (getCVRQualifiers())
1768239462Sdim    return false;
1769239462Sdim
1770327952Sdim  if (getAddressSpace() != LangAS::Default)
1771239462Sdim    return false;
1772239462Sdim
1773239462Sdim  if (getObjCGCAttr())
1774239462Sdim    return false;
1775239462Sdim
1776239462Sdim  if (Qualifiers::ObjCLifetime lifetime = getObjCLifetime())
1777239462Sdim    if (!(lifetime == Qualifiers::OCL_Strong && Policy.SuppressStrongLifetime))
1778239462Sdim      return false;
1779239462Sdim
1780239462Sdim  return true;
1781239462Sdim}
1782239462Sdim
1783360784Sdimstd::string Qualifiers::getAddrSpaceAsString(LangAS AS) {
1784360784Sdim  switch (AS) {
1785360784Sdim  case LangAS::Default:
1786360784Sdim    return "";
1787360784Sdim  case LangAS::opencl_global:
1788360784Sdim    return "__global";
1789360784Sdim  case LangAS::opencl_local:
1790360784Sdim    return "__local";
1791360784Sdim  case LangAS::opencl_private:
1792360784Sdim    return "__private";
1793360784Sdim  case LangAS::opencl_constant:
1794360784Sdim    return "__constant";
1795360784Sdim  case LangAS::opencl_generic:
1796360784Sdim    return "__generic";
1797360784Sdim  case LangAS::cuda_device:
1798360784Sdim    return "__device__";
1799360784Sdim  case LangAS::cuda_constant:
1800360784Sdim    return "__constant__";
1801360784Sdim  case LangAS::cuda_shared:
1802360784Sdim    return "__shared__";
1803360784Sdim  case LangAS::ptr32_sptr:
1804360784Sdim    return "__sptr __ptr32";
1805360784Sdim  case LangAS::ptr32_uptr:
1806360784Sdim    return "__uptr __ptr32";
1807360784Sdim  case LangAS::ptr64:
1808360784Sdim    return "__ptr64";
1809360784Sdim  default:
1810360784Sdim    return std::to_string(toTargetAddressSpace(AS));
1811360784Sdim  }
1812360784Sdim}
1813360784Sdim
1814239462Sdim// Appends qualifiers to the given string, separated by spaces.  Will
1815239462Sdim// prefix a space if the string is non-empty.  Will not append a final
1816239462Sdim// space.
1817239462Sdimvoid Qualifiers::print(raw_ostream &OS, const PrintingPolicy& Policy,
1818239462Sdim                       bool appendSpaceIfNonEmpty) const {
1819239462Sdim  bool addSpace = false;
1820239462Sdim
1821239462Sdim  unsigned quals = getCVRQualifiers();
1822239462Sdim  if (quals) {
1823309124Sdim    AppendTypeQualList(OS, quals, Policy.Restrict);
1824239462Sdim    addSpace = true;
1825239462Sdim  }
1826309124Sdim  if (hasUnaligned()) {
1827309124Sdim    if (addSpace)
1828309124Sdim      OS << ' ';
1829309124Sdim    OS << "__unaligned";
1830309124Sdim    addSpace = true;
1831309124Sdim  }
1832360784Sdim  auto ASStr = getAddrSpaceAsString(getAddressSpace());
1833360784Sdim  if (!ASStr.empty()) {
1834360784Sdim    if (addSpace)
1835360784Sdim      OS << ' ';
1836360784Sdim    addSpace = true;
1837360784Sdim    // Wrap target address space into an attribute syntax
1838360784Sdim    if (isTargetAddressSpace(getAddressSpace()))
1839360784Sdim      OS << "__attribute__((address_space(" << ASStr << ")))";
1840360784Sdim    else
1841360784Sdim      OS << ASStr;
1842199482Srdivacky  }
1843360784Sdim
1844221345Sdim  if (Qualifiers::GC gc = getObjCGCAttr()) {
1845239462Sdim    if (addSpace)
1846239462Sdim      OS << ' ';
1847239462Sdim    addSpace = true;
1848221345Sdim    if (gc == Qualifiers::Weak)
1849239462Sdim      OS << "__weak";
1850199482Srdivacky    else
1851239462Sdim      OS << "__strong";
1852199482Srdivacky  }
1853224145Sdim  if (Qualifiers::ObjCLifetime lifetime = getObjCLifetime()) {
1854239462Sdim    if (!(lifetime == Qualifiers::OCL_Strong && Policy.SuppressStrongLifetime)){
1855239462Sdim      if (addSpace)
1856239462Sdim        OS << ' ';
1857239462Sdim      addSpace = true;
1858239462Sdim    }
1859239462Sdim
1860224145Sdim    switch (lifetime) {
1861224145Sdim    case Qualifiers::OCL_None: llvm_unreachable("none but true");
1862239462Sdim    case Qualifiers::OCL_ExplicitNone: OS << "__unsafe_unretained"; break;
1863341825Sdim    case Qualifiers::OCL_Strong:
1864224145Sdim      if (!Policy.SuppressStrongLifetime)
1865341825Sdim        OS << "__strong";
1866224145Sdim      break;
1867341825Sdim
1868239462Sdim    case Qualifiers::OCL_Weak: OS << "__weak"; break;
1869239462Sdim    case Qualifiers::OCL_Autoreleasing: OS << "__autoreleasing"; break;
1870224145Sdim    }
1871224145Sdim  }
1872239462Sdim
1873239462Sdim  if (appendSpaceIfNonEmpty && addSpace)
1874239462Sdim    OS << ' ';
1875199482Srdivacky}
1876199482Srdivacky
1877327952Sdimstd::string QualType::getAsString() const {
1878327952Sdim  return getAsString(split(), LangOptions());
1879327952Sdim}
1880327952Sdim
1881239462Sdimstd::string QualType::getAsString(const PrintingPolicy &Policy) const {
1882239462Sdim  std::string S;
1883239462Sdim  getAsStringInternal(S, Policy);
1884239462Sdim  return S;
1885239462Sdim}
1886239462Sdim
1887327952Sdimstd::string QualType::getAsString(const Type *ty, Qualifiers qs,
1888327952Sdim                                  const PrintingPolicy &Policy) {
1889218893Sdim  std::string buffer;
1890327952Sdim  getAsStringInternal(ty, qs, buffer, Policy);
1891218893Sdim  return buffer;
1892199482Srdivacky}
1893199482Srdivacky
1894344779Sdimvoid QualType::print(raw_ostream &OS, const PrintingPolicy &Policy,
1895344779Sdim                     const Twine &PlaceHolder, unsigned Indentation) const {
1896344779Sdim  print(splitAccordingToPolicy(*this, Policy), OS, Policy, PlaceHolder,
1897344779Sdim        Indentation);
1898344779Sdim}
1899344779Sdim
1900239462Sdimvoid QualType::print(const Type *ty, Qualifiers qs,
1901239462Sdim                     raw_ostream &OS, const PrintingPolicy &policy,
1902309124Sdim                     const Twine &PlaceHolder, unsigned Indentation) {
1903239462Sdim  SmallString<128> PHBuf;
1904249423Sdim  StringRef PH = PlaceHolder.toStringRef(PHBuf);
1905239462Sdim
1906309124Sdim  TypePrinter(policy, Indentation).print(ty, qs, OS, PH);
1907239462Sdim}
1908239462Sdim
1909344779Sdimvoid QualType::getAsStringInternal(std::string &Str,
1910344779Sdim                                   const PrintingPolicy &Policy) const {
1911344779Sdim  return getAsStringInternal(splitAccordingToPolicy(*this, Policy), Str,
1912344779Sdim                             Policy);
1913344779Sdim}
1914344779Sdim
1915218893Sdimvoid QualType::getAsStringInternal(const Type *ty, Qualifiers qs,
1916218893Sdim                                   std::string &buffer,
1917218893Sdim                                   const PrintingPolicy &policy) {
1918239462Sdim  SmallString<256> Buf;
1919239462Sdim  llvm::raw_svector_ostream StrOS(Buf);
1920239462Sdim  TypePrinter(policy).print(ty, qs, StrOS, buffer);
1921239462Sdim  std::string str = StrOS.str();
1922239462Sdim  buffer.swap(str);
1923199482Srdivacky}
1924