From 5b92696c8f1f8ef943ad87397b95c031b5787305 Mon Sep 17 00:00:00 2001 From: Reid Kleckner <reid@kleckner.net> Date: Fri, 19 Jul 2013 19:51:03 +0000 Subject: [PATCH] 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 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@186714 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/AST/Type.h | 16 ++-- lib/AST/Type.cpp | 41 +++++++++++ lib/AST/TypePrinter.cpp | 73 +++++++++++-------- lib/Sema/SemaType.cpp | 45 ++++++++++-- .../instantiate-function-params.cpp | 6 ++ 5 files changed, 132 insertions(+), 49 deletions(-) diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h index 562243c123..4997ce2fb7 100644 --- a/include/clang/AST/Type.h +++ b/include/clang/AST/Type.h @@ -3360,9 +3360,10 @@ public: attr_objc_gc, attr_objc_ownership, attr_pcs, + attr_pcs_vfp, FirstEnumOperandKind = attr_objc_gc, - LastEnumOperandKind = attr_pcs, + LastEnumOperandKind = attr_pcs_vfp, // No operand. attr_noreturn, @@ -3406,16 +3407,9 @@ public: bool isSugared() const { return true; } QualType desugar() const { return getEquivalentType(); } - bool isMSTypeSpec() const { - switch (getAttrKind()) { - default: return false; - case attr_ptr32: - case attr_ptr64: - case attr_sptr: - case attr_uptr: - return true; - } - } + bool isMSTypeSpec() const; + + bool isCallingConv() const; void Profile(llvm::FoldingSetNodeID &ID) { Profile(ID, getAttrKind(), ModifiedType, EquivalentType); diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index 4068b2b898..44da348b0b 100644 --- a/lib/AST/Type.cpp +++ b/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/lib/AST/TypePrinter.cpp b/lib/AST/TypePrinter.cpp index d19c6a9450..3b917aa33f 100644 --- a/lib/AST/TypePrinter.cpp +++ b/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/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index 42e33faca3..2e0a06b5c7 100644 --- a/lib/Sema/SemaType.cpp +++ b/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; } diff --git a/test/SemaTemplate/instantiate-function-params.cpp b/test/SemaTemplate/instantiate-function-params.cpp index 54847e4190..97ee03f29c 100644 --- a/test/SemaTemplate/instantiate-function-params.cpp +++ b/test/SemaTemplate/instantiate-function-params.cpp @@ -82,9 +82,15 @@ namespace InstantiateFunctionTypedef { struct X { typedef int functype(int, int); functype func; + + typedef int stdfunctype(int, int) __attribute__((stdcall)); + __attribute__((stdcall)) functype stdfunc1; + stdfunctype stdfunc2; }; void f(X<int> x) { (void)x.func(1, 2); + (void)x.stdfunc1(1, 2); + (void)x.stdfunc2(1, 2); } } -- 2.40.0