r367520 - Delay emitting dllexport explicitly defaulted members until the class is fully parsed (PR40006)

Hans Wennborg via cfe-commits cfe-commits at lists.llvm.org
Mon Aug 5 00:26:52 PDT 2019


Merged to release_90 in r367804.

On Thu, Aug 1, 2019 at 10:00 AM Hans Wennborg via cfe-commits
<cfe-commits at lists.llvm.org> wrote:
>
> Author: hans
> Date: Thu Aug  1 01:01:09 2019
> New Revision: 367520
>
> URL: http://llvm.org/viewvc/llvm-project?rev=367520&view=rev
> Log:
> 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
>
> Modified:
>     cfe/trunk/include/clang/Sema/Sema.h
>     cfe/trunk/lib/Sema/Sema.cpp
>     cfe/trunk/lib/Sema/SemaDeclCXX.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=367520&r1=367519&r2=367520&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/Sema/Sema.h (original)
> +++ cfe/trunk/include/clang/Sema/Sema.h Thu Aug  1 01:01:09 2019
> @@ -11136,6 +11136,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 {
>
> Modified: cfe/trunk/lib/Sema/Sema.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.cpp?rev=367520&r1=367519&r2=367520&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Sema/Sema.cpp (original)
> +++ cfe/trunk/lib/Sema/Sema.cpp Thu Aug  1 01:01:09 2019
> @@ -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(
>
> Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=367520&r1=367519&r2=367520&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Thu Aug  1 01:01:09 2019
> @@ -6283,8 +6283,8 @@ void Sema::CheckCompletedCXXClass(CXXRec
>          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);
>        }
>      }
>    };
> @@ -11537,6 +11537,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() {
>
> Modified: cfe/trunk/test/CodeGenCXX/dllexport.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/dllexport.cpp?rev=367520&r1=367519&r2=367520&view=diff
> ==============================================================================
> --- cfe/trunk/test/CodeGenCXX/dllexport.cpp (original)
> +++ cfe/trunk/test/CodeGenCXX/dllexport.cpp Thu Aug  1 01:01:09 2019
> @@ -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 at InClassInits@@QAEAAU01 at 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 at InClassInits@@QAE at XZ"
> +
>  }
>
>  // We had an issue where instantiating A would force emission of B's delayed
>
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at lists.llvm.org
> https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


More information about the cfe-commits mailing list