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