r262056 - [dllexport] Sort out emission order of delayed exported classes

Reid Kleckner via cfe-commits cfe-commits at lists.llvm.org
Fri Feb 26 11:51:02 PST 2016


Author: rnk
Date: Fri Feb 26 13:51:02 2016
New Revision: 262056

URL: http://llvm.org/viewvc/llvm-project?rev=262056&view=rev
Log:
[dllexport] Sort out emission order of delayed exported classes

Relands r260194 with a fix. If we have a template that transitions from
an extern template to an explicitly instantiated dllexport template, we
would add that class to the delayed exported class list without flushing
it.

For explicit instantiations, we can just flush the list of delayed
classes immediately. We don't have to worry about the bug fixed in
r260194 in this case because explicit instantiations can only occur at
file and namespace scope.

Fixes PR26490.

Added:
    cfe/trunk/test/CodeGenCXX/dllexport-pr26549.cpp
Modified:
    cfe/trunk/include/clang/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaDeclCXX.cpp
    cfe/trunk/lib/Sema/SemaTemplate.cpp
    cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
    cfe/trunk/test/CodeGenCXX/dllexport.cpp

Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=262056&r1=262055&r2=262056&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Fri Feb 26 13:51:02 2016
@@ -5295,11 +5295,18 @@ public:
                             ArrayRef<CXXCtorInitializer*> MemInits,
                             bool AnyErrors);
 
+  /// \brief Check class-level dllimport/dllexport attribute. The caller must
+  /// ensure that referenceDLLExportedClassMethods is called some point later
+  /// when all outer classes of Class are complete.
   void checkClassLevelDLLAttribute(CXXRecordDecl *Class);
+
+  void referenceDLLExportedClassMethods();
+
   void propagateDLLAttrToBaseClassTemplate(
       CXXRecordDecl *Class, Attr *ClassAttr,
       ClassTemplateSpecializationDecl *BaseTemplateSpec,
       SourceLocation BaseLoc);
+
   void CheckCompletedCXXClass(CXXRecordDecl *Record);
   void ActOnFinishCXXMemberSpecification(Scope* S, SourceLocation RLoc,
                                          Decl *TagDecl,

Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=262056&r1=262055&r2=262056&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Fri Feb 26 13:51:02 2016
@@ -9533,6 +9533,10 @@ void Sema::ActOnFinishCXXNonNestedClass(
   if (RD && Context.getTargetInfo().getCXXABI().isMicrosoft())
     getDefaultArgExprsForConstructors(*this, RD);
 
+  referenceDLLExportedClassMethods();
+}
+
+void Sema::referenceDLLExportedClassMethods() {
   if (!DelayedDllExportClasses.empty()) {
     // Calling ReferenceDllExportedMethods might cause the current function to
     // be called again, so use a local copy of DelayedDllExportClasses.

Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=262056&r1=262055&r2=262056&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Fri Feb 26 13:51:02 2016
@@ -7458,7 +7458,13 @@ 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);
+        referenceDLLExportedClassMethods();
 
         // Propagate attribute to base class templates.
         for (auto &B : Def->bases()) {

Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp?rev=262056&r1=262055&r2=262056&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp Fri Feb 26 13:51:02 2016
@@ -1949,6 +1949,13 @@ Sema::InstantiateClass(SourceLocation Po
   bool MergeWithParentScope = !Instantiation->isDefinedOutsideFunctionOrMethod();
   LocalInstantiationScope Scope(*this, MergeWithParentScope);
 
+  // All dllexported classes created during instantiation should be fully
+  // emitted after instantiation completes. We may not be ready to emit any
+  // delayed classes already on the stack, so save them away and put them back
+  // later.
+  decltype(DelayedDllExportClasses) ExportedClasses;
+  std::swap(ExportedClasses, DelayedDllExportClasses);
+
   // Pull attributes from the pattern onto the instantiation.
   InstantiateAttrs(TemplateArgs, Pattern, Instantiation);
 
@@ -2034,6 +2041,9 @@ Sema::InstantiateClass(SourceLocation Po
   // default arg exprs for default constructors if necessary now.
   ActOnFinishCXXNonNestedClass(Instantiation);
 
+  // Put back the delayed exported classes that we moved out of the way.
+  std::swap(ExportedClasses, DelayedDllExportClasses);
+
   // Instantiate late parsed attributes, and attach them to their decls.
   // See Sema::InstantiateAttrs
   for (LateInstantiatedAttrVec::iterator I = LateAttrs.begin(),

Added: cfe/trunk/test/CodeGenCXX/dllexport-pr26549.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/dllexport-pr26549.cpp?rev=262056&view=auto
==============================================================================
--- cfe/trunk/test/CodeGenCXX/dllexport-pr26549.cpp (added)
+++ cfe/trunk/test/CodeGenCXX/dllexport-pr26549.cpp Fri Feb 26 13:51:02 2016
@@ -0,0 +1,9 @@
+// RUN: %clang_cc1 %s -fms-extensions -triple x86_64-windows-msvc -emit-llvm -o - | FileCheck %s
+
+template <typename> struct MessageT { };
+extern template struct MessageT<int>;
+
+// CHECK: define weak_odr dllexport {{.*}} %struct.MessageT* @"\01??4?$MessageT at H@@QEAAAEAU0 at AEBU0@@Z"(
+template struct __declspec(dllexport) MessageT<int>;
+// Previously we crashed when this dllexport was the last thing in the file.
+// DO NOT ADD MORE TESTS AFTER THIS LINE!

Modified: cfe/trunk/test/CodeGenCXX/dllexport.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/dllexport.cpp?rev=262056&r1=262055&r2=262056&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/dllexport.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/dllexport.cpp Fri Feb 26 13:51:02 2016
@@ -777,6 +777,17 @@ struct __declspec(dllexport) Baz {
 // M32-DAG: define weak_odr dllexport x86_thiscallcc dereferenceable(1) %"struct.InClassInits::Baz"* @"\01??4Baz at InClassInits@@QAEAAU01 at ABU01@@Z"
 }
 
+// We had an issue where instantiating A would force emission of B's delayed
+// exported methods.
+namespace pr26490 {
+template <typename T> struct A { };
+struct __declspec(dllexport) B {
+  B(int = 0) {}
+  A<int> m_fn1() {}
+};
+// M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01??_FB at pr26490@@QAEXXZ"
+}
+
 
 //===----------------------------------------------------------------------===//
 // Classes with template base classes




More information about the cfe-commits mailing list