forked from OSchip/llvm-project
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
This commit is contained in:
parent
e486e48c3d
commit
82afc9b169
|
@ -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
|
||||
-------------------------------------------------
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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}}
|
||||
};
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -34,7 +34,7 @@ typedef struct {
|
|||
@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
|
||||
|
|
|
@ -41,10 +41,10 @@ struct S {
|
|||
@implementation Foo
|
||||
- (void)x {
|
||||
bar.x = 0;
|
||||
bar.y = 1;
|
||||
bar.y = -1;
|
||||
|
||||
s.x = 0;
|
||||
s.y = 1;
|
||||
s.y = -1;
|
||||
}
|
||||
@end
|
||||
|
||||
|
|
|
@ -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 };
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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}}
|
||||
|
|
|
@ -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'}}
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue