[clang] [clang] Add diagnostic for usage of implicit constructor with pointer to bool convertion (PR #143990)

via cfe-commits cfe-commits at lists.llvm.org
Thu Jun 12 16:03:40 PDT 2025


https://github.com/Ralender created https://github.com/llvm/llvm-project/pull/143990

This emits warnings for this code instead of silently creating a new B in place.
```c++
struct B {
   B(bool V) {}
};

void test(const B& b);

void test0(B* b) {
   test(b); // HERE
}
```

>From f2744c89892d2803a36d03579b1fd278cfd1bb44 Mon Sep 17 00:00:00 2001
From: tyker <tyker1 at outlook.com>
Date: Fri, 13 Jun 2025 00:49:00 +0200
Subject: [PATCH] [clang] Add diagnostic for usage of implicit constructor with
 pointer to bool convertion

Like
```c++
struct B {
   B(bool V) {}
};

void test(const B& b);

void test0(B* b) {
   test(b); // HERE
}
```
---
 .../clang/Basic/DiagnosticSemaKinds.td        |  3 ++
 clang/lib/Sema/SemaChecking.cpp               | 19 ++++++++++++
 clang/test/SemaCXX/warn-bool-conversion.cpp   | 31 +++++++++++++++++++
 3 files changed, 53 insertions(+)

diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 0f77083dac9df..8a17b04ad91ed 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -4397,6 +4397,9 @@ def ext_ms_impcast_fn_obj : ExtWarn<
   "implicit conversion between pointer-to-function and pointer-to-object is a "
   "Microsoft extension">, InGroup<MicrosoftCast>;
 
+def warn_imp_constructor_pointer_to_bool : Warning<
+    "implicit conversion from %0 to %1 calls %q2; maybe you intended to dereference">,
+    InGroup<PointerBoolConversion>;
 def warn_impcast_pointer_to_bool : Warning<
     "address of %select{'%1'|function '%1'|array '%1'|lambda function pointer "
     "conversion operator}0 will always evaluate to 'true'">,
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 8f8e1ceb7197e..d0d52f3a1fe87 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -11767,6 +11767,25 @@ static void CheckImplicitArgumentConversions(Sema &S, const CallExpr *TheCall,
                                              SourceLocation CC) {
   for (unsigned I = 0, N = TheCall->getNumArgs(); I < N; ++I) {
     const Expr *CurrA = TheCall->getArg(I);
+
+    if (auto *MTE = dyn_cast<MaterializeTemporaryExpr>(CurrA))
+      // We shouldnt skip over any node here as it may be an attempt to silence
+      // the warning
+      if (auto *CCE = dyn_cast<CXXConstructExpr>(MTE->getSubExpr()))
+        if (CCE->getNumArgs() == 1) {
+          Expr *Inner = CCE->getArg(0)->IgnoreImpCasts();
+          if ((Inner->getType()->isAnyPointerType() &&
+               Inner->getType()->getPointeeType().getUnqualifiedType() ==
+                   CCE->getType().getUnqualifiedType())) {
+            S.Diag(CCE->getLocation(),
+                   diag::warn_imp_constructor_pointer_to_bool)
+                << Inner->getType() << CCE->getType() << CCE->getConstructor();
+            S.Diag(CCE->getConstructor()->getLocation(),
+                   diag::note_entity_declared_at)
+                << CCE->getConstructor();
+          }
+        }
+
     if (!IsImplicitBoolFloatConversion(S, CurrA, true))
       continue;
 
diff --git a/clang/test/SemaCXX/warn-bool-conversion.cpp b/clang/test/SemaCXX/warn-bool-conversion.cpp
index 18c35776b17bc..52d5315e7cb3b 100644
--- a/clang/test/SemaCXX/warn-bool-conversion.cpp
+++ b/clang/test/SemaCXX/warn-bool-conversion.cpp
@@ -234,3 +234,34 @@ namespace Template {
   template void h<d>();
 }
 #endif // __cplusplus < 201703L
+
+namespace implicit_constructor_bool {
+
+struct B {
+  bool a;
+  B(bool V) : a(V) {} // expected-note {{'B' declared here}}
+};
+
+void test(const B& b);
+
+void test0(B* b) {
+  test(b); // expected-warning {{implicit conversion from 'B *' to 'const B' calls}}
+  test((const B&)b);
+  test(B(b));
+  test((bool)b);
+  test(static_cast<bool>(b));
+  test(*b);
+}
+
+struct C {
+  bool a;
+  explicit C(bool V) : a(V) {}
+};
+
+void testC(const C& b); // expected-note {{candidate function not viable: no known conversion from 'C *' to 'const C'}}
+
+void testC0(C* b) {
+  testC(b); // expected-error {{no matching function for call to 'testC'}}
+}
+
+}



More information about the cfe-commits mailing list