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