[clang] [Clang][Sema]: Diagnose lambda to bool implicit casts (PR #83152)

Vinayak Dev via cfe-commits cfe-commits at lists.llvm.org
Wed Feb 28 06:27:36 PST 2024


https://github.com/vinayakdsci updated https://github.com/llvm/llvm-project/pull/83152

>From c65c6a379db75eb4bf38578106ba2aa4e894e3d8 Mon Sep 17 00:00:00 2001
From: Vinayak Dev <vinayakdev.sci at gmail.com>
Date: Tue, 27 Feb 2024 18:05:29 +0530
Subject: [PATCH] [Clang][Sema]: Diagnose lambda to bool implicit casts

---
 clang/docs/ReleaseNotes.rst                    |  3 +++
 clang/lib/Sema/SemaChecking.cpp                | 18 ++++++++++++++++++
 clang/test/CXX/drs/dr18xx.cpp                  |  5 +++++
 .../expr/expr.prim/expr.prim.lambda/blocks.mm  |  9 +++++----
 clang/test/SemaCXX/warn-bool-conversion.cpp    | 14 ++++++++++++++
 5 files changed, 45 insertions(+), 4 deletions(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 7e16b9f0c67dbd..a5c6b80c4e99e1 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -192,6 +192,9 @@ Improvements to Clang's diagnostics
 
 - Clang now diagnoses declarative nested name specifiers that name alias templates.
 
+- Clang now diagnoses lambda function expressions being implicitly cast to boolean values, under ``-Wpointer-bool-conversion``.
+  Fixes `#82512 <https://github.com/llvm/llvm-project/issues/82512>`_.
+
 Improvements to Clang's time-trace
 ----------------------------------
 
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 0de76ee119cf81..ea0a739af0cca1 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -16538,6 +16538,24 @@ void Sema::DiagnoseAlwaysNonNullPointer(Expr *E,
     }
   }
 
+  // Complain if we are converting a lambda expression to a boolean value
+  if (const auto *MCallExpr = dyn_cast<CXXMemberCallExpr>(E)) {
+    if (MCallExpr->getObjectType()->isRecordType()) {
+      if (const auto *MRecordDecl = MCallExpr->getRecordDecl()) {
+        if (MRecordDecl->isLambda()) {
+          std::string Str;
+          llvm::raw_string_ostream S(Str);
+
+          E->printPretty(S, nullptr, getPrintingPolicy());
+          Diag(E->getExprLoc(), diag::warn_impcast_pointer_to_bool)
+              << /*FunctionPointerType*/ 1 << S.str() << E->getSourceRange()
+              << Range << IsEqual;
+          return;
+        }
+      }
+    }
+  }
+
   // Expect to find a single Decl.  Skip anything more complicated.
   ValueDecl *D = nullptr;
   if (DeclRefExpr *R = dyn_cast<DeclRefExpr>(E)) {
diff --git a/clang/test/CXX/drs/dr18xx.cpp b/clang/test/CXX/drs/dr18xx.cpp
index a7cee4ef8902f9..6fd063e043517b 100644
--- a/clang/test/CXX/drs/dr18xx.cpp
+++ b/clang/test/CXX/drs/dr18xx.cpp
@@ -287,6 +287,11 @@ namespace dr1837 { // dr1837: 3.3
       };
     };
   };
+  /* since-cxx11-warning at -6{{address of function '[] {
+    struct Local {
+        static_assert(sizeof (this->f()) == sizeof(int), "");
+    };
+}' will always evaluate to 'true'}} */
 #endif
 }
 
diff --git a/clang/test/CXX/expr/expr.prim/expr.prim.lambda/blocks.mm b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/blocks.mm
index cb56f6816ad036..9041d07e02a5bc 100644
--- a/clang/test/CXX/expr/expr.prim/expr.prim.lambda/blocks.mm
+++ b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/blocks.mm
@@ -65,10 +65,10 @@ void nesting() {
 
 namespace overloading {
   void bool_conversion() {
-    if ([](){}) {
+    if ([](){}) { // expected-warning{{address of function '[]() {\n}' will always evaluate to 'true'}}
     }
 
-    bool b = []{};
+    bool b = []{}; // expected-warning{{address of function '[] {\n}' will always evaluate to 'true'}}
     b = (bool)[]{};
   }
 
@@ -108,8 +108,9 @@ void call_with_lambda() {
     using decltype(a)::operator id<void(*)()>; // expected-note {{here}}
   } extern d;
 
-  bool r1 = c;
-  bool r2 = d; // expected-error {{private}}
+  bool r1 = c; // expected-warning{{address of function 'c' will always evaluate to 'true'}}
+  bool r2 = d; // expected-error {{private}} \
+                  expected-warning{{address of function 'd' will always evaluate to 'true'}}
 }
 
 namespace PR13117 {
diff --git a/clang/test/SemaCXX/warn-bool-conversion.cpp b/clang/test/SemaCXX/warn-bool-conversion.cpp
index c81d52d864f2d2..f95627b8ac0ca5 100644
--- a/clang/test/SemaCXX/warn-bool-conversion.cpp
+++ b/clang/test/SemaCXX/warn-bool-conversion.cpp
@@ -81,6 +81,20 @@ struct S2 {
 
 bool f5();
 bool f6(int);
+#if __cplusplus >= 201103L
+auto f7 = []{};
+auto f8 = [](){};
+
+void foo() {
+  bool b;
+  b = f7; // expected-warning {{address of function 'f7' will always evaluate to 'true'}}
+  b = f8; // expected-warning {{address of function 'f8' will always evaluate to 'true'}}
+  bool is_true = [](){ return true; };
+/* expected-cxx11-warning at -1{{address of function '[]() {
+    return true;
+}' will always evaluate to 'true'}} */
+}
+#endif
 
 void bar() {
   bool b;



More information about the cfe-commits mailing list