Allowing individual targets to determine whether a given calling convention is allowed or ignored with warning. This allows for correct name mangling for x64 targets on Windows, which in turn allows for linking against the Win32 APIs.

Fixes PR13782

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@165015 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/test/CodeGen/microsoft-call-conv-x64.c b/test/CodeGen/microsoft-call-conv-x64.c
new file mode 100644
index 0000000..9a0aa59
--- /dev/null
+++ b/test/CodeGen/microsoft-call-conv-x64.c
@@ -0,0 +1,39 @@
+// RUN: %clang_cc1 -triple x86_64-pc-win32 -emit-llvm < %s | FileCheck %s

+

+void __fastcall f1(void);

+void __stdcall f2(void);

+void __fastcall f4(void) {

+// CHECK: define void @f4()

+  f1();

+// CHECK: call void @f1()

+}

+void __stdcall f5(void) {

+// CHECK: define void @f5()

+  f2();

+// CHECK: call void @f2()

+}

+

+// PR5280

+void (__fastcall *pf1)(void) = f1;

+void (__stdcall *pf2)(void) = f2;

+void (__fastcall *pf4)(void) = f4;

+void (__stdcall *pf5)(void) = f5;

+

+int main(void) {

+    f4(); f5();

+    // CHECK: call void @f4()

+    // CHECK: call void @f5()

+    pf1(); pf2(); pf4(); pf5();

+    // CHECK: call void %{{.*}}()

+    // CHECK: call void %{{.*}}()

+    // CHECK: call void %{{.*}}()

+    // CHECK: call void %{{.*}}()

+    return 0;

+}

+

+// PR7117

+void __stdcall f7(foo) int foo; {}

+void f8(void) {

+  f7(0);

+  // CHECK: call void @f7(i32 0)

+}

diff --git a/test/CodeGen/microsoft-call-conv.c b/test/CodeGen/microsoft-call-conv.c
index 390c3be..64d10fb 100644
--- a/test/CodeGen/microsoft-call-conv.c
+++ b/test/CodeGen/microsoft-call-conv.c
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -emit-llvm < %s | FileCheck %s
+// RUN: %clang_cc1 -triple i386-pc-linux -emit-llvm < %s | FileCheck %s
 
 void __fastcall f1(void);
 void __stdcall f2(void);
diff --git a/test/CodeGen/stdcall-fastcall.c b/test/CodeGen/stdcall-fastcall.c
index 3de7b67..2832e91 100644
--- a/test/CodeGen/stdcall-fastcall.c
+++ b/test/CodeGen/stdcall-fastcall.c
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -emit-llvm < %s | FileCheck %s
+// RUN: %clang_cc1 -triple i386-unknown-unknown -emit-llvm < %s | FileCheck %s
 
 void __attribute__((fastcall)) f1(void);
 void __attribute__((stdcall)) f2(void);
diff --git a/test/CodeGenCXX/mangle-ms.cpp b/test/CodeGenCXX/mangle-ms.cpp
index 6964581..0edb4b4 100644
--- a/test/CodeGenCXX/mangle-ms.cpp
+++ b/test/CodeGenCXX/mangle-ms.cpp
@@ -1,4 +1,5 @@
 // RUN: %clang_cc1 -fms-extensions -fblocks -emit-llvm %s -o - -cxx-abi microsoft -triple=i386-pc-win32 | FileCheck %s
+// RUN: %clang_cc1 -fms-compatibility -fblocks -emit-llvm %s -o - -cxx-abi microsoft -triple=x86_64-pc-win32 | FileCheck -check-prefix X64 %s
 
 // CHECK: @"\01?a@@3HA"
 // CHECK: @"\01?b@N@@3HA"
@@ -109,6 +110,7 @@
 }
 
 // CHECK: @"\01?alpha@@YGXMN@Z"
+// X64: @"\01?alpha@@YAXMN@Z"
 
 // Make sure tag-type mangling works.
 void gamma(class foo, struct bar, union baz, enum quux) {}
diff --git a/test/Sema/MicrosoftCompatibility-x64.c b/test/Sema/MicrosoftCompatibility-x64.c
new file mode 100644
index 0000000..bf595af
--- /dev/null
+++ b/test/Sema/MicrosoftCompatibility-x64.c
@@ -0,0 +1,8 @@
+// RUN: %clang_cc1 %s -fsyntax-only -Wno-unused-value -Wmicrosoft -verify -fms-compatibility -triple x86_64-pc-win32
+int __stdcall f(void); /* expected-warning {{calling convention '__stdcall' ignored for this target}} */
+
+/* This should compile without warning because __stdcall is treated
+as __cdecl in MS compatibility mode for x64 compiles*/
+int __cdecl f(void) {
+  return 0;
+}
diff --git a/test/Sema/MicrosoftCompatibility.c b/test/Sema/MicrosoftCompatibility.c
index 6b137a6..be13949 100644
--- a/test/Sema/MicrosoftCompatibility.c
+++ b/test/Sema/MicrosoftCompatibility.c
@@ -18,4 +18,10 @@
 __declspec(align(32768)) struct S1 { int a; } s;	/* expected-error {{requested alignment must be 8192 bytes or smaller}} */
 struct __declspec(aligned) S2 {}; /* expected-warning {{unknown __declspec attribute 'aligned' ignored}} */
 
-struct __declspec(appdomain) S3 {}; /* expected-warning {{__declspec attribute 'appdomain' is not supported}} */
\ No newline at end of file
+struct __declspec(appdomain) S3 {}; /* expected-warning {{__declspec attribute 'appdomain' is not supported}} */
+
+int __stdcall f(void); /* expected-note {{previous declaration is here}} */
+
+int __cdecl f(void) { /* expected-error {{function declared 'cdecl' here was previously declared 'stdcall'}} */
+  return 0;
+}
diff --git a/test/Sema/callingconv.c b/test/Sema/callingconv.c
index 6c844a3..76b5f2d 100644
--- a/test/Sema/callingconv.c
+++ b/test/Sema/callingconv.c
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 %s -fsyntax-only -verify
+// RUN: %clang_cc1 %s -fsyntax-only -triple i386-unknown-unknown -verify
 
 void __attribute__((fastcall)) foo(float *a) { 
 }
@@ -40,8 +40,9 @@
 int __attribute__((pcs())) pcs2(void); // expected-error {{attribute takes one argument}}
 int __attribute__((pcs(pcs1))) pcs3(void); // expected-error {{attribute takes one argument}}
 int __attribute__((pcs(0))) pcs4(void); // expected-error {{'pcs' attribute requires parameter 1 to be a string}}
-int __attribute__((pcs("aapcs"))) pcs5(void); // no-error
-int __attribute__((pcs("aapcs-vfp"))) pcs6(void); // no-error
+/* These are ignored because the target is i386 and not ARM */
+int __attribute__((pcs("aapcs"))) pcs5(void); // expected-warning {{calling convention 'pcs' ignored for this target}}
+int __attribute__((pcs("aapcs-vfp"))) pcs6(void); // expected-warning {{calling convention 'pcs' ignored for this target}}
 int __attribute__((pcs("foo"))) pcs7(void); // expected-error {{Invalid PCS type}}
 
 // PR6361
diff --git a/test/Sema/stdcall-fastcall-x64.c b/test/Sema/stdcall-fastcall-x64.c
new file mode 100644
index 0000000..ca1995e
--- /dev/null
+++ b/test/Sema/stdcall-fastcall-x64.c
@@ -0,0 +1,20 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -triple x86_64-pc-linux-gnu %s

+

+// CC qualifier can be applied only to functions

+int __attribute__((stdcall)) var1; // expected-warning{{'stdcall' only applies to function types; type here is 'int'}}

+int __attribute__((fastcall)) var2; // expected-warning{{'fastcall' only applies to function types; type here is 'int'}}

+

+// Different CC qualifiers are not compatible

+void __attribute__((stdcall, fastcall)) foo3(void); // expected-warning{{calling convention 'stdcall' ignored for this target}} expected-warning {{calling convention 'fastcall' ignored for this target}}

+void __attribute__((stdcall)) foo4(); // expected-warning{{calling convention 'stdcall' ignored for this target}}

+void __attribute__((fastcall)) foo4(void); // expected-warning {{calling convention 'fastcall' ignored for this target}}

+

+// rdar://8876096

+void rdar8876096foo1(int i, int j) __attribute__((fastcall, cdecl)); // expected-warning{{calling convention 'fastcall' ignored for this target}}

+void rdar8876096foo2(int i, int j) __attribute__((fastcall, stdcall)); // expected-warning{{calling convention 'stdcall' ignored for this target}} expected-warning {{calling convention 'fastcall' ignored for this target}}

+void rdar8876096foo3(int i, int j) __attribute__((fastcall, regparm(2))); // expected-warning {{calling convention 'fastcall' ignored for this target}}

+void rdar8876096foo4(int i, int j) __attribute__((stdcall, cdecl)); // expected-warning{{calling convention 'stdcall' ignored for this target}}

+void rdar8876096foo5(int i, int j) __attribute__((stdcall, fastcall)); // expected-warning{{calling convention 'stdcall' ignored for this target}} expected-warning {{calling convention 'fastcall' ignored for this target}}

+void rdar8876096foo6(int i, int j) __attribute__((cdecl, fastcall)); // expected-warning {{calling convention 'fastcall' ignored for this target}}

+void rdar8876096foo7(int i, int j) __attribute__((cdecl, stdcall)); // expected-warning{{calling convention 'stdcall' ignored for this target}}

+void rdar8876096foo8(int i, int j) __attribute__((regparm(2), fastcall)); // expected-warning {{calling convention 'fastcall' ignored for this target}}

diff --git a/test/Sema/stdcall-fastcall.c b/test/Sema/stdcall-fastcall.c
index eeacf94..dea1fc5 100644
--- a/test/Sema/stdcall-fastcall.c
+++ b/test/Sema/stdcall-fastcall.c
@@ -1,4 +1,3 @@
-// RUN: %clang_cc1 -fsyntax-only -verify -triple x86_64-pc-linux-gnu %s
 // RUN: %clang_cc1 -fsyntax-only -verify -triple i686-apple-darwin10 %s
 
 // CC qualifier can be applied only to functions