1// RUN: %clang_cc1 -triple i686-win32     -fsyntax-only -fms-extensions -verify -std=c99 -DMS %s
2// RUN: %clang_cc1 -triple x86_64-win32   -fsyntax-only -fms-extensions -verify -std=c11 -DMS %s
3// RUN: %clang_cc1 -triple i686-mingw32   -fsyntax-only -fms-extensions -verify -std=c11 -DGNU %s
4// RUN: %clang_cc1 -triple x86_64-mingw32 -fsyntax-only -fms-extensions -verify -std=c99 -DGNU %s
5
6// Invalid usage.
7__declspec(dllimport) typedef int typedef1; // expected-warning{{'dllimport' attribute only applies to variables and functions}}
8typedef __declspec(dllimport) int typedef2; // expected-warning{{'dllimport' attribute only applies to variables and functions}}
9typedef int __declspec(dllimport) typedef3; // expected-warning{{'dllimport' attribute only applies to variables and functions}}
10typedef __declspec(dllimport) void (*FunTy)(); // expected-warning{{'dllimport' attribute only applies to variables and functions}}
11enum __declspec(dllimport) Enum { EnumVal }; // expected-warning{{'dllimport' attribute only applies to variables and functions}}
12struct __declspec(dllimport) Record {}; // expected-warning{{'dllimport' attribute only applies to variables and functions}}
13
14
15
16//===----------------------------------------------------------------------===//
17// Globals
18//===----------------------------------------------------------------------===//
19
20// Import declaration.
21__declspec(dllimport) extern int ExternGlobalDecl;
22
23// dllimport implies a declaration.
24__declspec(dllimport) int GlobalDecl;
25int **__attribute__((dllimport))* GlobalDeclChunkAttr;
26int GlobalDeclAttr __attribute__((dllimport));
27
28// Address of variables can't be used for initialization in C language modes.
29int *VarForInit = &GlobalDecl; // expected-error{{initializer element is not a compile-time constant}}
30
31// Not allowed on definitions.
32__declspec(dllimport) extern int ExternGlobalInit = 1; // expected-error{{definition of dllimport data}}
33__declspec(dllimport) int GlobalInit1 = 1; // expected-error{{definition of dllimport data}}
34int __declspec(dllimport) GlobalInit2 = 1; // expected-error{{definition of dllimport data}}
35
36// Declare, then reject definition.
37#ifdef GNU
38// expected-note@+2{{previous attribute is here}}
39#endif
40__declspec(dllimport) extern int ExternGlobalDeclInit; // expected-note{{previous declaration is here}}
41#ifdef MS
42// expected-warning@+4{{'ExternGlobalDeclInit' redeclared without 'dllimport' attribute: 'dllexport' attribute added}}
43#else
44// expected-warning@+2{{'ExternGlobalDeclInit' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}}
45#endif
46int ExternGlobalDeclInit = 1;
47
48#ifdef GNU
49// expected-note@+2{{previous attribute is here}}
50#endif
51__declspec(dllimport) int GlobalDeclInit; // expected-note{{previous declaration is here}}
52#ifdef MS
53// expected-warning@+4{{'GlobalDeclInit' redeclared without 'dllimport' attribute: 'dllexport' attribute added}}
54#else
55// expected-warning@+2{{'GlobalDeclInit' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}}
56#endif
57int GlobalDeclInit = 1;
58
59#ifdef GNU
60// expected-note@+2{{previous attribute is here}}
61#endif
62int *__attribute__((dllimport)) GlobalDeclChunkAttrInit; // expected-note{{previous declaration is here}}
63#ifdef MS
64// expected-warning@+4{{'GlobalDeclChunkAttrInit' redeclared without 'dllimport' attribute: 'dllexport' attribute added}}
65#else
66// expected-warning@+2{{'GlobalDeclChunkAttrInit' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}}
67#endif
68int *GlobalDeclChunkAttrInit = 0;
69
70#ifdef GNU
71// expected-note@+2{{previous attribute is here}}
72#endif
73int GlobalDeclAttrInit __attribute__((dllimport)); // expected-note{{previous declaration is here}}
74#ifdef MS
75// expected-warning@+4{{'GlobalDeclAttrInit' redeclared without 'dllimport' attribute: 'dllexport' attribute added}}
76#else
77// expected-warning@+2{{'GlobalDeclAttrInit' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}}
78#endif
79int GlobalDeclAttrInit = 1;
80
81// Redeclarations
82__declspec(dllimport) extern int GlobalRedecl1;
83__declspec(dllimport) extern int GlobalRedecl1;
84
85__declspec(dllimport) int GlobalRedecl2a;
86__declspec(dllimport) int GlobalRedecl2a;
87
88int *__attribute__((dllimport)) GlobalRedecl2b;
89int *__attribute__((dllimport)) GlobalRedecl2b;
90
91int GlobalRedecl2c __attribute__((dllimport));
92int GlobalRedecl2c __attribute__((dllimport));
93
94// We follow GCC and drop the dllimport with a warning.
95__declspec(dllimport) extern int GlobalRedecl3; // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}}
96                      extern int GlobalRedecl3; // expected-warning{{'GlobalRedecl3' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}}
97
98// Adding an attribute on redeclaration.
99                      extern int GlobalRedecl4; // expected-note{{previous declaration is here}}
100int useGlobalRedecl4() { return GlobalRedecl4; }
101__declspec(dllimport) extern int GlobalRedecl4; // expected-error{{redeclaration of 'GlobalRedecl4' cannot add 'dllimport' attribute}}
102
103// Allow with a warning if the decl hasn't been used yet.
104                      extern int GlobalRedecl5; // expected-note{{previous declaration is here}}
105__declspec(dllimport) extern int GlobalRedecl5; // expected-warning{{redeclaration of 'GlobalRedecl5' should not add 'dllimport' attribute}}
106
107
108// External linkage is required.
109__declspec(dllimport) static int StaticGlobal; // expected-error{{'StaticGlobal' must have external linkage when declared 'dllimport'}}
110
111// Thread local variables are invalid.
112__declspec(dllimport) __thread int ThreadLocalGlobal; // expected-error{{'ThreadLocalGlobal' cannot be thread local when declared 'dllimport'}}
113
114// Import in local scope.
115__declspec(dllimport) float LocalRedecl1; // expected-note{{previous declaration is here}}
116__declspec(dllimport) float LocalRedecl2; // expected-note{{previous declaration is here}}
117__declspec(dllimport) float LocalRedecl3; // expected-note{{previous declaration is here}}
118__declspec(dllimport) float LocalRedecl4;
119void functionScope() {
120  __declspec(dllimport) int LocalRedecl1; // expected-error{{redeclaration of 'LocalRedecl1' with a different type: 'int' vs 'float'}}
121  int *__attribute__((dllimport)) LocalRedecl2; // expected-error{{redeclaration of 'LocalRedecl2' with a different type: 'int *' vs 'float'}}
122  int LocalRedecl3 __attribute__((dllimport)); // expected-error{{redeclaration of 'LocalRedecl3' with a different type: 'int' vs 'float'}}
123
124  __declspec(dllimport)        int LocalVarDecl;
125  __declspec(dllimport)        int LocalVarDef = 1; // expected-error{{definition of dllimport data}}
126  __declspec(dllimport) extern int ExternLocalVarDecl;
127  __declspec(dllimport) extern int ExternLocalVarDef = 1; // expected-error{{definition of dllimport data}}
128  __declspec(dllimport) static int StaticLocalVar; // expected-error{{'StaticLocalVar' must have external linkage when declared 'dllimport'}}
129
130  // Local extern redeclaration does not drop the attribute.
131  extern float LocalRedecl4;
132}
133
134
135
136//===----------------------------------------------------------------------===//
137// Functions
138//===----------------------------------------------------------------------===//
139
140// Import function declaration. Check different placements.
141__attribute__((dllimport)) void decl1A(); // Sanity check with __attribute__
142__declspec(dllimport)      void decl1B();
143
144void __attribute__((dllimport)) decl2A();
145void __declspec(dllimport)      decl2B();
146
147// Address of functions can be used for initialization in C language modes.
148// However, the address of the thunk wrapping the function is used instead of
149// the address in the import address table.
150void (*FunForInit)() = &decl2A;
151
152// Not allowed on function definitions.
153__declspec(dllimport) void def() {} // expected-error{{dllimport cannot be applied to non-inline function definition}}
154
155// Import inline function.
156#ifdef GNU
157// expected-warning@+3{{'dllimport' attribute ignored on inline function}}
158// expected-warning@+3{{'dllimport' attribute ignored on inline function}}
159#endif
160__declspec(dllimport) inline void inlineFunc1() {}
161inline void __attribute__((dllimport)) inlineFunc2() {}
162
163// Redeclarations
164__declspec(dllimport) void redecl1();
165__declspec(dllimport) void redecl1();
166
167__declspec(dllimport) void redecl2(); // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}}
168                      void redecl2(); // expected-warning{{'redecl2' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}}
169
170#ifdef GNU
171                      // expected-note@+2{{previous attribute is here}}
172#endif
173                      __declspec(dllimport) void redecl3(); // expected-note{{previous declaration is here}}
174                      // NB: Both MSVC and Clang issue a warning and make redecl3 dllexport.
175#ifdef MS
176                      // expected-warning@+4{{'redecl3' redeclared without 'dllimport' attribute: 'dllexport' attribute added}}
177#else
178                      // expected-warning@+2{{'redecl3' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}}
179#endif
180                      void redecl3() {}
181
182                      void redecl4(); // expected-note{{previous declaration is here}}
183void useRedecl4() { redecl4(); }
184__declspec(dllimport) void redecl4(); // expected-warning{{redeclaration of 'redecl4' should not add 'dllimport' attribute}}
185
186// Allow with a warning if the decl hasn't been used yet.
187                      void redecl5(); // expected-note{{previous declaration is here}}
188__declspec(dllimport) void redecl5(); // expected-warning{{redeclaration of 'redecl5' should not add 'dllimport' attribute}}
189
190
191// Inline redeclarations.
192#ifdef GNU
193// expected-warning@+3{{'redecl6' redeclared inline; 'dllimport' attribute ignored}}
194#endif
195__declspec(dllimport) void redecl6();
196                      inline void redecl6() {}
197
198#ifdef MS
199// expected-note@+5{{previous declaration is here}}
200// expected-warning@+5{{redeclaration of 'redecl7' should not add 'dllimport' attribute}}
201#else
202// expected-warning@+3{{'dllimport' attribute ignored on inline function}}
203#endif
204                      void redecl7();
205__declspec(dllimport) inline void redecl7() {}
206
207// External linkage is required.
208__declspec(dllimport) static int staticFunc(); // expected-error{{'staticFunc' must have external linkage when declared 'dllimport'}}
209
210// Static locals don't count as having external linkage.
211void staticLocalFunc() {
212  __declspec(dllimport) static int staticLocal; // expected-error{{'staticLocal' must have external linkage when declared 'dllimport'}}
213}
214