diff --git a/lib/checkother.cpp b/lib/checkother.cpp index e7da51161..b46910095 100644 --- a/lib/checkother.cpp +++ b/lib/checkother.cpp @@ -1271,6 +1271,32 @@ static bool isUnusedVariable(const Variable *var) return !Token::findmatch(start->next(), "%varid%", var->scope()->bodyEnd, var->declarationId()); } +static bool isVariableMutableInInitializer(const Token* start, const Token * end, nonneg int varid) +{ + if (!start) + return false; + if (!end) + return false; + for (const Token *tok = start; tok != end; tok = tok->next()) { + if (tok->varId() != varid) + continue; + if (tok->astParent()) { + const Token * memberTok = tok->astParent()->previous(); + if (Token::Match(memberTok, "%var% (") && memberTok->variable()) { + const Variable * memberVar = memberTok->variable(); + if (!memberVar->isReference()) + continue; + if (memberVar->isConst()) + continue; + } + return true; + } else { + return true; + } + } + return false; +} + void CheckOther::checkConstVariable() { if (!mSettings->isEnabled(Settings::STYLE) || mTokenizer->isC()) @@ -1298,8 +1324,7 @@ void CheckOther::checkConstVariable() continue; if (isUnusedVariable(var)) continue; - const Token * memberTok = Token::findmatch(function->constructorMemberInitialization(), "%var% ( %varid% )", scope->bodyStart, var->declarationId()); - if (memberTok && memberTok->variable() && memberTok->variable()->isReference()) + if (function->isConstructor() && isVariableMutableInInitializer(function->constructorMemberInitialization(), scope->bodyStart, var->declarationId())) continue; } if (var->isGlobal()) diff --git a/test/testother.cpp b/test/testother.cpp index 19da51bb9..02bb88306 100644 --- a/test/testother.cpp +++ b/test/testother.cpp @@ -1892,6 +1892,15 @@ private: "};\n"); ASSERT_EQUALS("", errout.str()); + check("struct A {\n" + " A(int& x);\n" + "};\n" + "struct B : A {\n" + " B(int& x) : A(x)\n" + " {}\n" + "};\n"); + ASSERT_EQUALS("", errout.str()); + check("void e();\n" "void g(void);\n" "void h(void);\n"