|
Cppcheck
|
00001 /* 00002 * Cppcheck - A tool for static C/C++ code analysis 00003 * Copyright (C) 2007-2013 Daniel Marjamäki and Cppcheck team. 00004 * 00005 * This program is free software: you can redistribute it and/or modify 00006 * it under the terms of the GNU General Public License as published by 00007 * the Free Software Foundation, either version 3 of the License, or 00008 * (at your option) any later version. 00009 * 00010 * This program is distributed in the hope that it will be useful, 00011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 * GNU General Public License for more details. 00014 * 00015 * You should have received a copy of the GNU General Public License 00016 * along with this program. If not, see <http://www.gnu.org/licenses/>. 00017 */ 00018 00019 //--------------------------------------------------------------------------- 00020 #ifndef CheckClassH 00021 #define CheckClassH 00022 //--------------------------------------------------------------------------- 00023 00024 #include "config.h" 00025 #include "check.h" 00026 00027 class Token; 00028 class Scope; 00029 class Function; 00030 00031 /// @addtogroup Checks 00032 /// @{ 00033 00034 00035 /** @brief %Check classes. Uninitialized member variables, non-conforming operators, missing virtual destructor, etc */ 00036 class CPPCHECKLIB CheckClass : public Check { 00037 public: 00038 /** @brief This constructor is used when registering the CheckClass */ 00039 CheckClass() : Check(myName()), symbolDatabase(NULL) 00040 { } 00041 00042 /** @brief This constructor is used when running checks. */ 00043 CheckClass(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger); 00044 00045 /** @brief Run checks on the normal token list */ 00046 void runChecks(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) { 00047 if (tokenizer->isC()) 00048 return; 00049 00050 CheckClass checkClass(tokenizer, settings, errorLogger); 00051 00052 // can't be a simplified check .. the 'sizeof' is used. 00053 checkClass.noMemset(); 00054 } 00055 00056 /** @brief Run checks on the simplified token list */ 00057 void runSimplifiedChecks(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) { 00058 if (tokenizer->isC()) 00059 return; 00060 00061 CheckClass checkClass(tokenizer, settings, errorLogger); 00062 00063 // Coding style checks 00064 checkClass.constructors(); 00065 checkClass.operatorEq(); 00066 checkClass.privateFunctions(); 00067 checkClass.operatorEqRetRefThis(); 00068 checkClass.thisSubtraction(); 00069 checkClass.operatorEqToSelf(); 00070 checkClass.initializerListOrder(); 00071 checkClass.initializationListUsage(); 00072 00073 checkClass.virtualDestructor(); 00074 checkClass.checkConst(); 00075 checkClass.copyconstructors(); 00076 } 00077 00078 00079 /** @brief %Check that all class constructors are ok */ 00080 void constructors(); 00081 00082 /** @brief %Check that all private functions are called */ 00083 void privateFunctions(); 00084 00085 /** 00086 * @brief %Check that the memsets are valid. 00087 * The 'memset' function can do dangerous things if used wrong. If it 00088 * is used on STL containers for instance it will clear all its data 00089 * and then the STL container may leak memory or worse have an invalid state. 00090 * It can also overwrite the virtual table. 00091 * Important: The checking doesn't work on simplified tokens list. 00092 */ 00093 void noMemset(); 00094 void checkMemsetType(const Scope *start, const Token *tok, const Scope *type, bool allocation); 00095 00096 /** @brief 'operator=' should return something and it should not be const. */ 00097 void operatorEq(); 00098 00099 /** @brief 'operator=' should return reference to *this */ 00100 void operatorEqRetRefThis(); // Warning upon no "return *this;" 00101 00102 /** @brief 'operator=' should check for assignment to self */ 00103 void operatorEqToSelf(); // Warning upon no check for assignment to self 00104 00105 /** @brief The destructor in a base class should be virtual */ 00106 void virtualDestructor(); 00107 00108 /** @brief warn for "this-x". The indented code may be "this->x" */ 00109 void thisSubtraction(); 00110 00111 /** @brief can member function be const? */ 00112 void checkConst(); 00113 00114 /** @brief Check initializer list order */ 00115 void initializerListOrder(); 00116 00117 void initializationListUsage(); 00118 00119 void copyconstructors(); 00120 00121 private: 00122 const SymbolDatabase *symbolDatabase; 00123 00124 // Reporting errors.. 00125 void noConstructorError(const Token *tok, const std::string &classname, bool isStruct); 00126 //void copyConstructorMallocError(const Token *cctor, const Token *alloc, const std::string& var_name); 00127 void copyConstructorShallowCopyError(const Token *tok, const std::string& varname); 00128 void noCopyConstructorError(const Token *tok, const std::string &classname, bool isStruct); 00129 void uninitVarError(const Token *tok, const std::string &classname, const std::string &varname, bool inconclusive); 00130 void operatorEqVarError(const Token *tok, const std::string &classname, const std::string &varname, bool inconclusive); 00131 void unusedPrivateFunctionError(const Token *tok, const std::string &classname, const std::string &funcname); 00132 void memsetError(const Token *tok, const std::string &memfunc, const std::string &classname, const std::string &type); 00133 void mallocOnClassError(const Token* tok, const std::string &memfunc, const Token* classTok, const std::string &classname); 00134 void mallocOnClassWarning(const Token* tok, const std::string &memfunc, const Token* classTok); 00135 void operatorEqReturnError(const Token *tok, const std::string &className); 00136 void virtualDestructorError(const Token *tok, const std::string &Base, const std::string &Derived); 00137 void thisSubtractionError(const Token *tok); 00138 void operatorEqRetRefThisError(const Token *tok); 00139 void operatorEqToSelfError(const Token *tok); 00140 void checkConstError(const Token *tok, const std::string &classname, const std::string &funcname, bool suggestStatic); 00141 void checkConstError2(const Token *tok1, const Token *tok2, const std::string &classname, const std::string &funcname, bool suggestStatic); 00142 void initializerListError(const Token *tok1,const Token *tok2, const std::string & classname, const std::string &varname); 00143 void suggestInitializationList(const Token *tok, const std::string& varname); 00144 00145 void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const { 00146 CheckClass c(0, settings, errorLogger); 00147 c.noConstructorError(0, "classname", false); 00148 //c.copyConstructorMallocError(0, 0, "var"); 00149 c.copyConstructorShallowCopyError(0, "var"); 00150 c.noCopyConstructorError(0, "class", false); 00151 c.uninitVarError(0, "classname", "varname", false); 00152 c.operatorEqVarError(0, "classname", "", false); 00153 c.unusedPrivateFunctionError(0, "classname", "funcname"); 00154 c.memsetError(0, "memfunc", "classname", "class"); 00155 c.mallocOnClassWarning(0, "malloc", 0); 00156 c.mallocOnClassError(0, "malloc", 0, "std::string"); 00157 c.operatorEqReturnError(0, "class"); 00158 c.virtualDestructorError(0, "Base", "Derived"); 00159 c.thisSubtractionError(0); 00160 c.operatorEqRetRefThisError(0); 00161 c.operatorEqToSelfError(0); 00162 c.checkConstError(0, "class", "function", false); 00163 c.checkConstError(0, "class", "function", true); 00164 c.initializerListError(0, 0, "class", "variable"); 00165 c.suggestInitializationList(0, "variable"); 00166 } 00167 00168 static std::string myName() { 00169 return "Class"; 00170 } 00171 00172 std::string classInfo() const { 00173 return "Check the code for each class.\n" 00174 "* Missing constructors and copy constructors\n" 00175 //"* Missing allocation of memory in copy constructor\n" 00176 "* Are all variables initialized by the constructors?\n" 00177 "* Are all variables assigned by 'operator='?\n" 00178 "* Warn if memset, memcpy etc are used on a class\n" 00179 "* Warn if memory for classes is allocated with malloc()\n" 00180 "* If it's a base class, check that the destructor is virtual\n" 00181 "* Are there unused private functions?\n" 00182 "* 'operator=' should return reference to self\n" 00183 "* 'operator=' should check for assignment to self\n" 00184 "* Constness for member functions\n" 00185 "* Order of initializations\n" 00186 "* Suggest usage of initialization list\n" 00187 "* Suspicious subtraction from 'this'\n"; 00188 } 00189 00190 // operatorEqRetRefThis helper function 00191 void checkReturnPtrThis(const Scope *scope, const Function *func, const Token *tok, const Token *last); 00192 00193 // operatorEqToSelf helper functions 00194 bool hasAllocation(const Function *func, const Scope* scope); 00195 static bool hasAssignSelf(const Function *func, const Token *rhs); 00196 00197 // checkConst helper functions 00198 bool isMemberVar(const Scope *scope, const Token *tok); 00199 bool isMemberFunc(const Scope *scope, const Token *tok); 00200 bool isConstMemberFunc(const Scope *scope, const Token *tok); 00201 bool checkConstFunc(const Scope *scope, const Function *func, bool& memberAccessed); 00202 00203 // constructors helper function 00204 /** @brief Information about a member variable. Used when checking for uninitialized variables */ 00205 struct Usage { 00206 Usage() : assign(false), init(false) { } 00207 00208 /** @brief has this variable been assigned? */ 00209 bool assign; 00210 00211 /** @brief has this variable been initialized? */ 00212 bool init; 00213 }; 00214 00215 static bool isBaseClassFunc(const Token *tok, const Scope *scope); 00216 00217 /** 00218 * @brief assign a variable in the varlist 00219 * @param varname name of variable to mark assigned 00220 * @param scope pointer to variable Scope 00221 * @param usage reference to usage vector 00222 */ 00223 static void assignVar(const std::string &varname, const Scope *scope, std::vector<Usage> &usage); 00224 00225 /** 00226 * @brief initialize a variable in the varlist 00227 * @param varname name of variable to mark initialized 00228 * @param scope pointer to variable Scope 00229 * @param usage reference to usage vector 00230 */ 00231 static void initVar(const std::string &varname, const Scope *scope, std::vector<Usage> &usage); 00232 00233 /** 00234 * @brief set all variables in list assigned 00235 * @param usage reference to usage vector 00236 */ 00237 static void assignAllVar(std::vector<Usage> &usage); 00238 00239 /** 00240 * @brief set all variables in list not assigned and not initialized 00241 * @param usage reference to usage vector 00242 */ 00243 static void clearAllVar(std::vector<Usage> &usage); 00244 00245 /** 00246 * @brief parse a scope for a constructor or member function and set the "init" flags in the provided varlist 00247 * @param func reference to the function that should be checked 00248 * @param callstack the function doesn't look into recursive function calls. 00249 * @param scope pointer to variable Scope 00250 * @param usage reference to usage vector 00251 */ 00252 void initializeVarList(const Function &func, std::list<const Function *> &callstack, const Scope *scope, std::vector<Usage> &usage); 00253 00254 static bool canNotCopy(const Scope *scope); 00255 }; 00256 /// @} 00257 //--------------------------------------------------------------------------- 00258 #endif
1.7.6.1