[clang] [Clang][CWG1815] Support lifetime extension of temporary created by aggregate initialization using a default member initializer (PR #87933)
yronglin wrote: > > @erichkeane Can you please take a look? > > Looking now, I was out on Friday due to illness. I'm sorry to hear that. Sending all my best and wishing you a rapid comeback. https://github.com/llvm/llvm-project/pull/87933 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][CWG1815] Support lifetime extension of temporary created by aggregate initialization using a default member initializer (PR #87933)
erichkeane wrote: > @erichkeane Can you please take a look? Looking now, I was out on Friday due to illness. https://github.com/llvm/llvm-project/pull/87933 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][CWG1815] Support lifetime extension of temporary created by aggregate initialization using a default member initializer (PR #87933)
yronglin wrote: Thanks for the new test case, it's fixed with https://github.com/llvm/llvm-project/pull/92527 https://github.com/llvm/llvm-project/pull/87933 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][CWG1815] Support lifetime extension of temporary created by aggregate initialization using a default member initializer (PR #87933)
jyknight wrote: We _don't_ diagnose it at the end of the definition of M -- it looks like we explicitly intentionally stopped doing so in the commit I referenced. That's why I'm a little confused here. With this patch, we start to diagnose only in the final line of code, `void test(M m = {}) {}` (that line doesn't appear in the error message, but it's the trigger). https://github.com/llvm/llvm-project/pull/87933 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][CWG1815] Support lifetime extension of temporary created by aggregate initialization using a default member initializer (PR #87933)
Endilll wrote: > It might violate https://eel.is/c++draft/temp.inst#11 to attempt to > instantiate the unused S::operator int? I don't think this clause of the standard is violated: you need to instantiate a declaration of the conversion function to at the end of definition of `M`, otherwise you can't "determine the correctness of the default member initializer" in `int x = S();`; https://github.com/llvm/llvm-project/pull/87933 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][CWG1815] Support lifetime extension of temporary created by aggregate initialization using a default member initializer (PR #87933)
jyknight wrote: Here's a test case that clang diagnoses with `-Wundefined-inline` after this patch, which I'm not sure whether is correct or not. It might violate https://eel.is/c++draft/temp.inst#11 to attempt to instantiate the unused `S::operator int`? I'm having a hard time telling whether this code is ill-defined NDR, or if the compiler is required to accept this. Clang stopped diagnosing this code with the fix for CWG2631, ca619613801233ef2def8c3cc7d311d5ed0033cb. Now this PR makes it diagnose again, despite that the default arg is never actually used. ``` struct S { template consteval operator T(); }; struct M { int x = S(); }; void test(M m = {}) {} ``` ``` test2.cc:3:13: error: inline function 'S::operator int' is not defined [-Werror,-Wundefined-inline] 3 | consteval operator T(); | ^ test2.cc:7:11: note: used here 7 | int x = S(); | ^ 1 error generated. ``` https://github.com/llvm/llvm-project/pull/87933 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][CWG1815] Support lifetime extension of temporary created by aggregate initialization using a default member initializer (PR #87933)
yronglin wrote: @erichkeane Can you please take a look? https://github.com/llvm/llvm-project/pull/87933 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][CWG1815] Support lifetime extension of temporary created by aggregate initialization using a default member initializer (PR #87933)
yronglin wrote: Sorry for the late reply, I found the update of comments from the email, and I have a new PR that fixes these problems. https://github.com/llvm/llvm-project/pull/87933 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][CWG1815] Support lifetime extension of temporary created by aggregate initialization using a default member initializer (PR #87933)
erichkeane wrote: I think we have enough evidence that we have to revert this, so I've done so in 224116ab9f4d97acb0cca76dc63c1d3d4a253078 @yronglin : Please submit a PR that includes the original patch + whatever it takes to fix the above issues. Unfortunately reverts happen :/ But I definitely appreciate the work you're doing on this. https://github.com/llvm/llvm-project/pull/87933 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][CWG1815] Support lifetime extension of temporary created by aggregate initialization using a default member initializer (PR #87933)
ZequanWu wrote: Here's a smaller repro of the `-Wuninitialized` warning: ``` int TestBody_got; namespace std { template struct integral_constant { static const int value = __v; }; template using enable_if_t = _Tp; template class initializer_list {}; template constexpr bool IsTypeOrDerived = integral_constant<__is_same(int, int)>::value; template using EnableIf = enable_if_t; template using EnableIfIsType = EnableIf, T>; template class Vector { public: Vector(initializer_list); }; template Vector(Ts...) -> Vector; class ProgramBuilder { public: template EnableIfIsType *create(ARGS); }; using TestHelper = ProgramBuilder; struct TypeTest : TestHelper { int *str_f16 = create(Vector{0}); TypeTest() {} }; class TypeTest_Element_Test : TypeTest { void TestBody(); }; } void std::TypeTest_Element_Test::TestBody() { int *expect = str_f16; _got != expect; } $ clang reduce.cpp -std=c++20 -fsyntax-only -Wuninitialized -Wno-unused-comparison reduce.cpp:34:20: warning: variable 'expect' is uninitialized when used here [-Wuninitialized] 34 | _got != expect; |^~ reduce.cpp:33:14: note: initialize the variable 'expect' to silence this warning 33 | int *expect = str_f16; | ^ | = nullptr 1 warning generated. ``` Can you verify if this is a false positive or not? If it's a false positive and would take a while to fix, can you revert this commit? https://github.com/llvm/llvm-project/pull/87933 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][CWG1815] Support lifetime extension of temporary created by aggregate initialization using a default member initializer (PR #87933)
ZequanWu wrote: Can we revert this change while you are investigating if this fix is not trivial? https://github.com/llvm/llvm-project/pull/87933 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][CWG1815] Support lifetime extension of temporary created by aggregate initialization using a default member initializer (PR #87933)
yronglin wrote: I've debug in local. The crash issue caused by initializer rebuild failed in https://github.com/llvm/llvm-project/blob/8e00703be9ceb41d9b80c2bc8f024a9610b9aaa1/clang/lib/Sema/SemaExpr.cpp#L5717-L5721 , if remove Line 5717 `SFINAETrap Trap(*this);`, we can got diagnostics like the following: ``` ``` https://github.com/llvm/llvm-project/pull/87933 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][CWG1815] Support lifetime extension of temporary created by aggregate initialization using a default member initializer (PR #87933)
ZequanWu wrote: Great, I just finished a creduce run with renaming pass disabled, but yours is short. https://github.com/llvm/llvm-project/pull/87933 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][CWG1815] Support lifetime extension of temporary created by aggregate initialization using a default member initializer (PR #87933)
yronglin wrote: I've a more short reproducer: ```C++ namespace std { template class initializer_list {}; } template class C { public: C(std::initializer_list); }; template using Ptr =__remove_pointer(T) *; template C(T) -> C, sizeof(T)>; class A { public: template T1 *some_func(T2 &&); }; struct B : A { int *ar = some_func(C{some_func(0)}); B() {} }; ``` https://github.com/llvm/llvm-project/pull/87933 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][CWG1815] Support lifetime extension of temporary created by aggregate initialization using a default member initializer (PR #87933)
yronglin wrote: Thanks, I'll take a look now. https://github.com/llvm/llvm-project/pull/87933 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][CWG1815] Support lifetime extension of temporary created by aggregate initialization using a default member initializer (PR #87933)
Endilll wrote: @ZequanWu thank you for your help, but next time you should disable renaming passes as specified in https://github.com/llvm/llvm-project/pull/89807#issuecomment-2102760018. C-Reduce output can be typically reduced further manually, but it's a pain without names. https://github.com/llvm/llvm-project/pull/87933 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][CWG1815] Support lifetime extension of temporary created by aggregate initialization using a default member initializer (PR #87933)
ZequanWu wrote: ``` $ cat a.cpp namespace std { template struct b { static const int c = a; }; template using e = d; template struct p { using g = f; }; template using i = p::g; template class initializer_list {}; template using j = __remove_pointer(d); template using k = j; template constexpr bool l = b<__is_base_of(int, int)>::c; template using ab = e; template using o = ab, n>; template constexpr bool ad = (l && ...); template struct u; template using ae = u::g; template struct u { using g = n; }; template class t { public: t(initializer_list); }; namespace ag { template struct D; template struct D { using ah = ae...>; using g = i<0, ah, ah *>; }; } template using r = ag::D, s...>::g; template t(s...) -> t, sizeof...(s)>; class v { public: template o *w(an &&); }; using ap = v; struct aq : ap { int *ar = w(t{w(int{})}); aq() {} } $ clang a.cpp [crash] ``` https://github.com/llvm/llvm-project/pull/87933 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][CWG1815] Support lifetime extension of temporary created by aggregate initialization using a default member initializer (PR #87933)
yronglin wrote: > Heads up. This causes clang to crash on some code. I'm running creduce to > reduce the cpp source file. > > ``` > clang: > /usr/local/google/home/zequanwu/workspace/llvm/clang/lib/Sema/SemaDecl.cpp:16509: > Decl *clang::Sema::ActOnFinishFunctionBody(Decl *, Stmt *, bool): Assertion > `!Cleanup.exprNeedsCleanups() && "Unaccounted cleanups in function"' failed. > ``` Thanks report this, nice and small reproducer would definitely help resolving this. https://github.com/llvm/llvm-project/pull/87933 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][CWG1815] Support lifetime extension of temporary created by aggregate initialization using a default member initializer (PR #87933)
ZequanWu wrote: Heads up. This causes clang to crash on some code. I'm running creduce to reduce the cpp source file. https://github.com/llvm/llvm-project/pull/87933 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][CWG1815] Support lifetime extension of temporary created by aggregate initialization using a default member initializer (PR #87933)
https://github.com/yronglin closed https://github.com/llvm/llvm-project/pull/87933 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][CWG1815] Support lifetime extension of temporary created by aggregate initialization using a default member initializer (PR #87933)
yronglin wrote: > > I'd like to proposal a separate PR for static analyzer. #91879 WDYT? > > That sounds good to me. Thanks for your confirmation! If you don’t have any concerns, I'd like to land this PR. 朗 https://github.com/llvm/llvm-project/pull/87933 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][CWG1815] Support lifetime extension of temporary created by aggregate initialization using a default member initializer (PR #87933)
zygoloid wrote: > I'd like to proposal a separate PR for static analyzer. #91879 WDYT? That sounds good to me. https://github.com/llvm/llvm-project/pull/87933 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][CWG1815] Support lifetime extension of temporary created by aggregate initialization using a default member initializer (PR #87933)
yronglin wrote: @zygoloid IIUC, since `CXXDefaultArgExpr` and `CXXDefaultInitExpr` were not added to CFG before and were fall back to constant evaluation in ExprEngine, they were not processed correctly in StaticAnalyzer. In CFG: https://github.com/llvm/llvm-project/blob/63224d717108d927e998da8a67050a6cc5dd74a2/clang/lib/Analysis/CFG.cpp#L2256-L2266 In ExprEngine: https://github.com/llvm/llvm-project/commit/5f6c173e7cb4f6a74c1aec2af3ae478a995c140d https://github.com/llvm/llvm-project/blob/63224d717108d927e998da8a67050a6cc5dd74a2/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp#L1965-L2004 I'd like to proposal a separate PR for static analyzer. https://github.com/llvm/llvm-project/pull/91879 https://github.com/llvm/llvm-project/pull/87933 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][CWG1815] Support lifetime extension of temporary created by aggregate initialization using a default member initializer (PR #87933)
https://github.com/yronglin updated https://github.com/llvm/llvm-project/pull/87933 >From 9fba6da7cb1ffbc7d46b69c6ac0cfd15a89c4b56 Mon Sep 17 00:00:00 2001 From: yronglin Date: Mon, 8 Apr 2024 01:38:23 +0800 Subject: [PATCH 1/6] [Clang] Support lifetime extension of temporary created by aggregate initialization using a default member initializer Signed-off-by: yronglin --- .../clang/Basic/DiagnosticSemaKinds.td| 6 --- clang/lib/Sema/SemaExpr.cpp | 16 clang/lib/Sema/SemaInit.cpp | 39 +-- .../Analysis/lifetime-extended-regions.cpp| 2 +- clang/test/CXX/drs/dr16xx.cpp | 2 - clang/test/CXX/drs/dr18xx.cpp | 5 +-- clang/test/CXX/special/class.temporary/p6.cpp | 20 ++ clang/test/SemaCXX/constexpr-default-arg.cpp | 4 +- clang/test/SemaCXX/eval-crashes.cpp | 6 +-- 9 files changed, 62 insertions(+), 38 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index a1dda2d2461c3..ba779e83d2afd 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -10010,12 +10010,6 @@ def warn_new_dangling_initializer_list : Warning< "the allocated initializer list}0 " "will be destroyed at the end of the full-expression">, InGroup; -def warn_unsupported_lifetime_extension : Warning< - "lifetime extension of " - "%select{temporary|backing array of initializer list}0 created " - "by aggregate initialization using a default member initializer " - "is not yet supported; lifetime of %select{temporary|backing array}0 " - "will end at the end of the full-expression">, InGroup; // For non-floating point, expressions of the form x == x or x != x // should result in a warning, since these always evaluate to a constant. diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 8db4fffeecfe3..b2e0f2a2a6011 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -6338,10 +6338,9 @@ ExprResult Sema::BuildCXXDefaultArgExpr(SourceLocation CallLoc, Res = Immediate.TransformInitializer(Param->getInit(), /*NotCopy=*/false); }); - if (Res.isInvalid()) -return ExprError(); - Res = ConvertParamDefaultArgument(Param, Res.get(), -Res.get()->getBeginLoc()); + if (Res.isUsable()) +Res = ConvertParamDefaultArgument(Param, Res.get(), + Res.get()->getBeginLoc()); if (Res.isInvalid()) return ExprError(); Init = Res.get(); @@ -6377,7 +6376,7 @@ ExprResult Sema::BuildCXXDefaultInitExpr(SourceLocation Loc, FieldDecl *Field) { Expr *Init = nullptr; bool NestedDefaultChecking = isCheckingDefaultArgumentOrInitializer(); - + bool InLifetimeExtendingContext = isInLifetimeExtendingContext(); EnterExpressionEvaluationContext EvalContext( *this, ExpressionEvaluationContext::PotentiallyEvaluated, Field); @@ -6412,11 +6411,14 @@ ExprResult Sema::BuildCXXDefaultInitExpr(SourceLocation Loc, FieldDecl *Field) { ImmediateCallVisitor V(getASTContext()); if (!NestedDefaultChecking) V.TraverseDecl(Field); - if (V.HasImmediateCalls) { + if (V.HasImmediateCalls || InLifetimeExtendingContext) { ExprEvalContexts.back().DelayedDefaultInitializationContext = {Loc, Field, CurContext}; ExprEvalContexts.back().IsCurrentlyCheckingDefaultArgumentOrInitializer = NestedDefaultChecking; +// Pass down lifetime extending flag, and collect temporaries in +// CreateMaterializeTemporaryExpr when we rewrite the call argument. +keepInLifetimeExtendingContext(); EnsureImmediateInvocationInDefaultArgs Immediate(*this); ExprResult Res; @@ -6424,7 +6426,7 @@ ExprResult Sema::BuildCXXDefaultInitExpr(SourceLocation Loc, FieldDecl *Field) { Res = Immediate.TransformInitializer(Field->getInClassInitializer(), /*CXXDirectInit=*/false); }); -if (!Res.isInvalid()) +if (Res.isUsable()) Res = ConvertMemberDefaultInitExpression(Field, Res.get(), Loc); if (Res.isInvalid()) { Field->setInvalidDecl(); diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index a75e9925a4314..842412cd674d8 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -710,6 +710,26 @@ void InitListChecker::FillInEmptyInitForField(unsigned Init, FieldDecl *Field, if (VerifyOnly) return; + // Enter a lifetime extension context, then we can support lifetime + // extension of temporary created by aggregate initialization using a + // default member initializer (DR1815 https://wg21.link/CWG1815). + // + // In
[clang] [Clang][CWG1815] Support lifetime extension of temporary created by aggregate initialization using a default member initializer (PR #87933)
https://github.com/yronglin updated https://github.com/llvm/llvm-project/pull/87933 >From 9fba6da7cb1ffbc7d46b69c6ac0cfd15a89c4b56 Mon Sep 17 00:00:00 2001 From: yronglin Date: Mon, 8 Apr 2024 01:38:23 +0800 Subject: [PATCH 1/5] [Clang] Support lifetime extension of temporary created by aggregate initialization using a default member initializer Signed-off-by: yronglin --- .../clang/Basic/DiagnosticSemaKinds.td| 6 --- clang/lib/Sema/SemaExpr.cpp | 16 clang/lib/Sema/SemaInit.cpp | 39 +-- .../Analysis/lifetime-extended-regions.cpp| 2 +- clang/test/CXX/drs/dr16xx.cpp | 2 - clang/test/CXX/drs/dr18xx.cpp | 5 +-- clang/test/CXX/special/class.temporary/p6.cpp | 20 ++ clang/test/SemaCXX/constexpr-default-arg.cpp | 4 +- clang/test/SemaCXX/eval-crashes.cpp | 6 +-- 9 files changed, 62 insertions(+), 38 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index a1dda2d2461c3..ba779e83d2afd 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -10010,12 +10010,6 @@ def warn_new_dangling_initializer_list : Warning< "the allocated initializer list}0 " "will be destroyed at the end of the full-expression">, InGroup; -def warn_unsupported_lifetime_extension : Warning< - "lifetime extension of " - "%select{temporary|backing array of initializer list}0 created " - "by aggregate initialization using a default member initializer " - "is not yet supported; lifetime of %select{temporary|backing array}0 " - "will end at the end of the full-expression">, InGroup; // For non-floating point, expressions of the form x == x or x != x // should result in a warning, since these always evaluate to a constant. diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 8db4fffeecfe3..b2e0f2a2a6011 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -6338,10 +6338,9 @@ ExprResult Sema::BuildCXXDefaultArgExpr(SourceLocation CallLoc, Res = Immediate.TransformInitializer(Param->getInit(), /*NotCopy=*/false); }); - if (Res.isInvalid()) -return ExprError(); - Res = ConvertParamDefaultArgument(Param, Res.get(), -Res.get()->getBeginLoc()); + if (Res.isUsable()) +Res = ConvertParamDefaultArgument(Param, Res.get(), + Res.get()->getBeginLoc()); if (Res.isInvalid()) return ExprError(); Init = Res.get(); @@ -6377,7 +6376,7 @@ ExprResult Sema::BuildCXXDefaultInitExpr(SourceLocation Loc, FieldDecl *Field) { Expr *Init = nullptr; bool NestedDefaultChecking = isCheckingDefaultArgumentOrInitializer(); - + bool InLifetimeExtendingContext = isInLifetimeExtendingContext(); EnterExpressionEvaluationContext EvalContext( *this, ExpressionEvaluationContext::PotentiallyEvaluated, Field); @@ -6412,11 +6411,14 @@ ExprResult Sema::BuildCXXDefaultInitExpr(SourceLocation Loc, FieldDecl *Field) { ImmediateCallVisitor V(getASTContext()); if (!NestedDefaultChecking) V.TraverseDecl(Field); - if (V.HasImmediateCalls) { + if (V.HasImmediateCalls || InLifetimeExtendingContext) { ExprEvalContexts.back().DelayedDefaultInitializationContext = {Loc, Field, CurContext}; ExprEvalContexts.back().IsCurrentlyCheckingDefaultArgumentOrInitializer = NestedDefaultChecking; +// Pass down lifetime extending flag, and collect temporaries in +// CreateMaterializeTemporaryExpr when we rewrite the call argument. +keepInLifetimeExtendingContext(); EnsureImmediateInvocationInDefaultArgs Immediate(*this); ExprResult Res; @@ -6424,7 +6426,7 @@ ExprResult Sema::BuildCXXDefaultInitExpr(SourceLocation Loc, FieldDecl *Field) { Res = Immediate.TransformInitializer(Field->getInClassInitializer(), /*CXXDirectInit=*/false); }); -if (!Res.isInvalid()) +if (Res.isUsable()) Res = ConvertMemberDefaultInitExpression(Field, Res.get(), Loc); if (Res.isInvalid()) { Field->setInvalidDecl(); diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index a75e9925a4314..842412cd674d8 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -710,6 +710,26 @@ void InitListChecker::FillInEmptyInitForField(unsigned Init, FieldDecl *Field, if (VerifyOnly) return; + // Enter a lifetime extension context, then we can support lifetime + // extension of temporary created by aggregate initialization using a + // default member initializer (DR1815 https://wg21.link/CWG1815). + // + // In
[clang] [Clang][CWG1815] Support lifetime extension of temporary created by aggregate initialization using a default member initializer (PR #87933)
yronglin wrote: Many thanks for your review and help! I‘d like to take a few days to try to update static analyzer. https://github.com/llvm/llvm-project/pull/87933 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][CWG1815] Support lifetime extension of temporary created by aggregate initialization using a default member initializer (PR #87933)
https://github.com/zygoloid approved this pull request. Looks great! I think it'd be good to understand what's happening with the static analyzer test, and update the comment to explain. But given that this is fixing a conformance / wrong code bug, I don't think we should block this PR on fixing any issue that turns up in the analyzer, unless it turns out that there's still a conformance issue here. https://github.com/llvm/llvm-project/pull/87933 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][CWG1815] Support lifetime extension of temporary created by aggregate initialization using a default member initializer (PR #87933)
@@ -711,6 +711,26 @@ void InitListChecker::FillInEmptyInitForField(unsigned Init, FieldDecl *Field, if (VerifyOnly) return; + // Enter a lifetime extension context, then we can support lifetime + // extension of temporary created by aggregate initialization using a + // default member initializer (DR1815 https://wg21.link/CWG1815). + // + // In a lifetime extension context, BuildCXXDefaultInitExpr will clone the + // initializer expression on each use that would lifetime extend its + // temporaries. + EnterExpressionEvaluationContext LifetimeExtensionContext( + SemaRef, Sema::ExpressionEvaluationContext::PotentiallyEvaluated, + /*LambdaContextDecl=*/nullptr, + Sema::ExpressionEvaluationContextRecord::EK_Other, true); + + // Lifetime extension in default-member-init. + auto = SemaRef.ExprEvalContexts.back(); + + // Just copy previous record, make sure we haven't forget anything. + LastRecord = + SemaRef.ExprEvalContexts[SemaRef.ExprEvalContexts.size() - 2]; + LastRecord.InLifetimeExtendingContext = true; yronglin wrote: Thanks for your guidance, done! https://github.com/llvm/llvm-project/pull/87933 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][CWG1815] Support lifetime extension of temporary created by aggregate initialization using a default member initializer (PR #87933)
https://github.com/yronglin deleted https://github.com/llvm/llvm-project/pull/87933 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][CWG1815] Support lifetime extension of temporary created by aggregate initialization using a default member initializer (PR #87933)
@@ -122,7 +122,7 @@ void aggregateWithReferences() { clang_analyzer_dump(viaReference.ry); // expected-warning-re {{_extended_object{Composite, viaReference, S{{[0-9]+}}} }} // clang does not currently implement extending lifetime of object bound to reference members of aggregates, - // that are created from default member initializer (see `warn_unsupported_lifetime_extension` from `-Wdangling`) + // that are created from default member initializer (see `warn_unsupported_lifetime_extension` from `-Wdangling`) (Supported now). RefAggregate defaultInitExtended{i}; // clang-bug does not extend `Composite` clang_analyzer_dump(defaultInitExtended.ry); // expected-warning {{Unknown }} yronglin wrote: Please give me some time to investigate, I'm not very familiar with analyzer. https://github.com/llvm/llvm-project/pull/87933 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][CWG1815] Support lifetime extension of temporary created by aggregate initialization using a default member initializer (PR #87933)
https://github.com/yronglin updated https://github.com/llvm/llvm-project/pull/87933 >From 9fba6da7cb1ffbc7d46b69c6ac0cfd15a89c4b56 Mon Sep 17 00:00:00 2001 From: yronglin Date: Mon, 8 Apr 2024 01:38:23 +0800 Subject: [PATCH 1/4] [Clang] Support lifetime extension of temporary created by aggregate initialization using a default member initializer Signed-off-by: yronglin --- .../clang/Basic/DiagnosticSemaKinds.td| 6 --- clang/lib/Sema/SemaExpr.cpp | 16 clang/lib/Sema/SemaInit.cpp | 39 +-- .../Analysis/lifetime-extended-regions.cpp| 2 +- clang/test/CXX/drs/dr16xx.cpp | 2 - clang/test/CXX/drs/dr18xx.cpp | 5 +-- clang/test/CXX/special/class.temporary/p6.cpp | 20 ++ clang/test/SemaCXX/constexpr-default-arg.cpp | 4 +- clang/test/SemaCXX/eval-crashes.cpp | 6 +-- 9 files changed, 62 insertions(+), 38 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index a1dda2d2461c3..ba779e83d2afd 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -10010,12 +10010,6 @@ def warn_new_dangling_initializer_list : Warning< "the allocated initializer list}0 " "will be destroyed at the end of the full-expression">, InGroup; -def warn_unsupported_lifetime_extension : Warning< - "lifetime extension of " - "%select{temporary|backing array of initializer list}0 created " - "by aggregate initialization using a default member initializer " - "is not yet supported; lifetime of %select{temporary|backing array}0 " - "will end at the end of the full-expression">, InGroup; // For non-floating point, expressions of the form x == x or x != x // should result in a warning, since these always evaluate to a constant. diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 8db4fffeecfe3..b2e0f2a2a6011 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -6338,10 +6338,9 @@ ExprResult Sema::BuildCXXDefaultArgExpr(SourceLocation CallLoc, Res = Immediate.TransformInitializer(Param->getInit(), /*NotCopy=*/false); }); - if (Res.isInvalid()) -return ExprError(); - Res = ConvertParamDefaultArgument(Param, Res.get(), -Res.get()->getBeginLoc()); + if (Res.isUsable()) +Res = ConvertParamDefaultArgument(Param, Res.get(), + Res.get()->getBeginLoc()); if (Res.isInvalid()) return ExprError(); Init = Res.get(); @@ -6377,7 +6376,7 @@ ExprResult Sema::BuildCXXDefaultInitExpr(SourceLocation Loc, FieldDecl *Field) { Expr *Init = nullptr; bool NestedDefaultChecking = isCheckingDefaultArgumentOrInitializer(); - + bool InLifetimeExtendingContext = isInLifetimeExtendingContext(); EnterExpressionEvaluationContext EvalContext( *this, ExpressionEvaluationContext::PotentiallyEvaluated, Field); @@ -6412,11 +6411,14 @@ ExprResult Sema::BuildCXXDefaultInitExpr(SourceLocation Loc, FieldDecl *Field) { ImmediateCallVisitor V(getASTContext()); if (!NestedDefaultChecking) V.TraverseDecl(Field); - if (V.HasImmediateCalls) { + if (V.HasImmediateCalls || InLifetimeExtendingContext) { ExprEvalContexts.back().DelayedDefaultInitializationContext = {Loc, Field, CurContext}; ExprEvalContexts.back().IsCurrentlyCheckingDefaultArgumentOrInitializer = NestedDefaultChecking; +// Pass down lifetime extending flag, and collect temporaries in +// CreateMaterializeTemporaryExpr when we rewrite the call argument. +keepInLifetimeExtendingContext(); EnsureImmediateInvocationInDefaultArgs Immediate(*this); ExprResult Res; @@ -6424,7 +6426,7 @@ ExprResult Sema::BuildCXXDefaultInitExpr(SourceLocation Loc, FieldDecl *Field) { Res = Immediate.TransformInitializer(Field->getInClassInitializer(), /*CXXDirectInit=*/false); }); -if (!Res.isInvalid()) +if (Res.isUsable()) Res = ConvertMemberDefaultInitExpression(Field, Res.get(), Loc); if (Res.isInvalid()) { Field->setInvalidDecl(); diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index a75e9925a4314..842412cd674d8 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -710,6 +710,26 @@ void InitListChecker::FillInEmptyInitForField(unsigned Init, FieldDecl *Field, if (VerifyOnly) return; + // Enter a lifetime extension context, then we can support lifetime + // extension of temporary created by aggregate initialization using a + // default member initializer (DR1815 https://wg21.link/CWG1815). + // + // In
[clang] [Clang][CWG1815] Support lifetime extension of temporary created by aggregate initialization using a default member initializer (PR #87933)
https://github.com/yronglin edited https://github.com/llvm/llvm-project/pull/87933 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][CWG1815] Support lifetime extension of temporary created by aggregate initialization using a default member initializer (PR #87933)
yronglin wrote: Thanks for you review! https://github.com/llvm/llvm-project/pull/87933 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][CWG1815] Support lifetime extension of temporary created by aggregate initialization using a default member initializer (PR #87933)
@@ -122,7 +122,7 @@ void aggregateWithReferences() { clang_analyzer_dump(viaReference.ry); // expected-warning-re {{_extended_object{Composite, viaReference, S{{[0-9]+}}} }} // clang does not currently implement extending lifetime of object bound to reference members of aggregates, - // that are created from default member initializer (see `warn_unsupported_lifetime_extension` from `-Wdangling`) + // that are created from default member initializer (see `warn_unsupported_lifetime_extension` from `-Wdangling`) (Supported now). RefAggregate defaultInitExtended{i}; // clang-bug does not extend `Composite` clang_analyzer_dump(defaultInitExtended.ry); // expected-warning {{Unknown }} yronglin wrote: Thanks, good catch! we need update this. https://github.com/llvm/llvm-project/pull/87933 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][CWG1815] Support lifetime extension of temporary created by aggregate initialization using a default member initializer (PR #87933)
@@ -711,6 +711,26 @@ void InitListChecker::FillInEmptyInitForField(unsigned Init, FieldDecl *Field, if (VerifyOnly) return; + // Enter a lifetime extension context, then we can support lifetime + // extension of temporary created by aggregate initialization using a + // default member initializer (DR1815 https://wg21.link/CWG1815). + // + // In a lifetime extension context, BuildCXXDefaultInitExpr will clone the + // initializer expression on each use that would lifetime extend its + // temporaries. + EnterExpressionEvaluationContext LifetimeExtensionContext( + SemaRef, Sema::ExpressionEvaluationContext::PotentiallyEvaluated, + /*LambdaContextDecl=*/nullptr, + Sema::ExpressionEvaluationContextRecord::EK_Other, true); + + // Lifetime extension in default-member-init. + auto = SemaRef.ExprEvalContexts.back(); + + // Just copy previous record, make sure we haven't forget anything. + LastRecord = + SemaRef.ExprEvalContexts[SemaRef.ExprEvalContexts.size() - 2]; + LastRecord.InLifetimeExtendingContext = true; yronglin wrote: Hmm, thanks point it out, somehow I misunderstand here. Can I extend `InLifetimeExtendingContext` from `bool` to an `enum{NoExtend, ExtendTopLevel, ExtendAll}` to guide lifetime extension behavior? I think it can reduce unnecessery rebuild action. https://github.com/llvm/llvm-project/pull/87933 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][CWG1815] Support lifetime extension of temporary created by aggregate initialization using a default member initializer (PR #87933)
https://github.com/yronglin deleted https://github.com/llvm/llvm-project/pull/87933 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][CWG1815] Support lifetime extension of temporary created by aggregate initialization using a default member initializer (PR #87933)
@@ -8194,25 +8216,18 @@ void Sema::checkInitializerLifetime(const InitializedEntity , } switch (shouldLifetimeExtendThroughPath(Path)) { + case PathLifetimeKind::ShouldExtend: yronglin wrote: Hmm, thanks point it out, somehow I misunderstand here. Can I extend `InLifetimeExtendingContext` from `bool` to an `enum{NoExtend, ExtendTopLevel, ExtendAll}` to guide lifetime extension behavior? I think it can reduce unnecessery rebuild action. https://github.com/llvm/llvm-project/pull/87933 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][CWG1815] Support lifetime extension of temporary created by aggregate initialization using a default member initializer (PR #87933)
@@ -10698,7 +10698,7 @@ C++ defect report implementation status https://cplusplus.github.io/CWG/issues/1815.html;>1815 CD4 Lifetime extension in aggregate initialization -No +Clang 19 yronglin wrote: Thanks for your tips! https://github.com/llvm/llvm-project/pull/87933 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][CWG1815] Support lifetime extension of temporary created by aggregate initialization using a default member initializer (PR #87933)
@@ -269,6 +269,26 @@ void init_capture_init_list() { // CHECK: } } +void check_dr1815() { // dr1815: yes +#if __cplusplus >= 201402L + + struct A { +int & = 0; +~A() {} + }; + + struct B { +A & = A{}; +~B() {} + }; + + // CHECK: void @_Z12check_dr1815v() + // CHECK: call void @_ZZ12check_dr1815vEN1BD1Ev( + // CHECK: call void @_ZZ12check_dr1815vEN1AD1Ev( + B a = {}; yronglin wrote: Agree https://github.com/llvm/llvm-project/pull/87933 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][CWG1815] Support lifetime extension of temporary created by aggregate initialization using a default member initializer (PR #87933)
@@ -206,13 +206,10 @@ namespace cwg1814 { // cwg1814: yes #endif } -namespace cwg1815 { // cwg1815: no +namespace cwg1815 { // cwg1815: yes yronglin wrote: Agree 100%! https://github.com/llvm/llvm-project/pull/87933 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][CWG1815] Support lifetime extension of temporary created by aggregate initialization using a default member initializer (PR #87933)
@@ -8194,25 +8216,18 @@ void Sema::checkInitializerLifetime(const InitializedEntity , } switch (shouldLifetimeExtendThroughPath(Path)) { + case PathLifetimeKind::ShouldExtend: yronglin wrote: Yeah, `ShouldExtend ` can be removed, and it's only used for `CXXDefaultInitExpr` now. https://github.com/llvm/llvm-project/pull/87933 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][CWG1815] Support lifetime extension of temporary created by aggregate initialization using a default member initializer (PR #87933)
@@ -711,6 +711,26 @@ void InitListChecker::FillInEmptyInitForField(unsigned Init, FieldDecl *Field, if (VerifyOnly) return; + // Enter a lifetime extension context, then we can support lifetime + // extension of temporary created by aggregate initialization using a + // default member initializer (DR1815 https://wg21.link/CWG1815). + // + // In a lifetime extension context, BuildCXXDefaultInitExpr will clone the + // initializer expression on each use that would lifetime extend its + // temporaries. + EnterExpressionEvaluationContext LifetimeExtensionContext( + SemaRef, Sema::ExpressionEvaluationContext::PotentiallyEvaluated, + /*LambdaContextDecl=*/nullptr, + Sema::ExpressionEvaluationContextRecord::EK_Other, true); + + // Lifetime extension in default-member-init. + auto = SemaRef.ExprEvalContexts.back(); + + // Just copy previous record, make sure we haven't forget anything. + LastRecord = + SemaRef.ExprEvalContexts[SemaRef.ExprEvalContexts.size() - 2]; + LastRecord.InLifetimeExtendingContext = true; zygoloid wrote: This doesn't look right -- this would lifetime-extend *all* temporaries in the initializer. Only those that are actually bound to a reference member should be extended here. Perhaps instead of these changes involving `InLifetimeExtendedContext`, you could change `BuildCXXDefaultInitExpr` to always rebuild the initializer if it contains any temporaries (if the initializer expression is an `ExprWithCleanups`). Then make sure the normal lifetime extension code recurses into the default initializer and does lifetime extension when warranted. https://github.com/llvm/llvm-project/pull/87933 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][CWG1815] Support lifetime extension of temporary created by aggregate initialization using a default member initializer (PR #87933)
@@ -206,13 +206,10 @@ namespace cwg1814 { // cwg1814: yes #endif } -namespace cwg1815 { // cwg1815: no +namespace cwg1815 { // cwg1815: yes zygoloid wrote: A test for constant evaluation would be nice here too. Maybe: ```c++ struct C { const int = 0; }; constexpr C c = {}; static_assert(c.r == 0); ``` or ```c++ constexpr int f() { A a = {}; return a.r; } static_assert(f() == 0); ``` https://github.com/llvm/llvm-project/pull/87933 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][CWG1815] Support lifetime extension of temporary created by aggregate initialization using a default member initializer (PR #87933)
@@ -10698,7 +10698,7 @@ C++ defect report implementation status https://cplusplus.github.io/CWG/issues/1815.html;>1815 CD4 Lifetime extension in aggregate initialization -No +Clang 19 zygoloid wrote: ```suggestion Clang 19 ``` We use a different CSS class here for features that haven't been in an official release yet. https://github.com/llvm/llvm-project/pull/87933 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][CWG1815] Support lifetime extension of temporary created by aggregate initialization using a default member initializer (PR #87933)
@@ -122,7 +122,7 @@ void aggregateWithReferences() { clang_analyzer_dump(viaReference.ry); // expected-warning-re {{_extended_object{Composite, viaReference, S{{[0-9]+}}} }} // clang does not currently implement extending lifetime of object bound to reference members of aggregates, - // that are created from default member initializer (see `warn_unsupported_lifetime_extension` from `-Wdangling`) + // that are created from default member initializer (see `warn_unsupported_lifetime_extension` from `-Wdangling`) (Supported now). RefAggregate defaultInitExtended{i}; // clang-bug does not extend `Composite` clang_analyzer_dump(defaultInitExtended.ry); // expected-warning {{Unknown }} zygoloid wrote: If the bug is fixed, does the analyzer output not change here? In any case, the comment should explain whatever the new behavior is, and shouldn't be mentioning a warning that no longer exists. https://github.com/llvm/llvm-project/pull/87933 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][CWG1815] Support lifetime extension of temporary created by aggregate initialization using a default member initializer (PR #87933)
@@ -269,6 +269,26 @@ void init_capture_init_list() { // CHECK: } } +void check_dr1815() { // dr1815: yes +#if __cplusplus >= 201402L + + struct A { +int & = 0; +~A() {} + }; + + struct B { +A & = A{}; +~B() {} + }; + + // CHECK: void @_Z12check_dr1815v() + // CHECK: call void @_ZZ12check_dr1815vEN1BD1Ev( + // CHECK: call void @_ZZ12check_dr1815vEN1AD1Ev( + B a = {}; zygoloid wrote: This check of destructor ordering is a bit too subtle for my tastes. How about: ```suggestion // CHECK: void @_Z12check_dr1815v() B a = {}; // CHECK: call {{.*}}some_other_function extern void some_other_function(); some_other_function(); // CHECK: call void @_ZZ12check_dr1815vEN1BD1Ev( // CHECK: call void @_ZZ12check_dr1815vEN1AD1Ev( ``` ... to really drive home that the `A` temporary isn't destroyed until the end of the function? https://github.com/llvm/llvm-project/pull/87933 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][CWG1815] Support lifetime extension of temporary created by aggregate initialization using a default member initializer (PR #87933)
@@ -8194,25 +8216,18 @@ void Sema::checkInitializerLifetime(const InitializedEntity , } switch (shouldLifetimeExtendThroughPath(Path)) { + case PathLifetimeKind::ShouldExtend: zygoloid wrote: Do we need separate `ShouldExtend` and `Extend` kinds still, or can we combine them? https://github.com/llvm/llvm-project/pull/87933 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][CWG1815] Support lifetime extension of temporary created by aggregate initialization using a default member initializer (PR #87933)
https://github.com/zygoloid edited https://github.com/llvm/llvm-project/pull/87933 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][CWG1815] Support lifetime extension of temporary created by aggregate initialization using a default member initializer (PR #87933)
https://github.com/zygoloid commented: Thanks for working on this. https://github.com/llvm/llvm-project/pull/87933 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][CWG1815] Support lifetime extension of temporary created by aggregate initialization using a default member initializer (PR #87933)
yronglin wrote: friendly ping~ https://github.com/llvm/llvm-project/pull/87933 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][CWG1815] Support lifetime extension of temporary created by aggregate initialization using a default member initializer (PR #87933)
https://github.com/yronglin updated https://github.com/llvm/llvm-project/pull/87933 >From 9fba6da7cb1ffbc7d46b69c6ac0cfd15a89c4b56 Mon Sep 17 00:00:00 2001 From: yronglin Date: Mon, 8 Apr 2024 01:38:23 +0800 Subject: [PATCH 1/3] [Clang] Support lifetime extension of temporary created by aggregate initialization using a default member initializer Signed-off-by: yronglin --- .../clang/Basic/DiagnosticSemaKinds.td| 6 --- clang/lib/Sema/SemaExpr.cpp | 16 clang/lib/Sema/SemaInit.cpp | 39 +-- .../Analysis/lifetime-extended-regions.cpp| 2 +- clang/test/CXX/drs/dr16xx.cpp | 2 - clang/test/CXX/drs/dr18xx.cpp | 5 +-- clang/test/CXX/special/class.temporary/p6.cpp | 20 ++ clang/test/SemaCXX/constexpr-default-arg.cpp | 4 +- clang/test/SemaCXX/eval-crashes.cpp | 6 +-- 9 files changed, 62 insertions(+), 38 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index a1dda2d2461c31..ba779e83d2afd4 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -10010,12 +10010,6 @@ def warn_new_dangling_initializer_list : Warning< "the allocated initializer list}0 " "will be destroyed at the end of the full-expression">, InGroup; -def warn_unsupported_lifetime_extension : Warning< - "lifetime extension of " - "%select{temporary|backing array of initializer list}0 created " - "by aggregate initialization using a default member initializer " - "is not yet supported; lifetime of %select{temporary|backing array}0 " - "will end at the end of the full-expression">, InGroup; // For non-floating point, expressions of the form x == x or x != x // should result in a warning, since these always evaluate to a constant. diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 8db4fffeecfe35..b2e0f2a2a60113 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -6338,10 +6338,9 @@ ExprResult Sema::BuildCXXDefaultArgExpr(SourceLocation CallLoc, Res = Immediate.TransformInitializer(Param->getInit(), /*NotCopy=*/false); }); - if (Res.isInvalid()) -return ExprError(); - Res = ConvertParamDefaultArgument(Param, Res.get(), -Res.get()->getBeginLoc()); + if (Res.isUsable()) +Res = ConvertParamDefaultArgument(Param, Res.get(), + Res.get()->getBeginLoc()); if (Res.isInvalid()) return ExprError(); Init = Res.get(); @@ -6377,7 +6376,7 @@ ExprResult Sema::BuildCXXDefaultInitExpr(SourceLocation Loc, FieldDecl *Field) { Expr *Init = nullptr; bool NestedDefaultChecking = isCheckingDefaultArgumentOrInitializer(); - + bool InLifetimeExtendingContext = isInLifetimeExtendingContext(); EnterExpressionEvaluationContext EvalContext( *this, ExpressionEvaluationContext::PotentiallyEvaluated, Field); @@ -6412,11 +6411,14 @@ ExprResult Sema::BuildCXXDefaultInitExpr(SourceLocation Loc, FieldDecl *Field) { ImmediateCallVisitor V(getASTContext()); if (!NestedDefaultChecking) V.TraverseDecl(Field); - if (V.HasImmediateCalls) { + if (V.HasImmediateCalls || InLifetimeExtendingContext) { ExprEvalContexts.back().DelayedDefaultInitializationContext = {Loc, Field, CurContext}; ExprEvalContexts.back().IsCurrentlyCheckingDefaultArgumentOrInitializer = NestedDefaultChecking; +// Pass down lifetime extending flag, and collect temporaries in +// CreateMaterializeTemporaryExpr when we rewrite the call argument. +keepInLifetimeExtendingContext(); EnsureImmediateInvocationInDefaultArgs Immediate(*this); ExprResult Res; @@ -6424,7 +6426,7 @@ ExprResult Sema::BuildCXXDefaultInitExpr(SourceLocation Loc, FieldDecl *Field) { Res = Immediate.TransformInitializer(Field->getInClassInitializer(), /*CXXDirectInit=*/false); }); -if (!Res.isInvalid()) +if (Res.isUsable()) Res = ConvertMemberDefaultInitExpression(Field, Res.get(), Loc); if (Res.isInvalid()) { Field->setInvalidDecl(); diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index a75e9925a43146..842412cd674d8c 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -710,6 +710,26 @@ void InitListChecker::FillInEmptyInitForField(unsigned Init, FieldDecl *Field, if (VerifyOnly) return; + // Enter a lifetime extension context, then we can support lifetime + // extension of temporary created by aggregate initialization using a + // default member initializer (DR1815 https://wg21.link/CWG1815). + // +
[clang] [Clang][CWG1815] Support lifetime extension of temporary created by aggregate initialization using a default member initializer (PR #87933)
https://github.com/yronglin edited https://github.com/llvm/llvm-project/pull/87933 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][CWG1815] Support lifetime extension of temporary created by aggregate initialization using a default member initializer (PR #87933)
yronglin wrote: Friendly ping! @zygoloid @hubert-reinterpretcast https://github.com/llvm/llvm-project/pull/87933 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][CWG1815] Support lifetime extension of temporary created by aggregate initialization using a default member initializer (PR #87933)
yronglin wrote: Friendly ping~ @zygoloid @hubert-reinterpretcast https://github.com/llvm/llvm-project/pull/87933 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][CWG1815] Support lifetime extension of temporary created by aggregate initialization using a default member initializer (PR #87933)
cor3ntin wrote: @hubert-reinterpretcast ping! https://github.com/llvm/llvm-project/pull/87933 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][CWG1815] Support lifetime extension of temporary created by aggregate initialization using a default member initializer (PR #87933)
yronglin wrote: friendly ping~ https://github.com/llvm/llvm-project/pull/87933 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][CWG1815] Support lifetime extension of temporary created by aggregate initialization using a default member initializer (PR #87933)
https://github.com/yronglin updated https://github.com/llvm/llvm-project/pull/87933 >From 9fba6da7cb1ffbc7d46b69c6ac0cfd15a89c4b56 Mon Sep 17 00:00:00 2001 From: yronglin Date: Mon, 8 Apr 2024 01:38:23 +0800 Subject: [PATCH 1/2] [Clang] Support lifetime extension of temporary created by aggregate initialization using a default member initializer Signed-off-by: yronglin --- .../clang/Basic/DiagnosticSemaKinds.td| 6 --- clang/lib/Sema/SemaExpr.cpp | 16 clang/lib/Sema/SemaInit.cpp | 39 +-- .../Analysis/lifetime-extended-regions.cpp| 2 +- clang/test/CXX/drs/dr16xx.cpp | 2 - clang/test/CXX/drs/dr18xx.cpp | 5 +-- clang/test/CXX/special/class.temporary/p6.cpp | 20 ++ clang/test/SemaCXX/constexpr-default-arg.cpp | 4 +- clang/test/SemaCXX/eval-crashes.cpp | 6 +-- 9 files changed, 62 insertions(+), 38 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index a1dda2d2461c31..ba779e83d2afd4 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -10010,12 +10010,6 @@ def warn_new_dangling_initializer_list : Warning< "the allocated initializer list}0 " "will be destroyed at the end of the full-expression">, InGroup; -def warn_unsupported_lifetime_extension : Warning< - "lifetime extension of " - "%select{temporary|backing array of initializer list}0 created " - "by aggregate initialization using a default member initializer " - "is not yet supported; lifetime of %select{temporary|backing array}0 " - "will end at the end of the full-expression">, InGroup; // For non-floating point, expressions of the form x == x or x != x // should result in a warning, since these always evaluate to a constant. diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 8db4fffeecfe35..b2e0f2a2a60113 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -6338,10 +6338,9 @@ ExprResult Sema::BuildCXXDefaultArgExpr(SourceLocation CallLoc, Res = Immediate.TransformInitializer(Param->getInit(), /*NotCopy=*/false); }); - if (Res.isInvalid()) -return ExprError(); - Res = ConvertParamDefaultArgument(Param, Res.get(), -Res.get()->getBeginLoc()); + if (Res.isUsable()) +Res = ConvertParamDefaultArgument(Param, Res.get(), + Res.get()->getBeginLoc()); if (Res.isInvalid()) return ExprError(); Init = Res.get(); @@ -6377,7 +6376,7 @@ ExprResult Sema::BuildCXXDefaultInitExpr(SourceLocation Loc, FieldDecl *Field) { Expr *Init = nullptr; bool NestedDefaultChecking = isCheckingDefaultArgumentOrInitializer(); - + bool InLifetimeExtendingContext = isInLifetimeExtendingContext(); EnterExpressionEvaluationContext EvalContext( *this, ExpressionEvaluationContext::PotentiallyEvaluated, Field); @@ -6412,11 +6411,14 @@ ExprResult Sema::BuildCXXDefaultInitExpr(SourceLocation Loc, FieldDecl *Field) { ImmediateCallVisitor V(getASTContext()); if (!NestedDefaultChecking) V.TraverseDecl(Field); - if (V.HasImmediateCalls) { + if (V.HasImmediateCalls || InLifetimeExtendingContext) { ExprEvalContexts.back().DelayedDefaultInitializationContext = {Loc, Field, CurContext}; ExprEvalContexts.back().IsCurrentlyCheckingDefaultArgumentOrInitializer = NestedDefaultChecking; +// Pass down lifetime extending flag, and collect temporaries in +// CreateMaterializeTemporaryExpr when we rewrite the call argument. +keepInLifetimeExtendingContext(); EnsureImmediateInvocationInDefaultArgs Immediate(*this); ExprResult Res; @@ -6424,7 +6426,7 @@ ExprResult Sema::BuildCXXDefaultInitExpr(SourceLocation Loc, FieldDecl *Field) { Res = Immediate.TransformInitializer(Field->getInClassInitializer(), /*CXXDirectInit=*/false); }); -if (!Res.isInvalid()) +if (Res.isUsable()) Res = ConvertMemberDefaultInitExpression(Field, Res.get(), Loc); if (Res.isInvalid()) { Field->setInvalidDecl(); diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index a75e9925a43146..842412cd674d8c 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -710,6 +710,26 @@ void InitListChecker::FillInEmptyInitForField(unsigned Init, FieldDecl *Field, if (VerifyOnly) return; + // Enter a lifetime extension context, then we can support lifetime + // extension of temporary created by aggregate initialization using a + // default member initializer (DR1815 https://wg21.link/CWG1815). + // +
[clang] [Clang][CWG1815] Support lifetime extension of temporary created by aggregate initialization using a default member initializer (PR #87933)
https://github.com/yronglin updated https://github.com/llvm/llvm-project/pull/87933 >From 9fba6da7cb1ffbc7d46b69c6ac0cfd15a89c4b56 Mon Sep 17 00:00:00 2001 From: yronglin Date: Mon, 8 Apr 2024 01:38:23 +0800 Subject: [PATCH 1/2] [Clang] Support lifetime extension of temporary created by aggregate initialization using a default member initializer Signed-off-by: yronglin --- .../clang/Basic/DiagnosticSemaKinds.td| 6 --- clang/lib/Sema/SemaExpr.cpp | 16 clang/lib/Sema/SemaInit.cpp | 39 +-- .../Analysis/lifetime-extended-regions.cpp| 2 +- clang/test/CXX/drs/dr16xx.cpp | 2 - clang/test/CXX/drs/dr18xx.cpp | 5 +-- clang/test/CXX/special/class.temporary/p6.cpp | 20 ++ clang/test/SemaCXX/constexpr-default-arg.cpp | 4 +- clang/test/SemaCXX/eval-crashes.cpp | 6 +-- 9 files changed, 62 insertions(+), 38 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index a1dda2d2461c31..ba779e83d2afd4 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -10010,12 +10010,6 @@ def warn_new_dangling_initializer_list : Warning< "the allocated initializer list}0 " "will be destroyed at the end of the full-expression">, InGroup; -def warn_unsupported_lifetime_extension : Warning< - "lifetime extension of " - "%select{temporary|backing array of initializer list}0 created " - "by aggregate initialization using a default member initializer " - "is not yet supported; lifetime of %select{temporary|backing array}0 " - "will end at the end of the full-expression">, InGroup; // For non-floating point, expressions of the form x == x or x != x // should result in a warning, since these always evaluate to a constant. diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 8db4fffeecfe35..b2e0f2a2a60113 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -6338,10 +6338,9 @@ ExprResult Sema::BuildCXXDefaultArgExpr(SourceLocation CallLoc, Res = Immediate.TransformInitializer(Param->getInit(), /*NotCopy=*/false); }); - if (Res.isInvalid()) -return ExprError(); - Res = ConvertParamDefaultArgument(Param, Res.get(), -Res.get()->getBeginLoc()); + if (Res.isUsable()) +Res = ConvertParamDefaultArgument(Param, Res.get(), + Res.get()->getBeginLoc()); if (Res.isInvalid()) return ExprError(); Init = Res.get(); @@ -6377,7 +6376,7 @@ ExprResult Sema::BuildCXXDefaultInitExpr(SourceLocation Loc, FieldDecl *Field) { Expr *Init = nullptr; bool NestedDefaultChecking = isCheckingDefaultArgumentOrInitializer(); - + bool InLifetimeExtendingContext = isInLifetimeExtendingContext(); EnterExpressionEvaluationContext EvalContext( *this, ExpressionEvaluationContext::PotentiallyEvaluated, Field); @@ -6412,11 +6411,14 @@ ExprResult Sema::BuildCXXDefaultInitExpr(SourceLocation Loc, FieldDecl *Field) { ImmediateCallVisitor V(getASTContext()); if (!NestedDefaultChecking) V.TraverseDecl(Field); - if (V.HasImmediateCalls) { + if (V.HasImmediateCalls || InLifetimeExtendingContext) { ExprEvalContexts.back().DelayedDefaultInitializationContext = {Loc, Field, CurContext}; ExprEvalContexts.back().IsCurrentlyCheckingDefaultArgumentOrInitializer = NestedDefaultChecking; +// Pass down lifetime extending flag, and collect temporaries in +// CreateMaterializeTemporaryExpr when we rewrite the call argument. +keepInLifetimeExtendingContext(); EnsureImmediateInvocationInDefaultArgs Immediate(*this); ExprResult Res; @@ -6424,7 +6426,7 @@ ExprResult Sema::BuildCXXDefaultInitExpr(SourceLocation Loc, FieldDecl *Field) { Res = Immediate.TransformInitializer(Field->getInClassInitializer(), /*CXXDirectInit=*/false); }); -if (!Res.isInvalid()) +if (Res.isUsable()) Res = ConvertMemberDefaultInitExpression(Field, Res.get(), Loc); if (Res.isInvalid()) { Field->setInvalidDecl(); diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index a75e9925a43146..842412cd674d8c 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -710,6 +710,26 @@ void InitListChecker::FillInEmptyInitForField(unsigned Init, FieldDecl *Field, if (VerifyOnly) return; + // Enter a lifetime extension context, then we can support lifetime + // extension of temporary created by aggregate initialization using a + // default member initializer (DR1815 https://wg21.link/CWG1815). + // +
[clang] [Clang][CWG1815] Support lifetime extension of temporary created by aggregate initialization using a default member initializer (PR #87933)
https://github.com/yronglin edited https://github.com/llvm/llvm-project/pull/87933 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][CWG1815] Support lifetime extension of temporary created by aggregate initialization using a default member initializer (PR #87933)
yronglin wrote: friendly ping~ https://github.com/llvm/llvm-project/pull/87933 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][CWG1815] Support lifetime extension of temporary created by aggregate initialization using a default member initializer (PR #87933)
https://github.com/yronglin edited https://github.com/llvm/llvm-project/pull/87933 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits