Author: Fangrui Song Date: 2024-03-01T08:57:54-08:00 New Revision: 64216ba1e427fab1ee38ef9492d3fbca907606b9
URL: https://github.com/llvm/llvm-project/commit/64216ba1e427fab1ee38ef9492d3fbca907606b9 DIFF: https://github.com/llvm/llvm-project/commit/64216ba1e427fab1ee38ef9492d3fbca907606b9.diff LOG: [Sema] -Wpointer-bool-conversion: suppress lambda function pointer conversion diagnostic during instantiation (#83497) I have seen two internal pieces of code that uses a template type parameter to accept any callable type (function pointer, std::function, closure type, etc). The diagnostic added in #83152 would require adaptation to the template, which is difficult and also seems unnecessary. Example: ```cpp template <typename... Ts> static bool IsFalse(const Ts&...) { return false; } template <typename T, typename... Ts, typename = typename std::enable_if<std::is_constructible<bool, const T&>::value>::type> static bool IsFalse(const T& p, const Ts&...) { return p ? false : true; } template <typename... Args> void Init(Args&&... args) { if (IsFalse(absl::implicit_cast<const typename std::decay<Args>::type&>( args)...)) { // A callable object convertible to false is either a null pointer or a // null functor (e.g., a default-constructed std::function). empty_ = true; } else { empty_ = false; new (&factory_) Factory(std::forward<Args>(args)...); } } ``` Added: Modified: clang/lib/Sema/SemaChecking.cpp clang/test/SemaCXX/warn-bool-conversion.cpp Removed: ################################################################################ diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index 7be2b31df2413f..9f9b0a0baba666 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -16588,13 +16588,16 @@ 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()) { - Diag(E->getExprLoc(), diag::warn_impcast_pointer_to_bool) - << /*LambdaPointerConversionOperatorType=*/3 - << MRecordDecl->getSourceRange() << Range << IsEqual; - return; + // outside of instantiation. + if (!inTemplateInstantiation()) { + if (const auto *MCallExpr = dyn_cast<CXXMemberCallExpr>(E)) { + if (const auto *MRecordDecl = MCallExpr->getRecordDecl(); + MRecordDecl && MRecordDecl->isLambda()) { + Diag(E->getExprLoc(), diag::warn_impcast_pointer_to_bool) + << /*LambdaPointerConversionOperatorType=*/3 + << MRecordDecl->getSourceRange() << Range << IsEqual; + return; + } } } diff --git a/clang/test/SemaCXX/warn-bool-conversion.cpp b/clang/test/SemaCXX/warn-bool-conversion.cpp index 9e8cf0e4f8944a..18c35776b17bc7 100644 --- a/clang/test/SemaCXX/warn-bool-conversion.cpp +++ b/clang/test/SemaCXX/warn-bool-conversion.cpp @@ -92,6 +92,21 @@ void foo() { bool is_true = [](){ return true; }; // expected-warning@-1{{address of lambda function pointer conversion operator will always evaluate to 'true'}} } + +template <typename... Ts> +static bool IsFalse(const Ts&...) { return false; } +template <typename T> +static bool IsFalse(const T& p) { + bool b; + b = f7; // expected-warning {{address of lambda function pointer conversion operator will always evaluate to 'true'}} + // Intentionally not warned on because p could be a lambda type in one + // instantiation, but a pointer type in another. + return p ? false : true; +} + +bool use_instantiation() { + return IsFalse([]() { return 0; }); +} #endif void bar() { _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits