Skip to content

Commit a2f28ac

Browse files
committed
checkimpl incomplete
1 parent 04235e2 commit a2f28ac

2 files changed

Lines changed: 193 additions & 189 deletions

File tree

lib/checkclass.cpp

Lines changed: 190 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "checkclass.h"
2121

2222
#include "astutils.h"
23+
#include "checkimpl.h"
2324
#include "library.h"
2425
#include "settings.h"
2526
#include "standards.h"
@@ -60,6 +61,122 @@ static const CWE CWE762(762U); // Mismatched Memory Management Routines
6061

6162
static const CWE CWE_ONE_DEFINITION_RULE(758U);
6263

64+
class CheckClassImpl : public CheckImpl
65+
{
66+
public:
67+
/** @brief This constructor is used when running checks. */
68+
CheckClassImpl(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger);
69+
70+
71+
/** @brief %Check that all class constructors are ok */
72+
void constructors();
73+
74+
/** @brief %Check that constructors with single parameter are explicit,
75+
* if they has to be.*/
76+
void checkExplicitConstructors();
77+
78+
/** @brief %Check that all private functions are called */
79+
void privateFunctions();
80+
81+
/**
82+
* @brief %Check that the memsets are valid.
83+
* The 'memset' function can do dangerous things if used wrong. If it
84+
* is used on STL containers for instance it will clear all its data
85+
* and then the STL container may leak memory or worse have an invalid state.
86+
* It can also overwrite the virtual table.
87+
* Important: The checking doesn't work on simplified tokens list.
88+
*/
89+
void checkMemset();
90+
void checkMemsetType(const Scope *start, const Token *tok, const Scope *type, bool allocation, std::set<const Scope *> parsedTypes);
91+
92+
/** @brief 'operator=' should return reference to *this */
93+
void operatorEqRetRefThis(); // Warning upon no "return *this;"
94+
95+
/** @brief 'operator=' should check for assignment to self */
96+
void operatorEqToSelf(); // Warning upon no check for assignment to self
97+
98+
/** @brief The destructor in a base class should be virtual */
99+
void virtualDestructor();
100+
101+
/** @brief warn for "this-x". The indented code may be "this->x" */
102+
void thisSubtraction();
103+
104+
/** @brief can member function be const? */
105+
void checkConst();
106+
107+
/** @brief Check initializer list order */
108+
void initializerListOrder();
109+
110+
/** @brief Suggest using initialization list */
111+
void initializationListUsage();
112+
113+
/** @brief Check for initialization of a member with itself */
114+
void checkSelfInitialization();
115+
116+
void copyconstructors();
117+
118+
/** @brief call of virtual function in constructor/destructor */
119+
void checkVirtualFunctionCallInConstructor();
120+
121+
/** @brief Check duplicated inherited members */
122+
void checkDuplInheritedMembers();
123+
124+
/** @brief Check that copy constructor and operator defined together */
125+
void checkCopyCtorAndEqOperator();
126+
127+
/** @brief Check that the override keyword is used when overriding virtual functions */
128+
void checkOverride();
129+
130+
/** @brief Check that the overriden function is not identical to the base function */
131+
void checkUselessOverride();
132+
133+
/** @brief When "self pointer" is destroyed, 'this' might become invalid. */
134+
void checkThisUseAfterFree();
135+
136+
/** @brief Unsafe class check - const reference member */
137+
void checkUnsafeClassRefMember();
138+
139+
void noConstructorError(const Token *tok, const std::string &classname, bool isStruct);
140+
void noExplicitConstructorError(const Token *tok, const std::string &classname, bool isStruct);
141+
//void copyConstructorMallocError(const Token *cctor, const Token *alloc, const std::string& var_name);
142+
void copyConstructorShallowCopyError(const Token *tok, const std::string& varname);
143+
void noCopyConstructorError(const Scope *scope, bool isdefault, const Token *alloc, bool inconclusive);
144+
void noOperatorEqError(const Scope *scope, bool isdefault, const Token *alloc, bool inconclusive);
145+
void noDestructorError(const Scope *scope, bool isdefault, const Token *alloc);
146+
void uninitVarError(const Token *tok, bool isprivate, Function::Type functionType, const std::string &classname, const std::string &varname, bool derived, bool inconclusive);
147+
void uninitVarError(const Token *tok, const std::string &classname, const std::string &varname);
148+
void missingMemberCopyError(const Token *tok, Function::Type functionType, const std::string& classname, const std::string& varname);
149+
void operatorEqVarError(const Token *tok, const std::string &classname, const std::string &varname, bool inconclusive);
150+
void unusedPrivateFunctionError(const Token *tok, const std::string &classname, const std::string &funcname);
151+
void memsetError(const Token *tok, const std::string &memfunc, const std::string &classname, const std::string &type, bool isContainer = false);
152+
void memsetErrorReference(const Token *tok, const std::string &memfunc, const std::string &type);
153+
void memsetErrorFloat(const Token *tok, const std::string &type);
154+
void mallocOnClassError(const Token* tok, const std::string &memfunc, const Token* classTok, const std::string &classname);
155+
void mallocOnClassWarning(const Token* tok, const std::string &memfunc, const Token* classTok);
156+
void virtualDestructorError(const Token *tok, const std::string &Base, const std::string &Derived, bool inconclusive);
157+
void thisSubtractionError(const Token *tok);
158+
void operatorEqRetRefThisError(const Token *tok);
159+
void operatorEqShouldBeLeftUnimplementedError(const Token *tok);
160+
void operatorEqMissingReturnStatementError(const Token *tok, bool error);
161+
void operatorEqToSelfError(const Token *tok);
162+
void checkConstError(const Token *tok, const std::string &classname, const std::string &funcname, bool suggestStatic);
163+
void checkConstError2(const Token *tok1, const Token *tok2, const std::string &classname, const std::string &funcname, bool suggestStatic);
164+
void initializerListError(const Token *tok1,const Token *tok2, const std::string & classname, const std::string &varname);
165+
void suggestInitializationList(const Token *tok, const std::string& varname);
166+
void selfInitializationError(const Token* tok, const std::string& varname);
167+
void pureVirtualFunctionCallInConstructorError(const Function * scopeFunction, const std::list<const Token *> & tokStack, const std::string &purefuncname);
168+
void virtualFunctionCallInConstructorError(const Function * scopeFunction, const std::list<const Token *> & tokStack, const std::string &funcname);
169+
void duplInheritedMembersError(const Token* tok1, const Token* tok2, const std::string &derivedName, const std::string &baseName, const std::string &memberName, bool derivedIsStruct, bool baseIsStruct, bool isFunction = false);
170+
void copyCtorAndEqOperatorError(const Token *tok, const std::string &classname, bool isStruct, bool hasCopyCtor);
171+
void overrideError(const Function *funcInBase, const Function *funcInDerived);
172+
void uselessOverrideError(const Function *funcInBase, const Function *funcInDerived, bool isSameCode = false);
173+
void thisUseAfterFree(const Token *self, const Token *free, const Token *use);
174+
void unsafeClassRefMemberError(const Token *tok, const std::string &varname);
175+
void checkDuplInheritedMembersRecursive(const Type* typeCurrent, const Type* typeBase);
176+
177+
const SymbolDatabase* mSymbolDatabase{};
178+
};
179+
63180
static const char * getFunctionTypeName(Function::Type type)
64181
{
65182
switch (type) {
@@ -115,16 +232,16 @@ static bool isVclTypeInit(const Type *type)
115232
}
116233
//---------------------------------------------------------------------------
117234

118-
CheckClass::CheckClass(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger)
119-
: Check(myName(), tokenizer, settings, errorLogger),
235+
CheckClassImpl::CheckClassImpl(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger)
236+
: CheckImpl(tokenizer, settings, errorLogger),
120237
mSymbolDatabase(tokenizer?tokenizer->getSymbolDatabase():nullptr)
121238
{}
122239

123240
//---------------------------------------------------------------------------
124241
// ClassCheck: Check that all class constructors are ok.
125242
//---------------------------------------------------------------------------
126243

127-
void CheckClass::constructors()
244+
void CheckClassImpl::constructors()
128245
{
129246
const bool printStyle = mSettings->severity.isEnabled(Severity::style);
130247
const bool printWarnings = mSettings->severity.isEnabled(Severity::warning);
@@ -3503,4 +3620,74 @@ bool CheckClass::analyseWholeProgram(const CTU::FileInfo *ctu, const std::list<C
35033620
return foundErrors;
35043621
}
35053622

3623+
void CheckClass::runChecks(const Tokenizer &tokenizer, ErrorLogger *errorLogger)
3624+
{
3625+
if (tokenizer.isC())
3626+
return;
35063627

3628+
CheckClassImpl checkClass(&tokenizer, tokenizer.getSettings(), errorLogger);
3629+
3630+
// can't be a simplified check .. the 'sizeof' is used.
3631+
checkClass.checkMemset();
3632+
checkClass.constructors();
3633+
checkClass.privateFunctions();
3634+
checkClass.operatorEqRetRefThis();
3635+
checkClass.thisSubtraction();
3636+
checkClass.operatorEqToSelf();
3637+
checkClass.initializerListOrder();
3638+
checkClass.initializationListUsage();
3639+
checkClass.checkSelfInitialization();
3640+
checkClass.virtualDestructor();
3641+
checkClass.checkConst();
3642+
checkClass.copyconstructors();
3643+
checkClass.checkVirtualFunctionCallInConstructor();
3644+
checkClass.checkDuplInheritedMembers();
3645+
checkClass.checkExplicitConstructors();
3646+
checkClass.checkCopyCtorAndEqOperator();
3647+
checkClass.checkOverride();
3648+
checkClass.checkUselessOverride();
3649+
checkClass.checkThisUseAfterFree();
3650+
checkClass.checkUnsafeClassRefMember();
3651+
}
3652+
3653+
void CheckClass::getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const
3654+
{
3655+
CheckClassImpl c(nullptr, settings, errorLogger);
3656+
c.noConstructorError(nullptr, "classname", false);
3657+
c.noExplicitConstructorError(nullptr, "classname", false);
3658+
//c.copyConstructorMallocError(nullptr, 0, "var");
3659+
c.copyConstructorShallowCopyError(nullptr, "var");
3660+
c.noCopyConstructorError(nullptr, false, nullptr, false);
3661+
c.noOperatorEqError(nullptr, false, nullptr, false);
3662+
c.noDestructorError(nullptr, false, nullptr);
3663+
c.uninitVarError(nullptr, false, Function::eConstructor, "classname", "varname", false, false);
3664+
c.uninitVarError(nullptr, true, Function::eConstructor, "classname", "varnamepriv", false, false);
3665+
c.uninitVarError(nullptr, false, Function::eConstructor, "classname", "varname", true, false);
3666+
c.uninitVarError(nullptr, true, Function::eConstructor, "classname", "varnamepriv", true, false);
3667+
c.missingMemberCopyError(nullptr, Function::eConstructor, "classname", "varnamepriv");
3668+
c.operatorEqVarError(nullptr, "classname", emptyString, false);
3669+
c.unusedPrivateFunctionError(nullptr, "classname", "funcname");
3670+
c.memsetError(nullptr, "memfunc", "classname", "class");
3671+
c.memsetErrorReference(nullptr, "memfunc", "class");
3672+
c.memsetErrorFloat(nullptr, "class");
3673+
c.mallocOnClassWarning(nullptr, "malloc", nullptr);
3674+
c.mallocOnClassError(nullptr, "malloc", nullptr, "std::string");
3675+
c.virtualDestructorError(nullptr, "Base", "Derived", false);
3676+
c.thisSubtractionError(nullptr);
3677+
c.operatorEqRetRefThisError(nullptr);
3678+
c.operatorEqMissingReturnStatementError(nullptr, true);
3679+
c.operatorEqShouldBeLeftUnimplementedError(nullptr);
3680+
c.operatorEqToSelfError(nullptr);
3681+
c.checkConstError(nullptr, "class", "function", false);
3682+
c.checkConstError(nullptr, "class", "function", true);
3683+
c.initializerListError(nullptr, nullptr, "class", "variable");
3684+
c.suggestInitializationList(nullptr, "variable");
3685+
c.selfInitializationError(nullptr, "var");
3686+
c.duplInheritedMembersError(nullptr, nullptr, "class", "class", "variable", false, false);
3687+
c.copyCtorAndEqOperatorError(nullptr, "class", false, false);
3688+
c.pureVirtualFunctionCallInConstructorError(nullptr, std::list<const Token *>(), "f");
3689+
c.virtualFunctionCallInConstructorError(nullptr, std::list<const Token *>(), "f");
3690+
c.overrideError(nullptr, nullptr);
3691+
c.thisUseAfterFree(nullptr, nullptr, nullptr);
3692+
c.unsafeClassRefMemberError(nullptr, "UnsafeClass::var");
3693+
}

0 commit comments

Comments
 (0)