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

Reply via email to