[clang] [Clang] Lazily allocate rare expression evaluation state (NFC) (PR #223036)

via cfe-commits cfe-commits at lists.llvm.org
Fri Sep 11 12:52:34 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang

Author: Mehdi Amini (joker-eph)

<details>
<summary>Changes</summary>

Keep common expression evaluation records compact by moving diagnostic and feature-specific collections behind one lazily allocated rare-data object. Add a no-rare-data pop path to avoid checking empty collections.

CTMark O0 (3 samples): 29.439800 s -> 29.219367 s (-0.749%).

Impact on significant TUs in MLIR build time:
- `mlir/lib/RegisterAllDialects.cpp`: 1.6043% fewer retired instructions.
- `mlir/lib/Dialect/LLVMIR/IR/NVVMDialect.cpp`: 0.9162% fewer retired instructions.

Assisted-by: Codex

---

Patch is 28.00 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/223036.diff


9 Files Affected:

- (modified) clang/include/clang/Sema/Sema.h (+47-31) 
- (modified) clang/lib/Parse/ParseStmt.cpp (+5-4) 
- (modified) clang/lib/Sema/SemaChecking.cpp (+12-6) 
- (modified) clang/lib/Sema/SemaExpr.cpp (+83-44) 
- (modified) clang/lib/Sema/SemaExprCXX.cpp (+10-8) 
- (modified) clang/lib/Sema/SemaExprMember.cpp (+1-1) 
- (modified) clang/lib/Sema/SemaInit.cpp (+3-1) 
- (modified) clang/lib/Sema/SemaLambda.cpp (+1-1) 
- (modified) clang/lib/Sema/TreeTransform.h (+10-6) 


``````````diff
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 4ff4c669a6b70..a74d1b58a4a8a 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -6809,12 +6809,6 @@ class Sema final : public SemaBase {
     /// this expression evaluation context.
     unsigned NumCleanupObjects;
 
-    MaybeODRUseExprSet SavedMaybeODRUseExprs;
-
-    /// The lambdas that are present within this context, if it
-    /// is indeed an unevaluated context.
-    SmallVector<LambdaExpr *, 2> Lambdas;
-
     /// The declaration that provides context for lambda expressions
     /// and block literals if the normal declaration context does not
     /// suffice, e.g., in a default function argument.
@@ -6825,38 +6819,60 @@ class Sema final : public SemaBase {
     /// diagnostic to reference the declaration as a whole.
     VarDecl *DeclForInitializer = nullptr;
 
-    /// If we are processing a decltype type, a set of call expressions
-    /// for which we have deferred checking the completeness of the return type.
-    SmallVector<CallExpr *, 8> DelayedDecltypeCalls;
+    /// Collections used by uncommon evaluation-context features. Keeping them
+    /// out of line avoids constructing empty containers for ordinary contexts.
+    struct RareData {
+      MaybeODRUseExprSet SavedMaybeODRUseExprs;
+
+      /// The lambdas that are present within an unevaluated context.
+      SmallVector<LambdaExpr *, 2> Lambdas;
+
+      /// If we are processing a decltype type, call expressions for which we
+      /// have deferred checking the completeness of the return type.
+      SmallVector<CallExpr *, 8> DelayedDecltypeCalls;
+
+      /// If we are processing a decltype type, temporary binding expressions
+      /// for which we have deferred checking the destructor.
+      SmallVector<CXXBindTemporaryExpr *, 8> DelayedDecltypeBinds;
 
-    /// If we are processing a decltype type, a set of temporary binding
-    /// expressions for which we have deferred checking the destructor.
-    SmallVector<CXXBindTemporaryExpr *, 8> DelayedDecltypeBinds;
+      llvm::SmallPtrSet<const Expr *, 8> PossibleDerefs;
 
-    llvm::SmallPtrSet<const Expr *, 8> PossibleDerefs;
+      /// Expressions appearing as the LHS of a volatile assignment in this
+      /// context. We warn when popping the context unless they are discarded-
+      /// value expressions or unevaluated operands.
+      SmallVector<Expr *, 2> VolatileAssignmentLHSs;
 
-    /// Expressions appearing as the LHS of a volatile assignment in this
-    /// context. We produce a warning for these when popping the context if
-    /// they are not discarded-value expressions nor unevaluated operands.
-    SmallVector<Expr *, 2> VolatileAssignmentLHSs;
+      /// Set of candidates for starting an immediate invocation.
+      llvm::SmallVector<ImmediateInvocationCandidate, 4>
+          ImmediateInvocationCandidates;
 
-    /// Set of candidates for starting an immediate invocation.
-    llvm::SmallVector<ImmediateInvocationCandidate, 4>
-        ImmediateInvocationCandidates;
+      /// DeclRefExprs referencing a consteval function in a context not already
+      /// known to be immediately invoked.
+      llvm::SmallPtrSet<DeclRefExpr *, 4> ReferenceToConsteval;
 
-    /// Set of DeclRefExprs referencing a consteval function when used in a
-    /// context not already known to be immediately invoked.
-    llvm::SmallPtrSet<DeclRefExpr *, 4> ReferenceToConsteval;
+      /// P2718R0 - Lifetime extension in range-based for loops.
+      /// Materialized temporaries in for-range-init expressions whose lifetime
+      /// needs extending. Collected when InLifetimeExtendingContext is true.
+      SmallVector<MaterializeTemporaryExpr *, 8> ForRangeLifetimeExtendTemps;
 
-    /// P2718R0 - Lifetime extension in range-based for loops.
-    /// MaterializeTemporaryExprs in for-range-init expressions which need to
-    /// extend lifetime. Add MaterializeTemporaryExpr* if the value of
-    /// InLifetimeExtendingContext is true.
-    SmallVector<MaterializeTemporaryExpr *, 8> ForRangeLifetimeExtendTemps;
+      /// Gathered accesses to potentially misaligned members due to the packed
+      /// attribute.
+      SmallVector<MisalignedMember, 4> MisalignedMembers;
+    };
+
+    /// Null means that every rare-data collection is empty.
+    std::unique_ptr<RareData> Rare;
+
+    /// Obtain storage for adding rare state, allocating it on first use.
+    RareData &getOrCreateRareData() {
+      if (!Rare)
+        Rare = std::make_unique<RareData>();
+      return *Rare;
+    }
 
-    /// Small set of gathered accesses to potentially misaligned members
-    /// due to the packed attribute.
-    SmallVector<MisalignedMember, 4> MisalignedMembers;
+    /// Inspect rare state without allocating storage for an empty context.
+    RareData *getRareData() { return Rare.get(); }
+    const RareData *getRareData() const { return Rare.get(); }
 
     /// \brief Describes whether we are in an expression constext which we have
     /// to handle differently.
diff --git a/clang/lib/Parse/ParseStmt.cpp b/clang/lib/Parse/ParseStmt.cpp
index 5e67cd551bff8..029b6c3f7ead6 100644
--- a/clang/lib/Parse/ParseStmt.cpp
+++ b/clang/lib/Parse/ParseStmt.cpp
@@ -1965,13 +1965,14 @@ void Parser::ParseForRangeInitializerAfterColon(ForRangeInit &FRI,
   }
 
   // Before c++23, ForRangeLifetimeExtendTemps should be empty.
-  assert(getLangOpts().CPlusPlus23 ||
-         Actions.ExprEvalContexts.back().ForRangeLifetimeExtendTemps.empty());
+  auto *Rare = Actions.ExprEvalContexts.back().getRareData();
+  assert(getLangOpts().CPlusPlus23 || !Rare ||
+         Rare->ForRangeLifetimeExtendTemps.empty());
 
   // Move the collected materialized temporaries into ForRangeInit before
   // ForRangeInitContext exit.
-  FRI.LifetimeExtendTemps =
-      std::move(Actions.ExprEvalContexts.back().ForRangeLifetimeExtendTemps);
+  if (Rare)
+    FRI.LifetimeExtendTemps = std::move(Rare->ForRangeLifetimeExtendTemps);
 }
 
 StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc,
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 25996ddbc0558..86e1062c8cc8f 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -16950,12 +16950,16 @@ void Sema::CheckArgumentWithTypeTag(const ArgumentWithTypeTagAttr *Attr,
 
 void Sema::AddPotentialMisalignedMembers(Expr *E, RecordDecl *RD, ValueDecl *MD,
                                          CharUnits Alignment) {
-  currentEvaluationContext().MisalignedMembers.emplace_back(E, RD, MD,
-                                                            Alignment);
+  currentEvaluationContext()
+      .getOrCreateRareData()
+      .MisalignedMembers.emplace_back(E, RD, MD, Alignment);
 }
 
 void Sema::DiagnoseMisalignedMembers() {
-  for (MisalignedMember &m : currentEvaluationContext().MisalignedMembers) {
+  auto *Rare = currentEvaluationContext().getRareData();
+  if (!Rare)
+    return;
+  for (MisalignedMember &m : Rare->MisalignedMembers) {
     const NamedDecl *ND = m.RD;
     if (ND->getName().empty()) {
       if (const TypedefNameDecl *TD = m.RD->getTypedefNameForAnonDecl())
@@ -16964,7 +16968,7 @@ void Sema::DiagnoseMisalignedMembers() {
     Diag(m.E->getBeginLoc(), diag::warn_taking_address_of_packed_member)
         << m.MD << ND << m.E->getSourceRange();
   }
-  currentEvaluationContext().MisalignedMembers.clear();
+  Rare->MisalignedMembers.clear();
 }
 
 void Sema::DiscardMisalignedMemberAddress(const Type *T, Expr *E) {
@@ -16975,8 +16979,10 @@ void Sema::DiscardMisalignedMemberAddress(const Type *T, Expr *E) {
       cast<UnaryOperator>(E)->getOpcode() == UO_AddrOf) {
     auto *Op = cast<UnaryOperator>(E)->getSubExpr()->IgnoreParens();
     if (isa<MemberExpr>(Op)) {
-      auto &MisalignedMembersForExpr =
-          currentEvaluationContext().MisalignedMembers;
+      auto *Rare = currentEvaluationContext().getRareData();
+      if (!Rare)
+        return;
+      auto &MisalignedMembersForExpr = Rare->MisalignedMembers;
       auto *MA = llvm::find(MisalignedMembersForExpr, MisalignedMember(Op));
       if (MA != MisalignedMembersForExpr.end() &&
           (T->isDependentType() || T->isIntegerType() ||
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 9fa8e517d9098..86e7f0dcf47ba 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -5382,7 +5382,8 @@ void Sema::CheckAddressOfNoDeref(const Expr *E) {
   while ((Member = dyn_cast<MemberExpr>(StrippedExpr)) && !Member->isArrow())
     StrippedExpr = Member->getBase()->IgnoreParenImpCasts();
 
-  LastRecord.PossibleDerefs.erase(StrippedExpr);
+  if (auto *Rare = LastRecord.getRareData())
+    Rare->PossibleDerefs.erase(StrippedExpr);
 }
 
 void Sema::CheckSubscriptAccessOfNoDeref(const ArraySubscriptExpr *E) {
@@ -5397,7 +5398,7 @@ void Sema::CheckSubscriptAccessOfNoDeref(const ArraySubscriptExpr *E) {
     return;
 
   if (ResultTy->hasAttr(attr::NoDeref)) {
-    LastRecord.PossibleDerefs.insert(E);
+    LastRecord.getOrCreateRareData().PossibleDerefs.insert(E);
     return;
   }
 
@@ -5416,7 +5417,7 @@ void Sema::CheckSubscriptAccessOfNoDeref(const ArraySubscriptExpr *E) {
 
   if (const auto *Ptr = dyn_cast<PointerType>(Base->getType())) {
     if (Ptr->getPointeeType()->hasAttr(attr::NoDeref))
-      LastRecord.PossibleDerefs.insert(E);
+      LastRecord.getOrCreateRareData().PossibleDerefs.insert(E);
   }
 }
 
@@ -6799,7 +6800,8 @@ ExprResult Sema::ActOnCallExpr(Scope *Scope, Expr *Fn, SourceLocation LParenLoc,
     // an invalid immediate call.
     if (auto *DRE = dyn_cast<DeclRefExpr>(Fn->IgnoreParens());
         DRE && Call.get()->isValueDependent()) {
-      currentEvaluationContext().ReferenceToConsteval.erase(DRE);
+      if (auto *Rare = currentEvaluationContext().getRareData())
+        Rare->ReferenceToConsteval.erase(DRE);
     }
   }
   return Call;
@@ -14730,7 +14732,9 @@ QualType Sema::CheckAssignmentOperands(Expr *LHSExpr, ExprResult &RHS,
       //   A simple-assignment whose left operand is of a volatile-qualified
       //   type is deprecated unless the assignment is either a discarded-value
       //   expression or an unevaluated operand
-      ExprEvalContexts.back().VolatileAssignmentLHSs.push_back(LHSExpr);
+      ExprEvalContexts.back()
+          .getOrCreateRareData()
+          .VolatileAssignmentLHSs.push_back(LHSExpr);
     }
   }
 
@@ -16584,7 +16588,7 @@ ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc,
   if (Opc == UO_Deref && UO->getType()->hasAttr(attr::NoDeref) &&
       !isa<ArrayType>(UO->getType().getDesugaredType(Context)) &&
       !isUnevaluatedContext())
-    ExprEvalContexts.back().PossibleDerefs.insert(UO);
+    ExprEvalContexts.back().getOrCreateRareData().PossibleDerefs.insert(UO);
 
   // Convert the result back to a half vector.
   if (ConvertHalfVec)
@@ -18322,29 +18326,35 @@ void
 Sema::PushExpressionEvaluationContext(
     ExpressionEvaluationContext NewContext, Decl *LambdaContextDecl,
     ExpressionEvaluationContextRecord::ExpressionKind ExprContext) {
+  const auto &Prev = currentEvaluationContext();
+  bool InDiscardedStatement = Prev.isDiscardedStatementContext();
+  bool InImmediateFunctionContext =
+      Prev.isImmediateFunctionContext() || Prev.isConstantEvaluated();
+  bool InImmediateEscalatingFunctionContext =
+      Prev.InImmediateEscalatingFunctionContext;
+
   ExprEvalContexts.emplace_back(NewContext, ExprCleanupObjects.size(), Cleanup,
                                 LambdaContextDecl, ExprContext);
+  auto &Current = currentEvaluationContext();
 
   // Discarded statements and immediate contexts nested in other
   // discarded statements or immediate context are themselves
   // a discarded statement or an immediate context, respectively.
-  ExprEvalContexts.back().InDiscardedStatement =
-      parentEvaluationContext().isDiscardedStatementContext();
+  Current.InDiscardedStatement = InDiscardedStatement;
 
   // C++23 [expr.const]/p15
   // An expression or conversion is in an immediate function context if [...]
   // it is a subexpression of a manifestly constant-evaluated expression or
   // conversion.
-  const auto &Prev = parentEvaluationContext();
-  ExprEvalContexts.back().InImmediateFunctionContext =
-      Prev.isImmediateFunctionContext() || Prev.isConstantEvaluated();
+  Current.InImmediateFunctionContext = InImmediateFunctionContext;
 
-  ExprEvalContexts.back().InImmediateEscalatingFunctionContext =
-      Prev.InImmediateEscalatingFunctionContext;
+  Current.InImmediateEscalatingFunctionContext =
+      InImmediateEscalatingFunctionContext;
 
   Cleanup.reset();
   if (!MaybeODRUseExprs.empty())
-    std::swap(MaybeODRUseExprs, ExprEvalContexts.back().SavedMaybeODRUseExprs);
+    std::swap(MaybeODRUseExprs,
+              Current.getOrCreateRareData().SavedMaybeODRUseExprs);
 }
 
 void
@@ -18434,7 +18444,10 @@ const DeclRefExpr *CheckPossibleDeref(Sema &S, const Expr *PossibleDeref) {
 } // namespace
 
 void Sema::WarnOnPendingNoDerefs(ExpressionEvaluationContextRecord &Rec) {
-  for (const Expr *E : Rec.PossibleDerefs) {
+  auto *Rare = Rec.getRareData();
+  if (!Rare)
+    return;
+  for (const Expr *E : Rare->PossibleDerefs) {
     const DeclRefExpr *DeclRef = CheckPossibleDeref(*this, E);
     if (DeclRef) {
       const ValueDecl *Decl = DeclRef->getDecl();
@@ -18446,7 +18459,7 @@ void Sema::WarnOnPendingNoDerefs(ExpressionEvaluationContextRecord &Rec) {
           << E->getSourceRange();
     }
   }
-  Rec.PossibleDerefs.clear();
+  Rare->PossibleDerefs.clear();
 }
 
 void Sema::CheckUnusedVolatileAssignment(Expr *E) {
@@ -18458,8 +18471,8 @@ void Sema::CheckUnusedVolatileAssignment(Expr *E) {
   // drives a deprecation warning so doesn't affect conformance.
   if (auto *BO = dyn_cast<BinaryOperator>(E->IgnoreParenImpCasts())) {
     if (BO->getOpcode() == BO_Assign) {
-      auto &LHSs = ExprEvalContexts.back().VolatileAssignmentLHSs;
-      llvm::erase(LHSs, BO->getLHS());
+      if (auto *Rare = ExprEvalContexts.back().getRareData())
+        llvm::erase(Rare->VolatileAssignmentLHSs, BO->getLHS());
     }
   }
 }
@@ -18499,7 +18512,8 @@ ExprResult Sema::CheckForImmediateInvocation(ExprResult E, FunctionDecl *Decl) {
   if (auto *Call = dyn_cast<CallExpr>(E.get()->IgnoreImplicit()))
     if (auto *DeclRef =
             dyn_cast<DeclRefExpr>(Call->getCallee()->IgnoreImplicit()))
-      ExprEvalContexts.back().ReferenceToConsteval.erase(DeclRef);
+      if (auto *Rare = ExprEvalContexts.back().getRareData())
+        Rare->ReferenceToConsteval.erase(DeclRef);
 
   // C++23 [expr.const]/p16
   // An expression or conversion is immediate-escalating if it is not initially
@@ -18555,7 +18569,9 @@ ExprResult Sema::CheckForImmediateInvocation(ExprResult E, FunctionDecl *Decl) {
   /// Value-dependent constant expressions should not be immediately
   /// evaluated until they are instantiated.
   if (!Res->isValueDependent())
-    ExprEvalContexts.back().ImmediateInvocationCandidates.emplace_back(Res, 0);
+    ExprEvalContexts.back()
+        .getOrCreateRareData()
+        .ImmediateInvocationCandidates.emplace_back(Res, 0);
   return Res;
 }
 
@@ -18691,8 +18707,8 @@ static void RemoveNestedImmediateInvocation(
       return Res;
     }
     bool AllowSkippingFirstCXXConstructExpr = true;
-  } Transformer(SemaRef, Rec.ReferenceToConsteval,
-                Rec.ImmediateInvocationCandidates, It);
+  } Transformer(SemaRef, Rec.getRareData()->ReferenceToConsteval,
+                Rec.getRareData()->ImmediateInvocationCandidates, It);
 
   /// CXXConstructExpr with a single argument are getting skipped by
   /// TreeTransform in some situtation because they could be implicit. This
@@ -18716,8 +18732,10 @@ static void RemoveNestedImmediateInvocation(
 static void
 HandleImmediateInvocations(Sema &SemaRef,
                            Sema::ExpressionEvaluationContextRecord &Rec) {
-  if ((Rec.ImmediateInvocationCandidates.size() == 0 &&
-       Rec.ReferenceToConsteval.size() == 0) ||
+  auto *Rare = Rec.getRareData();
+  if (!Rare ||
+      (Rare->ImmediateInvocationCandidates.empty() &&
+       Rare->ReferenceToConsteval.empty()) ||
       Rec.isImmediateFunctionContext() || SemaRef.RebuildingImmediateInvocation)
     return;
 
@@ -18745,7 +18763,7 @@ HandleImmediateInvocations(Sema &SemaRef,
   /// ImmediateInvocationCandidates in order to avoid duplicate diagnostics.
   /// Otherwise we only need to remove ReferenceToConsteval in the immediate
   /// invocation.
-  if (Rec.ImmediateInvocationCandidates.size() > 1 ||
+  if (Rare->ImmediateInvocationCandidates.size() > 1 ||
       !SemaRef.FailedImmediateInvocations.empty()) {
 
     /// Prevent sema calls during the tree transform from adding pointers that
@@ -18756,12 +18774,12 @@ HandleImmediateInvocations(Sema &SemaRef,
     /// Prevent diagnostic during tree transfrom as they are duplicates
     Sema::TentativeAnalysisScope DisableDiag(SemaRef);
 
-    for (auto It = Rec.ImmediateInvocationCandidates.rbegin();
-         It != Rec.ImmediateInvocationCandidates.rend(); It++)
+    for (auto It = Rare->ImmediateInvocationCandidates.rbegin();
+         It != Rare->ImmediateInvocationCandidates.rend(); It++)
       if (!It->getInt())
         RemoveNestedImmediateInvocation(SemaRef, Rec, It);
-  } else if (Rec.ImmediateInvocationCandidates.size() == 1 &&
-             Rec.ReferenceToConsteval.size()) {
+  } else if (Rare->ImmediateInvocationCandidates.size() == 1 &&
+             !Rare->ReferenceToConsteval.empty()) {
     struct SimpleRemove : DynamicRecursiveASTVisitor {
       llvm::SmallPtrSetImpl<DeclRefExpr *> &DRSet;
       SimpleRemove(llvm::SmallPtrSetImpl<DeclRefExpr *> &S) : DRSet(S) {}
@@ -18769,14 +18787,14 @@ HandleImmediateInvocations(Sema &SemaRef,
         DRSet.erase(E);
         return DRSet.size();
       }
-    } Visitor(Rec.ReferenceToConsteval);
+    } Visitor(Rare->ReferenceToConsteval);
     Visitor.TraverseStmt(
-        Rec.ImmediateInvocationCandidates.front().getPointer()->getSubExpr());
+        Rare->ImmediateInvocationCandidates.front().getPointer()->getSubExpr());
   }
-  for (auto CE : Rec.ImmediateInvocationCandidates)
+  for (auto CE : Rare->ImmediateInvocationCandidates)
     if (!CE.getInt())
       EvaluateAndDiagnoseImmediateInvocation(SemaRef, CE);
-  for (auto *DR : Rec.ReferenceToConsteval) {
+  for (auto *DR : Rare->ReferenceToConsteval) {
     // If the expression is immediate escalating, it is not an error;
     // The outer context itself becomes immediate and further errors,
     // if any, will be handled by DiagnoseImmediateEscalatingReason.
@@ -18825,7 +18843,23 @@ HandleImmediateInvocations(Sema &SemaRef,
 
 void Sema::PopExpressionEvaluationContext() {
   ExpressionEvaluationContextRecord& Rec = ExprEvalContexts.back();
-  if (!Rec.Lambdas.empty()) {
+  auto *Rare = Rec.getRareData();
+  if (!Rare) {
+    if (Rec.isUnevaluated() || Rec.isConstantEvaluated()) {
+      ExprCleanupObjects.erase(ExprCleanupObjects.begin() +
+                                   Rec.NumCleanupObjects,
+                               ExprCleanupObjects.end());
+      Cleanup = Rec.ParentCleanup;
+      CleanupVarDeclMarking();
+      MaybeODRUseExprs.clear();
+    } else {
+      Cleanup.mergeFrom(Rec.ParentCleanup);
+    }
+    ExprEvalContexts.pop_back();
+    return;
+  }
+
+  if (!Rare->Lambdas.empty()) {
     using ExpressionKind = ExpressionEvaluationContextRecord::ExpressionKind;
     if (!getLangOpts().CPlusPlus20 &&
         (Rec.ExprContext == ExpressionKind::EK_TemplateArgument ||
@@ -18850,7 +18884,7 @@ void Sema::PopExpressionEvaluationContext() {
       } else
         llvm_unreachable("Couldn't infer lambda error message.");
 
-      for (const auto *L : Rec.Lambdas)
+      for (const auto *L : Rare->Lambdas)
         Diag(L->getBeginLoc(), D);
     }
   }
@@ -18859,9 +18893,10 @@ void Sema::PopExpressionEvaluationContext() {
   // exit if the previous also is a lifetime extending context.
   if (getLangOpts().CPlusPlus23 && Rec.InLifetimeExtendingContext &&
       parentEvaluationContext().InLifetimeExtendingContext &&
-      !Rec.ForRangeLifetimeExtendTemps.empty()) {
-    parentEvaluationContext().ForRangeLifetimeExtendTemps.append(
-        Rec.ForRangeLifetimeExtendTemps);
+      !Rare->ForRangeLifetimeExtendTemps.empty()) {
+    parentEvaluationContext()
+      ...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/223036


More information about the cfe-commits mailing list