Fix issue 9006: False positive: Return value of function std::move() is not used.
This is trying to fix the issue by fixing the ast and symbol database. First, the ast nodes will be created for the init list and the symbol database will not mark it as a scope. I am not sure if this is the correct approach as I dont really understand how the AST part works. It did change the AST for `try {} catch (...) {}` but that is because it incorrectly treats `try {}` as an initializer list.
This commit is contained in:
parent
a3efe4e03c
commit
a90caa7e5a
|
@ -1051,6 +1051,18 @@ std::vector<const Token *> getArguments(const Token *ftok)
|
||||||
return arguments;
|
return arguments;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const Token *findLambdaStartToken(const Token *last)
|
||||||
|
{
|
||||||
|
if (!last || last->str() != "}")
|
||||||
|
return nullptr;
|
||||||
|
const Token* tok = last->link();
|
||||||
|
if (Token::simpleMatch(tok->astParent(), "("))
|
||||||
|
tok = tok->astParent();
|
||||||
|
if (Token::simpleMatch(tok->astParent(), "["))
|
||||||
|
return tok->astParent();
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
const Token *findLambdaEndToken(const Token *first)
|
const Token *findLambdaEndToken(const Token *first)
|
||||||
{
|
{
|
||||||
if (!first || first->str() != "[")
|
if (!first || first->str() != "[")
|
||||||
|
|
|
@ -146,6 +146,8 @@ int numberOfArguments(const Token *start);
|
||||||
*/
|
*/
|
||||||
std::vector<const Token *> getArguments(const Token *ftok);
|
std::vector<const Token *> getArguments(const Token *ftok);
|
||||||
|
|
||||||
|
const Token *findLambdaStartToken(const Token *last);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* find lambda function end token
|
* find lambda function end token
|
||||||
* \param first The [ token
|
* \param first The [ token
|
||||||
|
|
|
@ -878,7 +878,8 @@ std::string Library::getFunctionName(const Token *ftok) const
|
||||||
// Lookup function name using AST..
|
// Lookup function name using AST..
|
||||||
if (ftok->astParent()) {
|
if (ftok->astParent()) {
|
||||||
bool error = false;
|
bool error = false;
|
||||||
const std::string ret = getFunctionName(ftok->next()->astOperand1(), &error);
|
const Token * tok = ftok->astParent()->isUnaryOp("&") ? ftok->astParent()->astOperand1() : ftok->next()->astOperand1();
|
||||||
|
const std::string ret = getFunctionName(tok, &error);
|
||||||
return error ? std::string() : ret;
|
return error ? std::string() : ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -80,6 +80,27 @@ static const Token* skipScopeIdentifiers(const Token* tok)
|
||||||
return tok;
|
return tok;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool isExecutableScope(const Token* tok)
|
||||||
|
{
|
||||||
|
if (!Token::simpleMatch(tok, "{"))
|
||||||
|
return false;
|
||||||
|
const Token * tok2 = tok->link()->previous();
|
||||||
|
if (Token::simpleMatch(tok2, "; }"))
|
||||||
|
return true;
|
||||||
|
if (Token::Match(tok2, "{|} }")) {
|
||||||
|
const Token* startTok = tok2->str() == "{" ? tok2 : tok2->link();
|
||||||
|
if (Token::Match(startTok->previous(), "do|try|else {"))
|
||||||
|
return true;
|
||||||
|
if (Token::simpleMatch(startTok->previous(), ") {"))
|
||||||
|
return !findLambdaStartToken(tok2);
|
||||||
|
if (tok->str() == "{")
|
||||||
|
return false;
|
||||||
|
else
|
||||||
|
return isExecutableScope(startTok);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void SymbolDatabase::createSymbolDatabaseFindAllScopes()
|
void SymbolDatabase::createSymbolDatabaseFindAllScopes()
|
||||||
{
|
{
|
||||||
// create global scope
|
// create global scope
|
||||||
|
@ -650,7 +671,7 @@ void SymbolDatabase::createSymbolDatabaseFindAllScopes()
|
||||||
scope = &scopeList.back();
|
scope = &scopeList.back();
|
||||||
tok = lambdaStartToken;
|
tok = lambdaStartToken;
|
||||||
} else if (tok->str() == "{") {
|
} else if (tok->str() == "{") {
|
||||||
if (!Token::Match(tok->previous(), "=|,|(|return") && !(tok->strAt(-1) == ")" && Token::Match(tok->linkAt(-1)->previous(), "=|,|(|return"))) {
|
if (isExecutableScope(tok)) {
|
||||||
scopeList.emplace_back(this, tok, scope, Scope::eUnconditional, tok);
|
scopeList.emplace_back(this, tok, scope, Scope::eUnconditional, tok);
|
||||||
scope->nestedList.push_back(&scopeList.back());
|
scope->nestedList.push_back(&scopeList.back());
|
||||||
scope = &scopeList.back();
|
scope = &scopeList.back();
|
||||||
|
|
|
@ -483,6 +483,8 @@ static bool iscpp11init(const Token * const tok)
|
||||||
endtok = nameToken->linkAt(1)->linkAt(1);
|
endtok = nameToken->linkAt(1)->linkAt(1);
|
||||||
else
|
else
|
||||||
return false;
|
return false;
|
||||||
|
if (Token::Match(nameToken, "else|try|do"))
|
||||||
|
return false;
|
||||||
// There is no initialisation for example here: 'class Fred {};'
|
// There is no initialisation for example here: 'class Fred {};'
|
||||||
if (!Token::simpleMatch(endtok, "} ;"))
|
if (!Token::simpleMatch(endtok, "} ;"))
|
||||||
return true;
|
return true;
|
||||||
|
@ -1223,6 +1225,12 @@ static Token * createAstAtToken(Token *tok, bool cpp)
|
||||||
return endToken->previous();
|
return endToken->previous();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (cpp && tok->str() == "{" && iscpp11init(tok)) {
|
||||||
|
AST_state state(cpp);
|
||||||
|
compileExpression(tok, state);
|
||||||
|
return tok;
|
||||||
|
}
|
||||||
|
|
||||||
return tok;
|
return tok;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -34,6 +34,7 @@ private:
|
||||||
|
|
||||||
void run() OVERRIDE {
|
void run() OVERRIDE {
|
||||||
TEST_CASE(findLambdaEndToken);
|
TEST_CASE(findLambdaEndToken);
|
||||||
|
TEST_CASE(findLambdaStartToken);
|
||||||
TEST_CASE(isReturnScope);
|
TEST_CASE(isReturnScope);
|
||||||
TEST_CASE(isVariableChanged);
|
TEST_CASE(isVariableChanged);
|
||||||
TEST_CASE(isVariableChangedByFunctionCall);
|
TEST_CASE(isVariableChangedByFunctionCall);
|
||||||
|
@ -53,23 +54,55 @@ private:
|
||||||
ASSERT(nullptr == ::findLambdaEndToken(nullptr));
|
ASSERT(nullptr == ::findLambdaEndToken(nullptr));
|
||||||
ASSERT_EQUALS(false, findLambdaEndToken("void f() { }"));
|
ASSERT_EQUALS(false, findLambdaEndToken("void f() { }"));
|
||||||
ASSERT_EQUALS(true, findLambdaEndToken("[]{ }"));
|
ASSERT_EQUALS(true, findLambdaEndToken("[]{ }"));
|
||||||
ASSERT_EQUALS(true, findLambdaEndToken("[]{ return 0 }"));
|
ASSERT_EQUALS(true, findLambdaEndToken("[]{ return 0; }"));
|
||||||
ASSERT_EQUALS(true, findLambdaEndToken("[](){ }"));
|
ASSERT_EQUALS(true, findLambdaEndToken("[](){ }"));
|
||||||
ASSERT_EQUALS(true, findLambdaEndToken("[&](){ }"));
|
ASSERT_EQUALS(true, findLambdaEndToken("[&](){ }"));
|
||||||
ASSERT_EQUALS(true, findLambdaEndToken("[&, i](){ }"));
|
ASSERT_EQUALS(true, findLambdaEndToken("[&, i](){ }"));
|
||||||
ASSERT_EQUALS(true, findLambdaEndToken("[](void) { return -1 }"));
|
ASSERT_EQUALS(true, findLambdaEndToken("[](void) { return -1; }"));
|
||||||
ASSERT_EQUALS(true, findLambdaEndToken("[](int a, int b) { return a + b }"));
|
ASSERT_EQUALS(true, findLambdaEndToken("[](int a, int b) { return a + b; }"));
|
||||||
ASSERT_EQUALS(true, findLambdaEndToken("[](int a, int b) mutable { return a + b }"));
|
ASSERT_EQUALS(true, findLambdaEndToken("[](int a, int b) mutable { return a + b; }"));
|
||||||
ASSERT_EQUALS(true, findLambdaEndToken("[](int a, int b) constexpr { return a + b }"));
|
ASSERT_EQUALS(true, findLambdaEndToken("[](int a, int b) constexpr { return a + b; }"));
|
||||||
ASSERT_EQUALS(true, findLambdaEndToken("[](void) -> int { return -1 }"));
|
ASSERT_EQUALS(true, findLambdaEndToken("[](void) -> int { return -1; }"));
|
||||||
ASSERT_EQUALS(true, findLambdaEndToken("[](void) mutable -> int { return -1 }"));
|
ASSERT_EQUALS(true, findLambdaEndToken("[](void) mutable -> int { return -1; }"));
|
||||||
ASSERT_EQUALS(false, findLambdaEndToken("[](void) foo -> int { return -1 }"));
|
ASSERT_EQUALS(false, findLambdaEndToken("[](void) foo -> int { return -1; }"));
|
||||||
ASSERT_EQUALS(true, findLambdaEndToken("[](void) constexpr -> int { return -1 }"));
|
ASSERT_EQUALS(true, findLambdaEndToken("[](void) constexpr -> int { return -1; }"));
|
||||||
ASSERT_EQUALS(true, findLambdaEndToken("[](void) constexpr -> int* { return x }"));
|
ASSERT_EQUALS(true, findLambdaEndToken("[](void) constexpr -> int* { return x; }"));
|
||||||
ASSERT_EQUALS(true, findLambdaEndToken("[](void) constexpr -> const * int { return x }"));
|
ASSERT_EQUALS(true, findLambdaEndToken("[](void) constexpr -> const * int { return x; }"));
|
||||||
ASSERT_EQUALS(true, findLambdaEndToken("[](void) mutable -> const * int { return x }"));
|
ASSERT_EQUALS(true, findLambdaEndToken("[](void) mutable -> const * int { return x; }"));
|
||||||
ASSERT_EQUALS(true, findLambdaEndToken("[](void) constexpr -> const ** int { return x }"));
|
ASSERT_EQUALS(true, findLambdaEndToken("[](void) constexpr -> const ** int { return x; }"));
|
||||||
ASSERT_EQUALS(true, findLambdaEndToken("[](void) constexpr -> const * const* int { return x }"));
|
ASSERT_EQUALS(true, findLambdaEndToken("[](void) constexpr -> const * const* int { return x; }"));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool findLambdaStartToken(const char code[]) {
|
||||||
|
Settings settings;
|
||||||
|
Tokenizer tokenizer(&settings, this);
|
||||||
|
std::istringstream istr(code);
|
||||||
|
tokenizer.tokenize(istr, "test.cpp");
|
||||||
|
const Token * const tokStart = ::findLambdaStartToken(tokenizer.list.back());
|
||||||
|
return tokStart && tokStart == tokenizer.list.front();
|
||||||
|
}
|
||||||
|
|
||||||
|
void findLambdaStartToken() {
|
||||||
|
ASSERT(nullptr == ::findLambdaStartToken(nullptr));
|
||||||
|
ASSERT_EQUALS(false, findLambdaStartToken("void f() { }"));
|
||||||
|
ASSERT_EQUALS(true, findLambdaStartToken("[]{ }"));
|
||||||
|
ASSERT_EQUALS(true, findLambdaStartToken("[]{ return 0; }"));
|
||||||
|
ASSERT_EQUALS(true, findLambdaStartToken("[](){ }"));
|
||||||
|
ASSERT_EQUALS(true, findLambdaStartToken("[&](){ }"));
|
||||||
|
ASSERT_EQUALS(true, findLambdaStartToken("[&, i](){ }"));
|
||||||
|
ASSERT_EQUALS(true, findLambdaStartToken("[](void) { return -1; }"));
|
||||||
|
ASSERT_EQUALS(true, findLambdaStartToken("[](int a, int b) { return a + b; }"));
|
||||||
|
ASSERT_EQUALS(true, findLambdaStartToken("[](int a, int b) mutable { return a + b; }"));
|
||||||
|
ASSERT_EQUALS(true, findLambdaStartToken("[](int a, int b) constexpr { return a + b; }"));
|
||||||
|
ASSERT_EQUALS(true, findLambdaStartToken("[](void) -> int { return -1; }"));
|
||||||
|
ASSERT_EQUALS(true, findLambdaStartToken("[](void) mutable -> int { return -1; }"));
|
||||||
|
ASSERT_EQUALS(false, findLambdaStartToken("[](void) foo -> int { return -1; }"));
|
||||||
|
ASSERT_EQUALS(true, findLambdaStartToken("[](void) constexpr -> int { return -1; }"));
|
||||||
|
ASSERT_EQUALS(true, findLambdaStartToken("[](void) constexpr -> int* { return x; }"));
|
||||||
|
ASSERT_EQUALS(true, findLambdaStartToken("[](void) constexpr -> const * int { return x; }"));
|
||||||
|
ASSERT_EQUALS(true, findLambdaStartToken("[](void) mutable -> const * int { return x; }"));
|
||||||
|
ASSERT_EQUALS(true, findLambdaStartToken("[](void) constexpr -> const ** int { return x; }"));
|
||||||
|
ASSERT_EQUALS(true, findLambdaStartToken("[](void) constexpr -> const * const* int { return x; }"));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isReturnScope(const char code[], int offset) {
|
bool isReturnScope(const char code[], int offset) {
|
||||||
|
|
|
@ -1168,6 +1168,13 @@ private:
|
||||||
"[test.cpp:4]: (warning) Return value of function testfunc2() is not used.\n"
|
"[test.cpp:4]: (warning) Return value of function testfunc2() is not used.\n"
|
||||||
"[test.cpp:8]: (warning) Return value of function TestStruct1.testfunc1() is not used.\n"
|
"[test.cpp:8]: (warning) Return value of function TestStruct1.testfunc1() is not used.\n"
|
||||||
"[test.cpp:9]: (warning) Return value of function TestStruct1.testfunc2() is not used.\n", errout.str());
|
"[test.cpp:9]: (warning) Return value of function TestStruct1.testfunc2() is not used.\n", errout.str());
|
||||||
|
|
||||||
|
// #9006
|
||||||
|
check("template <typename... a> uint8_t b(std::tuple<uint8_t> d) {\n"
|
||||||
|
" std::tuple<a...> c{std::move(d)};\n"
|
||||||
|
" return std::get<0>(c);\n"
|
||||||
|
"}\n");
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void memsetZeroBytes() {
|
void memsetZeroBytes() {
|
||||||
|
|
|
@ -2215,8 +2215,7 @@ private:
|
||||||
|
|
||||||
void simplifyTypedef106() { // ticket #3619 (segmentation fault)
|
void simplifyTypedef106() { // ticket #3619 (segmentation fault)
|
||||||
const char code[] = "typedef void f ();\ntypedef { f }";
|
const char code[] = "typedef void f ();\ntypedef { f }";
|
||||||
tok(code);
|
ASSERT_THROW(tok(code), InternalError);
|
||||||
ASSERT_EQUALS("", errout.str());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void simplifyTypedef107() { // ticket #3963 (bad code => segmentation fault)
|
void simplifyTypedef107() { // ticket #3963 (bad code => segmentation fault)
|
||||||
|
|
|
@ -7076,7 +7076,7 @@ private:
|
||||||
|
|
||||||
ASSERT_EQUALS("abc.1:?1+bd.1:?+=", testAst("a =(b.c ? : 1) + 1 + (b.d ? : 1);"));
|
ASSERT_EQUALS("abc.1:?1+bd.1:?+=", testAst("a =(b.c ? : 1) + 1 + (b.d ? : 1);"));
|
||||||
|
|
||||||
ASSERT_EQUALS("try{ catch.(", testAst("try {} catch (...) {}"));
|
ASSERT_EQUALS("catch.(", testAst("try {} catch (...) {}"));
|
||||||
|
|
||||||
ASSERT_EQUALS("FooBar(", testAst("void Foo(Bar&);"));
|
ASSERT_EQUALS("FooBar(", testAst("void Foo(Bar&);"));
|
||||||
ASSERT_EQUALS("FooBar(", testAst("void Foo(Bar& &);")); // Rvalue reference - simplified from && to & & by real tokenizer
|
ASSERT_EQUALS("FooBar(", testAst("void Foo(Bar& &);")); // Rvalue reference - simplified from && to & & by real tokenizer
|
||||||
|
|
Loading…
Reference in New Issue