aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/AST/ExprConstant.cpp
diff options
context:
space:
mode:
authorShafik Yaghmour <shafik.yaghmour@intel.com>2022-08-17 13:54:14 -0700
committerShafik Yaghmour <shafik.yaghmour@intel.com>2022-08-17 14:14:00 -0700
commit8de51375f12d91675a18d17f262276e65f43fbe0 (patch)
treed4b8b8fa1d420b19147a185b5955a1fc3fb00e42 /clang/lib/AST/ExprConstant.cpp
parentaa41fe664ab203257e2336bd8f33f5dcc91b5101 (diff)
downloadllvm-8de51375f12d91675a18d17f262276e65f43fbe0.zip
llvm-8de51375f12d91675a18d17f262276e65f43fbe0.tar.gz
llvm-8de51375f12d91675a18d17f262276e65f43fbe0.tar.bz2
[Clang] Tighten restrictions on enum out of range diagnostic to avoid constant initialization
The restrictions added in D131704 were not sufficient to avoid all non-constant expression contexts. In particular constant initialization cases. We need to check EvaluatingDecl to detect if the variable we are initializing is constexpr or not. At this point it looks like this is the remaining case affecting various projects with this diagnostic. Differential Revision: https://reviews.llvm.org/D131874
Diffstat (limited to 'clang/lib/AST/ExprConstant.cpp')
-rw-r--r--clang/lib/AST/ExprConstant.cpp23
1 files changed, 18 insertions, 5 deletions
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index f8de0f2..3df0e4292 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -13536,6 +13536,18 @@ bool IntExprEvaluator::VisitCastExpr(const CastExpr *E) {
if (Info.Ctx.getLangOpts().CPlusPlus && Info.InConstantContext &&
Info.EvalMode == EvalInfo::EM_ConstantExpression &&
DestType->isEnumeralType()) {
+
+ bool ConstexprVar = true;
+
+ // We know if we are here that we are in a context that we might require
+ // a constant expression or a context that requires a constant
+ // value. But if we are initializing a value we don't know if it is a
+ // constexpr variable or not. We can check the EvaluatingDecl to determine
+ // if it constexpr or not. If not then we don't want to emit a diagnostic.
+ if (const auto *VD = dyn_cast_or_null<VarDecl>(
+ Info.EvaluatingDecl.dyn_cast<const ValueDecl *>()))
+ ConstexprVar = VD->isConstexpr();
+
const EnumType *ET = dyn_cast<EnumType>(DestType.getCanonicalType());
const EnumDecl *ED = ET->getDecl();
// Check that the value is within the range of the enumeration values.
@@ -13555,13 +13567,14 @@ bool IntExprEvaluator::VisitCastExpr(const CastExpr *E) {
ED->getValueRange(Max, Min);
--Max;
- if (ED->getNumNegativeBits() &&
+ if (ED->getNumNegativeBits() && ConstexprVar &&
(Max.slt(Result.getInt().getSExtValue()) ||
Min.sgt(Result.getInt().getSExtValue())))
- Info.Ctx.getDiagnostics().Report(E->getExprLoc(),
- diag::warn_constexpr_unscoped_enum_out_of_range)
- << llvm::toString(Result.getInt(),10) << Min.getSExtValue() << Max.getSExtValue();
- else if (!ED->getNumNegativeBits() &&
+ Info.Ctx.getDiagnostics().Report(
+ E->getExprLoc(), diag::warn_constexpr_unscoped_enum_out_of_range)
+ << llvm::toString(Result.getInt(), 10) << Min.getSExtValue()
+ << Max.getSExtValue();
+ else if (!ED->getNumNegativeBits() && ConstexprVar &&
Max.ult(Result.getInt().getZExtValue()))
Info.Ctx.getDiagnostics().Report(E->getExprLoc(),
diag::warn_constexpr_unscoped_enum_out_of_range)