@@ -5429,6 +5429,8 @@ struct EnsureImmediateInvocationInDefaultArgs
54295429 EnsureImmediateInvocationInDefaultArgs(Sema &SemaRef)
54305430 : TreeTransform(SemaRef) {}
54315431
5432+ bool AlwaysRebuild() { return true; }
5433+
54325434 // Lambda can only have immediate invocations in the default
54335435 // args of their parameters, which is transformed upon calling the closure.
54345436 // The body is not a subexpression, so we have nothing to do.
@@ -5470,7 +5472,7 @@ ExprResult Sema::BuildCXXDefaultArgExpr(SourceLocation CallLoc,
54705472 assert(Param->hasDefaultArg() && "can't build nonexistent default arg");
54715473
54725474 bool NestedDefaultChecking = isCheckingDefaultArgumentOrInitializer();
5473- bool InLifetimeExtendingContext = isInLifetimeExtendingContext ();
5475+ bool NeedRebuild = needsRebuildOfDefaultArgOrInit ();
54745476 std::optional<ExpressionEvaluationContextRecord::InitializationContext>
54755477 InitializationContext =
54765478 OutermostDeclarationWithDelayedImmediateInvocations();
@@ -5506,13 +5508,15 @@ ExprResult Sema::BuildCXXDefaultArgExpr(SourceLocation CallLoc,
55065508
55075509 // Rewrite the call argument that was created from the corresponding
55085510 // parameter's default argument.
5509- if (V.HasImmediateCalls || InLifetimeExtendingContext) {
5511+ if (V.HasImmediateCalls ||
5512+ (NeedRebuild && isa_and_present<ExprWithCleanups>(Param->getInit()))) {
55105513 if (V.HasImmediateCalls)
55115514 ExprEvalContexts.back().DelayedDefaultInitializationContext = {
55125515 CallLoc, Param, CurContext};
55135516 // Pass down lifetime extending flag, and collect temporaries in
55145517 // CreateMaterializeTemporaryExpr when we rewrite the call argument.
5515- keepInLifetimeExtendingContext();
5518+ currentEvaluationContext().InLifetimeExtendingContext =
5519+ parentEvaluationContext().InLifetimeExtendingContext;
55165520 EnsureImmediateInvocationInDefaultArgs Immediate(*this);
55175521 ExprResult Res;
55185522 runWithSufficientStackSpace(CallLoc, [&] {
@@ -5558,7 +5562,7 @@ ExprResult Sema::BuildCXXDefaultInitExpr(SourceLocation Loc, FieldDecl *Field) {
55585562 Expr *Init = nullptr;
55595563
55605564 bool NestedDefaultChecking = isCheckingDefaultArgumentOrInitializer();
5561-
5565+ bool NeedRebuild = needsRebuildOfDefaultArgOrInit();
55625566 EnterExpressionEvaluationContext EvalContext(
55635567 *this, ExpressionEvaluationContext::PotentiallyEvaluated, Field);
55645568
@@ -5593,12 +5597,27 @@ ExprResult Sema::BuildCXXDefaultInitExpr(SourceLocation Loc, FieldDecl *Field) {
55935597 ImmediateCallVisitor V(getASTContext());
55945598 if (!NestedDefaultChecking)
55955599 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))) {
55975613 ExprEvalContexts.back().DelayedDefaultInitializationContext = {Loc, Field,
55985614 CurContext};
55995615 ExprEvalContexts.back().IsCurrentlyCheckingDefaultArgumentOrInitializer =
56005616 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;
56025621 EnsureImmediateInvocationInDefaultArgs Immediate(*this);
56035622 ExprResult Res;
56045623 runWithSufficientStackSpace(Loc, [&] {
@@ -17675,11 +17694,10 @@ void Sema::PopExpressionEvaluationContext() {
1767517694
1767617695 // Append the collected materialized temporaries into previous context before
1767717696 // exit if the previous also is a lifetime extending context.
17678- auto &PrevRecord = parentEvaluationContext();
1767917697 if (getLangOpts().CPlusPlus23 && Rec.InLifetimeExtendingContext &&
17680- PrevRecord .InLifetimeExtendingContext &&
17698+ parentEvaluationContext() .InLifetimeExtendingContext &&
1768117699 !Rec.ForRangeLifetimeExtendTemps.empty()) {
17682- PrevRecord .ForRangeLifetimeExtendTemps.append(
17700+ parentEvaluationContext() .ForRangeLifetimeExtendTemps.append(
1768317701 Rec.ForRangeLifetimeExtendTemps);
1768417702 }
1768517703
0 commit comments