Commit 3b00e486 authored by Aaron Ballman's avatar Aaron Ballman
Browse files

Further update -Wbitfield-constant-conversion for 1-bit bitfield

https://reviews.llvm.org/D131255 (82afc9b1)
began warning about conversion causing data loss for a single-bit
bit-field. However, after landing the changes, there were reports about
significant false positives from some code bases.

This alters the approach taken in that patch by introducing a new
warning group (-Wsingle-bit-bitfield-constant-conversion) which is
grouped under -Wbitfield-constant-conversion to allow users to
selectively disable the single-bit warning without losing the other
constant conversion warnings.

Differential Revision: https://reviews.llvm.org/D132851
parent faad5675
Loading
Loading
Loading
Loading
+7 −3
Original line number Diff line number Diff line
@@ -106,9 +106,13 @@ Improvements to Clang's diagnostics
- ``-Wformat`` now recognizes ``%b`` for the ``printf``/``scanf`` family of
  functions and ``%B`` for the ``printf`` family of functions. Fixes
  `Issue 56885: <https://github.com/llvm/llvm-project/issues/56885>`_.
- ``-Wbitfield-constant-conversion`` now diagnoses implicit truncation when 1 is
  assigned to a 1-bit signed integer bitfield. This fixes
  `Issue 53253 <https://github.com/llvm/llvm-project/issues/53253>`_.
- Introduced ``-Wsingle-bit-bitfield-constant-conversion``, grouped under
  ``-Wbitfield-constant-conversion``, which diagnoses implicit truncation when
  ``1`` is assigned to a 1-bit signed integer bitfield. This fixes
  `Issue 53253 <https://github.com/llvm/llvm-project/issues/53253>`_. To reduce
  potential false positives, this diagnostic will not diagnose use of the
  ``true`` macro (from ``<stdbool.h>>`) in C language mode despite the macro
  being defined to expand to ``1``.
- ``-Wincompatible-function-pointer-types`` now defaults to an error in all C
  language modes. It may be downgraded to a warning with
  ``-Wno-error=incompatible-function-pointer-types`` or disabled entirely with
+4 −1
Original line number Diff line number Diff line
@@ -47,7 +47,10 @@ def BinaryLiteral : DiagGroup<"binary-literal", [CXX14BinaryLiteral,
                                                 CXXPre14CompatBinaryLiteral,
                                                 GNUBinaryLiteral]>;
def GNUCompoundLiteralInitializer : DiagGroup<"gnu-compound-literal-initializer">;
def BitFieldConstantConversion : DiagGroup<"bitfield-constant-conversion">;
def SingleBitBitFieldConstantConversion :
  DiagGroup<"single-bit-bitfield-constant-conversion">;
def BitFieldConstantConversion : DiagGroup<"bitfield-constant-conversion",
                                           [SingleBitBitFieldConstantConversion]>;
def BitFieldEnumConversion : DiagGroup<"bitfield-enum-conversion">;
def BitFieldWidth : DiagGroup<"bitfield-width">;
def CompoundTokenSplitByMacro : DiagGroup<"compound-token-split-by-macro">;
+3 −0
Original line number Diff line number Diff line
@@ -3846,6 +3846,9 @@ def warn_impcast_integer_64_32 : Warning<
def warn_impcast_integer_precision_constant : Warning<
  "implicit conversion from %2 to %3 changes value from %0 to %1">,
  InGroup<ConstantConversion>;
def warn_impcast_single_bit_bitield_precision_constant : Warning<
  "implicit truncation from %2 to a one-bit wide bit-field changes value from "
  "%0 to %1">, InGroup<SingleBitBitFieldConstantConversion>;
def warn_impcast_bitfield_precision_constant : Warning<
  "implicit truncation from %2 to bit-field changes value from %0 to %1">,
  InGroup<BitFieldConstantConversion>;
+17 −3
Original line number Diff line number Diff line
@@ -13047,6 +13047,18 @@ static bool AnalyzeBitFieldAssignment(Sema &S, FieldDecl *Bitfield, Expr *Init,
  unsigned OriginalWidth = Value.getBitWidth();
  // In C, the macro 'true' from stdbool.h will evaluate to '1'; To reduce
  // false positives where the user is demonstrating they intend to use the
  // bit-field as a Boolean, check to see if the value is 1 and we're assigning
  // to a one-bit bit-field to see if the value came from a macro named 'true'.
  bool OneAssignedToOneBitBitfield = FieldWidth == 1 && Value == 1;
  if (OneAssignedToOneBitBitfield && !S.LangOpts.CPlusPlus) {
    SourceLocation MaybeMacroLoc = OriginalInit->getBeginLoc();
    if (S.SourceMgr.isInSystemMacro(MaybeMacroLoc) &&
        S.findMacroSpelling(MaybeMacroLoc, "true"))
      return false;
  }
  if (!Value.isSigned() || Value.isNegative())
    if (UnaryOperator *UO = dyn_cast<UnaryOperator>(OriginalInit))
      if (UO->getOpcode() == UO_Minus || UO->getOpcode() == UO_Not)
@@ -13067,7 +13079,9 @@ static bool AnalyzeBitFieldAssignment(Sema &S, FieldDecl *Bitfield, Expr *Init,
  std::string PrettyValue = toString(Value, 10);
  std::string PrettyTrunc = toString(TruncatedValue, 10);
  S.Diag(InitLoc, diag::warn_impcast_bitfield_precision_constant)
  S.Diag(InitLoc, OneAssignedToOneBitBitfield
                      ? diag::warn_impcast_single_bit_bitield_precision_constant
                      : diag::warn_impcast_bitfield_precision_constant)
      << PrettyValue << PrettyTrunc << OriginalInit->getType()
      << Init->getSourceRange();
+3 −3
Original line number Diff line number Diff line
@@ -911,9 +911,9 @@ namespace dr674 { // dr674: 8
namespace dr675 { // dr675: dup 739
  template<typename T> struct A { T n : 1; };
#if __cplusplus >= 201103L
  static_assert(A<char>{1}.n < 0, ""); // expected-warning {{implicit truncation from 'int' to bit-field changes value from 1 to -1}}
  static_assert(A<int>{1}.n < 0, ""); // expected-warning {{implicit truncation from 'int' to bit-field changes value from 1 to -1}}
  static_assert(A<long long>{1}.n < 0, ""); // expected-warning {{implicit truncation from 'int' to bit-field changes value from 1 to -1}}
  static_assert(A<char>{1}.n < 0, ""); // expected-warning {{implicit truncation from 'int' to a one-bit wide bit-field changes value from 1 to -1}}
  static_assert(A<int>{1}.n < 0, ""); // expected-warning {{implicit truncation from 'int' to a one-bit wide bit-field changes value from 1 to -1}}
  static_assert(A<long long>{1}.n < 0, ""); // expected-warning {{implicit truncation from 'int' to a one-bit wide bit-field changes value from 1 to -1}}
#endif
}

Loading