// If the source is a constant, use a default-on diagnostic.
// TODO: this should happen for bitfield stores, too.
llvm::APSInt Value(32);
- if (E->isIntegerConstantExpr(Value, S.Context)) {
+ if (E->EvaluateAsInt(Value, S.Context, Expr::SE_AllowSideEffects)) {
if (S.SourceMgr.isInSystemMacro(CC))
return;
return DiagnoseImpCast(S, E, T, CC, diag::warn_impcast_integer_precision);
}
+ if (TargetRange.Width == SourceRange.Width && !TargetRange.NonNegative &&
+ SourceRange.NonNegative && Source->isSignedIntegerType()) {
+ // Warn when doing a signed to signed conversion, warn if the positive
+ // source value is exactly the width of the target type, which will
+ // cause a negative value to be stored.
+
+ llvm::APSInt Value;
+ if (E->EvaluateAsInt(Value, S.Context, Expr::SE_AllowSideEffects)) {
+ if (!S.SourceMgr.isInSystemMacro(CC)) {
+
+ IntegerLiteral *IntLit =
+ dyn_cast<IntegerLiteral>(E->IgnoreParenImpCasts());
+
+ // If initializing from a constant, and the constant starts with '0',
+ // then it is a binary, octal, or hexadecimal. Allow these constants
+ // to fill all the bits, even if there is a sign change.
+ if (!IntLit ||
+ *(S.getSourceManager().getCharacterData(IntLit->getLocStart())) !=
+ '0') {
+
+ std::string PrettySourceValue = Value.toString(10);
+ std::string PrettyTargetValue =
+ PrettyPrintInRange(Value, TargetRange);
+
+ S.DiagRuntimeBehavior(
+ E->getExprLoc(), E,
+ S.PDiag(diag::warn_impcast_integer_precision_constant)
+ << PrettySourceValue << PrettyTargetValue << E->getType() << T
+ << E->getSourceRange() << clang::SourceRange(CC));
+ return;
+ }
+ }
+ }
+ // Fall through for non-constants to give a sign conversion warning.
+ }
+
if ((TargetRange.NonNegative && !SourceRange.NonNegative) ||
(!TargetRange.NonNegative && SourceRange.NonNegative &&
SourceRange.Width == TargetRange.Width)) {
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 signed char c1 = 100 * 2; // ok
- constexpr signed char c2 = '\x64' * '\2'; // also ok
+ constexpr signed char c1 = 100 * 2; // ok expected-warning{{changes value}}
+ constexpr signed char c2 = '\x64' * '\2'; // also ok expected-warning{{changes value}}
constexpr long long ll1 = 0x7fffffffffffffff; // ok
constexpr long long ll2 = ll1 + 1; // expected-error {{constant}} expected-note {{ 9223372036854775808 }}
constexpr long long ll3 = -ll1 - 1; // ok
struct { enum E x : 1; } f;
f.x = C; // expected-warning {{implicit truncation from 'int' to bitfield changes value from 2 to 0}}
}
+
+void test9() {
+ const char max_char = 0x7F;
+ const short max_short = 0x7FFF;
+ const int max_int = 0x7FFFFFFF;
+
+ const short max_char_plus_one = (short)max_char + 1;
+ const int max_short_plus_one = (int)max_short + 1;
+ const long max_int_plus_one = (long)max_int + 1;
+
+ char new_char = max_char_plus_one; // expected-warning {{implicit conversion from 'const short' to 'char' changes value from 128 to -128}}
+ short new_short = max_short_plus_one; // expected-warning {{implicit conversion from 'const int' to 'short' changes value from 32768 to -32768}}
+ int new_int = max_int_plus_one; // expected-warning {{implicit conversion from 'const long' to 'int' changes value from 2147483648 to -2147483648}}
+
+ char hex_char = 0x80;
+ short hex_short = 0x8000;
+ int hex_int = 0x80000000;
+
+ char oct_char = 0200;
+ short oct_short = 0100000;
+ int oct_int = 020000000000;
+
+ char bin_char = 0b10000000;
+ short bin_short = 0b1000000000000000;
+ int bin_int = 0b10000000000000000000000000000000;
+
+#define CHAR_MACRO_HEX 0xff
+ char macro_char_hex = CHAR_MACRO_HEX;
+#define CHAR_MACRO_DEC 255
+ char macro_char_dec = CHAR_MACRO_DEC; // expected-warning {{implicit conversion from 'int' to 'char' changes value from 255 to -1}}
+}