smeenai created this revision. 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.
https://reviews.llvm.org/D32213 Files: lib/Sema/SemaTemplateInstantiate.cpp test/CodeGenCXX/windows-itanium-dllexport.cpp Index: test/CodeGenCXX/windows-itanium-dllexport.cpp =================================================================== --- test/CodeGenCXX/windows-itanium-dllexport.cpp +++ test/CodeGenCXX/windows-itanium-dllexport.cpp @@ -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 @@ // 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 Index: lib/Sema/SemaTemplateInstantiate.cpp =================================================================== --- lib/Sema/SemaTemplateInstantiate.cpp +++ lib/Sema/SemaTemplateInstantiate.cpp @@ -2605,10 +2605,11 @@ == 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: test/CodeGenCXX/windows-itanium-dllexport.cpp =================================================================== --- test/CodeGenCXX/windows-itanium-dllexport.cpp +++ test/CodeGenCXX/windows-itanium-dllexport.cpp @@ -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 @@ // 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 Index: lib/Sema/SemaTemplateInstantiate.cpp =================================================================== --- lib/Sema/SemaTemplateInstantiate.cpp +++ lib/Sema/SemaTemplateInstantiate.cpp @@ -2605,10 +2605,11 @@ == 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; }
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits