From b23ca879ed8f31eead0104abd90230fe7282e498 Mon Sep 17 00:00:00 2001 From: chrchr-github <78114321+chrchr-github@users.noreply.github.com> Date: Fri, 21 Jan 2022 20:40:10 +0100 Subject: [PATCH] Fix #10735 FP functionConst with overloaded operator[] [inconclusive] (#3733) --- lib/checkclass.cpp | 12 ++++++++++++ test/testclass.cpp | 16 ++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/lib/checkclass.cpp b/lib/checkclass.cpp index e3777fdd4..300355326 100644 --- a/lib/checkclass.cpp +++ b/lib/checkclass.cpp @@ -2168,6 +2168,18 @@ bool CheckClass::checkConstFunc(const Scope *scope, const Function *func, bool& const Variable *var = end->variable(); if (var && var->isStlType(stl_containers_not_const)) return false; + const Token* assignTok = end->next()->astParent(); + if (assignTok && assignTok->isAssignmentOp() && assignTok->astOperand1() && assignTok->astOperand1()->variable()) { + const Variable* assignVar = assignTok->astOperand1()->variable(); + if (assignVar->isPointer() && !assignVar->isConst() && var->typeScope()) { + const auto& funcMap = var->typeScope()->functionMap; + // if there is no operator that is const and returns a non-const pointer, func cannot be const + if (std::none_of(funcMap.begin(), funcMap.end(), [](const std::pair& fm) { + return fm.second->isConst() && fm.first == "operator[]" && !Function::returnsConst(fm.second); + })) + return false; + } + } } if (!jumpBackToken) jumpBackToken = end->next(); // Check inside the [] brackets diff --git a/test/testclass.cpp b/test/testclass.cpp index 475bd5f17..addc10061 100644 --- a/test/testclass.cpp +++ b/test/testclass.cpp @@ -175,6 +175,7 @@ private: TEST_CASE(const70); // variadic template can receive more arguments than in its definition TEST_CASE(const71); // ticket #10146 TEST_CASE(const72); // ticket #10520 + TEST_CASE(const73); // ticket #10735 TEST_CASE(const_handleDefaultParameters); TEST_CASE(const_passThisToMemberOfOtherClass); TEST_CASE(assigningPointerToPointerIsNotAConstOperation); @@ -5886,6 +5887,21 @@ private: TODO_ASSERT_EQUALS("[test.cpp:7]: (style, inconclusive) Technically the member function 'C::f' can be const.\n", "", errout.str()); } + void const73() { + checkConst("struct A {\n" + " int* operator[](int i);\n" + " const int* operator[](int i) const;\n" + "};\n" + "struct S {\n" + " A a;\n" + " void f(int j) {\n" + " int* p = a[j];\n" + " *p = 0;\n" + " }\n" + "};\n"); + ASSERT_EQUALS("", errout.str()); + } + void const_handleDefaultParameters() { checkConst("struct Foo {\n" " void foo1(int i, int j = 0) {\n"