@@ -794,58 +794,47 @@ namespace {
794794 // / constant value.
795795 bool InConstantContext;
796796
797+ // / Whether we're checking that an expression is a potential constant
798+ // / expression. If so, do not fail on constructs that could become constant
799+ // / later on (such as a use of an undefined global).
800+ bool CheckingPotentialConstantExpression = false ;
801+
802+ // / Whether we're checking for an expression that has undefined behavior.
803+ // / If so, we will produce warnings if we encounter an operation that is
804+ // / always undefined.
805+ bool CheckingForUndefinedBehavior = false ;
806+
797807 enum EvaluationMode {
798808 // / Evaluate as a constant expression. Stop if we find that the expression
799809 // / is not a constant expression.
800810 EM_ConstantExpression,
801811
802- // / Evaluate as a potential constant expression. Keep going if we hit a
803- // / construct that we can't evaluate yet (because we don't yet know the
804- // / value of something) but stop if we hit something that could never be
805- // / a constant expression.
806- EM_PotentialConstantExpression,
812+ // / Evaluate as a constant expression. Stop if we find that the expression
813+ // / is not a constant expression. Some expressions can be retried in the
814+ // / optimizer if we don't constant fold them here, but in an unevaluated
815+ // / context we try to fold them immediately since the optimizer never
816+ // / gets a chance to look at it.
817+ EM_ConstantExpressionUnevaluated,
807818
808819 // / Fold the expression to a constant. Stop if we hit a side-effect that
809820 // / we can't model.
810821 EM_ConstantFold,
811822
812- // / Evaluate the expression looking for integer overflow and similar
813- // / issues. Don't worry about side-effects, and try to visit all
814- // / subexpressions.
815- EM_EvaluateForOverflow,
816-
817823 // / Evaluate in any way we know how. Don't worry about side-effects that
818824 // / can't be modeled.
819825 EM_IgnoreSideEffects,
820-
821- // / Evaluate as a constant expression. Stop if we find that the expression
822- // / is not a constant expression. Some expressions can be retried in the
823- // / optimizer if we don't constant fold them here, but in an unevaluated
824- // / context we try to fold them immediately since the optimizer never
825- // / gets a chance to look at it.
826- EM_ConstantExpressionUnevaluated,
827-
828- // / Evaluate as a potential constant expression. Keep going if we hit a
829- // / construct that we can't evaluate yet (because we don't yet know the
830- // / value of something) but stop if we hit something that could never be
831- // / a constant expression. Some expressions can be retried in the
832- // / optimizer if we don't constant fold them here, but in an unevaluated
833- // / context we try to fold them immediately since the optimizer never
834- // / gets a chance to look at it.
835- EM_PotentialConstantExpressionUnevaluated,
836826 } EvalMode;
837827
838828 // / Are we checking whether the expression is a potential constant
839829 // / expression?
840830 bool checkingPotentialConstantExpression () const {
841- return EvalMode == EM_PotentialConstantExpression ||
842- EvalMode == EM_PotentialConstantExpressionUnevaluated;
831+ return CheckingPotentialConstantExpression;
843832 }
844833
845834 // / Are we checking an expression for overflow?
846835 // FIXME: We should check for any kind of undefined or suspicious behavior
847836 // in such constructs, not just overflow.
848- bool checkingForOverflow () { return EvalMode == EM_EvaluateForOverflow ; }
837+ bool checkingForUndefinedBehavior () { return CheckingForUndefinedBehavior ; }
849838
850839 EvalInfo (const ASTContext &C, Expr::EvalStatus &S, EvaluationMode Mode)
851840 : Ctx(const_cast <ASTContext &>(C)), EvalStatus(S), CurrentCall(nullptr ),
@@ -932,15 +921,12 @@ namespace {
932921 switch (EvalMode) {
933922 case EM_ConstantFold:
934923 case EM_IgnoreSideEffects:
935- case EM_EvaluateForOverflow:
936924 if (!HasFoldFailureDiagnostic)
937925 break ;
938926 // We've already failed to fold something. Keep that diagnostic.
939927 LLVM_FALLTHROUGH;
940928 case EM_ConstantExpression:
941- case EM_PotentialConstantExpression:
942929 case EM_ConstantExpressionUnevaluated:
943- case EM_PotentialConstantExpressionUnevaluated:
944930 HasActiveDiagnostic = false ;
945931 return OptionalDiagnostic ();
946932 }
@@ -986,8 +972,8 @@ namespace {
986972 // / Diagnose that the evaluation does not produce a C++11 core constant
987973 // / expression.
988974 // /
989- // / FIXME: Stop evaluating if we're in EM_ConstantExpression or
990- // / EM_PotentialConstantExpression mode and we produce one of these.
975+ // / FIXME: Stop evaluating if we're in EM_ConstantExpression mode
976+ // / and we produce one of these.
991977 OptionalDiagnostic CCEDiag (SourceLocation Loc, diag::kind DiagId
992978 = diag::note_invalid_subexpr_in_const_expr,
993979 unsigned ExtraNotes = 0 ) {
@@ -1023,16 +1009,16 @@ namespace {
10231009 // / couldn't model?
10241010 bool keepEvaluatingAfterSideEffect () {
10251011 switch (EvalMode) {
1026- case EM_PotentialConstantExpression:
1027- case EM_PotentialConstantExpressionUnevaluated:
1028- case EM_EvaluateForOverflow:
10291012 case EM_IgnoreSideEffects:
10301013 return true ;
10311014
10321015 case EM_ConstantExpression:
10331016 case EM_ConstantExpressionUnevaluated:
10341017 case EM_ConstantFold:
1035- return false ;
1018+ // By default, assume any side effect might be valid in some other
1019+ // evaluation of this expression from a different context.
1020+ return checkingPotentialConstantExpression () ||
1021+ checkingForUndefinedBehavior ();
10361022 }
10371023 llvm_unreachable (" Missed EvalMode case" );
10381024 }
@@ -1047,16 +1033,13 @@ namespace {
10471033 // / Should we continue evaluation after encountering undefined behavior?
10481034 bool keepEvaluatingAfterUndefinedBehavior () {
10491035 switch (EvalMode) {
1050- case EM_EvaluateForOverflow:
10511036 case EM_IgnoreSideEffects:
10521037 case EM_ConstantFold:
10531038 return true ;
10541039
1055- case EM_PotentialConstantExpression:
1056- case EM_PotentialConstantExpressionUnevaluated:
10571040 case EM_ConstantExpression:
10581041 case EM_ConstantExpressionUnevaluated:
1059- return false ;
1042+ return checkingForUndefinedBehavior () ;
10601043 }
10611044 llvm_unreachable (" Missed EvalMode case" );
10621045 }
@@ -1076,16 +1059,12 @@ namespace {
10761059 return false ;
10771060
10781061 switch (EvalMode) {
1079- case EM_PotentialConstantExpression:
1080- case EM_PotentialConstantExpressionUnevaluated:
1081- case EM_EvaluateForOverflow:
1082- return true ;
1083-
10841062 case EM_ConstantExpression:
10851063 case EM_ConstantExpressionUnevaluated:
10861064 case EM_ConstantFold:
10871065 case EM_IgnoreSideEffects:
1088- return false ;
1066+ return checkingPotentialConstantExpression () ||
1067+ checkingForUndefinedBehavior ();
10891068 }
10901069 llvm_unreachable (" Missed EvalMode case" );
10911070 }
@@ -1142,9 +1121,7 @@ namespace {
11421121 Info.EvalStatus.Diag->empty () &&
11431122 !Info.EvalStatus.HasSideEffects),
11441123 OldMode(Info.EvalMode) {
1145- if (Enabled &&
1146- (Info.EvalMode == EvalInfo::EM_ConstantExpression ||
1147- Info.EvalMode == EvalInfo::EM_ConstantExpressionUnevaluated))
1124+ if (Enabled)
11481125 Info.EvalMode = EvalInfo::EM_ConstantFold;
11491126 }
11501127 void keepDiagnostics () { Enabled = false ; }
@@ -1163,8 +1140,7 @@ namespace {
11631140 EvalInfo::EvaluationMode OldMode;
11641141 explicit IgnoreSideEffectsRAII (EvalInfo &Info)
11651142 : Info(Info), OldMode(Info.EvalMode) {
1166- if (!Info.checkingPotentialConstantExpression ())
1167- Info.EvalMode = EvalInfo::EM_IgnoreSideEffects;
1143+ Info.EvalMode = EvalInfo::EM_IgnoreSideEffects;
11681144 }
11691145
11701146 ~IgnoreSideEffectsRAII () { Info.EvalMode = OldMode; }
@@ -2323,7 +2299,7 @@ static bool CheckedIntArithmetic(EvalInfo &Info, const Expr *E,
23232299 APSInt Value (Op (LHS.extend (BitWidth), RHS.extend (BitWidth)), false );
23242300 Result = Value.trunc (LHS.getBitWidth ());
23252301 if (Result.extend (BitWidth) != Value) {
2326- if (Info.checkingForOverflow ())
2302+ if (Info.checkingForUndefinedBehavior ())
23272303 Info.Ctx .getDiagnostics ().Report (E->getExprLoc (),
23282304 diag::warn_integer_constant_overflow)
23292305 << Result.toString (10 ) << E->getType ();
@@ -6047,6 +6023,8 @@ class ExprEvaluatorBase
60476023
60486024 // Always assume __builtin_constant_p(...) ? ... : ... is a potential
60496025 // constant expression; we can't check whether it's potentially foldable.
6026+ // FIXME: We should instead treat __builtin_constant_p as non-constant if
6027+ // it would return 'false' in this mode.
60506028 if (Info.checkingPotentialConstantExpression () && IsBcpCall)
60516029 return false ;
60526030
@@ -6329,7 +6307,7 @@ class ExprEvaluatorBase
63296307 bool VisitStmtExpr (const StmtExpr *E) {
63306308 // We will have checked the full-expressions inside the statement expression
63316309 // when they were completed, and don't need to check them again now.
6332- if (Info.checkingForOverflow ())
6310+ if (Info.checkingForUndefinedBehavior ())
63336311 return Error (E);
63346312
63356313 BlockScopeRAII Scope (Info);
@@ -9499,14 +9477,11 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E,
94999477 // size of the referenced object.
95009478 switch (Info.EvalMode ) {
95019479 case EvalInfo::EM_ConstantExpression:
9502- case EvalInfo::EM_PotentialConstantExpression:
95039480 case EvalInfo::EM_ConstantFold:
9504- case EvalInfo::EM_EvaluateForOverflow:
95059481 case EvalInfo::EM_IgnoreSideEffects:
95069482 // Leave it to IR generation.
95079483 return Error (E);
95089484 case EvalInfo::EM_ConstantExpressionUnevaluated:
9509- case EvalInfo::EM_PotentialConstantExpressionUnevaluated:
95109485 // Reduce it to a constant now.
95119486 return Success ((Type & 2 ) ? 0 : -1 , E);
95129487 }
@@ -12546,8 +12521,9 @@ APSInt Expr::EvaluateKnownConstIntCheckOverflow(
1254612521
1254712522 EvalResult EVResult;
1254812523 EVResult.Diag = Diag;
12549- EvalInfo Info (Ctx, EVResult, EvalInfo::EM_EvaluateForOverflow );
12524+ EvalInfo Info (Ctx, EVResult, EvalInfo::EM_IgnoreSideEffects );
1255012525 Info.InConstantContext = true ;
12526+ Info.CheckingForUndefinedBehavior = true ;
1255112527
1255212528 bool Result = ::EvaluateAsRValue (Info, this , EVResult.Val );
1255312529 (void )Result;
@@ -12564,7 +12540,8 @@ void Expr::EvaluateForOverflow(const ASTContext &Ctx) const {
1256412540 bool IsConst;
1256512541 EvalResult EVResult;
1256612542 if (!FastEvaluateAsRValue (this , EVResult, Ctx, IsConst)) {
12567- EvalInfo Info (Ctx, EVResult, EvalInfo::EM_EvaluateForOverflow);
12543+ EvalInfo Info (Ctx, EVResult, EvalInfo::EM_IgnoreSideEffects);
12544+ Info.CheckingForUndefinedBehavior = true ;
1256812545 (void )::EvaluateAsRValue (Info, this , EVResult.Val );
1256912546 }
1257012547}
@@ -13178,9 +13155,9 @@ bool Expr::isPotentialConstantExpr(const FunctionDecl *FD,
1317813155 Expr::EvalStatus Status;
1317913156 Status.Diag = &Diags;
1318013157
13181- EvalInfo Info (FD->getASTContext (), Status,
13182- EvalInfo::EM_PotentialConstantExpression);
13158+ EvalInfo Info (FD->getASTContext (), Status, EvalInfo::EM_ConstantExpression);
1318313159 Info.InConstantContext = true ;
13160+ Info.CheckingPotentialConstantExpression = true ;
1318413161
1318513162 const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD);
1318613163 const CXXRecordDecl *RD = MD ? MD->getParent ()->getCanonicalDecl () : nullptr ;
@@ -13219,8 +13196,9 @@ bool Expr::isPotentialConstantExprUnevaluated(Expr *E,
1321913196 Status.Diag = &Diags;
1322013197
1322113198 EvalInfo Info (FD->getASTContext (), Status,
13222- EvalInfo::EM_PotentialConstantExpressionUnevaluated );
13199+ EvalInfo::EM_ConstantExpressionUnevaluated );
1322313200 Info.InConstantContext = true ;
13201+ Info.CheckingPotentialConstantExpression = true ;
1322413202
1322513203 // Fabricate a call stack frame to give the arguments a plausible cover story.
1322613204 ArrayRef<const Expr*> Args;
0 commit comments