Index: include/clang/Sema/Sema.h =================================================================== --- include/clang/Sema/Sema.h +++ include/clang/Sema/Sema.h @@ -2935,6 +2935,7 @@ bool isValidPointerAttrType(QualType T, bool RefOkay = false); bool CheckRegparmAttr(const AttributeList &attr, unsigned &value); + bool getCCFromAttr(const AttributeList &attr, CallingConv &CC); bool CheckCallingConvAttr(const AttributeList &attr, CallingConv &CC, const FunctionDecl *FD = nullptr); bool CheckNoReturnAttr(const AttributeList &attr); Index: lib/Sema/SemaDeclAttr.cpp =================================================================== --- lib/Sema/SemaDeclAttr.cpp +++ lib/Sema/SemaDeclAttr.cpp @@ -3701,8 +3701,11 @@ } } -bool Sema::CheckCallingConvAttr(const AttributeList &attr, CallingConv &CC, - const FunctionDecl *FD) { +/// This function simply dispatches passed attribute to corresponding +/// calling convention. +/// If attribute is ill-formed, it returns 'true' and makes marks attribute as +/// invalid. +bool Sema::getCCFromAttr(const AttributeList &attr, CallingConv &CC) { if (attr.isInvalid()) return true; @@ -3714,19 +3717,31 @@ // TODO: diagnose uses of these conventions on the wrong target. switch (attr.getKind()) { - case AttributeList::AT_CDecl: CC = CC_C; break; - case AttributeList::AT_FastCall: CC = CC_X86FastCall; break; - case AttributeList::AT_StdCall: CC = CC_X86StdCall; break; - case AttributeList::AT_ThisCall: CC = CC_X86ThisCall; break; - case AttributeList::AT_Pascal: CC = CC_X86Pascal; break; - case AttributeList::AT_VectorCall: CC = CC_X86VectorCall; break; + case AttributeList::AT_CDecl: + CC = CC_C; + break; + case AttributeList::AT_FastCall: + CC = CC_X86FastCall; + break; + case AttributeList::AT_StdCall: + CC = CC_X86StdCall; + break; + case AttributeList::AT_ThisCall: + CC = CC_X86ThisCall; + break; + case AttributeList::AT_Pascal: + CC = CC_X86Pascal; + break; + case AttributeList::AT_VectorCall: + CC = CC_X86VectorCall; + break; case AttributeList::AT_MSABI: - CC = Context.getTargetInfo().getTriple().isOSWindows() ? CC_C : - CC_X86_64Win64; + CC = Context.getTargetInfo().getTriple().isOSWindows() ? CC_C + : CC_X86_64Win64; break; case AttributeList::AT_SysVABI: - CC = Context.getTargetInfo().getTriple().isOSWindows() ? CC_X86_64SysV : - CC_C; + CC = Context.getTargetInfo().getTriple().isOSWindows() ? CC_X86_64SysV + : CC_C; break; case AttributeList::AT_Pcs: { StringRef StrRef; @@ -3741,13 +3756,27 @@ CC = CC_AAPCS_VFP; break; } - attr.setInvalid(); Diag(attr.getLoc(), diag::err_invalid_pcs); return true; } - case AttributeList::AT_IntelOclBicc: CC = CC_IntelOclBicc; break; - default: llvm_unreachable("unexpected attribute kind"); + case AttributeList::AT_IntelOclBicc: + CC = CC_IntelOclBicc; + break; + default: + llvm_unreachable("unexpected attribute kind"); + } + return false; +} + +bool Sema::CheckCallingConvAttr(const AttributeList &attr, CallingConv &CC, + const FunctionDecl *FD) { + if (attr.isInvalid()) + return true; + + if (getCCFromAttr(attr, CC)) { + assert(attr.isInvalid() && "Error occured but attribute is not invalid!"); + return true; } const TargetInfo &TI = Context.getTargetInfo(); Index: lib/Sema/SemaType.cpp =================================================================== --- lib/Sema/SemaType.cpp +++ lib/Sema/SemaType.cpp @@ -5913,7 +5913,19 @@ FunctionType::ExtInfo EI = unwrapped.get()->getExtInfo().withCallingConv(CC); QualType Equivalent = unwrapped.wrap(S, S.Context.adjustFunctionType(unwrapped.get(), EI)); - type = S.Context.getAttributedType(CCAttrKind, type, Equivalent); + + // We should add attribute specifier to type only if we didn't subsitute + // 'default' calling convention instead of the one provided by the attribute. + CallingConv RawCC; + bool RecognizedAttr = S.getCCFromAttr(attr, RawCC); + assert(!RecognizedAttr && + "Somehow ill-formed calling convention attribute reached here!"); + TargetInfo::CallingConvCheckResult CCResult = + S.Context.getTargetInfo().checkCallingConvention(RawCC); + // If calling convention is available (CCCR_OK) or default (CCCR_Ignored), add + // it to type. + if (CCResult != TargetInfo::CCCR_Warning) + type = S.Context.getAttributedType(CCAttrKind, type, Equivalent); return true; } Index: test/CodeGen/adding_defaulted_attr_to_type.c =================================================================== --- test/CodeGen/adding_defaulted_attr_to_type.c +++ test/CodeGen/adding_defaulted_attr_to_type.c @@ -0,0 +1,5 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -verify -emit-llvm -o - %s | FileCheck %s + +void (__attribute__ ((regparm (3), stdcall )) *f) (int); // expected-warning {{calling convention 'stdcall' ignored for this target}} + +// CHECK: @f = common global void (i32)* Index: test/Sema/callingconv.c =================================================================== --- test/Sema/callingconv.c +++ test/Sema/callingconv.c @@ -66,3 +66,6 @@ void __attribute__((stdcall)) typedef_fun(int x) { } // expected-error {{function declared 'stdcall' here was previously declared without calling convention}} struct type_test {} __attribute__((stdcall)); // expected-warning {{'stdcall' attribute only applies to functions and methods}} + + +void (__attribute__ ((regparm (3), stdcall("abacaba") )) *test_ignored) (int); // expected-error {{'stdcall' attribute takes no arguments}}