Refactorized CheckClass::checkConst:

- Added checking for functions that can be even declared static (#1971. Removed fix for #1563)
- Consistent usage of Function::TokenDef to avoid problems with scope identifiers
- Rewrote parsing of function body making it more generic
- Removed three redundant tests
This commit is contained in:
PKEuS 2012-08-01 10:24:38 -07:00
parent 98d608231d
commit 88e4794d6e
3 changed files with 185 additions and 214 deletions

View File

@ -1197,15 +1197,13 @@ void CheckClass::checkConst()
for (func = scope->functionList.begin(); func != scope->functionList.end(); ++func) {
// does the function have a body?
if (func->type == Function::eFunction && func->hasBody && !func->isFriend && !func->isStatic && !func->isConst && !func->isVirtual) {
if (func->type == Function::eFunction && func->hasBody && !func->isFriend && !func->isStatic && !func->isVirtual) {
// get last token of return type
const Token *previous = func->tokenDef->isName() ? func->token->previous() : func->token->tokAt(-2);
while (previous && previous->str() == "::")
previous = previous->tokAt(-2);
const Token *previous = func->tokenDef->previous();
// does the function return a pointer or reference?
if (Token::Match(previous, "*|&")) {
const Token *temp = func->token->previous();
const Token *temp = previous;
while (!Token::Match(temp->previous(), ";|}|{|public:|protected:|private:"))
temp = temp->previous();
@ -1213,7 +1211,7 @@ void CheckClass::checkConst()
if (temp->str() != "const")
continue;
} else if (Token::Match(previous->previous(), "*|& >")) {
const Token *temp = func->token->previous();
const Token *temp = previous;
while (!Token::Match(temp->previous(), ";|}|{|public:|protected:|private:")) {
temp = temp->previous();
@ -1223,27 +1221,15 @@ void CheckClass::checkConst()
if (temp->str() != "const")
continue;
} else if (func->isOperator && Token::Match(func->tokenDef->previous(), ";|{|}|public:|private:|protected:")) { // Operator without return type: conversion operator
const std::string& opName = func->token->str();
} else if (func->isOperator && Token::Match(previous, ";|{|}|public:|private:|protected:")) { // Operator without return type: conversion operator
const std::string& opName = func->tokenDef->str();
if (opName.compare(8, 5, "const") != 0 && opName[opName.size()-1] == '&')
continue;
} else {
// don't warn for unknown types..
// LPVOID, HDC, etc
if (previous->isName()) {
bool allupper = true;
const std::string& s(previous->str());
for (std::string::size_type pos = 0; pos < s.size(); ++pos) {
const char ch = s[pos];
if (ch != '_' && !std::isupper(ch)) {
allupper = false;
break;
}
}
if (allupper && s.size() > 2)
continue;
}
if (previous->isUpperCaseName() && previous->str().size() > 2 && !symbolDatabase->isClassOrStruct(previous->str()))
continue;
}
// check if base class function is virtual
@ -1252,8 +1238,9 @@ void CheckClass::checkConst()
continue;
}
bool memberAccessed = false;
// if nothing non-const was found. write error..
if (checkConstFunc(&(*scope), &*func)) {
if (checkConstFunc(&(*scope), &*func, memberAccessed)) {
std::string classname = scope->className;
const Scope *nest = scope->nestedIn;
while (nest && nest->type != Scope::eGlobal) {
@ -1269,10 +1256,12 @@ void CheckClass::checkConst()
else if (func->tokenDef->str() == "[")
functionName += "]";
if (func->isInline)
checkConstError(func->token, classname, functionName);
else // not inline
checkConstError2(func->token, func->tokenDef, classname, functionName);
if (!func->isConst || (!memberAccessed && !func->isOperator)) {
if (func->isInline)
checkConstError(func->token, classname, functionName, !memberAccessed && !func->isOperator);
else // not inline
checkConstError2(func->token, func->tokenDef, classname, functionName, !memberAccessed && !func->isOperator);
}
}
}
}
@ -1309,7 +1298,7 @@ bool CheckClass::isMemberVar(const Scope *scope, const Token *tok)
if (tok->varId() == 0)
symbolDatabase->debugMessage(tok, "CheckClass::isMemberVar found used member variable \'" + tok->str() + "\' with varid 0");
return !var->isMutable();
return !var->isStatic();
}
}
@ -1375,7 +1364,7 @@ bool CheckClass::isMemberFunc(const Scope *scope, const Token *tok)
/** @todo we need to look at the argument types when there are overloaded functions
* with the same number of arguments */
if (func->tokenDef->str() == tok->str() && (func->argCount() == args || (func->argCount() > args && countMinArgs(func->argDef) <= args))) {
return true;
return !func->isStatic;
}
}
@ -1437,138 +1426,139 @@ bool CheckClass::isConstMemberFunc(const Scope *scope, const Token *tok)
return false;
}
bool CheckClass::checkConstFunc(const Scope *scope, const Function *func)
bool CheckClass::checkConstFunc(const Scope *scope, const Function *func, bool& memberAccessed)
{
// if the function doesn't have any assignment nor function call,
// it can be a const function..
for (const Token *tok1 = func->functionScope->classStart; tok1 && tok1 != func->functionScope->classEnd; tok1 = tok1->next()) {
// assignment.. = += |= ..
if (tok1->isAssignmentOp()) {
if (tok1->next()->str() == "this") {
return(false);
} else if (isMemberVar(scope, tok1->previous())) {
if (tok1->isName() && isMemberVar(scope, tok1)) {
memberAccessed = true;
const Variable* v = symbolDatabase->getVariableFromVarId(tok1->varId());
if (v && v->isMutable())
continue;
if (tok1->str() == "this" && tok1->previous()->isAssignmentOp())
return(false);
unsigned int lastVarId = tok1->varId();
const Token* end = tok1;
for (;;) {
if (Token::Match(end->next(), ". %var%")) {
end = end->tokAt(2);
if (end->varId())
lastVarId = end->varId();
} else if (end->strAt(1) == "[") {
if (end->varId()) {
const Variable *var = symbolDatabase->getVariableFromVarId(end->varId());
if (var && Token::simpleMatch(var->typeStartToken(), "std :: map")) // operator[] changes a map
return(false);
}
end = end->linkAt(1);
} else if (end->strAt(1) == ")")
end = end->next();
else
break;
}
if (end->strAt(1) == "(") {
const Variable *var = symbolDatabase->getVariableFromVarId(lastVarId);
if (!var)
return(false);
if (Token::simpleMatch(var->typeStartToken(), "std ::") // assume all std::*::size() and std::*::empty() are const
&& (Token::Match(end, "size|empty|cend|crend|cbegin|crbegin|max_size|length|count|capacity|get_allocator|c_str|str ( )") || Token::Match(end, "rfind|copy")))
;
else if (!var->type() || !isConstMemberFunc(var->type(), end))
return(false);
}
// Assignment
else if (end->next()->type() == Token::eAssignmentOp)
return(false);
// Streaming
else if (end->strAt(1) == "<<" && tok1->strAt(-1) != "<<")
return(false);
else if (tok1->strAt(-1) == ">>")
return(false);
// ++/--
else if (end->next()->type() == Token::eIncDecOp || tok1->previous()->type() == Token::eIncDecOp)
return(false);
const Token* start = tok1;
while (tok1->strAt(-1) == ")")
tok1 = tok1->linkAt(-1);
if (start->strAt(-1) == "delete")
return(false);
tok1 = end;
}
// streaming: <<
else if (tok1->str() == "<<" && isMemberVar(scope, tok1->previous()) && tok1->strAt(-2) != "<<") {
return(false);
} else if (Token::simpleMatch(tok1->previous(), ") <<") &&
isMemberVar(scope, tok1->tokAt(-2))) {
return(false);
}
// streaming: >>
else if (tok1->str() == ">>" && isMemberVar(scope, tok1->next())) {
return(false);
}
// increment/decrement (member variable?)..
else if (tok1->type() == Token::eIncDecOp) {
// var++ and var--
if (Token::Match(tok1->previous(), "%var%") &&
tok1->previous()->str() != "return") {
if (isMemberVar(scope, tok1->previous())) {
return(false);
}
}
// var[...]++ and var[...]--
else if (tok1->previous()->str() == "]") {
if (isMemberVar(scope, tok1->previous()->link()->previous())) {
return(false);
}
}
// ++var and --var
else if (Token::Match(tok1->next(), "%var%")) {
if (isMemberVar(scope, tok1->next())) {
return(false);
}
}
}
// std::map variable member
else if (Token::Match(tok1, "%var% [") && isMemberVar(scope, tok1)) {
const Variable *var = symbolDatabase->getVariableFromVarId(tok1->varId());
if (var && (var->typeStartToken()->str() == "map" ||
Token::simpleMatch(var->typeStartToken(), "std :: map"))) {
else if (Token::simpleMatch(tok1->previous(), ") <<") &&
isMemberVar(scope, tok1->tokAt(-2))) {
const Variable* var = symbolDatabase->getVariableFromVarId(tok1->tokAt(-2)->varId());
if (!var || !var->isMutable())
return(false);
}
}
// function call..
else if (Token::Match(tok1, "%var% (") && !tok1->isStandardType() &&
!Token::Match(tok1, "return|if|string|switch|while|catch|for")) {
if (isMemberFunc(scope, tok1) && !isConstMemberFunc(scope, tok1) && tok1->strAt(-1) != ".") {
return(false);
if (isMemberFunc(scope, tok1) && tok1->strAt(-1) != ".") {
if (!isConstMemberFunc(scope, tok1))
return(false);
memberAccessed = true;
}
// Member variable given as parameter
for (const Token* tok2 = tok1->tokAt(2); tok2 && tok2 != tok1->next()->link(); tok2 = tok2->next()) {
if (tok2->str() == "(")
tok2 = tok2->link();
else if (tok2->isName() && isMemberVar(scope, tok2))
return(false); // TODO: Only bailout if function takes argument as non-const reference
else if (tok2->isName() && isMemberVar(scope, tok2)) {
const Variable* var = symbolDatabase->getVariableFromVarId(tok2->varId());
if (!var || !var->isMutable())
return(false); // TODO: Only bailout if function takes argument as non-const reference
}
}
} else if (Token::simpleMatch(tok1, "> (") && (!tok1->link() || !Token::Match(tok1->link()->previous(), "static_cast|const_cast|dynamic_cast|reinterpret_cast"))) {
return(false);
} else if (Token::Match(tok1, "%var% . %var% (")) {
if (!isMemberVar(scope, tok1))
tok1 = tok1->next();
else if (tok1->varId()) {
const Variable *var = symbolDatabase->getVariableFromVarId(tok1->varId());
if (var && Token::simpleMatch(var->typeStartToken(), "std ::") // assume all std::*::size() and std::*::empty() are const
&& (Token::Match(tok1->tokAt(2), "size|empty|cend|crend|cbegin|crbegin|max_size|length|count|capacity|get_allocator|c_str|str ( )") || Token::Match(tok1->tokAt(2), "rfind|copy")))
tok1 = tok1->next();
else if (var) { // Check if the function is const
const Scope* type = var->type();
if (!type || !isConstMemberFunc(type, tok1->tokAt(2)))
return(false);
else
tok1 = tok1->next();
} else
return(false);
} else
return(false);
}
// delete..
else if (tok1->str() == "delete") {
const Token* end = Token::findsimplematch(tok1->next(), ";")->previous();
while (end->str() == ")")
end = end->previous();
if (end->str() == "this")
return(false);
if (end->isName() && isMemberVar(scope, end))
return(false);
}
}
return(true);
}
void CheckClass::checkConstError(const Token *tok, const std::string &classname, const std::string &funcname)
void CheckClass::checkConstError(const Token *tok, const std::string &classname, const std::string &funcname, bool suggestStatic)
{
checkConstError2(tok, 0, classname, funcname);
checkConstError2(tok, 0, classname, funcname, suggestStatic);
}
void CheckClass::checkConstError2(const Token *tok1, const Token *tok2, const std::string &classname, const std::string &funcname)
void CheckClass::checkConstError2(const Token *tok1, const Token *tok2, const std::string &classname, const std::string &funcname, bool suggestStatic)
{
std::list<const Token *> toks;
toks.push_back(tok1);
if (tok2)
toks.push_back(tok2);
reportError(toks, Severity::style, "functionConst",
"Technically the member function '" + classname + "::" + funcname + "' can be const.\n"
"The member function '" + classname + "::" + funcname + "' can be made a const "
"function. Making this function 'const' should not cause compiler errors. "
"Even though the function can be made const function technically it may not make "
"sense conceptually. Think about your design and the task of the function first - is "
"it a function that must not change object internal state?", true);
if (!suggestStatic)
reportError(toks, Severity::style, "functionConst",
"Technically the member function '" + classname + "::" + funcname + "' can be const.\n"
"The member function '" + classname + "::" + funcname + "' can be made a const "
"function. Making this function 'const' should not cause compiler errors. "
"Even though the function can be made const function technically it may not make "
"sense conceptually. Think about your design and the task of the function first - is "
"it a function that must not change object internal state?", true);
else
reportError(toks, Severity::performance, "functionStatic",
"Technically the member function '" + classname + "::" + funcname + "' can be static.\n"
"The member function '" + classname + "::" + funcname + "' can be made a static "
"function. Making a function static can bring a performance benefit since no 'this' instance is "
"passed to the function. This change should not cause compiler errors but it does not "
"necessarily make sense conceptually. Think about your design and the task of the function first - "
"is it a function that must not access members of class instances?", true);
}
//---------------------------------------------------------------------------

View File

@ -123,8 +123,8 @@ private:
void thisSubtractionError(const Token *tok);
void operatorEqRetRefThisError(const Token *tok);
void operatorEqToSelfError(const Token *tok);
void checkConstError(const Token *tok, const std::string &classname, const std::string &funcname);
void checkConstError2(const Token *tok1, const Token *tok2, const std::string &classname, const std::string &funcname);
void checkConstError(const Token *tok, const std::string &classname, const std::string &funcname, bool suggestStatic);
void checkConstError2(const Token *tok1, const Token *tok2, const std::string &classname, const std::string &funcname, bool suggestStatic);
void initializerListError(const Token *tok1,const Token *tok2, const std::string & classname, const std::string &varname);
void suggestInitializationList(const Token *tok, const std::string& varname);
@ -140,7 +140,8 @@ private:
c.thisSubtractionError(0);
c.operatorEqRetRefThisError(0);
c.operatorEqToSelfError(0);
c.checkConstError(0, "class", "function");
c.checkConstError(0, "class", "function", false);
c.checkConstError(0, "class", "function", true);
c.initializerListError(0, 0, "class", "variable");
c.suggestInitializationList(0, "variable");
}
@ -176,7 +177,7 @@ private:
bool isMemberVar(const Scope *scope, const Token *tok);
bool isMemberFunc(const Scope *scope, const Token *tok);
bool isConstMemberFunc(const Scope *scope, const Token *tok);
bool checkConstFunc(const Scope *scope, const Function *func);
bool checkConstFunc(const Scope *scope, const Function *func, bool& memberAccessed);
// constructors helper function
/** @brief Information about a member variable. Used when checking for uninitialized variables */

View File

@ -93,7 +93,7 @@ private:
TEST_CASE(const15);
TEST_CASE(const16); // ticket #1551
TEST_CASE(const17); // ticket #1552
TEST_CASE(const18); // ticket #1563
TEST_CASE(const18);
TEST_CASE(const19); // ticket #1612
TEST_CASE(const20); // ticket #1602
TEST_CASE(const21); // ticket #1683
@ -2075,13 +2075,13 @@ private:
checkConst("class Fred {\n"
" const std::string foo() { return ""; }\n"
"};\n");
ASSERT_EQUALS("[test.cpp:2]: (style, inconclusive) Technically the member function 'Fred::foo' can be const.\n", errout.str());
ASSERT_EQUALS("[test.cpp:2]: (performance, inconclusive) Technically the member function 'Fred::foo' can be static.\n", errout.str());
checkConst("class Fred {\n"
" std::string s;\n"
" const std::string & foo() { return ""; }\n"
"};\n");
ASSERT_EQUALS("[test.cpp:3]: (style, inconclusive) Technically the member function 'Fred::foo' can be const.\n", errout.str());
ASSERT_EQUALS("[test.cpp:3]: (performance, inconclusive) Technically the member function 'Fred::foo' can be static.\n", errout.str());
// constructors can't be const..
checkConst("class Fred {\n"
@ -2120,7 +2120,7 @@ private:
" int x;\n"
" void b() { a(); }\n"
"};");
ASSERT_EQUALS("[test.cpp:4]: (style, inconclusive) Technically the member function 'Fred::b' can be const.\n", errout.str());
ASSERT_EQUALS("[test.cpp:4]: (performance, inconclusive) Technically the member function 'Fred::b' can be static.\n", errout.str());
// static functions can't be const..
checkConst("class foo\n"
@ -2134,7 +2134,7 @@ private:
checkConst("class Fred {\n"
" const std::string foo() const throw() { return ""; }\n"
"};\n");
ASSERT_EQUALS("", errout.str());
ASSERT_EQUALS("[test.cpp:2]: (performance, inconclusive) Technically the member function 'Fred::foo' can be static.\n", errout.str());
}
void const2() {
@ -2241,35 +2241,12 @@ private:
"int Fred::getA() { return a; }");
ASSERT_EQUALS("[test.cpp:5] -> [test.cpp:3]: (style, inconclusive) Technically the member function 'Fred::getA' can be const.\n", errout.str());
checkConst("class Fred {\n"
" const std::string foo();\n"
"};\n"
"const std::string Fred::foo() { return ""; }");
ASSERT_EQUALS("[test.cpp:4] -> [test.cpp:2]: (style, inconclusive) Technically the member function 'Fred::foo' can be const.\n", errout.str());
checkConst("class Fred {\n"
" std::string s;\n"
" const std::string & foo();\n"
"};\n"
"const std::string & Fred::foo() { return ""; }");
ASSERT_EQUALS("[test.cpp:5] -> [test.cpp:3]: (style, inconclusive) Technically the member function 'Fred::foo' can be const.\n", errout.str());
// constructors can't be const..
checkConst("class Fred {\n"
" int a;\n"
"public:\n"
" Fred()\n"
"};\n"
"Fred::Fred() { }");
ASSERT_EQUALS("", errout.str());
// assignment through |=..
checkConst("class Fred {\n"
" int a;\n"
" int setA();\n"
"};\n"
"int Fred::setA() { a |= true; }");
ASSERT_EQUALS("", errout.str());
ASSERT_EQUALS("[test.cpp:5] -> [test.cpp:3]: (performance, inconclusive) Technically the member function 'Fred::foo' can be static.\n", errout.str());
// functions with a function call to a non-const member can't be const.. (#1305)
checkConst("class Fred\n"
@ -2405,7 +2382,7 @@ private:
"void Fred::foo() { }"
"void Fred::foo(std::string & a) { a = s; }"
"void Fred::foo(const std::string & a) { s = a; }");
ASSERT_EQUALS("[test.cpp:7] -> [test.cpp:3]: (style, inconclusive) Technically the member function 'Fred::foo' can be const.\n"
ASSERT_EQUALS("[test.cpp:7] -> [test.cpp:3]: (performance, inconclusive) Technically the member function 'Fred::foo' can be static.\n"
"[test.cpp:7] -> [test.cpp:4]: (style, inconclusive) Technically the member function 'Fred::foo' can be const.\n", errout.str());
// check functions with different or missing parameter names
@ -2422,11 +2399,11 @@ private:
"void Fred::foo3(int a, int b) { }\n"
"void Fred::foo4(int a, int b) { }\n"
"void Fred::foo5(int, int) { }");
ASSERT_EQUALS("[test.cpp:9] -> [test.cpp:3]: (style, inconclusive) Technically the member function 'Fred::foo1' can be const.\n"
"[test.cpp:10] -> [test.cpp:4]: (style, inconclusive) Technically the member function 'Fred::foo2' can be const.\n"
"[test.cpp:11] -> [test.cpp:5]: (style, inconclusive) Technically the member function 'Fred::foo3' can be const.\n"
"[test.cpp:12] -> [test.cpp:6]: (style, inconclusive) Technically the member function 'Fred::foo4' can be const.\n"
"[test.cpp:13] -> [test.cpp:7]: (style, inconclusive) Technically the member function 'Fred::foo5' can be const.\n", errout.str());
ASSERT_EQUALS("[test.cpp:9] -> [test.cpp:3]: (performance, inconclusive) Technically the member function 'Fred::foo1' can be static.\n"
"[test.cpp:10] -> [test.cpp:4]: (performance, inconclusive) Technically the member function 'Fred::foo2' can be static.\n"
"[test.cpp:11] -> [test.cpp:5]: (performance, inconclusive) Technically the member function 'Fred::foo3' can be static.\n"
"[test.cpp:12] -> [test.cpp:6]: (performance, inconclusive) Technically the member function 'Fred::foo4' can be static.\n"
"[test.cpp:13] -> [test.cpp:7]: (performance, inconclusive) Technically the member function 'Fred::foo5' can be static.\n", errout.str());
// check nested classes
checkConst("class Fred {\n"
@ -2622,7 +2599,7 @@ private:
}
void const6() {
// ticket # 1491
// ticket #1491
checkConst("class foo {\n"
"public:\n"
"};\n"
@ -2634,7 +2611,7 @@ private:
"public:\n"
" void foo() { }\n"
"};");
ASSERT_EQUALS("[test.cpp:4]: (style, inconclusive) Technically the member function 'Fred::foo' can be const.\n", errout.str());
ASSERT_EQUALS("[test.cpp:4]: (performance, inconclusive) Technically the member function 'Fred::foo' can be static.\n", errout.str());
checkConst("struct fast_string\n"
"{\n"
@ -3197,13 +3174,12 @@ private:
}
void const18() {
// ticket #1563
checkConst("class Fred {\n"
"static int x;\n"
"public:\n"
" void set(int i) { x = i; }\n"
"};\n");
ASSERT_EQUALS("", errout.str());
ASSERT_EQUALS("[test.cpp:4]: (performance, inconclusive) Technically the member function 'Fred::set' can be static.\n", errout.str());
}
void const19() {
@ -3451,7 +3427,7 @@ private:
" UnknownScope::x = x_;\n"
" }\n"
"};\n");
ASSERT_EQUALS("[test.cpp:4]: (style, inconclusive) Technically the member function 'AA::vSetXPos' can be const.\n", errout.str());
ASSERT_EQUALS("[test.cpp:4]: (performance, inconclusive) Technically the member function 'AA::vSetXPos' can be static.\n", errout.str());
}
@ -3880,7 +3856,7 @@ private:
"{\n"
"}\n");
ASSERT_EQUALS("[test.cpp:7] -> [test.cpp:5]: (style, inconclusive) Technically the member function 'Fred::f' can be const.\n", errout.str());
ASSERT_EQUALS("[test.cpp:7] -> [test.cpp:5]: (performance, inconclusive) Technically the member function 'Fred::f' can be static.\n", errout.str());
checkConst("class Fred\n"
"{\n"
@ -3894,7 +3870,7 @@ private:
"{\n"
"}\n");
ASSERT_EQUALS("[test.cpp:9] -> [test.cpp:7]: (style, inconclusive) Technically the member function 'Fred::f' can be const.\n", errout.str());
ASSERT_EQUALS("[test.cpp:9] -> [test.cpp:7]: (performance, inconclusive) Technically the member function 'Fred::f' can be static.\n", errout.str());
checkConst("namespace NS {\n"
" class Fred\n"
@ -3910,7 +3886,7 @@ private:
" }\n"
"}\n");
ASSERT_EQUALS("[test.cpp:10] -> [test.cpp:8]: (style, inconclusive) Technically the member function 'NS::Fred::f' can be const.\n", errout.str());
ASSERT_EQUALS("[test.cpp:10] -> [test.cpp:8]: (performance, inconclusive) Technically the member function 'NS::Fred::f' can be static.\n", errout.str());
checkConst("namespace NS {\n"
" class Fred\n"
@ -3926,7 +3902,7 @@ private:
"{\n"
"}\n");
ASSERT_EQUALS("[test.cpp:11] -> [test.cpp:8]: (style, inconclusive) Technically the member function 'NS::Fred::f' can be const.\n", errout.str());
ASSERT_EQUALS("[test.cpp:11] -> [test.cpp:8]: (performance, inconclusive) Technically the member function 'NS::Fred::f' can be static.\n", errout.str());
checkConst("class Foo {\n"
" class Fred\n"
@ -3942,7 +3918,7 @@ private:
"{\n"
"}\n");
ASSERT_EQUALS("[test.cpp:11] -> [test.cpp:8]: (style, inconclusive) Technically the member function 'Foo::Fred::f' can be const.\n", errout.str());
ASSERT_EQUALS("[test.cpp:11] -> [test.cpp:8]: (performance, inconclusive) Technically the member function 'Foo::Fred::f' can be static.\n", errout.str());
}
void const43() { // ticket 2377
@ -4031,7 +4007,7 @@ private:
" };\n"
"}\n");
ASSERT_EQUALS("[test.cpp:8]: (style, inconclusive) Technically the member function 'tools::WorkspaceControl::toGrid' can be const.\n", errout.str());
ASSERT_EQUALS("[test.cpp:8]: (performance, inconclusive) Technically the member function 'tools::WorkspaceControl::toGrid' can be static.\n", errout.str());
}
void const46() { // ticket 2663
@ -4046,8 +4022,8 @@ private:
" }\n"
"};\n");
ASSERT_EQUALS("[test.cpp:3]: (style, inconclusive) Technically the member function 'Altren::fun1' can be const.\n"
"[test.cpp:7]: (style, inconclusive) Technically the member function 'Altren::fun2' can be const.\n", errout.str());
ASSERT_EQUALS("[test.cpp:3]: (performance, inconclusive) Technically the member function 'Altren::fun1' can be static.\n"
"[test.cpp:7]: (performance, inconclusive) Technically the member function 'Altren::fun2' can be static.\n", errout.str());
}
void const47() { // ticket 2670
@ -4058,7 +4034,7 @@ private:
" void bar() { foo(); }\n"
"};\n");
ASSERT_EQUALS("", errout.str());
ASSERT_EQUALS("[test.cpp:4]: (performance, inconclusive) Technically the member function 'Altren::foo' can be static.\n", errout.str());
checkConst("class Altren {\n"
"public:\n"
@ -4067,7 +4043,8 @@ private:
" void bar() { foo(1); }\n"
"};\n");
ASSERT_EQUALS("[test.cpp:5]: (style, inconclusive) Technically the member function 'Altren::bar' can be const.\n", errout.str());
ASSERT_EQUALS("[test.cpp:4]: (performance, inconclusive) Technically the member function 'Altren::foo' can be static.\n"
"[test.cpp:5]: (style, inconclusive) Technically the member function 'Altren::bar' can be const.\n", errout.str());
}
void const48() { // ticket 2672
@ -4157,7 +4134,7 @@ private:
"private:\n"
" int bar;\n"
"};");
ASSERT_EQUALS("", errout.str());
ASSERT_EQUALS("[test.cpp:2]: (performance, inconclusive) Technically the member function 'foo::DoSomething' can be static.\n", errout.str());
}
void const53() { // ticket 3049
@ -4201,7 +4178,7 @@ private:
" switch (x) { }\n"
" }\n"
"};\n");
ASSERT_EQUALS("[test.cpp:3]: (style, inconclusive) Technically the member function 'MyObject::foo' can be const.\n", errout.str());
ASSERT_EQUALS("[test.cpp:3]: (performance, inconclusive) Technically the member function 'MyObject::foo' can be static.\n", errout.str());
checkConst("class A\n"
"{\n"
@ -4244,7 +4221,7 @@ private:
"\n"
" return RET_NOK;\n"
"}\n");
ASSERT_EQUALS("[test.cpp:9] -> [test.cpp:4]: (style, inconclusive) Technically the member function 'A::f' can be const.\n", errout.str());
ASSERT_EQUALS("[test.cpp:9] -> [test.cpp:4]: (performance, inconclusive) Technically the member function 'A::f' can be static.\n", errout.str());
checkConst("class MyObject {\n"
"public:\n"
@ -4252,7 +4229,7 @@ private:
" for (int i = 0; i < 5; i++) { }\n"
" }\n"
"};\n");
ASSERT_EQUALS("[test.cpp:3]: (style, inconclusive) Technically the member function 'MyObject::foo' can be const.\n", errout.str());
ASSERT_EQUALS("[test.cpp:3]: (performance, inconclusive) Technically the member function 'MyObject::foo' can be static.\n", errout.str());
}
void const57() { // tickets #2669 and #2477
@ -4277,7 +4254,8 @@ private:
"private:\n"
" MyGUI::IntCoord mCoordValue;\n"
"};\n");
ASSERT_EQUALS("[test.cpp:15]: (style, inconclusive) Technically the member function 'SelectorControl::getSize' can be const.\n", errout.str());
ASSERT_EQUALS("[test.cpp:7]: (performance, inconclusive) Technically the member function 'MyGUI::types::TCoord::size' can be static.\n"
"[test.cpp:15]: (style, inconclusive) Technically the member function 'SelectorControl::getSize' can be const.\n", errout.str());
checkConst("struct Foo {\n"
" Bar b;\n"
@ -4308,7 +4286,8 @@ private:
" b.run();\n"
" }\n"
"};");
ASSERT_EQUALS("[test.cpp:6]: (style, inconclusive) Technically the member function 'Foo::foo' can be const.\n", errout.str());
ASSERT_EQUALS("[test.cpp:2]: (performance, inconclusive) Technically the member function 'Bar::run' can be static.\n"
"[test.cpp:6]: (style, inconclusive) Technically the member function 'Foo::foo' can be const.\n", errout.str());
}
void const58() {
@ -4317,14 +4296,14 @@ private:
" f.clear();\n"
" }\n"
"};");
ASSERT_EQUALS("[test.cpp:2]: (style, inconclusive) Technically the member function 'MyObject::foo' can be const.\n", errout.str());
ASSERT_EQUALS("[test.cpp:2]: (performance, inconclusive) Technically the member function 'MyObject::foo' can be static.\n", errout.str());
checkConst("struct MyObject {\n"
" int foo(Foo f) {\n"
" return f.length();\n"
" }\n"
"};");
ASSERT_EQUALS("[test.cpp:2]: (style, inconclusive) Technically the member function 'MyObject::foo' can be const.\n", errout.str());
ASSERT_EQUALS("[test.cpp:2]: (performance, inconclusive) Technically the member function 'MyObject::foo' can be static.\n", errout.str());
checkConst("struct MyObject {\n"
" Foo f;\n"
@ -4373,8 +4352,8 @@ private:
" return foo3();\n"
" }\n"
"};");
ASSERT_EQUALS("[test.cpp:11]: (style, inconclusive) Technically the member function 'Foo::bar3' can be const.\n"
"[test.cpp:14]: (style, inconclusive) Technically the member function 'Foo::bar4' can be const.\n", errout.str());
ASSERT_EQUALS("[test.cpp:11]: (performance, inconclusive) Technically the member function 'Foo::bar3' can be static.\n"
"[test.cpp:14]: (performance, inconclusive) Technically the member function 'Foo::bar4' can be static.\n", errout.str());
}
void const_passThisToMemberOfOtherClass() {
@ -4392,7 +4371,7 @@ private:
" f.foo();\n"
" }\n"
"};");
ASSERT_EQUALS("[test.cpp:2]: (style, inconclusive) Technically the member function 'Foo::foo' can be const.\n", errout.str());
ASSERT_EQUALS("[test.cpp:2]: (performance, inconclusive) Technically the member function 'Foo::foo' can be static.\n", errout.str());
}
void assigningPointerToPointerIsNotAConstOperation() {
@ -4451,25 +4430,25 @@ private:
"class Fred {\n"
" void nextA() { return ++a; }\n"
"};\n");
ASSERT_EQUALS("[test.cpp:3]: (style, inconclusive) Technically the member function 'Fred::nextA' can be const.\n", errout.str());
ASSERT_EQUALS("[test.cpp:3]: (performance, inconclusive) Technically the member function 'Fred::nextA' can be static.\n", errout.str());
checkConst("int a;\n"
"class Fred {\n"
" void nextA() { return --a; }\n"
"};\n");
ASSERT_EQUALS("[test.cpp:3]: (style, inconclusive) Technically the member function 'Fred::nextA' can be const.\n", errout.str());
ASSERT_EQUALS("[test.cpp:3]: (performance, inconclusive) Technically the member function 'Fred::nextA' can be static.\n", errout.str());
checkConst("int a;\n"
"class Fred {\n"
" void nextA() { return a++; }\n"
"};\n");
ASSERT_EQUALS("[test.cpp:3]: (style, inconclusive) Technically the member function 'Fred::nextA' can be const.\n", errout.str());
ASSERT_EQUALS("[test.cpp:3]: (performance, inconclusive) Technically the member function 'Fred::nextA' can be static.\n", errout.str());
checkConst("int a;\n"
"class Fred {\n"
" void nextA() { return a--; }\n"
"};\n");
ASSERT_EQUALS("[test.cpp:3]: (style, inconclusive) Technically the member function 'Fred::nextA' can be const.\n", errout.str());
ASSERT_EQUALS("[test.cpp:3]: (performance, inconclusive) Technically the member function 'Fred::nextA' can be static.\n", errout.str());
}
void constassign1() {
@ -4507,31 +4486,31 @@ private:
"class Fred {\n"
" void nextA() { return a=1; }\n"
"};\n");
ASSERT_EQUALS("[test.cpp:3]: (style, inconclusive) Technically the member function 'Fred::nextA' can be const.\n", errout.str());
ASSERT_EQUALS("[test.cpp:3]: (performance, inconclusive) Technically the member function 'Fred::nextA' can be static.\n", errout.str());
checkConst("int a;\n"
"class Fred {\n"
" void nextA() { return a-=1; }\n"
"};\n");
ASSERT_EQUALS("[test.cpp:3]: (style, inconclusive) Technically the member function 'Fred::nextA' can be const.\n", errout.str());
ASSERT_EQUALS("[test.cpp:3]: (performance, inconclusive) Technically the member function 'Fred::nextA' can be static.\n", errout.str());
checkConst("int a;\n"
"class Fred {\n"
" void nextA() { return a+=1; }\n"
"};\n");
ASSERT_EQUALS("[test.cpp:3]: (style, inconclusive) Technically the member function 'Fred::nextA' can be const.\n", errout.str());
ASSERT_EQUALS("[test.cpp:3]: (performance, inconclusive) Technically the member function 'Fred::nextA' can be static.\n", errout.str());
checkConst("int a;\n"
"class Fred {\n"
" void nextA() { return a*=-1; }\n"
"};\n");
ASSERT_EQUALS("[test.cpp:3]: (style, inconclusive) Technically the member function 'Fred::nextA' can be const.\n", errout.str());
ASSERT_EQUALS("[test.cpp:3]: (performance, inconclusive) Technically the member function 'Fred::nextA' can be static.\n", errout.str());
checkConst("int a;\n"
"class Fred {\n"
" void nextA() { return a/=-2; }\n"
"};\n");
ASSERT_EQUALS("[test.cpp:3]: (style, inconclusive) Technically the member function 'Fred::nextA' can be const.\n", errout.str());
ASSERT_EQUALS("[test.cpp:3]: (performance, inconclusive) Technically the member function 'Fred::nextA' can be static.\n", errout.str());
}
void constassign2() {
@ -4563,31 +4542,31 @@ private:
"class Fred {\n"
" void nextA() { return s.a=1; }\n"
"};\n");
ASSERT_EQUALS("[test.cpp:3]: (style, inconclusive) Technically the member function 'Fred::nextA' can be const.\n", errout.str());
ASSERT_EQUALS("[test.cpp:3]: (performance, inconclusive) Technically the member function 'Fred::nextA' can be static.\n", errout.str());
checkConst("struct A { int a; } s;\n"
"class Fred {\n"
" void nextA() { return s.a-=1; }\n"
"};\n");
ASSERT_EQUALS("[test.cpp:3]: (style, inconclusive) Technically the member function 'Fred::nextA' can be const.\n", errout.str());
ASSERT_EQUALS("[test.cpp:3]: (performance, inconclusive) Technically the member function 'Fred::nextA' can be static.\n", errout.str());
checkConst("struct A { int a; } s;\n"
"class Fred {\n"
" void nextA() { return s.a+=1; }\n"
"};\n");
ASSERT_EQUALS("[test.cpp:3]: (style, inconclusive) Technically the member function 'Fred::nextA' can be const.\n", errout.str());
ASSERT_EQUALS("[test.cpp:3]: (performance, inconclusive) Technically the member function 'Fred::nextA' can be static.\n", errout.str());
checkConst("struct A { int a; } s;\n"
"class Fred {\n"
" void nextA() { return s.a*=-1; }\n"
"};\n");
ASSERT_EQUALS("[test.cpp:3]: (style, inconclusive) Technically the member function 'Fred::nextA' can be const.\n", errout.str());
ASSERT_EQUALS("[test.cpp:3]: (performance, inconclusive) Technically the member function 'Fred::nextA' can be static.\n", errout.str());
checkConst("struct A { int a; } s;\n"
"class Fred {\n"
" void nextA() { return s.a/=-2; }\n"
"};\n");
ASSERT_EQUALS("[test.cpp:3]: (style, inconclusive) Technically the member function 'Fred::nextA' can be const.\n", errout.str());
ASSERT_EQUALS("[test.cpp:3]: (performance, inconclusive) Technically the member function 'Fred::nextA' can be static.\n", errout.str());
checkConst("struct A { int a; };\n"
"class Fred {\n"
@ -4655,25 +4634,25 @@ private:
"class Fred {\n"
" void nextA() { return ++a[0]; }\n"
"};\n");
ASSERT_EQUALS("[test.cpp:3]: (style, inconclusive) Technically the member function 'Fred::nextA' can be const.\n", errout.str());
ASSERT_EQUALS("[test.cpp:3]: (performance, inconclusive) Technically the member function 'Fred::nextA' can be static.\n", errout.str());
checkConst("int a[2];\n"
"class Fred {\n"
" void nextA() { return --a[0]; }\n"
"};\n");
ASSERT_EQUALS("[test.cpp:3]: (style, inconclusive) Technically the member function 'Fred::nextA' can be const.\n", errout.str());
ASSERT_EQUALS("[test.cpp:3]: (performance, inconclusive) Technically the member function 'Fred::nextA' can be static.\n", errout.str());
checkConst("int a[2];\n"
"class Fred {\n"
" void nextA() { return a[0]++; }\n"
"};\n");
ASSERT_EQUALS("[test.cpp:3]: (style, inconclusive) Technically the member function 'Fred::nextA' can be const.\n", errout.str());
ASSERT_EQUALS("[test.cpp:3]: (performance, inconclusive) Technically the member function 'Fred::nextA' can be static.\n", errout.str());
checkConst("int a[2];\n"
"class Fred {\n"
" void nextA() { return a[0]--; }\n"
"};\n");
ASSERT_EQUALS("[test.cpp:3]: (style, inconclusive) Technically the member function 'Fred::nextA' can be const.\n", errout.str());
ASSERT_EQUALS("[test.cpp:3]: (performance, inconclusive) Technically the member function 'Fred::nextA' can be static.\n", errout.str());
}
void constassignarray() {
@ -4711,31 +4690,31 @@ private:
"class Fred {\n"
" void nextA() { return a[0]=1; }\n"
"};\n");
ASSERT_EQUALS("[test.cpp:3]: (style, inconclusive) Technically the member function 'Fred::nextA' can be const.\n", errout.str());
ASSERT_EQUALS("[test.cpp:3]: (performance, inconclusive) Technically the member function 'Fred::nextA' can be static.\n", errout.str());
checkConst("int a[2];\n"
"class Fred {\n"
" void nextA() { return a[0]-=1; }\n"
"};\n");
ASSERT_EQUALS("[test.cpp:3]: (style, inconclusive) Technically the member function 'Fred::nextA' can be const.\n", errout.str());
ASSERT_EQUALS("[test.cpp:3]: (performance, inconclusive) Technically the member function 'Fred::nextA' can be static.\n", errout.str());
checkConst("int a[2];\n"
"class Fred {\n"
" void nextA() { return a[0]+=1; }\n"
"};\n");
ASSERT_EQUALS("[test.cpp:3]: (style, inconclusive) Technically the member function 'Fred::nextA' can be const.\n", errout.str());
ASSERT_EQUALS("[test.cpp:3]: (performance, inconclusive) Technically the member function 'Fred::nextA' can be static.\n", errout.str());
checkConst("int a[2];\n"
"class Fred {\n"
" void nextA() { return a[0]*=-1; }\n"
"};\n");
ASSERT_EQUALS("[test.cpp:3]: (style, inconclusive) Technically the member function 'Fred::nextA' can be const.\n", errout.str());
ASSERT_EQUALS("[test.cpp:3]: (performance, inconclusive) Technically the member function 'Fred::nextA' can be static.\n", errout.str());
checkConst("int a[2];\n"
"class Fred {\n"
" void nextA() { return a[0]/=-2; }\n"
"};\n");
ASSERT_EQUALS("[test.cpp:3]: (style, inconclusive) Technically the member function 'Fred::nextA' can be const.\n", errout.str());
ASSERT_EQUALS("[test.cpp:3]: (performance, inconclusive) Technically the member function 'Fred::nextA' can be static.\n", errout.str());
}
// return pointer/reference => not const
@ -4777,7 +4756,8 @@ private:
" void f() const { };\n"
" void a() { f(); };\n"
"};\n");
ASSERT_EQUALS("[test.cpp:3]: (style, inconclusive) Technically the member function 'Fred::a' can be const.\n", errout.str());
ASSERT_EQUALS("[test.cpp:2]: (performance, inconclusive) Technically the member function 'Fred::f' can be static.\n"
"[test.cpp:3]: (style, inconclusive) Technically the member function 'Fred::a' can be const.\n", errout.str());
// ticket #1593
checkConst("class A\n"
@ -5040,7 +5020,7 @@ private:
settings.addEnabled("style");
checkConst(code, &settings, true);
ASSERT_EQUALS("[test.cpp:3]: (style, inconclusive) Technically the member function 'foo::f' can be const.\n", errout.str());
ASSERT_EQUALS("[test.cpp:3]: (performance, inconclusive) Technically the member function 'foo::f' can be static.\n", errout.str());
checkConst(code, &settings, false); // TODO: Set inconclusive to true (preprocess it)
ASSERT_EQUALS("", errout.str());