1 | // RUN: %clang_cc1 -fms-extensions -triple i686-pc-windows-msvc -Wcast-calling-convention -DMSVC -Wno-pointer-bool-conversion -verify -x c %s |
2 | // RUN: %clang_cc1 -fms-extensions -triple i686-pc-windows-msvc -Wcast-calling-convention -DMSVC -Wno-pointer-bool-conversion -verify -x c++ %s |
3 | // RUN: %clang_cc1 -fms-extensions -triple i686-pc-windows-msvc -Wcast-calling-convention -DMSVC -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s --check-prefix=MSFIXIT |
4 | // RUN: %clang_cc1 -triple i686-pc-windows-gnu -Wcast-calling-convention -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s --check-prefix=GNUFIXIT |
5 | |
6 | // expected-note@+1 {{consider defining 'mismatched_before_winapi' with the 'stdcall' calling convention}} |
7 | void mismatched_before_winapi(int x) {} |
8 | |
9 | #ifdef MSVC |
10 | #define WINAPI __stdcall |
11 | #else |
12 | #define WINAPI __attribute__((stdcall)) |
13 | #endif |
14 | |
15 | // expected-note@+1 3 {{consider defining 'mismatched' with the 'stdcall' calling convention}} |
16 | void mismatched(int x) {} |
17 | |
18 | // expected-note@+1 {{consider defining 'mismatched_declaration' with the 'stdcall' calling convention}} |
19 | void mismatched_declaration(int x); |
20 | |
21 | // expected-note@+1 {{consider defining 'suggest_fix_first_redecl' with the 'stdcall' calling convention}} |
22 | void suggest_fix_first_redecl(int x); |
23 | void suggest_fix_first_redecl(int x); |
24 | |
25 | typedef void (WINAPI *callback_t)(int); |
26 | void take_callback(callback_t callback); |
27 | |
28 | void WINAPI mismatched_stdcall(int x) {} |
29 | |
30 | void take_opaque_fn(void (*callback)(int)); |
31 | |
32 | int main() { |
33 | // expected-warning@+1 {{cast between incompatible calling conventions 'cdecl' and 'stdcall'}} |
34 | take_callback((callback_t)mismatched); |
35 | |
36 | // expected-warning@+1 {{cast between incompatible calling conventions 'cdecl' and 'stdcall'}} |
37 | callback_t callback = (callback_t)mismatched; // warns |
38 | (void)callback; |
39 | |
40 | // expected-warning@+1 {{cast between incompatible calling conventions 'cdecl' and 'stdcall'}} |
41 | callback = (callback_t)&mismatched; // warns |
42 | |
43 | // No warning, just to show we don't drill through other kinds of unary operators. |
44 | callback = (callback_t)!mismatched; |
45 | |
46 | // expected-warning@+1 {{cast between incompatible calling conventions 'cdecl' and 'stdcall'}} |
47 | callback = (callback_t)&mismatched_before_winapi; // warns |
48 | |
49 | // Probably a bug, but we don't warn. |
50 | void (*callback2)(int) = mismatched; |
51 | take_callback((callback_t)callback2); |
52 | |
53 | // Another way to suppress the warning. |
54 | take_callback((callback_t)(void*)mismatched); |
55 | |
56 | // Warn on declarations as well as definitions. |
57 | // expected-warning@+1 {{cast between incompatible calling conventions 'cdecl' and 'stdcall'}} |
58 | take_callback((callback_t)mismatched_declaration); |
59 | // expected-warning@+1 {{cast between incompatible calling conventions 'cdecl' and 'stdcall'}} |
60 | take_callback((callback_t)suggest_fix_first_redecl); |
61 | |
62 | // Don't warn, because we're casting from stdcall to cdecl. Usually that means |
63 | // the programmer is rinsing the function pointer through some kind of opaque |
64 | // API. |
65 | take_opaque_fn((void (*)(int))mismatched_stdcall); |
66 | } |
67 | |
68 | // MSFIXIT: fix-it:"{{.*}}callingconv-cast.c":{16:6-16:6}:"WINAPI " |
69 | // MSFIXIT: fix-it:"{{.*}}callingconv-cast.c":{16:6-16:6}:"WINAPI " |
70 | // MSFIXIT: fix-it:"{{.*}}callingconv-cast.c":{16:6-16:6}:"WINAPI " |
71 | // MSFIXIT: fix-it:"{{.*}}callingconv-cast.c":{7:6-7:6}:"__stdcall " |
72 | |
73 | // GNUFIXIT: fix-it:"{{.*}}callingconv-cast.c":{16:6-16:6}:"WINAPI " |
74 | // GNUFIXIT: fix-it:"{{.*}}callingconv-cast.c":{16:6-16:6}:"WINAPI " |
75 | // GNUFIXIT: fix-it:"{{.*}}callingconv-cast.c":{16:6-16:6}:"WINAPI " |
76 | // GNUFIXIT: fix-it:"{{.*}}callingconv-cast.c":{7:6-7:6}:"__attribute__((stdcall)) " |
77 | |