summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Storsjo <martin@martin.st>2019-04-26 19:31:39 +0000
committerMartin Storsjo <martin@martin.st>2019-04-26 19:31:39 +0000
commitda93dec330507c5f5ff20115a4d571979ed31393 (patch)
treec05170c984248112ffb902ed8960a06c9677d646
parentc03fe73176067a2eb2ed5aca8ec685b6ea931b30 (diff)
downloadbcm5719-llvm-da93dec330507c5f5ff20115a4d571979ed31393.tar.gz
bcm5719-llvm-da93dec330507c5f5ff20115a4d571979ed31393.zip
[MinGW] Don't let template instantiation declarations cover nested classes
An explicit template instantiation declaration used to let callers assume both outer and nested classes instantiations were defined in a different translation unit. If the instantiation is marked dllexport, only the outer class is exported, but the caller will try to reference the instantiation of both outer and inner classes. This makes MinGW mode match both MSVC and Windows Itanium, by having instantations only cover the outer class, and locally emitting definitions of the nested classes. Windows Itanium was changed to use this behavious in SVN r300804. This deviates from what GCC does, but should be safe (and only inflate the object file size a bit, but MSVC and Windows Itanium modes do the same), and fixes cases where inner classes aren't dllexported. This fixes missing references in combination with dllexported/imported template intantiations. GCC suffers from the same issue, reported at [1], but the issue is still unresolved there. The issue can probably be solved either by making dllexport cover all nested classes as well, or this way (matching MSVC). [1] https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89087 Differential Revision: https://reviews.llvm.org/D61175 llvm-svn: 359342
-rw-r--r--clang/lib/Sema/SemaTemplateInstantiate.cpp6
-rw-r--r--clang/test/CodeGenCXX/mingw-template-dllexport.cpp12
2 files changed, 17 insertions, 1 deletions
diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp
index c7457354b33..a7be1ea7c89 100644
--- a/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -2685,10 +2685,14 @@ Sema::InstantiateClassMembers(SourceLocation PointOfInstantiation,
continue;
if ((Context.getTargetInfo().getCXXABI().isMicrosoft() ||
- Context.getTargetInfo().getTriple().isWindowsItaniumEnvironment()) &&
+ Context.getTargetInfo().getTriple().isWindowsItaniumEnvironment() ||
+ Context.getTargetInfo().getTriple().isWindowsGNUEnvironment()) &&
TSK == TSK_ExplicitInstantiationDeclaration) {
// In MSVC and Windows Itanium mode, explicit instantiation decl of the
// outer class doesn't affect the inner class.
+ // In GNU mode, inner classes aren't dllexported. Don't let the
+ // instantiation cover the inner class, to avoid undefined references
+ // to inner classes that weren't exported.
continue;
}
diff --git a/clang/test/CodeGenCXX/mingw-template-dllexport.cpp b/clang/test/CodeGenCXX/mingw-template-dllexport.cpp
index 478c4dfb288..9e8f9b1bccf 100644
--- a/clang/test/CodeGenCXX/mingw-template-dllexport.cpp
+++ b/clang/test/CodeGenCXX/mingw-template-dllexport.cpp
@@ -1,5 +1,10 @@
// RUN: %clang_cc1 -emit-llvm -triple i686-mingw32 %s -o - | FileCheck %s
+#define JOIN2(x, y) x##y
+#define JOIN(x, y) JOIN2(x, y)
+#define UNIQ(name) JOIN(name, __LINE__)
+#define USEMEMFUNC(class, func) void (class::*UNIQ(use)())() { return &class::func; }
+
template <class T>
class c {
void f();
@@ -36,3 +41,10 @@ template class __declspec(dllexport) outer<int>;
// CHECK: define {{.*}} dllexport {{.*}} @_ZN5outerIiE1fEv
// CHECK-NOT: define {{.*}} dllexport {{.*}} @_ZN5outerIiE5inner1fEv
+
+extern template class __declspec(dllimport) outer<char>;
+USEMEMFUNC(outer<char>, f)
+USEMEMFUNC(outer<char>::inner, f)
+
+// CHECK: declare dllimport {{.*}} @_ZN5outerIcE1fEv
+// CHECK: define {{.*}} @_ZN5outerIcE5inner1fEv
OpenPOWER on IntegriCloud