@@ -5429,6 +5429,8 @@ struct EnsureImmediateInvocationInDefaultArgs
5429
5429
EnsureImmediateInvocationInDefaultArgs(Sema &SemaRef)
5430
5430
: TreeTransform(SemaRef) {}
5431
5431
5432
+ bool AlwaysRebuild() { return true; }
5433
+
5432
5434
// Lambda can only have immediate invocations in the default
5433
5435
// args of their parameters, which is transformed upon calling the closure.
5434
5436
// The body is not a subexpression, so we have nothing to do.
@@ -5470,7 +5472,7 @@ ExprResult Sema::BuildCXXDefaultArgExpr(SourceLocation CallLoc,
5470
5472
assert(Param->hasDefaultArg() && "can't build nonexistent default arg");
5471
5473
5472
5474
bool NestedDefaultChecking = isCheckingDefaultArgumentOrInitializer();
5473
- bool InLifetimeExtendingContext = isInLifetimeExtendingContext ();
5475
+ bool NeedRebuild = needRebuildDefaultArgOrInit ();
5474
5476
std::optional<ExpressionEvaluationContextRecord::InitializationContext>
5475
5477
InitializationContext =
5476
5478
OutermostDeclarationWithDelayedImmediateInvocations();
@@ -5506,13 +5508,15 @@ ExprResult Sema::BuildCXXDefaultArgExpr(SourceLocation CallLoc,
5506
5508
5507
5509
// Rewrite the call argument that was created from the corresponding
5508
5510
// parameter's default argument.
5509
- if (V.HasImmediateCalls || InLifetimeExtendingContext) {
5511
+ if (V.HasImmediateCalls ||
5512
+ (NeedRebuild && isa_and_present<ExprWithCleanups>(Param->getInit()))) {
5510
5513
if (V.HasImmediateCalls)
5511
5514
ExprEvalContexts.back().DelayedDefaultInitializationContext = {
5512
5515
CallLoc, Param, CurContext};
5513
5516
// Pass down lifetime extending flag, and collect temporaries in
5514
5517
// CreateMaterializeTemporaryExpr when we rewrite the call argument.
5515
- keepInLifetimeExtendingContext();
5518
+ currentEvaluationContext().InLifetimeExtendingContext =
5519
+ parentEvaluationContext().InLifetimeExtendingContext;
5516
5520
EnsureImmediateInvocationInDefaultArgs Immediate(*this);
5517
5521
ExprResult Res;
5518
5522
runWithSufficientStackSpace(CallLoc, [&] {
@@ -5558,7 +5562,7 @@ ExprResult Sema::BuildCXXDefaultInitExpr(SourceLocation Loc, FieldDecl *Field) {
5558
5562
Expr *Init = nullptr;
5559
5563
5560
5564
bool NestedDefaultChecking = isCheckingDefaultArgumentOrInitializer();
5561
-
5565
+ bool NeedRebuild = needRebuildDefaultArgOrInit();
5562
5566
EnterExpressionEvaluationContext EvalContext(
5563
5567
*this, ExpressionEvaluationContext::PotentiallyEvaluated, Field);
5564
5568
@@ -5593,12 +5597,27 @@ ExprResult Sema::BuildCXXDefaultInitExpr(SourceLocation Loc, FieldDecl *Field) {
5593
5597
ImmediateCallVisitor V(getASTContext());
5594
5598
if (!NestedDefaultChecking)
5595
5599
V.TraverseDecl(Field);
5596
- if (V.HasImmediateCalls) {
5600
+
5601
+ // CWG1815
5602
+ // Support lifetime extension of temporary created by aggregate
5603
+ // initialization using a default member initializer. We should rebuild
5604
+ // the initializer in a lifetime extension context if the initializer
5605
+ // expression is an ExprWithCleanups. Then make sure the normal lifetime
5606
+ // extension code recurses into the default initializer and does lifetime
5607
+ // extension when warranted.
5608
+ bool ContainsAnyTemporaries =
5609
+ isa_and_present<ExprWithCleanups>(Field->getInClassInitializer());
5610
+ if (Field->getInClassInitializer() &&
5611
+ !Field->getInClassInitializer()->containsErrors() &&
5612
+ (V.HasImmediateCalls || (NeedRebuild && ContainsAnyTemporaries))) {
5597
5613
ExprEvalContexts.back().DelayedDefaultInitializationContext = {Loc, Field,
5598
5614
CurContext};
5599
5615
ExprEvalContexts.back().IsCurrentlyCheckingDefaultArgumentOrInitializer =
5600
5616
NestedDefaultChecking;
5601
-
5617
+ // Pass down lifetime extending flag, and collect temporaries in
5618
+ // CreateMaterializeTemporaryExpr when we rewrite the call argument.
5619
+ currentEvaluationContext().InLifetimeExtendingContext =
5620
+ parentEvaluationContext().InLifetimeExtendingContext;
5602
5621
EnsureImmediateInvocationInDefaultArgs Immediate(*this);
5603
5622
ExprResult Res;
5604
5623
runWithSufficientStackSpace(Loc, [&] {
@@ -17675,11 +17694,10 @@ void Sema::PopExpressionEvaluationContext() {
17675
17694
17676
17695
// Append the collected materialized temporaries into previous context before
17677
17696
// exit if the previous also is a lifetime extending context.
17678
- auto &PrevRecord = parentEvaluationContext();
17679
17697
if (getLangOpts().CPlusPlus23 && Rec.InLifetimeExtendingContext &&
17680
- PrevRecord .InLifetimeExtendingContext &&
17698
+ parentEvaluationContext() .InLifetimeExtendingContext &&
17681
17699
!Rec.ForRangeLifetimeExtendTemps.empty()) {
17682
- PrevRecord .ForRangeLifetimeExtendTemps.append(
17700
+ parentEvaluationContext() .ForRangeLifetimeExtendTemps.append(
17683
17701
Rec.ForRangeLifetimeExtendTemps);
17684
17702
}
17685
17703
0 commit comments