https://github.com/wenju-he updated 
https://github.com/llvm/llvm-project/pull/207917

>From d36ab97dd4818a50a9e4b5cd91223757738715aa Mon Sep 17 00:00:00 2001
From: Wenju He <[email protected]>
Date: Tue, 7 Jul 2026 09:39:12 +0200
Subject: [PATCH 1/3] [Clang] Fix null-pointer assertion reading
 CtorClosureDefaultArgs

BuildCtorClosureDefaultArgs deliberately leaves the first default-arg
slot null for MS ABI copy-constructor closures (the closure itself
supplies that argument), and ASTWriterDecl.cpp serializes the null.
But e7924d50db0a deserialized it with cast<>, which asserts
on null. This only triggers under the MS C++ ABI, e.g. when
throwing a class with a non-trivial copy constructor by value across
a PCH boundary, as in test
https://github.com/intel/llvm/blob/cb9b7b7/clang-tools-extra/clangd/test/sycl.test

Assisted by: Claude
---
 clang/lib/Serialization/ASTReaderDecl.cpp     |  2 +-
 .../test/PCH/dllexport-ctor-closure-copy.cpp  | 29 +++++++++++++++++++
 2 files changed, 30 insertions(+), 1 deletion(-)
 create mode 100644 clang/test/PCH/dllexport-ctor-closure-copy.cpp

diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp 
b/clang/lib/Serialization/ASTReaderDecl.cpp
index 86445e196722c..25598683d1d62 100644
--- a/clang/lib/Serialization/ASTReaderDecl.cpp
+++ b/clang/lib/Serialization/ASTReaderDecl.cpp
@@ -2345,7 +2345,7 @@ void 
ASTDeclReader::VisitCXXConstructorDecl(CXXConstructorDecl *D) {
     CXXDefaultArgExpr **Args =
         new (Reader.getContext()) CXXDefaultArgExpr *[NumArgs];
     for (unsigned I = 0; I != NumArgs; I++)
-      Args[I] = cast<CXXDefaultArgExpr>(Record.readStmt());
+      Args[I] = cast_or_null<CXXDefaultArgExpr>(Record.readStmt());
     D->setCtorClosureDefaultArgs(ArrayRef(Args, NumArgs));
   }
 
diff --git a/clang/test/PCH/dllexport-ctor-closure-copy.cpp 
b/clang/test/PCH/dllexport-ctor-closure-copy.cpp
new file mode 100644
index 0000000000000..bc7855deaba76
--- /dev/null
+++ b/clang/test/PCH/dllexport-ctor-closure-copy.cpp
@@ -0,0 +1,29 @@
+// Test that MS ABI copy-constructor closures (built when throwing a class by
+// value whose copy constructor has default arguments) survive a PCH
+// round-trip. BuildCtorClosureDefaultArgs deliberately leaves the first
+// default-arg slot null for a copy ctor closure (the closure itself supplies
+// that argument).
+//
+// Test this without pch.
+// RUN: %clang_cc1 -fcxx-exceptions -fms-extensions -triple i386-pc-win32 
-std=c++20 -include %s -emit-llvm -o - %s | FileCheck %s
+//
+// Test with pch.
+// RUN: %clang_cc1 -fcxx-exceptions -fms-extensions -triple i386-pc-win32 
-std=c++20 -emit-pch -o %t %s
+// RUN: %clang_cc1 -fcxx-exceptions -fms-extensions -triple i386-pc-win32 
-std=c++20 -include-pch %t -emit-llvm -o - %s | FileCheck %s
+
+#ifndef HEADER
+#define HEADER
+
+struct Default {
+  Default(Default &, int = 42);
+};
+
+void h(Default &d) {
+  throw d;
+}
+
+// CHECK-LABEL: define {{.*}} void @"?h@@YAXAAUDefault@@@Z"
+
+#else
+
+#endif

>From 4bb4a64b69df407cdfce28c842ed01bce2c24768 Mon Sep 17 00:00:00 2001
From: Wenju He <[email protected]>
Date: Tue, 7 Jul 2026 11:37:17 +0200
Subject: [PATCH 2/3] check ??_ODefault@@QAEXAAU0@@Z for non-pch case, add
 issue link

---
 clang/test/PCH/dllexport-ctor-closure-copy.cpp | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/clang/test/PCH/dllexport-ctor-closure-copy.cpp 
b/clang/test/PCH/dllexport-ctor-closure-copy.cpp
index bc7855deaba76..86e163f608c02 100644
--- a/clang/test/PCH/dllexport-ctor-closure-copy.cpp
+++ b/clang/test/PCH/dllexport-ctor-closure-copy.cpp
@@ -5,9 +5,11 @@
 // that argument).
 //
 // Test this without pch.
-// RUN: %clang_cc1 -fcxx-exceptions -fms-extensions -triple i386-pc-win32 
-std=c++20 -include %s -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -fcxx-exceptions -fms-extensions -triple i386-pc-win32 
-std=c++20 -include %s -emit-llvm -o - %s | FileCheck 
--check-prefixes=CHECK,CHECK-NOPCH %s
 //
 // Test with pch.
+// #207949: this cannot check for ??_ODefault copy-ctor closure:
+// ASTContext::CopyConstructorForExceptionObject is serialized into the PCH.
 // RUN: %clang_cc1 -fcxx-exceptions -fms-extensions -triple i386-pc-win32 
-std=c++20 -emit-pch -o %t %s
 // RUN: %clang_cc1 -fcxx-exceptions -fms-extensions -triple i386-pc-win32 
-std=c++20 -include-pch %t -emit-llvm -o - %s | FileCheck %s
 
@@ -23,6 +25,8 @@ void h(Default &d) {
 }
 
 // CHECK-LABEL: define {{.*}} void @"?h@@YAXAAUDefault@@@Z"
+// CHECK-NOPCH-LABEL: define linkonce_odr {{.*}} void 
@"??_ODefault@@QAEXAAU0@@Z"
+// CHECK-NOPCH: call {{.*}} @"??0Default@@QAE@AAU0@H@Z"({{.*}}, i32 noundef 42)
 
 #else
 

>From 16a9045d17d502fd75e1979e5f8e7016899d177a Mon Sep 17 00:00:00 2001
From: Wenju He <[email protected]>
Date: Tue, 7 Jul 2026 11:58:04 +0200
Subject: [PATCH 3/3] add not

---
 clang/test/PCH/dllexport-ctor-closure-copy.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang/test/PCH/dllexport-ctor-closure-copy.cpp 
b/clang/test/PCH/dllexport-ctor-closure-copy.cpp
index 86e163f608c02..ec847f56f84ca 100644
--- a/clang/test/PCH/dllexport-ctor-closure-copy.cpp
+++ b/clang/test/PCH/dllexport-ctor-closure-copy.cpp
@@ -9,7 +9,7 @@
 //
 // Test with pch.
 // #207949: this cannot check for ??_ODefault copy-ctor closure:
-// ASTContext::CopyConstructorForExceptionObject is serialized into the PCH.
+// ASTContext::CopyConstructorForExceptionObject is not serialized into the 
PCH.
 // RUN: %clang_cc1 -fcxx-exceptions -fms-extensions -triple i386-pc-win32 
-std=c++20 -emit-pch -o %t %s
 // RUN: %clang_cc1 -fcxx-exceptions -fms-extensions -triple i386-pc-win32 
-std=c++20 -include-pch %t -emit-llvm -o - %s | FileCheck %s
 

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to