parent
809430631f
commit
9ed21fb917
|
@ -2306,6 +2306,19 @@ bool CheckClass::checkConstFunc(const Scope *scope, const Function *func, bool&
|
||||||
return false;
|
return false;
|
||||||
memberAccessed = true;
|
memberAccessed = true;
|
||||||
}
|
}
|
||||||
|
bool mayModifyArgs = true;
|
||||||
|
if (const Function* f = funcTok->function()) { // TODO: improve (we bail out if there is any possible modification of any argument)
|
||||||
|
const std::vector<const Token*> args = getArguments(funcTok);
|
||||||
|
const auto argMax = std::min<nonneg int>(args.size(), f->argCount());
|
||||||
|
mayModifyArgs = false;
|
||||||
|
for (nonneg int argIndex = 0; argIndex < argMax; ++argIndex) {
|
||||||
|
const Variable* const argVar = f->getArgumentVar(argIndex);
|
||||||
|
if (!argVar || !argVar->valueType() || ((argVar->valueType()->pointer || argVar->valueType()->reference != Reference::None) && !argVar->isConst())) {
|
||||||
|
mayModifyArgs = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
// Member variable given as parameter
|
// Member variable given as parameter
|
||||||
const Token *lpar = funcTok->next();
|
const Token *lpar = funcTok->next();
|
||||||
if (Token::simpleMatch(lpar, "( ) ("))
|
if (Token::simpleMatch(lpar, "( ) ("))
|
||||||
|
@ -2313,9 +2326,9 @@ bool CheckClass::checkConstFunc(const Scope *scope, const Function *func, bool&
|
||||||
for (const Token* tok = lpar->next(); tok && tok != funcTok->next()->link(); tok = tok->next()) {
|
for (const Token* tok = lpar->next(); tok && tok != funcTok->next()->link(); tok = tok->next()) {
|
||||||
if (tok->str() == "(")
|
if (tok->str() == "(")
|
||||||
tok = tok->link();
|
tok = tok->link();
|
||||||
else if ((tok->isName() && isMemberVar(scope, tok)) || (tok->isUnaryOp("&") && (tok = tok->astOperand1()))) {
|
else if ((tok->isName() && isMemberVar(scope, tok)) || (tok->isUnaryOp("&") && (tok = tok->astOperand1()) && isMemberVar(scope, tok))) {
|
||||||
const Variable* var = tok->variable();
|
const Variable* var = tok->variable();
|
||||||
if (!var || !var->isMutable())
|
if ((!var || !var->isMutable()) && mayModifyArgs)
|
||||||
return false; // TODO: Only bailout if function takes argument as non-const reference
|
return false; // TODO: Only bailout if function takes argument as non-const reference
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -145,7 +145,7 @@ public:
|
||||||
bool isUnusedFunctionCheckEnabled() const;
|
bool isUnusedFunctionCheckEnabled() const;
|
||||||
|
|
||||||
/** Remove *.ctu-info files */
|
/** Remove *.ctu-info files */
|
||||||
void removeCtuInfoFiles(const std::map<std::string, std::size_t>& files);
|
void removeCtuInfoFiles(const std::map<std::string, std::size_t>& files); // cppcheck-suppress functionConst // has side effects
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/** Are there "simple" rules */
|
/** Are there "simple" rules */
|
||||||
|
|
|
@ -1474,12 +1474,12 @@ private:
|
||||||
void createSymbolDatabaseNeedInitialization();
|
void createSymbolDatabaseNeedInitialization();
|
||||||
void createSymbolDatabaseVariableSymbolTable();
|
void createSymbolDatabaseVariableSymbolTable();
|
||||||
void createSymbolDatabaseSetScopePointers();
|
void createSymbolDatabaseSetScopePointers();
|
||||||
void createSymbolDatabaseSetFunctionPointers(bool firstPass);
|
void createSymbolDatabaseSetFunctionPointers(bool firstPass); // cppcheck-suppress functionConst // has side effects
|
||||||
void createSymbolDatabaseSetVariablePointers();
|
void createSymbolDatabaseSetVariablePointers();
|
||||||
// cppcheck-suppress functionConst
|
// cppcheck-suppress functionConst
|
||||||
void createSymbolDatabaseSetTypePointers();
|
void createSymbolDatabaseSetTypePointers();
|
||||||
void createSymbolDatabaseSetSmartPointerType();
|
void createSymbolDatabaseSetSmartPointerType();
|
||||||
void createSymbolDatabaseEnums();
|
void createSymbolDatabaseEnums(); // cppcheck-suppress functionConst // has side effects
|
||||||
void createSymbolDatabaseEscapeFunctions();
|
void createSymbolDatabaseEscapeFunctions();
|
||||||
// cppcheck-suppress functionConst
|
// cppcheck-suppress functionConst
|
||||||
void createSymbolDatabaseIncompleteVars();
|
void createSymbolDatabaseIncompleteVars();
|
||||||
|
|
|
@ -586,7 +586,7 @@ private:
|
||||||
|
|
||||||
void unsupportedTypedef(const Token *tok) const;
|
void unsupportedTypedef(const Token *tok) const;
|
||||||
|
|
||||||
void setVarIdClassDeclaration(const Token * const startToken,
|
void setVarIdClassDeclaration(const Token * const startToken, // cppcheck-suppress functionConst // has side effects
|
||||||
VariableMap &variableMap,
|
VariableMap &variableMap,
|
||||||
const nonneg int scopeStartVarId,
|
const nonneg int scopeStartVarId,
|
||||||
std::map<nonneg int, std::map<std::string, nonneg int>>& structMembers);
|
std::map<nonneg int, std::map<std::string, nonneg int>>& structMembers);
|
||||||
|
@ -595,7 +595,7 @@ private:
|
||||||
std::map<nonneg int, std::map<std::string, nonneg int>>& structMembers,
|
std::map<nonneg int, std::map<std::string, nonneg int>>& structMembers,
|
||||||
nonneg int &varId) const;
|
nonneg int &varId) const;
|
||||||
|
|
||||||
void setVarIdClassFunction(const std::string &classname,
|
void setVarIdClassFunction(const std::string &classname, // cppcheck-suppress functionConst // has side effects
|
||||||
Token * const startToken,
|
Token * const startToken,
|
||||||
const Token * const endToken,
|
const Token * const endToken,
|
||||||
const std::map<std::string, nonneg int> &varlist,
|
const std::map<std::string, nonneg int> &varlist,
|
||||||
|
|
|
@ -195,7 +195,9 @@ private:
|
||||||
TEST_CASE(const79); // ticket #9861
|
TEST_CASE(const79); // ticket #9861
|
||||||
TEST_CASE(const80); // ticket #11328
|
TEST_CASE(const80); // ticket #11328
|
||||||
TEST_CASE(const81); // ticket #11330
|
TEST_CASE(const81); // ticket #11330
|
||||||
TEST_CASE(const82);
|
TEST_CASE(const82); // ticket #11513
|
||||||
|
TEST_CASE(const83);
|
||||||
|
|
||||||
TEST_CASE(const_handleDefaultParameters);
|
TEST_CASE(const_handleDefaultParameters);
|
||||||
TEST_CASE(const_passThisToMemberOfOtherClass);
|
TEST_CASE(const_passThisToMemberOfOtherClass);
|
||||||
TEST_CASE(assigningPointerToPointerIsNotAConstOperation);
|
TEST_CASE(assigningPointerToPointerIsNotAConstOperation);
|
||||||
|
@ -6322,7 +6324,26 @@ private:
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void const82() {
|
void const82() { // #11513
|
||||||
|
checkConst("struct S {\n"
|
||||||
|
" int i;\n"
|
||||||
|
" void h(bool) const;\n"
|
||||||
|
" void g() { h(i == 1); }\n"
|
||||||
|
"};\n");
|
||||||
|
ASSERT_EQUALS("[test.cpp:4]: (style, inconclusive) Technically the member function 'S::g' can be const.\n",
|
||||||
|
errout.str());
|
||||||
|
|
||||||
|
checkConst("struct S {\n"
|
||||||
|
" int i;\n"
|
||||||
|
" void h(int, int*) const;\n"
|
||||||
|
" void g() { int a; h(i, &a); }\n"
|
||||||
|
"};\n");
|
||||||
|
TODO_ASSERT_EQUALS("[test.cpp:4]: (style, inconclusive) Technically the member function 'S::g' can be const.\n",
|
||||||
|
"",
|
||||||
|
errout.str());
|
||||||
|
}
|
||||||
|
|
||||||
|
void const83() {
|
||||||
checkConst("struct S {\n"
|
checkConst("struct S {\n"
|
||||||
" int i1, i2;\n"
|
" int i1, i2;\n"
|
||||||
" void f(bool b);\n"
|
" void f(bool b);\n"
|
||||||
|
|
|
@ -561,7 +561,7 @@ private:
|
||||||
ASSERT_EQUALS(true, suppressions6.isSuppressed(errorMessage("abc", "test.cpp", 123)));
|
ASSERT_EQUALS(true, suppressions6.isSuppressed(errorMessage("abc", "test.cpp", 123)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void inlinesuppress() {
|
void inlinesuppress() const {
|
||||||
Suppressions::Suppression s;
|
Suppressions::Suppression s;
|
||||||
std::string msg;
|
std::string msg;
|
||||||
ASSERT_EQUALS(false, s.parseComment("/* some text */", &msg));
|
ASSERT_EQUALS(false, s.parseComment("/* some text */", &msg));
|
||||||
|
@ -593,7 +593,7 @@ private:
|
||||||
ASSERT_EQUALS("[test.cpp:4]: (error) Uninitialized variable: a\n", errout.str());
|
ASSERT_EQUALS("[test.cpp:4]: (error) Uninitialized variable: a\n", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void inlinesuppress_comment() {
|
void inlinesuppress_comment() const {
|
||||||
Suppressions::Suppression s;
|
Suppressions::Suppression s;
|
||||||
std::string errMsg;
|
std::string errMsg;
|
||||||
ASSERT_EQUALS(true, s.parseComment("// cppcheck-suppress abc ; some comment", &errMsg));
|
ASSERT_EQUALS(true, s.parseComment("// cppcheck-suppress abc ; some comment", &errMsg));
|
||||||
|
@ -604,7 +604,7 @@ private:
|
||||||
ASSERT_EQUALS("", errMsg);
|
ASSERT_EQUALS("", errMsg);
|
||||||
}
|
}
|
||||||
|
|
||||||
void multi_inlinesuppress() {
|
void multi_inlinesuppress() const {
|
||||||
std::vector<Suppressions::Suppression> suppressions;
|
std::vector<Suppressions::Suppression> suppressions;
|
||||||
std::string errMsg;
|
std::string errMsg;
|
||||||
|
|
||||||
|
@ -669,7 +669,7 @@ private:
|
||||||
ASSERT_EQUALS(false, errMsg.empty());
|
ASSERT_EQUALS(false, errMsg.empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
void multi_inlinesuppress_comment() {
|
void multi_inlinesuppress_comment() const {
|
||||||
std::vector<Suppressions::Suppression> suppressions;
|
std::vector<Suppressions::Suppression> suppressions;
|
||||||
std::string errMsg;
|
std::string errMsg;
|
||||||
|
|
||||||
|
|
|
@ -7171,7 +7171,7 @@ private:
|
||||||
ASSERT(tok->tokAt(2)->function());
|
ASSERT(tok->tokAt(2)->function());
|
||||||
}
|
}
|
||||||
|
|
||||||
void valueTypeMatchParameter() {
|
void valueTypeMatchParameter() const {
|
||||||
ValueType vt_int(ValueType::Sign::SIGNED, ValueType::Type::INT, 0);
|
ValueType vt_int(ValueType::Sign::SIGNED, ValueType::Type::INT, 0);
|
||||||
ValueType vt_const_int(ValueType::Sign::SIGNED, ValueType::Type::INT, 0, 1);
|
ValueType vt_const_int(ValueType::Sign::SIGNED, ValueType::Type::INT, 0, 1);
|
||||||
ASSERT_EQUALS((int)ValueType::MatchResult::SAME, (int)ValueType::matchParameter(&vt_int, &vt_int));
|
ASSERT_EQUALS((int)ValueType::MatchResult::SAME, (int)ValueType::matchParameter(&vt_int, &vt_int));
|
||||||
|
|
Loading…
Reference in New Issue