: SourceLocation());
}
ExprResult ActOnFinishFullExpr(Expr *Expr, SourceLocation CC,
- bool DiscardedValue = false);
+ bool DiscardedValue = false,
+ bool IsConstexpr = false);
StmtResult ActOnFinishFullStmt(Stmt *Stmt);
// Marks SS invalid if it represents an incomplete type.
SourceLocation ReturnLoc);
void CheckFloatComparison(SourceLocation Loc, Expr* LHS, Expr* RHS);
void CheckImplicitConversions(Expr *E, SourceLocation CC = SourceLocation());
+ void CheckForIntOverflow(Expr *E);
void CheckUnsequencedOperations(Expr *E);
/// \brief Perform semantic checks on a completed expression. This will either
/// be a full-expression or a default argument expression.
- void CheckCompletedExpr(Expr *E, SourceLocation CheckLoc = SourceLocation());
+ void CheckCompletedExpr(Expr *E, SourceLocation CheckLoc = SourceLocation(),
+ bool IsConstexpr = false);
void CheckBitFieldInitialization(SourceLocation InitLoc, FieldDecl *Field,
Expr *Init);
/// expression is a potential constant expression? If so, some diagnostics
/// are suppressed.
bool CheckingPotentialConstantExpression;
+
+ bool IntOverflowCheckMode;
- EvalInfo(const ASTContext &C, Expr::EvalStatus &S)
+ EvalInfo(const ASTContext &C, Expr::EvalStatus &S,
+ bool OverflowCheckMode=false)
: Ctx(const_cast<ASTContext&>(C)), EvalStatus(S), CurrentCall(0),
CallStackDepth(0), NextCallIndex(1),
BottomFrame(*this, SourceLocation(), 0, 0, 0),
EvaluatingDecl(0), EvaluatingDeclValue(0), HasActiveDiagnostic(false),
- CheckingPotentialConstantExpression(false) {}
+ CheckingPotentialConstantExpression(false),
+ IntOverflowCheckMode(OverflowCheckMode) {}
void setEvaluatingDecl(const VarDecl *VD, APValue &Value) {
EvaluatingDecl = VD;
return OptionalDiagnostic();
}
+ bool getIntOverflowCheckMode() { return IntOverflowCheckMode; }
+
/// Diagnose that the evaluation does not produce a C++11 core constant
/// expression.
template<typename LocArg>
/// Should we continue evaluation as much as possible after encountering a
/// construct which can't be folded?
bool keepEvaluatingAfterFailure() {
- return CheckingPotentialConstantExpression &&
- EvalStatus.Diag && EvalStatus.Diag->empty();
+ // Should return true in IntOverflowCheckMode, so that we check for
+ // overflow even if some subexpressions can't be evaluated as constants.
+ // subexpressions can't be evaluated as constants.
+ return IntOverflowCheckMode ||
+ (CheckingPotentialConstantExpression &&
+ EvalStatus.Diag && EvalStatus.Diag->empty());
}
};
APSInt Value(Op(LHS.extend(BitWidth), RHS.extend(BitWidth)), false);
APSInt Result = Value.trunc(LHS.getBitWidth());
- if (Result.extend(BitWidth) != Value)
- HandleOverflow(Info, E, Value, E->getType());
+ if (Result.extend(BitWidth) != Value) {
+ if (Info.getIntOverflowCheckMode())
+ Info.Ctx.getDiagnostics().Report(E->getExprLoc(),
+ diag::warn_integer_constant_overflow)
+ << Result.toString(10) << E->getType();
+ else
+ HandleOverflow(Info, E, Value, E->getType());
+ }
return Result;
}
return CheckConstantExpression(Info, E->getExprLoc(), E->getType(), Result);
}
-/// EvaluateAsRValue - Return true if this is a constant which we can fold using
-/// any crazy technique (that has nothing to do with language standards) that
-/// we want to. If this function returns true, it returns the folded constant
-/// in Result. If this expression is a glvalue, an lvalue-to-rvalue conversion
-/// will be applied to the result.
-bool Expr::EvaluateAsRValue(EvalResult &Result, const ASTContext &Ctx) const {
+static bool FastEvaluateAsRValue(const Expr *Exp, Expr::EvalResult &Result,
+ const ASTContext &Ctx, bool &IsConst) {
// Fast-path evaluations of integer literals, since we sometimes see files
// containing vast quantities of these.
- if (const IntegerLiteral *L = dyn_cast<IntegerLiteral>(this)) {
+ if (const IntegerLiteral *L = dyn_cast<IntegerLiteral>(Exp)) {
Result.Val = APValue(APSInt(L->getValue(),
L->getType()->isUnsignedIntegerType()));
+ IsConst = true;
return true;
}
-
+
// FIXME: Evaluating values of large array and record types can cause
// performance problems. Only do so in C++11 for now.
- if (isRValue() && (getType()->isArrayType() || getType()->isRecordType()) &&
- !Ctx.getLangOpts().CPlusPlus11)
- return false;
+ if (Exp->isRValue() && (Exp->getType()->isArrayType() ||
+ Exp->getType()->isRecordType()) &&
+ !Ctx.getLangOpts().CPlusPlus11) {
+ IsConst = false;
+ return true;
+ }
+ return false;
+}
+
+/// EvaluateAsRValue - Return true if this is a constant which we can fold using
+/// any crazy technique (that has nothing to do with language standards) that
+/// we want to. If this function returns true, it returns the folded constant
+/// in Result. If this expression is a glvalue, an lvalue-to-rvalue conversion
+/// will be applied to the result.
+bool Expr::EvaluateAsRValue(EvalResult &Result, const ASTContext &Ctx) const {
+ bool IsConst;
+ if (FastEvaluateAsRValue(this, Result, Ctx, IsConst))
+ return IsConst;
+
EvalInfo Info(Ctx, Result);
return ::EvaluateAsRValue(Info, this, Result.Val);
}
return EvalResult.Val.getInt();
}
+void Expr::EvaluateForOverflow(const ASTContext &Ctx,
+ SmallVectorImpl<PartialDiagnosticAt> *Diags) const {
+ bool IsConst;
+ EvalResult EvalResult;
+ EvalResult.Diag = Diags;
+ if (!FastEvaluateAsRValue(this, EvalResult, Ctx, IsConst)) {
+ EvalInfo Info(Ctx, EvalResult, true);
+ (void)::EvaluateAsRValue(Info, this, EvalResult.Val);
+ }
+}
+
bool Expr::EvalResult::isGlobalLValue() const {
assert(Val.isLValue());
return IsGlobalLValue(Val.getLValueBase());
AnalyzeImplicitConversions(*this, E, CC);
}
+/// Diagnose when expression is an integer constant expression and its evaluation
+/// results in integer overflow
+void Sema::CheckForIntOverflow (Expr *E) {
+ if (const BinaryOperator *BExpr = dyn_cast<BinaryOperator>(E->IgnoreParens())) {
+ unsigned Opc = BExpr->getOpcode();
+ if (Opc != BO_Add && Opc != BO_Sub && Opc != BO_Mul)
+ return;
+ llvm::SmallVector<PartialDiagnosticAt, 4> Diags;
+ E->EvaluateForOverflow(Context, &Diags);
+ }
+}
+
namespace {
/// \brief Visitor for expressions which looks for unsequenced operations on the
/// same object.
}
}
-void Sema::CheckCompletedExpr(Expr *E, SourceLocation CheckLoc) {
+void Sema::CheckCompletedExpr(Expr *E, SourceLocation CheckLoc,
+ bool IsConstexpr) {
CheckImplicitConversions(E, CheckLoc);
CheckUnsequencedOperations(E);
+ if (!IsConstexpr && !E->isValueDependent())
+ CheckForIntOverflow(E);
}
void Sema::CheckBitFieldInitialization(SourceLocation InitLoc,
// Recover from an error by just forgetting about it.
}
}
+
+ LHSVal = ActOnFinishFullExpr(LHSVal, LHSVal->getExprLoc(), false,
+ getLangOpts().CPlusPlus11).take();
+ if (RHSVal)
+ RHSVal = ActOnFinishFullExpr(RHSVal, RHSVal->getExprLoc(), false,
+ getLangOpts().CPlusPlus11).take();
CaseStmt *CS = new (Context) CaseStmt(LHSVal, RHSVal, CaseLoc, DotDotDotLoc,
ColonLoc);
} else {
// We already verified that the expression has a i-c-e value (C99
// 6.8.4.2p3) - get that value now.
- SmallVector<PartialDiagnosticAt, 8> Diags;
- LoVal = Lo->EvaluateKnownConstInt(Context, &Diags);
- if (Diags.size() == 1 &&
- Diags[0].second.getDiagID() == diag::note_constexpr_overflow) {
- Diag(Lo->getLocStart(), diag::warn_case_constant_overflow) <<
- LoVal.toString(10);
- Diag(Diags[0].first, Diags[0].second);
- }
+ LoVal = Lo->EvaluateKnownConstInt(Context);
// If the LHS is not the same type as the condition, insert an implicit
// cast.