forked from OSchip/llvm-project
Added an assertion to constant evaluation enty points that prohibits dependent expressions
Summary: Constant evaluator does not work on value-dependent or type-dependent expressions. Also fixed bugs uncovered by these assertions. Subscribers: cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D61522 llvm-svn: 361050
This commit is contained in:
parent
5d95b11b6b
commit
04323c24a1
|
@ -2974,6 +2974,9 @@ bool Expr::hasAnyTypeDependentArguments(ArrayRef<Expr *> Exprs) {
|
|||
|
||||
bool Expr::isConstantInitializer(ASTContext &Ctx, bool IsForRef,
|
||||
const Expr **Culprit) const {
|
||||
assert(!isValueDependent() &&
|
||||
"Expression evaluator can't be called on a dependent expression.");
|
||||
|
||||
// This function is attempting whether an expression is an initializer
|
||||
// which can be evaluated at compile-time. It very closely parallels
|
||||
// ConstExprEmitter in CGExprConstant.cpp; if they don't match, it
|
||||
|
|
|
@ -11642,6 +11642,8 @@ static bool EvaluateAsFixedPoint(const Expr *E, Expr::EvalResult &ExprResult,
|
|||
/// will be applied to the result.
|
||||
bool Expr::EvaluateAsRValue(EvalResult &Result, const ASTContext &Ctx,
|
||||
bool InConstantContext) const {
|
||||
assert(!isValueDependent() &&
|
||||
"Expression evaluator can't be called on a dependent expression.");
|
||||
EvalInfo Info(Ctx, Result, EvalInfo::EM_IgnoreSideEffects);
|
||||
Info.InConstantContext = InConstantContext;
|
||||
return ::EvaluateAsRValue(this, Result, Ctx, Info);
|
||||
|
@ -11649,6 +11651,8 @@ bool Expr::EvaluateAsRValue(EvalResult &Result, const ASTContext &Ctx,
|
|||
|
||||
bool Expr::EvaluateAsBooleanCondition(bool &Result,
|
||||
const ASTContext &Ctx) const {
|
||||
assert(!isValueDependent() &&
|
||||
"Expression evaluator can't be called on a dependent expression.");
|
||||
EvalResult Scratch;
|
||||
return EvaluateAsRValue(Scratch, Ctx) &&
|
||||
HandleConversionToBool(Scratch.Val, Result);
|
||||
|
@ -11656,18 +11660,25 @@ bool Expr::EvaluateAsBooleanCondition(bool &Result,
|
|||
|
||||
bool Expr::EvaluateAsInt(EvalResult &Result, const ASTContext &Ctx,
|
||||
SideEffectsKind AllowSideEffects) const {
|
||||
assert(!isValueDependent() &&
|
||||
"Expression evaluator can't be called on a dependent expression.");
|
||||
EvalInfo Info(Ctx, Result, EvalInfo::EM_IgnoreSideEffects);
|
||||
return ::EvaluateAsInt(this, Result, Ctx, AllowSideEffects, Info);
|
||||
}
|
||||
|
||||
bool Expr::EvaluateAsFixedPoint(EvalResult &Result, const ASTContext &Ctx,
|
||||
SideEffectsKind AllowSideEffects) const {
|
||||
assert(!isValueDependent() &&
|
||||
"Expression evaluator can't be called on a dependent expression.");
|
||||
EvalInfo Info(Ctx, Result, EvalInfo::EM_IgnoreSideEffects);
|
||||
return ::EvaluateAsFixedPoint(this, Result, Ctx, AllowSideEffects, Info);
|
||||
}
|
||||
|
||||
bool Expr::EvaluateAsFloat(APFloat &Result, const ASTContext &Ctx,
|
||||
SideEffectsKind AllowSideEffects) const {
|
||||
assert(!isValueDependent() &&
|
||||
"Expression evaluator can't be called on a dependent expression.");
|
||||
|
||||
if (!getType()->isRealFloatingType())
|
||||
return false;
|
||||
|
||||
|
@ -11681,6 +11692,9 @@ bool Expr::EvaluateAsFloat(APFloat &Result, const ASTContext &Ctx,
|
|||
}
|
||||
|
||||
bool Expr::EvaluateAsLValue(EvalResult &Result, const ASTContext &Ctx) const {
|
||||
assert(!isValueDependent() &&
|
||||
"Expression evaluator can't be called on a dependent expression.");
|
||||
|
||||
EvalInfo Info(Ctx, Result, EvalInfo::EM_ConstantFold);
|
||||
|
||||
LValue LV;
|
||||
|
@ -11696,6 +11710,9 @@ bool Expr::EvaluateAsLValue(EvalResult &Result, const ASTContext &Ctx) const {
|
|||
|
||||
bool Expr::EvaluateAsConstantExpr(EvalResult &Result, ConstExprUsage Usage,
|
||||
const ASTContext &Ctx) const {
|
||||
assert(!isValueDependent() &&
|
||||
"Expression evaluator can't be called on a dependent expression.");
|
||||
|
||||
EvalInfo::EvaluationMode EM = EvalInfo::EM_ConstantExpression;
|
||||
EvalInfo Info(Ctx, Result, EM);
|
||||
Info.InConstantContext = true;
|
||||
|
@ -11710,6 +11727,9 @@ bool Expr::EvaluateAsConstantExpr(EvalResult &Result, ConstExprUsage Usage,
|
|||
bool Expr::EvaluateAsInitializer(APValue &Value, const ASTContext &Ctx,
|
||||
const VarDecl *VD,
|
||||
SmallVectorImpl<PartialDiagnosticAt> &Notes) const {
|
||||
assert(!isValueDependent() &&
|
||||
"Expression evaluator can't be called on a dependent expression.");
|
||||
|
||||
// FIXME: Evaluating initializers for large array and record types can cause
|
||||
// performance problems. Only do so in C++11 for now.
|
||||
if (isRValue() && (getType()->isArrayType() || getType()->isRecordType()) &&
|
||||
|
@ -11752,6 +11772,9 @@ bool Expr::EvaluateAsInitializer(APValue &Value, const ASTContext &Ctx,
|
|||
/// isEvaluatable - Call EvaluateAsRValue to see if this expression can be
|
||||
/// constant folded, but discard the result.
|
||||
bool Expr::isEvaluatable(const ASTContext &Ctx, SideEffectsKind SEK) const {
|
||||
assert(!isValueDependent() &&
|
||||
"Expression evaluator can't be called on a dependent expression.");
|
||||
|
||||
EvalResult Result;
|
||||
return EvaluateAsRValue(Result, Ctx, /* in constant context */ true) &&
|
||||
!hasUnacceptableSideEffect(Result, SEK);
|
||||
|
@ -11759,6 +11782,9 @@ bool Expr::isEvaluatable(const ASTContext &Ctx, SideEffectsKind SEK) const {
|
|||
|
||||
APSInt Expr::EvaluateKnownConstInt(const ASTContext &Ctx,
|
||||
SmallVectorImpl<PartialDiagnosticAt> *Diag) const {
|
||||
assert(!isValueDependent() &&
|
||||
"Expression evaluator can't be called on a dependent expression.");
|
||||
|
||||
EvalResult EVResult;
|
||||
EVResult.Diag = Diag;
|
||||
EvalInfo Info(Ctx, EVResult, EvalInfo::EM_IgnoreSideEffects);
|
||||
|
@ -11774,6 +11800,9 @@ APSInt Expr::EvaluateKnownConstInt(const ASTContext &Ctx,
|
|||
|
||||
APSInt Expr::EvaluateKnownConstIntCheckOverflow(
|
||||
const ASTContext &Ctx, SmallVectorImpl<PartialDiagnosticAt> *Diag) const {
|
||||
assert(!isValueDependent() &&
|
||||
"Expression evaluator can't be called on a dependent expression.");
|
||||
|
||||
EvalResult EVResult;
|
||||
EVResult.Diag = Diag;
|
||||
EvalInfo Info(Ctx, EVResult, EvalInfo::EM_EvaluateForOverflow);
|
||||
|
@ -11788,6 +11817,9 @@ APSInt Expr::EvaluateKnownConstIntCheckOverflow(
|
|||
}
|
||||
|
||||
void Expr::EvaluateForOverflow(const ASTContext &Ctx) const {
|
||||
assert(!isValueDependent() &&
|
||||
"Expression evaluator can't be called on a dependent expression.");
|
||||
|
||||
bool IsConst;
|
||||
EvalResult EVResult;
|
||||
if (!FastEvaluateAsRValue(this, EVResult, Ctx, IsConst)) {
|
||||
|
@ -12269,6 +12301,9 @@ static bool EvaluateCPlusPlus11IntegralConstantExpr(const ASTContext &Ctx,
|
|||
|
||||
bool Expr::isIntegerConstantExpr(const ASTContext &Ctx,
|
||||
SourceLocation *Loc) const {
|
||||
assert(!isValueDependent() &&
|
||||
"Expression evaluator can't be called on a dependent expression.");
|
||||
|
||||
if (Ctx.getLangOpts().CPlusPlus11)
|
||||
return EvaluateCPlusPlus11IntegralConstantExpr(Ctx, this, nullptr, Loc);
|
||||
|
||||
|
@ -12282,6 +12317,9 @@ bool Expr::isIntegerConstantExpr(const ASTContext &Ctx,
|
|||
|
||||
bool Expr::isIntegerConstantExpr(llvm::APSInt &Value, const ASTContext &Ctx,
|
||||
SourceLocation *Loc, bool isEvaluated) const {
|
||||
assert(!isValueDependent() &&
|
||||
"Expression evaluator can't be called on a dependent expression.");
|
||||
|
||||
if (Ctx.getLangOpts().CPlusPlus11)
|
||||
return EvaluateCPlusPlus11IntegralConstantExpr(Ctx, this, &Value, Loc);
|
||||
|
||||
|
@ -12305,11 +12343,17 @@ bool Expr::isIntegerConstantExpr(llvm::APSInt &Value, const ASTContext &Ctx,
|
|||
}
|
||||
|
||||
bool Expr::isCXX98IntegralConstantExpr(const ASTContext &Ctx) const {
|
||||
assert(!isValueDependent() &&
|
||||
"Expression evaluator can't be called on a dependent expression.");
|
||||
|
||||
return CheckICE(this, Ctx).Kind == IK_ICE;
|
||||
}
|
||||
|
||||
bool Expr::isCXX11ConstantExpr(const ASTContext &Ctx, APValue *Result,
|
||||
SourceLocation *Loc) const {
|
||||
assert(!isValueDependent() &&
|
||||
"Expression evaluator can't be called on a dependent expression.");
|
||||
|
||||
// We support this checking in C++98 mode in order to diagnose compatibility
|
||||
// issues.
|
||||
assert(Ctx.getLangOpts().CPlusPlus);
|
||||
|
@ -12338,6 +12382,9 @@ bool Expr::EvaluateWithSubstitution(APValue &Value, ASTContext &Ctx,
|
|||
const FunctionDecl *Callee,
|
||||
ArrayRef<const Expr*> Args,
|
||||
const Expr *This) const {
|
||||
assert(!isValueDependent() &&
|
||||
"Expression evaluator can't be called on a dependent expression.");
|
||||
|
||||
Expr::EvalStatus Status;
|
||||
EvalInfo Info(Ctx, Status, EvalInfo::EM_ConstantExpressionUnevaluated);
|
||||
Info.InConstantContext = true;
|
||||
|
@ -12419,6 +12466,9 @@ bool Expr::isPotentialConstantExprUnevaluated(Expr *E,
|
|||
const FunctionDecl *FD,
|
||||
SmallVectorImpl<
|
||||
PartialDiagnosticAt> &Diags) {
|
||||
assert(!E->isValueDependent() &&
|
||||
"Expression evaluator can't be called on a dependent expression.");
|
||||
|
||||
Expr::EvalStatus Status;
|
||||
Status.Diag = &Diags;
|
||||
|
||||
|
|
|
@ -5894,14 +5894,21 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
|
|||
if (CollapseLoopCountExpr) {
|
||||
// Found 'collapse' clause - calculate collapse number.
|
||||
Expr::EvalResult Result;
|
||||
if (CollapseLoopCountExpr->EvaluateAsInt(Result, SemaRef.getASTContext()))
|
||||
if (!CollapseLoopCountExpr->isValueDependent() &&
|
||||
CollapseLoopCountExpr->EvaluateAsInt(Result, SemaRef.getASTContext())) {
|
||||
NestedLoopCount = Result.Val.getInt().getLimitedValue();
|
||||
} else {
|
||||
Built.clear(/*size=*/1);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
unsigned OrderedLoopCount = 1;
|
||||
if (OrderedLoopCountExpr) {
|
||||
// Found 'ordered' clause - calculate collapse number.
|
||||
Expr::EvalResult EVResult;
|
||||
if (OrderedLoopCountExpr->EvaluateAsInt(EVResult, SemaRef.getASTContext())) {
|
||||
if (!OrderedLoopCountExpr->isValueDependent() &&
|
||||
OrderedLoopCountExpr->EvaluateAsInt(EVResult,
|
||||
SemaRef.getASTContext())) {
|
||||
llvm::APSInt Result = EVResult.Val.getInt();
|
||||
if (Result.getLimitedValue() < NestedLoopCount) {
|
||||
SemaRef.Diag(OrderedLoopCountExpr->getExprLoc(),
|
||||
|
@ -5912,6 +5919,9 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
|
|||
<< CollapseLoopCountExpr->getSourceRange();
|
||||
}
|
||||
OrderedLoopCount = Result.getLimitedValue();
|
||||
} else {
|
||||
Built.clear(/*size=*/1);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
// This is helper routine for loop directives (e.g., 'for', 'simd',
|
||||
|
|
|
@ -6376,7 +6376,8 @@ EnableIfAttr *Sema::CheckEnableIf(FunctionDecl *Function, ArrayRef<Expr *> Args,
|
|||
APValue Result;
|
||||
// FIXME: This doesn't consider value-dependent cases, because doing so is
|
||||
// very difficult. Ideally, we should handle them more gracefully.
|
||||
if (!EIA->getCond()->EvaluateWithSubstitution(
|
||||
if (EIA->getCond()->isValueDependent() ||
|
||||
!EIA->getCond()->EvaluateWithSubstitution(
|
||||
Result, Context, Function, llvm::makeArrayRef(ConvertedArgs)))
|
||||
return EIA;
|
||||
|
||||
|
@ -9562,7 +9563,8 @@ static bool isFunctionAlwaysEnabled(const ASTContext &Ctx,
|
|||
const FunctionDecl *FD) {
|
||||
for (auto *EnableIf : FD->specific_attrs<EnableIfAttr>()) {
|
||||
bool AlwaysTrue;
|
||||
if (!EnableIf->getCond()->EvaluateAsBooleanCondition(AlwaysTrue, Ctx))
|
||||
if (EnableIf->getCond()->isValueDependent() ||
|
||||
!EnableIf->getCond()->EvaluateAsBooleanCondition(AlwaysTrue, Ctx))
|
||||
return false;
|
||||
if (!AlwaysTrue)
|
||||
return false;
|
||||
|
|
Loading…
Reference in New Issue