summaryrefslogtreecommitdiffstats
path: root/lib/AST/TypePrinter.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/AST/TypePrinter.cpp')
-rw-r--r--lib/AST/TypePrinter.cpp130
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();
OpenPOWER on IntegriCloud