================
@@ -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