[clang] [clang-tools-extra] [clang][clang-tidy] Fixes false positive with a non-const method on a pointer (PR #188844)

Berkay Sahin via cfe-commits cfe-commits at lists.llvm.org
Sat Apr 4 14:00:16 PDT 2026


https://github.com/berkaysahiin updated https://github.com/llvm/llvm-project/pull/188844

>From 939e926a0f72e6620f545ad02de7fe3122a818c1 Mon Sep 17 00:00:00 2001
From: Berkay Sahin <berkaysahindev at gmail.com>
Date: Fri, 27 Mar 2026 00:03:11 +0300
Subject: [PATCH 1/2] [clang][clang-tidy] False-positive with non-const methods
 on pointer variables

---
 clang-tools-extra/docs/ReleaseNotes.rst               |  4 ++++
 .../checkers/misc/const-correctness-parameters.cpp    |  7 +++++--
 .../misc/const-correctness-pointer-as-values.cpp      | 11 +++++++++++
 clang/lib/Analysis/ExprMutationAnalyzer.cpp           |  4 +++-
 4 files changed, 23 insertions(+), 3 deletions(-)

diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index f8550e72dcc85..0818eac233c8b 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -289,6 +289,10 @@ Changes in existing checks
   - Fixed false positive where a pointer used with placement new was
     incorrectly diagnosed as allowing the pointee to be made ``const``.
 
+  - Fixed false positive where calling a non-const member function on a
+    pointer was incorrectly treated as mutating the pointer, when it only
+    mutates the pointee.
+
 - Improved :doc:`misc-multiple-inheritance
   <clang-tidy/checks/misc/multiple-inheritance>` by avoiding false positives when
   virtual inheritance causes concrete bases to be counted more than once.
diff --git a/clang-tools-extra/test/clang-tidy/checkers/misc/const-correctness-parameters.cpp b/clang-tools-extra/test/clang-tidy/checkers/misc/const-correctness-parameters.cpp
index 8ff099eadb5a9..a8d90f1b582bf 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/misc/const-correctness-parameters.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/misc/const-correctness-parameters.cpp
@@ -40,6 +40,8 @@ void pointer_param_read_only(Bar* b) {
 }
 
 void pointer_param_mutated_pointee(Bar* b) {
+  // CHECK-MESSAGES: [[@LINE-1]]:36: warning: variable 'b' of type 'Bar *' can be declared 'const'
+  // CHECK-FIXES: void pointer_param_mutated_pointee(Bar* const b) {
   b->mutating_method();
 }
 
@@ -505,8 +507,9 @@ void struct_ptr_param(Bar** bp) {
 }
 
 void struct_ptr_param_modified(Bar** bp) {
-  // CHECK-MESSAGES: [[@LINE-1]]:32: warning: variable 'bp' of type 'Bar **' can be declared 'const'
-  // CHECK-FIXES: void struct_ptr_param_modified(Bar** const bp) {
+  // CHECK-MESSAGES: [[@LINE-1]]:32: warning: pointee of variable 'bp' of type 'Bar **' can be declared 'const'
+  // CHECK-MESSAGES: [[@LINE-2]]:32: warning: variable 'bp' of type 'Bar **' can be declared 'const'
+  // CHECK-FIXES: void struct_ptr_param_modified(Bar* const* const bp) {
   (*bp)->mutating_method();
 }
 
diff --git a/clang-tools-extra/test/clang-tidy/checkers/misc/const-correctness-pointer-as-values.cpp b/clang-tools-extra/test/clang-tidy/checkers/misc/const-correctness-pointer-as-values.cpp
index 02d32c0ec73e5..41cf3d8b4aa05 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/misc/const-correctness-pointer-as-values.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/misc/const-correctness-pointer-as-values.cpp
@@ -72,3 +72,14 @@ void instantiate() {
   // CHECK-FIXES: int *const p_local0[4] = {nullptr, nullptr, nullptr, nullptr};
   EmitProtocolMethodList(p_local0);
 }
+
+struct Mutating {
+  void mutating_method();
+};
+
+void pointer_member_call_not_pointer_mutation() {
+  Mutating *p = nullptr;
+  // CHECK-MESSAGES: warning: variable 'p' of type 'Mutating *' can be declared 'const'
+  // CHECK-FIXES: Mutating *const p = nullptr;
+  p->mutating_method();
+}
diff --git a/clang/lib/Analysis/ExprMutationAnalyzer.cpp b/clang/lib/Analysis/ExprMutationAnalyzer.cpp
index 5def6ba3cac5a..ad7ce91e0f966 100644
--- a/clang/lib/Analysis/ExprMutationAnalyzer.cpp
+++ b/clang/lib/Analysis/ExprMutationAnalyzer.cpp
@@ -404,7 +404,9 @@ ExprMutationAnalyzer::Analyzer::findDirectMutation(const Expr *Exp) {
   const auto NonConstMethod = cxxMethodDecl(unless(isConst()));
 
   const auto AsNonConstThis = expr(anyOf(
-      cxxMemberCallExpr(on(canResolveToExpr(Exp)), unless(isConstCallee())),
+      cxxMemberCallExpr(
+          on(canResolveToExpr(Exp)),
+          unless(anyOf(isConstCallee(), thisPointerType(pointerType())))),
       cxxOperatorCallExpr(callee(NonConstMethod),
                           hasArgument(0, canResolveToExpr(Exp))),
       // In case of a templated type, calling overloaded operators is not

>From 37470bd0d95ef863d5d96af0a71ead1704d825b8 Mon Sep 17 00:00:00 2001
From: Berkay Sahin <berkaysahindev at gmail.com>
Date: Sun, 5 Apr 2026 00:00:04 +0300
Subject: [PATCH 2/2] Address PR comments

---
 .../checkers/misc/const-correctness-pointer-as-values.cpp       | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang-tools-extra/test/clang-tidy/checkers/misc/const-correctness-pointer-as-values.cpp b/clang-tools-extra/test/clang-tidy/checkers/misc/const-correctness-pointer-as-values.cpp
index 41cf3d8b4aa05..0875e79e22f17 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/misc/const-correctness-pointer-as-values.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/misc/const-correctness-pointer-as-values.cpp
@@ -79,7 +79,7 @@ struct Mutating {
 
 void pointer_member_call_not_pointer_mutation() {
   Mutating *p = nullptr;
-  // CHECK-MESSAGES: warning: variable 'p' of type 'Mutating *' can be declared 'const'
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p' of type 'Mutating *' can be declared 'const'
   // CHECK-FIXES: Mutating *const p = nullptr;
   p->mutating_method();
 }



More information about the cfe-commits mailing list