[clang] [Sema] Fix c23 not checking CheckBoolLikeConversion (PR #79588)

Pil Eghoff via cfe-commits cfe-commits at lists.llvm.org
Sun Jan 28 23:55:34 PST 2024


https://github.com/pileghoff updated https://github.com/llvm/llvm-project/pull/79588

>From 6ea74d7aa0eadd4093350c04de95cbb2bdbaf0eb Mon Sep 17 00:00:00 2001
From: Pil Eghoff <pieg at bang-olufsen.dk>
Date: Fri, 26 Jan 2024 13:30:17 +0100
Subject: [PATCH] [Sema] Fix c23 not checking CheckBoolLikeConversion

---
 clang/docs/ReleaseNotes.rst                |  2 ++
 clang/lib/Sema/SemaChecking.cpp            |  2 +-
 clang/test/C/C2x/n3042.c                   | 36 ++++++++++++----------
 clang/test/Sema/warn-int-in-bool-context.c |  7 +++++
 4 files changed, 29 insertions(+), 18 deletions(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index db3d74e124e7d1d..641fa14ab069ed5 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -104,6 +104,8 @@ Improvements to Clang's time-trace
 Bug Fixes in This Version
 -------------------------
 
+- Fixed missing warnings when doing bool-like conversions in C23 (`#79435: https://github.com/llvm/llvm-project/issues/79435`_).
+
 Bug Fixes to Compiler Builtins
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 4d280f25cc04c25..8e3bd1cd46076d6 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -16166,7 +16166,7 @@ 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)
+  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 3f869013af48070..99661b1fb39eba1 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 0c94ebb391f3c53..a6890161b5af89d 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 at -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);
 }



More information about the cfe-commits mailing list