================
@@ -2710,6 +2715,224 @@ static StmtResult RebuildForRangeWithDereference(Sema 
&SemaRef, Scope *S,
       AdjustedRange.get(), RParenLoc, Sema::BFRK_Rebuild);
 }
 
+void Sema::ApplyForRangeOrExpansionStatementLifetimeExtension(
+    VarDecl *RangeVar, ArrayRef<MaterializeTemporaryExpr *> Temporaries) {
+  if (Temporaries.empty())
+    return;
+
+  InitializedEntity Entity = InitializedEntity::InitializeVariable(RangeVar);
+  for (auto *MTE : Temporaries)
+    MTE->setExtendingDecl(RangeVar, Entity.allocateManglingNumber());
+}
+
+Sema::ForRangeBeginEndInfo Sema::BuildCXXForRangeBeginEndVars(
+    Scope *S, VarDecl *RangeVar, SourceLocation ColonLoc,
+    SourceLocation CoawaitLoc,
+    ArrayRef<MaterializeTemporaryExpr *> LifetimeExtendTemps,
+    BuildForRangeKind Kind, bool Constexpr, StmtResult *RebuildResult,
+    llvm::function_ref<StmtResult()> RebuildWithDereference,
+    IdentifierInfo *BeginName, IdentifierInfo *EndName) {
+  QualType RangeVarType = RangeVar->getType();
+  SourceLocation RangeLoc = RangeVar->getLocation();
+  const QualType RangeVarNonRefType = RangeVarType.getNonReferenceType();
+
+  ExprResult BeginRangeRef =
+      BuildDeclRefExpr(RangeVar, RangeVarNonRefType, VK_LValue, ColonLoc);
+  if (BeginRangeRef.isInvalid())
+    return {};
+
+  ExprResult EndRangeRef =
+      BuildDeclRefExpr(RangeVar, RangeVarNonRefType, VK_LValue, ColonLoc);
+  if (EndRangeRef.isInvalid())
+    return {};
+
+  QualType AutoType = Context.getAutoDeductType();
+  Expr *Range = RangeVar->getInit();
+  if (!Range)
+    return {};
+  QualType RangeType = Range->getType();
+
+  if (RequireCompleteType(RangeLoc, RangeType,
+                          diag::err_for_range_incomplete_type))
+    return {};
+
+  // Build auto __begin = begin-expr, __end = end-expr.
+  // Divide by 2, since the variables are in the inner scope (loop body).
+  const auto DepthStr = std::to_string(S->getDepth() / 2);
+  if (!BeginName)
+    BeginName = PP.getIdentifierInfo(std::string("__begin") + DepthStr);
+  if (!EndName)
+    EndName = PP.getIdentifierInfo(std::string("__end") + DepthStr);
+  VarDecl *BeginVar = BuildForRangeVarDecl(
+      ColonLoc, AutoType, BeginName, Constexpr);
+  VarDecl *EndVar = BuildForRangeVarDecl(
+      ColonLoc, AutoType, EndName, Constexpr);
+
+  // Build begin-expr and end-expr and attach to __begin and __end variables.
+  ExprResult BeginExpr, EndExpr;
+  if (const ArrayType *UnqAT = RangeType->getAsArrayTypeUnsafe()) {
+    // - if _RangeT is an array type, begin-expr and end-expr are __range and
+    //   __range + __bound, respectively, where __bound is the array bound. If
+    //   _RangeT is an array of unknown size or an array of incomplete type,
+    //   the program is ill-formed;
+
+    // begin-expr is __range.
+    BeginExpr = BeginRangeRef;
+    if (!CoawaitLoc.isInvalid()) {
+      BeginExpr = ActOnCoawaitExpr(S, ColonLoc, BeginExpr.get());
+      if (BeginExpr.isInvalid())
+        return {};
+    }
+    if (FinishForRangeVarDecl(*this, BeginVar, BeginRangeRef.get(), ColonLoc,
+                              diag::err_for_range_iter_deduction_failure)) {
+      NoteForRangeBeginEndFunction(*this, BeginExpr.get(), BEF_begin);
+      return {};
+    }
+
+    // Find the array bound.
+    ExprResult BoundExpr;
+    if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(UnqAT))
+      BoundExpr = IntegerLiteral::Create(
+          Context, CAT->getSize(), Context.getPointerDiffType(), RangeLoc);
+    else if (const VariableArrayType *VAT =
+                 dyn_cast<VariableArrayType>(UnqAT)) {
+      // For a variably modified type we can't just use the expression within
+      // the array bounds, since we don't want that to be re-evaluated here.
+      // Rather, we need to determine what it was when the array was first
+      // created - so we resort to using sizeof(vla)/sizeof(element).
+      // For e.g.
+      //  void f(int b) {
+      //    int vla[b];
+      //    b = -1;   <-- This should not affect the num of iterations below
+      //    for (int &c : vla) { .. }
+      //  }
+
+      // FIXME: This results in codegen generating IR that recalculates the
+      // run-time number of elements (as opposed to just using the IR Value
+      // that corresponds to the run-time value of each bound that was
+      // generated when the array was created.) If this proves too embarrassing
+      // even for unoptimized IR, consider passing a magic-value/cookie to
+      // codegen that then knows to simply use that initial llvm::Value (that
+      // corresponds to the bound at time of array creation) within
+      // getelementptr.  But be prepared to pay the price of increasing a
+      // customized form of coupling between the two components - which  could
+      // be hard to maintain as the codebase evolves.
+
+      ExprResult SizeOfVLAExprR = ActOnUnaryExprOrTypeTraitExpr(
+          EndVar->getLocation(), UETT_SizeOf,
+          /*IsType=*/true,
+          CreateParsedType(VAT->desugar(), Context.getTrivialTypeSourceInfo(
+                                               VAT->desugar(), RangeLoc))
+              .getAsOpaquePtr(),
+          EndVar->getSourceRange());
+      if (SizeOfVLAExprR.isInvalid())
+        return {};
+
+      ExprResult SizeOfEachElementExprR = ActOnUnaryExprOrTypeTraitExpr(
+          EndVar->getLocation(), UETT_SizeOf,
+          /*IsType=*/true,
+          CreateParsedType(VAT->desugar(), Context.getTrivialTypeSourceInfo(
+                                               VAT->getElementType(), 
RangeLoc))
+              .getAsOpaquePtr(),
+          EndVar->getSourceRange());
+      if (SizeOfEachElementExprR.isInvalid())
+        return {};
+
+      BoundExpr =
+          ActOnBinOp(S, EndVar->getLocation(), tok::slash, 
SizeOfVLAExprR.get(),
+                     SizeOfEachElementExprR.get());
+      if (BoundExpr.isInvalid())
+        return {};
+
+    } else {
+      // Can't be a DependentSizedArrayType or an IncompleteArrayType since
+      // UnqAT is not incomplete and Range is not type-dependent.
+      llvm_unreachable("Unexpected array type in for-range");
----------------
Sirraide wrote:

No idea; presumably it really just can’t happen

https://github.com/llvm/llvm-project/pull/169683
_______________________________________________
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits

Reply via email to