a.makarov created this revision.
a.makarov added reviewers: aaron.ballman, rsmith.
a.makarov added a subscriber: cfe-commits.
Herald added subscribers: rengolin, aemerson.

This patch is to avoid attaching the calling convention attribute to the result 
type if this attribute was ignored and calling convention was substituted by 
default.

http://reviews.llvm.org/D15373

Files:
  include/clang/Sema/Sema.h
  lib/Sema/SemaDeclAttr.cpp
  lib/Sema/SemaType.cpp
  test/CodeGen/adding_defaulted_attr_to_type.c
  test/Sema/callingconv.c

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: 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: 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: 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}}
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to