https://github.com/vinayakdsci updated https://github.com/llvm/llvm-project/pull/83152
>From 613e7c0698f16292bb408be832c7ab3647f17195 Mon Sep 17 00:00:00 2001 From: Vinayak Dev <vinayakdev....@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/include/clang/Basic/DiagnosticSemaKinds.td | 4 ++-- clang/lib/Sema/SemaChecking.cpp | 15 +++++++++++++++ clang/test/CXX/drs/dr18xx.cpp | 7 ++++++- .../CXX/expr/expr.prim/expr.prim.lambda/blocks.mm | 9 +++++---- clang/test/SemaCXX/warn-bool-conversion.cpp | 14 ++++++++++++++ 6 files changed, 45 insertions(+), 7 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/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index c8141fefb8edba..1fd450237e0266 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -4127,8 +4127,8 @@ def ext_ms_impcast_fn_obj : ExtWarn< "Microsoft extension">, InGroup<MicrosoftCast>; def warn_impcast_pointer_to_bool : Warning< - "address of%select{| function| array}0 '%1' will always evaluate to " - "'true'">, + "address of%select{| function| array| lambda function pointer conversion operator}0 '%1' " + "will always evaluate to 'true'">, InGroup<PointerBoolConversion>; def warn_cast_nonnull_to_bool : Warning< "nonnull %select{function call|parameter}0 '%1' will evaluate to " diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index 0de76ee119cf81..1ce7f0044103fc 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -16538,6 +16538,21 @@ 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 (const auto *MRecordDecl = MCallExpr->getRecordDecl(); + MRecordDecl && 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) + << /*LambdaPointerConversionOperatorType*/ 3 << S.str() + << MRecordDecl->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..d69698c5e27fdb 100644 --- a/clang/test/CXX/drs/dr18xx.cpp +++ b/clang/test/CXX/drs/dr18xx.cpp @@ -281,12 +281,17 @@ namespace dr1837 { // dr1837: 3.3 struct A { int f(); - bool b = [] { + bool b = [] { // #dr1837-a struct Local { static_assert(sizeof(this->f()) == sizeof(int), ""); }; }; }; + /* since-cxx11-warning@#dr1837-a{{address of lambda function pointer conversion operator '[] { + 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..0e27075a2a2597 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 lambda function pointer conversion operator '[]() {\n}' will always evaluate to 'true'}} } - bool b = []{}; + bool b = []{}; // expected-warning{{address of lambda function pointer conversion operator '[] {\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 lambda function pointer conversion operator 'c' will always evaluate to 'true'}} + bool r2 = d; // expected-error {{private}} \ + expected-warning{{address of lambda function pointer conversion operator '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..88eb17382a7562 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 lambda function pointer conversion operator 'f7' will always evaluate to 'true'}} + b = f8; // expected-warning {{address of lambda function pointer conversion operator 'f8' will always evaluate to 'true'}} + bool is_true = [](){ return true; }; +/* expected-warning@-1{{address of lambda function pointer conversion operator '[]() { + return true; +}' will always evaluate to 'true'}} */ +} +#endif void bar() { bool b; _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits