forked from danmar/cppcheck
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcheckclass.h
249 lines (205 loc) · 10.4 KB
/
checkclass.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
/*
* Cppcheck - A tool for static C/C++ code analysis
* Copyright (C) 2007-2012 Daniel Marjamäki and Cppcheck team.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
//---------------------------------------------------------------------------
#ifndef CheckClassH
#define CheckClassH
//---------------------------------------------------------------------------
#include "config.h"
#include "check.h"
class Token;
class Scope;
class Function;
/// @addtogroup Checks
/// @{
/** @brief %Check classes. Uninitialized member variables, non-conforming operators, missing virtual destructor, etc */
class CPPCHECKLIB CheckClass : public Check {
public:
/** @brief This constructor is used when registering the CheckClass */
CheckClass() : Check(myName()), symbolDatabase(NULL)
{ }
/** @brief This constructor is used when running checks. */
CheckClass(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger);
/** @brief Run checks on the normal token list */
void runChecks(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) {
CheckClass checkClass(tokenizer, settings, errorLogger);
// can't be a simplified check .. the 'sizeof' is used.
checkClass.noMemset();
}
/** @brief Run checks on the simplified token list */
void runSimplifiedChecks(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) {
CheckClass checkClass(tokenizer, settings, errorLogger);
// Coding style checks
checkClass.constructors();
checkClass.operatorEq();
checkClass.privateFunctions();
checkClass.operatorEqRetRefThis();
checkClass.thisSubtraction();
checkClass.operatorEqToSelf();
checkClass.initializerListOrder();
checkClass.initializationListUsage();
checkClass.virtualDestructor();
checkClass.checkConst();
checkClass.copyconstructors();
}
/** @brief %Check that all class constructors are ok */
void constructors();
/** @brief %Check that all private functions are called */
void privateFunctions();
/**
* @brief %Check that the memsets are valid.
* The 'memset' function can do dangerous things if used wrong. If it
* is used on STL containers for instance it will clear all its data
* and then the STL container may leak memory or worse have an invalid state.
* It can also overwrite the virtual table.
* Important: The checking doesn't work on simplified tokens list.
*/
void noMemset();
void checkMemsetType(const Scope *start, const Token *tok, const Scope *type);
/** @brief 'operator=' should return something and it should not be const. */
void operatorEq();
/** @brief 'operator=' should return reference to *this */
void operatorEqRetRefThis(); // Warning upon no "return *this;"
/** @brief 'operator=' should check for assignment to self */
void operatorEqToSelf(); // Warning upon no check for assignment to self
/** @brief The destructor in a base class should be virtual */
void virtualDestructor();
/** @brief warn for "this-x". The indented code may be "this->x" */
void thisSubtraction();
/** @brief can member function be const? */
void checkConst();
/** @brief Check initializer list order */
void initializerListOrder();
void initializationListUsage();
void copyconstructors();
private:
const SymbolDatabase *symbolDatabase;
// Reporting errors..
void noConstructorError(const Token *tok, const std::string &classname, bool isStruct);
void copyConstructorMallocError(const Token *tok, const std::string &classname, bool isStruct, const std::vector<std::string>& var_name);
void copyConstructorShallowCopyError(const Token *tok, const std::string &classname, bool isStruct);
void noCopyConstructorError(const Token *tok, const std::string &classname, bool isStruct);
void uninitVarError(const Token *tok, const std::string &classname, const std::string &varname);
void operatorEqVarError(const Token *tok, const std::string &classname, const std::string &varname);
void unusedPrivateFunctionError(const Token *tok, const std::string &classname, const std::string &funcname);
void memsetError(const Token *tok, const std::string &memfunc, const std::string &classname, const std::string &type);
void operatorEqReturnError(const Token *tok, const std::string &className);
void virtualDestructorError(const Token *tok, const std::string &Base, const std::string &Derived);
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, 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);
void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const {
CheckClass c(0, settings, errorLogger);
c.noConstructorError(0, "classname", false);
std::vector<std::string> temp;
c.copyConstructorMallocError(0, "class", false, temp);
c.copyConstructorShallowCopyError(0, "class", false);
c.noCopyConstructorError(0, "class", false);
c.uninitVarError(0, "classname", "varname");
c.operatorEqVarError(0, "classname", "");
c.unusedPrivateFunctionError(0, "classname", "funcname");
c.memsetError(0, "memfunc", "classname", "class");
c.operatorEqReturnError(0, "class");
c.virtualDestructorError(0, "Base", "Derived");
c.thisSubtractionError(0);
c.operatorEqRetRefThisError(0);
c.operatorEqToSelfError(0);
c.checkConstError(0, "class", "function", false);
c.checkConstError(0, "class", "function", true);
c.initializerListError(0, 0, "class", "variable");
c.suggestInitializationList(0, "variable");
}
static std::string myName() {
return "Class";
}
std::string classInfo() const {
return "Check the code for each class.\n"
"* Missing constructors and copy constructors\n"
"* Missing allocation of memory in copy constructor\n"
"* Are all variables initialized by the constructors?\n"
"* Are all variables assigned by 'operator='?\n"
"* Warn if memset, memcpy etc are used on a class\n"
"* If it's a base class, check that the destructor is virtual\n"
"* Are there unused private functions?\n"
"* 'operator=' should return reference to self\n"
"* 'operator=' should check for assignment to self\n"
"* Constness for member functions\n"
"* Order of initializations\n"
"* Suggest usage of initialization list\n"
"* Suspicious subtraction from 'this'\n";
}
// operatorEqRetRefThis helper function
void checkReturnPtrThis(const Scope *scope, const Function *func, const Token *tok, const Token *last);
// operatorEqToSelf helper functions
bool hasAllocation(const Function *func, const Scope* scope);
static bool hasAssignSelf(const Function *func, const Token *rhs);
// checkConst helper functions
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& memberAccessed);
// constructors helper function
/** @brief Information about a member variable. Used when checking for uninitialized variables */
struct Usage {
Usage() : assign(false), init(false) { }
/** @brief has this variable been assigned? */
bool assign;
/** @brief has this variable been initialized? */
bool init;
};
static bool isBaseClassFunc(const Token *tok, const Scope *scope);
/**
* @brief assign a variable in the varlist
* @param varname name of variable to mark assigned
* @param scope pointer to variable Scope
* @param usage reference to usage vector
*/
static void assignVar(const std::string &varname, const Scope *scope, std::vector<Usage> &usage);
/**
* @brief initialize a variable in the varlist
* @param varname name of variable to mark initialized
* @param scope pointer to variable Scope
* @param usage reference to usage vector
*/
static void initVar(const std::string &varname, const Scope *scope, std::vector<Usage> &usage);
/**
* @brief set all variables in list assigned
* @param usage reference to usage vector
*/
static void assignAllVar(std::vector<Usage> &usage);
/**
* @brief set all variables in list not assigned and not initialized
* @param usage reference to usage vector
*/
static void clearAllVar(std::vector<Usage> &usage);
/**
* @brief parse a scope for a constructor or member function and set the "init" flags in the provided varlist
* @param func reference to the function that should be checked
* @param callstack the function doesn't look into recursive function calls.
* @param scope pointer to variable Scope
* @param usage reference to usage vector
*/
void initializeVarList(const Function &func, std::list<std::string> &callstack, const Scope *scope, std::vector<Usage> &usage);
static bool canNotCopy(const Scope *scope);
};
/// @}
//---------------------------------------------------------------------------
#endif