]> granicus.if.org Git - clang/commitdiff
[Sema] Use MSVC inner class behavior on Itanium
authorShoaib Meenai <smeenai@fb.com>
Thu, 20 Apr 2017 01:11:42 +0000 (01:11 +0000)
committerShoaib Meenai <smeenai@fb.com>
Thu, 20 Apr 2017 01:11:42 +0000 (01:11 +0000)
Windows Itanium aims to use MSVC export and import semantics. Inner
class members shouldn't be exported on a dllexport explicit
instantiation definition of the outer class, and they shouldn't be
imported on a dllimport explicit instantiation declaration of the outer
class (instead a local copy should be emitted). We were doing the first
but not the second, and this mismatch can lead to link errors. Fix the
behavior and add tests for both.

Differential Revision: https://reviews.llvm.org/D32213

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@300804 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaTemplateInstantiate.cpp
test/CodeGenCXX/windows-itanium-dllexport.cpp

index edd6edfce9dc7a795a6d59856c738b75ef382737..2d44489023ef814713be6b1468feed8391f363c8 100644 (file)
@@ -2605,10 +2605,11 @@ Sema::InstantiateClassMembers(SourceLocation PointOfInstantiation,
                                                 == TSK_ExplicitSpecialization)
         continue;
 
-      if (Context.getTargetInfo().getCXXABI().isMicrosoft() &&
+      if ((Context.getTargetInfo().getCXXABI().isMicrosoft() ||
+           Context.getTargetInfo().getTriple().isWindowsItaniumEnvironment()) &&
           TSK == TSK_ExplicitInstantiationDeclaration) {
-        // In MSVC mode, explicit instantiation decl of the outer class doesn't
-        // affect the inner class.
+        // In MSVC and Windows Itanium mode, explicit instantiation decl of the
+        // outer class doesn't affect the inner class.
         continue;
       }
 
index 92cca24442874717a27675ce1d2c64c5db943c62..ff780c777822d2ef464e0e685fea71026cb3d86c 100644 (file)
@@ -1,5 +1,10 @@
 // RUN: %clang_cc1 -emit-llvm -triple i686-windows-itanium -fdeclspec %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; }
+
 struct __declspec(dllexport) s {
   void f() {}
 };
@@ -28,3 +33,23 @@ template class __declspec(dllexport) c<double>;
 
 // CHECK: define {{.*}} dllexport {{.*}} @_ZN1cIdEaSERKS0_
 // CHECK: define {{.*}} dllexport {{.*}} @_ZN1cIdE1fEv
+
+template <class T>
+struct outer {
+  void f() {}
+  struct inner {
+    void f() {}
+  };
+};
+
+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