Skip to content

Commit 613e7c0

Browse files
committed
[Clang][Sema]: Diagnose lambda to bool implicit casts
1 parent 3e35ba5 commit 613e7c0

File tree

6 files changed

+45
-7
lines changed

6 files changed

+45
-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{| function| array| lambda function pointer conversion operator}0 '%1' "
4131+
"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: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16538,6 +16538,21 @@ 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+
std::string Str;
16546+
llvm::raw_string_ostream S(Str);
16547+
16548+
E->printPretty(S, nullptr, getPrintingPolicy());
16549+
Diag(E->getExprLoc(), diag::warn_impcast_pointer_to_bool)
16550+
<< /*LambdaPointerConversionOperatorType*/ 3 << S.str()
16551+
<< MRecordDecl->getSourceRange() << Range << IsEqual;
16552+
return;
16553+
}
16554+
}
16555+
1654116556
// Expect to find a single Decl. Skip anything more complicated.
1654216557
ValueDecl *D = nullptr;
1654316558
if (DeclRefExpr *R = dyn_cast<DeclRefExpr>(E)) {

clang/test/CXX/drs/dr18xx.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -281,12 +281,17 @@ namespace dr1837 { // dr1837: 3.3
281281

282282
struct A {
283283
int f();
284-
bool b = [] {
284+
bool b = [] { // #dr1837-a
285285
struct Local {
286286
static_assert(sizeof(this->f()) == sizeof(int), "");
287287
};
288288
};
289289
};
290+
/* since-cxx11-warning@#dr1837-a{{address of lambda function pointer conversion operator '[] {
291+
struct Local {
292+
static_assert(sizeof (this->f()) == sizeof(int), "");
293+
};
294+
}' will always evaluate to 'true'}} */
290295
#endif
291296
}
292297

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 '[]() {\n}' will always evaluate to 'true'}}
6969
}
7070

71-
bool b = []{};
71+
bool b = []{}; // expected-warning{{address of lambda function pointer conversion operator '[] {\n}' 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 'c' will always evaluate to 'true'}}
112+
bool r2 = d; // expected-error {{private}} \
113+
expected-warning{{address of lambda function pointer conversion operator 'd' will always evaluate to 'true'}}
113114
}
114115

115116
namespace PR13117 {

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

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,20 @@ 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 'f7' will always evaluate to 'true'}}
91+
b = f8; // expected-warning {{address of lambda function pointer conversion operator 'f8' will always evaluate to 'true'}}
92+
bool is_true = [](){ return true; };
93+
/* expected-warning@-1{{address of lambda function pointer conversion operator '[]() {
94+
return true;
95+
}' will always evaluate to 'true'}} */
96+
}
97+
#endif
8498

8599
void bar() {
86100
bool b;

0 commit comments

Comments
 (0)