yronglin created this revision.
Herald added a project: All.
yronglin requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.
Signed-off-by: yronglin <yronglin...@gmail.com>
Repository:
rG LLVM Github Monorepo
https://reviews.llvm.org/D153701
Files:
clang/docs/ReleaseNotes.rst
clang/include/clang/AST/Decl.h
clang/include/clang/Sema/Sema.h
clang/lib/Sema/SemaDecl.cpp
clang/lib/Sema/SemaExprCXX.cpp
clang/lib/Sema/SemaStmt.cpp
clang/test/CodeGenCXX/for-range-temporaries.cpp
Index: clang/test/CodeGenCXX/for-range-temporaries.cpp
===================================================================
--- clang/test/CodeGenCXX/for-range-temporaries.cpp
+++ clang/test/CodeGenCXX/for-range-temporaries.cpp
@@ -1,9 +1,10 @@
-// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -std=c++11 -emit-llvm -o - -UDESUGAR %s | FileCheck %s
-// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -std=c++11 -emit-llvm -o - -DDESUGAR %s | FileCheck %s
-// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -std=c++11 -emit-llvm -o - -UDESUGAR -DTEMPLATE %s | FileCheck %s
-// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -std=c++11 -emit-llvm -o - -DDESUGAR -DTEMPLATE %s | FileCheck %s
-// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -std=c++11 -emit-llvm -o - -UDESUGAR -DTEMPLATE -DDEPENDENT %s | FileCheck %s
-// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -std=c++11 -emit-llvm -o - -DDESUGAR -DTEMPLATE -DDEPENDENT %s | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -std=c++11 -emit-llvm -o - -UDESUGAR %s | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-NO-EXT-LIFETIME
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -std=c++11 -emit-llvm -o - -DDESUGAR %s | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-NO-EXT-LIFETIME
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -std=c++11 -emit-llvm -o - -UDESUGAR -DTEMPLATE %s | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-NO-EXT-LIFETIME
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -std=c++11 -emit-llvm -o - -DDESUGAR -DTEMPLATE %s | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-NO-EXT-LIFETIME
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -std=c++11 -emit-llvm -o - -UDESUGAR -DTEMPLATE -DDEPENDENT %s | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-NO-EXT-LIFETIME
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -std=c++11 -emit-llvm -o - -DDESUGAR -DTEMPLATE -DDEPENDENT %s | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-NO-EXT-LIFETIME
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -std=c++23 -emit-llvm -o - -UDESUGAR %s | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-EXT-LIFETIME
struct A {
A();
@@ -103,8 +104,8 @@
// CHECK: call void @_ZN1BC1Ev(
// CHECK: call void @_ZN1CC1ERK1B(
// CHECK: call void @_ZN1DC1ERK1C(
-// CHECK: call void @_ZN1CD1Ev(
-// CHECK: call void @_ZN1BD1Ev(
+// CHECK-NO-EXT-LIFETIME: call void @_ZN1CD1Ev(
+// CHECK-NO-EXT-LIFETIME: call void @_ZN1BD1Ev(
// CHECK: call void @_ZN1DC1ERKS_(
// CHECK: call void @_Z5begin1D(
// CHECK: call void @_ZN1DD1Ev(
@@ -122,6 +123,8 @@
// CHECK: [[CLEANUP]]:
// CHECK: call void @_ZN1ED1Ev(
// CHECK: call void @_ZN1ED1Ev(
+// CHECK-EXT-LIFETIME: call void @_ZN1CD1Ev(
+// CHECK-EXT-LIFETIME: call void @_ZN1BD1Ev(
// In for-range:
// call void @_ZN1DD1Ev(
// CHECK: br label %[[END:.*]]
@@ -142,5 +145,6 @@
// CHECK: [[END]]:
// In desugared version:
// call void @_ZN1DD1Ev(
+// CHECK-EXT-LIFETIME: call void @_ZN1DD1Ev(
// CHECK: call void @_ZN1AD1Ev(
// CHECK: ret void
Index: clang/lib/Sema/SemaStmt.cpp
===================================================================
--- clang/lib/Sema/SemaStmt.cpp
+++ clang/lib/Sema/SemaStmt.cpp
@@ -2528,6 +2528,7 @@
VarDecl *RangeVar = BuildForRangeVarDecl(*this, RangeLoc,
Context.getAutoRRefDeductType(),
std::string("__range") + DepthStr);
+ RangeVar->setCXXForRangeInitializer(true);
if (FinishForRangeVarDecl(*this, RangeVar, Range, RangeLoc,
diag::err_for_range_deduction_failure)) {
ActOnInitializerError(LoopVar);
Index: clang/lib/Sema/SemaExprCXX.cpp
===================================================================
--- clang/lib/Sema/SemaExprCXX.cpp
+++ clang/lib/Sema/SemaExprCXX.cpp
@@ -8806,7 +8806,7 @@
ExprResult Sema::ActOnFinishFullExpr(Expr *FE, SourceLocation CC,
bool DiscardedValue, bool IsConstexpr,
- bool IsTemplateArgument) {
+ bool IsTemplateArgument, bool IsForRangeInit) {
ExprResult FullExpr = FE;
if (!FullExpr.get())
@@ -8889,13 +8889,28 @@
// - Teach the handful of places that iterate over FunctionScopes to
// stop at the outermost enclosing lexical scope."
DeclContext *DC = CurContext;
- while (DC && isa<CapturedDecl>(DC))
+ while (isa_and_nonnull<CapturedDecl>(DC))
DC = DC->getParent();
const bool IsInLambdaDeclContext = isLambdaCallOperator(DC);
if (IsInLambdaDeclContext && CurrentLSI &&
CurrentLSI->hasPotentialCaptures() && !FullExpr.isInvalid())
CheckIfAnyEnclosingLambdasMustCaptureAnyPotentialCaptures(FE, CurrentLSI,
*this);
+ // [P2718R0] Lifetime extension in range-based for loops.
+ //
+ // 6.7.7 [class.temporary] p5:
+ // There are four contexts in which temporaries are destroyed at a different
+ // point than the end of the full-expression.
+ //
+ // 6.7.7 [class.temporary] p6:
+ // The fourth context is when a temporary object other than a function
+ // parameter object is created in the for-range-initializer of a range-based
+ // for statement. If such a temporary object would otherwise be destroyed at
+ // the end of the for-range-initializer full-expression, the object persists
+ // for the lifetime of the reference initialized by the for-range-initializer.
+ if (getLangOpts().CPlusPlus23 && IsForRangeInit)
+ return FullExpr;
+
return MaybeCreateExprWithCleanups(FullExpr);
}
Index: clang/lib/Sema/SemaDecl.cpp
===================================================================
--- clang/lib/Sema/SemaDecl.cpp
+++ clang/lib/Sema/SemaDecl.cpp
@@ -13386,9 +13386,10 @@
// struct T { S a, b; } t = { Temp(), Temp() }
//
// we should destroy the first Temp before constructing the second.
- ExprResult Result =
- ActOnFinishFullExpr(Init, VDecl->getLocation(),
- /*DiscardedValue*/ false, VDecl->isConstexpr());
+ ExprResult Result = ActOnFinishFullExpr(
+ Init, VDecl->getLocation(),
+ /*DiscardedValue*/ false, VDecl->isConstexpr(),
+ /*IsTemplateArgument*/ false, VDecl->isCXXForRangeInitializer());
if (Result.isInvalid()) {
VDecl->setInvalidDecl();
return;
Index: clang/include/clang/Sema/Sema.h
===================================================================
--- clang/include/clang/Sema/Sema.h
+++ clang/include/clang/Sema/Sema.h
@@ -6919,7 +6919,8 @@
}
ExprResult ActOnFinishFullExpr(Expr *Expr, SourceLocation CC,
bool DiscardedValue, bool IsConstexpr = false,
- bool IsTemplateArgument = false);
+ bool IsTemplateArgument = false,
+ bool IsForRangeInit = false);
StmtResult ActOnFinishFullStmt(Stmt *Stmt);
// Marks SS invalid if it represents an incomplete type.
Index: clang/include/clang/AST/Decl.h
===================================================================
--- clang/include/clang/AST/Decl.h
+++ clang/include/clang/AST/Decl.h
@@ -1047,6 +1047,10 @@
/// for-range statement.
unsigned CXXForRangeDecl : 1;
+ /// Whether this variable is the for-range-initializer in a for-range
+ /// statement.
+ unsigned CXXForRangeInitializer : 1;
+
/// Whether this variable is the for-in loop declaration in Objective-C.
unsigned ObjCForDecl : 1;
@@ -1477,6 +1481,15 @@
NonParmVarDeclBits.CXXForRangeDecl = FRD;
}
+ bool isCXXForRangeInitializer() const {
+ return isa<ParmVarDecl>(this) || !isImplicit() ? false : NonParmVarDeclBits.CXXForRangeInitializer;
+ }
+
+ void setCXXForRangeInitializer(bool FRI) {
+ assert(!isa<ParmVarDecl>(this) && isImplicit());
+ NonParmVarDeclBits.CXXForRangeInitializer = FRI;
+ }
+
/// Determine whether this variable is a for-loop declaration for a
/// for-in statement in Objective-C.
bool isObjCForDecl() const {
Index: clang/docs/ReleaseNotes.rst
===================================================================
--- clang/docs/ReleaseNotes.rst
+++ clang/docs/ReleaseNotes.rst
@@ -128,6 +128,7 @@
non-constexpr functions and constructors.
- Clang now supports `requires cplusplus23` for module maps.
- Implemented `P2564R3: consteval needs to propagate up <https://wg21.link/P2564R3>`_.
+- Implemented `P2718R0: Lifetime extension in range-based for loops <https://wg21.link/P2718R0>`_.
C++2c Feature Support
^^^^^^^^^^^^^^^^^^^^^
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits