@@ -1342,6 +1342,12 @@ class Sema final {
13421342 /// context not already known to be immediately invoked.
13431343 llvm::SmallPtrSet<DeclRefExpr *, 4> ReferenceToConsteval;
13441344
1345+ /// P2718R0 - Lifetime extension in range-based for loops.
1346+ /// MaterializeTemporaryExprs in for-range-init expressions which need to
1347+ /// extend lifetime. Add MaterializeTemporaryExpr* if the value of
1348+ /// InLifetimeExtendingContext is true.
1349+ SmallVector<MaterializeTemporaryExpr *, 8> ForRangeLifetimeExtendTemps;
1350+
13451351 /// \brief Describes whether we are in an expression constext which we have
13461352 /// to handle differently.
13471353 enum ExpressionKind {
@@ -1361,6 +1367,39 @@ class Sema final {
13611367 // VLAs).
13621368 bool InConditionallyConstantEvaluateContext = false;
13631369
1370+ /// Whether we are currently in a context in which all temporaries must be
1371+ /// lifetime-extended, even if they're not bound to a reference (for
1372+ /// example, in a for-range initializer).
1373+ bool InLifetimeExtendingContext = false;
1374+
1375+ /// Whether we are currently in a context in which all temporaries must be
1376+ /// materialized.
1377+ ///
1378+ /// [class.temporary]/p2:
1379+ /// The materialization of a temporary object is generally delayed as long
1380+ /// as possible in order to avoid creating unnecessary temporary objects.
1381+ ///
1382+ /// Temporary objects are materialized:
1383+ /// (2.1) when binding a reference to a prvalue ([dcl.init.ref],
1384+ /// [expr.type.conv], [expr.dynamic.cast], [expr.static.cast],
1385+ /// [expr.const.cast], [expr.cast]),
1386+ ///
1387+ /// (2.2) when performing member access on a class prvalue ([expr.ref],
1388+ /// [expr.mptr.oper]),
1389+ ///
1390+ /// (2.3) when performing an array-to-pointer conversion or subscripting
1391+ /// on an array prvalue ([conv.array], [expr.sub]),
1392+ ///
1393+ /// (2.4) when initializing an object of type
1394+ /// std::initializer_list<T> from a braced-init-list
1395+ /// ([dcl.init.list]),
1396+ ///
1397+ /// (2.5) for certain unevaluated operands ([expr.typeid], [expr.sizeof])
1398+ ///
1399+ /// (2.6) when a prvalue that has type other than cv void appears as a
1400+ /// discarded-value expression ([expr.context]).
1401+ bool InMaterializeTemporaryObjectContext = false;
1402+
13641403 // When evaluating immediate functions in the initializer of a default
13651404 // argument or default member initializer, this is the declaration whose
13661405 // default initializer is being evaluated and the location of the call
@@ -5253,22 +5292,17 @@ class Sema final {
52535292 BFRK_Check
52545293 };
52555294
5256- StmtResult ActOnCXXForRangeStmt(Scope *S, SourceLocation ForLoc,
5257- SourceLocation CoawaitLoc,
5258- Stmt *InitStmt,
5259- Stmt *LoopVar,
5260- SourceLocation ColonLoc, Expr *Collection,
5261- SourceLocation RParenLoc,
5262- BuildForRangeKind Kind);
5263- StmtResult BuildCXXForRangeStmt(SourceLocation ForLoc,
5264- SourceLocation CoawaitLoc,
5265- Stmt *InitStmt,
5266- SourceLocation ColonLoc,
5267- Stmt *RangeDecl, Stmt *Begin, Stmt *End,
5268- Expr *Cond, Expr *Inc,
5269- Stmt *LoopVarDecl,
5270- SourceLocation RParenLoc,
5271- BuildForRangeKind Kind);
5295+ StmtResult ActOnCXXForRangeStmt(
5296+ Scope *S, SourceLocation ForLoc, SourceLocation CoawaitLoc,
5297+ Stmt *InitStmt, Stmt *LoopVar, SourceLocation ColonLoc, Expr *Collection,
5298+ SourceLocation RParenLoc, BuildForRangeKind Kind,
5299+ ArrayRef<MaterializeTemporaryExpr *> LifetimeExtendTemps = {});
5300+ StmtResult BuildCXXForRangeStmt(
5301+ SourceLocation ForLoc, SourceLocation CoawaitLoc, Stmt *InitStmt,
5302+ SourceLocation ColonLoc, Stmt *RangeDecl, Stmt *Begin, Stmt *End,
5303+ Expr *Cond, Expr *Inc, Stmt *LoopVarDecl, SourceLocation RParenLoc,
5304+ BuildForRangeKind Kind,
5305+ ArrayRef<MaterializeTemporaryExpr *> LifetimeExtendTemps = {});
52725306 StmtResult FinishCXXForRangeStmt(Stmt *ForRange, Stmt *Body);
52735307
52745308 StmtResult ActOnGotoStmt(SourceLocation GotoLoc,
@@ -10010,6 +10044,18 @@ class Sema final {
1001010044 return currentEvaluationContext().isImmediateFunctionContext();
1001110045 }
1001210046
10047+ bool isInLifetimeExtendingContext() const {
10048+ assert(!ExprEvalContexts.empty() &&
10049+ "Must be in an expression evaluation context");
10050+ return ExprEvalContexts.back().InLifetimeExtendingContext;
10051+ }
10052+
10053+ bool isInMaterializeTemporaryObjectContext() const {
10054+ assert(!ExprEvalContexts.empty() &&
10055+ "Must be in an expression evaluation context");
10056+ return ExprEvalContexts.back().InMaterializeTemporaryObjectContext;
10057+ }
10058+
1001310059 bool isCheckingDefaultArgumentOrInitializer() const {
1001410060 const ExpressionEvaluationContextRecord &Ctx = currentEvaluationContext();
1001510061 return (Ctx.Context ==
@@ -10049,6 +10095,32 @@ class Sema final {
1004910095 return Res;
1005010096 }
1005110097
10098+ /// keepInLifetimeExtendingContext - Pull down InLifetimeExtendingContext
10099+ /// flag from previous context.
10100+ void keepInLifetimeExtendingContext() {
10101+ if (ExprEvalContexts.size() > 2 &&
10102+ ExprEvalContexts[ExprEvalContexts.size() - 2]
10103+ .InLifetimeExtendingContext) {
10104+ auto &LastRecord = ExprEvalContexts.back();
10105+ auto &PrevRecord = ExprEvalContexts[ExprEvalContexts.size() - 2];
10106+ LastRecord.InLifetimeExtendingContext =
10107+ PrevRecord.InLifetimeExtendingContext;
10108+ }
10109+ }
10110+
10111+ /// keepInMaterializeTemporaryObjectContext - Pull down
10112+ /// InMaterializeTemporaryObjectContext flag from previous context.
10113+ void keepInMaterializeTemporaryObjectContext() {
10114+ if (ExprEvalContexts.size() > 2 &&
10115+ ExprEvalContexts[ExprEvalContexts.size() - 2]
10116+ .InMaterializeTemporaryObjectContext) {
10117+ auto &LastRecord = ExprEvalContexts.back();
10118+ auto &PrevRecord = ExprEvalContexts[ExprEvalContexts.size() - 2];
10119+ LastRecord.InMaterializeTemporaryObjectContext =
10120+ PrevRecord.InMaterializeTemporaryObjectContext;
10121+ }
10122+ }
10123+
1005210124 /// RAII class used to determine whether SFINAE has
1005310125 /// trapped any errors that occur during template argument
1005410126 /// deduction.
0 commit comments