diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 9473867c1f231..89302dfc09734 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -122,6 +122,8 @@ Bug Fixes in This Version - Clang now accepts elaborated-type-specifiers that explicitly specialize a member class template for an implicit instantiation of a class template. +- Fixed missing warnings when doing bool-like conversions in C23 (`#79435 `_). + Bug Fixes to Compiler Builtins ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index 502b24bcdf8b4..a9f08354b3497 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -16134,7 +16134,10 @@ static void CheckConditionalOperator(Sema &S, AbstractConditionalOperator *E, /// Check conversion of given expression to boolean. /// Input argument E is a logical expression. static void CheckBoolLikeConversion(Sema &S, Expr *E, SourceLocation CC) { - if (S.getLangOpts().Bool) + // While C23 does have bool as a keyword, we still need to run the bool-like + // conversion checks as bools are still not used as the return type from + // "boolean" operators or as the input type for conditional operators. + if (S.getLangOpts().Bool && !S.getLangOpts().C23) return; if (E->IgnoreParenImpCasts()->getType()->isAtomicType()) return; diff --git a/clang/test/C/C2x/n3042.c b/clang/test/C/C2x/n3042.c index 3f869013af480..99661b1fb39eb 100644 --- a/clang/test/C/C2x/n3042.c +++ b/clang/test/C/C2x/n3042.c @@ -65,13 +65,15 @@ void test() { void *other_ptr = null_val; // Can it be used in all the places a scalar can be used? - if (null_val) {} - if (!null_val) {} - for (;null_val;) {} - while (nullptr) {} - null_val && nullptr; - nullptr || null_val; - null_val ? 0 : 1; + if (null_val) {} // expected-warning {{implicit conversion of nullptr constant to 'bool'}} + if (!null_val) {} // expected-warning {{implicit conversion of nullptr constant to 'bool'}} + for (;null_val;) {} // expected-warning {{implicit conversion of nullptr constant to 'bool'}} + while (nullptr) {} // expected-warning {{implicit conversion of nullptr constant to 'bool'}} + null_val && nullptr; // expected-warning {{implicit conversion of nullptr constant to 'bool'}} \ + expected-warning {{implicit conversion of nullptr constant to 'bool'}} + nullptr || null_val; // expected-warning {{implicit conversion of nullptr constant to 'bool'}} \ + expected-warning {{implicit conversion of nullptr constant to 'bool'}} + null_val ? 0 : 1; // expected-warning {{implicit conversion of nullptr constant to 'bool'}} sizeof(null_val); alignas(nullptr_t) int aligned; @@ -95,12 +97,12 @@ void test() { // Can it be converted to bool with the result false (this relies on Clang // accepting additional kinds of constant expressions where an ICE is // required)? - static_assert(!nullptr); - static_assert(!null_val); - static_assert(nullptr); // expected-error {{static assertion failed due to requirement 'nullptr'}} \ - expected-warning {{implicit conversion of nullptr constant to 'bool'}} - static_assert(null_val); // expected-error {{static assertion failed due to requirement 'null_val'}} \ - expected-warning {{implicit conversion of nullptr constant to 'bool'}} + static_assert(!nullptr); // expected-warning {{implicit conversion of nullptr constant to 'bool'}} + static_assert(!null_val); // expected-warning {{implicit conversion of nullptr constant to 'bool'}} + static_assert(nullptr); // expected-error {{static assertion failed due to requirement 'nullptr'}} \ + expected-warning {{implicit conversion of nullptr constant to 'bool'}} + static_assert(null_val); // expected-error {{static assertion failed due to requirement 'null_val'}} \ + expected-warning {{implicit conversion of nullptr constant to 'bool'}} // Do equality operators work as expected with it? static_assert(nullptr == nullptr); @@ -142,11 +144,11 @@ void test() { _Generic(1 ? typed_ptr : nullptr, typeof(typed_ptr) : 0); // Same for GNU conditional operators? - _Generic(nullptr ?: nullptr, nullptr_t : 0); - _Generic(null_val ?: null_val, nullptr_t : 0); + _Generic(nullptr ?: nullptr, nullptr_t : 0); // expected-warning {{implicit conversion of nullptr constant to 'bool'}} + _Generic(null_val ?: null_val, nullptr_t : 0); // expected-warning {{implicit conversion of nullptr constant to 'bool'}} _Generic(typed_ptr ?: null_val, typeof(typed_ptr) : 0); - _Generic(null_val ?: typed_ptr, typeof(typed_ptr) : 0); - _Generic(nullptr ?: typed_ptr, typeof(typed_ptr) : 0); + _Generic(null_val ?: typed_ptr, typeof(typed_ptr) : 0); // expected-warning {{implicit conversion of nullptr constant to 'bool'}} + _Generic(nullptr ?: typed_ptr, typeof(typed_ptr) : 0); // expected-warning {{implicit conversion of nullptr constant to 'bool'}} _Generic(typed_ptr ?: nullptr, typeof(typed_ptr) : 0); // Do we correctly issue type incompatibility diagnostics? diff --git a/clang/test/Sema/warn-int-in-bool-context.c b/clang/test/Sema/warn-int-in-bool-context.c index 0c94ebb391f3c..a6890161b5af8 100644 --- a/clang/test/Sema/warn-int-in-bool-context.c +++ b/clang/test/Sema/warn-int-in-bool-context.c @@ -1,5 +1,6 @@ // RUN: %clang_cc1 -x c -fsyntax-only -verify -Wint-in-bool-context %s // RUN: %clang_cc1 -x c -fsyntax-only -verify -Wall %s +// RUN: %clang_cc1 -x c -std=c23 -fsyntax-only -verify -Wall %s // RUN: %clang_cc1 -x c++ -fsyntax-only -verify -Wint-in-bool-context %s // RUN: %clang_cc1 -x c++ -fsyntax-only -verify -Wall %s @@ -42,6 +43,9 @@ int test(int a, unsigned b, enum num n) { r = ONE << a; // expected-warning {{converting the result of '<<' to a boolean; did you mean '(1 << a) != 0'?}} if (TWO << a) // expected-warning {{converting the result of '<<' to a boolean; did you mean '(2 << a) != 0'?}} return a; + + a = 1 << 2 ? 0: 1; // expected-warning {{converting the result of '<<' to a boolean always evaluates to true}} + a = 1 << a ? 0: 1; // expected-warning {{converting the result of '<<' to a boolean; did you mean '(1 << a) != 0'?}} for (a = 0; 1 << a; a++) // expected-warning {{converting the result of '<<' to a boolean; did you mean '(1 << a) != 0'?}} ; @@ -69,6 +73,9 @@ int test(int a, unsigned b, enum num n) { // expected-warning@-1 {{converting the enum constant to a boolean}} return a; + if(1 << 5) // expected-warning {{converting the result of '<<' to a boolean always evaluates to true}} + return a; + // Don't warn in macros. return SHIFT(1, a); }