================
@@ -0,0 +1,181 @@
+// RUN: %clang_cc1 -triple x86_64-win32 -fms-extensions -emit-llvm -o - %s | \
+// RUN:     FileCheck %s --check-prefixes=MSC --implicit-check-not=to_be_ 
--implicit-check-not=dllexport
+// RUN: %clang_cc1 -triple x86_64-mingw                 -emit-llvm -o - %s | \
+// RUN:     FileCheck %s --check-prefixes=GNU --implicit-check-not=to_be_ 
--implicit-check-not=dllexport
+// RUN: %clang_cc1 -triple x86_64-cygwin                -emit-llvm -o - %s | \
+// RUN:     FileCheck %s --check-prefixes=GNU --implicit-check-not=to_be_ 
--implicit-check-not=dllexport
+
+// Test that __declspec(dllexport) doesn't instantiate entities marked with
+// the exclude_from_explicit_instantiation attribute unless marked as 
dllexport explicitly.
+
+// Silence --implicit-check-not=dllexport.
+// MSC: ModuleID = {{.*}}exclude_from_dllexport.cpp
+// MSC: source_filename = {{.*}}exclude_from_dllexport.cpp
+// GNU: ModuleID = {{.*}}exclude_from_dllexport.cpp
+// GNU: source_filename = {{.*}}exclude_from_dllexport.cpp
+
+#define EXCLUDE_FROM_EXPLICIT_INSTANTIATION 
__attribute__((exclude_from_explicit_instantiation))
+
+template <class T>
+struct C {
+  // This will be instantiated explicitly as an exported function because it
+  // inherits dllexport from the class instantiation.
+  void to_be_exported();
+
+  // This will be instantiated implicitly as an exported function because it is
+  // marked as dllexport explicitly.
+  EXCLUDE_FROM_EXPLICIT_INSTANTIATION __declspec(dllexport) void 
to_be_exported_explicitly();
+
+  // This will be instantiated implicitly but won't be exported.
+  EXCLUDE_FROM_EXPLICIT_INSTANTIATION void not_to_be_exported();
+
+  // This won't be instantiated.
+  EXCLUDE_FROM_EXPLICIT_INSTANTIATION void not_to_be_instantiated();
+};
+
+template <class T> void C<T>::to_be_exported() {}
+template <class T> void C<T>::to_be_exported_explicitly() {}
+template <class T> void C<T>::not_to_be_exported() {}
+template <class T> void C<T>::not_to_be_instantiated() {}
+
+// Attach the attribute to class template declaration instead of instantiation 
declaration.
+template <class T>
+struct __declspec(dllexport) D {
+  // This will be exported if and only if no explicit instantiations are 
provided.
+  EXCLUDE_FROM_EXPLICIT_INSTANTIATION void 
to_be_exported_iff_no_explicit_instantiation();
+};
+
+template <class T> void D<T>::to_be_exported_iff_no_explicit_instantiation() {}
+
+// Interaction with VTables.
+template <class T>
+struct E {
+  // This will be instanciated by the explicit template instantiation 
definition.
+  virtual void to_be_exported();
+
+  // This will be instantiated by the VTable definition, regardless of
+  // `exclude_from_explicit_instantiation`.
+  // The dllexport attribute won't be inherited.
+  EXCLUDE_FROM_EXPLICIT_INSTANTIATION virtual void to_be_instantiated();
+
+  // This too, but will be exported by the member attribute.
+  EXCLUDE_FROM_EXPLICIT_INSTANTIATION __declspec(dllexport) virtual void 
to_be_exported_explicitly();
+};
+
+template <class T> void E<T>::to_be_exported() {}
+template <class T> void E<T>::to_be_instantiated() {}
+template <class T> void E<T>::to_be_exported_explicitly() {}
+
+// MSC: $"?to_be_exported@?$C@H@@QEAAXXZ" = comdat any
+// MSC: $"?to_be_exported@?$E@H@@UEAAXXZ" = comdat any
+// MSC: $"?to_be_exported@?$E@I@@UEAAXXZ" = comdat any
+// MSC: $"?to_be_exported_explicitly@?$C@H@@QEAAXXZ" = comdat any
+// MSC: $"?not_to_be_exported@?$C@H@@QEAAXXZ" = comdat any
+// MSC: $"?to_be_exported_iff_no_explicit_instantiation@?$D@H@@QEAAXXZ" = 
comdat any
+// MSC: $"?to_be_exported_iff_no_explicit_instantiation@?$D@I@@QEAAXXZ" = 
comdat any
+// MSC: $"?to_be_instantiated@?$E@H@@UEAAXXZ" = comdat any
+// MSC: $"?to_be_exported_explicitly@?$E@H@@UEAAXXZ" = comdat any
+// MSC: $"?to_be_instantiated@?$E@I@@UEAAXXZ" = comdat any
+// MSC: $"?to_be_exported_explicitly@?$E@I@@UEAAXXZ" = comdat any
+// GNU: $_ZN1CIiE14to_be_exportedEv = comdat any
+// GNU: $_ZN1EIiE14to_be_exportedEv = comdat any
+// GNU: $_ZN1EIjE14to_be_exportedEv = comdat any
+// GNU: $_ZN1CIiE25to_be_exported_explicitlyEv = comdat any
+// GNU: $_ZN1CIiE18not_to_be_exportedEv = comdat any
+// GNU: $_ZN1DIiE44to_be_exported_iff_no_explicit_instantiationEv = comdat any
+// GNU: $_ZN1DIjE44to_be_exported_iff_no_explicit_instantiationEv = comdat any
+// GNU: $_ZN1EIiE18to_be_instantiatedEv = comdat any
+// GNU: $_ZN1EIiE25to_be_exported_explicitlyEv = comdat any
+// GNU: $_ZN1EIjE18to_be_instantiatedEv = comdat any
+// GNU: $_ZN1EIjE25to_be_exported_explicitlyEv = comdat any
+
+// MSC: @0 = private unnamed_addr constant {{.*}}, comdat($"??_7?$E@H@@6B@")
+// MSC: @1 = private unnamed_addr constant {{.*}}, comdat($"??_7?$E@I@@6B@")
+// MSC: @"??_7?$E@H@@6B@" = dllexport unnamed_addr
+// MSC: @"??_7?$E@I@@6B@" = unnamed_addr
+// GNU: @_ZTV1EIiE = weak_odr dso_local dllexport unnamed_addr constant 
{{.*}}, comdat
+// GNU: @_ZTV1EIjE = weak_odr dso_local unnamed_addr constant {{.*}}, comdat
+
+// MSC: define weak_odr dso_local dllexport{{.*}} ptr 
@"??4?$C@H@@QEAAAEAU0@AEBU0@@Z"
+// MSC: define weak_odr dso_local dllexport{{.*}} ptr 
@"??4?$C@H@@QEAAAEAU0@$$QEAU0@@Z"
+// MSC: define weak_odr dso_local dllexport{{.*}} void 
@"?to_be_exported@?$C@H@@QEAAXXZ"
+// GNU: define weak_odr dso_local dllexport{{.*}} ptr @_ZN1CIiEaSERKS0_
+// GNU: define weak_odr dso_local dllexport{{.*}} ptr @_ZN1CIiEaSEOS0_
+// GNU: define weak_odr dso_local dllexport{{.*}} void 
@_ZN1CIiE14to_be_exportedEv
+template struct __declspec(dllexport) C<int>;
----------------
zmodem wrote:

I'd suggest moving the instantiation of C, and the checks related to it, to the 
definition of C above.

Having the class definition, with the explanatory comments, and the test 
expectations closer together will make the test easier to read.

Same for the other classes.

https://github.com/llvm/llvm-project/pull/168171
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to