| // RUN: %clang_cc1 -triple i686-windows-msvc -fms-extensions -emit-llvm -std=c11 -O0 -o - %s | FileCheck --check-prefix=CHECK --check-prefix=MS %s |
| // 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 |
| // RUN: %clang_cc1 -triple i686-windows-gnu -fms-extensions -emit-llvm -std=c11 -O0 -o - %s | FileCheck --check-prefix=CHECK --check-prefix=GNU %s |
| // 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 |
| // RUN: %clang_cc1 -triple i686-windows-msvc -fms-extensions -emit-llvm -std=c11 -O1 -o - %s | FileCheck --check-prefix=O1 --check-prefix=MO1 %s |
| // RUN: %clang_cc1 -triple i686-windows-gnu -fms-extensions -emit-llvm -std=c11 -O1 -o - %s | FileCheck --check-prefix=O1 --check-prefix=GO1 %s |
| |
| #define JOIN2(x, y) x##y |
| #define JOIN(x, y) JOIN2(x, y) |
| #define USEVAR(var) int JOIN(use, __LINE__)() { return var; } |
| #define USE(func) void JOIN(use, __LINE__)() { func(); } |
| |
| |
| |
| //===----------------------------------------------------------------------===// |
| // Globals |
| //===----------------------------------------------------------------------===// |
| |
| // Import declaration. |
| // CHECK: @ExternGlobalDecl = external dllimport global i32 |
| __declspec(dllimport) extern int ExternGlobalDecl; |
| USEVAR(ExternGlobalDecl) |
| |
| // dllimport implies a declaration. |
| // CHECK: @GlobalDecl = external dllimport global i32 |
| __declspec(dllimport) int GlobalDecl; |
| USEVAR(GlobalDecl) |
| |
| // Redeclarations |
| // CHECK: @GlobalRedecl1 = external dllimport global i32 |
| __declspec(dllimport) extern int GlobalRedecl1; |
| __declspec(dllimport) extern int GlobalRedecl1; |
| USEVAR(GlobalRedecl1) |
| |
| // CHECK: @GlobalRedecl2 = external dllimport global i32 |
| __declspec(dllimport) int GlobalRedecl2; |
| __declspec(dllimport) int GlobalRedecl2; |
| USEVAR(GlobalRedecl2) |
| |
| // NB: MSVC issues a warning and makes GlobalRedecl3 dllexport. We follow GCC |
| // and drop the dllimport with a warning. |
| // CHECK: @GlobalRedecl3 = external global i32 |
| __declspec(dllimport) extern int GlobalRedecl3; |
| extern int GlobalRedecl3; // dllimport ignored |
| USEVAR(GlobalRedecl3) |
| |
| // Make sure this works even if the decl has been used before it's defined (PR20792). |
| // CHECK: @GlobalRedecl4 = common global i32 |
| __declspec(dllimport) extern int GlobalRedecl4; |
| USEVAR(GlobalRedecl4) |
| int GlobalRedecl4; // dllimport ignored |
| |
| // FIXME: dllimport is dropped in the AST; this should be reflected in codegen (PR02803). |
| // CHECK: @GlobalRedecl5 = external dllimport global i32 |
| __declspec(dllimport) extern int GlobalRedecl5; |
| USEVAR(GlobalRedecl5) |
| extern int GlobalRedecl5; // dllimport ignored |
| |
| // Redeclaration in local context. |
| // CHECK: @GlobalRedecl6 = external dllimport global i32 |
| __declspec(dllimport) int GlobalRedecl6; |
| int functionScope() { |
| extern int GlobalRedecl6; // still dllimport |
| return GlobalRedecl6; |
| } |
| |
| |
| |
| //===----------------------------------------------------------------------===// |
| // Functions |
| //===----------------------------------------------------------------------===// |
| |
| // Import function declaration. |
| // CHECK-DAG: declare dllimport void @decl() |
| __declspec(dllimport) void decl(void); |
| |
| // Initialize use_decl with the address of the thunk. |
| // CHECK-DAG: @use_decl = global void ()* @decl |
| void (*use_decl)(void) = &decl; |
| |
| // Import inline function. |
| // MS-DAG: declare dllimport void @inlineFunc() |
| // MO1-DAG: define available_externally dllimport void @inlineFunc() |
| // GNU-DAG: declare void @inlineFunc() |
| // GO1-DAG: define available_externally void @inlineFunc() |
| __declspec(dllimport) inline void inlineFunc(void) {} |
| USE(inlineFunc) |
| |
| // inline attributes |
| // MS-DAG: declare dllimport void @noinline() |
| // MO1-DAG: define available_externally dllimport void @noinline() |
| // GNU-DAG: declare void @noinline() |
| // GO1-DAG: define available_externally void @noinline() |
| // CHECK-NOT: @alwaysInline() |
| // O1-NOT: @alwaysInline() |
| __declspec(dllimport) __attribute__((noinline)) inline void noinline(void) {} |
| __declspec(dllimport) __attribute__((always_inline)) inline void alwaysInline(void) {} |
| USE(noinline) |
| USE(alwaysInline) |
| |
| // Redeclarations |
| // CHECK-DAG: declare dllimport void @redecl1() |
| __declspec(dllimport) void redecl1(void); |
| __declspec(dllimport) void redecl1(void); |
| USE(redecl1) |
| |
| // NB: MSVC issues a warning and makes redecl2/redecl3 dllexport. We follow GCC |
| // and drop the dllimport with a warning. |
| // CHECK-DAG: declare void @redecl2() |
| __declspec(dllimport) void redecl2(void); |
| void redecl2(void); |
| USE(redecl2) |
| |
| // CHECK-DAG: define void @redecl3() |
| __declspec(dllimport) void redecl3(void); |
| void redecl3(void) {} // dllimport ignored |
| USE(redecl3) |
| |
| // Make sure this works even if the decl is used before it's defined (PR20792). |
| // CHECK-DAG: define void @redecl4() |
| __declspec(dllimport) void redecl4(void); |
| USE(redecl4) |
| void redecl4(void) {} // dllimport ignored |
| |
| // FIXME: dllimport is dropped in the AST; this should be reflected in codegen (PR20803). |
| // CHECK-DAG: declare dllimport |
| __declspec(dllimport) void redecl5(void); |
| USE(redecl5) |
| void redecl5(void); // dllimport ignored |