diff --git a/lib/astutils.cpp b/lib/astutils.cpp index 30f10794855..33608df6fc6 100644 --- a/lib/astutils.cpp +++ b/lib/astutils.cpp @@ -1062,7 +1062,7 @@ bool isAliasOf(const Token *tok, nonneg int varid, bool* inconclusive) return false; } -bool isAliasOf(const Token* tok, const Token* expr, int* indirect) +bool isAliasOf(const Token* tok, const Token* expr, nonneg int* indirect) { const Token* r = nullptr; if (indirect) @@ -2906,7 +2906,7 @@ static bool isExpressionChangedAt(const F& getExprTok, // TODO: Is global variable really changed by function call? return true; } - int i = 1; + nonneg int i = 1; bool aliased = false; // If we can't find the expression then assume it is an alias auto expr = getExprTok(); @@ -2916,7 +2916,10 @@ static bool isExpressionChangedAt(const F& getExprTok, aliased = isAliasOf(tok, expr, &i); if (!aliased) return false; - if (isVariableChanged(tok, indirect + i, settings, depth)) + i += indirect; + if (tok->valueType() && tok->valueType()->pointer) + i = std::min(i, tok->valueType()->pointer); + if (isVariableChanged(tok, i, settings, depth)) return true; // TODO: Try to traverse the lambda function if (Token::Match(tok, "%var% (")) diff --git a/lib/astutils.h b/lib/astutils.h index f7a245c0430..895748acf72 100644 --- a/lib/astutils.h +++ b/lib/astutils.h @@ -379,7 +379,7 @@ bool isExpressionChangedAt(const Token* expr, /// If token is an alias if another variable bool isAliasOf(const Token *tok, nonneg int varid, bool* inconclusive = nullptr); -bool isAliasOf(const Token* tok, const Token* expr, int* indirect = nullptr); +bool isAliasOf(const Token* tok, const Token* expr, nonneg int* indirect = nullptr); const Token* getArgumentStart(const Token* ftok); diff --git a/lib/checkother.cpp b/lib/checkother.cpp index 7a06f66f644..1b1d6194559 100644 --- a/lib/checkother.cpp +++ b/lib/checkother.cpp @@ -1916,8 +1916,13 @@ void CheckOther::checkConstPointer() continue; if (Token::simpleMatch(parent, "(") && Token::Match(parent->astOperand1(), "if|while")) continue; - if (Token::simpleMatch(parent, "=") && parent->astOperand1() == tok) - continue; + if (Token::simpleMatch(parent, "=")) { + const Token* lhs = parent->astOperand1(); + if (lhs == tok) + continue; + if (lhs && lhs->valueType() && lhs->valueType()->isConst(vt->pointer)) + continue; + } if (const Token* ftok = getTokenArgumentFunction(tok, argn)) { if (ftok->function()) { const bool isCastArg = parent->isCast() && !ftok->function()->getOverloadedFunctions().empty(); // assume that cast changes the called function diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index 55145f1207c..04b87f050f3 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -2296,7 +2296,7 @@ Variable& Variable::operator=(const Variable &var) & if (this == &var) return *this; - ValueType* vt = nullptr; + const ValueType* vt = nullptr; if (var.mValueType) vt = new ValueType(*var.mValueType); @@ -2462,7 +2462,7 @@ void Variable::setValueType(const ValueType &valueType) if (declType && !declType->next()->valueType()) return; } - auto* vt = new ValueType(valueType); + const auto* vt = new ValueType(valueType); delete mValueType; mValueType = vt; if ((mValueType->pointer > 0) && (!isArray() || Token::Match(mNameToken->previous(), "( * %name% )"))) diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 9c6db66a4c6..b87c6d11103 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -1243,7 +1243,7 @@ void Tokenizer::simplifyTypedefCpp() bool refToArray = false; bool ptrMember = false; bool typeOf = false; - Token *namespaceStart = nullptr; + const Token *namespaceStart = nullptr; Token *namespaceEnd = nullptr; // check for invalid input @@ -3025,7 +3025,7 @@ bool Tokenizer::simplifyUsing() ScopeInfo3 scopeInfo1; ScopeInfo3 *currentScope1 = &scopeInfo1; Token *startToken = list.front(); - Token *endToken = nullptr; + const Token *endToken = nullptr; bool inMemberFunc = false; const ScopeInfo3 * memberFuncScope = nullptr; const Token * memberFuncEnd = nullptr; @@ -3039,7 +3039,7 @@ bool Tokenizer::simplifyUsing() if (!currentScope1) return substitute; // something bad happened startToken = usingEnd->next(); - endToken = const_cast(currentScope->bodyEnd->next()); + endToken = currentScope->bodyEnd->next(); if (currentScope->type == ScopeInfo3::MemberFunction) { const ScopeInfo3 * temp = currentScope->findScope(currentScope->fullName); if (temp) { diff --git a/test/testother.cpp b/test/testother.cpp index 64e8ddf5960..18d6e54e5f5 100644 --- a/test/testother.cpp +++ b/test/testother.cpp @@ -4497,6 +4497,16 @@ class TestOther : public TestFixture { ASSERT_EQUALS("[test.cpp:2:18]: (style) Parameter 's' can be declared as pointer to const [constParameterPointer]\n" "[test.cpp:5:18]: (style) Parameter 's' can be declared as pointer to const [constParameterPointer]\n", errout_str()); + + check("struct T;\n" + "void use(const T*);\n" + "void f(T* tok0) {\n" + " T *tok1 = tok0;\n" + " const T *tok2 = tok1;\n" + " use(tok2);\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:4:8]: (style) Variable 'tok1' can be declared as pointer to const [constVariablePointer]\n", + errout_str()); } void constArray() {