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;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
if (!first || first->str() != "[")
|
||||
|
|
|
@ -146,6 +146,8 @@ int numberOfArguments(const Token *start);
|
|||
*/
|
||||
std::vector<const Token *> getArguments(const Token *ftok);
|
||||
|
||||
const Token *findLambdaStartToken(const Token *last);
|
||||
|
||||
/**
|
||||
* find lambda function end token
|
||||
* \param first The [ token
|
||||
|
|
|
@ -878,7 +878,8 @@ std::string Library::getFunctionName(const Token *ftok) const
|
|||
// Lookup function name using AST..
|
||||
if (ftok->astParent()) {
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -80,6 +80,27 @@ static const Token* skipScopeIdentifiers(const Token* 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()
|
||||
{
|
||||
// create global scope
|
||||
|
@ -650,7 +671,7 @@ void SymbolDatabase::createSymbolDatabaseFindAllScopes()
|
|||
scope = &scopeList.back();
|
||||
tok = lambdaStartToken;
|
||||
} 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);
|
||||
scope->nestedList.push_back(&scopeList.back());
|
||||
scope = &scopeList.back();
|
||||
|
|
|
@ -483,6 +483,8 @@ static bool iscpp11init(const Token * const tok)
|
|||
endtok = nameToken->linkAt(1)->linkAt(1);
|
||||
else
|
||||
return false;
|
||||
if (Token::Match(nameToken, "else|try|do"))
|
||||
return false;
|
||||
// There is no initialisation for example here: 'class Fred {};'
|
||||
if (!Token::simpleMatch(endtok, "} ;"))
|
||||
return true;
|
||||
|
@ -1223,6 +1225,12 @@ static Token * createAstAtToken(Token *tok, bool cpp)
|
|||
return endToken->previous();
|
||||
}
|
||||
|
||||
if (cpp && tok->str() == "{" && iscpp11init(tok)) {
|
||||
AST_state state(cpp);
|
||||
compileExpression(tok, state);
|
||||
return tok;
|
||||
}
|
||||
|
||||
return tok;
|
||||
}
|
||||
|
||||
|
|
|
@ -34,6 +34,7 @@ private:
|
|||
|
||||
void run() OVERRIDE {
|
||||
TEST_CASE(findLambdaEndToken);
|
||||
TEST_CASE(findLambdaStartToken);
|
||||
TEST_CASE(isReturnScope);
|
||||
TEST_CASE(isVariableChanged);
|
||||
TEST_CASE(isVariableChangedByFunctionCall);
|
||||
|
@ -53,23 +54,55 @@ private:
|
|||
ASSERT(nullptr == ::findLambdaEndToken(nullptr));
|
||||
ASSERT_EQUALS(false, findLambdaEndToken("void f() { }"));
|
||||
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("[&, i](){ }"));
|
||||
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) mutable { 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) mutable -> 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 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) constexpr -> const ** int { return x }"));
|
||||
ASSERT_EQUALS(true, findLambdaEndToken("[](void) constexpr -> const * const* int { return x }"));
|
||||
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) mutable { 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) mutable -> 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 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) constexpr -> 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) {
|
||||
|
|
|
@ -1168,6 +1168,13 @@ private:
|
|||
"[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: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() {
|
||||
|
|
|
@ -2215,8 +2215,7 @@ private:
|
|||
|
||||
void simplifyTypedef106() { // ticket #3619 (segmentation fault)
|
||||
const char code[] = "typedef void f ();\ntypedef { f }";
|
||||
tok(code);
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
ASSERT_THROW(tok(code), InternalError);
|
||||
}
|
||||
|
||||
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("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& &);")); // Rvalue reference - simplified from && to & & by real tokenizer
|
||||
|
|
Loading…
Reference in New Issue