diff options
author | Shafik Yaghmour <shafik.yaghmour@intel.com> | 2022-08-17 13:54:14 -0700 |
---|---|---|
committer | Shafik Yaghmour <shafik.yaghmour@intel.com> | 2022-08-17 14:14:00 -0700 |
commit | 8de51375f12d91675a18d17f262276e65f43fbe0 (patch) | |
tree | d4b8b8fa1d420b19147a185b5955a1fc3fb00e42 /clang/lib/AST/ExprConstant.cpp | |
parent | aa41fe664ab203257e2336bd8f33f5dcc91b5101 (diff) | |
download | llvm-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.cpp | 23 |
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) |