[clang] [clang] Don't dllexport inherited constructors with -fno-dllexport-inlines (PR #187684)
Hans Wennborg via cfe-commits
cfe-commits at lists.llvm.org
Fri Mar 20 05:06:48 PDT 2026
https://github.com/zmodem created https://github.com/llvm/llvm-project/pull/187684
The inherited constructors are inline thunks, so like other inline functions they are exempted from ABI compatibility concerns with this flag, and should not be exported.
This is a follow-up to #182706
>From 3f01cc72125cbef52824e4e7e9b2c915dfc4dc77 Mon Sep 17 00:00:00 2001
From: Hans Wennborg <hans at chromium.org>
Date: Fri, 20 Mar 2026 12:35:58 +0100
Subject: [PATCH] [clang] Don't dllexport inherited constructors with
-fno-dllexport-inlines
The inherited constructors are inline thunks, so like other inline
functions they are exempted from ABI compatibility concerns with this
flag, and should not be exported.
This is a follow-up to #182706
---
clang/lib/Sema/SemaDeclCXX.cpp | 11 +++------
.../CodeGenCXX/dllexport-inherited-ctor.cpp | 24 +++++++++----------
.../dllexport-constrained-inherited-ctor.cpp | 1 +
3 files changed, 15 insertions(+), 21 deletions(-)
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 2a24ee42bcb4d..87e07c8ac0d05 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -6590,7 +6590,7 @@ void Sema::checkClassLevelDLLAttribute(CXXRecordDecl *Class) {
// Inherited constructors are created lazily; force their creation now so the
// loop below can propagate the DLL attribute to them.
- if (ClassExported) {
+ if (ClassExported && getLangOpts().DllExportInlines) {
SmallVector<ConstructorUsingShadowDecl *, 4> Shadows;
for (Decl *D : Class->decls())
if (auto *S = dyn_cast<ConstructorUsingShadowDecl>(D))
@@ -6631,7 +6631,7 @@ void Sema::checkClassLevelDLLAttribute(CXXRecordDecl *Class) {
if (MD->isDeleted())
continue;
- if (ClassExported) {
+ if (ClassExported && getLangOpts().DllExportInlines) {
CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(MD);
if (CD && CD->getInheritedConstructor()) {
// Inherited constructors already had their base constructor's
@@ -6724,13 +6724,8 @@ 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() &&
- !IsInheritedCtor && TSK != TSK_ExplicitInstantiationDeclaration &&
+ 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
index 03026f843eda6..9340b5db66e7d 100644
--- a/clang/test/CodeGenCXX/dllexport-inherited-ctor.cpp
+++ b/clang/test/CodeGenCXX/dllexport-inherited-ctor.cpp
@@ -225,21 +225,19 @@ struct __declspec(dllexport) CalleeCleanupChild : CalleeCleanupBase {
// 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.
+// -fno-dllexport-inlines should not export inherited constructors.
+// Inherited constructors are marked inline internally.
//===----------------------------------------------------------------------===//
-// NOINLINE-DAG: define weak_odr dso_local dllexport {{.*}} @"??0Child@@QEAA at H@Z"
-// NOINLINE-DAG: define weak_odr dso_local dllexport {{.*}} @"??0Child@@QEAA at N@Z"
-// NOINLINE-DAG: define weak_odr dso_local dllexport {{.*}} @"??0ExportedChild@@QEAA at H@Z"
-// NOINLINE-DAG: define weak_odr dso_local dllexport {{.*}} @"??0ExportedChild@@QEAA at M@Z"
-// NOINLINE-DAG: define weak_odr dso_local dllexport {{.*}} @"??0MLChild@@QEAA at H@Z"
-// NOINLINE-DAG: define weak_odr dso_local dllexport {{.*}} @"??0TplChild@@QEAA at H@Z"
-// NOINLINE-DAG: define weak_odr dso_local dllexport {{.*}} @"??0DefArgChild@@QEAA at HHH@Z"
-// NOINLINE-DAG: define weak_odr dso_local dllexport {{.*}} @"??0MixedDefChild@@QEAA at HN@Z"
-// NOINLINE-DAG: define weak_odr dso_local dllexport {{.*}} @"??0AllDefChild@@QEAA at 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 weak_odr dso_local dllexport {{.*}} @"??0Child@@QEAA at H@Z"
+// NOINLINE-NOT: define weak_odr dso_local dllexport {{.*}} @"??0Child@@QEAA at N@Z"
+// NOINLINE-NOT: define weak_odr dso_local dllexport {{.*}} @"??0ExportedChild@@QEAA at H@Z"
+// NOINLINE-NOT: define weak_odr dso_local dllexport {{.*}} @"??0ExportedChild@@QEAA at M@Z"
+// NOINLINE-NOT: define weak_odr dso_local dllexport {{.*}} @"??0MLChild@@QEAA at H@Z"
+// NOINLINE-NOT: define weak_odr dso_local dllexport {{.*}} @"??0TplChild@@QEAA at H@Z"
+// NOINLINE-NOT: define weak_odr dso_local dllexport {{.*}} @"??0DefArgChild@@QEAA at HHH@Z"
+// NOINLINE-NOT: define weak_odr dso_local dllexport {{.*}} @"??0MixedDefChild@@QEAA at HN@Z"
+// NOINLINE-NOT: define weak_odr dso_local dllexport {{.*}} @"??0AllDefChild@@QEAA at HH@Z"
// NOINLINE-NOT: define {{.*}}dllexport{{.*}} @"??0AllDefChild@@QEAA at XZ"
//===----------------------------------------------------------------------===//
diff --git a/clang/test/SemaCXX/dllexport-constrained-inherited-ctor.cpp b/clang/test/SemaCXX/dllexport-constrained-inherited-ctor.cpp
index 019f0a17bdf1e..dc37948996ea7 100644
--- a/clang/test/SemaCXX/dllexport-constrained-inherited-ctor.cpp
+++ b/clang/test/SemaCXX/dllexport-constrained-inherited-ctor.cpp
@@ -1,4 +1,5 @@
// RUN: %clang_cc1 -triple x86_64-windows-msvc -fsyntax-only -fms-extensions -verify -std=c++20 %s
+// RUN: %clang_cc1 -triple x86_64-windows-msvc -fsyntax-only -fms-extensions -verify -std=c++20 -fno-dllexport-inlines %s
// RUN: %clang_cc1 -triple x86_64-windows-gnu -fsyntax-only -fms-extensions -verify -std=c++20 %s
// expected-no-diagnostics
More information about the cfe-commits
mailing list