diff options
author | Reid Kleckner <reid@kleckner.net> | 2013-07-19 19:51:03 +0000 |
---|---|---|
committer | Reid Kleckner <reid@kleckner.net> | 2013-07-19 19:51:03 +0000 |
commit | 569b8f83a4188048c910cf50050ea8c6ea31293f (patch) | |
tree | 946bfa25a5053ba62f31e7b31740d46602d6eaec /clang/lib | |
parent | 8917ad5d1f1f336dcbb42bd395b02ee0a8618688 (diff) | |
download | bcm5719-llvm-569b8f83a4188048c910cf50050ea8c6ea31293f.tar.gz bcm5719-llvm-569b8f83a4188048c910cf50050ea8c6ea31293f.zip |
Create calling convention AttributedType sugar nodes
Canonical types are unchanged. The type printer had to be changed to
avoid printing any non-default implicit calling convention as well as
the calling convention attribute.
Reviewers: rjmccall
Differential Revision: http://llvm-reviews.chandlerc.com/D1132
llvm-svn: 186714
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/AST/Type.cpp | 41 | ||||
-rw-r--r-- | clang/lib/AST/TypePrinter.cpp | 73 | ||||
-rw-r--r-- | clang/lib/Sema/SemaType.cpp | 45 |
3 files changed, 121 insertions, 38 deletions
diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp index 4068b2b8988..44da348b0b7 100644 --- a/clang/lib/AST/Type.cpp +++ b/clang/lib/AST/Type.cpp @@ -1842,6 +1842,47 @@ bool TagType::isBeingDefined() const { return getDecl()->isBeingDefined(); } +bool AttributedType::isMSTypeSpec() const { + switch (getAttrKind()) { + default: return false; + case attr_ptr32: + case attr_ptr64: + case attr_sptr: + case attr_uptr: + return true; + } + llvm_unreachable("invalid attr kind"); +} + +bool AttributedType::isCallingConv() const { + switch (getAttrKind()) { + case attr_ptr32: + case attr_ptr64: + case attr_sptr: + case attr_uptr: + case attr_address_space: + case attr_regparm: + case attr_vector_size: + case attr_neon_vector_type: + case attr_neon_polyvector_type: + case attr_objc_gc: + case attr_objc_ownership: + case attr_noreturn: + return false; + case attr_pcs: + case attr_pcs_vfp: + case attr_cdecl: + case attr_fastcall: + case attr_stdcall: + case attr_thiscall: + case attr_pascal: + case attr_pnaclcall: + case attr_inteloclbicc: + return true; + } + llvm_unreachable("invalid attr kind"); +} + CXXRecordDecl *InjectedClassNameType::getDecl() const { return cast<CXXRecordDecl>(getInterestingTagDecl(Decl)); } diff --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp index d19c6a94508..3b917aa33fb 100644 --- a/clang/lib/AST/TypePrinter.cpp +++ b/clang/lib/AST/TypePrinter.cpp @@ -81,10 +81,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); @@ -630,36 +631,40 @@ 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_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 (Info.getNoReturn()) OS << " __attribute__((noreturn))"; if (Info.getRegParm()) @@ -1089,7 +1094,7 @@ void TypePrinter::printAttributedBefore(const AttributedType *T, case AttributedType::attr_ptr64: OS << " __ptr64"; break; case AttributedType::attr_sptr: OS << " __sptr"; break; case AttributedType::attr_uptr: OS << " __uptr"; break; -} + } spaceBeforePlaceHolder(OS); } } @@ -1105,6 +1110,12 @@ void TypePrinter::printAttributedAfter(const AttributedType *T, 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"); diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index 42e33faca38..2e0a06b5c79 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -546,12 +546,7 @@ distributeFunctionTypeAttrToInnermost(TypeProcessingState &state, return true; } - if (handleFunctionTypeAttr(state, attr, declSpecType)) { - spliceAttrOutOfList(attr, attrList); - return true; - } - - return false; + return handleFunctionTypeAttr(state, attr, declSpecType); } /// A function type attribute was written in the decl spec. Try to @@ -3345,6 +3340,7 @@ static AttributeList::Kind getAttrListKind(AttributedType::Kind kind) { case AttributedType::attr_pascal: return AttributeList::AT_Pascal; case AttributedType::attr_pcs: + case AttributedType::attr_pcs_vfp: return AttributeList::AT_Pcs; case AttributedType::attr_pnaclcall: return AttributeList::AT_PnaclCall; @@ -4302,6 +4298,36 @@ static bool handleMSPointerTypeQualifierAttr(TypeProcessingState &State, return false; } +static AttributedType::Kind getCCTypeAttrKind(AttributeList &Attr) { + assert(!Attr.isInvalid()); + switch (Attr.getKind()) { + default: + llvm_unreachable("not a calling convention attribute"); + case AttributeList::AT_CDecl: + return AttributedType::attr_cdecl; + case AttributeList::AT_FastCall: + return AttributedType::attr_fastcall; + case AttributeList::AT_StdCall: + return AttributedType::attr_stdcall; + case AttributeList::AT_ThisCall: + return AttributedType::attr_thiscall; + case AttributeList::AT_Pascal: + return AttributedType::attr_pascal; + case AttributeList::AT_Pcs: { + // We know attr is valid so it can only have one of two strings args. + StringLiteral *Str = cast<StringLiteral>(Attr.getArg(0)); + return llvm::StringSwitch<AttributedType::Kind>(Str->getString()) + .Case("aapcs", AttributedType::attr_pcs) + .Case("aapcs-vfp", AttributedType::attr_pcs_vfp); + } + case AttributeList::AT_PnaclCall: + return AttributedType::attr_pnaclcall; + case AttributeList::AT_IntelOclBicc: + return AttributedType::attr_inteloclbicc; + } + llvm_unreachable("unexpected attribute kind!"); +} + /// Process an individual function attribute. Returns true to /// indicate that the attribute was handled, false if it wasn't. static bool handleFunctionTypeAttr(TypeProcessingState &state, @@ -4421,8 +4447,13 @@ static bool handleFunctionTypeAttr(TypeProcessingState &state, } } + // Modify the CC from the wrapped function type, wrap it all back, and then + // wrap the whole thing in an AttributedType as written. The modified type + // might have a different CC if we ignored the attribute. FunctionType::ExtInfo EI = unwrapped.get()->getExtInfo().withCallingConv(CC); - type = unwrapped.wrap(S, S.Context.adjustFunctionType(unwrapped.get(), EI)); + QualType Equivalent = + unwrapped.wrap(S, S.Context.adjustFunctionType(unwrapped.get(), EI)); + type = S.Context.getAttributedType(getCCTypeAttrKind(attr), type, Equivalent); return true; } |