// 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).
// MS: @GlobalRedecl4 = common dllexport global i32
// GNU: @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)
// MS: define dllexport void @redecl3()
// GNU: 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).
// MS: define dllexport void @redecl4()
// GNU: 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