yronglin updated this revision to Diff 534212.
yronglin added a comment.

Update c++ status


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D153701/new/

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
  clang/www/cxx_status.html

Index: clang/www/cxx_status.html
===================================================================
--- clang/www/cxx_status.html
+++ clang/www/cxx_status.html
@@ -413,7 +413,7 @@
     <tr>
       <td>Lifetime extension in range-based for loops</td>
       <td><a href="https://wg21.link/P2718R0";>P2718R0</a></td>
-      <td class="none" align="center">No</td>
+      <td class="none" align="center">Clang 17</td>
     </tr>
     <!--Issaquah 2023 papers-->
     <tr>
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++20 -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().CPlusPlus20 && 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

Reply via email to