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

Aaron Ballman via cfe-commits cfe-commits at lists.llvm.org
Wed Feb 28 06:59:45 PST 2024


================
@@ -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;
+        }
+      }
+    }
+  }
----------------
AaronBallman wrote:

Actually, I'm not convinced we *should* print the entire expression in this case. Lambdas usually aren't nearly as trivial as the ones we have in our test cases, and can be arbitrarily long. e.g.,
```
C:\Users\aballman\OneDrive - Intel Corporation\Desktop\test.cpp:2:7: warning: address of function '[]() {
    int foo = 0;
    return foo;
}' will always evaluate to 'true' [-Wpointer-bool-conversion]
    2 |   if ([](){
      |   ~~  ^~~~~
    3 |     // This is a comment
      |     ~~~~~~~~~~~~~~~~~~~~
    4 |     // intended to make the lambda
      |     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    5 |     // longer so that it shows
      |     ~~~~~~~~~~~~~~~~~~~~~~~~~~
    6 |     // what the diagnostic behavior is
      |     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    7 |     int foo = 0;
      |     ~~~~~~~~~~~~
    8 |     // of really large lambdas, and whether
      |     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    9 |     // it is worth it to print out the entire
      |     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   10 |     // expression in this case.
      |     ~~~~~~~~~~~~~~~~~~~~~~~~~~~
   11 |     return foo;
      |     ~~~~~~~~~~~
   12 |   }) {
      |   ~
1 warning generated.
```
This has two problems: 1) it repeats the user's code in both the diagnostic and in the highlighting, 2) the amount of context is huge and distracts from the diagnostic.

I think we should modify `warn_impcast_pointer_to_bool` to something along these lines:
```
def warn_impcast_pointer_to_bool : Warning<
    "address of%select{| function| array| lambda function pointer conversion operator}0 '%1' will always evaluate to 'true'">, InGroup<PointerBoolConversion>;
```
(Will need to be reformatted for the usual 80-col limits.) And when passing the source range for the lambda expression, I think we should pass only the lambda introducer as the source range so that we highlight far less code.

WDYT?

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


More information about the cfe-commits mailing list