================
@@ -22210,59 +22269,126 @@ bool Expr::EvaluateAsInitializer(const ASTContext 
&Ctx, const VarDecl *VD,
          CheckMemoryLeaks(Info);
 }
 
-bool VarDecl::evaluateDestruction(
-    SmallVectorImpl<PartialDiagnosticAt> &Notes) const {
+bool Expr::EvaluateAsInitializer(const ASTContext &Ctx, const VarDecl *VD,
+                                 Expr::EvalResult &EStatus,
+                                 bool IsConstantInitialization) const {
+  assert(!isValueDependent() &&
+         "Expression evaluator can't be called on a dependent expression.");
+  assert(VD && "Need a valid VarDecl");
+
+  llvm::TimeTraceScope TimeScope("EvaluateAsInitializer", [&] {
+    std::string Name;
+    llvm::raw_string_ostream OS(Name);
+    VD->printQualifiedName(OS);
+    return Name;
+  });
+
+  EvalInfo Info(Ctx, /*Sema=*/nullptr, EStatus,
+                (IsConstantInitialization &&
+                 (Ctx.getLangOpts().CPlusPlus || Ctx.getLangOpts().C23))
+                    ? EvaluationMode::ConstantExpression
+                    : EvaluationMode::ConstantFold);
+  Info.setEvaluatingDecl(VD, EStatus.Val);
+  Info.InConstantContext = IsConstantInitialization;
+
+  return ::EvaluateInitializer(Ctx, Info, VD, this, EStatus,
+                               IsConstantInitialization);
+}
+
+bool Expr::EvaluateAsMandatedConstantInitializer(EvalResult &EStatus,
+                                                 const ASTContext &Ctx,
+                                                 SemaProxy &Sema,
+                                                 const VarDecl *VD) const {
+  assert(!isValueDependent() &&
+         "Expression evaluator can't be called on a dependent expression.");
+  assert(VD && "Need a valid VarDecl");
+
+  llvm::TimeTraceScope TimeScope("EvaluateAsMandatedConstantInitializer", [&] {
+    std::string Name;
+    llvm::raw_string_ostream OS(Name);
+    VD->printQualifiedName(OS);
+    return Name;
+  });
+
+  EvalInfo Info(Ctx, &Sema, EStatus, EvaluationMode::ConstantExpression);
+  Info.setEvaluatingDecl(VD, EStatus.Val);
+  Info.InConstantContext = true;
+
+  return ::EvaluateInitializer(Ctx, Info, VD, this, EStatus,
+                               /*IsConstantInitialization=*/true);
+}
+
+static bool evaluateDestruction(Expr::EvalStatus EStatus, EvalInfo &Info,
+                                const VarDecl *VD, bool IsConstantDestruction) 
{
+  ASTContext &Ctx = VD->getASTContext();
+
   // This function is only meaningful for records and arrays of records.
-  QualType VarTy = getType();
+  QualType VarTy = VD->getType();
   if (VarTy->isArrayType()) {
-    QualType ElemTy = getASTContext().getBaseElementType(VarTy);
+    QualType ElemTy = Ctx.getBaseElementType(VarTy);
     if (!ElemTy->isRecordType()) {
-      ensureEvaluatedStmt()->HasConstantDestruction = true;
+      VD->ensureEvaluatedStmt()->HasConstantDestruction = true;
       return true;
     }
   } else if (!VarTy->isRecordType()) {
-    ensureEvaluatedStmt()->HasConstantDestruction = true;
+    VD->ensureEvaluatedStmt()->HasConstantDestruction = true;
     return true;
   }
 
-  Expr::EvalStatus EStatus;
-  EStatus.Diag = &Notes;
-
-  // Only treat the destruction as constant destruction if we formally have
-  // constant initialization (or are usable in a constant expression).
-  bool IsConstantDestruction = hasConstantInitialization();
-  ASTContext &Ctx = getASTContext();
+  Info.InConstantContext = IsConstantDestruction;
 
   // Make a copy of the value for the destructor to mutate, if we know it.
   // Otherwise, treat the value as default-initialized; if the destructor works
   // anyway, then the destruction is constant (and must be essentially empty).
   APValue DestroyedValue;
-  if (getEvaluatedValue())
-    DestroyedValue = *getEvaluatedValue();
+  if (VD->getEvaluatedValue())
+    DestroyedValue = *VD->getEvaluatedValue();
   else if (!handleDefaultInitValue(VarTy, DestroyedValue))
     return false;
 
   if (Ctx.getLangOpts().EnableNewConstInterp) {
-    EvalInfo Info(Ctx, EStatus,
-                  IsConstantDestruction ? EvaluationMode::ConstantExpression
-                                        : EvaluationMode::ConstantFold);
-    Info.InConstantContext = IsConstantDestruction;
-    if (!Ctx.getInterpContext().evaluateDestruction(Info, this,
+    if (!Ctx.getInterpContext().evaluateDestruction(Info, VD,
                                                     std::move(DestroyedValue)))
       return false;
-    ensureEvaluatedStmt()->HasConstantDestruction = true;
+    VD->ensureEvaluatedStmt()->HasConstantDestruction = true;
     return true;
   }
 
-  if (!EvaluateDestruction(Ctx, this, std::move(DestroyedValue), VarTy,
-                           getLocation(), EStatus, IsConstantDestruction) ||
+  if (!EvaluateDestruction(Ctx, Info.getSemaProxy(), VD,
+                           std::move(DestroyedValue), VarTy, VD->getLocation(),
+                           EStatus, IsConstantDestruction) ||
       EStatus.HasSideEffects)
     return false;
 
-  ensureEvaluatedStmt()->HasConstantDestruction = true;
+  VD->ensureEvaluatedStmt()->HasConstantDestruction = true;
   return true;
 }
 
+bool VarDecl::evaluateDestruction(
----------------
katzdm wrote:

Please note that `evaluateDestruction` is an [existing 
function](https://github.com/llvm/llvm-project/blob/688a1498b3ce9011ee58c214086e3cd408e86f5e/clang/lib/AST/ExprConstant.cpp#L22223-L22274),
 the internals of which I've broken out into a separate `::evaluateDestruction` 
function in order to better share code between these two entrypoints.

But again - I'm trying to follow the precedent that the entry-points to the 
constant evaluator are responsible for rigging the `EvalInfo` object, even if 
that means duplicating a line here and there.

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

Reply via email to