-
Notifications
You must be signed in to change notification settings - Fork 14.3k
Reapply "[Clang][CWG1815] Support lifetime extension of temporary created by aggregate initialization using a default member initializer" #108039
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
…ated by aggregate initialization using a default member initializer" Signed-off-by: yronglin <[email protected]>
…text Signed-off-by: yronglin <[email protected]>
@llvm/pr-subscribers-clang Author: None (yronglin) ChangesThe PR reapply #97308. Fix crash that introduced in #97308. In Patch is 29.68 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/108039.diff 21 Files Affected:
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 250821a9f9c45c..07f3544e2324e3 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -108,6 +108,9 @@ C++ Language Changes
- Allow single element access of GCC vector/ext_vector_type object to be
constant expression. Supports the `V.xyzw` syntax and other tidbits
as seen in OpenCL. Selecting multiple elements is left as a future work.
+- Implement `CWG1815 <https://wg21.link/CWG1815>`_. Support lifetime extension
+ of temporary created by aggregate initialization using a default member
+ initializer.
- Accept C++26 user-defined ``static_assert`` messages in C++11 as an extension.
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 58819a64813fce..4609d2ec2b7209 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -10159,13 +10159,6 @@ def warn_dangling_pointer_assignment : Warning<
"will be destroyed at the end of the full-expression">,
InGroup<DanglingAssignment>;
-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<Dangling>;
-
// 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.
// Array comparisons have similar warnings
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 68c782a15c6f1b..ac4c11964b126f 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -6403,6 +6403,9 @@ class Sema final : public SemaBase {
/// example, in a for-range initializer).
bool InLifetimeExtendingContext = false;
+ /// Whether we should rebuild CXXDefaultArgExpr and CXXDefaultInitExpr.
+ bool RebuildDefaultArgOrDefaultInit = false;
+
// When evaluating immediate functions in the initializer of a default
// argument or default member initializer, this is the declaration whose
// default initializer is being evaluated and the location of the call
@@ -7810,9 +7813,11 @@ class Sema final : public SemaBase {
}
bool isInLifetimeExtendingContext() const {
- assert(!ExprEvalContexts.empty() &&
- "Must be in an expression evaluation context");
- return ExprEvalContexts.back().InLifetimeExtendingContext;
+ return currentEvaluationContext().InLifetimeExtendingContext;
+ }
+
+ bool needRebuildDefaultArgOrInit() const {
+ return currentEvaluationContext().RebuildDefaultArgOrDefaultInit;
}
bool isCheckingDefaultArgumentOrInitializer() const {
@@ -7854,18 +7859,6 @@ class Sema final : public SemaBase {
return Res;
}
- /// keepInLifetimeExtendingContext - Pull down InLifetimeExtendingContext
- /// flag from previous context.
- void keepInLifetimeExtendingContext() {
- if (ExprEvalContexts.size() > 2 &&
- parentEvaluationContext().InLifetimeExtendingContext) {
- auto &LastRecord = ExprEvalContexts.back();
- auto &PrevRecord = parentEvaluationContext();
- LastRecord.InLifetimeExtendingContext =
- PrevRecord.InLifetimeExtendingContext;
- }
- }
-
DefaultedComparisonKind getDefaultedComparisonKind(const FunctionDecl *FD) {
return getDefaultedFunctionKind(FD).asComparison();
}
diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp
index 61a1ca3da6bca0..1f56884be392d6 100644
--- a/clang/lib/Parse/ParseDecl.cpp
+++ b/clang/lib/Parse/ParseDecl.cpp
@@ -2509,8 +2509,9 @@ Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS,
// P2718R0 - Lifetime extension in range-based for loops.
if (getLangOpts().CPlusPlus23) {
- auto &LastRecord = Actions.ExprEvalContexts.back();
+ auto &LastRecord = Actions.currentEvaluationContext();
LastRecord.InLifetimeExtendingContext = true;
+ LastRecord.RebuildDefaultArgOrDefaultInit = true;
}
if (getLangOpts().OpenMP)
diff --git a/clang/lib/Sema/CheckExprLifetime.cpp b/clang/lib/Sema/CheckExprLifetime.cpp
index f1507ebb9a5068..f62e18543851c1 100644
--- a/clang/lib/Sema/CheckExprLifetime.cpp
+++ b/clang/lib/Sema/CheckExprLifetime.cpp
@@ -871,11 +871,6 @@ static void visitLocalsRetainedByInitializer(IndirectLocalPath &Path,
enum PathLifetimeKind {
/// Lifetime-extend along this path.
Extend,
- /// We should lifetime-extend, but we don't because (due to technical
- /// limitations) we can't. This happens for default member initializers,
- /// which we don't clone for every use, so we don't have a unique
- /// MaterializeTemporaryExpr to update.
- ShouldExtend,
/// Do not lifetime extend along this path.
NoExtend
};
@@ -887,7 +882,7 @@ shouldLifetimeExtendThroughPath(const IndirectLocalPath &Path) {
PathLifetimeKind Kind = PathLifetimeKind::Extend;
for (auto Elem : Path) {
if (Elem.Kind == IndirectLocalPathEntry::DefaultInit)
- Kind = PathLifetimeKind::ShouldExtend;
+ return PathLifetimeKind::Extend;
else if (Elem.Kind != IndirectLocalPathEntry::LambdaCaptureInit)
return PathLifetimeKind::NoExtend;
}
@@ -1034,17 +1029,6 @@ static void checkExprLifetimeImpl(Sema &SemaRef,
// Also visit the temporaries lifetime-extended by this initializer.
return true;
- case PathLifetimeKind::ShouldExtend:
- // We're supposed to lifetime-extend the temporary along this path (per
- // the resolution of DR1815), but we don't support that yet.
- //
- // FIXME: Properly handle this situation. Perhaps the easiest approach
- // would be to clone the initializer expression on each use that would
- // lifetime extend its temporaries.
- SemaRef.Diag(DiagLoc, diag::warn_unsupported_lifetime_extension)
- << RK << DiagRange;
- break;
-
case PathLifetimeKind::NoExtend:
// If the path goes through the initialization of a variable or field,
// it can't possibly reach a temporary created in this full-expression.
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 32dac4440fb82a..30e5fe4543bcaa 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -5429,6 +5429,8 @@ struct EnsureImmediateInvocationInDefaultArgs
EnsureImmediateInvocationInDefaultArgs(Sema &SemaRef)
: TreeTransform(SemaRef) {}
+ bool AlwaysRebuild() { return true; }
+
// Lambda can only have immediate invocations in the default
// args of their parameters, which is transformed upon calling the closure.
// The body is not a subexpression, so we have nothing to do.
@@ -5470,7 +5472,7 @@ ExprResult Sema::BuildCXXDefaultArgExpr(SourceLocation CallLoc,
assert(Param->hasDefaultArg() && "can't build nonexistent default arg");
bool NestedDefaultChecking = isCheckingDefaultArgumentOrInitializer();
- bool InLifetimeExtendingContext = isInLifetimeExtendingContext();
+ bool NeedRebuild = needRebuildDefaultArgOrInit();
std::optional<ExpressionEvaluationContextRecord::InitializationContext>
InitializationContext =
OutermostDeclarationWithDelayedImmediateInvocations();
@@ -5506,13 +5508,15 @@ ExprResult Sema::BuildCXXDefaultArgExpr(SourceLocation CallLoc,
// Rewrite the call argument that was created from the corresponding
// parameter's default argument.
- if (V.HasImmediateCalls || InLifetimeExtendingContext) {
+ if (V.HasImmediateCalls ||
+ (NeedRebuild && isa_and_present<ExprWithCleanups>(Param->getInit()))) {
if (V.HasImmediateCalls)
ExprEvalContexts.back().DelayedDefaultInitializationContext = {
CallLoc, Param, CurContext};
// Pass down lifetime extending flag, and collect temporaries in
// CreateMaterializeTemporaryExpr when we rewrite the call argument.
- keepInLifetimeExtendingContext();
+ currentEvaluationContext().InLifetimeExtendingContext =
+ parentEvaluationContext().InLifetimeExtendingContext;
EnsureImmediateInvocationInDefaultArgs Immediate(*this);
ExprResult Res;
runWithSufficientStackSpace(CallLoc, [&] {
@@ -5558,7 +5562,7 @@ ExprResult Sema::BuildCXXDefaultInitExpr(SourceLocation Loc, FieldDecl *Field) {
Expr *Init = nullptr;
bool NestedDefaultChecking = isCheckingDefaultArgumentOrInitializer();
-
+ bool NeedRebuild = needRebuildDefaultArgOrInit();
EnterExpressionEvaluationContext EvalContext(
*this, ExpressionEvaluationContext::PotentiallyEvaluated, Field);
@@ -5593,12 +5597,27 @@ ExprResult Sema::BuildCXXDefaultInitExpr(SourceLocation Loc, FieldDecl *Field) {
ImmediateCallVisitor V(getASTContext());
if (!NestedDefaultChecking)
V.TraverseDecl(Field);
- if (V.HasImmediateCalls) {
+
+ // CWG1815
+ // Support lifetime extension of temporary created by aggregate
+ // initialization using a default member initializer. We should rebuild
+ // the initializer in a lifetime extension context 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.
+ bool ContainsAnyTemporaries =
+ isa_and_present<ExprWithCleanups>(Field->getInClassInitializer());
+ if (Field->getInClassInitializer() &&
+ !Field->getInClassInitializer()->containsErrors() &&
+ (V.HasImmediateCalls || (NeedRebuild && ContainsAnyTemporaries))) {
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.
+ currentEvaluationContext().InLifetimeExtendingContext =
+ parentEvaluationContext().InLifetimeExtendingContext;
EnsureImmediateInvocationInDefaultArgs Immediate(*this);
ExprResult Res;
runWithSufficientStackSpace(Loc, [&] {
@@ -17675,11 +17694,10 @@ void Sema::PopExpressionEvaluationContext() {
// Append the collected materialized temporaries into previous context before
// exit if the previous also is a lifetime extending context.
- auto &PrevRecord = parentEvaluationContext();
if (getLangOpts().CPlusPlus23 && Rec.InLifetimeExtendingContext &&
- PrevRecord.InLifetimeExtendingContext &&
+ parentEvaluationContext().InLifetimeExtendingContext &&
!Rec.ForRangeLifetimeExtendTemps.empty()) {
- PrevRecord.ForRangeLifetimeExtendTemps.append(
+ parentEvaluationContext().ForRangeLifetimeExtendTemps.append(
Rec.ForRangeLifetimeExtendTemps);
}
diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index 14feafd1e6b17f..e086c601107041 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -1540,9 +1540,6 @@ Sema::BuildCXXTypeConstructExpr(TypeSourceInfo *TInfo,
bool ListInitialization) {
QualType Ty = TInfo->getType();
SourceLocation TyBeginLoc = TInfo->getTypeLoc().getBeginLoc();
-
- assert((!ListInitialization || Exprs.size() == 1) &&
- "List initialization must have exactly one expression.");
SourceRange FullRange = SourceRange(TyBeginLoc, RParenOrBraceLoc);
InitializedEntity Entity =
diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp
index 7dc17187524621..d21b8cb8c04e63 100644
--- a/clang/lib/Sema/SemaInit.cpp
+++ b/clang/lib/Sema/SemaInit.cpp
@@ -750,8 +750,21 @@ void InitListChecker::FillInEmptyInitForField(unsigned Init, FieldDecl *Field,
if (Field->hasInClassInitializer()) {
if (VerifyOnly)
return;
-
- ExprResult DIE = SemaRef.BuildCXXDefaultInitExpr(Loc, Field);
+ ExprResult DIE;
+ {
+ // Enter a default initializer rebuild context, then we can support
+ // lifetime extension of temporary created by aggregate initialization
+ // using a default member initializer.
+ // CWG1815 (https://wg21.link/CWG1815).
+ EnterExpressionEvaluationContext RebuildDefaultInit(
+ SemaRef, Sema::ExpressionEvaluationContext::PotentiallyEvaluated);
+ SemaRef.currentEvaluationContext().RebuildDefaultArgOrDefaultInit =
+ true;
+ SemaRef.currentEvaluationContext().DelayedDefaultInitializationContext =
+ SemaRef.parentEvaluationContext()
+ .DelayedDefaultInitializationContext;
+ DIE = SemaRef.BuildCXXDefaultInitExpr(Loc, Field);
+ }
if (DIE.isInvalid()) {
hadError = true;
return;
@@ -7521,10 +7534,8 @@ Sema::CreateMaterializeTemporaryExpr(QualType T, Expr *Temporary,
// are done in both CreateMaterializeTemporaryExpr and MaybeBindToTemporary,
// but there may be a chance to merge them.
Cleanup.setExprNeedsCleanups(false);
- if (isInLifetimeExtendingContext()) {
- auto &Record = ExprEvalContexts.back();
- Record.ForRangeLifetimeExtendTemps.push_back(MTE);
- }
+ if (isInLifetimeExtendingContext())
+ currentEvaluationContext().ForRangeLifetimeExtendTemps.push_back(MTE);
return MTE;
}
diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 6df412cbb09c83..bb311e38409280 100644
--- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -5481,7 +5481,10 @@ void Sema::InstantiateVariableInitializer(
EnterExpressionEvaluationContext Evaluated(
*this, Sema::ExpressionEvaluationContext::PotentiallyEvaluated, Var);
- keepInLifetimeExtendingContext();
+ currentEvaluationContext().InLifetimeExtendingContext =
+ parentEvaluationContext().InLifetimeExtendingContext;
+ currentEvaluationContext().RebuildDefaultArgOrDefaultInit =
+ parentEvaluationContext().RebuildDefaultArgOrDefaultInit;
// Instantiate the initializer.
ExprResult Init;
diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index 0daf620b4123e4..4bbc024587915c 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -4254,7 +4254,10 @@ ExprResult TreeTransform<Derived>::TransformInitializer(Expr *Init,
getSema(), EnterExpressionEvaluationContext::InitList,
Construct->isListInitialization());
- getSema().keepInLifetimeExtendingContext();
+ getSema().currentEvaluationContext().InLifetimeExtendingContext =
+ getSema().parentEvaluationContext().InLifetimeExtendingContext;
+ getSema().currentEvaluationContext().RebuildDefaultArgOrDefaultInit =
+ getSema().parentEvaluationContext().RebuildDefaultArgOrDefaultInit;
SmallVector<Expr*, 8> NewArgs;
bool ArgChanged = false;
if (getDerived().TransformExprs(Construct->getArgs(), Construct->getNumArgs(),
@@ -8924,8 +8927,9 @@ TreeTransform<Derived>::TransformCXXForRangeStmt(CXXForRangeStmt *S) {
// P2718R0 - Lifetime extension in range-based for loops.
if (getSema().getLangOpts().CPlusPlus23) {
- auto &LastRecord = getSema().ExprEvalContexts.back();
+ auto &LastRecord = getSema().currentEvaluationContext();
LastRecord.InLifetimeExtendingContext = true;
+ LastRecord.RebuildDefaultArgOrDefaultInit = true;
}
StmtResult Init =
S->getInit() ? getDerived().TransformStmt(S->getInit()) : StmtResult();
@@ -14443,6 +14447,13 @@ TreeTransform<Derived>::TransformCXXTemporaryObjectExpr(
if (TransformExprs(E->getArgs(), E->getNumArgs(), true, Args,
&ArgumentChanged))
return ExprError();
+
+ if (E->isListInitialization() && !E->isStdInitListInitialization()) {
+ ExprResult Res = RebuildInitList(E->getBeginLoc(), Args, E->getEndLoc());
+ if (Res.isInvalid())
+ return ExprError();
+ Args = {Res.get()};
+ }
}
if (!getDerived().AlwaysRebuild() &&
@@ -14454,12 +14465,9 @@ TreeTransform<Derived>::TransformCXXTemporaryObjectExpr(
return SemaRef.MaybeBindToTemporary(E);
}
- // FIXME: We should just pass E->isListInitialization(), but we're not
- // prepared to handle list-initialization without a child InitListExpr.
SourceLocation LParenLoc = T->getTypeLoc().getEndLoc();
return getDerived().RebuildCXXTemporaryObjectExpr(
- T, LParenLoc, Args, E->getEndLoc(),
- /*ListInitialization=*/LParenLoc.isInvalid());
+ T, LParenLoc, Args, E->getEndLoc(), E->isListInitialization());
}
template<typename Derived>
diff --git a/clang/test/AST/ast-dump-default-init-json.cpp b/clang/test/AST/ast-dump-default-init-json.cpp
index 1058b4e3ea4d93..f4949a9c9eedf4 100644
--- a/clang/test/AST/ast-dump-default-init-json.cpp
+++ b/clang/test/AST/ast-dump-default-init-json.cpp
@@ -789,10 +789,10 @@ void test() {
// CHECK-NEXT: "valueCategory": "lvalue",
// CHECK-NEXT: "extendingDecl": {
// CHECK-NEXT: "id": "0x{{.*}}",
-// CHECK-NEXT: "kind": "FieldDecl",
-// CHECK-NEXT: "name": "a",
+// CHECK-NEXT: "kind": "VarDecl",
+// CHECK-NEXT: "name": "b",
// CHECK-NEXT: "type": {
-// CHECK-NEXT: "qualType": "const A &"
+// CHECK-NEXT: "qualType": "B"
// CHECK-NEXT: }
// CHECK-NEXT: },
// CHECK-NEXT: "storageDuration": "automatic",
diff --git a/clang/test/AST/ast-dump-default-init.cpp b/clang/test/AST/ast-dump-default-init.cpp
index 15b29f04bf21bf..26864fbf15424d 100644
--- a/clang/test/AST/ast-dump-default-init.cpp
+++ b/clang/test/AST/ast-dump-default-init.cpp
@@ -13,7 +13,7 @@ void test() {
}
// CHECK: -CXXDefaultInitExpr 0x{{[^ ]*}} <{{.*}}> 'const A' lvalue has rewritten init
// CHECK-NEXT: `-ExprWithCleanups 0x{{[^ ]*}} <{{.*}}> 'const A' lvalue
-// CHECK-NEXT: `-MaterializeTemporaryExpr 0x{{[^ ]*}} <{{.*}}> 'const A' lvalue extended by Field 0x{{[^ ]*}} 'a' 'const A &'
+// CHECK-NEXT: `-MaterializeTemporaryExpr 0x{{[^ ]*}} <{{.*}}> 'const A' lvalue extended by Var 0x{{[^ ]*}} 'b' 'B'
// CHECK-NEXT: `-ImplicitCastExpr 0x{{[^ ]*}} <{{.*}}> 'const A' <NoOp>
// CHECK-NEXT: `-CXXFunctionalCastExpr 0x{{[^ ]*}} <{{.*}}> 'A' functional cast to A <NoOp>
// CHECK-NEXT: `-InitListExpr 0x{{[^ ]*}} <{{.*}}> 'A'
diff --git a/clang/test/Analysis/lifetime-extended-regions.cpp b/clang/test/Analysis/lifetime-extended-regions.cpp
index 4e98bd4b0403eb..4458ad294af7cb 100644
--- a/clang/test/Analysis/lifetime-extended-regions.cpp
+++ b/clang/test/Analysis/lifetime-extended-regions.cpp
@@ -120,10 +120,11 @@ void aggregateWithReferences() {
clang_analyzer_dump(viaReference); // expected-warning-re {{&lifetime_extended_object{RefAggregate, viaReference, S{{[0-9]+}}} }}
clang_analyzer_dump(viaReference.rx); // expected-warning-re {{&lifetime_extended_object{int, viaReference, S{{[0-9]+}}} }}
clang_analyzer_dump(viaReference.ry); // expected-warning-re {{&lifetime_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`)
- RefAggregate defaultInitExtended{i}; // clang-bug does not extend `Composite`
+
+ // FIXME: clang currently support extending lifetime of object bound to reference members of aggregates,
+ // that are created from default member initializer. But CFG and ExprEngine need to be updated to address this change.
+ // The following expect warning: {{&lifetime_extended_object{Composite, defaultInitExtended, S{{[0-9]+}}} }}
+ RefAggregate defaultInitExtended{i};
clang_analyzer_dump(defaultInitExtended.ry); // expected-warning {{Unknown }}
}
diff --git a/clang/test/CXX/drs/cwg16xx.cpp b/clang/test/CXX/drs/cwg16xx.cpp
index cf6b45ceabf2cc..95e241f0d03e9b 100644
--- a/clang/test/CXX/drs/cwg...
[truncated]
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
// that are created from default member initializer (see `warn_unsupported_lifetime_extension` from `-Wdangling`) | ||
RefAggregate defaultInitExtended{i}; // clang-bug does not extend `Composite` | ||
|
||
// FIXME: clang currently support extending lifetime of object bound to reference members of aggregates, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please create an issue for this if it doesn't exist.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This because we need to add support in Static Analyzer. I once had a separate PR(#91879) to implement this feature for StaticAnalyzer, but because the CWG1815 implementation was reverted, that PR was also reverted. I'll create an issue for this.
Thanks for your review! @cor3ntin @erichkeane |
Signed-off-by: yronglin <[email protected]>
#86960) Depends on [CWG1815](#108039). Fixes #85613. In [[Clang] Implement P2718R0 "Lifetime extension in range-based for loops"](#76361), we've not implement the lifetime extensions for the temporaries which in `CXXDefaultInitExpr`. As the confirmation in #85613, we should extend lifetime for that. To avoid modifying current CodeGen rules, in a lifetime extension context, the cleanup of `CXXDefaultInitExpr` was ignored. --------- Signed-off-by: yronglin <[email protected]>
llvm#86960) Depends on [CWG1815](llvm#108039). Fixes llvm#85613. In [[Clang] Implement P2718R0 "Lifetime extension in range-based for loops"](llvm#76361), we've not implement the lifetime extensions for the temporaries which in `CXXDefaultInitExpr`. As the confirmation in llvm#85613, we should extend lifetime for that. To avoid modifying current CodeGen rules, in a lifetime extension context, the cleanup of `CXXDefaultInitExpr` was ignored. --------- Signed-off-by: yronglin <[email protected]>
The PR reapply #97308.
Implement CWG1815: Support lifetime extension of temporary created by aggregate initialization using a default member initializer.
Fix crash that introduced in Reapply "[Clang][CWG1815] Support lifetime extension of temporary created by aggregate initialization using a default member initializer" #97308. In
InitListChecker::FillInEmptyInitForField
, when we enter rebuild-default-init context, we copy all the contents of the parent context to the current context, which will cause theMaybeODRUseExprs
to be lost. But we don't need to copy the entire context, only theDelayedDefaultInitializationContext
was required, which is used to buildSourceLocExpr
, etc.