[clang] 82afc9b - Fix -Wbitfield-constant-conversion on 1-bit signed bitfield
Aaron Ballman via cfe-commits
cfe-commits at lists.llvm.org
Tue Aug 9 08:43:59 PDT 2022
Author: Shawn Zhong
Date: 2022-08-09T11:43:50-04:00
New Revision: 82afc9b169a67e8b8a1862fb9c41a2cd974d6691
URL: https://github.com/llvm/llvm-project/commit/82afc9b169a67e8b8a1862fb9c41a2cd974d6691
DIFF: https://github.com/llvm/llvm-project/commit/82afc9b169a67e8b8a1862fb9c41a2cd974d6691.diff
LOG: Fix -Wbitfield-constant-conversion on 1-bit signed bitfield
A one-bit signed bit-field can only hold the values 0 and -1; this
corrects the diagnostic behavior accordingly.
Fixes #53253
Differential Revision: https://reviews.llvm.org/D131255
Added:
Modified:
clang/docs/ReleaseNotes.rst
clang/lib/Sema/SemaChecking.cpp
clang/test/CXX/class/class.bit/p1.cpp
clang/test/CXX/drs/dr6xx.cpp
clang/test/CodeGen/bitfield.c
clang/test/CodeGenCXX/bitfield-layout.cpp
clang/test/Rewriter/rewrite-modern-struct-ivar-1.mm
clang/test/Rewriter/rewrite-modern-struct-ivar.mm
clang/test/Sema/constant-conversion.c
clang/test/SemaCXX/constant-expression-cxx11.cpp
clang/test/SemaCXX/cxx1z-decomposition.cpp
clang/test/SemaCXX/decomposition-blocks.cpp
Removed:
################################################################################
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index d830928a13d4d..4b01f018005ed 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -82,6 +82,9 @@ 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>`_.
Non-comprehensive list of changes in this release
-------------------------------------------------
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 5a1c21d3a367b..a0ea35e1234f6 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -13064,11 +13064,6 @@ static bool AnalyzeBitFieldAssignment(Sema &S, FieldDecl *Bitfield, Expr *Init,
if (llvm::APSInt::isSameValue(Value, TruncatedValue))
return false;
- // Special-case bitfields of width 1: booleans are naturally 0/1, and
- // therefore don't strictly fit into a signed bitfield of width 1.
- if (FieldWidth == 1 && Value == 1)
- return false;
-
std::string PrettyValue = toString(Value, 10);
std::string PrettyTrunc = toString(TruncatedValue, 10);
diff --git a/clang/test/CXX/class/class.bit/p1.cpp b/clang/test/CXX/class/class.bit/p1.cpp
index ab15e3a356cfc..5df1ab52cdd8d 100644
--- a/clang/test/CXX/class/class.bit/p1.cpp
+++ b/clang/test/CXX/class/class.bit/p1.cpp
@@ -9,11 +9,11 @@ struct A {
int [[]] c : 1; // OK, attribute applies to the type.
int : 2 = 1; // expected-error {{anonymous bit-field cannot have a default member initializer}}
int : 0 { 1 }; // expected-error {{anonymous bit-field cannot have a default member initializer}}
- int : 0, d : 1 = 1;
+ unsigned int : 0, d : 1 = 1;
int : 1 = 12, e : 1; // expected-error {{anonymous bit-field cannot have a default member initializer}}
- int : 0, f : 1 = 1;
- int g [[]] : 1 = 1;
- int h [[]] : 1 {1};
- int i : foo() = foo();
+ unsigned int : 0, f : 1 = 1;
+ unsigned int g [[]] : 1 = 1;
+ unsigned int h [[]] : 1 {1};
+ unsigned int i : foo() = foo();
int j, [[]] k; // expected-error {{an attribute list cannot appear here}}
};
diff --git a/clang/test/CXX/drs/dr6xx.cpp b/clang/test/CXX/drs/dr6xx.cpp
index ad87c7295cfe8..432fd6e6c5efa 100644
--- a/clang/test/CXX/drs/dr6xx.cpp
+++ b/clang/test/CXX/drs/dr6xx.cpp
@@ -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, "");
- static_assert(A<int>{1}.n < 0, "");
- static_assert(A<long long>{1}.n < 0, "");
+ 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}}
#endif
}
diff --git a/clang/test/CodeGen/bitfield.c b/clang/test/CodeGen/bitfield.c
index c624d0045d330..4845d7c478429 100644
--- a/clang/test/CodeGen/bitfield.c
+++ b/clang/test/CodeGen/bitfield.c
@@ -87,3 +87,19 @@ int g3(void) {
// PATH: ret i32 1
return f3(20) + 130725747;
}
+
+static int f4(void) {
+ struct s5 {
+ int b:1;
+ } x;
+ x.b = 1;
+ return x.b;
+}
+
+int g4(void) {
+// CHECK-LABEL: @g4()
+// CHECK: ret i32 1
+// PATH-LABEL: @g4()
+// PATH: ret i32 1
+ return f4() + 2;
+}
diff --git a/clang/test/CodeGenCXX/bitfield-layout.cpp b/clang/test/CodeGenCXX/bitfield-layout.cpp
index d570b8f33e343..0e0d712fd8aae 100644
--- a/clang/test/CodeGenCXX/bitfield-layout.cpp
+++ b/clang/test/CodeGenCXX/bitfield-layout.cpp
@@ -105,6 +105,15 @@ int test_trunc_three_bits() {
// CHECK: define{{.*}} i32 @test_trunc_three_bits()
// CHECK: ret i32 -1
+int test_trunc_one_bit() {
+ union {
+ int i : 1; // truncated to 0b1 == -1
+ } const U = {1}; // 0b00000001
+ return U.i;
+}
+// CHECK: define{{.*}} i32 @test_trunc_one_bit()
+// CHECK: ret i32 -1
+
int test_trunc_1() {
union {
int i : 1; // truncated to 0b1 == -1
diff --git a/clang/test/Rewriter/rewrite-modern-struct-ivar-1.mm b/clang/test/Rewriter/rewrite-modern-struct-ivar-1.mm
index a17fe3f85675d..e54b1cdaab3af 100644
--- a/clang/test/Rewriter/rewrite-modern-struct-ivar-1.mm
+++ b/clang/test/Rewriter/rewrite-modern-struct-ivar-1.mm
@@ -34,7 +34,7 @@ @interface Foo{
@implementation Foo
- (void)x:(Foo *)other {
bar.x = 0;
- bar.y = 1;
+ bar.y = -1;
self->_internal._singleRange._range = (( other ->bar.x) ? &( other ->_internal._singleRange._range) : ((NSRange *)(&(((_NSRangeInfo *)( other ->_internal._multipleRanges._data))->_ranges))))[0];
}
@end
diff --git a/clang/test/Rewriter/rewrite-modern-struct-ivar.mm b/clang/test/Rewriter/rewrite-modern-struct-ivar.mm
index 9f56cd8b1b837..f98bdbc460d32 100644
--- a/clang/test/Rewriter/rewrite-modern-struct-ivar.mm
+++ b/clang/test/Rewriter/rewrite-modern-struct-ivar.mm
@@ -41,10 +41,10 @@ @interface Foo{
@implementation Foo
- (void)x {
bar.x = 0;
- bar.y = 1;
+ bar.y = -1;
s.x = 0;
- s.y = 1;
+ s.y = -1;
}
@end
diff --git a/clang/test/Sema/constant-conversion.c b/clang/test/Sema/constant-conversion.c
index 025f4709a7d5f..d386d21f24aad 100644
--- a/clang/test/Sema/constant-conversion.c
+++ b/clang/test/Sema/constant-conversion.c
@@ -15,8 +15,16 @@ void test_7809123(void) {
}
void test(void) {
- struct { int bit : 1; } a;
- a.bit = 1; // shouldn't warn
+ struct S {
+ int b : 1; // The only valid values are 0 and -1.
+ } s;
+
+ s.b = -3; // expected-warning {{implicit truncation from 'int' to bit-field changes value from -3 to -1}}
+ s.b = -2; // expected-warning {{implicit truncation from 'int' to bit-field changes value from -2 to 0}}
+ s.b = -1; // no-warning
+ s.b = 0; // no-warning
+ s.b = 1; // expected-warning {{implicit truncation from 'int' to bit-field changes value from 1 to -1}}
+ s.b = 2; // expected-warning {{implicit truncation from 'int' to bit-field changes value from 2 to 0}}
}
enum Test2 { K_zero, K_one };
diff --git a/clang/test/SemaCXX/constant-expression-cxx11.cpp b/clang/test/SemaCXX/constant-expression-cxx11.cpp
index e145ca982cdd0..c5742ad8c2cbb 100644
--- a/clang/test/SemaCXX/constant-expression-cxx11.cpp
+++ b/clang/test/SemaCXX/constant-expression-cxx11.cpp
@@ -2035,6 +2035,7 @@ namespace Bitfields {
}
};
static_assert(X::f(3) == -1, "3 should truncate to -1");
+ static_assert(X::f(1) == -1, "1 should truncate to -1");
}
struct HasUnnamedBitfield {
diff --git a/clang/test/SemaCXX/cxx1z-decomposition.cpp b/clang/test/SemaCXX/cxx1z-decomposition.cpp
index 13fe826759a34..305a9ac2ebc24 100644
--- a/clang/test/SemaCXX/cxx1z-decomposition.cpp
+++ b/clang/test/SemaCXX/cxx1z-decomposition.cpp
@@ -84,7 +84,7 @@ void enclosing() {
(void)[outerbit1]{}; // expected-error {{'outerbit1' cannot be captured because it does not have automatic storage duration}}
- auto [bit, var] = S2{1, 1}; // expected-note 2{{'bit' declared here}}
+ auto [bit, var] = S2{-1, 1}; // expected-note 2{{'bit' declared here}}
(void)[&bit] { // expected-error {{non-const reference cannot bind to bit-field 'a'}} \
// expected-warning {{C++20}}
diff --git a/clang/test/SemaCXX/decomposition-blocks.cpp b/clang/test/SemaCXX/decomposition-blocks.cpp
index 21f66f8c7c1b8..0676463d12c78 100644
--- a/clang/test/SemaCXX/decomposition-blocks.cpp
+++ b/clang/test/SemaCXX/decomposition-blocks.cpp
@@ -7,7 +7,7 @@ struct S {
void run(void (^)());
void test() {
- auto [i, j] = S{1, 42}; // expected-note {{'i' declared here}}
+ auto [i, j] = S{-1, 42}; // expected-note {{'i' declared here}}
run(^{
(void)i; // expected-error {{reference to local binding 'i' declared in enclosing function 'test'}}
});
More information about the cfe-commits
mailing list