summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHans Wennborg <hans@hanshq.net>2019-08-05 07:27:39 +0000
committerHans Wennborg <hans@hanshq.net>2019-08-05 07:27:39 +0000
commite333eb0d63721ee2d0f8cb8c24c5434a87d72f1c (patch)
treede80995aaa8eb62097c1418ea38d0ec3ab47588f
parenta57867942a11e8d6680d639d1535fed897aafa7c (diff)
Merging r367520:
------------------------------------------------------------------------ r367520 | hans | 2019-08-01 10:01:09 +0200 (Thu, 01 Aug 2019) | 15 lines Delay emitting dllexport explicitly defaulted members until the class is fully parsed (PR40006) This is similar to r245139, but that only addressed dllexported classes. It was still possible to run into the same problem with dllexported members in an otherwise normal class (see bug). This uses the same strategy to fix: delay defining the method until the whole class has been parsed. (The easiest way to see the ordering problem is in Parser::ParseCXXMemberSpecification(): it calls ParseLexedMemberInitializers() *after* ActOnFinishCXXMemberDecls(), which was trying to define the dllexport method. Now we delay it to ActOnFinishCXXNonNestedClass() which is called after both of those.) Differential revision: https://reviews.llvm.org/D65511 ------------------------------------------------------------------------ git-svn-id: https://llvm.org/svn/llvm-project/cfe/branches/release_90@367804 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang/Sema/Sema.h1
-rw-r--r--lib/Sema/Sema.cpp1
-rw-r--r--lib/Sema/SemaDeclCXX.cpp13
-rw-r--r--test/CodeGenCXX/dllexport.cpp9
4 files changed, 22 insertions, 2 deletions
diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h
index af762f74d7..e6c63fd9c0 100644
--- a/include/clang/Sema/Sema.h
+++ b/include/clang/Sema/Sema.h
@@ -11165,6 +11165,7 @@ public:
// Emitting members of dllexported classes is delayed until the class
// (including field initializers) is fully parsed.
SmallVector<CXXRecordDecl*, 4> DelayedDllExportClasses;
+ SmallVector<CXXMethodDecl*, 4> DelayedDllExportMemberFunctions;
private:
class SavePendingParsedClassStateRAII {
diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp
index 11fed28b52..485d39e2c9 100644
--- a/lib/Sema/Sema.cpp
+++ b/lib/Sema/Sema.cpp
@@ -961,6 +961,7 @@ void Sema::ActOnEndOfTranslationUnit() {
// All dllexport classes should have been processed already.
assert(DelayedDllExportClasses.empty());
+ assert(DelayedDllExportMemberFunctions.empty());
// Remove file scoped decls that turned out to be used.
UnusedFileScopedDecls.erase(
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index 9a6385f283..3d4c7fc3e0 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -6165,8 +6165,8 @@ void Sema::CheckCompletedCXXClass(CXXRecordDecl *Record) {
M->dropAttr<DLLExportAttr>();
if (M->hasAttr<DLLExportAttr>()) {
- DefineImplicitSpecialMember(*this, M, M->getLocation());
- ActOnFinishInlineFunctionDef(M);
+ // Define after any fields with in-class initializers have been parsed.
+ DelayedDllExportMemberFunctions.push_back(M);
}
}
};
@@ -11419,6 +11419,15 @@ void Sema::ActOnFinishCXXMemberDecls() {
void Sema::ActOnFinishCXXNonNestedClass(Decl *D) {
referenceDLLExportedClassMethods();
+
+ if (!DelayedDllExportMemberFunctions.empty()) {
+ SmallVector<CXXMethodDecl*, 4> WorkList;
+ std::swap(DelayedDllExportMemberFunctions, WorkList);
+ for (CXXMethodDecl *M : WorkList) {
+ DefineImplicitSpecialMember(*this, M, M->getLocation());
+ ActOnFinishInlineFunctionDef(M);
+ }
+ }
}
void Sema::referenceDLLExportedClassMethods() {
diff --git a/test/CodeGenCXX/dllexport.cpp b/test/CodeGenCXX/dllexport.cpp
index 16cfb84658..5d4523f2ea 100644
--- a/test/CodeGenCXX/dllexport.cpp
+++ b/test/CodeGenCXX/dllexport.cpp
@@ -851,6 +851,15 @@ struct __declspec(dllexport) Baz {
// Baz's operator=, causing instantiation of Foo<int> after which
// ActOnFinishCXXNonNestedClass is called, and we would bite our own tail.
// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc dereferenceable(1) %"struct.InClassInits::Baz"* @"??4Baz@InClassInits@@QAEAAU01@ABU01@@Z"
+
+// Trying to define the explicitly defaulted ctor must be delayed until the
+// in-class initializer for x has been processed.
+struct PR40006 {
+ __declspec(dllexport) PR40006() = default;
+ int x = 42;
+};
+// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc %"struct.InClassInits::PR40006"* @"??0PR40006@InClassInits@@QAE@XZ"
+
}
// We had an issue where instantiating A would force emission of B's delayed