llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang Author: Timm Baeder (tbaederr) <details> <summary>Changes</summary> Make it an enum class and move the enum to State.h as well as the `EvalMode` member to `State`. This is in preparation of using the evaluation mode from `InterpState` as well. --- Full diff: https://github.com/llvm/llvm-project/pull/157988.diff 2 Files Affected: - (modified) clang/lib/AST/ByteCode/State.h (+23) - (modified) clang/lib/AST/ExprConstant.cpp (+52-70) ``````````diff diff --git a/clang/lib/AST/ByteCode/State.h b/clang/lib/AST/ByteCode/State.h index 387ce396a7235..a834eed142de0 100644 --- a/clang/lib/AST/ByteCode/State.h +++ b/clang/lib/AST/ByteCode/State.h @@ -50,6 +50,27 @@ enum CheckSubobjectKind { CSK_VectorElement }; +enum class EvaluationMode { + /// Evaluate as a constant expression. Stop if we find that the expression + /// is not a constant expression. + ConstantExpression, + + /// Evaluate as a constant expression. Stop if we find that the expression + /// is not a constant expression. Some expressions can be retried in the + /// optimizer if we don't constant fold them here, but in an unevaluated + /// context we try to fold them immediately since the optimizer never + /// gets a chance to look at it. + ConstantExpressionUnevaluated, + + /// Fold the expression to a constant. Stop if we hit a side-effect that + /// we can't model. + ConstantFold, + + /// Evaluate in any way we know how. Don't worry about side-effects that + /// can't be modeled. + IgnoreSideEffects, +}; + namespace interp { class Frame; class SourceInfo; @@ -149,6 +170,8 @@ class State { /// is set; this is used when evaluating ICEs in C. bool CheckingForUndefinedBehavior = false; + EvaluationMode EvalMode; + private: void addCallStack(unsigned Limit); diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 662b2392e9253..1065c1e70eb64 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -926,27 +926,6 @@ namespace { /// fold (not just why it's not strictly a constant expression)? bool HasFoldFailureDiagnostic; - enum EvaluationMode { - /// Evaluate as a constant expression. Stop if we find that the expression - /// is not a constant expression. - EM_ConstantExpression, - - /// Evaluate as a constant expression. Stop if we find that the expression - /// is not a constant expression. Some expressions can be retried in the - /// optimizer if we don't constant fold them here, but in an unevaluated - /// context we try to fold them immediately since the optimizer never - /// gets a chance to look at it. - EM_ConstantExpressionUnevaluated, - - /// Fold the expression to a constant. Stop if we hit a side-effect that - /// we can't model. - EM_ConstantFold, - - /// Evaluate in any way we know how. Don't worry about side-effects that - /// can't be modeled. - EM_IgnoreSideEffects, - } EvalMode; - EvalInfo(const ASTContext &C, Expr::EvalStatus &S, EvaluationMode Mode) : Ctx(const_cast<ASTContext &>(C)), EvalStatus(S), CurrentCall(nullptr), CallStackDepth(0), NextCallIndex(1), @@ -957,7 +936,9 @@ namespace { /*CallExpr=*/nullptr, CallRef()), EvaluatingDecl((const ValueDecl *)nullptr), EvaluatingDeclValue(nullptr), HasActiveDiagnostic(false), - HasFoldFailureDiagnostic(false), EvalMode(Mode) {} + HasFoldFailureDiagnostic(false) { + EvalMode = Mode; + } ~EvalInfo() { discardCleanups(); @@ -1132,18 +1113,18 @@ namespace { // unless we require this evaluation to produce a constant expression. // // FIXME: We might want to show both diagnostics to the user in - // EM_ConstantFold mode. + // EvaluationMode::ConstantFold mode. bool hasPriorDiagnostic() override { if (!EvalStatus.Diag->empty()) { switch (EvalMode) { - case EM_ConstantFold: - case EM_IgnoreSideEffects: + case EvaluationMode::ConstantFold: + case EvaluationMode::IgnoreSideEffects: if (!HasFoldFailureDiagnostic) break; // We've already failed to fold something. Keep that diagnostic. [[fallthrough]]; - case EM_ConstantExpression: - case EM_ConstantExpressionUnevaluated: + case EvaluationMode::ConstantExpression: + case EvaluationMode::ConstantExpressionUnevaluated: setActiveDiagnostic(false); return true; } @@ -1158,12 +1139,12 @@ namespace { /// couldn't model? bool keepEvaluatingAfterSideEffect() const override { switch (EvalMode) { - case EM_IgnoreSideEffects: + case EvaluationMode::IgnoreSideEffects: return true; - case EM_ConstantExpression: - case EM_ConstantExpressionUnevaluated: - case EM_ConstantFold: + case EvaluationMode::ConstantExpression: + case EvaluationMode::ConstantExpressionUnevaluated: + case EvaluationMode::ConstantFold: // By default, assume any side effect might be valid in some other // evaluation of this expression from a different context. return checkingPotentialConstantExpression() || @@ -1182,12 +1163,12 @@ namespace { /// Should we continue evaluation after encountering undefined behavior? bool keepEvaluatingAfterUndefinedBehavior() { switch (EvalMode) { - case EM_IgnoreSideEffects: - case EM_ConstantFold: + case EvaluationMode::IgnoreSideEffects: + case EvaluationMode::ConstantFold: return true; - case EM_ConstantExpression: - case EM_ConstantExpressionUnevaluated: + case EvaluationMode::ConstantExpression: + case EvaluationMode::ConstantExpressionUnevaluated: return checkingForUndefinedBehavior(); } llvm_unreachable("Missed EvalMode case"); @@ -1208,10 +1189,10 @@ namespace { return false; switch (EvalMode) { - case EM_ConstantExpression: - case EM_ConstantExpressionUnevaluated: - case EM_ConstantFold: - case EM_IgnoreSideEffects: + case EvaluationMode::ConstantExpression: + case EvaluationMode::ConstantExpressionUnevaluated: + case EvaluationMode::ConstantFold: + case EvaluationMode::IgnoreSideEffects: return checkingPotentialConstantExpression() || checkingForUndefinedBehavior(); } @@ -1261,7 +1242,7 @@ namespace { EvalInfo &Info; bool Enabled; bool HadNoPriorDiags; - EvalInfo::EvaluationMode OldMode; + EvaluationMode OldMode; explicit FoldConstant(EvalInfo &Info, bool Enabled) : Info(Info), @@ -1271,7 +1252,7 @@ namespace { !Info.EvalStatus.HasSideEffects), OldMode(Info.EvalMode) { if (Enabled) - Info.EvalMode = EvalInfo::EM_ConstantFold; + Info.EvalMode = EvaluationMode::ConstantFold; } void keepDiagnostics() { Enabled = false; } ~FoldConstant() { @@ -1286,10 +1267,10 @@ namespace { /// side-effects. struct IgnoreSideEffectsRAII { EvalInfo &Info; - EvalInfo::EvaluationMode OldMode; + EvaluationMode OldMode; explicit IgnoreSideEffectsRAII(EvalInfo &Info) : Info(Info), OldMode(Info.EvalMode) { - Info.EvalMode = EvalInfo::EM_IgnoreSideEffects; + Info.EvalMode = EvaluationMode::IgnoreSideEffects; } ~IgnoreSideEffectsRAII() { Info.EvalMode = OldMode; } @@ -9188,7 +9169,7 @@ bool LValueExprEvaluator::VisitMaterializeTemporaryExpr( // value for use outside this evaluation. APValue *Value; if (E->getStorageDuration() == SD_Static) { - if (Info.EvalMode == EvalInfo::EM_ConstantFold) + if (Info.EvalMode == EvaluationMode::ConstantFold) return false; // FIXME: What about SD_Thread? Value = E->getOrCreateValue(true); @@ -13576,12 +13557,12 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E, // Expression had no side effects, but we couldn't statically determine the // size of the referenced object. switch (Info.EvalMode) { - case EvalInfo::EM_ConstantExpression: - case EvalInfo::EM_ConstantFold: - case EvalInfo::EM_IgnoreSideEffects: + case EvaluationMode::ConstantExpression: + case EvaluationMode::ConstantFold: + case EvaluationMode::IgnoreSideEffects: // Leave it to IR generation. return Error(E); - case EvalInfo::EM_ConstantExpressionUnevaluated: + case EvaluationMode::ConstantExpressionUnevaluated: // Reduce it to a constant now. return Success((Type & 2) ? 0 : -1, E); } @@ -17587,7 +17568,7 @@ bool Expr::EvaluateAsRValue(EvalResult &Result, const ASTContext &Ctx, assert(!isValueDependent() && "Expression evaluator can't be called on a dependent expression."); ExprTimeTraceScope TimeScope(this, Ctx, "EvaluateAsRValue"); - EvalInfo Info(Ctx, Result, EvalInfo::EM_IgnoreSideEffects); + EvalInfo Info(Ctx, Result, EvaluationMode::IgnoreSideEffects); Info.InConstantContext = InConstantContext; return ::EvaluateAsRValue(this, Result, Ctx, Info); } @@ -17608,7 +17589,7 @@ bool Expr::EvaluateAsInt(EvalResult &Result, const ASTContext &Ctx, assert(!isValueDependent() && "Expression evaluator can't be called on a dependent expression."); ExprTimeTraceScope TimeScope(this, Ctx, "EvaluateAsInt"); - EvalInfo Info(Ctx, Result, EvalInfo::EM_IgnoreSideEffects); + EvalInfo Info(Ctx, Result, EvaluationMode::IgnoreSideEffects); Info.InConstantContext = InConstantContext; return ::EvaluateAsInt(this, Result, Ctx, AllowSideEffects, Info); } @@ -17619,7 +17600,7 @@ bool Expr::EvaluateAsFixedPoint(EvalResult &Result, const ASTContext &Ctx, assert(!isValueDependent() && "Expression evaluator can't be called on a dependent expression."); ExprTimeTraceScope TimeScope(this, Ctx, "EvaluateAsFixedPoint"); - EvalInfo Info(Ctx, Result, EvalInfo::EM_IgnoreSideEffects); + EvalInfo Info(Ctx, Result, EvaluationMode::IgnoreSideEffects); Info.InConstantContext = InConstantContext; return ::EvaluateAsFixedPoint(this, Result, Ctx, AllowSideEffects, Info); } @@ -17650,7 +17631,7 @@ bool Expr::EvaluateAsLValue(EvalResult &Result, const ASTContext &Ctx, "Expression evaluator can't be called on a dependent expression."); ExprTimeTraceScope TimeScope(this, Ctx, "EvaluateAsLValue"); - EvalInfo Info(Ctx, Result, EvalInfo::EM_ConstantFold); + EvalInfo Info(Ctx, Result, EvaluationMode::ConstantFold); Info.InConstantContext = InConstantContext; LValue LV; CheckedTemporaries CheckedTemps; @@ -17670,8 +17651,8 @@ static bool EvaluateDestruction(const ASTContext &Ctx, APValue::LValueBase Base, SourceLocation Loc, Expr::EvalStatus &EStatus, bool IsConstantDestruction) { EvalInfo Info(Ctx, EStatus, - IsConstantDestruction ? EvalInfo::EM_ConstantExpression - : EvalInfo::EM_ConstantFold); + IsConstantDestruction ? EvaluationMode::ConstantExpression + : EvaluationMode::ConstantFold); Info.setEvaluatingDecl(Base, DestroyedValue, EvalInfo::EvaluatingDeclKind::Dtor); Info.InConstantContext = IsConstantDestruction; @@ -17699,7 +17680,7 @@ bool Expr::EvaluateAsConstantExpr(EvalResult &Result, const ASTContext &Ctx, return true; ExprTimeTraceScope TimeScope(this, Ctx, "EvaluateAsConstantExpr"); - EvalInfo::EvaluationMode EM = EvalInfo::EM_ConstantExpression; + EvaluationMode EM = EvaluationMode::ConstantExpression; EvalInfo Info(Ctx, Result, EM); Info.InConstantContext = true; @@ -17776,8 +17757,8 @@ bool Expr::EvaluateAsInitializer(APValue &Value, const ASTContext &Ctx, EvalInfo Info(Ctx, EStatus, (IsConstantInitialization && (Ctx.getLangOpts().CPlusPlus || Ctx.getLangOpts().C23)) - ? EvalInfo::EM_ConstantExpression - : EvalInfo::EM_ConstantFold); + ? EvaluationMode::ConstantExpression + : EvaluationMode::ConstantFold); Info.setEvaluatingDecl(VD, Value); Info.InConstantContext = IsConstantInitialization; @@ -17872,7 +17853,7 @@ APSInt Expr::EvaluateKnownConstInt(const ASTContext &Ctx, ExprTimeTraceScope TimeScope(this, Ctx, "EvaluateKnownConstInt"); EvalResult EVResult; EVResult.Diag = Diag; - EvalInfo Info(Ctx, EVResult, EvalInfo::EM_IgnoreSideEffects); + EvalInfo Info(Ctx, EVResult, EvaluationMode::IgnoreSideEffects); Info.InConstantContext = true; bool Result = ::EvaluateAsRValue(this, EVResult, Ctx, Info); @@ -17891,7 +17872,7 @@ APSInt Expr::EvaluateKnownConstIntCheckOverflow( ExprTimeTraceScope TimeScope(this, Ctx, "EvaluateKnownConstIntCheckOverflow"); EvalResult EVResult; EVResult.Diag = Diag; - EvalInfo Info(Ctx, EVResult, EvalInfo::EM_IgnoreSideEffects); + EvalInfo Info(Ctx, EVResult, EvaluationMode::IgnoreSideEffects); Info.InConstantContext = true; Info.CheckingForUndefinedBehavior = true; @@ -17911,7 +17892,7 @@ void Expr::EvaluateForOverflow(const ASTContext &Ctx) const { bool IsConst; EvalResult EVResult; if (!FastEvaluateAsRValue(this, EVResult.Val, Ctx, IsConst)) { - EvalInfo Info(Ctx, EVResult, EvalInfo::EM_IgnoreSideEffects); + EvalInfo Info(Ctx, EVResult, EvaluationMode::IgnoreSideEffects); Info.CheckingForUndefinedBehavior = true; (void)::EvaluateAsRValue(Info, this, EVResult.Val); } @@ -17965,7 +17946,7 @@ static ICEDiag Worst(ICEDiag A, ICEDiag B) { return A.Kind >= B.Kind ? A : B; } static ICEDiag CheckEvalInICE(const Expr* E, const ASTContext &Ctx) { Expr::EvalResult EVResult; Expr::EvalStatus Status; - EvalInfo Info(Ctx, Status, EvalInfo::EM_ConstantExpression); + EvalInfo Info(Ctx, Status, EvaluationMode::ConstantExpression); Info.InConstantContext = true; if (!::EvaluateAsRValue(E, EVResult, Ctx, Info) || EVResult.HasSideEffects || @@ -18449,7 +18430,7 @@ Expr::getIntegerConstantExpr(const ASTContext &Ctx) const { // value. EvalResult ExprResult; Expr::EvalStatus Status; - EvalInfo Info(Ctx, Status, EvalInfo::EM_IgnoreSideEffects); + EvalInfo Info(Ctx, Status, EvaluationMode::IgnoreSideEffects); Info.InConstantContext = true; if (!::EvaluateAsInt(this, ExprResult, Ctx, SE_AllowSideEffects, Info)) @@ -18485,7 +18466,7 @@ bool Expr::isCXX11ConstantExpr(const ASTContext &Ctx, APValue *Result) const { Expr::EvalStatus Status; SmallVector<PartialDiagnosticAt, 8> Diags; Status.Diag = &Diags; - EvalInfo Info(Ctx, Status, EvalInfo::EM_ConstantExpression); + EvalInfo Info(Ctx, Status, EvaluationMode::ConstantExpression); bool IsConstExpr = ::EvaluateAsRValue(Info, this, Result ? *Result : Scratch) && @@ -18512,7 +18493,7 @@ bool Expr::EvaluateWithSubstitution(APValue &Value, ASTContext &Ctx, }); Expr::EvalStatus Status; - EvalInfo Info(Ctx, Status, EvalInfo::EM_ConstantExpressionUnevaluated); + EvalInfo Info(Ctx, Status, EvaluationMode::ConstantExpressionUnevaluated); Info.InConstantContext = true; LValue ThisVal; @@ -18588,7 +18569,8 @@ bool Expr::isPotentialConstantExpr(const FunctionDecl *FD, Expr::EvalStatus Status; Status.Diag = &Diags; - EvalInfo Info(FD->getASTContext(), Status, EvalInfo::EM_ConstantExpression); + EvalInfo Info(FD->getASTContext(), Status, + EvaluationMode::ConstantExpression); Info.InConstantContext = true; Info.CheckingPotentialConstantExpression = true; @@ -18638,7 +18620,7 @@ bool Expr::isPotentialConstantExprUnevaluated(Expr *E, Status.Diag = &Diags; EvalInfo Info(FD->getASTContext(), Status, - EvalInfo::EM_ConstantExpressionUnevaluated); + EvaluationMode::ConstantExpressionUnevaluated); Info.InConstantContext = true; Info.CheckingPotentialConstantExpression = true; @@ -18662,7 +18644,7 @@ bool Expr::tryEvaluateObjectSize(uint64_t &Result, ASTContext &Ctx, return false; Expr::EvalStatus Status; - EvalInfo Info(Ctx, Status, EvalInfo::EM_ConstantFold); + EvalInfo Info(Ctx, Status, EvaluationMode::ConstantFold); return tryEvaluateBuiltinObjectSize(this, Type, Info, Result); } @@ -18720,7 +18702,7 @@ static bool EvaluateBuiltinStrLen(const Expr *E, uint64_t &Result, std::optional<std::string> Expr::tryEvaluateString(ASTContext &Ctx) const { Expr::EvalStatus Status; - EvalInfo Info(Ctx, Status, EvalInfo::EM_ConstantFold); + EvalInfo Info(Ctx, Status, EvaluationMode::ConstantFold); uint64_t Result; std::string StringResult; @@ -18735,7 +18717,7 @@ static bool EvaluateCharRangeAsStringImpl(const Expr *, T &Result, const Expr *PtrExpression, ASTContext &Ctx, Expr::EvalResult &Status) { - EvalInfo Info(Ctx, Status, EvalInfo::EM_ConstantExpression); + EvalInfo Info(Ctx, Status, EvaluationMode::ConstantExpression); Info.InConstantContext = true; if (Info.EnableNewConstInterp) @@ -18803,7 +18785,7 @@ bool Expr::EvaluateCharRangeAsString(APValue &Result, bool Expr::tryEvaluateStrLen(uint64_t &Result, ASTContext &Ctx) const { Expr::EvalStatus Status; - EvalInfo Info(Ctx, Status, EvalInfo::EM_ConstantFold); + EvalInfo Info(Ctx, Status, EvaluationMode::ConstantFold); if (Info.EnableNewConstInterp) return Info.Ctx.getInterpContext().evaluateStrlen(Info, this, Result); `````````` </details> https://github.com/llvm/llvm-project/pull/157988 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits