[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