diff options
Diffstat (limited to 'lib/AST/TypePrinter.cpp')
-rw-r--r-- | lib/AST/TypePrinter.cpp | 130 |
1 files changed, 94 insertions, 36 deletions
diff --git a/lib/AST/TypePrinter.cpp b/lib/AST/TypePrinter.cpp index 0437076..571e3db 100644 --- a/lib/AST/TypePrinter.cpp +++ b/lib/AST/TypePrinter.cpp @@ -36,7 +36,8 @@ namespace { public: explicit IncludeStrongLifetimeRAII(PrintingPolicy &Policy) : Policy(Policy), Old(Policy.SuppressStrongLifetime) { - Policy.SuppressStrongLifetime = false; + if (!Policy.SuppressLifetimeQualifiers) + Policy.SuppressStrongLifetime = false; } ~IncludeStrongLifetimeRAII() { @@ -81,10 +82,11 @@ namespace { class TypePrinter { PrintingPolicy Policy; bool HasEmptyPlaceHolder; + bool InsideCCAttribute; public: explicit TypePrinter(const PrintingPolicy &Policy) - : Policy(Policy), HasEmptyPlaceHolder(false) { } + : Policy(Policy), HasEmptyPlaceHolder(false), InsideCCAttribute(false) { } void print(const Type *ty, Qualifiers qs, raw_ostream &OS, StringRef PlaceHolder); @@ -166,6 +168,7 @@ bool TypePrinter::canPrefixQualifiers(const Type *T, TC = Subst->getReplacementType()->getTypeClass(); switch (TC) { + case Type::Auto: case Type::Builtin: case Type::Complex: case Type::UnresolvedUsing: @@ -201,6 +204,7 @@ bool TypePrinter::canPrefixQualifiers(const Type *T, NeedARCStrongQualifier = true; // Fall through + case Type::Decayed: case Type::Pointer: case Type::BlockPointer: case Type::LValueReference: @@ -215,7 +219,6 @@ bool TypePrinter::canPrefixQualifiers(const Type *T, case Type::Attributed: case Type::PackExpansion: case Type::SubstTemplateTypeParm: - case Type::Auto: CanPrefixQualifiers = false; break; } @@ -468,6 +471,14 @@ void TypePrinter::printVariableArrayAfter(const VariableArrayType *T, printAfter(T->getElementType(), OS); } +void TypePrinter::printDecayedBefore(const DecayedType *T, raw_ostream &OS) { + // Print as though it's a pointer. + printBefore(T->getDecayedType(), OS); +} +void TypePrinter::printDecayedAfter(const DecayedType *T, raw_ostream &OS) { + printAfter(T->getDecayedType(), OS); +} + void TypePrinter::printDependentSizedArrayBefore( const DependentSizedArrayType *T, raw_ostream &OS) { @@ -621,36 +632,51 @@ void TypePrinter::printFunctionProtoAfter(const FunctionProtoType *T, OS << ')'; FunctionType::ExtInfo Info = T->getExtInfo(); - switch(Info.getCC()) { - case CC_Default: break; - case CC_C: - OS << " __attribute__((cdecl))"; - break; - case CC_X86StdCall: - OS << " __attribute__((stdcall))"; - break; - case CC_X86FastCall: - OS << " __attribute__((fastcall))"; - break; - case CC_X86ThisCall: - OS << " __attribute__((thiscall))"; - break; - case CC_X86Pascal: - OS << " __attribute__((pascal))"; - break; - case CC_AAPCS: - OS << " __attribute__((pcs(\"aapcs\")))"; - break; - case CC_AAPCS_VFP: - OS << " __attribute__((pcs(\"aapcs-vfp\")))"; - break; - case CC_PnaclCall: - OS << " __attribute__((pnaclcall))"; - break; - case CC_IntelOclBicc: - OS << " __attribute__((intel_ocl_bicc))"; - break; + + if (!InsideCCAttribute) { + switch (Info.getCC()) { + case CC_C: + // The C calling convention is the default on the vast majority of platforms + // we support. If the user wrote it explicitly, it will usually be printed + // while traversing the AttributedType. If the type has been desugared, let + // the canonical spelling be the implicit calling convention. + // FIXME: It would be better to be explicit in certain contexts, such as a + // cdecl function typedef used to declare a member function with the + // Microsoft C++ ABI. + break; + case CC_X86StdCall: + OS << " __attribute__((stdcall))"; + break; + case CC_X86FastCall: + OS << " __attribute__((fastcall))"; + break; + case CC_X86ThisCall: + OS << " __attribute__((thiscall))"; + break; + case CC_X86Pascal: + OS << " __attribute__((pascal))"; + break; + case CC_AAPCS: + OS << " __attribute__((pcs(\"aapcs\")))"; + break; + case CC_AAPCS_VFP: + OS << " __attribute__((pcs(\"aapcs-vfp\")))"; + break; + case CC_PnaclCall: + OS << " __attribute__((pnaclcall))"; + break; + case CC_IntelOclBicc: + OS << " __attribute__((intel_ocl_bicc))"; + break; + case CC_X86_64Win64: + OS << " __attribute__((ms_abi))"; + break; + case CC_X86_64SysV: + OS << " __attribute__((sysv_abi))"; + break; + } } + if (Info.getNoReturn()) OS << " __attribute__((noreturn))"; if (Info.getRegParm()) @@ -989,6 +1015,8 @@ void TypePrinter::printInjectedClassNameAfter(const InjectedClassNameType *T, void TypePrinter::printElaboratedBefore(const ElaboratedType *T, raw_ostream &OS) { + if (Policy.SuppressTag && isa<TagType>(T->getNamedType())) + return; OS << TypeWithKeyword::getKeywordName(T->getKeyword()); if (T->getKeyword() != ETK_None) OS << " "; @@ -1072,6 +1100,17 @@ void TypePrinter::printAttributedBefore(const AttributedType *T, return printBefore(T->getEquivalentType(), OS); printBefore(T->getModifiedType(), OS); + + if (T->isMSTypeSpec()) { + switch (T->getAttrKind()) { + default: return; + case AttributedType::attr_ptr32: OS << " __ptr32"; break; + case AttributedType::attr_ptr64: OS << " __ptr64"; break; + case AttributedType::attr_sptr: OS << " __sptr"; break; + case AttributedType::attr_uptr: OS << " __uptr"; break; + } + spaceBeforePlaceHolder(OS); + } } void TypePrinter::printAttributedAfter(const AttributedType *T, @@ -1082,8 +1121,18 @@ void TypePrinter::printAttributedAfter(const AttributedType *T, return printAfter(T->getEquivalentType(), OS); // TODO: not all attributes are GCC-style attributes. + if (T->isMSTypeSpec()) + return; + + // If this is a calling convention attribute, don't print the implicit CC from + // the modified type. + SaveAndRestore<bool> MaybeSuppressCC(InsideCCAttribute, T->isCallingConv()); + + printAfter(T->getModifiedType(), OS); + OS << " __attribute__(("; switch (T->getAttrKind()) { + default: llvm_unreachable("This attribute should have been handled already"); case AttributedType::attr_address_space: OS << "address_space("; OS << T->getEquivalentType().getAddressSpace(); @@ -1115,6 +1164,8 @@ void TypePrinter::printAttributedAfter(const AttributedType *T, } case AttributedType::attr_regparm: { + // FIXME: When Sema learns to form this AttributedType, avoid printing the + // attribute again in printFunctionProtoAfter. OS << "regparm("; QualType t = T->getEquivalentType(); while (!t->isFunctionType()) @@ -1154,13 +1205,19 @@ void TypePrinter::printAttributedAfter(const AttributedType *T, OS << ')'; break; + // FIXME: When Sema learns to form this AttributedType, avoid printing the + // attribute again in printFunctionProtoAfter. case AttributedType::attr_noreturn: OS << "noreturn"; break; + case AttributedType::attr_cdecl: OS << "cdecl"; break; case AttributedType::attr_fastcall: OS << "fastcall"; break; case AttributedType::attr_stdcall: OS << "stdcall"; break; case AttributedType::attr_thiscall: OS << "thiscall"; break; case AttributedType::attr_pascal: OS << "pascal"; break; - case AttributedType::attr_pcs: { + case AttributedType::attr_ms_abi: OS << "ms_abi"; break; + case AttributedType::attr_sysv_abi: OS << "sysv_abi"; break; + case AttributedType::attr_pcs: + case AttributedType::attr_pcs_vfp: { OS << "pcs("; QualType t = T->getEquivalentType(); while (!t->isFunctionType()) @@ -1266,18 +1323,19 @@ TemplateSpecializationType::PrintTemplateArgumentList( bool needSpace = false; for (unsigned Arg = 0; Arg < NumArgs; ++Arg) { - if (Arg > 0) - OS << ", "; - // Print the argument into a string. SmallString<128> Buf; llvm::raw_svector_ostream ArgOS(Buf); if (Args[Arg].getKind() == TemplateArgument::Pack) { + if (Args[Arg].pack_size() && Arg > 0) + OS << ", "; PrintTemplateArgumentList(ArgOS, Args[Arg].pack_begin(), Args[Arg].pack_size(), Policy, true); } else { + if (Arg > 0) + OS << ", "; Args[Arg].print(Policy, ArgOS); } StringRef ArgString = ArgOS.str(); |