diff options
| author | Reid Kleckner <rnk@google.com> | 2016-02-26 19:51:02 +0000 |
|---|---|---|
| committer | Reid Kleckner <rnk@google.com> | 2016-02-26 19:51:02 +0000 |
| commit | 5b64034a435d2bd25813918bdb1f7368e2af77b7 (patch) | |
| tree | 8819e47a345ff8996b0462c9f16a1dc6d9c92dd3 /clang/lib/Sema | |
| parent | 5cc45e0122f014fd90dd77ac2d1d379952016020 (diff) | |
| download | bcm5719-llvm-5b64034a435d2bd25813918bdb1f7368e2af77b7.tar.gz bcm5719-llvm-5b64034a435d2bd25813918bdb1f7368e2af77b7.zip | |
[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.
llvm-svn: 262056
Diffstat (limited to 'clang/lib/Sema')
| -rw-r--r-- | clang/lib/Sema/SemaDeclCXX.cpp | 4 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaTemplate.cpp | 6 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaTemplateInstantiate.cpp | 10 |
3 files changed, 20 insertions, 0 deletions
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index c160f444ca5..38901203416 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -9533,6 +9533,10 @@ void Sema::ActOnFinishCXXNonNestedClass(Decl *D) { 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. diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 38df76ee315..3b85b98abdd 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -7458,7 +7458,13 @@ Sema::ActOnExplicitInstantiation(Scope *S, 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()) { diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp index 56858bcc7e6..db3f47fd916 100644 --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -1949,6 +1949,13 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation, 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 PointOfInstantiation, // 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(), |

