diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 11f62bc881b03..a25ffd3105a5e 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -352,6 +352,10 @@ Improvements to Clang's diagnostics - Now correctly diagnose a tentative definition of an array with static storage duration in pedantic mode in C. (#GH50661) +- Split diagnosis of implicit integer comparison on negation to a new + diagnostic group ``-Wimplicit-int-comparison-on-negation``, grouped under + ``-Wimplicit-int-conversion``, so user can turn it off independently. + Improvements to Clang's time-trace ---------------------------------- diff --git a/clang/include/clang/Basic/DiagnosticGroups.td b/clang/include/clang/Basic/DiagnosticGroups.td index d97bbfee2e4d5..4ea8143438474 100644 --- a/clang/include/clang/Basic/DiagnosticGroups.td +++ b/clang/include/clang/Basic/DiagnosticGroups.td @@ -110,9 +110,11 @@ def DeprecatedOFast : DiagGroup<"deprecated-ofast">; def ObjCSignedCharBoolImplicitIntConversion : DiagGroup<"objc-signed-char-bool-implicit-int-conversion">; def Shorten64To32 : DiagGroup<"shorten-64-to-32">; +def ImplicitIntConversionOnNegation : DiagGroup<"implicit-int-conversion-on-negation">; def ImplicitIntConversion : DiagGroup<"implicit-int-conversion", [Shorten64To32, - ObjCSignedCharBoolImplicitIntConversion]>; + ObjCSignedCharBoolImplicitIntConversion, + ImplicitIntConversionOnNegation]>; def ImplicitConstIntFloatConversion : DiagGroup<"implicit-const-int-float-conversion">; def ImplicitIntFloatConversion : DiagGroup<"implicit-int-float-conversion", [ImplicitConstIntFloatConversion]>; diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 180ca39bc07e9..d315f056e54e7 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -4217,6 +4217,9 @@ def warn_impcast_integer_sign_conditional : Warning< def warn_impcast_integer_precision : Warning< "implicit conversion loses integer precision: %0 to %1">, InGroup, DefaultIgnore; +def warn_impcast_integer_precision_on_negation : Warning< + "implicit conversion loses integer precision: %0 to %1 on negation">, + InGroup, DefaultIgnore; def warn_impcast_high_order_zero_bits : Warning< "higher order bits are zeroes after implicit conversion">, InGroup, DefaultIgnore; diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index bffd0dd461d3d..cc06e3506fefc 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -12091,6 +12091,12 @@ void Sema::CheckImplicitConversion(Expr *E, QualType T, SourceLocation CC, if (SourceMgr.isInSystemMacro(CC)) return; + if (const auto *UO = dyn_cast(E)) { + if (UO->getOpcode() == UO_Minus) + return DiagnoseImpCast( + *this, E, T, CC, diag::warn_impcast_integer_precision_on_negation); + } + if (TargetRange.Width == 32 && Context.getIntWidth(E->getType()) == 64) return DiagnoseImpCast(*this, E, T, CC, diag::warn_impcast_integer_64_32, /* pruneControlFlow */ true); diff --git a/clang/test/Sema/implicit-int-conversion-on-int.c b/clang/test/Sema/implicit-int-conversion-on-int.c new file mode 100644 index 0000000000000..f555893d9e17a --- /dev/null +++ b/clang/test/Sema/implicit-int-conversion-on-int.c @@ -0,0 +1,50 @@ +// RUN: %clang_cc1 %s -verify=expected -Wimplicit-int-conversion +// RUN: %clang_cc1 %s -verify=none -Wimplicit-int-conversion -Wno-implicit-int-conversion-on-negation + +// none-no-diagnostics + +char test_char(char x) { + return -x; // expected-warning {{implicit conversion loses integer precision: 'int' to 'char' on negation}} +} + +unsigned char test_unsigned_char(unsigned char x) { + return -x; // expected-warning {{implicit conversion loses integer precision: 'int' to 'unsigned char' on negation}} +} + +short test_short(short x) { + return -x; // expected-warning {{implicit conversion loses integer precision: 'int' to 'short' on negation}} +} + +unsigned short test_unsigned_short(unsigned short x) { + return -x; // expected-warning {{implicit conversion loses integer precision: 'int' to 'unsigned short' on negation}} +} + +// --- int-width and wider (should NOT warn) --- + +int test_i(int x) { + return -x; +} + +unsigned int test_ui(unsigned int x) { + return -x; +} + +long test_l(long x) { + return -x; +} + +unsigned long test_ul(unsigned long x) { + return -x; +} + +long long test_ll(long long x) { + return -x; +} + +unsigned long long test_ull(unsigned long long x) { + return -x; +} + +unsigned _BitInt(16) test_unsigned_bit_int(unsigned _BitInt(16) x) { + return -x; +}