Author: Chinmay Deshpande Date: 2026-03-05T10:57:11-08:00 New Revision: 6811a83c81500ee373adfc0d9978ff9625a4cf1c
URL: https://github.com/llvm/llvm-project/commit/6811a83c81500ee373adfc0d9978ff9625a4cf1c DIFF: https://github.com/llvm/llvm-project/commit/6811a83c81500ee373adfc0d9978ff9625a4cf1c.diff LOG: [Clang] Ensure child classes export inherited constructors from base classes (#182706) Inherited constructors in `dllexport` classes are now exported for ABI-compatible cases, matching MSVC behavior. Constructors with variadic arguments or callee-cleanup parameters are not yet supported and produce a warning. This aims to partially resolve https://github.com/llvm/llvm-project/issues/162640. Assisted by : Cursor // Claude Opus 4.6 Added: clang/test/CodeGenCXX/dllexport-inherited-ctor.cpp Modified: clang/docs/ReleaseNotes.rst clang/include/clang/Basic/DiagnosticSemaKinds.td clang/lib/AST/ASTContext.cpp clang/lib/CodeGen/ModuleBuilder.cpp clang/lib/Sema/SemaDeclCXX.cpp clang/test/SemaCXX/dllexport.cpp Removed: ################################################################################ diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 18ce0f919daa9..82b03341138de 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -335,6 +335,9 @@ Bug Fixes to C++ Support when used inside decltype in the return type. (#GH180460) - Fixed a crash when evaluating uninitialized GCC vector/ext_vector_type vectors in ``constexpr``. (#GH180044) - Fixed a crash on ``typeid`` of incomplete local types during template instantiation. (#GH63242), (#GH176397) +- Inherited constructors in ``dllexport`` classes are now exported for ABI-compatible cases, matching + MSVC behavior. Constructors with variadic arguments or callee-cleanup parameters are not yet supported + and produce a warning. (#GH162640) - Fix initialization of GRO when GRO-return type mismatches, as part of CWG2563. (#GH98744) diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 58e15a89c2373..2f8a37e506136 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -3935,6 +3935,11 @@ def warn_dllexport_on_decl_ignored : Warning< InGroup<IgnoredAttributes>; def note_dllexport_on_decl : Note< "'dllexport' attribute on the declaration is ignored">; +def warn_dllexport_inherited_ctor_unsupported : Warning< + "exporting inherited constructor is not yet supported; " + "'dllexport' ignored on inherited constructor with " + "%select{variadic arguments|callee-cleanup parameters}0">, + InGroup<IgnoredAttributes>; def warn_attribute_exclude_from_explicit_instantiation_local_class : Warning< "%0 attribute ignored on local class%select{| member}1">, InGroup<IgnoredAttributes>; diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 5fbdff280073f..d9e9ae062e8d7 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -13013,11 +13013,20 @@ static GVALinkage basicGVALinkageForFunction(const ASTContext &Context, if (Context.getTargetInfo().getCXXABI().isMicrosoft() && isa<CXXConstructorDecl>(FD) && - cast<CXXConstructorDecl>(FD)->isInheritingConstructor()) - // Our approach to inheriting constructors is fundamentally diff erent from - // that used by the MS ABI, so keep our inheriting constructor thunks - // internal rather than trying to pick an unambiguous mangling for them. + cast<CXXConstructorDecl>(FD)->isInheritingConstructor() && + !FD->hasAttr<DLLExportAttr>()) { + // Both Clang and MSVC implement inherited constructors as forwarding + // thunks that delegate to the base constructor. Keep non-dllexport + // inheriting constructor thunks internal since they are not needed + // outside the translation unit. + // + // dllexport inherited constructors are exempted so they are externally + // visible, matching MSVC's export behavior. Inherited constructors + // whose parameters prevent ABI-compatible forwarding (e.g. callee- + // cleanup types) are excluded from export in Sema to avoid silent + // runtime mismatches. return GVA_Internal; + } return GVA_DiscardableODR; } diff --git a/clang/lib/CodeGen/ModuleBuilder.cpp b/clang/lib/CodeGen/ModuleBuilder.cpp index c364d5c31513c..dd6b3c904d03d 100644 --- a/clang/lib/CodeGen/ModuleBuilder.cpp +++ b/clang/lib/CodeGen/ModuleBuilder.cpp @@ -260,6 +260,21 @@ namespace { } } } + + // Emit dllexport inherited constructors. These are synthesized during + // Sema (in checkClassLevelDLLAttribute) but have no written definition, + // so they must be emitted now while visiting the class definition. + if (auto *RD = dyn_cast<CXXRecordDecl>(D); + RD && RD->hasAttr<DLLExportAttr>()) { + for (Decl *Member : RD->decls()) { + if (auto *CD = dyn_cast<CXXConstructorDecl>(Member)) { + if (CD->getInheritedConstructor() && CD->hasAttr<DLLExportAttr>() && + !CD->isDeleted()) + Builder->EmitTopLevelDecl(CD); + } + } + } + // For OpenMP emit declare reduction functions, if required. if (Ctx->getLangOpts().OpenMP) { for (Decl *Member : D->decls()) { diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 5837ecd6b9163..68f27dce84fe3 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -6588,6 +6588,19 @@ void Sema::checkClassLevelDLLAttribute(CXXRecordDecl *Class) { // Force declaration of implicit members so they can inherit the attribute. ForceDeclarationOfImplicitMembers(Class); + // Inherited constructors are created lazily; force their creation now so the + // loop below can propagate the DLL attribute to them. + if (ClassExported) { + SmallVector<ConstructorUsingShadowDecl *, 4> Shadows; + for (Decl *D : Class->decls()) + if (auto *S = dyn_cast<ConstructorUsingShadowDecl>(D)) + Shadows.push_back(S); + for (ConstructorUsingShadowDecl *S : Shadows) + if (auto *BC = dyn_cast<CXXConstructorDecl>(S->getTargetDecl()); + BC && !BC->isDeleted()) + findInheritingConstructor(Class->getLocation(), BC, S); + } + // FIXME: MSVC's docs say all bases must be exportable, but this doesn't // seem to be true in practice? @@ -6604,13 +6617,52 @@ void Sema::checkClassLevelDLLAttribute(CXXRecordDecl *Class) { if (MD->isDeleted()) continue; + // Don't export inherited constructors whose parameters prevent ABI- + // compatible forwarding. When canEmitDelegateCallArgs (in CodeGen) + // returns false, Clang inlines the constructor body instead of + // emitting a forwarding thunk, producing code that is not ABI- + // compatible with MSVC. Suppress the export and warn so the user + // gets a linker error rather than a silent runtime mismatch. + if (ClassExported) { + if (auto *CD = dyn_cast<CXXConstructorDecl>(MD)) { + if (CD->getInheritedConstructor()) { + if (CD->isVariadic()) { + Diag(CD->getLocation(), + diag::warn_dllexport_inherited_ctor_unsupported) + << /*variadic=*/0; + continue; + } + if (Context.getTargetInfo() + .getCXXABI() + .areArgsDestroyedLeftToRightInCallee()) { + bool HasCalleeCleanupParam = false; + for (const auto *P : CD->parameters()) + if (P->needsDestruction(Context)) { + HasCalleeCleanupParam = true; + break; + } + if (HasCalleeCleanupParam) { + Diag(CD->getLocation(), + diag::warn_dllexport_inherited_ctor_unsupported) + << /*callee-cleanup=*/1; + continue; + } + } + } + } + } + if (MD->isInlined()) { // MinGW does not import or export inline methods. But do it for - // template instantiations. + // template instantiations and inherited constructors (which are + // marked inline but must be exported to match MSVC behavior). if (!Context.getTargetInfo().shouldDLLImportComdatSymbols() && TSK != TSK_ExplicitInstantiationDeclaration && - TSK != TSK_ExplicitInstantiationDefinition) - continue; + TSK != TSK_ExplicitInstantiationDefinition) { + if (auto *CD = dyn_cast<CXXConstructorDecl>(MD); + !CD || !CD->getInheritedConstructor()) + continue; + } // MSVC versions before 2015 don't export the move assignment operators // and move constructor, so don't attempt to import/export them if @@ -6643,8 +6695,13 @@ void Sema::checkClassLevelDLLAttribute(CXXRecordDecl *Class) { // Do not export/import inline function when -fno-dllexport-inlines is // passed. But add attribute for later local static var check. + // Inherited constructors are marked inline but must still be exported + // to match MSVC behavior, so exclude them from this override. + bool IsInheritedCtor = false; + if (auto *CD = dyn_cast_or_null<CXXConstructorDecl>(MD)) + IsInheritedCtor = (bool)CD->getInheritedConstructor(); if (!getLangOpts().DllExportInlines && MD && MD->isInlined() && - TSK != TSK_ExplicitInstantiationDeclaration && + !IsInheritedCtor && TSK != TSK_ExplicitInstantiationDeclaration && TSK != TSK_ExplicitInstantiationDefinition) { if (ClassExported) { NewAttr = ::new (getASTContext()) diff --git a/clang/test/CodeGenCXX/dllexport-inherited-ctor.cpp b/clang/test/CodeGenCXX/dllexport-inherited-ctor.cpp new file mode 100644 index 0000000000000..cad081fd7f999 --- /dev/null +++ b/clang/test/CodeGenCXX/dllexport-inherited-ctor.cpp @@ -0,0 +1,243 @@ +// RUN: %clang_cc1 -no-enable-noundef-analysis -triple x86_64-windows-msvc -emit-llvm -std=c++17 -fms-extensions -O0 -o - %s | FileCheck --check-prefix=MSVC %s +// RUN: %clang_cc1 -no-enable-noundef-analysis -triple i686-windows-msvc -emit-llvm -std=c++17 -fms-extensions -O0 -o - %s | FileCheck --check-prefix=M32 %s +// RUN: %clang_cc1 -no-enable-noundef-analysis -triple x86_64-windows-gnu -emit-llvm -std=c++17 -fms-extensions -O0 -o - %s | FileCheck --check-prefix=GNU %s +// RUN: %clang_cc1 -no-enable-noundef-analysis -triple x86_64-windows-msvc -emit-llvm -std=c++17 -fms-extensions -fno-dllexport-inlines -O0 -o - %s | FileCheck --check-prefix=NOINLINE %s + +// Test that inherited constructors via 'using Base::Base' in a dllexport +// class are properly exported (https://github.com/llvm/llvm-project/issues/162640). + +//===----------------------------------------------------------------------===// +// Basic: both base and child exported, simple parameter types. +//===----------------------------------------------------------------------===// + +struct __declspec(dllexport) Base { + Base(int); + Base(double); +}; + +struct __declspec(dllexport) Child : public Base { + using Base::Base; +}; + +// The inherited constructors Child(int) and Child(double) should be exported. +// Verify the thunk bodies delegate to the base constructor with the correct +// arguments, ensuring ABI compatibility with MSVC-compiled callers. + +// MSVC-DAG: define weak_odr dso_local dllexport {{.*}} @"??0Child@@QEAA@H@Z"(ptr {{.*}} %this, i32 %0) +// MSVC-DAG: call {{.*}} @"??0Base@@QEAA@H@Z"(ptr {{.*}} %this{{.*}}, i32 +// MSVC-DAG: define weak_odr dso_local dllexport {{.*}} @"??0Child@@QEAA@N@Z"(ptr {{.*}} %this, double %0) +// MSVC-DAG: call {{.*}} @"??0Base@@QEAA@N@Z"(ptr {{.*}} %this{{.*}}, double + +// M32-DAG: define weak_odr dso_local dllexport {{.*}} @"??0Child@@QAE@H@Z" +// M32-DAG: define weak_odr dso_local dllexport {{.*}} @"??0Child@@QAE@N@Z" + +// GNU-DAG: define {{.*}}dso_local dllexport {{.*}} @_ZN5ChildCI14BaseEi( +// GNU-DAG: define {{.*}}dso_local dllexport {{.*}} @_ZN5ChildCI14BaseEd( + +//===----------------------------------------------------------------------===// +// Non-exported class should not export inherited ctors. +//===----------------------------------------------------------------------===// + +struct NonExportedBase { + NonExportedBase(int); +}; + +struct NonExportedChild : public NonExportedBase { + using NonExportedBase::NonExportedBase; +}; + +// MSVC-NOT: dllexport{{.*}}NonExportedChild +// M32-NOT: dllexport{{.*}}NonExportedChild +// GNU-NOT: dllexport{{.*}}NonExportedChild + +//===----------------------------------------------------------------------===// +// Only the derived class is dllexport, base is not. +//===----------------------------------------------------------------------===// + +struct PlainBase { + PlainBase(int); + PlainBase(float); +}; + +struct __declspec(dllexport) ExportedChild : public PlainBase { + using PlainBase::PlainBase; +}; + +// MSVC-DAG: define weak_odr dso_local dllexport {{.*}} @"??0ExportedChild@@QEAA@H@Z" +// MSVC-DAG: define weak_odr dso_local dllexport {{.*}} @"??0ExportedChild@@QEAA@M@Z" + +// M32-DAG: define weak_odr dso_local dllexport {{.*}} @"??0ExportedChild@@QAE@H@Z" +// M32-DAG: define weak_odr dso_local dllexport {{.*}} @"??0ExportedChild@@QAE@M@Z" + +// GNU-DAG: define {{.*}}dso_local dllexport {{.*}} @_ZN13ExportedChildCI19PlainBaseEi( +// GNU-DAG: define {{.*}}dso_local dllexport {{.*}} @_ZN13ExportedChildCI19PlainBaseEf( + +//===----------------------------------------------------------------------===// +// Multi-level inheritance: A -> B -> C with using at each level. +//===----------------------------------------------------------------------===// + +struct MLBase { + MLBase(int); +}; + +struct MLMiddle : MLBase { + using MLBase::MLBase; +}; + +struct __declspec(dllexport) MLChild : MLMiddle { + using MLMiddle::MLMiddle; +}; + +// MSVC-DAG: define weak_odr dso_local dllexport {{.*}} @"??0MLChild@@QEAA@H@Z" +// M32-DAG: define weak_odr dso_local dllexport {{.*}} @"??0MLChild@@QAE@H@Z" +// GNU-DAG: define {{.*}}dso_local dllexport {{.*}} @_ZN7MLChildCI16MLBaseEi( + +//===----------------------------------------------------------------------===// +// Class template specialization with inherited constructors. +//===----------------------------------------------------------------------===// + +template <typename T> +struct TplBase { + TplBase(T); +}; + +struct __declspec(dllexport) TplChild : TplBase<int> { + using TplBase<int>::TplBase; +}; + +// MSVC-DAG: define weak_odr dso_local dllexport {{.*}} @"??0TplChild@@QEAA@H@Z" +// M32-DAG: define weak_odr dso_local dllexport {{.*}} @"??0TplChild@@QAE@H@Z" +// GNU-DAG: define {{.*}}dso_local dllexport {{.*}} @_ZN8TplChildCI17TplBaseIiEEi( + +//===----------------------------------------------------------------------===// +// Default arguments: thunk takes the full parameter list. +//===----------------------------------------------------------------------===// + +struct DefArgBase { + DefArgBase(int a, int b = 10, int c = 20); +}; + +struct __declspec(dllexport) DefArgChild : DefArgBase { + using DefArgBase::DefArgBase; +}; + +// MSVC-DAG: define weak_odr dso_local dllexport {{.*}} @"??0DefArgChild@@QEAA@HHH@Z"(ptr {{.*}} %this, i32 %0, i32 %1, i32 %2) +// MSVC-DAG: call {{.*}} @"??0DefArgBase@@QEAA@HHH@Z"(ptr {{.*}}, i32 {{.*}}, i32 {{.*}}, i32 + +// M32-DAG: define weak_odr dso_local dllexport {{.*}} @"??0DefArgChild@@QAE@HHH@Z" +// M32-DAG: call {{.*}} @"??0DefArgBase@@QAE@HHH@Z"(ptr {{.*}}, i32 {{.*}}, i32 {{.*}}, i32 + +// GNU-DAG: define {{.*}}dso_local dllexport {{.*}} @_ZN11DefArgChildCI110DefArgBaseEiii( +// GNU-DAG: call {{.*}} @_ZN10DefArgBaseC2Eiii(ptr {{.*}}, i32 {{.*}}, i32 {{.*}}, i32 + +//===----------------------------------------------------------------------===// +// Default arguments with mixed types. +//===----------------------------------------------------------------------===// + +struct MixedDefBase { + MixedDefBase(int a, double b = 3.14); +}; + +struct __declspec(dllexport) MixedDefChild : MixedDefBase { + using MixedDefBase::MixedDefBase; +}; + +// MSVC-DAG: define weak_odr dso_local dllexport {{.*}} @"??0MixedDefChild@@QEAA@HN@Z"(ptr {{.*}} %this, i32 %0, double %1) +// MSVC-DAG: call {{.*}} @"??0MixedDefBase@@QEAA@HN@Z"(ptr {{.*}}, i32 {{.*}}, double + +// M32-DAG: define weak_odr dso_local dllexport {{.*}} @"??0MixedDefChild@@QAE@HN@Z" +// M32-DAG: call {{.*}} @"??0MixedDefBase@@QAE@HN@Z"(ptr {{.*}}, i32 {{.*}}, double + +// GNU-DAG: define {{.*}}dso_local dllexport {{.*}} @_ZN13MixedDefChildCI112MixedDefBaseEid( +// GNU-DAG: call {{.*}} @_ZN12MixedDefBaseC2Eid(ptr {{.*}}, i32 {{.*}}, double + +//===----------------------------------------------------------------------===// +// All parameters have defaults. The inherited constructor takes the full +// parameter list. The implicit default constructor also gets exported, with +// default argument values baked in. +//===----------------------------------------------------------------------===// + +struct AllDefBase { + AllDefBase(int a = 1, int b = 2); +}; + +struct __declspec(dllexport) AllDefChild : AllDefBase { + using AllDefBase::AllDefBase; +}; + +// MSVC-DAG: define weak_odr dso_local dllexport {{.*}} @"??0AllDefChild@@QEAA@HH@Z"(ptr {{.*}} %this, i32 %0, i32 %1) +// MSVC-DAG: define weak_odr dso_local dllexport {{.*}} @"??0AllDefChild@@QEAA@XZ"(ptr {{.*}} %this) +// MSVC-DAG: call {{.*}} @"??0AllDefBase@@QEAA@HH@Z"(ptr {{.*}}, i32 1, i32 2) + +// M32-DAG: define weak_odr dso_local dllexport {{.*}} @"??0AllDefChild@@QAE@HH@Z" +// M32-DAG: call {{.*}} @"??0AllDefBase@@QAE@HH@Z"(ptr {{.*}}, i32 % +// M32-DAG: define weak_odr dso_local dllexport {{.*}} @"??0AllDefChild@@QAE@XZ" +// M32-DAG: call {{.*}} @"??0AllDefBase@@QAE@HH@Z"(ptr {{.*}}, i32 1, i32 2) + +// GNU does not emit an implicit default constructor unless it is used. +// Only the inherited constructor with the full parameter list is exported. +// GNU-DAG: define {{.*}}dso_local dllexport {{.*}} @_ZN11AllDefChildCI110AllDefBaseEii( +// GNU-DAG: call {{.*}} @_ZN10AllDefBaseC2Eii(ptr {{.*}}, i32 %{{.*}}, i32 % + +//===----------------------------------------------------------------------===// +// Variadic constructor: inherited variadic constructors cannot be exported +// because delegate forwarding is not supported for variadic arguments. +//===----------------------------------------------------------------------===// + +struct VariadicBase { + VariadicBase(int, ...); +}; + +struct __declspec(dllexport) VariadicChild : VariadicBase { + using VariadicBase::VariadicBase; +}; + +// The variadic inherited constructor (int, ...) should NOT be exported. +// Match specifically to avoid matching implicitly exported copy/move ctors. +// MSVC-NOT: dllexport{{.*}}??0VariadicChild@@QEAA@H +// M32-NOT: dllexport{{.*}}??0VariadicChild@@QAE@H +// GNU-NOT: dllexport{{.*}}VariadicChildCI1{{.*}}Eiz + +//===----------------------------------------------------------------------===// +// Callee-cleanup parameter: struct with non-trivial destructor passed by value. +// canEmitDelegateCallArgs returns false for this case, so the inherited +// constructor must NOT be exported to avoid ABI incompatibility with MSVC. +//===----------------------------------------------------------------------===// + +struct NontrivialDtor { + int x; + ~NontrivialDtor(); +}; + +struct CalleeCleanupBase { + CalleeCleanupBase(NontrivialDtor); +}; + +struct __declspec(dllexport) CalleeCleanupChild : CalleeCleanupBase { + using CalleeCleanupBase::CalleeCleanupBase; +}; + +// The inherited constructor should NOT be exported on MSVC targets because the +// parameter requires callee-cleanup, making the thunk ABI-incompatible. +// On GNU targets the callee-cleanup issue does not apply, so export is fine. +// MSVC-NOT: dllexport{{.*}}CalleeCleanupChild{{.*}}NontrivialDtor +// M32-NOT: dllexport{{.*}}CalleeCleanupChild{{.*}}NontrivialDtor +// GNU-DAG: define {{.*}}dso_local dllexport {{.*}}CalleeCleanupChild{{.*}}NontrivialDtor + +//===----------------------------------------------------------------------===// +// -fno-dllexport-inlines should still export inherited constructors. +// Inherited constructors are marked inline internally but must be exported. +//===----------------------------------------------------------------------===// + +// NOINLINE-DAG: define weak_odr dso_local dllexport {{.*}} @"??0Child@@QEAA@H@Z" +// NOINLINE-DAG: define weak_odr dso_local dllexport {{.*}} @"??0Child@@QEAA@N@Z" +// NOINLINE-DAG: define weak_odr dso_local dllexport {{.*}} @"??0ExportedChild@@QEAA@H@Z" +// NOINLINE-DAG: define weak_odr dso_local dllexport {{.*}} @"??0ExportedChild@@QEAA@M@Z" +// NOINLINE-DAG: define weak_odr dso_local dllexport {{.*}} @"??0MLChild@@QEAA@H@Z" +// NOINLINE-DAG: define weak_odr dso_local dllexport {{.*}} @"??0TplChild@@QEAA@H@Z" +// NOINLINE-DAG: define weak_odr dso_local dllexport {{.*}} @"??0DefArgChild@@QEAA@HHH@Z" +// NOINLINE-DAG: define weak_odr dso_local dllexport {{.*}} @"??0MixedDefChild@@QEAA@HN@Z" +// NOINLINE-DAG: define weak_odr dso_local dllexport {{.*}} @"??0AllDefChild@@QEAA@HH@Z" +// The implicit default ctor is a regular inline method, NOT an inherited +// constructor, so -fno-dllexport-inlines correctly suppresses it. +// NOINLINE-NOT: define {{.*}}dllexport{{.*}} @"??0AllDefChild@@QEAA@XZ" diff --git a/clang/test/SemaCXX/dllexport.cpp b/clang/test/SemaCXX/dllexport.cpp index f5ff99da38091..d625b15557762 100644 --- a/clang/test/SemaCXX/dllexport.cpp +++ b/clang/test/SemaCXX/dllexport.cpp @@ -1131,3 +1131,28 @@ template<typename T> template<typename U> __declspec(dllexport) constexpr int CT //===----------------------------------------------------------------------===// // The MS ABI doesn't provide a stable mangling for lambdas, so they can't be imported or exported. auto Lambda = []() __declspec(dllexport) -> bool { return true; }; // non-gnu-error {{lambda cannot be declared 'dllexport'}} + +//===----------------------------------------------------------------------===// +// Inherited constructors: unsupported export warnings +//===----------------------------------------------------------------------===// + +struct VariadicBase { + VariadicBase(int, ...); +}; + +struct __declspec(dllexport) VariadicChild : VariadicBase { + using VariadicBase::VariadicBase; // expected-warning{{exporting inherited constructor is not yet supported; 'dllexport' ignored on inherited constructor with variadic arguments}} +}; + +struct NontrivialDtorParam { + int x; + ~NontrivialDtorParam(); +}; + +struct CalleeCleanupBase { + CalleeCleanupBase(NontrivialDtorParam); +}; + +struct __declspec(dllexport) CalleeCleanupChild : CalleeCleanupBase { + using CalleeCleanupBase::CalleeCleanupBase; // ms-warning{{exporting inherited constructor is not yet supported; 'dllexport' ignored on inherited constructor with callee-cleanup parameters}} +}; _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
