1 | // RUN: %clang_cc1 -triple i686-win32 -fsyntax-only -fms-extensions -verify -std=c++11 -Wunsupported-dll-base-class-template -DMS %s |
2 | // RUN: %clang_cc1 -triple x86_64-win32 -fsyntax-only -fms-extensions -verify -std=c++1y -Wunsupported-dll-base-class-template -DMS %s |
3 | // RUN: %clang_cc1 -triple i686-mingw32 -fsyntax-only -fms-extensions -verify -std=c++1y -Wunsupported-dll-base-class-template %s |
4 | // RUN: %clang_cc1 -triple x86_64-mingw32 -fsyntax-only -fms-extensions -verify -std=c++11 -Wunsupported-dll-base-class-template %s |
5 | |
6 | // Helper structs to make templates more expressive. |
7 | struct ImplicitInst_Exported {}; |
8 | struct ExplicitDecl_Exported {}; |
9 | struct ExplicitInst_Exported {}; |
10 | struct ExplicitSpec_Exported {}; |
11 | struct ExplicitSpec_Def_Exported {}; |
12 | struct ExplicitSpec_InlineDef_Exported {}; |
13 | struct ExplicitSpec_NotExported {}; |
14 | namespace { struct Internal {}; } |
15 | struct External { int v; }; |
16 | |
17 | |
18 | // Invalid usage. |
19 | __declspec(dllexport) typedef int typedef1; |
20 | // expected-warning@-1{{'dllexport' attribute only applies to functions, variables, classes, and Objective-C interfaces}} |
21 | typedef __declspec(dllexport) int typedef2; |
22 | // expected-warning@-1{{'dllexport' attribute only applies to}} |
23 | typedef int __declspec(dllexport) typedef3; |
24 | // expected-warning@-1{{'dllexport' attribute only applies to}} |
25 | typedef __declspec(dllexport) void (*FunTy)(); |
26 | // expected-warning@-1{{'dllexport' attribute only applies to}} |
27 | enum __declspec(dllexport) Enum {}; |
28 | // expected-warning@-1{{'dllexport' attribute only applies to}} |
29 | #if __has_feature(cxx_strong_enums) |
30 | enum class __declspec(dllexport) EnumClass {}; |
31 | // expected-warning@-1{{'dllexport' attribute only applies to}} |
32 | #endif |
33 | |
34 | |
35 | |
36 | //===----------------------------------------------------------------------===// |
37 | // Globals |
38 | //===----------------------------------------------------------------------===// |
39 | |
40 | // Export declaration. |
41 | __declspec(dllexport) extern int ExternGlobalDecl; |
42 | |
43 | // dllexport implies a definition. |
44 | __declspec(dllexport) int GlobalDef; |
45 | |
46 | // Export definition. |
47 | __declspec(dllexport) int GlobalInit1 = 1; |
48 | int __declspec(dllexport) GlobalInit2 = 1; |
49 | |
50 | // Declare, then export definition. |
51 | __declspec(dllexport) extern int GlobalDeclInit; |
52 | int GlobalDeclInit = 1; |
53 | |
54 | // Redeclarations |
55 | __declspec(dllexport) extern int GlobalRedecl1; |
56 | __declspec(dllexport) int GlobalRedecl1; |
57 | |
58 | __declspec(dllexport) extern int GlobalRedecl2; |
59 | int GlobalRedecl2; |
60 | |
61 | extern int GlobalRedecl3; // expected-note{{previous declaration is here}} |
62 | __declspec(dllexport) extern int GlobalRedecl3; // expected-warning{{redeclaration of 'GlobalRedecl3' should not add 'dllexport' attribute}} |
63 | |
64 | extern "C" { |
65 | extern int GlobalRedecl4; // expected-note{{previous declaration is here}} |
66 | __declspec(dllexport) extern int GlobalRedecl4; // expected-warning{{redeclaration of 'GlobalRedecl4' should not add 'dllexport' attribute}} |
67 | } |
68 | |
69 | // External linkage is required. |
70 | __declspec(dllexport) static int StaticGlobal; // expected-error{{'StaticGlobal' must have external linkage when declared 'dllexport'}} |
71 | __declspec(dllexport) Internal InternalTypeGlobal; // expected-error{{'InternalTypeGlobal' must have external linkage when declared 'dllexport'}} |
72 | #ifndef MS |
73 | namespace { __declspec(dllexport) int InternalGlobal; } // expected-error{{'(anonymous namespace)::InternalGlobal' must have external linkage when declared 'dllexport'}} |
74 | #endif |
75 | namespace ns { __declspec(dllexport) int ExternalGlobal; } |
76 | |
77 | __declspec(dllexport) auto InternalAutoTypeGlobal = Internal(); // expected-error{{'InternalAutoTypeGlobal' must have external linkage when declared 'dllexport'}} |
78 | __declspec(dllexport) auto ExternalAutoTypeGlobal = External(); |
79 | |
80 | // Thread local variables are invalid. |
81 | __declspec(dllexport) __thread int ThreadLocalGlobal; // expected-error{{'ThreadLocalGlobal' cannot be thread local when declared 'dllexport'}} |
82 | // But a static local TLS var in an export function is OK. |
83 | inline void __declspec(dllexport) ExportedInlineWithThreadLocal() { |
84 | static __thread int OK; // no-error |
85 | } |
86 | |
87 | // Export in local scope. |
88 | void functionScope() { |
89 | __declspec(dllexport) int LocalVarDecl; // expected-error{{'LocalVarDecl' must have external linkage when declared 'dllexport'}} |
90 | __declspec(dllexport) int LocalVarDef = 1; // expected-error{{'LocalVarDef' must have external linkage when declared 'dllexport'}} |
91 | __declspec(dllexport) extern int ExternLocalVarDecl; |
92 | __declspec(dllexport) static int StaticLocalVar; // expected-error{{'StaticLocalVar' must have external linkage when declared 'dllexport'}} |
93 | } |
94 | |
95 | |
96 | |
97 | //===----------------------------------------------------------------------===// |
98 | // Variable templates |
99 | //===----------------------------------------------------------------------===// |
100 | #if __has_feature(cxx_variable_templates) |
101 | |
102 | // Export declaration. |
103 | template<typename T> __declspec(dllexport) extern int ExternVarTmplDecl; |
104 | |
105 | // dllexport implies a definition. |
106 | template<typename T> __declspec(dllexport) int VarTmplDef; |
107 | |
108 | // Export definition. |
109 | template<typename T> __declspec(dllexport) int VarTmplInit1 = 1; |
110 | template<typename T> int __declspec(dllexport) VarTmplInit2 = 1; |
111 | |
112 | // Declare, then export definition. |
113 | template<typename T> __declspec(dllexport) extern int VarTmplDeclInit; |
114 | template<typename T> int VarTmplDeclInit = 1; |
115 | |
116 | // Redeclarations |
117 | template<typename T> __declspec(dllexport) extern int VarTmplRedecl1; |
118 | template<typename T> __declspec(dllexport) int VarTmplRedecl1 = 1; |
119 | |
120 | template<typename T> __declspec(dllexport) extern int VarTmplRedecl2; |
121 | template<typename T> int VarTmplRedecl2 = 1; |
122 | |
123 | template<typename T> extern int VarTmplRedecl3; // expected-note{{previous declaration is here}} |
124 | template<typename T> __declspec(dllexport) extern int VarTmplRedecl3; // expected-error{{redeclaration of 'VarTmplRedecl3' cannot add 'dllexport' attribute}} |
125 | |
126 | // External linkage is required. |
127 | template<typename T> __declspec(dllexport) static int StaticVarTmpl; // expected-error{{'StaticVarTmpl' must have external linkage when declared 'dllexport'}} |
128 | template<typename T> __declspec(dllexport) Internal InternalTypeVarTmpl; // expected-error{{'InternalTypeVarTmpl' must have external linkage when declared 'dllexport'}} |
129 | #ifndef MS |
130 | namespace { template<typename T> __declspec(dllexport) int InternalVarTmpl; } // expected-error{{'(anonymous namespace)::InternalVarTmpl' must have external linkage when declared 'dllexport'}} |
131 | #endif |
132 | namespace ns { template<typename T> __declspec(dllexport) int ExternalVarTmpl = 1; } |
133 | |
134 | template<typename T> __declspec(dllexport) auto InternalAutoTypeVarTmpl = Internal(); // expected-error{{'InternalAutoTypeVarTmpl' must have external linkage when declared 'dllexport'}} |
135 | template<typename T> __declspec(dllexport) auto ExternalAutoTypeVarTmpl = External(); |
136 | template External ExternalAutoTypeVarTmpl<ExplicitInst_Exported>; |
137 | |
138 | |
139 | template<typename T> int VarTmpl = 1; |
140 | template<typename T> __declspec(dllexport) int ExportedVarTmpl = 1; |
141 | |
142 | // Export implicit instantiation of an exported variable template. |
143 | int useVarTmpl() { return ExportedVarTmpl<ImplicitInst_Exported>; } |
144 | |
145 | // Export explicit instantiation declaration of an exported variable template. |
146 | extern template int ExportedVarTmpl<ExplicitDecl_Exported>; |
147 | template int ExportedVarTmpl<ExplicitDecl_Exported>; |
148 | |
149 | // Export explicit instantiation definition of an exported variable template. |
150 | template __declspec(dllexport) int ExportedVarTmpl<ExplicitInst_Exported>; |
151 | |
152 | // Export specialization of an exported variable template. |
153 | template<> __declspec(dllexport) int ExportedVarTmpl<ExplicitSpec_Exported>; |
154 | template<> __declspec(dllexport) int ExportedVarTmpl<ExplicitSpec_Def_Exported> = 1; |
155 | |
156 | // Not exporting specialization of an exported variable template without |
157 | // explicit dllexport. |
158 | template<> int ExportedVarTmpl<ExplicitSpec_NotExported>; |
159 | |
160 | |
161 | // Export explicit instantiation declaration of a non-exported variable template. |
162 | extern template __declspec(dllexport) int VarTmpl<ExplicitDecl_Exported>; |
163 | template __declspec(dllexport) int VarTmpl<ExplicitDecl_Exported>; |
164 | |
165 | // Export explicit instantiation definition of a non-exported variable template. |
166 | template __declspec(dllexport) int VarTmpl<ExplicitInst_Exported>; |
167 | |
168 | // Export specialization of a non-exported variable template. |
169 | template<> __declspec(dllexport) int VarTmpl<ExplicitSpec_Exported>; |
170 | template<> __declspec(dllexport) int VarTmpl<ExplicitSpec_Def_Exported> = 1; |
171 | |
172 | #endif // __has_feature(cxx_variable_templates) |
173 | |
174 | |
175 | |
176 | //===----------------------------------------------------------------------===// |
177 | // Functions |
178 | //===----------------------------------------------------------------------===// |
179 | |
180 | // Export function declaration. Check different placements. |
181 | __attribute__((dllexport)) void decl1A(); // Sanity check with __attribute__ |
182 | __declspec(dllexport) void decl1B(); |
183 | |
184 | void __attribute__((dllexport)) decl2A(); |
185 | void __declspec(dllexport) decl2B(); |
186 | |
187 | // Export function definition. |
188 | __declspec(dllexport) void def() {} |
189 | |
190 | // extern "C" |
191 | extern "C" __declspec(dllexport) void externC() {} |
192 | |
193 | // Export inline function. |
194 | __declspec(dllexport) inline void inlineFunc1() {} |
195 | inline void __attribute__((dllexport)) inlineFunc2() {} |
196 | |
197 | __declspec(dllexport) inline void inlineDecl(); |
198 | void inlineDecl() {} |
199 | |
200 | __declspec(dllexport) void inlineDef(); |
201 | inline void inlineDef() {} |
202 | |
203 | // Redeclarations |
204 | __declspec(dllexport) void redecl1(); |
205 | __declspec(dllexport) void redecl1() {} |
206 | |
207 | __declspec(dllexport) void redecl2(); |
208 | void redecl2() {} |
209 | |
210 | void redecl3(); // expected-note{{previous declaration is here}} |
211 | __declspec(dllexport) void redecl3(); // expected-warning{{redeclaration of 'redecl3' should not add 'dllexport' attribute}} |
212 | |
213 | extern "C" { |
214 | void redecl4(); // expected-note{{previous declaration is here}} |
215 | __declspec(dllexport) void redecl4(); // expected-warning{{redeclaration of 'redecl4' should not add 'dllexport' attribute}} |
216 | } |
217 | |
218 | void redecl5(); // expected-note{{previous declaration is here}} |
219 | __declspec(dllexport) inline void redecl5() {} // expected-warning{{redeclaration of 'redecl5' should not add 'dllexport' attribute}} |
220 | |
221 | // Friend functions |
222 | struct FuncFriend { |
223 | friend __declspec(dllexport) void friend1(); |
224 | friend __declspec(dllexport) void friend2(); |
225 | friend void friend3(); // expected-note{{previous declaration is here}} |
226 | friend void friend4(); // expected-note{{previous declaration is here}} |
227 | }; |
228 | __declspec(dllexport) void friend1() {} |
229 | void friend2() {} |
230 | __declspec(dllexport) void friend3() {} // expected-warning{{redeclaration of 'friend3' should not add 'dllexport' attribute}} |
231 | __declspec(dllexport) inline void friend4() {} // expected-warning{{redeclaration of 'friend4' should not add 'dllexport' attribute}} |
232 | |
233 | // Implicit declarations can be redeclared with dllexport. |
234 | __declspec(dllexport) void* operator new(__SIZE_TYPE__ n); |
235 | |
236 | // External linkage is required. |
237 | __declspec(dllexport) static int staticFunc(); // expected-error{{'staticFunc' must have external linkage when declared 'dllexport'}} |
238 | __declspec(dllexport) Internal internalRetFunc(); // expected-error{{'internalRetFunc' must have external linkage when declared 'dllexport'}} |
239 | namespace { __declspec(dllexport) void internalFunc() {} } // expected-error{{'(anonymous namespace)::internalFunc' must have external linkage when declared 'dllexport'}} |
240 | namespace ns { __declspec(dllexport) void externalFunc() {} } |
241 | |
242 | // Export deleted function. |
243 | __declspec(dllexport) void deletedFunc() = delete; // expected-error{{attribute 'dllexport' cannot be applied to a deleted function}} |
244 | __declspec(dllexport) inline void deletedInlineFunc() = delete; // expected-error{{attribute 'dllexport' cannot be applied to a deleted function}} |
245 | |
246 | |
247 | |
248 | //===----------------------------------------------------------------------===// |
249 | // Function templates |
250 | //===----------------------------------------------------------------------===// |
251 | |
252 | // Export function template declaration. Check different placements. |
253 | template<typename T> __declspec(dllexport) void funcTmplDecl1(); |
254 | template<typename T> void __declspec(dllexport) funcTmplDecl2(); |
255 | |
256 | // Export function template definition. |
257 | template<typename T> __declspec(dllexport) void funcTmplDef() {} |
258 | |
259 | // Export inline function template. |
260 | template<typename T> __declspec(dllexport) inline void inlineFuncTmpl1() {} |
261 | template<typename T> inline void __attribute__((dllexport)) inlineFuncTmpl2() {} |
262 | |
263 | template<typename T> __declspec(dllexport) inline void inlineFuncTmplDecl(); |
264 | template<typename T> void inlineFuncTmplDecl() {} |
265 | |
266 | template<typename T> __declspec(dllexport) void inlineFuncTmplDef(); |
267 | template<typename T> inline void inlineFuncTmplDef() {} |
268 | |
269 | // Redeclarations |
270 | template<typename T> __declspec(dllexport) void funcTmplRedecl1(); |
271 | template<typename T> __declspec(dllexport) void funcTmplRedecl1() {} |
272 | |
273 | template<typename T> __declspec(dllexport) void funcTmplRedecl2(); |
274 | template<typename T> void funcTmplRedecl2() {} |
275 | |
276 | template<typename T> void funcTmplRedecl3(); // expected-note{{previous declaration is here}} |
277 | template<typename T> __declspec(dllexport) void funcTmplRedecl3(); // expected-error{{redeclaration of 'funcTmplRedecl3' cannot add 'dllexport' attribute}} |
278 | |
279 | template<typename T> void funcTmplRedecl4(); // expected-note{{previous declaration is here}} |
280 | template<typename T> __declspec(dllexport) inline void funcTmplRedecl4() {} // expected-error{{redeclaration of 'funcTmplRedecl4' cannot add 'dllexport' attribute}} |
281 | |
282 | // Function template friends |
283 | struct FuncTmplFriend { |
284 | template<typename T> friend __declspec(dllexport) void funcTmplFriend1(); |
285 | template<typename T> friend __declspec(dllexport) void funcTmplFriend2(); |
286 | template<typename T> friend void funcTmplFriend3(); // expected-note{{previous declaration is here}} |
287 | template<typename T> friend void funcTmplFriend4(); // expected-note{{previous declaration is here}} |
288 | }; |
289 | template<typename T> __declspec(dllexport) void funcTmplFriend1() {} |
290 | template<typename T> void funcTmplFriend2() {} |
291 | template<typename T> __declspec(dllexport) void funcTmplFriend3() {} // expected-error{{redeclaration of 'funcTmplFriend3' cannot add 'dllexport' attribute}} |
292 | template<typename T> __declspec(dllexport) inline void funcTmplFriend4() {} // expected-error{{redeclaration of 'funcTmplFriend4' cannot add 'dllexport' attribute}} |
293 | |
294 | // External linkage is required. |
295 | template<typename T> __declspec(dllexport) static int staticFuncTmpl(); // expected-error{{'staticFuncTmpl' must have external linkage when declared 'dllexport'}} |
296 | template<typename T> __declspec(dllexport) Internal internalRetFuncTmpl(); // expected-error{{'internalRetFuncTmpl' must have external linkage when declared 'dllexport'}} |
297 | namespace { template<typename T> __declspec(dllexport) void internalFuncTmpl(); } // expected-error{{'(anonymous namespace)::internalFuncTmpl' must have external linkage when declared 'dllexport'}} |
298 | namespace ns { template<typename T> __declspec(dllexport) void externalFuncTmpl(); } |
299 | |
300 | |
301 | template<typename T> void funcTmpl() {} |
302 | template<typename T> __declspec(dllexport) void exportedFuncTmplDecl(); |
303 | template<typename T> __declspec(dllexport) void exportedFuncTmpl() {} |
304 | |
305 | // Export implicit instantiation of an exported function template. |
306 | void useFunTmplDecl() { exportedFuncTmplDecl<ImplicitInst_Exported>(); } |
307 | void useFunTmplDef() { exportedFuncTmpl<ImplicitInst_Exported>(); } |
308 | |
309 | // Export explicit instantiation declaration of an exported function template. |
310 | extern template void exportedFuncTmpl<ExplicitDecl_Exported>(); |
311 | template void exportedFuncTmpl<ExplicitDecl_Exported>(); |
312 | |
313 | // Export explicit instantiation definition of an exported function template. |
314 | template void exportedFuncTmpl<ExplicitInst_Exported>(); |
315 | |
316 | // Export specialization of an exported function template. |
317 | template<> __declspec(dllexport) void exportedFuncTmpl<ExplicitSpec_Exported>(); |
318 | template<> __declspec(dllexport) void exportedFuncTmpl<ExplicitSpec_Def_Exported>() {} |
319 | template<> __declspec(dllexport) inline void exportedFuncTmpl<ExplicitSpec_InlineDef_Exported>() {} |
320 | |
321 | // Not exporting specialization of an exported function template without |
322 | // explicit dllexport. |
323 | template<> void exportedFuncTmpl<ExplicitSpec_NotExported>() {} |
324 | |
325 | |
326 | // Export explicit instantiation declaration of a non-exported function template. |
327 | extern template __declspec(dllexport) void funcTmpl<ExplicitDecl_Exported>(); |
328 | template __declspec(dllexport) void funcTmpl<ExplicitDecl_Exported>(); |
329 | |
330 | // Export explicit instantiation definition of a non-exported function template. |
331 | template __declspec(dllexport) void funcTmpl<ExplicitInst_Exported>(); |
332 | |
333 | // Export specialization of a non-exported function template. |
334 | template<> __declspec(dllexport) void funcTmpl<ExplicitSpec_Exported>(); |
335 | template<> __declspec(dllexport) void funcTmpl<ExplicitSpec_Def_Exported>() {} |
336 | template<> __declspec(dllexport) inline void funcTmpl<ExplicitSpec_InlineDef_Exported>() {} |
337 | |
338 | |
339 | |
340 | //===----------------------------------------------------------------------===// |
341 | // Classes |
342 | //===----------------------------------------------------------------------===// |
343 | |
344 | namespace { |
345 | struct __declspec(dllexport) AnonymousClass {}; // expected-error{{(anonymous namespace)::AnonymousClass' must have external linkage when declared 'dllexport'}} |
346 | } |
347 | |
348 | class __declspec(dllexport) ClassDecl; |
349 | |
350 | class __declspec(dllexport) ClassDef {}; |
351 | |
352 | #ifdef MS |
353 | // expected-warning@+3{{'dllexport' attribute ignored}} |
354 | #endif |
355 | template <typename T> struct PartiallySpecializedClassTemplate {}; |
356 | template <typename T> struct __declspec(dllexport) PartiallySpecializedClassTemplate<T*> { void f() {} }; |
357 | |
358 | template <typename T> struct ExpliciallySpecializedClassTemplate {}; |
359 | template <> struct __declspec(dllexport) ExpliciallySpecializedClassTemplate<int> { void f() {} }; |
360 | |
361 | // Don't instantiate class members of implicitly instantiated templates, even if they are exported. |
362 | struct IncompleteType; |
363 | template <typename T> struct __declspec(dllexport) ImplicitlyInstantiatedExportedTemplate { |
364 | int f() { return sizeof(T); } // no-error |
365 | }; |
366 | ImplicitlyInstantiatedExportedTemplate<IncompleteType> implicitlyInstantiatedExportedTemplate; |
367 | |
368 | // Don't instantiate class members of templates with explicit instantiation declarations, even if they are exported. |
369 | struct IncompleteType2; |
370 | template <typename T> struct __declspec(dllexport) ExportedTemplateWithExplicitInstantiationDecl { // expected-note{{attribute is here}} |
371 | int f() { return sizeof(T); } // no-error |
372 | }; |
373 | extern template struct ExportedTemplateWithExplicitInstantiationDecl<IncompleteType2>; // expected-warning{{explicit instantiation declaration should not be 'dllexport'}} |
374 | |
375 | // Instantiate class members for explicitly instantiated exported templates. |
376 | struct IncompleteType3; // expected-note{{forward declaration of 'IncompleteType3'}} |
377 | template <typename T> struct __declspec(dllexport) ExplicitlyInstantiatedExportedTemplate { |
378 | int f() { return sizeof(T); } // expected-error{{invalid application of 'sizeof' to an incomplete type 'IncompleteType3'}} |
379 | }; |
380 | template struct ExplicitlyInstantiatedExportedTemplate<IncompleteType3>; // expected-note{{in instantiation of member function 'ExplicitlyInstantiatedExportedTemplate<IncompleteType3>::f' requested here}} |
381 | |
382 | // In MS mode, instantiate members of class templates that are base classes of exported classes. |
383 | #ifdef MS |
384 | // expected-note@+3{{forward declaration of 'IncompleteType4'}} |
385 | // expected-note@+3{{in instantiation of member function 'BaseClassTemplateOfExportedClass<IncompleteType4>::f' requested here}} |
386 | #endif |
387 | struct IncompleteType4; |
388 | template <typename T> struct BaseClassTemplateOfExportedClass { |
389 | #ifdef MS |
390 | // expected-error@+2{{invalid application of 'sizeof' to an incomplete type 'IncompleteType4'}} |
391 | #endif |
392 | int f() { return sizeof(T); }; |
393 | }; |
394 | struct __declspec(dllexport) ExportedBaseClass : public BaseClassTemplateOfExportedClass<IncompleteType4> {}; |
395 | |
396 | // Don't instantiate members of explicitly exported class templates that are base classes of exported classes. |
397 | struct IncompleteType5; |
398 | template <typename T> struct __declspec(dllexport) ExportedBaseClassTemplateOfExportedClass { |
399 | int f() { return sizeof(T); }; // no-error |
400 | }; |
401 | struct __declspec(dllexport) ExportedBaseClass2 : public ExportedBaseClassTemplateOfExportedClass<IncompleteType5> {}; |
402 | |
403 | // Warn about explicit instantiation declarations of dllexport classes. |
404 | template <typename T> struct ExplicitInstantiationDeclTemplate {}; |
405 | extern template struct __declspec(dllexport) ExplicitInstantiationDeclTemplate<int>; // expected-warning{{explicit instantiation declaration should not be 'dllexport'}} expected-note{{attribute is here}} |
406 | |
407 | template <typename T> struct __declspec(dllexport) ExplicitInstantiationDeclExportedTemplate {}; // expected-note{{attribute is here}} |
408 | extern template struct ExplicitInstantiationDeclExportedTemplate<int>; // expected-warning{{explicit instantiation declaration should not be 'dllexport'}} |
409 | |
410 | namespace { struct InternalLinkageType {}; } |
411 | struct __declspec(dllexport) PR23308 { |
412 | void f(InternalLinkageType*); |
413 | }; |
414 | void PR23308::f(InternalLinkageType*) {} // No error; we don't try to export f because it has internal linkage. |
415 | |
416 | //===----------------------------------------------------------------------===// |
417 | // Classes with template base classes |
418 | //===----------------------------------------------------------------------===// |
419 | |
420 | template <typename T> class ClassTemplate {}; |
421 | template <typename T> class __declspec(dllexport) ExportedClassTemplate {}; |
422 | template <typename T> class __declspec(dllimport) ImportedClassTemplate {}; |
423 | |
424 | template <typename T> struct ExplicitlySpecializedTemplate { void func() {} }; |
425 | #ifdef MS |
426 | // expected-note@+2{{class template 'ExplicitlySpecializedTemplate<int>' was explicitly specialized here}} |
427 | #endif |
428 | template <> struct ExplicitlySpecializedTemplate<int> { void func() {} }; |
429 | template <typename T> struct ExplicitlyExportSpecializedTemplate { void func() {} }; |
430 | template <> struct __declspec(dllexport) ExplicitlyExportSpecializedTemplate<int> { void func() {} }; |
431 | template <typename T> struct ExplicitlyImportSpecializedTemplate { void func() {} }; |
432 | template <> struct __declspec(dllimport) ExplicitlyImportSpecializedTemplate<int> { void func() {} }; |
433 | |
434 | template <typename T> struct ExplicitlyInstantiatedTemplate { void func() {} }; |
435 | #ifdef MS |
436 | // expected-note@+2{{class template 'ExplicitlyInstantiatedTemplate<int>' was instantiated here}} |
437 | #endif |
438 | template struct ExplicitlyInstantiatedTemplate<int>; |
439 | template <typename T> struct ExplicitlyExportInstantiatedTemplate { void func() {} }; |
440 | template struct __declspec(dllexport) ExplicitlyExportInstantiatedTemplate<int>; |
441 | template <typename T> struct ExplicitlyImportInstantiatedTemplate { void func() {} }; |
442 | template struct __declspec(dllimport) ExplicitlyImportInstantiatedTemplate<int>; |
443 | |
444 | // ClassTemplate<int> gets exported. |
445 | class __declspec(dllexport) DerivedFromTemplate : public ClassTemplate<int> {}; |
446 | |
447 | // ClassTemplate<int> is already exported. |
448 | class __declspec(dllexport) DerivedFromTemplate2 : public ClassTemplate<int> {}; |
449 | |
450 | // ExportedTemplate is explicitly exported. |
451 | class __declspec(dllexport) DerivedFromExportedTemplate : public ExportedClassTemplate<int> {}; |
452 | |
453 | // ImportedTemplate is explicitly imported. |
454 | class __declspec(dllexport) DerivedFromImportedTemplate : public ImportedClassTemplate<int> {}; |
455 | |
456 | class DerivedFromTemplateD : public ClassTemplate<double> {}; |
457 | // Base class previously implicitly instantiated without attribute; it will get propagated. |
458 | class __declspec(dllexport) DerivedFromTemplateD2 : public ClassTemplate<double> {}; |
459 | |
460 | // Base class has explicit instantiation declaration; the attribute will get propagated. |
461 | extern template class ClassTemplate<float>; |
462 | class __declspec(dllexport) DerivedFromTemplateF : public ClassTemplate<float> {}; |
463 | |
464 | class __declspec(dllexport) DerivedFromTemplateB : public ClassTemplate<bool> {}; |
465 | // The second derived class doesn't change anything, the attribute that was propagated first wins. |
466 | class __declspec(dllimport) DerivedFromTemplateB2 : public ClassTemplate<bool> {}; |
467 | |
468 | #ifdef MS |
469 | // expected-warning@+3{{propagating dll attribute to explicitly specialized base class template without dll attribute is not supported}} |
470 | // expected-note@+2{{attribute is here}} |
471 | #endif |
472 | struct __declspec(dllexport) DerivedFromExplicitlySpecializedTemplate : public ExplicitlySpecializedTemplate<int> {}; |
473 | |
474 | // Base class alredy specialized with export attribute. |
475 | struct __declspec(dllexport) DerivedFromExplicitlyExportSpecializedTemplate : public ExplicitlyExportSpecializedTemplate<int> {}; |
476 | |
477 | // Base class already specialized with import attribute. |
478 | struct __declspec(dllexport) DerivedFromExplicitlyImportSpecializedTemplate : public ExplicitlyImportSpecializedTemplate<int> {}; |
479 | |
480 | #ifdef MS |
481 | // expected-warning@+3{{propagating dll attribute to already instantiated base class template without dll attribute is not supported}} |
482 | // expected-note@+2{{attribute is here}} |
483 | #endif |
484 | struct __declspec(dllexport) DerivedFromExplicitlyInstantiatedTemplate : public ExplicitlyInstantiatedTemplate<int> {}; |
485 | |
486 | // Base class already instantiated with export attribute. |
487 | struct __declspec(dllexport) DerivedFromExplicitlyExportInstantiatedTemplate : public ExplicitlyExportInstantiatedTemplate<int> {}; |
488 | |
489 | // Base class already instantiated with import attribute. |
490 | struct __declspec(dllexport) DerivedFromExplicitlyImportInstantiatedTemplate : public ExplicitlyImportInstantiatedTemplate<int> {}; |
491 | |
492 | template <typename T> struct ExplicitInstantiationDeclTemplateBase { void func() {} }; |
493 | extern template struct ExplicitInstantiationDeclTemplateBase<int>; |
494 | struct __declspec(dllexport) DerivedFromExplicitInstantiationDeclTemplateBase : public ExplicitInstantiationDeclTemplateBase<int> {}; |
495 | |
496 | |
497 | //===----------------------------------------------------------------------===// |
498 | // Precedence |
499 | //===----------------------------------------------------------------------===// |
500 | |
501 | // dllexport takes precedence over dllimport if both are specified. |
502 | __attribute__((dllimport, dllexport)) extern int PrecedenceExternGlobal1A; // expected-warning{{'dllimport' attribute ignored}} |
503 | __declspec(dllimport) __declspec(dllexport) extern int PrecedenceExternGlobal1B; // expected-warning{{'dllimport' attribute ignored}} |
504 | |
505 | __attribute__((dllexport, dllimport)) extern int PrecedenceExternGlobal2A; // expected-warning{{'dllimport' attribute ignored}} |
506 | __declspec(dllexport) __declspec(dllimport) extern int PrecedenceExternGlobal2B; // expected-warning{{'dllimport' attribute ignored}} |
507 | |
508 | __attribute__((dllimport, dllexport)) int PrecedenceGlobal1A; // expected-warning{{'dllimport' attribute ignored}} |
509 | __declspec(dllimport) __declspec(dllexport) int PrecedenceGlobal1B; // expected-warning{{'dllimport' attribute ignored}} |
510 | |
511 | __attribute__((dllexport, dllimport)) int PrecedenceGlobal2A; // expected-warning{{'dllimport' attribute ignored}} |
512 | __declspec(dllexport) __declspec(dllimport) int PrecedenceGlobal2B; // expected-warning{{'dllimport' attribute ignored}} |
513 | |
514 | __declspec(dllexport) extern int PrecedenceExternGlobalRedecl1; |
515 | __declspec(dllimport) extern int PrecedenceExternGlobalRedecl1; // expected-warning{{'dllimport' attribute ignored}} |
516 | |
517 | __declspec(dllimport) extern int PrecedenceExternGlobalRedecl2; // expected-warning{{'dllimport' attribute ignored}} |
518 | __declspec(dllexport) extern int PrecedenceExternGlobalRedecl2; |
519 | |
520 | __declspec(dllexport) extern int PrecedenceGlobalRedecl1; |
521 | __declspec(dllimport) int PrecedenceGlobalRedecl1; // expected-warning{{'dllimport' attribute ignored}} |
522 | |
523 | __declspec(dllimport) extern int PrecedenceGlobalRedecl2; // expected-warning{{'dllimport' attribute ignored}} |
524 | __declspec(dllexport) int PrecedenceGlobalRedecl2; |
525 | |
526 | void __attribute__((dllimport, dllexport)) precedence1A() {} // expected-warning{{'dllimport' attribute ignored}} |
527 | void __declspec(dllimport) __declspec(dllexport) precedence1B() {} // expected-warning{{'dllimport' attribute ignored}} |
528 | |
529 | void __attribute__((dllexport, dllimport)) precedence2A() {} // expected-warning{{'dllimport' attribute ignored}} |
530 | void __declspec(dllexport) __declspec(dllimport) precedence2B() {} // expected-warning{{'dllimport' attribute ignored}} |
531 | |
532 | void __declspec(dllimport) precedenceRedecl1(); // expected-warning{{'dllimport' attribute ignored}} |
533 | void __declspec(dllexport) precedenceRedecl1() {} |
534 | |
535 | void __declspec(dllexport) precedenceRedecl2(); |
536 | void __declspec(dllimport) precedenceRedecl2() {} // expected-warning{{'dllimport' attribute ignored}} |
537 | |
538 | |
539 | |
540 | //===----------------------------------------------------------------------===// |
541 | // Class members |
542 | //===----------------------------------------------------------------------===// |
543 | |
544 | // Export individual members of a class. |
545 | struct ExportMembers { |
546 | struct Nested { |
547 | __declspec(dllexport) void normalDef(); |
548 | }; |
549 | |
550 | __declspec(dllexport) void normalDecl(); |
551 | __declspec(dllexport) void normalDef(); |
552 | __declspec(dllexport) void normalInclass() {} |
553 | __declspec(dllexport) void normalInlineDef(); |
554 | __declspec(dllexport) inline void normalInlineDecl(); |
555 | __declspec(dllexport) virtual void virtualDecl(); |
556 | __declspec(dllexport) virtual void virtualDef(); |
557 | __declspec(dllexport) virtual void virtualInclass() {} |
558 | __declspec(dllexport) virtual void virtualInlineDef(); |
559 | __declspec(dllexport) virtual inline void virtualInlineDecl(); |
560 | __declspec(dllexport) static void staticDecl(); |
561 | __declspec(dllexport) static void staticDef(); |
562 | __declspec(dllexport) static void staticInclass() {} |
563 | __declspec(dllexport) static void staticInlineDef(); |
564 | __declspec(dllexport) static inline void staticInlineDecl(); |
565 | |
566 | protected: |
567 | __declspec(dllexport) void protectedDef(); |
568 | private: |
569 | __declspec(dllexport) void privateDef(); |
570 | public: |
571 | |
572 | __declspec(dllexport) int Field; // expected-warning{{'dllexport' attribute only applies to}} |
573 | __declspec(dllexport) static int StaticField; |
574 | __declspec(dllexport) static int StaticFieldDef; |
575 | __declspec(dllexport) static const int StaticConstField; |
576 | __declspec(dllexport) static const int StaticConstFieldDef; |
577 | __declspec(dllexport) static const int StaticConstFieldEqualInit = 1; |
578 | __declspec(dllexport) static const int StaticConstFieldBraceInit{1}; |
579 | __declspec(dllexport) constexpr static int ConstexprField = 1; |
580 | __declspec(dllexport) constexpr static int ConstexprFieldDef = 1; |
581 | }; |
582 | |
583 | void ExportMembers::Nested::normalDef() {} |
584 | void ExportMembers::normalDef() {} |
585 | inline void ExportMembers::normalInlineDef() {} |
586 | void ExportMembers::normalInlineDecl() {} |
587 | void ExportMembers::virtualDef() {} |
588 | inline void ExportMembers::virtualInlineDef() {} |
589 | void ExportMembers::virtualInlineDecl() {} |
590 | void ExportMembers::staticDef() {} |
591 | inline void ExportMembers::staticInlineDef() {} |
592 | void ExportMembers::staticInlineDecl() {} |
593 | void ExportMembers::protectedDef() {} |
594 | void ExportMembers::privateDef() {} |
595 | |
596 | int ExportMembers::StaticFieldDef; |
597 | const int ExportMembers::StaticConstFieldDef = 1; |
598 | constexpr int ExportMembers::ConstexprFieldDef; |
599 | |
600 | |
601 | // Export on member definitions. |
602 | struct ExportMemberDefs { |
603 | __declspec(dllexport) void normalDef(); |
604 | __declspec(dllexport) void normalInlineDef(); |
605 | __declspec(dllexport) inline void normalInlineDecl(); |
606 | __declspec(dllexport) virtual void virtualDef(); |
607 | __declspec(dllexport) virtual void virtualInlineDef(); |
608 | __declspec(dllexport) virtual inline void virtualInlineDecl(); |
609 | __declspec(dllexport) static void staticDef(); |
610 | __declspec(dllexport) static void staticInlineDef(); |
611 | __declspec(dllexport) static inline void staticInlineDecl(); |
612 | |
613 | __declspec(dllexport) static int StaticField; |
614 | __declspec(dllexport) static const int StaticConstField; |
615 | __declspec(dllexport) constexpr static int ConstexprField = 1; |
616 | }; |
617 | |
618 | __declspec(dllexport) void ExportMemberDefs::normalDef() {} |
619 | __declspec(dllexport) inline void ExportMemberDefs::normalInlineDef() {} |
620 | __declspec(dllexport) void ExportMemberDefs::normalInlineDecl() {} |
621 | __declspec(dllexport) void ExportMemberDefs::virtualDef() {} |
622 | __declspec(dllexport) inline void ExportMemberDefs::virtualInlineDef() {} |
623 | __declspec(dllexport) void ExportMemberDefs::virtualInlineDecl() {} |
624 | __declspec(dllexport) void ExportMemberDefs::staticDef() {} |
625 | __declspec(dllexport) inline void ExportMemberDefs::staticInlineDef() {} |
626 | __declspec(dllexport) void ExportMemberDefs::staticInlineDecl() {} |
627 | |
628 | __declspec(dllexport) int ExportMemberDefs::StaticField; |
629 | __declspec(dllexport) const int ExportMemberDefs::StaticConstField = 1; |
630 | __declspec(dllexport) constexpr int ExportMemberDefs::ConstexprField; |
631 | |
632 | |
633 | // Export special member functions. |
634 | struct ExportSpecials { |
635 | __declspec(dllexport) ExportSpecials() {} |
636 | __declspec(dllexport) ~ExportSpecials(); |
637 | __declspec(dllexport) inline ExportSpecials(const ExportSpecials&); |
638 | __declspec(dllexport) ExportSpecials& operator=(const ExportSpecials&); |
639 | __declspec(dllexport) ExportSpecials(ExportSpecials&&); |
640 | __declspec(dllexport) ExportSpecials& operator=(ExportSpecials&&); |
641 | }; |
642 | |
643 | ExportSpecials::~ExportSpecials() {} |
644 | ExportSpecials::ExportSpecials(const ExportSpecials&) {} |
645 | inline ExportSpecials& ExportSpecials::operator=(const ExportSpecials&) { return *this; } |
646 | ExportSpecials::ExportSpecials(ExportSpecials&&) {} |
647 | ExportSpecials& ExportSpecials::operator=(ExportSpecials&&) { return *this; } |
648 | |
649 | |
650 | // Export allocation functions. |
651 | extern "C" void* malloc(__SIZE_TYPE__ size); |
652 | extern "C" void free(void* p); |
653 | struct ExportAlloc { |
654 | __declspec(dllexport) void* operator new(__SIZE_TYPE__); |
655 | __declspec(dllexport) void* operator new[](__SIZE_TYPE__); |
656 | __declspec(dllexport) void operator delete(void*); |
657 | __declspec(dllexport) void operator delete[](void*); |
658 | }; |
659 | void* ExportAlloc::operator new(__SIZE_TYPE__ n) { return malloc(n); } |
660 | void* ExportAlloc::operator new[](__SIZE_TYPE__ n) { return malloc(n); } |
661 | void ExportAlloc::operator delete(void* p) { free(p); } |
662 | void ExportAlloc::operator delete[](void* p) { free(p); } |
663 | |
664 | |
665 | // Export deleted member functions. |
666 | struct ExportDeleted { |
667 | __declspec(dllexport) ExportDeleted() = delete; // expected-error{{attribute 'dllexport' cannot be applied to a deleted function}} |
668 | __declspec(dllexport) ~ExportDeleted() = delete; // expected-error{{attribute 'dllexport' cannot be applied to a deleted function}} |
669 | __declspec(dllexport) ExportDeleted(const ExportDeleted&) = delete; // expected-error{{attribute 'dllexport' cannot be applied to a deleted function}} |
670 | __declspec(dllexport) ExportDeleted& operator=(const ExportDeleted&) = delete; // expected-error{{attribute 'dllexport' cannot be applied to a deleted function}} |
671 | __declspec(dllexport) ExportDeleted(ExportDeleted&&) = delete; // expected-error{{attribute 'dllexport' cannot be applied to a deleted function}} |
672 | __declspec(dllexport) ExportDeleted& operator=(ExportDeleted&&) = delete; // expected-error{{attribute 'dllexport' cannot be applied to a deleted function}} |
673 | __declspec(dllexport) void deleted() = delete; // expected-error{{attribute 'dllexport' cannot be applied to a deleted function}} |
674 | }; |
675 | |
676 | |
677 | // Export defaulted member functions. |
678 | struct ExportDefaulted { |
679 | __declspec(dllexport) ExportDefaulted() = default; |
680 | __declspec(dllexport) ~ExportDefaulted() = default; |
681 | __declspec(dllexport) ExportDefaulted(const ExportDefaulted&) = default; |
682 | __declspec(dllexport) ExportDefaulted& operator=(const ExportDefaulted&) = default; |
683 | __declspec(dllexport) ExportDefaulted(ExportDefaulted&&) = default; |
684 | __declspec(dllexport) ExportDefaulted& operator=(ExportDefaulted&&) = default; |
685 | }; |
686 | |
687 | |
688 | // Export defaulted member function definitions. |
689 | struct ExportDefaultedDefs { |
690 | __declspec(dllexport) ExportDefaultedDefs(); |
691 | __declspec(dllexport) ~ExportDefaultedDefs(); |
692 | |
693 | __declspec(dllexport) inline ExportDefaultedDefs(const ExportDefaultedDefs&); |
694 | __declspec(dllexport) ExportDefaultedDefs& operator=(const ExportDefaultedDefs&); |
695 | |
696 | __declspec(dllexport) ExportDefaultedDefs(ExportDefaultedDefs&&); |
697 | __declspec(dllexport) ExportDefaultedDefs& operator=(ExportDefaultedDefs&&); |
698 | }; |
699 | |
700 | // Export definitions. |
701 | __declspec(dllexport) ExportDefaultedDefs::ExportDefaultedDefs() = default; |
702 | ExportDefaultedDefs::~ExportDefaultedDefs() = default; |
703 | |
704 | // Export inline declaration and definition. |
705 | __declspec(dllexport) ExportDefaultedDefs::ExportDefaultedDefs(const ExportDefaultedDefs&) = default; |
706 | inline ExportDefaultedDefs& ExportDefaultedDefs::operator=(const ExportDefaultedDefs&) = default; |
707 | |
708 | __declspec(dllexport) ExportDefaultedDefs::ExportDefaultedDefs(ExportDefaultedDefs&&) = default; |
709 | ExportDefaultedDefs& ExportDefaultedDefs::operator=(ExportDefaultedDefs&&) = default; |
710 | |
711 | |
712 | // Redeclarations cannot add dllexport. |
713 | struct MemberRedecl { |
714 | void normalDef(); // expected-note{{previous declaration is here}} |
715 | void normalInlineDef(); // expected-note{{previous declaration is here}} |
716 | inline void normalInlineDecl(); // expected-note{{previous declaration is here}} |
717 | virtual void virtualDef(); // expected-note{{previous declaration is here}} |
718 | virtual void virtualInlineDef(); // expected-note{{previous declaration is here}} |
719 | virtual inline void virtualInlineDecl(); // expected-note{{previous declaration is here}} |
720 | static void staticDef(); // expected-note{{previous declaration is here}} |
721 | static void staticInlineDef(); // expected-note{{previous declaration is here}} |
722 | static inline void staticInlineDecl(); // expected-note{{previous declaration is here}} |
723 | |
724 | static int StaticField; // expected-note{{previous declaration is here}} |
725 | static const int StaticConstField; // expected-note{{previous declaration is here}} |
726 | constexpr static int ConstexprField = 1; // expected-note{{previous declaration is here}} |
727 | }; |
728 | |
729 | __declspec(dllexport) void MemberRedecl::normalDef() {} // expected-error{{redeclaration of 'MemberRedecl::normalDef' cannot add 'dllexport' attribute}} |
730 | __declspec(dllexport) inline void MemberRedecl::normalInlineDef() {} // expected-error{{redeclaration of 'MemberRedecl::normalInlineDef' cannot add 'dllexport' attribute}} |
731 | __declspec(dllexport) void MemberRedecl::normalInlineDecl() {} // expected-error{{redeclaration of 'MemberRedecl::normalInlineDecl' cannot add 'dllexport' attribute}} |
732 | __declspec(dllexport) void MemberRedecl::virtualDef() {} // expected-error{{redeclaration of 'MemberRedecl::virtualDef' cannot add 'dllexport' attribute}} |
733 | __declspec(dllexport) inline void MemberRedecl::virtualInlineDef() {} // expected-error{{redeclaration of 'MemberRedecl::virtualInlineDef' cannot add 'dllexport' attribute}} |
734 | __declspec(dllexport) void MemberRedecl::virtualInlineDecl() {} // expected-error{{redeclaration of 'MemberRedecl::virtualInlineDecl' cannot add 'dllexport' attribute}} |
735 | __declspec(dllexport) void MemberRedecl::staticDef() {} // expected-error{{redeclaration of 'MemberRedecl::staticDef' cannot add 'dllexport' attribute}} |
736 | __declspec(dllexport) inline void MemberRedecl::staticInlineDef() {} // expected-error{{redeclaration of 'MemberRedecl::staticInlineDef' cannot add 'dllexport' attribute}} |
737 | __declspec(dllexport) void MemberRedecl::staticInlineDecl() {} // expected-error{{redeclaration of 'MemberRedecl::staticInlineDecl' cannot add 'dllexport' attribute}} |
738 | |
739 | __declspec(dllexport) int MemberRedecl::StaticField = 1; // expected-error{{redeclaration of 'MemberRedecl::StaticField' cannot add 'dllexport' attribute}} |
740 | __declspec(dllexport) const int MemberRedecl::StaticConstField = 1; // expected-error{{redeclaration of 'MemberRedecl::StaticConstField' cannot add 'dllexport' attribute}} |
741 | __declspec(dllexport) constexpr int MemberRedecl::ConstexprField; // expected-error{{redeclaration of 'MemberRedecl::ConstexprField' cannot add 'dllexport' attribute}} |
742 | |
743 | #ifdef MS |
744 | struct __declspec(dllexport) ClassWithMultipleDefaultCtors { |
745 | ClassWithMultipleDefaultCtors(int = 40) {} // expected-error{{'__declspec(dllexport)' cannot be applied to more than one default constructor}} |
746 | ClassWithMultipleDefaultCtors(int = 30, ...) {} // expected-note{{declared here}} |
747 | }; |
748 | template <typename T> |
749 | struct ClassTemplateWithMultipleDefaultCtors { |
750 | __declspec(dllexport) ClassTemplateWithMultipleDefaultCtors(int = 40) {} // expected-error{{'__declspec(dllexport)' cannot be applied to more than one default constructor}} |
751 | __declspec(dllexport) ClassTemplateWithMultipleDefaultCtors(int = 30, ...) {} // expected-note{{declared here}} |
752 | }; |
753 | |
754 | template <typename T> struct HasDefaults { |
755 | HasDefaults(int x = sizeof(T)) {} // expected-error {{invalid application of 'sizeof'}} |
756 | }; |
757 | template struct __declspec(dllexport) HasDefaults<char>; |
758 | |
759 | template struct |
760 | __declspec(dllexport) // expected-note {{in instantiation of default function argument expression for 'HasDefaults<void>' required here}} |
761 | HasDefaults<void>; // expected-note {{in instantiation of member function 'HasDefaults<void>::HasDefaults' requested here}} |
762 | |
763 | template <typename T> struct HasDefaults2 { |
764 | __declspec(dllexport) // expected-note {{in instantiation of default function argument expression for 'HasDefaults2<void>' required here}} |
765 | HasDefaults2(int x = sizeof(T)) {} // expected-error {{invalid application of 'sizeof'}} |
766 | }; |
767 | template struct HasDefaults2<void>; // expected-note {{in instantiation of member function 'HasDefaults2<void>::HasDefaults2' requested here}} |
768 | |
769 | #endif |
770 | |
771 | //===----------------------------------------------------------------------===// |
772 | // Class member templates |
773 | //===----------------------------------------------------------------------===// |
774 | |
775 | struct ExportMemberTmpl { |
776 | template<typename T> __declspec(dllexport) void normalDecl(); |
777 | template<typename T> __declspec(dllexport) void normalDef(); |
778 | template<typename T> __declspec(dllexport) void normalInclass() {} |
779 | template<typename T> __declspec(dllexport) void normalInlineDef(); |
780 | template<typename T> __declspec(dllexport) inline void normalInlineDecl(); |
781 | template<typename T> __declspec(dllexport) static void staticDecl(); |
782 | template<typename T> __declspec(dllexport) static void staticDef(); |
783 | template<typename T> __declspec(dllexport) static void staticInclass() {} |
784 | template<typename T> __declspec(dllexport) static void staticInlineDef(); |
785 | template<typename T> __declspec(dllexport) static inline void staticInlineDecl(); |
786 | |
787 | #if __has_feature(cxx_variable_templates) |
788 | template<typename T> __declspec(dllexport) static int StaticField; |
789 | template<typename T> __declspec(dllexport) static int StaticFieldDef; |
790 | template<typename T> __declspec(dllexport) static const int StaticConstField; |
791 | template<typename T> __declspec(dllexport) static const int StaticConstFieldDef; |
792 | template<typename T> __declspec(dllexport) static const int StaticConstFieldEqualInit = 1; |
793 | template<typename T> __declspec(dllexport) static const int StaticConstFieldBraceInit{1}; |
794 | template<typename T> __declspec(dllexport) constexpr static int ConstexprField = 1; |
795 | template<typename T> __declspec(dllexport) constexpr static int ConstexprFieldDef = 1; |
796 | #endif // __has_feature(cxx_variable_templates) |
797 | }; |
798 | |
799 | template<typename T> void ExportMemberTmpl::normalDef() {} |
800 | template<typename T> inline void ExportMemberTmpl::normalInlineDef() {} |
801 | template<typename T> void ExportMemberTmpl::normalInlineDecl() {} |
802 | template<typename T> void ExportMemberTmpl::staticDef() {} |
803 | template<typename T> inline void ExportMemberTmpl::staticInlineDef() {} |
804 | template<typename T> void ExportMemberTmpl::staticInlineDecl() {} |
805 | |
806 | #if __has_feature(cxx_variable_templates) |
807 | template<typename T> int ExportMemberTmpl::StaticFieldDef; |
808 | template<typename T> const int ExportMemberTmpl::StaticConstFieldDef = 1; |
809 | template<typename T> constexpr int ExportMemberTmpl::ConstexprFieldDef; |
810 | #endif // __has_feature(cxx_variable_templates) |
811 | |
812 | |
813 | // Redeclarations cannot add dllexport. |
814 | struct MemTmplRedecl { |
815 | template<typename T> void normalDef(); // expected-note{{previous declaration is here}} |
816 | template<typename T> void normalInlineDef(); // expected-note{{previous declaration is here}} |
817 | template<typename T> inline void normalInlineDecl(); // expected-note{{previous declaration is here}} |
818 | template<typename T> static void staticDef(); // expected-note{{previous declaration is here}} |
819 | template<typename T> static void staticInlineDef(); // expected-note{{previous declaration is here}} |
820 | template<typename T> static inline void staticInlineDecl(); // expected-note{{previous declaration is here}} |
821 | |
822 | #if __has_feature(cxx_variable_templates) |
823 | template<typename T> static int StaticField; // expected-note{{previous declaration is here}} |
824 | template<typename T> static const int StaticConstField; // expected-note{{previous declaration is here}} |
825 | template<typename T> constexpr static int ConstexprField = 1; // expected-note{{previous declaration is here}} |
826 | #endif // __has_feature(cxx_variable_templates) |
827 | }; |
828 | |
829 | template<typename T> __declspec(dllexport) void MemTmplRedecl::normalDef() {} // expected-error{{redeclaration of 'MemTmplRedecl::normalDef' cannot add 'dllexport' attribute}} |
830 | template<typename T> __declspec(dllexport) inline void MemTmplRedecl::normalInlineDef() {} // expected-error{{redeclaration of 'MemTmplRedecl::normalInlineDef' cannot add 'dllexport' attribute}} |
831 | template<typename T> __declspec(dllexport) void MemTmplRedecl::normalInlineDecl() {} // expected-error{{redeclaration of 'MemTmplRedecl::normalInlineDecl' cannot add 'dllexport' attribute}} |
832 | template<typename T> __declspec(dllexport) void MemTmplRedecl::staticDef() {} // expected-error{{redeclaration of 'MemTmplRedecl::staticDef' cannot add 'dllexport' attribute}} |
833 | template<typename T> __declspec(dllexport) inline void MemTmplRedecl::staticInlineDef() {} // expected-error{{redeclaration of 'MemTmplRedecl::staticInlineDef' cannot add 'dllexport' attribute}} |
834 | template<typename T> __declspec(dllexport) void MemTmplRedecl::staticInlineDecl() {} // expected-error{{redeclaration of 'MemTmplRedecl::staticInlineDecl' cannot add 'dllexport' attribute}} |
835 | |
836 | #if __has_feature(cxx_variable_templates) |
837 | template<typename T> __declspec(dllexport) int MemTmplRedecl::StaticField = 1; // expected-error{{redeclaration of 'MemTmplRedecl::StaticField' cannot add 'dllexport' attribute}} |
838 | template<typename T> __declspec(dllexport) const int MemTmplRedecl::StaticConstField = 1; // expected-error{{redeclaration of 'MemTmplRedecl::StaticConstField' cannot add 'dllexport' attribute}} |
839 | template<typename T> __declspec(dllexport) constexpr int MemTmplRedecl::ConstexprField; // expected-error{{redeclaration of 'MemTmplRedecl::ConstexprField' cannot add 'dllexport' attribute}} |
840 | #endif // __has_feature(cxx_variable_templates) |
841 | |
842 | |
843 | |
844 | struct MemFunTmpl { |
845 | template<typename T> void normalDef() {} |
846 | template<typename T> __declspec(dllexport) void exportedNormal() {} |
847 | template<typename T> static void staticDef() {} |
848 | template<typename T> __declspec(dllexport) static void exportedStatic() {} |
849 | }; |
850 | |
851 | // Export implicit instantiation of an exported member function template. |
852 | void useMemFunTmpl() { |
853 | MemFunTmpl().exportedNormal<ImplicitInst_Exported>(); |
854 | MemFunTmpl().exportedStatic<ImplicitInst_Exported>(); |
855 | } |
856 | |
857 | // Export explicit instantiation declaration of an exported member function |
858 | // template. |
859 | extern template void MemFunTmpl::exportedNormal<ExplicitDecl_Exported>(); |
860 | template void MemFunTmpl::exportedNormal<ExplicitDecl_Exported>(); |
861 | |
862 | extern template void MemFunTmpl::exportedStatic<ExplicitDecl_Exported>(); |
863 | template void MemFunTmpl::exportedStatic<ExplicitDecl_Exported>(); |
864 | |
865 | // Export explicit instantiation definition of an exported member function |
866 | // template. |
867 | template void MemFunTmpl::exportedNormal<ExplicitInst_Exported>(); |
868 | template void MemFunTmpl::exportedStatic<ExplicitInst_Exported>(); |
869 | |
870 | // Export specialization of an exported member function template. |
871 | template<> __declspec(dllexport) void MemFunTmpl::exportedNormal<ExplicitSpec_Exported>(); |
872 | template<> __declspec(dllexport) void MemFunTmpl::exportedNormal<ExplicitSpec_Def_Exported>() {} |
873 | template<> __declspec(dllexport) inline void MemFunTmpl::exportedNormal<ExplicitSpec_InlineDef_Exported>() {} |
874 | |
875 | template<> __declspec(dllexport) void MemFunTmpl::exportedStatic<ExplicitSpec_Exported>(); |
876 | template<> __declspec(dllexport) void MemFunTmpl::exportedStatic<ExplicitSpec_Def_Exported>() {} |
877 | template<> __declspec(dllexport) inline void MemFunTmpl::exportedStatic<ExplicitSpec_InlineDef_Exported>() {} |
878 | |
879 | // Not exporting specialization of an exported member function template without |
880 | // explicit dllexport. |
881 | template<> void MemFunTmpl::exportedNormal<ExplicitSpec_NotExported>() {} |
882 | template<> void MemFunTmpl::exportedStatic<ExplicitSpec_NotExported>() {} |
883 | |
884 | |
885 | // Export explicit instantiation declaration of a non-exported member function |
886 | // template. |
887 | extern template __declspec(dllexport) void MemFunTmpl::normalDef<ExplicitDecl_Exported>(); |
888 | template __declspec(dllexport) void MemFunTmpl::normalDef<ExplicitDecl_Exported>(); |
889 | |
890 | extern template __declspec(dllexport) void MemFunTmpl::staticDef<ExplicitDecl_Exported>(); |
891 | template __declspec(dllexport) void MemFunTmpl::staticDef<ExplicitDecl_Exported>(); |
892 | |
893 | // Export explicit instantiation definition of a non-exported member function |
894 | // template. |
895 | template __declspec(dllexport) void MemFunTmpl::normalDef<ExplicitInst_Exported>(); |
896 | template __declspec(dllexport) void MemFunTmpl::staticDef<ExplicitInst_Exported>(); |
897 | |
898 | // Export specialization of a non-exported member function template. |
899 | template<> __declspec(dllexport) void MemFunTmpl::normalDef<ExplicitSpec_Exported>(); |
900 | template<> __declspec(dllexport) void MemFunTmpl::normalDef<ExplicitSpec_Def_Exported>() {} |
901 | template<> __declspec(dllexport) inline void MemFunTmpl::normalDef<ExplicitSpec_InlineDef_Exported>() {} |
902 | |
903 | template<> __declspec(dllexport) void MemFunTmpl::staticDef<ExplicitSpec_Exported>(); |
904 | template<> __declspec(dllexport) void MemFunTmpl::staticDef<ExplicitSpec_Def_Exported>() {} |
905 | template<> __declspec(dllexport) inline void MemFunTmpl::staticDef<ExplicitSpec_InlineDef_Exported>() {} |
906 | |
907 | |
908 | |
909 | #if __has_feature(cxx_variable_templates) |
910 | struct MemVarTmpl { |
911 | template<typename T> static const int StaticVar = 1; |
912 | template<typename T> __declspec(dllexport) static const int ExportedStaticVar = 1; |
913 | }; |
914 | template<typename T> const int MemVarTmpl::StaticVar; |
915 | template<typename T> const int MemVarTmpl::ExportedStaticVar; |
916 | |
917 | // Export implicit instantiation of an exported member variable template. |
918 | int useMemVarTmpl() { return MemVarTmpl::ExportedStaticVar<ImplicitInst_Exported>; } |
919 | |
920 | // Export explicit instantiation declaration of an exported member variable |
921 | // template. |
922 | extern template const int MemVarTmpl::ExportedStaticVar<ExplicitDecl_Exported>; |
923 | template const int MemVarTmpl::ExportedStaticVar<ExplicitDecl_Exported>; |
924 | |
925 | // Export explicit instantiation definition of an exported member variable |
926 | // template. |
927 | template const int MemVarTmpl::ExportedStaticVar<ExplicitInst_Exported>; |
928 | |
929 | // Export specialization of an exported member variable template. |
930 | template<> __declspec(dllexport) const int MemVarTmpl::ExportedStaticVar<ExplicitSpec_Exported>; |
931 | template<> __declspec(dllexport) const int MemVarTmpl::ExportedStaticVar<ExplicitSpec_Def_Exported> = 1; |
932 | |
933 | // Not exporting specialization of an exported member variable template without |
934 | // explicit dllexport. |
935 | template<> const int MemVarTmpl::ExportedStaticVar<ExplicitSpec_NotExported>; |
936 | |
937 | |
938 | // Export explicit instantiation declaration of a non-exported member variable |
939 | // template. |
940 | extern template __declspec(dllexport) const int MemVarTmpl::StaticVar<ExplicitDecl_Exported>; |
941 | template __declspec(dllexport) const int MemVarTmpl::StaticVar<ExplicitDecl_Exported>; |
942 | |
943 | // Export explicit instantiation definition of a non-exported member variable |
944 | // template. |
945 | template __declspec(dllexport) const int MemVarTmpl::StaticVar<ExplicitInst_Exported>; |
946 | |
947 | // Export specialization of a non-exported member variable template. |
948 | template<> __declspec(dllexport) const int MemVarTmpl::StaticVar<ExplicitSpec_Exported>; |
949 | template<> __declspec(dllexport) const int MemVarTmpl::StaticVar<ExplicitSpec_Def_Exported> = 1; |
950 | |
951 | #endif // __has_feature(cxx_variable_templates) |
952 | |
953 | |
954 | |
955 | //===----------------------------------------------------------------------===// |
956 | // Class template members |
957 | //===----------------------------------------------------------------------===// |
958 | |
959 | // Export individual members of a class template. |
960 | template<typename T> |
961 | struct ExportClassTmplMembers { |
962 | __declspec(dllexport) void normalDecl(); |
963 | __declspec(dllexport) void normalDef(); |
964 | __declspec(dllexport) void normalInclass() {} |
965 | __declspec(dllexport) void normalInlineDef(); |
966 | __declspec(dllexport) inline void normalInlineDecl(); |
967 | __declspec(dllexport) virtual void virtualDecl(); |
968 | __declspec(dllexport) virtual void virtualDef(); |
969 | __declspec(dllexport) virtual void virtualInclass() {} |
970 | __declspec(dllexport) virtual void virtualInlineDef(); |
971 | __declspec(dllexport) virtual inline void virtualInlineDecl(); |
972 | __declspec(dllexport) static void staticDecl(); |
973 | __declspec(dllexport) static void staticDef(); |
974 | __declspec(dllexport) static void staticInclass() {} |
975 | __declspec(dllexport) static void staticInlineDef(); |
976 | __declspec(dllexport) static inline void staticInlineDecl(); |
977 | |
978 | protected: |
979 | __declspec(dllexport) void protectedDef(); |
980 | private: |
981 | __declspec(dllexport) void privateDef(); |
982 | public: |
983 | |
984 | __declspec(dllexport) int Field; // expected-warning{{'dllexport' attribute only applies to}} |
985 | __declspec(dllexport) static int StaticField; |
986 | __declspec(dllexport) static int StaticFieldDef; |
987 | __declspec(dllexport) static const int StaticConstField; |
988 | __declspec(dllexport) static const int StaticConstFieldDef; |
989 | __declspec(dllexport) static const int StaticConstFieldEqualInit = 1; |
990 | __declspec(dllexport) static const int StaticConstFieldBraceInit{1}; |
991 | __declspec(dllexport) constexpr static int ConstexprField = 1; |
992 | __declspec(dllexport) constexpr static int ConstexprFieldDef = 1; |
993 | }; |
994 | |
995 | template<typename T> void ExportClassTmplMembers<T>::normalDef() {} |
996 | template<typename T> inline void ExportClassTmplMembers<T>::normalInlineDef() {} |
997 | template<typename T> void ExportClassTmplMembers<T>::normalInlineDecl() {} |
998 | template<typename T> void ExportClassTmplMembers<T>::virtualDef() {} |
999 | template<typename T> inline void ExportClassTmplMembers<T>::virtualInlineDef() {} |
1000 | template<typename T> void ExportClassTmplMembers<T>::virtualInlineDecl() {} |
1001 | template<typename T> void ExportClassTmplMembers<T>::staticDef() {} |
1002 | template<typename T> inline void ExportClassTmplMembers<T>::staticInlineDef() {} |
1003 | template<typename T> void ExportClassTmplMembers<T>::staticInlineDecl() {} |
1004 | template<typename T> void ExportClassTmplMembers<T>::protectedDef() {} |
1005 | template<typename T> void ExportClassTmplMembers<T>::privateDef() {} |
1006 | |
1007 | template<typename T> int ExportClassTmplMembers<T>::StaticFieldDef; |
1008 | template<typename T> const int ExportClassTmplMembers<T>::StaticConstFieldDef = 1; |
1009 | template<typename T> constexpr int ExportClassTmplMembers<T>::ConstexprFieldDef; |
1010 | |
1011 | template struct ExportClassTmplMembers<ImplicitInst_Exported>; |
1012 | |
1013 | |
1014 | // Redeclarations cannot add dllexport. |
1015 | template<typename T> |
1016 | struct CTMR /*ClassTmplMemberRedecl*/ { |
1017 | void normalDef(); // expected-note{{previous declaration is here}} |
1018 | void normalInlineDef(); // expected-note{{previous declaration is here}} |
1019 | inline void normalInlineDecl(); // expected-note{{previous declaration is here}} |
1020 | virtual void virtualDef(); // expected-note{{previous declaration is here}} |
1021 | virtual void virtualInlineDef(); // expected-note{{previous declaration is here}} |
1022 | virtual inline void virtualInlineDecl(); // expected-note{{previous declaration is here}} |
1023 | static void staticDef(); // expected-note{{previous declaration is here}} |
1024 | static void staticInlineDef(); // expected-note{{previous declaration is here}} |
1025 | static inline void staticInlineDecl(); // expected-note{{previous declaration is here}} |
1026 | |
1027 | static int StaticField; // expected-note{{previous declaration is here}} |
1028 | static const int StaticConstField; // expected-note{{previous declaration is here}} |
1029 | constexpr static int ConstexprField = 1; // expected-note{{previous declaration is here}} |
1030 | }; |
1031 | |
1032 | template<typename T> __declspec(dllexport) void CTMR<T>::normalDef() {} // expected-error{{redeclaration of 'CTMR::normalDef' cannot add 'dllexport' attribute}} |
1033 | template<typename T> __declspec(dllexport) inline void CTMR<T>::normalInlineDef() {} // expected-error{{redeclaration of 'CTMR::normalInlineDef' cannot add 'dllexport' attribute}} |
1034 | template<typename T> __declspec(dllexport) void CTMR<T>::normalInlineDecl() {} // expected-error{{redeclaration of 'CTMR::normalInlineDecl' cannot add 'dllexport' attribute}} |
1035 | template<typename T> __declspec(dllexport) void CTMR<T>::virtualDef() {} // expected-error{{redeclaration of 'CTMR::virtualDef' cannot add 'dllexport' attribute}} |
1036 | template<typename T> __declspec(dllexport) inline void CTMR<T>::virtualInlineDef() {} // expected-error{{redeclaration of 'CTMR::virtualInlineDef' cannot add 'dllexport' attribute}} |
1037 | template<typename T> __declspec(dllexport) void CTMR<T>::virtualInlineDecl() {} // expected-error{{redeclaration of 'CTMR::virtualInlineDecl' cannot add 'dllexport' attribute}} |
1038 | template<typename T> __declspec(dllexport) void CTMR<T>::staticDef() {} // expected-error{{redeclaration of 'CTMR::staticDef' cannot add 'dllexport' attribute}} |
1039 | template<typename T> __declspec(dllexport) inline void CTMR<T>::staticInlineDef() {} // expected-error{{redeclaration of 'CTMR::staticInlineDef' cannot add 'dllexport' attribute}} |
1040 | template<typename T> __declspec(dllexport) void CTMR<T>::staticInlineDecl() {} // expected-error{{redeclaration of 'CTMR::staticInlineDecl' cannot add 'dllexport' attribute}} |
1041 | |
1042 | template<typename T> __declspec(dllexport) int CTMR<T>::StaticField = 1; // expected-error{{redeclaration of 'CTMR::StaticField' cannot add 'dllexport' attribute}} |
1043 | template<typename T> __declspec(dllexport) const int CTMR<T>::StaticConstField = 1; // expected-error{{redeclaration of 'CTMR::StaticConstField' cannot add 'dllexport' attribute}} |
1044 | template<typename T> __declspec(dllexport) constexpr int CTMR<T>::ConstexprField; // expected-error{{redeclaration of 'CTMR::ConstexprField' cannot add 'dllexport' attribute}} |
1045 | |
1046 | |
1047 | |
1048 | //===----------------------------------------------------------------------===// |
1049 | // Class template member templates |
1050 | //===----------------------------------------------------------------------===// |
1051 | |
1052 | template<typename T> |
1053 | struct ExportClsTmplMemTmpl { |
1054 | template<typename U> __declspec(dllexport) void normalDecl(); |
1055 | template<typename U> __declspec(dllexport) void normalDef(); |
1056 | template<typename U> __declspec(dllexport) void normalInclass() {} |
1057 | template<typename U> __declspec(dllexport) void normalInlineDef(); |
1058 | template<typename U> __declspec(dllexport) inline void normalInlineDecl(); |
1059 | template<typename U> __declspec(dllexport) static void staticDecl(); |
1060 | template<typename U> __declspec(dllexport) static void staticDef(); |
1061 | template<typename U> __declspec(dllexport) static void staticInclass() {} |
1062 | template<typename U> __declspec(dllexport) static void staticInlineDef(); |
1063 | template<typename U> __declspec(dllexport) static inline void staticInlineDecl(); |
1064 | |
1065 | #if __has_feature(cxx_variable_templates) |
1066 | template<typename U> __declspec(dllexport) static int StaticField; |
1067 | template<typename U> __declspec(dllexport) static int StaticFieldDef; |
1068 | template<typename U> __declspec(dllexport) static const int StaticConstField; |
1069 | template<typename U> __declspec(dllexport) static const int StaticConstFieldDef; |
1070 | template<typename U> __declspec(dllexport) static const int StaticConstFieldEqualInit = 1; |
1071 | template<typename U> __declspec(dllexport) static const int StaticConstFieldBraceInit{1}; |
1072 | template<typename U> __declspec(dllexport) constexpr static int ConstexprField = 1; |
1073 | template<typename U> __declspec(dllexport) constexpr static int ConstexprFieldDef = 1; |
1074 | #endif // __has_feature(cxx_variable_templates) |
1075 | }; |
1076 | |
1077 | template<typename T> template<typename U> void ExportClsTmplMemTmpl<T>::normalDef() {} |
1078 | template<typename T> template<typename U> inline void ExportClsTmplMemTmpl<T>::normalInlineDef() {} |
1079 | template<typename T> template<typename U> void ExportClsTmplMemTmpl<T>::normalInlineDecl() {} |
1080 | template<typename T> template<typename U> void ExportClsTmplMemTmpl<T>::staticDef() {} |
1081 | template<typename T> template<typename U> inline void ExportClsTmplMemTmpl<T>::staticInlineDef() {} |
1082 | template<typename T> template<typename U> void ExportClsTmplMemTmpl<T>::staticInlineDecl() {} |
1083 | |
1084 | #if __has_feature(cxx_variable_templates) |
1085 | template<typename T> template<typename U> int ExportClsTmplMemTmpl<T>::StaticFieldDef; |
1086 | template<typename T> template<typename U> const int ExportClsTmplMemTmpl<T>::StaticConstFieldDef = 1; |
1087 | template<typename T> template<typename U> constexpr int ExportClsTmplMemTmpl<T>::ConstexprFieldDef; |
1088 | #endif // __has_feature(cxx_variable_templates) |
1089 | |
1090 | |
1091 | // Redeclarations cannot add dllexport. |
1092 | template<typename T> |
1093 | struct CTMTR /*ClassTmplMemberTmplRedecl*/ { |
1094 | template<typename U> void normalDef(); // expected-note{{previous declaration is here}} |
1095 | template<typename U> void normalInlineDef(); // expected-note{{previous declaration is here}} |
1096 | template<typename U> inline void normalInlineDecl(); // expected-note{{previous declaration is here}} |
1097 | template<typename U> static void staticDef(); // expected-note{{previous declaration is here}} |
1098 | template<typename U> static void staticInlineDef(); // expected-note{{previous declaration is here}} |
1099 | template<typename U> static inline void staticInlineDecl(); // expected-note{{previous declaration is here}} |
1100 | |
1101 | #if __has_feature(cxx_variable_templates) |
1102 | template<typename U> static int StaticField; // expected-note{{previous declaration is here}} |
1103 | template<typename U> static const int StaticConstField; // expected-note{{previous declaration is here}} |
1104 | template<typename U> constexpr static int ConstexprField = 1; // expected-note{{previous declaration is here}} |
1105 | #endif // __has_feature(cxx_variable_templates) |
1106 | }; |
1107 | |
1108 | template<typename T> template<typename U> __declspec(dllexport) void CTMTR<T>::normalDef() {} // expected-error{{redeclaration of 'CTMTR::normalDef' cannot add 'dllexport' attribute}} |
1109 | template<typename T> template<typename U> __declspec(dllexport) inline void CTMTR<T>::normalInlineDef() {} // expected-error{{redeclaration of 'CTMTR::normalInlineDef' cannot add 'dllexport' attribute}} |
1110 | template<typename T> template<typename U> __declspec(dllexport) void CTMTR<T>::normalInlineDecl() {} // expected-error{{redeclaration of 'CTMTR::normalInlineDecl' cannot add 'dllexport' attribute}} |
1111 | template<typename T> template<typename U> __declspec(dllexport) void CTMTR<T>::staticDef() {} // expected-error{{redeclaration of 'CTMTR::staticDef' cannot add 'dllexport' attribute}} |
1112 | template<typename T> template<typename U> __declspec(dllexport) inline void CTMTR<T>::staticInlineDef() {} // expected-error{{redeclaration of 'CTMTR::staticInlineDef' cannot add 'dllexport' attribute}} |
1113 | template<typename T> template<typename U> __declspec(dllexport) void CTMTR<T>::staticInlineDecl() {} // expected-error{{redeclaration of 'CTMTR::staticInlineDecl' cannot add 'dllexport' attribute}} |
1114 | |
1115 | #if __has_feature(cxx_variable_templates) |
1116 | template<typename T> template<typename U> __declspec(dllexport) int CTMTR<T>::StaticField = 1; // expected-error{{redeclaration of 'CTMTR::StaticField' cannot add 'dllexport' attribute}} |
1117 | template<typename T> template<typename U> __declspec(dllexport) const int CTMTR<T>::StaticConstField = 1; // expected-error{{redeclaration of 'CTMTR::StaticConstField' cannot add 'dllexport' attribute}} |
1118 | template<typename T> template<typename U> __declspec(dllexport) constexpr int CTMTR<T>::ConstexprField; // expected-error{{redeclaration of 'CTMTR::ConstexprField' cannot add 'dllexport' attribute}} |
1119 | #endif // __has_feature(cxx_variable_templates) |
1120 | |
1121 | // FIXME: Precedence rules seem to be different for classes. |
1122 | |
1123 | //===----------------------------------------------------------------------===// |
1124 | // Lambdas |
1125 | //===----------------------------------------------------------------------===// |
1126 | // The MS ABI doesn't provide a stable mangling for lambdas, so they can't be imported or exported. |
1127 | #ifdef MS |
1128 | // expected-error@+2{{lambda cannot be declared 'dllexport'}} |
1129 | #endif |
1130 | auto Lambda = []() __declspec(dllexport) -> bool { return true; }; |
1131 | |