r288682 - [Sema] Respect DLL attributes more faithfully
Shoaib Meenai via cfe-commits
cfe-commits at lists.llvm.org
Mon Dec 5 10:01:35 PST 2016
Author: smeenai
Date: Mon Dec 5 12:01:35 2016
New Revision: 288682
URL: http://llvm.org/viewvc/llvm-project?rev=288682&view=rev
Log:
[Sema] Respect DLL attributes more faithfully
On MSVC, if an implicit instantiation already exists and an explicit
instantiation definition with a DLL attribute is created, the DLL
attribute still takes effect. Make clang match this behavior for
exporting.
Differential Revision: https://reviews.llvm.org/D26657
Modified:
cfe/trunk/lib/Sema/SemaTemplate.cpp
cfe/trunk/test/CodeGenCXX/dllexport.cpp
cfe/trunk/test/CodeGenCXX/windows-itanium-dllexport.cpp
Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=288682&r1=288681&r2=288682&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Mon Dec 5 12:01:35 2016
@@ -7435,6 +7435,30 @@ static bool ScopeSpecifierHasTemplateId(
return false;
}
+/// Make a dllexport or dllimport attr on a class template specialization take
+/// effect.
+static void dllExportImportClassTemplateSpecialization(
+ Sema &S, ClassTemplateSpecializationDecl *Def) {
+ auto *A = cast_or_null<InheritableAttr>(getDLLAttr(Def));
+ assert(A && "dllExportImportClassTemplateSpecialization called "
+ "on Def without dllexport or dllimport");
+
+ // We reject explicit instantiations in class scope, so there should
+ // never be any delayed exported classes to worry about.
+ assert(S.DelayedDllExportClasses.empty() &&
+ "delayed exports present at explicit instantiation");
+ S.checkClassLevelDLLAttribute(Def);
+
+ // Propagate attribute to base class templates.
+ for (auto &B : Def->bases()) {
+ if (auto *BT = dyn_cast_or_null<ClassTemplateSpecializationDecl>(
+ B.getType()->getAsCXXRecordDecl()))
+ S.propagateDLLAttrToBaseClassTemplate(Def, A, BT, B.getLocStart());
+ }
+
+ S.referenceDLLExportedClassMethods();
+}
+
// Explicit instantiation of a class template specialization
DeclResult
Sema::ActOnExplicitInstantiation(Scope *S,
@@ -7681,24 +7705,33 @@ Sema::ActOnExplicitInstantiation(Scope *
getDLLAttr(Specialization)->clone(getASTContext()));
A->setInherited(true);
Def->addAttr(A);
-
- // We reject explicit instantiations in class scope, so there should
- // never be any delayed exported classes to worry about.
- assert(DelayedDllExportClasses.empty() &&
- "delayed exports present at explicit instantiation");
- checkClassLevelDLLAttribute(Def);
-
- // Propagate attribute to base class templates.
- for (auto &B : Def->bases()) {
- if (auto *BT = dyn_cast_or_null<ClassTemplateSpecializationDecl>(
- B.getType()->getAsCXXRecordDecl()))
- propagateDLLAttrToBaseClassTemplate(Def, A, BT, B.getLocStart());
- }
-
- referenceDLLExportedClassMethods();
+ dllExportImportClassTemplateSpecialization(*this, Def);
}
}
+ // Fix a TSK_ImplicitInstantiation followed by a
+ // TSK_ExplicitInstantiationDefinition
+ if (Old_TSK == TSK_ImplicitInstantiation &&
+ Specialization->hasAttr<DLLExportAttr>() &&
+ (Context.getTargetInfo().getCXXABI().isMicrosoft() ||
+ Context.getTargetInfo().getTriple().isWindowsItaniumEnvironment())) {
+ // In the MS ABI, an explicit instantiation definition can add a dll
+ // attribute to a template with a previous implicit instantiation.
+ // MinGW doesn't allow this. We limit clang to only adding dllexport, to
+ // avoid potentially strange codegen behavior. For example, if we extend
+ // this conditional to dllimport, and we have a source file calling a
+ // method on an implicitly instantiated template class instance and then
+ // declaring a dllimport explicit instantiation definition for the same
+ // template class, the codegen for the method call will not respect the
+ // dllimport, while it will with cl. The Def will already have the DLL
+ // attribute, since the Def and Specialization will be the same in the
+ // case of Old_TSK == TSK_ImplicitInstantiation, and we already added the
+ // attribute to the Specialization; we just need to make it take effect.
+ assert(Def == Specialization &&
+ "Def and Specialization should match for implicit instantiation");
+ dllExportImportClassTemplateSpecialization(*this, Def);
+ }
+
// Set the template specialization kind. Make sure it is set before
// instantiating the members which will trigger ASTConsumer callbacks.
Specialization->setTemplateSpecializationKind(TSK);
Modified: cfe/trunk/test/CodeGenCXX/dllexport.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/dllexport.cpp?rev=288682&r1=288681&r2=288682&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/dllexport.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/dllexport.cpp Mon Dec 5 12:01:35 2016
@@ -771,6 +771,13 @@ USEMEMFUNC(ExplicitInstantiationDeclExpo
// M32-DAG: define weak_odr dllexport x86_thiscallcc %struct.ExplicitInstantiationDeclExportedDefTemplate* @"\01??0?$ExplicitInstantiationDeclExportedDefTemplate at H@@QAE at XZ"
// G32-DAG: define weak_odr x86_thiscallcc void @_ZN44ExplicitInstantiationDeclExportedDefTemplateIiE1fEv
+template <typename T> struct ImplicitInstantiationExplicitInstantiationDefExportedTemplate { void f() {} };
+ImplicitInstantiationExplicitInstantiationDefExportedTemplate<int> ImplicitInstantiationExplicitInstantiationDefExportedTemplateInstance;
+template class __declspec(dllexport) ImplicitInstantiationExplicitInstantiationDefExportedTemplate<int>;
+USEMEMFUNC(ImplicitInstantiationExplicitInstantiationDefExportedTemplate<int>, f);
+// M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?f@?$ImplicitInstantiationExplicitInstantiationDefExportedTemplate at H@@QAEXXZ"
+// G32-DAG: define weak_odr x86_thiscallcc void @_ZN61ImplicitInstantiationExplicitInstantiationDefExportedTemplateIiE1fEv
+
namespace { struct InternalLinkageType {}; }
struct __declspec(dllexport) PR23308 {
void f(InternalLinkageType*);
Modified: cfe/trunk/test/CodeGenCXX/windows-itanium-dllexport.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/windows-itanium-dllexport.cpp?rev=288682&r1=288681&r2=288682&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/windows-itanium-dllexport.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/windows-itanium-dllexport.cpp Mon Dec 5 12:01:35 2016
@@ -23,3 +23,8 @@ template class __declspec(dllexport) c<c
// CHECK: define {{.*}} dllexport {{.*}} @_ZN1cIcEaSERKS0_
// CHECK: define {{.*}} dllexport {{.*}} @_ZN1cIcE1fEv
+c<double> g;
+template class __declspec(dllexport) c<double>;
+
+// CHECK: define {{.*}} dllexport {{.*}} @_ZN1cIdEaSERKS0_
+// CHECK: define {{.*}} dllexport {{.*}} @_ZN1cIdE1fEv
More information about the cfe-commits
mailing list