[Sema] Use MSVC inner class behavior on Itanium

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

llvm-svn: 300804
This commit is contained in:
Shoaib Meenai 2017-04-20 01:11:42 +00:00
parent 2b0d6134c7
commit a90474544e
2 changed files with 29 additions and 3 deletions

View 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;
}

View 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