| 1 | // RUN: %clang_cc1 -triple i686-windows-msvc -fms-extensions -emit-llvm -std=c11 -O0 -o - %s | FileCheck --check-prefix=CHECK --check-prefix=MS %s |
| 2 | // RUN: %clang_cc1 -triple x86_64-windows-msvc -fms-extensions -emit-llvm -std=c11 -O0 -o - %s | FileCheck --check-prefix=CHECK --check-prefix=MS %s |
| 3 | // RUN: %clang_cc1 -triple i686-windows-gnu -fms-extensions -emit-llvm -std=c11 -O0 -o - %s | FileCheck --check-prefix=CHECK --check-prefix=GNU %s |
| 4 | // RUN: %clang_cc1 -triple x86_64-windows-gnu -fms-extensions -emit-llvm -std=c11 -O0 -o - %s | FileCheck --check-prefix=CHECK --check-prefix=GNU %s |
| 5 | // RUN: %clang_cc1 -triple i686-windows-msvc -fms-extensions -emit-llvm -std=c11 -O1 -o - %s | FileCheck --check-prefix=O1 --check-prefix=MO1 %s |
| 6 | // RUN: %clang_cc1 -triple i686-windows-gnu -fms-extensions -emit-llvm -std=c11 -O1 -o - %s | FileCheck --check-prefix=O1 --check-prefix=GO1 %s |
| 7 | |
| 8 | #define JOIN2(x, y) x##y |
| 9 | #define JOIN(x, y) JOIN2(x, y) |
| 10 | #define USEVAR(var) int JOIN(use, __LINE__)() { return var; } |
| 11 | #define USE(func) void JOIN(use, __LINE__)() { func(); } |
| 12 | |
| 13 | |
| 14 | |
| 15 | //===----------------------------------------------------------------------===// |
| 16 | // Globals |
| 17 | //===----------------------------------------------------------------------===// |
| 18 | |
| 19 | // Import declaration. |
| 20 | // CHECK: @ExternGlobalDecl = external dllimport global i32 |
| 21 | __declspec(dllimport) extern int ExternGlobalDecl; |
| 22 | USEVAR(ExternGlobalDecl) |
| 23 | |
| 24 | // dllimport implies a declaration. |
| 25 | // CHECK: @GlobalDecl = external dllimport global i32 |
| 26 | __declspec(dllimport) int GlobalDecl; |
| 27 | USEVAR(GlobalDecl) |
| 28 | |
| 29 | // Redeclarations |
| 30 | // CHECK: @GlobalRedecl1 = external dllimport global i32 |
| 31 | __declspec(dllimport) extern int GlobalRedecl1; |
| 32 | __declspec(dllimport) extern int GlobalRedecl1; |
| 33 | USEVAR(GlobalRedecl1) |
| 34 | |
| 35 | // CHECK: @GlobalRedecl2 = external dllimport global i32 |
| 36 | __declspec(dllimport) int GlobalRedecl2; |
| 37 | __declspec(dllimport) int GlobalRedecl2; |
| 38 | USEVAR(GlobalRedecl2) |
| 39 | |
| 40 | // NB: MSVC issues a warning and makes GlobalRedecl3 dllexport. We follow GCC |
| 41 | // and drop the dllimport with a warning. |
| 42 | // MS: @GlobalRedecl3 = external dso_local global i32 |
| 43 | // GNU: @GlobalRedecl3 = external global i32 |
| 44 | __declspec(dllimport) extern int GlobalRedecl3; |
| 45 | extern int GlobalRedecl3; // dllimport ignored |
| 46 | USEVAR(GlobalRedecl3) |
| 47 | |
| 48 | // Make sure this works even if the decl has been used before it's defined (PR20792). |
| 49 | // MS: @GlobalRedecl4 = common dso_local dllexport global i32 |
| 50 | // GNU: @GlobalRedecl4 = common dso_local global i32 |
| 51 | __declspec(dllimport) extern int GlobalRedecl4; |
| 52 | USEVAR(GlobalRedecl4) |
| 53 | int GlobalRedecl4; // dllimport ignored |
| 54 | |
| 55 | // FIXME: dllimport is dropped in the AST; this should be reflected in codegen (PR02803). |
| 56 | // CHECK: @GlobalRedecl5 = external dllimport global i32 |
| 57 | __declspec(dllimport) extern int GlobalRedecl5; |
| 58 | USEVAR(GlobalRedecl5) |
| 59 | extern int GlobalRedecl5; // dllimport ignored |
| 60 | |
| 61 | // Redeclaration in local context. |
| 62 | // CHECK: @GlobalRedecl6 = external dllimport global i32 |
| 63 | __declspec(dllimport) int GlobalRedecl6; |
| 64 | int functionScope() { |
| 65 | extern int GlobalRedecl6; // still dllimport |
| 66 | return GlobalRedecl6; |
| 67 | } |
| 68 | |
| 69 | |
| 70 | |
| 71 | //===----------------------------------------------------------------------===// |
| 72 | // Functions |
| 73 | //===----------------------------------------------------------------------===// |
| 74 | |
| 75 | // Import function declaration. |
| 76 | // CHECK-DAG: declare dllimport void @decl() |
| 77 | __declspec(dllimport) void decl(void); |
| 78 | |
| 79 | // Initialize use_decl with the address of the thunk. |
| 80 | // CHECK-DAG: @use_decl = dso_local global void ()* @decl |
| 81 | void (*use_decl)(void) = &decl; |
| 82 | |
| 83 | // Import inline function. |
| 84 | // MS-DAG: declare dllimport void @inlineFunc() |
| 85 | // MO1-DAG: define available_externally dllimport void @inlineFunc() |
| 86 | // GNU-DAG: declare dso_local void @inlineFunc() |
| 87 | // GO1-DAG: define available_externally dso_local void @inlineFunc() |
| 88 | __declspec(dllimport) inline void inlineFunc(void) {} |
| 89 | USE(inlineFunc) |
| 90 | |
| 91 | // inline attributes |
| 92 | // MS-DAG: declare dllimport void @noinline() |
| 93 | // MO1-DAG: define available_externally dllimport void @noinline() |
| 94 | // GNU-DAG: declare dso_local void @noinline() |
| 95 | // GO1-DAG: define available_externally dso_local void @noinline() |
| 96 | // CHECK-NOT: @alwaysInline() |
| 97 | // O1-NOT: @alwaysInline() |
| 98 | __declspec(dllimport) __attribute__((noinline)) inline void noinline(void) {} |
| 99 | __declspec(dllimport) __attribute__((always_inline)) inline void alwaysInline(void) {} |
| 100 | USE(noinline) |
| 101 | USE(alwaysInline) |
| 102 | |
| 103 | // Redeclarations |
| 104 | // CHECK-DAG: declare dllimport void @redecl1() |
| 105 | __declspec(dllimport) void redecl1(void); |
| 106 | __declspec(dllimport) void redecl1(void); |
| 107 | USE(redecl1) |
| 108 | |
| 109 | // NB: MSVC issues a warning and makes redecl2/redecl3 dllexport. We follow GCC |
| 110 | // and drop the dllimport with a warning. |
| 111 | // CHECK-DAG: declare dso_local void @redecl2() |
| 112 | __declspec(dllimport) void redecl2(void); |
| 113 | void redecl2(void); |
| 114 | USE(redecl2) |
| 115 | |
| 116 | // MS: define dso_local dllexport void @redecl3() |
| 117 | // GNU: define dso_local void @redecl3() |
| 118 | __declspec(dllimport) void redecl3(void); |
| 119 | void redecl3(void) {} // dllimport ignored |
| 120 | USE(redecl3) |
| 121 | |
| 122 | // Make sure this works even if the decl is used before it's defined (PR20792). |
| 123 | // MS: define dso_local dllexport void @redecl4() |
| 124 | // GNU: define dso_local void @redecl4() |
| 125 | __declspec(dllimport) void redecl4(void); |
| 126 | USE(redecl4) |
| 127 | void redecl4(void) {} // dllimport ignored |
| 128 | |
| 129 | // FIXME: dllimport is dropped in the AST; this should be reflected in codegen (PR20803). |
| 130 | // CHECK-DAG: declare dllimport |
| 131 | __declspec(dllimport) void redecl5(void); |
| 132 | USE(redecl5) |
| 133 | void redecl5(void); // dllimport ignored |
| 134 | |