diff --git a/clang/Lex/PPExpressions.cpp b/clang/Lex/PPExpressions.cpp index b9a73cf8e313..c46dcb1f1070 100644 --- a/clang/Lex/PPExpressions.cpp +++ b/clang/Lex/PPExpressions.cpp @@ -430,9 +430,19 @@ static bool EvaluateDirectiveSubExpr(APSInt &LHS, unsigned MinPrec, // either operand is unsigned. Don't do this for x and y in "x ? y : z". APSInt Res(LHS.getBitWidth()); if (Operator != tok::question) { - if (RHS.isUnsigned()) LHS.setIsUnsigned(true); - RHS.setIsUnsigned(LHS.isUnsigned()); - Res.setIsUnsigned(LHS.isUnsigned()); + Res.setIsUnsigned(LHS.isUnsigned()|RHS.isUnsigned()); + // If this just promoted something from signed to unsigned, and if the + // value was negative, warn about it. + if (ValueLive && Res.isUnsigned()) { + if (!LHS.isUnsigned() && LHS.isNegative()) + PP.Diag(OpToken, diag::warn_pp_convert_lhs_to_positive, + LHS.toString(10, true) + " to " + LHS.toString(10, false)); + if (!RHS.isUnsigned() && RHS.isNegative()) + PP.Diag(OpToken, diag::warn_pp_convert_rhs_to_positive, + RHS.toString(10, true) + " to " + RHS.toString(10, false)); + } + LHS.setIsUnsigned(Res.isUnsigned()); + RHS.setIsUnsigned(Res.isUnsigned()); } // FIXME: All of these should detect and report overflow?? diff --git a/clang/include/clang/Basic/DiagnosticKinds.def b/clang/include/clang/Basic/DiagnosticKinds.def index abfeaa1f9505..9dd47263d54c 100644 --- a/clang/include/clang/Basic/DiagnosticKinds.def +++ b/clang/include/clang/Basic/DiagnosticKinds.def @@ -116,6 +116,10 @@ DIAG(pp_invalid_string_literal, WARNING, "invalid string literal, ignoring final '\\'") DIAG(warn_pp_expr_overflow, WARNING, "integer overflow in preprocessor expression") +DIAG(warn_pp_convert_lhs_to_positive, WARNING, + "left side of operator converted from negative value to unsigned: %s") +DIAG(warn_pp_convert_rhs_to_positive, WARNING, + "right side of operator converted from negative value to unsigned: %s") DIAG(ext_pp_import_directive, EXTENSION, "#import is a language extension") diff --git a/clang/test/Preprocessor/expr_usual_conversions.c b/clang/test/Preprocessor/expr_usual_conversions.c new file mode 100644 index 000000000000..b2ccc4090075 --- /dev/null +++ b/clang/test/Preprocessor/expr_usual_conversions.c @@ -0,0 +1,8 @@ +// RUN: clang %s -E 2>&1 | grep warning | wc -l | grep 2 + +#define INTMAX_MIN (-9223372036854775807LL -1) + +#if (-42 + 0U) / -2 +foo +#endif +