[llvm-branch-commits] [clang] 1943eaf - [clang][Sema] Check exported default constructors in nested classes (#214275)

Tobias Hieta via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Sat Sep 5 00:12:25 PDT 2026


Author: vangthao95
Date: 2026-09-05T09:11:54+02:00
New Revision: 1943eaf4faa33a5eace0900f5aa1e6b92ef80624

URL: https://github.com/llvm/llvm-project/commit/1943eaf4faa33a5eace0900f5aa1e6b92ef80624
DIFF: https://github.com/llvm/llvm-project/commit/1943eaf4faa33a5eace0900f5aa1e6b92ef80624.diff

LOG: [clang][Sema] Check exported default constructors in nested classes (#214275)

Teach Clang to check exported default constructors declared in nested
classes. This prepares Microsoft ABI constructor closures for
non-dependent nested classes before CodeGen.

This fixes a failure seen when compiling PyTorch on Windows. An exported
nested
class with defaults for every constructor parameter caused Clang to emit
its
constructor closure without cached default arguments and assert in
MicrosoftCXXABI.cpp.

Assisted by: GPT-5.6 Sol

(cherry picked from commit 1b782da49ae976dbb59607b95b49a1465e2cfef9)

Added: 
    

Modified: 
    clang/lib/Sema/SemaDeclCXX.cpp
    clang/test/CodeGenCXX/dllexport-ctor-closure-nested.cpp
    clang/test/PCH/dllexport-default-arg-closure.cpp
    clang/test/SemaCXX/default-arg-closures.cpp
    clang/test/SemaCXX/dllexport.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 685412d681680..b0669c602d249 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -6383,8 +6383,19 @@ static void checkForMultipleExportedDefaultConstructors(Sema &S,
   if (!S.Context.getTargetInfo().getCXXABI().isMicrosoft())
     return;
 
+  if (Class->isInvalidDecl())
+    return;
+
   CXXConstructorDecl *LastExportedDefaultCtor = nullptr;
   for (Decl *Member : Class->decls()) {
+    // Nested classes finish delayed default argument parsing with the outermost
+    // class, so check each nested definition here.
+    if (auto *NestedClass = dyn_cast<CXXRecordDecl>(Member)) {
+      if (NestedClass->isThisDeclarationADefinition())
+        checkForMultipleExportedDefaultConstructors(S, NestedClass);
+      continue;
+    }
+
     // Look for exported default constructors.
     auto *CD = dyn_cast<CXXConstructorDecl>(Member);
     if (!CD || !CD->isDefaultConstructor())

diff  --git a/clang/test/CodeGenCXX/dllexport-ctor-closure-nested.cpp b/clang/test/CodeGenCXX/dllexport-ctor-closure-nested.cpp
index 36dab8600e21b..e949bc82686c7 100644
--- a/clang/test/CodeGenCXX/dllexport-ctor-closure-nested.cpp
+++ b/clang/test/CodeGenCXX/dllexport-ctor-closure-nested.cpp
@@ -18,3 +18,14 @@ struct __declspec(dllexport) CtorClosureOuter {
 
 // CHECK-LABEL: $"??1HasImplicitDtor1@@QAE at XZ" = comdat any
 // CHECK-LABEL: define weak_odr dso_local dllexport x86_thiscallcc void @"??_FCtorClosureInner at CtorClosureOuter@@QAEXXZ"({{.*}}) {{#[0-9]+}} comdat
+
+// Member-level dllexport on a nested default constructor needs constructor
+// closure default arguments before the enclosing class is emitted.
+struct MemberExportedCtorClosureOuter {
+  struct MemberExportedCtorClosureInner {
+    __declspec(dllexport) MemberExportedCtorClosureInner(
+        const HasImplicitDtor1 &v = {}) {}
+  };
+};
+
+// CHECK-LABEL: define weak_odr dso_local dllexport x86_thiscallcc void @"??_FMemberExportedCtorClosureInner at MemberExportedCtorClosureOuter@@QAEXXZ"({{.*}}) {{#[0-9]+}} comdat

diff  --git a/clang/test/PCH/dllexport-default-arg-closure.cpp b/clang/test/PCH/dllexport-default-arg-closure.cpp
index b5ac7815b8111..b56d166e8d9f3 100644
--- a/clang/test/PCH/dllexport-default-arg-closure.cpp
+++ b/clang/test/PCH/dllexport-default-arg-closure.cpp
@@ -20,6 +20,15 @@ struct __declspec(dllexport) Foo {
 // CHECK: define weak_odr dso_local dllexport void @"??_FFoo@@QEAAXXZ"(ptr{{.*}})
 // CHECK:   call noundef ptr @"??0Foo@@QEAA at W4E@0@@Z"(ptr {{.*}}, i32 noundef 0)
 
+struct PCHMemberExportOuter {
+  struct Inner {
+    enum E { E0 } e;
+    __declspec(dllexport) Inner(E e = E0) : e(e) {}
+  };
+};
+
+// CHECK: define weak_odr dso_local dllexport void @"??_FInner at PCHMemberExportOuter@@QEAAXXZ"(ptr{{.*}})
+
 #else
 
 

diff  --git a/clang/test/SemaCXX/default-arg-closures.cpp b/clang/test/SemaCXX/default-arg-closures.cpp
index 676bd486105f9..86c44f0ead9f7 100644
--- a/clang/test/SemaCXX/default-arg-closures.cpp
+++ b/clang/test/SemaCXX/default-arg-closures.cpp
@@ -25,6 +25,15 @@ struct DependentDefaultCopyArg {
 struct HasMember {
   enum { member = 0 };
 };
+
+template <typename T>
+struct NestedDependentDefaultCtorArg {
+  struct Inner {
+    __declspec(dllexport) Inner(int n = T::member) {}
+  };
+};
+NestedDependentDefaultCtorArg<HasMember>::Inner ValidNestedDependentArg;
+
 void UseDependentArg() { throw DependentDefaultCopyArg<HasMember>(); }
 
 void ErrorInDependentArg() {

diff  --git a/clang/test/SemaCXX/dllexport.cpp b/clang/test/SemaCXX/dllexport.cpp
index d625b15557762..70e7f1398ad05 100644
--- a/clang/test/SemaCXX/dllexport.cpp
+++ b/clang/test/SemaCXX/dllexport.cpp
@@ -746,6 +746,20 @@ struct ClassTemplateWithMultipleDefaultCtors {
   __declspec(dllexport) ClassTemplateWithMultipleDefaultCtors(int = 30, ...) {} // ms-note{{declared here}}
 };
 
+struct ClassWithNestedMultipleDefaultCtors {
+  struct Nested {
+    __declspec(dllexport) Nested(int = 40) {}      // ms-error{{'__declspec(dllexport)' cannot be applied to more than one default constructor}}
+    __declspec(dllexport) Nested(int = 30, ...) {} // ms-note{{declared here}}
+  };
+};
+
+struct ClassWithNestedObviousMultipleDefaultCtors {
+  struct Nested {
+    __declspec(dllexport) Nested() {}    // ms-error{{'__declspec(dllexport)' cannot be applied to more than one default constructor}}
+    __declspec(dllexport) Nested(...) {} // ms-note{{declared here}}
+  };
+};
+
 template <typename T> struct HasDefaults {
   HasDefaults(int x = sizeof(T)) {} // ms-error {{invalid application of 'sizeof'}}
 };


        


More information about the llvm-branch-commits mailing list