Skip to content

Commit dcc37e7

Browse files
authored
[Sema] Fix c23 not checking CheckBoolLikeConversion (#79588)
Fixes issue #79435 Checks for implicit conversion into boolean was previously triggered by `CheckBoolLikeConversion` for C. When `bool` as a keyword was introduced in C23, `CheckBoolLikeConversion` would no longer trigger when using `-std=c23`, but since logical operators and conditional statements still operate on scalar values, the checks for implicit conversion into bool were never triggered. This fix changes `CheckBoolLikeConversion` to not return early for C23, even though it has support for bools.
1 parent 7ff2dc3 commit dcc37e7

File tree

4 files changed

+32
-18
lines changed

4 files changed

+32
-18
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,8 @@ Bug Fixes in This Version
151151
- Clang now accepts elaborated-type-specifiers that explicitly specialize
152152
a member class template for an implicit instantiation of a class template.
153153

154+
- Fixed missing warnings when doing bool-like conversions in C23 (`#79435 <https://github.com/llvm/llvm-project/issues/79435>`_).
155+
154156
Bug Fixes to Compiler Builtins
155157
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
156158

clang/lib/Sema/SemaChecking.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16133,7 +16133,10 @@ static void CheckConditionalOperator(Sema &S, AbstractConditionalOperator *E,
1613316133
/// Check conversion of given expression to boolean.
1613416134
/// Input argument E is a logical expression.
1613516135
static void CheckBoolLikeConversion(Sema &S, Expr *E, SourceLocation CC) {
16136-
if (S.getLangOpts().Bool)
16136+
// While C23 does have bool as a keyword, we still need to run the bool-like
16137+
// conversion checks as bools are still not used as the return type from
16138+
// "boolean" operators or as the input type for conditional operators.
16139+
if (S.getLangOpts().Bool && !S.getLangOpts().C23)
1613716140
return;
1613816141
if (E->IgnoreParenImpCasts()->getType()->isAtomicType())
1613916142
return;

clang/test/C/C2x/n3042.c

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -65,13 +65,15 @@ void test() {
6565
void *other_ptr = null_val;
6666

6767
// Can it be used in all the places a scalar can be used?
68-
if (null_val) {}
69-
if (!null_val) {}
70-
for (;null_val;) {}
71-
while (nullptr) {}
72-
null_val && nullptr;
73-
nullptr || null_val;
74-
null_val ? 0 : 1;
68+
if (null_val) {} // expected-warning {{implicit conversion of nullptr constant to 'bool'}}
69+
if (!null_val) {} // expected-warning {{implicit conversion of nullptr constant to 'bool'}}
70+
for (;null_val;) {} // expected-warning {{implicit conversion of nullptr constant to 'bool'}}
71+
while (nullptr) {} // expected-warning {{implicit conversion of nullptr constant to 'bool'}}
72+
null_val && nullptr; // expected-warning {{implicit conversion of nullptr constant to 'bool'}} \
73+
expected-warning {{implicit conversion of nullptr constant to 'bool'}}
74+
nullptr || null_val; // expected-warning {{implicit conversion of nullptr constant to 'bool'}} \
75+
expected-warning {{implicit conversion of nullptr constant to 'bool'}}
76+
null_val ? 0 : 1; // expected-warning {{implicit conversion of nullptr constant to 'bool'}}
7577
sizeof(null_val);
7678
alignas(nullptr_t) int aligned;
7779

@@ -95,12 +97,12 @@ void test() {
9597
// Can it be converted to bool with the result false (this relies on Clang
9698
// accepting additional kinds of constant expressions where an ICE is
9799
// required)?
98-
static_assert(!nullptr);
99-
static_assert(!null_val);
100-
static_assert(nullptr); // expected-error {{static assertion failed due to requirement 'nullptr'}} \
101-
expected-warning {{implicit conversion of nullptr constant to 'bool'}}
102-
static_assert(null_val); // expected-error {{static assertion failed due to requirement 'null_val'}} \
103-
expected-warning {{implicit conversion of nullptr constant to 'bool'}}
100+
static_assert(!nullptr); // expected-warning {{implicit conversion of nullptr constant to 'bool'}}
101+
static_assert(!null_val); // expected-warning {{implicit conversion of nullptr constant to 'bool'}}
102+
static_assert(nullptr); // expected-error {{static assertion failed due to requirement 'nullptr'}} \
103+
expected-warning {{implicit conversion of nullptr constant to 'bool'}}
104+
static_assert(null_val); // expected-error {{static assertion failed due to requirement 'null_val'}} \
105+
expected-warning {{implicit conversion of nullptr constant to 'bool'}}
104106

105107
// Do equality operators work as expected with it?
106108
static_assert(nullptr == nullptr);
@@ -142,11 +144,11 @@ void test() {
142144
_Generic(1 ? typed_ptr : nullptr, typeof(typed_ptr) : 0);
143145

144146
// Same for GNU conditional operators?
145-
_Generic(nullptr ?: nullptr, nullptr_t : 0);
146-
_Generic(null_val ?: null_val, nullptr_t : 0);
147+
_Generic(nullptr ?: nullptr, nullptr_t : 0); // expected-warning {{implicit conversion of nullptr constant to 'bool'}}
148+
_Generic(null_val ?: null_val, nullptr_t : 0); // expected-warning {{implicit conversion of nullptr constant to 'bool'}}
147149
_Generic(typed_ptr ?: null_val, typeof(typed_ptr) : 0);
148-
_Generic(null_val ?: typed_ptr, typeof(typed_ptr) : 0);
149-
_Generic(nullptr ?: typed_ptr, typeof(typed_ptr) : 0);
150+
_Generic(null_val ?: typed_ptr, typeof(typed_ptr) : 0); // expected-warning {{implicit conversion of nullptr constant to 'bool'}}
151+
_Generic(nullptr ?: typed_ptr, typeof(typed_ptr) : 0); // expected-warning {{implicit conversion of nullptr constant to 'bool'}}
150152
_Generic(typed_ptr ?: nullptr, typeof(typed_ptr) : 0);
151153

152154
// Do we correctly issue type incompatibility diagnostics?

clang/test/Sema/warn-int-in-bool-context.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
// RUN: %clang_cc1 -x c -fsyntax-only -verify -Wint-in-bool-context %s
22
// RUN: %clang_cc1 -x c -fsyntax-only -verify -Wall %s
3+
// RUN: %clang_cc1 -x c -std=c23 -fsyntax-only -verify -Wall %s
34
// RUN: %clang_cc1 -x c++ -fsyntax-only -verify -Wint-in-bool-context %s
45
// RUN: %clang_cc1 -x c++ -fsyntax-only -verify -Wall %s
56

@@ -42,6 +43,9 @@ int test(int a, unsigned b, enum num n) {
4243
r = ONE << a; // expected-warning {{converting the result of '<<' to a boolean; did you mean '(1 << a) != 0'?}}
4344
if (TWO << a) // expected-warning {{converting the result of '<<' to a boolean; did you mean '(2 << a) != 0'?}}
4445
return a;
46+
47+
a = 1 << 2 ? 0: 1; // expected-warning {{converting the result of '<<' to a boolean always evaluates to true}}
48+
a = 1 << a ? 0: 1; // expected-warning {{converting the result of '<<' to a boolean; did you mean '(1 << a) != 0'?}}
4549

4650
for (a = 0; 1 << a; a++) // expected-warning {{converting the result of '<<' to a boolean; did you mean '(1 << a) != 0'?}}
4751
;
@@ -69,6 +73,9 @@ int test(int a, unsigned b, enum num n) {
6973
// expected-warning@-1 {{converting the enum constant to a boolean}}
7074
return a;
7175

76+
if(1 << 5) // expected-warning {{converting the result of '<<' to a boolean always evaluates to true}}
77+
return a;
78+
7279
// Don't warn in macros.
7380
return SHIFT(1, a);
7481
}

0 commit comments

Comments
 (0)