Create a symbol database
This commit is contained in:
parent
bb7484945a
commit
0bb07e6947
1237
lib/checkclass.cpp
1237
lib/checkclass.cpp
File diff suppressed because it is too large
Load Diff
|
@ -23,6 +23,7 @@
|
||||||
|
|
||||||
#include "check.h"
|
#include "check.h"
|
||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
|
#include <map>
|
||||||
|
|
||||||
class Token;
|
class Token;
|
||||||
|
|
||||||
|
@ -39,9 +40,9 @@ public:
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
/** @brief This constructor is used when running checks. */
|
/** @brief This constructor is used when running checks. */
|
||||||
CheckClass(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger)
|
CheckClass(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger);
|
||||||
: Check(tokenizer, settings, errorLogger)
|
|
||||||
{ }
|
~CheckClass();
|
||||||
|
|
||||||
/** @brief Run checks on the normal token list */
|
/** @brief Run checks on the normal token list */
|
||||||
void runChecks(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger)
|
void runChecks(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger)
|
||||||
|
@ -145,6 +146,58 @@ private:
|
||||||
Var& operator=(const Var&); // disallow assignments
|
Var& operator=(const Var&); // disallow assignments
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum AccessControl { Public, Protected, Private };
|
||||||
|
|
||||||
|
struct Func
|
||||||
|
{
|
||||||
|
enum Type { Constructor, CopyConstructor, OperatorEqual, Destructor, Function };
|
||||||
|
|
||||||
|
Func()
|
||||||
|
: tokenDef(NULL),
|
||||||
|
token(NULL),
|
||||||
|
access(Public),
|
||||||
|
hasBody(false),
|
||||||
|
isInline(false),
|
||||||
|
isConst(false),
|
||||||
|
isVirtual(false),
|
||||||
|
isStatic(false),
|
||||||
|
isOperator(false),
|
||||||
|
type(Function)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
const Token *tokenDef; // function name token in class definition
|
||||||
|
const Token *token; // function name token in implementation
|
||||||
|
AccessControl access; // public/protected/private
|
||||||
|
bool hasBody; // has implementation
|
||||||
|
bool isInline; // implementation in class definition
|
||||||
|
bool isConst; // is const
|
||||||
|
bool isVirtual; // is virtual
|
||||||
|
bool isStatic; // is static
|
||||||
|
bool isOperator; // is operator
|
||||||
|
Type type; // constructor, destructor, ...
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SpaceInfo
|
||||||
|
{
|
||||||
|
bool isNamespace;
|
||||||
|
std::string className;
|
||||||
|
const Token *classDef; // class/struct/namespace token
|
||||||
|
const Token *classStart; // '{' token
|
||||||
|
const Token *classEnd; // '}' token
|
||||||
|
unsigned int numConstructors;
|
||||||
|
std::list<Func> functionList;
|
||||||
|
Var *varlist;
|
||||||
|
std::vector<std::string> derivedFrom;
|
||||||
|
SpaceInfo *nest;
|
||||||
|
AccessControl access;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** @brief Information about all namespaces/classes/structrues */
|
||||||
|
std::multimap<std::string, SpaceInfo *> spaceInfoMMap;
|
||||||
|
|
||||||
|
bool argsMatch(const Token *first, const Token *second, const std::string &path, unsigned int depth) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief parse a scope for a constructor or member function and set the "init" flags in the provided varlist
|
* @brief parse a scope for a constructor or member function and set the "init" flags in the provided varlist
|
||||||
* @param tok1 pointer to class declaration
|
* @param tok1 pointer to class declaration
|
||||||
|
@ -163,21 +216,12 @@ private:
|
||||||
*/
|
*/
|
||||||
Var *getVarList(const Token *tok1);
|
Var *getVarList(const Token *tok1);
|
||||||
|
|
||||||
bool sameFunc(int nest, const Token *firstEnd, const Token *secondEnd);
|
|
||||||
bool isMemberFunc(const Token *tok);
|
|
||||||
bool isMemberVar(const std::string &classname, const std::vector<std::string> &derivedFrom, const Var *varlist, const Token *tok);
|
bool isMemberVar(const std::string &classname, const std::vector<std::string> &derivedFrom, const Var *varlist, const Token *tok);
|
||||||
bool checkConstFunc(const std::string &classname, const std::vector<std::string> &derivedFrom, const Var *varlist, const Token *tok);
|
bool checkConstFunc(const std::string &classname, const std::vector<std::string> &derivedFrom, const Var *varlist, const Token *tok);
|
||||||
|
|
||||||
/** @brief check if this function is virtual in the base classes */
|
/** @brief check if this function is virtual in the base classes */
|
||||||
bool isVirtual(const std::vector<std::string> &derivedFrom, const Token *functionToken) const;
|
bool isVirtual(const std::vector<std::string> &derivedFrom, const Token *functionToken) const;
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Helper function for operatorEqRetRefThis that checks if there are errors
|
|
||||||
* @param tok The "operator" token in a operator=(.. function
|
|
||||||
* @param classname Name of class
|
|
||||||
*/
|
|
||||||
void operatorEqRetRefThis_finderr(const Token *tok, const std::string &classname);
|
|
||||||
|
|
||||||
// Reporting errors..
|
// Reporting errors..
|
||||||
void noConstructorError(const Token *tok, const std::string &classname, bool isStruct);
|
void noConstructorError(const Token *tok, const std::string &classname, bool isStruct);
|
||||||
void uninitVarError(const Token *tok, const std::string &classname, const std::string &varname);
|
void uninitVarError(const Token *tok, const std::string &classname, const std::string &varname);
|
||||||
|
|
|
@ -603,6 +603,16 @@ const Token *Token::findmatch(const Token *tok, const char pattern[], unsigned i
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const Token *Token::findmatch(const Token *tok, const char pattern[], const Token *end, unsigned int varId)
|
||||||
|
{
|
||||||
|
for (; tok && tok != end; tok = tok->next())
|
||||||
|
{
|
||||||
|
if (Token::Match(tok, pattern, varId))
|
||||||
|
return tok;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void Token::insertToken(const std::string &tokenStr)
|
void Token::insertToken(const std::string &tokenStr)
|
||||||
{
|
{
|
||||||
Token *newToken = new Token(tokensBack);
|
Token *newToken = new Token(tokensBack);
|
||||||
|
|
|
@ -184,6 +184,7 @@ public:
|
||||||
bool isIntegerType() const;
|
bool isIntegerType() const;
|
||||||
|
|
||||||
static const Token *findmatch(const Token *tok, const char pattern[], unsigned int varId = 0);
|
static const Token *findmatch(const Token *tok, const char pattern[], unsigned int varId = 0);
|
||||||
|
static const Token *findmatch(const Token *tok, const char pattern[], const Token *end, unsigned int varId = 0);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Needle is build from multiple alternatives. If one of
|
* Needle is build from multiple alternatives. If one of
|
||||||
|
|
|
@ -98,6 +98,7 @@ private:
|
||||||
TEST_CASE(operatorEqToSelf5); // ticket # 1233
|
TEST_CASE(operatorEqToSelf5); // ticket # 1233
|
||||||
TEST_CASE(operatorEqToSelf6); // ticket # 1550
|
TEST_CASE(operatorEqToSelf6); // ticket # 1550
|
||||||
TEST_CASE(memsetOnStruct);
|
TEST_CASE(memsetOnStruct);
|
||||||
|
TEST_CASE(memsetVector);
|
||||||
TEST_CASE(memsetOnClass);
|
TEST_CASE(memsetOnClass);
|
||||||
|
|
||||||
TEST_CASE(this_subtraction); // warn about "this-x"
|
TEST_CASE(this_subtraction); // warn about "this-x"
|
||||||
|
@ -271,7 +272,7 @@ private:
|
||||||
"class A\n"
|
"class A\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
"public:\n"
|
"public:\n"
|
||||||
" A & operator=(const A &)\n"
|
" A & operator=(const A &);\n"
|
||||||
"};\n"
|
"};\n"
|
||||||
"A & A::operator=(const A &a) { return a; }\n");
|
"A & A::operator=(const A &a) { return a; }\n");
|
||||||
ASSERT_EQUALS("[test.cpp:6]: (style) 'operator=' should return reference to self\n", errout.str());
|
ASSERT_EQUALS("[test.cpp:6]: (style) 'operator=' should return reference to self\n", errout.str());
|
||||||
|
@ -280,7 +281,7 @@ private:
|
||||||
"class A\n"
|
"class A\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
"public:\n"
|
"public:\n"
|
||||||
" A & operator=(const A &a)\n"
|
" A & operator=(const A &a);\n"
|
||||||
"};\n"
|
"};\n"
|
||||||
"A & A::operator=(const A &a) { return a; }\n");
|
"A & A::operator=(const A &a) { return a; }\n");
|
||||||
ASSERT_EQUALS("[test.cpp:6]: (style) 'operator=' should return reference to self\n", errout.str());
|
ASSERT_EQUALS("[test.cpp:6]: (style) 'operator=' should return reference to self\n", errout.str());
|
||||||
|
@ -351,7 +352,7 @@ private:
|
||||||
"{\n"
|
"{\n"
|
||||||
" szp &operator =(int *other);\n"
|
" szp &operator =(int *other);\n"
|
||||||
"};\n"
|
"};\n"
|
||||||
"szp &szp::operator =(int *other) {};");
|
"szp &szp::operator =(int *other) {}");
|
||||||
ASSERT_EQUALS("[test.cpp:5]: (style) 'operator=' should return reference to self\n", errout.str());
|
ASSERT_EQUALS("[test.cpp:5]: (style) 'operator=' should return reference to self\n", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2557,7 +2558,7 @@ private:
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
// functions with a function call can't be const..
|
// functions with a function call can't be const..
|
||||||
checkConst("class foo\n"
|
checkConst("class Fred\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
"public:\n"
|
"public:\n"
|
||||||
" int x;\n"
|
" int x;\n"
|
||||||
|
@ -2567,7 +2568,7 @@ private:
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
// static functions can't be const..
|
// static functions can't be const..
|
||||||
checkConst("class foo\n"
|
checkConst("class Fred\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
"public:\n"
|
"public:\n"
|
||||||
" static unsigned get();\n"
|
" static unsigned get();\n"
|
||||||
|
@ -2578,7 +2579,7 @@ private:
|
||||||
// assignment to variable can't be const
|
// assignment to variable can't be const
|
||||||
checkConst("class Fred {\n"
|
checkConst("class Fred {\n"
|
||||||
" std::string s;\n"
|
" std::string s;\n"
|
||||||
" void foo()\n"
|
" void foo();\n"
|
||||||
"};\n"
|
"};\n"
|
||||||
"void Fred::foo() { s = ""; }");
|
"void Fred::foo() { s = ""; }");
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
@ -2628,7 +2629,7 @@ private:
|
||||||
" std::string s;\n"
|
" std::string s;\n"
|
||||||
" void foo(std::string & a, std::string & b);\n"
|
" void foo(std::string & a, std::string & b);\n"
|
||||||
"};\n"
|
"};\n"
|
||||||
"void foo(std::string & a, std::string & b) { a = s; s = b; }");
|
"void Fred::foo(std::string & a, std::string & b) { a = s; s = b; }");
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
// assignment to function argument pointer can be const
|
// assignment to function argument pointer can be const
|
||||||
|
@ -2750,8 +2751,8 @@ private:
|
||||||
" };\n"
|
" };\n"
|
||||||
" };\n"
|
" };\n"
|
||||||
"};");
|
"};");
|
||||||
ASSERT_EQUALS("[test.cpp:4]: (style) The function 'Fred::B::getB' can be const\n"
|
ASSERT_EQUALS("[test.cpp:7]: (style) The function 'Fred::B::A::getA' can be const\n"
|
||||||
"[test.cpp:7]: (style) The function 'Fred::B::A::getA' can be const\n", errout.str());
|
"[test.cpp:4]: (style) The function 'Fred::B::getB' can be const\n", errout.str());
|
||||||
|
|
||||||
checkConst("class Fred {\n"
|
checkConst("class Fred {\n"
|
||||||
" class B {\n"
|
" class B {\n"
|
||||||
|
@ -2765,8 +2766,8 @@ private:
|
||||||
" };\n"
|
" };\n"
|
||||||
" int B::getB() { return b; }\n"
|
" int B::getB() { return b; }\n"
|
||||||
"};");
|
"};");
|
||||||
ASSERT_EQUALS("[test.cpp:11] -> [test.cpp:4]: (style) The function 'Fred::B::getB' can be const\n"
|
ASSERT_EQUALS("[test.cpp:9] -> [test.cpp:7]: (style) The function 'Fred::B::A::getA' can be const\n"
|
||||||
"[test.cpp:9] -> [test.cpp:7]: (style) The function 'Fred::B::A::getA' can be const\n", errout.str());
|
"[test.cpp:11] -> [test.cpp:4]: (style) The function 'Fred::B::getB' can be const\n", errout.str());
|
||||||
|
|
||||||
checkConst("class Fred {\n"
|
checkConst("class Fred {\n"
|
||||||
" class B {\n"
|
" class B {\n"
|
||||||
|
@ -2780,8 +2781,8 @@ private:
|
||||||
"};\n"
|
"};\n"
|
||||||
"int Fred::B::A::getA() { return a; }\n"
|
"int Fred::B::A::getA() { return a; }\n"
|
||||||
"int Fred::B::getB() { return b; }\n");
|
"int Fred::B::getB() { return b; }\n");
|
||||||
ASSERT_EQUALS("[test.cpp:12] -> [test.cpp:4]: (style) The function 'Fred::B::getB' can be const\n"
|
ASSERT_EQUALS("[test.cpp:11] -> [test.cpp:7]: (style) The function 'Fred::B::A::getA' can be const\n"
|
||||||
"[test.cpp:11] -> [test.cpp:7]: (style) The function 'Fred::B::A::getA' can be const\n", errout.str());
|
"[test.cpp:12] -> [test.cpp:4]: (style) The function 'Fred::B::getB' can be const\n", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
// operator< can often be const
|
// operator< can often be const
|
||||||
|
|
|
@ -771,7 +771,7 @@ private:
|
||||||
" C();\n"
|
" C();\n"
|
||||||
" struct D {\n"
|
" struct D {\n"
|
||||||
" struct E { };\n"
|
" struct E { };\n"
|
||||||
" E d;\n"
|
" struct E d;\n"
|
||||||
" D(const E &);\n"
|
" D(const E &);\n"
|
||||||
" };\n"
|
" };\n"
|
||||||
" int c;\n"
|
" int c;\n"
|
||||||
|
|
Loading…
Reference in New Issue