https://github.com/IvyXu420 updated https://github.com/llvm/llvm-project/pull/228340
>From e18bacfeed81a1cf3cd085a88e34ee359079c54d Mon Sep 17 00:00:00 2001 From: Ivy Xu <[email protected]> Date: Fri, 2 Oct 2026 03:38:40 +0800 Subject: [PATCH 1/6] Fix clang rejecting valid `void{}` when template is used --- clang/lib/Sema/SemaExprCXX.cpp | 2 +- clang/test/CXX/drs/cwg23xx.cpp | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index 1bf6430665ddf..1ed58fcf20af0 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -1647,7 +1647,7 @@ Sema::BuildCXXTypeConstructExpr(TypeSourceInfo *TInfo, return CXXFunctionalCastExpr::Create( Context, Ty.getUnqualifiedType(), VK_PRValue, TInfo, CK_ToVoid, Exprs[0], /*Path=*/nullptr, CurFPFeatureOverrides(), - Exprs[0]->getBeginLoc(), Exprs[0]->getEndLoc()); + SourceLocation(), Exprs[0]->getEndLoc()); } } else if (RequireCompleteType(TyBeginLoc, ElemTy, diag::err_invalid_incomplete_type_use, diff --git a/clang/test/CXX/drs/cwg23xx.cpp b/clang/test/CXX/drs/cwg23xx.cpp index cfd78465c0dbe..c81fe223a596c 100644 --- a/clang/test/CXX/drs/cwg23xx.cpp +++ b/clang/test/CXX/drs/cwg23xx.cpp @@ -240,6 +240,10 @@ namespace cwg2351 { // cwg2351: 20 template void i<void>(); template const void i<const void>(); + template <class T> + void f(T) { void{}; } + void g() { f(1); } + static_assert((void({}), true), ""); // since-cxx11-error@-1 {{cannot initialize non-class type 'void' with a parenthesized initializer list}} #else >From 71dd64f2aa5951756198f7ad7a99bd1ab851be3a Mon Sep 17 00:00:00 2001 From: Ivy Xu <[email protected]> Date: Fri, 2 Oct 2026 14:25:05 +0800 Subject: [PATCH 2/6] Add release note --- clang/docs/ReleaseNotes.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md index d22874d4130ee..04ded7c5b6a2e 100644 --- a/clang/docs/ReleaseNotes.md +++ b/clang/docs/ReleaseNotes.md @@ -801,6 +801,9 @@ features cannot lower the translation-unit ABI level; take effect, causing them to be dropped from llvm.used and omitted from the object file. (#GH226572) +- Fixed rejection of non-dependent `void{}` during template instantiation, + which previously rebuilt the expression as `void({})`. (#GH226485, #GH181448) + #### Bug Fixes to AST Handling - Fixed a non-deterministic ordering of unused local typedefs that made >From ed5657d9a4fcb2dadbbc190d6ca7e4277fcfc5ff Mon Sep 17 00:00:00 2001 From: Ivy Xu <[email protected]> Date: Fri, 2 Oct 2026 15:20:06 +0800 Subject: [PATCH 3/6] fix the format --- clang/lib/Sema/SemaExprCXX.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index 1ed58fcf20af0..bb08c3bf1a0e4 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -1646,8 +1646,8 @@ Sema::BuildCXXTypeConstructExpr(TypeSourceInfo *TInfo, cast<InitListExpr>(Exprs[0])->getNumInits() == 0) { return CXXFunctionalCastExpr::Create( Context, Ty.getUnqualifiedType(), VK_PRValue, TInfo, CK_ToVoid, - Exprs[0], /*Path=*/nullptr, CurFPFeatureOverrides(), - SourceLocation(), Exprs[0]->getEndLoc()); + Exprs[0], /*Path=*/nullptr, CurFPFeatureOverrides(), SourceLocation(), + Exprs[0]->getEndLoc()); } } else if (RequireCompleteType(TyBeginLoc, ElemTy, diag::err_invalid_incomplete_type_use, >From 102f689f149cdb8ed4dcec2a3404879ba5fa50bf Mon Sep 17 00:00:00 2001 From: Ivy Xu <[email protected]> Date: Fri, 2 Oct 2026 21:08:37 +0800 Subject: [PATCH 4/6] Add a CXXFunctionalCastExpr::CreateListInitializer(...) function --- clang/include/clang/AST/ExprCXX.h | 5 +++++ clang/lib/AST/ExprCXX.cpp | 8 ++++++++ clang/lib/Sema/SemaExprCXX.cpp | 21 +++++++++++---------- 3 files changed, 24 insertions(+), 10 deletions(-) diff --git a/clang/include/clang/AST/ExprCXX.h b/clang/include/clang/AST/ExprCXX.h index 1393da4da2721..e42b4cd2d78db 100644 --- a/clang/include/clang/AST/ExprCXX.h +++ b/clang/include/clang/AST/ExprCXX.h @@ -1869,6 +1869,11 @@ class CXXFunctionalCastExpr final static CXXFunctionalCastExpr * CreateEmpty(const ASTContext &Context, unsigned PathSize, bool HasFPFeatures); + static CXXFunctionalCastExpr * + CreateListInitializer(const ASTContext &Context, QualType T, ExprValueKind VK, + TypeSourceInfo *Written, CastKind Kind, Expr *Op, + const CXXCastPath *Path, FPOptionsOverride FPO); + SourceLocation getLParenLoc() const { return LParenLoc; } void setLParenLoc(SourceLocation L) { LParenLoc = L; } SourceLocation getRParenLoc() const { return RParenLoc; } diff --git a/clang/lib/AST/ExprCXX.cpp b/clang/lib/AST/ExprCXX.cpp index 9d42d47f24840..135269696e044 100644 --- a/clang/lib/AST/ExprCXX.cpp +++ b/clang/lib/AST/ExprCXX.cpp @@ -974,6 +974,14 @@ CXXFunctionalCastExpr *CXXFunctionalCastExpr::CreateEmpty(const ASTContext &C, CXXFunctionalCastExpr(EmptyShell(), PathSize, HasFPFeatures); } +CXXFunctionalCastExpr *CXXFunctionalCastExpr::CreateListInitializer( + const ASTContext &C, QualType T, ExprValueKind VK, TypeSourceInfo *Written, + CastKind K, Expr *Op, const CXXCastPath *BasePath, FPOptionsOverride FPO) { + // List-initialization is represented by null paren locations + return Create(C, T, VK, Written, K, Op, BasePath, FPO, SourceLocation(), + SourceLocation()); +} + SourceLocation CXXFunctionalCastExpr::getBeginLoc() const { return getTypeInfoAsWritten()->getTypeLoc().getBeginLoc(); } diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index bb08c3bf1a0e4..c32f24808a4df 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -1644,10 +1644,9 @@ Sema::BuildCXXTypeConstructExpr(TypeSourceInfo *TInfo, Ty.getUnqualifiedType(), TInfo, Kind.getRange().getEnd()); if (ListInitialization && cast<InitListExpr>(Exprs[0])->getNumInits() == 0) { - return CXXFunctionalCastExpr::Create( + return CXXFunctionalCastExpr::CreateListInitializer( Context, Ty.getUnqualifiedType(), VK_PRValue, TInfo, CK_ToVoid, - Exprs[0], /*Path=*/nullptr, CurFPFeatureOverrides(), SourceLocation(), - Exprs[0]->getEndLoc()); + Exprs[0], /*Path=*/nullptr, CurFPFeatureOverrides()); } } else if (RequireCompleteType(TyBeginLoc, ElemTy, diag::err_invalid_incomplete_type_use, @@ -1687,13 +1686,15 @@ Sema::BuildCXXTypeConstructExpr(TypeSourceInfo *TInfo, // to false. bool IsListInit = ListInitialization || (getLangOpts().HLSL && isa<InitListExpr>(Result.get())); - SourceRange Locs = IsListInit - ? SourceRange() - : SourceRange(LParenOrBraceLoc, RParenOrBraceLoc); - Result = CXXFunctionalCastExpr::Create( - Context, ResultType, Expr::getValueKindForType(Ty), TInfo, CK_NoOp, - Result.get(), /*Path=*/nullptr, CurFPFeatureOverrides(), - Locs.getBegin(), Locs.getEnd()); + if (IsListInit) + Result = CXXFunctionalCastExpr::CreateListInitializer( + Context, ResultType, Expr::getValueKindForType(Ty), TInfo, CK_NoOp, + Result.get(), /*Path=*/nullptr, CurFPFeatureOverrides()); + else + Result = CXXFunctionalCastExpr::Create( + Context, ResultType, Expr::getValueKindForType(Ty), TInfo, CK_NoOp, + Result.get(), /*Path=*/nullptr, CurFPFeatureOverrides(), + LParenOrBraceLoc, RParenOrBraceLoc); } return Result; >From c82f63b5480b5f1a779667454be58d99f6cc91a2 Mon Sep 17 00:00:00 2001 From: Ivy Xu <[email protected]> Date: Sun, 4 Oct 2026 21:53:43 +0800 Subject: [PATCH 5/6] Address review --- clang/include/clang/AST/ExprCXX.h | 3 ++- clang/lib/AST/ExprCXX.cpp | 9 +++++---- clang/lib/Sema/SemaExprCXX.cpp | 6 ++++-- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/clang/include/clang/AST/ExprCXX.h b/clang/include/clang/AST/ExprCXX.h index c1e5cae48116b..0bf35edc47c46 100644 --- a/clang/include/clang/AST/ExprCXX.h +++ b/clang/include/clang/AST/ExprCXX.h @@ -1873,7 +1873,8 @@ class CXXFunctionalCastExpr final static CXXFunctionalCastExpr * CreateListInitializer(const ASTContext &Context, QualType T, ExprValueKind VK, TypeSourceInfo *Written, CastKind Kind, Expr *Op, - const CXXCastPath *Path, FPOptionsOverride FPO); + const CXXCastPath *Path, FPOptionsOverride FPO, + SourceLocation R); SourceLocation getLParenLoc() const { return LParenLoc; } void setLParenLoc(SourceLocation L) { LParenLoc = L; } diff --git a/clang/lib/AST/ExprCXX.cpp b/clang/lib/AST/ExprCXX.cpp index 4897cc16d79cf..ebf3500d9ca6d 100644 --- a/clang/lib/AST/ExprCXX.cpp +++ b/clang/lib/AST/ExprCXX.cpp @@ -975,10 +975,11 @@ CXXFunctionalCastExpr *CXXFunctionalCastExpr::CreateEmpty(const ASTContext &C, CXXFunctionalCastExpr *CXXFunctionalCastExpr::CreateListInitializer( const ASTContext &C, QualType T, ExprValueKind VK, TypeSourceInfo *Written, - CastKind K, Expr *Op, const CXXCastPath *BasePath, FPOptionsOverride FPO) { - // List-initialization is represented by null paren locations - return Create(C, T, VK, Written, K, Op, BasePath, FPO, SourceLocation(), - SourceLocation()); + CastKind K, Expr *Op, const CXXCastPath *BasePath, FPOptionsOverride FPO, + SourceLocation R) { + // List-initialization is represented by the null LParen location. + // FIXME: We should use a bit to represent it. + return Create(C, T, VK, Written, K, Op, BasePath, FPO, SourceLocation(), R); } SourceLocation CXXFunctionalCastExpr::getBeginLoc() const { diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index e00a8a39ce7a9..fd89fbf95b554 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -1646,7 +1646,8 @@ Sema::BuildCXXTypeConstructExpr(TypeSourceInfo *TInfo, cast<InitListExpr>(Exprs[0])->getNumInits() == 0) { return CXXFunctionalCastExpr::CreateListInitializer( Context, Ty.getUnqualifiedType(), VK_PRValue, TInfo, CK_ToVoid, - Exprs[0], /*Path=*/nullptr, CurFPFeatureOverrides()); + Exprs[0], /*Path=*/nullptr, CurFPFeatureOverrides(), + Exprs[0]->getEndLoc()); } } else if (RequireCompleteType(TyBeginLoc, ElemTy, diag::err_invalid_incomplete_type_use, @@ -1689,7 +1690,8 @@ Sema::BuildCXXTypeConstructExpr(TypeSourceInfo *TInfo, if (IsListInit) Result = CXXFunctionalCastExpr::CreateListInitializer( Context, ResultType, Expr::getValueKindForType(Ty), TInfo, CK_NoOp, - Result.get(), /*Path=*/nullptr, CurFPFeatureOverrides()); + Result.get(), /*Path=*/nullptr, CurFPFeatureOverrides(), + RParenOrBraceLoc); else Result = CXXFunctionalCastExpr::Create( Context, ResultType, Expr::getValueKindForType(Ty), TInfo, CK_NoOp, >From 66ef358821c085886473c9d97f9eb6d44875d794 Mon Sep 17 00:00:00 2001 From: Ivy Xu <[email protected]> Date: Sun, 4 Oct 2026 22:00:11 +0800 Subject: [PATCH 6/6] Add the "FIXME" comment to `CXXFunctionalCastExpr::isListInitialization` --- clang/include/clang/AST/ExprCXX.h | 1 + clang/lib/AST/ExprCXX.cpp | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/include/clang/AST/ExprCXX.h b/clang/include/clang/AST/ExprCXX.h index 0bf35edc47c46..cef23154b9230 100644 --- a/clang/include/clang/AST/ExprCXX.h +++ b/clang/include/clang/AST/ExprCXX.h @@ -1882,6 +1882,7 @@ class CXXFunctionalCastExpr final void setRParenLoc(SourceLocation L) { RParenLoc = L; } /// Determine whether this expression models list-initialization. + /// FIXME: We should use a bit to represent it. bool isListInitialization() const { return LParenLoc.isInvalid(); } SourceLocation getBeginLoc() const LLVM_READONLY; diff --git a/clang/lib/AST/ExprCXX.cpp b/clang/lib/AST/ExprCXX.cpp index ebf3500d9ca6d..4c64359154e4d 100644 --- a/clang/lib/AST/ExprCXX.cpp +++ b/clang/lib/AST/ExprCXX.cpp @@ -978,7 +978,6 @@ CXXFunctionalCastExpr *CXXFunctionalCastExpr::CreateListInitializer( CastKind K, Expr *Op, const CXXCastPath *BasePath, FPOptionsOverride FPO, SourceLocation R) { // List-initialization is represented by the null LParen location. - // FIXME: We should use a bit to represent it. return Create(C, T, VK, Written, K, Op, BasePath, FPO, SourceLocation(), R); } _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
