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
