* Fix #10980 FN constVariable with range-based for loop * Format * nullptr check * Restrict scopes * Add const * Undo * Add more const
This commit is contained in:
parent
e1c51940a2
commit
7fbb9c7c13
|
@ -915,14 +915,14 @@ static bool hasUnknownVars(const Token* startTok)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool isStructuredBindingVariable(const Variable* var)
|
bool isStructuredBindingVariable(const Variable* var)
|
||||||
{
|
{
|
||||||
if (!var)
|
if (!var)
|
||||||
return false;
|
return false;
|
||||||
const Token* tok = var->nameToken();
|
const Token* tok = var->nameToken();
|
||||||
while (Token::Match(tok->astParent(), "[|,"))
|
while (tok && Token::Match(tok->astParent(), "[|,|:"))
|
||||||
tok = tok->astParent();
|
tok = tok->astParent();
|
||||||
return Token::simpleMatch(tok, "[");
|
return tok && (tok->str() == "[" || Token::simpleMatch(tok->previous(), "] :")); // TODO: remove workaround when #11105 is fixed
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This takes a token that refers to a variable and it will return the token
|
/// This takes a token that refers to a variable and it will return the token
|
||||||
|
|
|
@ -205,6 +205,8 @@ bool isSameExpression(bool cpp, bool macro, const Token *tok1, const Token *tok2
|
||||||
|
|
||||||
bool isEqualKnownValue(const Token * const tok1, const Token * const tok2);
|
bool isEqualKnownValue(const Token * const tok1, const Token * const tok2);
|
||||||
|
|
||||||
|
bool isStructuredBindingVariable(const Variable* var);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Is token used a boolean, that is to say cast to a bool, or used as a condition in a if/while/for
|
* Is token used a boolean, that is to say cast to a bool, or used as a condition in a if/while/for
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -1407,13 +1407,13 @@ void CheckOther::checkConstVariable()
|
||||||
continue;
|
continue;
|
||||||
if (var->isConst())
|
if (var->isConst())
|
||||||
continue;
|
continue;
|
||||||
if (!var->scope())
|
const Scope* scope = var->scope();
|
||||||
|
if (!scope)
|
||||||
continue;
|
continue;
|
||||||
const Scope *scope = var->scope();
|
const Function* function = scope->function;
|
||||||
if (!scope->function)
|
if (!function && !scope->isLocal())
|
||||||
continue;
|
continue;
|
||||||
const Function *function = scope->function;
|
if (function && var->isArgument()) {
|
||||||
if (var->isArgument()) {
|
|
||||||
if (function->isImplicitlyVirtual() || function->templateDef)
|
if (function->isImplicitlyVirtual() || function->templateDef)
|
||||||
continue;
|
continue;
|
||||||
if (isUnusedVariable(var))
|
if (isUnusedVariable(var))
|
||||||
|
@ -1433,9 +1433,18 @@ void CheckOther::checkConstVariable()
|
||||||
continue;
|
continue;
|
||||||
if (isAliased(var))
|
if (isAliased(var))
|
||||||
continue;
|
continue;
|
||||||
|
if (isStructuredBindingVariable(var)) // TODO: check all bound variables
|
||||||
|
continue;
|
||||||
if (isVariableChanged(var, mSettings, mTokenizer->isCPP()))
|
if (isVariableChanged(var, mSettings, mTokenizer->isCPP()))
|
||||||
continue;
|
continue;
|
||||||
if (Function::returnsReference(function) && !Function::returnsConst(function)) {
|
const bool hasFunction = function != nullptr;
|
||||||
|
if (!hasFunction) {
|
||||||
|
const Scope* functionScope = scope;
|
||||||
|
do {
|
||||||
|
functionScope = functionScope->nestedIn;
|
||||||
|
} while (functionScope && !(function = functionScope->function));
|
||||||
|
}
|
||||||
|
if (function && Function::returnsReference(function) && !Function::returnsConst(function)) {
|
||||||
std::vector<const Token*> returns = Function::findReturns(function);
|
std::vector<const Token*> returns = Function::findReturns(function);
|
||||||
if (std::any_of(returns.begin(), returns.end(), [&](const Token* retTok) {
|
if (std::any_of(returns.begin(), returns.end(), [&](const Token* retTok) {
|
||||||
if (retTok->varId() == var->declarationId())
|
if (retTok->varId() == var->declarationId())
|
||||||
|
@ -1531,7 +1540,7 @@ void CheckOther::checkConstVariable()
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
constVariableError(var, function);
|
constVariableError(var, hasFunction ? function : nullptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1519,7 +1519,7 @@ static void setValues(Tokenizer *tokenizer, SymbolDatabase *symbolDatabase)
|
||||||
{
|
{
|
||||||
const Settings * const settings = tokenizer->getSettings();
|
const Settings * const settings = tokenizer->getSettings();
|
||||||
|
|
||||||
for (Scope &scope: symbolDatabase->scopeList) {
|
for (const Scope& scope : symbolDatabase->scopeList) {
|
||||||
if (!scope.definedType)
|
if (!scope.definedType)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
|
|
@ -71,7 +71,7 @@ Preprocessor::Preprocessor(Settings& settings, ErrorLogger *errorLogger) : mSett
|
||||||
|
|
||||||
Preprocessor::~Preprocessor()
|
Preprocessor::~Preprocessor()
|
||||||
{
|
{
|
||||||
for (std::pair<const std::string, simplecpp::TokenList *>& tokenList : mTokenLists)
|
for (const std::pair<const std::string, simplecpp::TokenList*>& tokenList : mTokenLists)
|
||||||
delete tokenList.second;
|
delete tokenList.second;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1043,10 +1043,10 @@ unsigned int Preprocessor::calculateChecksum(const simplecpp::TokenList &tokens1
|
||||||
return crc32(ostr.str());
|
return crc32(ostr.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void Preprocessor::simplifyPragmaAsm(simplecpp::TokenList *tokenList)
|
void Preprocessor::simplifyPragmaAsm(simplecpp::TokenList *tokenList) const
|
||||||
{
|
{
|
||||||
Preprocessor::simplifyPragmaAsmPrivate(tokenList);
|
Preprocessor::simplifyPragmaAsmPrivate(tokenList);
|
||||||
for (std::pair<const std::string, simplecpp::TokenList *>& list : mTokenLists) {
|
for (const std::pair<const std::string, simplecpp::TokenList*>& list : mTokenLists) {
|
||||||
Preprocessor::simplifyPragmaAsmPrivate(list.second);
|
Preprocessor::simplifyPragmaAsmPrivate(list.second);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -172,7 +172,7 @@ public:
|
||||||
*/
|
*/
|
||||||
unsigned int calculateChecksum(const simplecpp::TokenList &tokens1, const std::string &toolinfo) const;
|
unsigned int calculateChecksum(const simplecpp::TokenList &tokens1, const std::string &toolinfo) const;
|
||||||
|
|
||||||
void simplifyPragmaAsm(simplecpp::TokenList *tokenList);
|
void simplifyPragmaAsm(simplecpp::TokenList *tokenList) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
|
|
@ -863,7 +863,7 @@ void SymbolDatabase::createSymbolDatabaseNeedInitialization()
|
||||||
{
|
{
|
||||||
if (mTokenizer->isC()) {
|
if (mTokenizer->isC()) {
|
||||||
// For C code it is easy, as there are no constructors and no default values
|
// For C code it is easy, as there are no constructors and no default values
|
||||||
for (Scope& scope : scopeList) {
|
for (const Scope& scope : scopeList) {
|
||||||
if (scope.definedType)
|
if (scope.definedType)
|
||||||
scope.definedType->needInitialization = Type::NeedInitialization::True;
|
scope.definedType->needInitialization = Type::NeedInitialization::True;
|
||||||
}
|
}
|
||||||
|
@ -888,7 +888,7 @@ void SymbolDatabase::createSymbolDatabaseNeedInitialization()
|
||||||
// check for default constructor
|
// check for default constructor
|
||||||
bool hasDefaultConstructor = false;
|
bool hasDefaultConstructor = false;
|
||||||
|
|
||||||
for (Function& func: scope.functionList) {
|
for (const Function& func : scope.functionList) {
|
||||||
if (func.type == Function::eConstructor) {
|
if (func.type == Function::eConstructor) {
|
||||||
// check for no arguments: func ( )
|
// check for no arguments: func ( )
|
||||||
if (func.argCount() == 0) {
|
if (func.argCount() == 0) {
|
||||||
|
@ -1452,7 +1452,7 @@ void SymbolDatabase::createSymbolDatabaseIncompleteVars()
|
||||||
|
|
||||||
void SymbolDatabase::createSymbolDatabaseEscapeFunctions()
|
void SymbolDatabase::createSymbolDatabaseEscapeFunctions()
|
||||||
{
|
{
|
||||||
for (Scope & scope : scopeList) {
|
for (const Scope& scope : scopeList) {
|
||||||
if (scope.type != Scope::eFunction)
|
if (scope.type != Scope::eFunction)
|
||||||
continue;
|
continue;
|
||||||
Function * function = scope.function;
|
Function * function = scope.function;
|
||||||
|
|
|
@ -3374,10 +3374,10 @@ static bool specMatch(
|
||||||
void TemplateSimplifier::getSpecializations()
|
void TemplateSimplifier::getSpecializations()
|
||||||
{
|
{
|
||||||
// try to locate a matching declaration for each user defined specialization
|
// try to locate a matching declaration for each user defined specialization
|
||||||
for (auto & spec : mTemplateDeclarations) {
|
for (const auto& spec : mTemplateDeclarations) {
|
||||||
if (spec.isSpecialization()) {
|
if (spec.isSpecialization()) {
|
||||||
bool found = false;
|
bool found = false;
|
||||||
for (auto & decl : mTemplateDeclarations) {
|
for (const auto& decl : mTemplateDeclarations) {
|
||||||
if (specMatch(spec, decl)) {
|
if (specMatch(spec, decl)) {
|
||||||
mTemplateSpecializationMap[spec.token()] = decl.token();
|
mTemplateSpecializationMap[spec.token()] = decl.token();
|
||||||
found = true;
|
found = true;
|
||||||
|
@ -3386,7 +3386,7 @@ void TemplateSimplifier::getSpecializations()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!found) {
|
if (!found) {
|
||||||
for (auto & decl : mTemplateForwardDeclarations) {
|
for (const auto& decl : mTemplateForwardDeclarations) {
|
||||||
if (specMatch(spec, decl)) {
|
if (specMatch(spec, decl)) {
|
||||||
mTemplateSpecializationMap[spec.token()] = decl.token();
|
mTemplateSpecializationMap[spec.token()] = decl.token();
|
||||||
break;
|
break;
|
||||||
|
@ -3400,10 +3400,10 @@ void TemplateSimplifier::getSpecializations()
|
||||||
void TemplateSimplifier::getPartialSpecializations()
|
void TemplateSimplifier::getPartialSpecializations()
|
||||||
{
|
{
|
||||||
// try to locate a matching declaration for each user defined partial specialization
|
// try to locate a matching declaration for each user defined partial specialization
|
||||||
for (auto & spec : mTemplateDeclarations) {
|
for (const auto& spec : mTemplateDeclarations) {
|
||||||
if (spec.isPartialSpecialization()) {
|
if (spec.isPartialSpecialization()) {
|
||||||
bool found = false;
|
bool found = false;
|
||||||
for (auto & decl : mTemplateDeclarations) {
|
for (const auto& decl : mTemplateDeclarations) {
|
||||||
if (specMatch(spec, decl)) {
|
if (specMatch(spec, decl)) {
|
||||||
mTemplatePartialSpecializationMap[spec.token()] = decl.token();
|
mTemplatePartialSpecializationMap[spec.token()] = decl.token();
|
||||||
found = true;
|
found = true;
|
||||||
|
@ -3412,7 +3412,7 @@ void TemplateSimplifier::getPartialSpecializations()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!found) {
|
if (!found) {
|
||||||
for (auto & decl : mTemplateForwardDeclarations) {
|
for (const auto& decl : mTemplateForwardDeclarations) {
|
||||||
if (specMatch(spec, decl)) {
|
if (specMatch(spec, decl)) {
|
||||||
mTemplatePartialSpecializationMap[spec.token()] = decl.token();
|
mTemplatePartialSpecializationMap[spec.token()] = decl.token();
|
||||||
break;
|
break;
|
||||||
|
@ -3841,7 +3841,7 @@ void TemplateSimplifier::simplifyTemplates(
|
||||||
}
|
}
|
||||||
|
|
||||||
// remove explicit instantiations
|
// remove explicit instantiations
|
||||||
for (TokenAndName & j : mExplicitInstantiationsToDelete) {
|
for (const TokenAndName& j : mExplicitInstantiationsToDelete) {
|
||||||
Token * start = j.token();
|
Token * start = j.token();
|
||||||
if (start) {
|
if (start) {
|
||||||
Token * end = start->next();
|
Token * end = start->next();
|
||||||
|
|
|
@ -2181,7 +2181,24 @@ private:
|
||||||
check("void f(std::vector<int>& v) {\n"
|
check("void f(std::vector<int>& v) {\n"
|
||||||
" for(auto& x:v) {}\n"
|
" for(auto& x:v) {}\n"
|
||||||
"}");
|
"}");
|
||||||
ASSERT_EQUALS("[test.cpp:1]: (style) Parameter 'v' can be declared as reference to const\n", errout.str());
|
ASSERT_EQUALS("[test.cpp:1]: (style) Parameter 'v' can be declared as reference to const\n"
|
||||||
|
"[test.cpp:2]: (style) Variable 'x' can be declared as reference to const\n",
|
||||||
|
errout.str());
|
||||||
|
|
||||||
|
check("void f(std::vector<int>& v) {\n" // #10980
|
||||||
|
" for (int& i : v)\n"
|
||||||
|
" if (i == 0) {}\n"
|
||||||
|
" for (const int& i : v)\n"
|
||||||
|
" if (i == 0) {}\n"
|
||||||
|
" for (auto& i : v)\n"
|
||||||
|
" if (i == 0) {}\n"
|
||||||
|
" for (const auto& i : v)\n"
|
||||||
|
" if (i == 0) {}\n"
|
||||||
|
" v.clear();\n"
|
||||||
|
"}\n");
|
||||||
|
ASSERT_EQUALS("[test.cpp:2]: (style) Variable 'i' can be declared as reference to const\n"
|
||||||
|
"[test.cpp:6]: (style) Variable 'i' can be declared as reference to const\n",
|
||||||
|
errout.str());
|
||||||
|
|
||||||
check("void f(std::vector<int>& v) {\n"
|
check("void f(std::vector<int>& v) {\n"
|
||||||
" for(const auto& x:v) {}\n"
|
" for(const auto& x:v) {}\n"
|
||||||
|
|
Loading…
Reference in New Issue