Skip to content

Commit 8bfb353

Browse files
committed
[Sema] Fix a -Wobjc-signed-char-bool false-positive
Unsigned bit-field flags can only have boolean values, so handle that case in Expr::isKnownToHaveBooleanValue. rdar://56256999
1 parent 626260c commit 8bfb353

File tree

2 files changed

+62
-0
lines changed

2 files changed

+62
-0
lines changed

clang/lib/AST/Expr.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,12 @@ bool Expr::isKnownToHaveBooleanValue() const {
191191
if (const auto *OVE = dyn_cast<OpaqueValueExpr>(E))
192192
return OVE->getSourceExpr()->isKnownToHaveBooleanValue();
193193

194+
if (const FieldDecl *FD = E->getSourceBitField())
195+
if (FD->getType()->isUnsignedIntegerType() &&
196+
!FD->getBitWidth()->isValueDependent() &&
197+
FD->getBitWidthValue(FD->getASTContext()) == 1)
198+
return true;
199+
194200
return false;
195201
}
196202

clang/test/SemaObjC/signed-char-bool-conversion.m

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,3 +47,59 @@ void t2(BoolProp *bp) {
4747
bp.p = 1;
4848
bp.p = 2; // expected-warning {{implicit conversion from constant value 2 to 'BOOL'; the only well defined values for 'BOOL' are YES and NO}}
4949
}
50+
51+
struct has_bf {
52+
int signed_bf1 : 1;
53+
int signed_bf2 : 2;
54+
unsigned unsigned_bf1 : 1;
55+
unsigned unsigned_bf2 : 2;
56+
57+
struct has_bf *nested;
58+
};
59+
60+
void t3(struct has_bf *bf) {
61+
b = bf->signed_bf1; // expected-warning{{implicit conversion from integral type 'int' to 'BOOL'}}
62+
b = bf->signed_bf2; // expected-warning{{implicit conversion from integral type 'int' to 'BOOL'}}
63+
b = bf->unsigned_bf1; // no warning
64+
b = bf->unsigned_bf2; // expected-warning{{implicit conversion from integral type 'unsigned int' to 'BOOL'}}
65+
struct has_bf local;
66+
b = local.unsigned_bf1;
67+
b = local.unsigned_bf2; // expected-warning{{implicit conversion from integral type 'unsigned int' to 'BOOL'}}
68+
b = local.nested->unsigned_bf1;
69+
b = local.nested->unsigned_bf2; // expected-warning{{implicit conversion from integral type 'unsigned int' to 'BOOL'}}
70+
}
71+
72+
__attribute__((objc_root_class))
73+
@interface BFIvar {
74+
struct has_bf bf;
75+
unsigned unsigned_bf1 : 1;
76+
unsigned unsigned_bf2 : 2;
77+
}
78+
@end
79+
80+
@implementation BFIvar
81+
-(void)m {
82+
b = bf.unsigned_bf1;
83+
b = bf.unsigned_bf2; // expected-warning{{implicit conversion from integral type 'unsigned int' to 'BOOL'}}
84+
b = unsigned_bf1;
85+
b = unsigned_bf2; // expected-warning{{implicit conversion from integral type 'unsigned int' to 'BOOL'}}
86+
}
87+
@end
88+
89+
#ifdef __cplusplus
90+
template <class T>
91+
struct S {
92+
unsigned i : sizeof(T);
93+
};
94+
95+
template <class T>
96+
void f() {
97+
S<T> i;
98+
BOOL b = i.i; // expected-warning{{implicit conversion from integral type 'unsigned int' to 'BOOL'}}
99+
}
100+
101+
int main() {
102+
f<char>();
103+
f<short>(); // expected-note {{in instantiation of function template specialization 'f<short>' requested here}}
104+
}
105+
#endif

0 commit comments

Comments
 (0)