Fix #10735 FP functionConst with overloaded operator[] [inconclusive] (#3733)

This commit is contained in:
chrchr-github 2022-01-21 20:40:10 +01:00 committed by GitHub
parent be73eb3c7c
commit b23ca879ed
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 28 additions and 0 deletions

View File

@ -2168,6 +2168,18 @@ bool CheckClass::checkConstFunc(const Scope *scope, const Function *func, bool&
const Variable *var = end->variable(); const Variable *var = end->variable();
if (var && var->isStlType(stl_containers_not_const)) if (var && var->isStlType(stl_containers_not_const))
return false; 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<std::string, const Function*>& fm) {
return fm.second->isConst() && fm.first == "operator[]" && !Function::returnsConst(fm.second);
}))
return false;
}
}
} }
if (!jumpBackToken) if (!jumpBackToken)
jumpBackToken = end->next(); // Check inside the [] brackets jumpBackToken = end->next(); // Check inside the [] brackets

View File

@ -175,6 +175,7 @@ private:
TEST_CASE(const70); // variadic template can receive more arguments than in its definition TEST_CASE(const70); // variadic template can receive more arguments than in its definition
TEST_CASE(const71); // ticket #10146 TEST_CASE(const71); // ticket #10146
TEST_CASE(const72); // ticket #10520 TEST_CASE(const72); // ticket #10520
TEST_CASE(const73); // ticket #10735
TEST_CASE(const_handleDefaultParameters); TEST_CASE(const_handleDefaultParameters);
TEST_CASE(const_passThisToMemberOfOtherClass); TEST_CASE(const_passThisToMemberOfOtherClass);
TEST_CASE(assigningPointerToPointerIsNotAConstOperation); 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()); 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() { void const_handleDefaultParameters() {
checkConst("struct Foo {\n" checkConst("struct Foo {\n"
" void foo1(int i, int j = 0) {\n" " void foo1(int i, int j = 0) {\n"