Skip to content

Commit 640cbf9

Browse files
committed
[Clang][Sema]: Diagnose lambda to bool implicit casts
1 parent b6f4dd9 commit 640cbf9

File tree

6 files changed

+34
-7
lines changed

6 files changed

+34
-7
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,9 @@ Improvements to Clang's diagnostics
192192

193193
- Clang now diagnoses declarative nested name specifiers that name alias templates.
194194

195+
- Clang now diagnoses lambda function expressions being implicitly cast to boolean values, under ``-Wpointer-bool-conversion``.
196+
Fixes `#82512 <https://github.com/llvm/llvm-project/issues/82512>`_.
197+
195198
Improvements to Clang's time-trace
196199
----------------------------------
197200

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4127,8 +4127,8 @@ def ext_ms_impcast_fn_obj : ExtWarn<
41274127
"Microsoft extension">, InGroup<MicrosoftCast>;
41284128

41294129
def warn_impcast_pointer_to_bool : Warning<
4130-
"address of%select{| function| array}0 '%1' will always evaluate to "
4131-
"'true'">,
4130+
"address of %select{'%1'|function '%1'|array '%1'|lambda function pointer "
4131+
"conversion operator}0 will always evaluate to 'true'">,
41324132
InGroup<PointerBoolConversion>;
41334133
def warn_cast_nonnull_to_bool : Warning<
41344134
"nonnull %select{function call|parameter}0 '%1' will evaluate to "

clang/lib/Sema/SemaChecking.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16538,6 +16538,17 @@ void Sema::DiagnoseAlwaysNonNullPointer(Expr *E,
1653816538
}
1653916539
}
1654016540

16541+
// Complain if we are converting a lambda expression to a boolean value
16542+
if (const auto *MCallExpr = dyn_cast<CXXMemberCallExpr>(E)) {
16543+
if (const auto *MRecordDecl = MCallExpr->getRecordDecl();
16544+
MRecordDecl && MRecordDecl->isLambda()) {
16545+
Diag(E->getExprLoc(), diag::warn_impcast_pointer_to_bool)
16546+
<< /*LambdaPointerConversionOperatorType*/ 3
16547+
<< MRecordDecl->getSourceRange() << Range << IsEqual;
16548+
return;
16549+
}
16550+
}
16551+
1654116552
// Expect to find a single Decl. Skip anything more complicated.
1654216553
ValueDecl *D = nullptr;
1654316554
if (DeclRefExpr *R = dyn_cast<DeclRefExpr>(E)) {

clang/test/CXX/drs/dr18xx.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -281,7 +281,7 @@ namespace dr1837 { // dr1837: 3.3
281281

282282
struct A {
283283
int f();
284-
bool b = [] {
284+
bool b = [] { // since-cxx11-warning{{address of lambda function pointer conversion operator will always evaluate to 'true'}}
285285
struct Local {
286286
static_assert(sizeof(this->f()) == sizeof(int), "");
287287
};

clang/test/CXX/expr/expr.prim/expr.prim.lambda/blocks.mm

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -65,10 +65,10 @@ void nesting() {
6565

6666
namespace overloading {
6767
void bool_conversion() {
68-
if ([](){}) {
68+
if ([](){}) { // expected-warning{{address of lambda function pointer conversion operator will always evaluate to 'true'}}
6969
}
7070

71-
bool b = []{};
71+
bool b = []{}; // expected-warning{{address of lambda function pointer conversion operator will always evaluate to 'true'}}
7272
b = (bool)[]{};
7373
}
7474

@@ -108,8 +108,9 @@ void call_with_lambda() {
108108
using decltype(a)::operator id<void(*)()>; // expected-note {{here}}
109109
} extern d;
110110

111-
bool r1 = c;
112-
bool r2 = d; // expected-error {{private}}
111+
bool r1 = c; // expected-warning{{address of lambda function pointer conversion operator will always evaluate to 'true'}}
112+
bool r2 = d; // expected-error {{private}} \
113+
expected-warning{{address of lambda function pointer conversion operator will always evaluate to 'true'}}
113114
}
114115

115116
namespace PR13117 {

clang/test/SemaCXX/warn-bool-conversion.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,18 @@ struct S2 {
8181

8282
bool f5();
8383
bool f6(int);
84+
#if __cplusplus >= 201103L
85+
auto f7 = []{};
86+
auto f8 = [](){};
87+
88+
void foo() {
89+
bool b;
90+
b = f7; // expected-warning {{address of lambda function pointer conversion operator will always evaluate to 'true'}}
91+
b = f8; // expected-warning {{address of lambda function pointer conversion operator will always evaluate to 'true'}}
92+
bool is_true = [](){ return true; };
93+
// expected-warning@-1{{address of lambda function pointer conversion operator will always evaluate to 'true'}}
94+
}
95+
#endif
8496

8597
void bar() {
8698
bool b;

0 commit comments

Comments
 (0)