Index: include/clang/Sema/Sema.h =================================================================== --- include/clang/Sema/Sema.h +++ include/clang/Sema/Sema.h @@ -2937,8 +2937,9 @@ bool isValidPointerAttrType(QualType T, bool RefOkay = false); bool CheckRegparmAttr(const AttributeList &attr, unsigned &value); - bool CheckCallingConvAttr(const AttributeList &attr, CallingConv &CC, - const FunctionDecl *FD = nullptr); + bool CheckCallingConvAttr(const AttributeList &attr, CallingConv &CC, + const FunctionDecl *FD = nullptr, + bool *Defaulted = nullptr); bool CheckNoReturnAttr(const AttributeList &attr); bool checkStringLiteralArgumentAttr(const AttributeList &Attr, unsigned ArgNum, StringRef &Str, Index: lib/Sema/SemaDeclAttr.cpp =================================================================== --- lib/Sema/SemaDeclAttr.cpp +++ lib/Sema/SemaDeclAttr.cpp @@ -3701,8 +3701,8 @@ } } -bool Sema::CheckCallingConvAttr(const AttributeList &attr, CallingConv &CC, - const FunctionDecl *FD) { +bool Sema::CheckCallingConvAttr(const AttributeList &attr, CallingConv &CC, + const FunctionDecl *FD, bool *Defaulted) { if (attr.isInvalid()) return true; @@ -3750,11 +3750,16 @@ default: llvm_unreachable("unexpected attribute kind"); } + if (Defaulted) + *Defaulted = false; const TargetInfo &TI = Context.getTargetInfo(); TargetInfo::CallingConvCheckResult A = TI.checkCallingConvention(CC); if (A != TargetInfo::CCCR_OK) { - if (A == TargetInfo::CCCR_Warning) + if (A == TargetInfo::CCCR_Warning) { Diag(attr.getLoc(), diag::warn_cconv_ignored) << attr.getName(); + if (Defaulted) + *Defaulted = true; + } // This convention is not valid for the target. Use the default function or // method calling convention. Index: lib/Sema/SemaType.cpp =================================================================== --- lib/Sema/SemaType.cpp +++ lib/Sema/SemaType.cpp @@ -5856,7 +5856,8 @@ // Otherwise, a calling convention. CallingConv CC; - if (S.CheckCallingConvAttr(attr, CC)) + bool isDefaulted = false; + if (S.CheckCallingConvAttr(attr, CC, /*FD*/nullptr, &isDefaulted)) return true; const FunctionType *fn = unwrapped.get(); @@ -5906,7 +5907,11 @@ 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); + // If calling convention was defaulted, we should not create attributed type + // with this attribute. + if (!isDefaulted) + type = S.Context.getAttributedType(CCAttrKind, type, Equivalent); + return true; } Index: test/CodeGen/adding_defaulted_cc_attr_to_type.c =================================================================== --- test/CodeGen/adding_defaulted_cc_attr_to_type.c +++ test/CodeGen/adding_defaulted_cc_attr_to_type.c @@ -0,0 +1,10 @@ +// 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)* + +void (__attribute__((regparm(2), stdcall)) foo) () { // expected-warning {{calling convention 'stdcall' ignored for this target}} +} + +// CHECK: define void @foo(){{.*}} 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}}