Index: test/Sema/switch-1.c =================================================================== --- test/Sema/switch-1.c (revision 172433) +++ 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: include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- include/clang/Basic/DiagnosticSemaKinds.td (revision 172433) +++ include/clang/Basic/DiagnosticSemaKinds.td (working copy) @@ -5709,9 +5709,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 172433) +++ include/clang/Sema/Sema.h (working copy) @@ -6757,7 +6757,7 @@ ExprResult &LHS, ExprResult &RHS, SourceLocation Loc, unsigned Opc, QualType* CompLHSTy = 0); QualType CheckSubtractionOperands( // C99 6.5.6 - ExprResult &LHS, ExprResult &RHS, SourceLocation Loc, + ExprResult &LHS, ExprResult &RHS, SourceLocation Loc, unsigned Opc, QualType* CompLHSTy = 0); QualType CheckShiftOperands( // C99 6.5.7 ExprResult &LHS, ExprResult &RHS, SourceLocation Loc, unsigned Opc, Index: lib/Sema/SemaStmt.cpp =================================================================== --- lib/Sema/SemaStmt.cpp (revision 172433) +++ lib/Sema/SemaStmt.cpp (working copy) @@ -726,14 +726,7 @@ } 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); // If the LHS is not the same type as the condition, insert an implicit // cast. Index: lib/Sema/SemaExpr.cpp =================================================================== --- lib/Sema/SemaExpr.cpp (revision 172433) +++ 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); +} + +static void DiagnoseIntegerOverflow(Sema& S, ExprResult &LHS, ExprResult &RHS, + SourceLocation Loc, unsigned Opc) { + llvm::APSInt Right; + if (RHS.get()->isValueDependent() || + !RHS.get()->isIntegerConstantExpr(Right, S.Context)) + return; + + llvm::APSInt Left; + if (LHS.get()->isValueDependent() || + !LHS.get()->isIntegerConstantExpr(Left, S.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) + S.Diag(Loc, diag::warn_integer_constant_overflow); +} + // 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,6 +6230,9 @@ if (LHS.isInvalid() || RHS.isInvalid()) return QualType(); + // Check for integer overflow in multiple + if (!IsDiv && !IsCompAssign) + DiagnoseIntegerOverflow(*this, LHS, RHS, Loc, BO_Mul); if (compType.isNull() || !compType->isArithmeticType()) return InvalidOperands(Loc, LHS, RHS); @@ -6434,9 +6477,11 @@ if (LHS.isInvalid() || RHS.isInvalid()) return QualType(); - // Diagnose "string literal" '+' int. - if (Opc == BO_Add) + if (Opc == BO_Add) { + // Diagnose "string literal" '+' int. diagnoseStringPlusInt(*this, Loc, LHS.get(), RHS.get()); + DiagnoseIntegerOverflow(*this, LHS, RHS, Loc, Opc); + } // handle the common case first (both operands are arithmetic). if (!compType.isNull() && compType->isArithmeticType()) { @@ -6493,6 +6538,7 @@ // C99 6.5.6 QualType Sema::CheckSubtractionOperands(ExprResult &LHS, ExprResult &RHS, SourceLocation Loc, + unsigned Opc, QualType* CompLHSTy) { checkArithmeticNull(*this, LHS, RHS, Loc, /*isCompare=*/false); @@ -6507,6 +6553,9 @@ if (LHS.isInvalid() || RHS.isInvalid()) return QualType(); + if (Opc == BO_Sub) + DiagnoseIntegerOverflow(*this, LHS, RHS, Loc, Opc); + // Enforce type constraints: C99 6.5.6p3. // Handle the common case first (both operands are arithmetic). @@ -8375,7 +8424,7 @@ ResultTy = CheckAdditionOperands(LHS, RHS, OpLoc, Opc); break; case BO_Sub: - ResultTy = CheckSubtractionOperands(LHS, RHS, OpLoc); + ResultTy = CheckSubtractionOperands(LHS, RHS, OpLoc, Opc); break; case BO_Shl: case BO_Shr: @@ -8420,7 +8469,7 @@ ResultTy = CheckAssignmentOperands(LHS.get(), RHS, OpLoc, CompResultTy); break; case BO_SubAssign: - CompResultTy = CheckSubtractionOperands(LHS, RHS, OpLoc, &CompLHSTy); + CompResultTy = CheckSubtractionOperands(LHS, RHS, OpLoc, Opc, &CompLHSTy); if (!CompResultTy.isNull() && !LHS.isInvalid() && !RHS.isInvalid()) ResultTy = CheckAssignmentOperands(LHS.get(), RHS, OpLoc, CompResultTy); break;