Index: test/Sema/switch-1.c =================================================================== --- test/Sema/switch-1.c (revision 172727) +++ test/Sema/switch-1.c (working copy) @@ -4,11 +4,9 @@ int f(int i) { switch (i) { - case 2147483647 + 2: // expected-note {{value 2147483649 is outside the range of representable values of type 'int'}} \ - // expected-warning {{overflow in case constant expression results in value -2147483647}} + case 2147483647 + 2: // expected-warning {{integer constant overflow in expression}} return 1; - case 9223372036854775807L * 4 : // expected-note {{value 36893488147419103228 is outside the range of representable values of type 'long'}} \ - // expected-warning {{overflow in case constant expression results in value -4}} + case 9223372036854775807L * 4: // expected-warning {{integer constant overflow in expression}} return 2; case 2147483647: return 0; Index: test/CXX/expr/expr.const/p2-0x.cpp =================================================================== --- test/CXX/expr/expr.const/p2-0x.cpp (revision 172727) +++ test/CXX/expr/expr.const/p2-0x.cpp (working copy) @@ -226,27 +226,39 @@ namespace Overflow { // Signed int overflow. constexpr int n1 = 2 * 3 * 3 * 7 * 11 * 31 * 151 * 331; // ok - constexpr int n2 = 65536 * 32768; // expected-error {{constant expression}} expected-note {{value 2147483648 is outside the range of }} + constexpr int n2 = 65536 * 32768; // expected-error {{constant expression}} expected-note {{value 2147483648 is outside the range of }} \ + // expected-warning {{integer constant overflow in expression}} constexpr int n3 = n1 + 1; // ok - constexpr int n4 = n3 + 1; // expected-error {{constant expression}} expected-note {{value 2147483648 is outside the range of }} + constexpr int n4 = n3 + 1; // expected-error {{constant expression}} expected-note {{value 2147483648 is outside the range of }} \ + // expected-warning {{integer constant overflow in expression}} constexpr int n5 = -65536 * 32768; // ok - constexpr int n6 = 3 * -715827883; // expected-error {{constant expression}} expected-note {{value -2147483649 is outside the range of }} + constexpr int n6 = 3 * -715827883; // expected-error {{constant expression}} expected-note {{value -2147483649 is outside the range of }} \ + // expected-warning {{integer constant overflow in expression}} constexpr int n7 = -n3 + -1; // ok - constexpr int n8 = -1 + n7; // expected-error {{constant expression}} expected-note {{value -2147483649 is outside the range of }} + constexpr int n8 = -1 + n7; // expected-error {{constant expression}} expected-note {{value -2147483649 is outside the range of }} \ + // expected-warning {{integer constant overflow in expression}} constexpr int n9 = n3 - 0; // ok - constexpr int n10 = n3 - -1; // expected-error {{constant expression}} expected-note {{value 2147483648 is outside the range of }} + constexpr int n10 = n3 - -1; // expected-error {{constant expression}} expected-note {{value 2147483648 is outside the range of }} \ + // expected-warning {{integer constant overflow in expression}} constexpr int n11 = -1 - n3; // ok - constexpr int n12 = -2 - n3; // expected-error {{constant expression}} expected-note {{value -2147483649 is outside the range of }} - constexpr int n13 = n5 + n5; // expected-error {{constant expression}} expected-note {{value -4294967296 is outside the range of }} - constexpr int n14 = n3 - n5; // expected-error {{constant expression}} expected-note {{value 4294967295 is outside the range of }} - constexpr int n15 = n5 * n5; // expected-error {{constant expression}} expected-note {{value 4611686018427387904 is outside the range of }} + constexpr int n12 = -2 - n3; // expected-error {{constant expression}} expected-note {{value -2147483649 is outside the range of }} \ + // expected-warning {{integer constant overflow in expression}} + constexpr int n13 = n5 + n5; // expected-error {{constant expression}} expected-note {{value -4294967296 is outside the range of }} \ + // expected-warning {{integer constant overflow in expression}} + constexpr int n14 = n3 - n5; // expected-error {{constant expression}} expected-note {{value 4294967295 is outside the range of }} \ + // expected-warning {{integer constant overflow in expression}} + constexpr int n15 = n5 * n5; // expected-error {{constant expression}} expected-note {{value 4611686018427387904 is outside the range of }} \ + // expected-warning {{integer constant overflow in expression}} constexpr signed char c1 = 100 * 2; // ok constexpr signed char c2 = '\x64' * '\2'; // also ok constexpr long long ll1 = 0x7fffffffffffffff; // ok - constexpr long long ll2 = ll1 + 1; // expected-error {{constant}} expected-note {{ 9223372036854775808 }} + constexpr long long ll2 = ll1 + 1; // expected-error {{constant}} expected-note {{ 9223372036854775808 }} \ + // expected-warning {{integer constant overflow in expression}} constexpr long long ll3 = -ll1 - 1; // ok - constexpr long long ll4 = ll3 - 1; // expected-error {{constant}} expected-note {{ -9223372036854775809 }} - constexpr long long ll5 = ll3 * ll3; // expected-error {{constant}} expected-note {{ 85070591730234615865843651857942052864 }} + constexpr long long ll4 = ll3 - 1; // expected-error {{constant}} expected-note {{ -9223372036854775809 }} \ + // expected-warning {{integer constant overflow in expression}} + constexpr long long ll5 = ll3 * ll3; // expected-error {{constant}} expected-note {{ 85070591730234615865843651857942052864 }} \ + // expected-warning {{integer constant overflow in expression}} // Yikes. char melchizedek[2200000000]; Index: include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- include/clang/Basic/DiagnosticSemaKinds.td (revision 172727) +++ include/clang/Basic/DiagnosticSemaKinds.td (working copy) @@ -5727,9 +5727,9 @@ def warn_case_value_overflow : Warning< "overflow converting case value to switch condition type (%0 to %1)">, InGroup; -def warn_case_constant_overflow : Warning< - "overflow in case constant expression results in value %0">, - InGroup; +def warn_integer_constant_overflow : Warning< + "integer constant overflow in expression">, + InGroup>; def err_duplicate_case : Error<"duplicate case value '%0'">; def err_duplicate_case_differing_expr : Error< "duplicate case value: '%0' and '%1' both equal '%2'">; Index: include/clang/Sema/Sema.h =================================================================== --- include/clang/Sema/Sema.h (revision 172727) +++ include/clang/Sema/Sema.h (working copy) @@ -7321,6 +7321,9 @@ SourceLocation ReturnLoc); void CheckFloatComparison(SourceLocation Loc, Expr* LHS, Expr* RHS); void CheckImplicitConversions(Expr *E, SourceLocation CC = SourceLocation()); + void CheckForIntOverflow(Expr *E); + void DiagnoseIntegerOverflow(ExprResult &LHS, ExprResult &RHS, + SourceRange R, unsigned Opc); void CheckUnsequencedOperations(Expr *E); /// \brief Perform semantic checks on a completed expression. This will either Index: lib/Sema/SemaStmt.cpp =================================================================== --- lib/Sema/SemaStmt.cpp (revision 172727) +++ lib/Sema/SemaStmt.cpp (working copy) @@ -732,14 +732,8 @@ } else { // We already verified that the expression has a i-c-e value (C99 // 6.8.4.2p3) - get that value now. - SmallVector 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); + CheckForIntOverflow(Lo); // If the LHS is not the same type as the condition, insert an implicit // cast. Index: lib/Sema/SemaChecking.cpp =================================================================== --- lib/Sema/SemaChecking.cpp (revision 172727) +++ lib/Sema/SemaChecking.cpp (working copy) @@ -5171,6 +5171,21 @@ 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(E)) { + unsigned Opc = BExpr->getOpcode(); + if (Opc != BO_Add && Opc != BO_Sub && Opc != BO_Mul) + return; + + ExprResult LHS = BExpr->getLHS()->IgnoreParens(); + + ExprResult RHS = BExpr->getRHS()->IgnoreParens(); + DiagnoseIntegerOverflow(LHS, RHS, SourceRange(E->getExprLoc()), Opc); + } +} + namespace { /// \brief Visitor for expressions which looks for unsequenced operations on the /// same object. @@ -5587,6 +5602,7 @@ void Sema::CheckCompletedExpr(Expr *E, SourceLocation CheckLoc) { CheckImplicitConversions(E, CheckLoc); CheckUnsequencedOperations(E); + CheckForIntOverflow(E); } void Sema::CheckBitFieldInitialization(SourceLocation InitLoc, Index: lib/Sema/SemaExpr.cpp =================================================================== --- lib/Sema/SemaExpr.cpp (revision 172727) +++ lib/Sema/SemaExpr.cpp (working copy) @@ -6138,6 +6138,46 @@ return QualType(); } +template +static bool CheckedIntOverflow(const llvm::APSInt &LHS, const llvm::APSInt &RHS, + unsigned BitWidth, Operation Op) { + if (LHS.isUnsigned()) + return false; + + llvm::APSInt Value(Op(LHS.extend(BitWidth), RHS.extend(BitWidth)), false); + llvm::APSInt Result = Value.trunc(LHS.getBitWidth()); + return (Result.extend(BitWidth) != Value); +} + +void Sema::DiagnoseIntegerOverflow(ExprResult &LHS, ExprResult &RHS, + SourceRange R, unsigned Opc) { + llvm::APSInt Right; + if (RHS.get()->isValueDependent() || + !RHS.get()->isIntegerConstantExpr(Right, Context)) + return; + + llvm::APSInt Left; + if (LHS.get()->isValueDependent() || + !LHS.get()->isIntegerConstantExpr(Left, Context)) + return; + bool overflow = false; + + if (Opc == BO_Add) + overflow = CheckedIntOverflow(Left, Right, Left.getBitWidth() + 1, + std::plus()); + else if (Opc == BO_Sub) + overflow = CheckedIntOverflow(Left, Right, Left.getBitWidth() + 1, + std::minus()); + else if (Opc == BO_Mul) + overflow = CheckedIntOverflow(Left, Right, Left.getBitWidth() * 2, + std::multiplies()); + else + llvm_unreachable("Unknown operator when checking for integer overflow"); + + if (overflow) + Diag(R.getBegin(), diag::warn_integer_constant_overflow) << R ; +} + // checkArithmeticNull - Detect when a NULL constant is used improperly in an // expression. These are mainly cases where the null pointer is used as an // integer instead of a pointer. @@ -6190,7 +6230,6 @@ if (LHS.isInvalid() || RHS.isInvalid()) return QualType(); - if (compType.isNull() || !compType->isArithmeticType()) return InvalidOperands(Loc, LHS, RHS);