From 338d58a998a0b4ede4596880cc6948a77f5a4d3a Mon Sep 17 00:00:00 2001 From: chrchr-github Date: Thu, 19 Jun 2025 10:46:43 +0200 Subject: [PATCH 1/2] Fix #13953 FP functionConst when casting address of pointer member --- lib/checkclass.cpp | 18 +++++++++++++++--- test/testclass.cpp | 12 ++++++++++++ 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/lib/checkclass.cpp b/lib/checkclass.cpp index 6fd15dafc72..01c54b2c1b3 100644 --- a/lib/checkclass.cpp +++ b/lib/checkclass.cpp @@ -2355,6 +2355,14 @@ bool CheckClass::isConstMemberFunc(const Scope *scope, const Token *tok) const std::set CheckClass::stl_containers_not_const = { "map", "unordered_map", "std :: map|unordered_map <" }; // start pattern +static bool isNonConstPtrCast(const Token* tok) +{ + if (!tok || !tok->isCast()) + return false; + const ValueType* vt = tok->valueType(); + return !vt || (vt->pointer > 0 && !vt->isConst(vt->pointer)); +} + bool CheckClass::checkConstFunc(const Scope *scope, const Function *func, MemberAccess& memberAccessed) const { if (mTokenizer->hasIfdef(func->functionScope->bodyStart, func->functionScope->bodyEnd)) @@ -2445,9 +2453,7 @@ bool CheckClass::checkConstFunc(const Scope *scope, const Function *func, Member } // non const pointer cast - if (tok1->valueType() && tok1->valueType()->pointer > 0 && tok1->astParent() && tok1->astParent()->isCast() && - !(tok1->astParent()->valueType() && - (tok1->astParent()->valueType()->pointer == 0 || tok1->astParent()->valueType()->isConst(tok1->astParent()->valueType()->pointer)))) + if (tok1->valueType() && tok1->valueType()->pointer > 0 && isNonConstPtrCast(tok1->astParent())) return false; const Token* lhs = tok1->previous(); @@ -2458,6 +2464,12 @@ bool CheckClass::checkConstFunc(const Scope *scope, const Function *func, Member else if (lhs->str() == ":" && lhs->astParent() && lhs->astParent()->astParent() && lhs->astParent()->str() == "?") lhs = lhs->astParent()->astParent(); if (lhs->str() == "&") { + const Token* parent = lhs->astParent(); + while (parent) { + if (isNonConstPtrCast(parent)) + return false; + parent = parent->astParent(); + } const Token* const top = lhs->astTop(); if (top->isAssignmentOp()) { if (Token::simpleMatch(top->astOperand2(), "{") && !top->astOperand2()->previous()->function()) // TODO: check usage in init list diff --git a/test/testclass.cpp b/test/testclass.cpp index 8eeb7eb7696..d5c2e1c76e5 100644 --- a/test/testclass.cpp +++ b/test/testclass.cpp @@ -189,6 +189,7 @@ class TestClass : public TestFixture { TEST_CASE(const96); TEST_CASE(const97); TEST_CASE(const98); + TEST_CASE(const99); TEST_CASE(const_handleDefaultParameters); TEST_CASE(const_passThisToMemberOfOtherClass); @@ -6835,6 +6836,17 @@ class TestClass : public TestFixture { ASSERT_EQUALS("", errout_str()); } + void const99() { + checkConst("typedef void (*InitFunc)(void**);\n" // #13953 + "struct S {\n" + " int *m;\n" + " void f(InitFunc func) {\n" + " func(reinterpret_cast(&m));\n" + " }\n" + "};\n"); + ASSERT_EQUALS("", errout_str()); + } + void const_handleDefaultParameters() { checkConst("struct Foo {\n" " void foo1(int i, int j = 0) {\n" From eafdc58fb5ce571088d1394d2d7a24bfa0d061a0 Mon Sep 17 00:00:00 2001 From: chrchr-github Date: Fri, 20 Jun 2025 18:56:48 +0200 Subject: [PATCH 2/2] Restrict loop --- lib/checkclass.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/checkclass.cpp b/lib/checkclass.cpp index 01c54b2c1b3..7bfc1eaf045 100644 --- a/lib/checkclass.cpp +++ b/lib/checkclass.cpp @@ -2465,7 +2465,7 @@ bool CheckClass::checkConstFunc(const Scope *scope, const Function *func, Member lhs = lhs->astParent()->astParent(); if (lhs->str() == "&") { const Token* parent = lhs->astParent(); - while (parent) { + while (Token::Match(parent, "[+(]")) { if (isNonConstPtrCast(parent)) return false; parent = parent->astParent();