LCppC backports: Refactorizations/Optimizations (#4204)

This commit is contained in:
PKEuS 2022-08-21 17:21:02 +02:00 committed by GitHub
parent 0e1cd8b2ac
commit d81a758850
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 74 additions and 46 deletions

View File

@ -1865,21 +1865,22 @@ bool isUniqueExpression(const Token* tok)
const Type * varType = var->type(); const Type * varType = var->type();
// Iterate over the variables in scope and the parameters of the function if possible // Iterate over the variables in scope and the parameters of the function if possible
const Function * fun = scope->function; const Function * fun = scope->function;
const std::list<Variable>* setOfVars[] = {&scope->varlist, fun ? &fun->argumentList : nullptr};
for (const std::list<Variable>* vars:setOfVars) { auto pred = [=](const Variable& v) {
if (!vars) if (varType)
continue; return v.type() && v.type()->name() == varType->name() && v.name() != var->name();
bool other = std::any_of(vars->cbegin(), vars->cend(), [=](const Variable &v) { return v.isFloatingType() == var->isFloatingType() &&
if (varType) v.isEnumType() == var->isEnumType() &&
return v.type() && v.type()->name() == varType->name() && v.name() != var->name(); v.isClass() == var->isClass() &&
return v.isFloatingType() == var->isFloatingType() && v.isArray() == var->isArray() &&
v.isEnumType() == var->isEnumType() && v.isPointer() == var->isPointer() &&
v.isClass() == var->isClass() && v.name() != var->name();
v.isArray() == var->isArray() && };
v.isPointer() == var->isPointer() && bool other = std::any_of(scope->varlist.cbegin(), scope->varlist.cend(), pred);
v.name() != var->name(); if (other)
}); return false;
if (fun) {
other = std::any_of(fun->argumentList.cbegin(), fun->argumentList.cend(), pred);
if (other) if (other)
return false; return false;
} }

View File

@ -354,7 +354,7 @@ CheckMemoryLeak::AllocType CheckMemoryLeak::functionReturnType(const Function* f
return No; return No;
// Get return pointer.. // Get return pointer..
int varid = 0; const Variable* var = nullptr;
for (const Token *tok2 = func->functionScope->bodyStart; tok2 != func->functionScope->bodyEnd; tok2 = tok2->next()) { for (const Token *tok2 = func->functionScope->bodyStart; tok2 != func->functionScope->bodyEnd; tok2 = tok2->next()) {
if (const Token *endOfLambda = findLambdaEndToken(tok2)) if (const Token *endOfLambda = findLambdaEndToken(tok2))
tok2 = endOfLambda; tok2 = endOfLambda;
@ -371,24 +371,24 @@ CheckMemoryLeak::AllocType CheckMemoryLeak::functionReturnType(const Function* f
if (Token::Match(tok, ".|::")) if (Token::Match(tok, ".|::"))
tok = tok->astOperand2() ? tok->astOperand2() : tok->astOperand1(); tok = tok->astOperand2() ? tok->astOperand2() : tok->astOperand1();
if (tok) if (tok)
varid = tok->varId(); var = tok->variable();
break; break;
} }
} }
// Not returning pointer value.. // Not returning pointer value..
if (varid == 0) if (!var)
return No; return No;
// If variable is not local then alloctype shall be "No" // If variable is not local then alloctype shall be "No"
// Todo: there can be false negatives about mismatching allocation/deallocation. // Todo: there can be false negatives about mismatching allocation/deallocation.
// => Generate "alloc ; use ;" if variable is not local? // => Generate "alloc ; use ;" if variable is not local?
const Variable *var = mTokenizer_->getSymbolDatabase()->getVariableFromVarId(varid); if (!var->isLocal() || var->isStatic())
if (!var || !var->isLocal() || var->isStatic())
return No; return No;
// Check if return pointer is allocated.. // Check if return pointer is allocated..
AllocType allocType = No; AllocType allocType = No;
nonneg int varid = var->declarationId();
for (const Token* tok = func->functionScope->bodyStart; tok != func->functionScope->bodyEnd; tok = tok->next()) { for (const Token* tok = func->functionScope->bodyStart; tok != func->functionScope->bodyEnd; tok = tok->next()) {
if (Token::Match(tok, "%varid% =", varid)) { if (Token::Match(tok, "%varid% =", varid)) {
allocType = getAllocationType(tok->tokAt(2), varid, callstack); allocType = getAllocationType(tok->tokAt(2), varid, callstack);
@ -452,12 +452,6 @@ bool CheckMemoryLeakInFunction::test_white_list(const std::string &funcname, con
// a = malloc(10); a = realloc(a, 100); // a = malloc(10); a = realloc(a, 100);
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
static bool isNoArgument(const SymbolDatabase* symbolDatabase, nonneg int varid)
{
const Variable* var = symbolDatabase->getVariableFromVarId(varid);
return var && !var->isArgument();
}
void CheckMemoryLeakInFunction::checkReallocUsage() void CheckMemoryLeakInFunction::checkReallocUsage()
{ {
// only check functions // only check functions
@ -497,7 +491,7 @@ void CheckMemoryLeakInFunction::checkReallocUsage()
if (!arg || !tok2) if (!arg || !tok2)
continue; continue;
if (!((tok->varId() == arg->varId()) && isNoArgument(symbolDatabase, tok->varId()))) if (!(tok->varId() == arg->varId() && tok->variable() && !tok->variable()->isArgument()))
continue; continue;
// Check that another copy of the pointer wasn't saved earlier in the function // Check that another copy of the pointer wasn't saved earlier in the function

View File

@ -162,8 +162,6 @@ void CheckUninitVar::checkScope(const Scope* scope, const std::set<std::string>
continue; continue;
if (var.isArray()) { if (var.isArray()) {
Alloc alloc = ARRAY;
const std::map<nonneg int, VariableValue> variableValue;
bool init = false; bool init = false;
for (const Token *parent = var.nameToken(); parent; parent = parent->astParent()) { for (const Token *parent = var.nameToken(); parent; parent = parent->astParent()) {
if (parent->str() == "=") { if (parent->str() == "=") {
@ -171,8 +169,11 @@ void CheckUninitVar::checkScope(const Scope* scope, const std::set<std::string>
break; break;
} }
} }
if (!init) if (!init) {
Alloc alloc = ARRAY;
const std::map<nonneg int, VariableValue> variableValue;
checkScopeForVariable(tok, var, nullptr, nullptr, &alloc, emptyString, variableValue); checkScopeForVariable(tok, var, nullptr, nullptr, &alloc, emptyString, variableValue);
}
continue; continue;
} }
if (stdtype || var.isPointer()) { if (stdtype || var.isPointer()) {
@ -444,8 +445,7 @@ bool CheckUninitVar::checkScopeForVariable(const Token *tok, const Variable& var
const Token *condVarTok = nullptr; const Token *condVarTok = nullptr;
if (alwaysFalse) if (alwaysFalse)
; ;
else if (Token::simpleMatch(tok, "if (") && else if (astIsVariableComparison(tok->next()->astOperand2(), "!=", "0", &condVarTok)) {
astIsVariableComparison(tok->next()->astOperand2(), "!=", "0", &condVarTok)) {
const std::map<nonneg int,VariableValue>::const_iterator it = variableValue.find(condVarTok->varId()); const std::map<nonneg int,VariableValue>::const_iterator it = variableValue.find(condVarTok->varId());
if (it != variableValue.end() && it->second != 0) if (it != variableValue.end() && it->second != 0)
return true; // this scope is not fully analysed => return true return true; // this scope is not fully analysed => return true
@ -453,7 +453,7 @@ bool CheckUninitVar::checkScopeForVariable(const Token *tok, const Variable& var
condVarId = condVarTok->varId(); condVarId = condVarTok->varId();
condVarValue = !VariableValue(0); condVarValue = !VariableValue(0);
} }
} else if (Token::simpleMatch(tok, "if (") && Token::Match(tok->next()->astOperand2(), "==|!=")) { } else if (Token::Match(tok->next()->astOperand2(), "==|!=")) {
const Token *condition = tok->next()->astOperand2(); const Token *condition = tok->next()->astOperand2();
const Token *lhs = condition->astOperand1(); const Token *lhs = condition->astOperand1();
const Token *rhs = condition->astOperand2(); const Token *rhs = condition->astOperand2();

View File

@ -68,9 +68,7 @@ void CheckVaarg::va_start_argument()
if (var && var->isReference()) if (var && var->isReference())
referenceAs_va_start_error(param2, var->name()); referenceAs_va_start_error(param2, var->name());
if (var && var->index() + 2 < function->argCount() && printWarnings) { if (var && var->index() + 2 < function->argCount() && printWarnings) {
std::list<Variable>::const_reverse_iterator it = function->argumentList.rbegin(); wrongParameterTo_va_start_error(tok, var->name(), function->argumentList[function->argumentList.size()-2].name());
++it;
wrongParameterTo_va_start_error(tok, var->name(), it->name());
} }
tok = tok->linkAt(1); tok = tok->linkAt(1);
} }

View File

@ -1371,6 +1371,7 @@ void clangimport::AstNode::createTokensFunctionDecl(TokenList *tokenList)
function->nestedIn = nestedIn; function->nestedIn = nestedIn;
function->argDef = par1; function->argDef = par1;
// Function arguments // Function arguments
function->argumentList.reserve(children.size());
for (int i = 0; i < children.size(); ++i) { for (int i = 0; i < children.size(); ++i) {
AstNodePtr child = children[i]; AstNodePtr child = children[i];
if (child->nodeType != ParmVarDecl) if (child->nodeType != ParmVarDecl)

View File

@ -22,12 +22,14 @@
#define clangimportH #define clangimportH
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
#include "config.h"
#include <istream> #include <istream>
class Tokenizer; class Tokenizer;
namespace clangimport { namespace clangimport {
void parseClangAstDump(Tokenizer *tokenizer, std::istream &f); void CPPCHECKLIB parseClangAstDump(Tokenizer *tokenizer, std::istream &f);
} }
#endif #endif

View File

@ -106,8 +106,10 @@
<ItemGroup> <ItemGroup>
<ClInclude Include="..\externals\simplecpp\simplecpp.h" /> <ClInclude Include="..\externals\simplecpp\simplecpp.h" />
<ClInclude Include="..\externals\tinyxml2\tinyxml2.h" /> <ClInclude Include="..\externals\tinyxml2\tinyxml2.h" />
<ClInclude Include="analyzer.h" />
<ClInclude Include="analyzerinfo.h" /> <ClInclude Include="analyzerinfo.h" />
<ClInclude Include="astutils.h" /> <ClInclude Include="astutils.h" />
<ClInclude Include="calculate.h" />
<ClInclude Include="check.h" /> <ClInclude Include="check.h" />
<ClInclude Include="check64bit.h" /> <ClInclude Include="check64bit.h" />
<ClInclude Include="checkassert.h" /> <ClInclude Include="checkassert.h" />
@ -141,17 +143,22 @@
<ClInclude Include="ctu.h" /> <ClInclude Include="ctu.h" />
<ClInclude Include="errorlogger.h" /> <ClInclude Include="errorlogger.h" />
<ClInclude Include="errortypes.h" /> <ClInclude Include="errortypes.h" />
<ClInclude Include="forwardanalyzer.h" />
<ClInclude Include="infer.h" /> <ClInclude Include="infer.h" />
<ClInclude Include="library.h" /> <ClInclude Include="library.h" />
<ClInclude Include="mathlib.h" /> <ClInclude Include="mathlib.h" />
<ClInclude Include="path.h" /> <ClInclude Include="path.h" />
<ClInclude Include="pathanalysis.h" />
<ClInclude Include="pathmatch.h" /> <ClInclude Include="pathmatch.h" />
<ClInclude Include="platform.h" /> <ClInclude Include="platform.h" />
<ClInclude Include="precompiled.h" /> <ClInclude Include="precompiled.h" />
<ClInclude Include="preprocessor.h" /> <ClInclude Include="preprocessor.h" />
<ClInclude Include="importproject.h" /> <ClInclude Include="importproject.h" />
<ClInclude Include="programmemory.h" /> <ClInclude Include="programmemory.h" />
<ClInclude Include="reverseanalyzer.h" />
<ClInclude Include="settings.h" /> <ClInclude Include="settings.h" />
<ClInclude Include="smallvector.h" />
<ClInclude Include="standards.h" />
<ClInclude Include="summaries.h" /> <ClInclude Include="summaries.h" />
<ClInclude Include="suppressions.h" /> <ClInclude Include="suppressions.h" />
<ClInclude Include="symboldatabase.h" /> <ClInclude Include="symboldatabase.h" />
@ -163,6 +170,7 @@
<ClInclude Include="tokenrange.h" /> <ClInclude Include="tokenrange.h" />
<ClInclude Include="utils.h" /> <ClInclude Include="utils.h" />
<ClInclude Include="valueflow.h" /> <ClInclude Include="valueflow.h" />
<ClInclude Include="valueptr.h" />
<ClInclude Include="version.h" /> <ClInclude Include="version.h" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View File

@ -370,6 +370,30 @@
<ClInclude Include="infer.h"> <ClInclude Include="infer.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="analyzer.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="calculate.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="forwardanalyzer.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="pathanalysis.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="reverseanalyzer.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="smallvector.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="standards.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="valueptr.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ResourceCompile Include="version.rc" /> <ResourceCompile Include="version.rc" />
@ -377,4 +401,4 @@
<ItemGroup> <ItemGroup>
<Natvis Include="cppcheck.natvis" /> <Natvis Include="cppcheck.natvis" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -4272,12 +4272,8 @@ const Function * Function::getOverriddenFunctionRecursive(const ::Type* baseType
const Variable* Function::getArgumentVar(nonneg int num) const const Variable* Function::getArgumentVar(nonneg int num) const
{ {
for (std::list<Variable>::const_iterator i = argumentList.begin(); i != argumentList.end(); ++i) { if (num < argumentList.size())
if (i->index() == num) return &argumentList[num];
return (&*i);
else if (i->index() > num)
return nullptr;
}
return nullptr; return nullptr;
} }

View File

@ -693,7 +693,7 @@ private:
/** @brief pointer to scope this variable is in */ /** @brief pointer to scope this variable is in */
const Scope *mScope; const Scope *mScope;
ValueType *mValueType; const ValueType *mValueType;
/** @brief array dimensions */ /** @brief array dimensions */
std::vector<Dimension> mDimensions; std::vector<Dimension> mDimensions;
@ -916,7 +916,7 @@ public:
const ::Type *retType; ///< function return type const ::Type *retType; ///< function return type
const Scope *functionScope; ///< scope of function body const Scope *functionScope; ///< scope of function body
const Scope* nestedIn; ///< Scope the function is declared in const Scope* nestedIn; ///< Scope the function is declared in
std::list<Variable> argumentList; ///< argument list std::vector<Variable> argumentList; ///< argument list
nonneg int initArgCount; ///< number of args with default values nonneg int initArgCount; ///< number of args with default values
Type type; ///< constructor, destructor, ... Type type; ///< constructor, destructor, ...
const Token *noexceptArg; ///< noexcept token const Token *noexceptArg; ///< noexcept token

View File

@ -42,6 +42,7 @@
<ClCompile Include="testboost.cpp" /> <ClCompile Include="testboost.cpp" />
<ClCompile Include="testbufferoverrun.cpp" /> <ClCompile Include="testbufferoverrun.cpp" />
<ClCompile Include="testcharvar.cpp" /> <ClCompile Include="testcharvar.cpp" />
<ClCompile Include="testclangimport.cpp" />
<ClCompile Include="testclass.cpp" /> <ClCompile Include="testclass.cpp" />
<ClCompile Include="testcmdlineparser.cpp" /> <ClCompile Include="testcmdlineparser.cpp" />
<ClCompile Include="testcondition.cpp" /> <ClCompile Include="testcondition.cpp" />

View File

@ -220,6 +220,9 @@
<ClCompile Include="testtokenrange.cpp"> <ClCompile Include="testtokenrange.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="testclangimport.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="options.h"> <ClInclude Include="options.h">
@ -250,4 +253,4 @@
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
</ItemGroup> </ItemGroup>
</Project> </Project>