Partial fix for #11552 Handle lambda return types (#5188)

This commit is contained in:
chrchr-github 2023-06-25 12:01:59 +02:00 committed by GitHub
parent 91dedf05b5
commit 9b892f3239
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 50 additions and 12 deletions

View File

@ -2447,7 +2447,7 @@ Function::Function(const Tokenizer *mTokenizer,
const Token *tok1 = setFlags(tok, scope);
// find the return type
if (!isConstructor() && !isDestructor() && !isLambda()) {
if (!isConstructor() && !isDestructor()) {
// @todo auto type deduction should be checked
// @todo attributes and exception specification can also precede trailing return type
if (Token::Match(argDef->link()->next(), "const|volatile| &|&&| .")) { // Trailing return type
@ -2458,7 +2458,7 @@ Function::Function(const Tokenizer *mTokenizer,
retDef = argDef->link()->tokAt(3);
else if (argDef->link()->strAt(3) == ".")
retDef = argDef->link()->tokAt(4);
} else {
} else if (!isLambda()) {
if (tok1->str() == ">")
tok1 = tok1->next();
while (Token::Match(tok1, "extern|virtual|static|friend|struct|union|enum"))
@ -6895,6 +6895,23 @@ static const Function *getOperatorFunction(const Token * const tok)
return nullptr;
}
static const Function* getFunction(const Token* tok) {
if (!tok)
return nullptr;
if (tok->function() && tok->function()->retDef)
return tok->function();
if (const Variable* lvar = tok->variable()) { // lambda
const Function* lambda{};
if (Token::Match(lvar->nameToken()->next(), "; %varid% = [", lvar->declarationId()))
lambda = lvar->nameToken()->tokAt(4)->function();
else if (Token::simpleMatch(lvar->nameToken()->next(), "{ ["))
lambda = lvar->nameToken()->tokAt(2)->function();
if (lambda && lambda->retDef)
return lambda;
}
return nullptr;
}
void SymbolDatabase::setValueTypeInTokenList(bool reportDebugWarnings, Token *tokens)
{
if (!tokens)
@ -7012,10 +7029,10 @@ void SymbolDatabase::setValueTypeInTokenList(bool reportDebugWarnings, Token *to
}
// function
else if (tok->previous() && tok->previous()->function() && tok->previous()->function()->retDef) {
// function or lambda
else if (const Function* f = getFunction(tok->previous())) {
ValueType valuetype;
if (parsedecl(tok->previous()->function()->retDef, &valuetype, mDefaultSignedness, mSettings, mIsCpp))
if (parsedecl(f->retDef, &valuetype, mDefaultSignedness, mSettings, mIsCpp))
setValueType(tok, valuetype);
}

View File

@ -735,11 +735,6 @@ static void compileTerm(Token *&tok, AST_state& state)
tok = tok->next();
else
throw InternalError(tok, "Syntax error. Unexpected tokens in designated initializer.", InternalError::AST);
} else if (Token::simpleMatch(tok, "{ }")) {
tok->astOperand1(state.op.top());
state.op.pop();
state.op.push(tok);
tok = tok->tokAt(2);
}
} else if (!state.cpp || !Token::Match(tok, "new|delete %name%|*|&|::|(|[")) {
std::vector<Token*> inner;

View File

@ -119,6 +119,16 @@ private:
std::istringstream istr(code);
ASSERT_LOC(tokenizer.tokenize(istr, filename), file, line);
// filter out ValueFlow messages..
const std::string debugwarnings = errout.str();
errout.str("");
std::istringstream istr2(debugwarnings);
std::string errline;
while (std::getline(istr2, errline)) {
if (errline.find("valueflow.cpp") == std::string::npos)
errout << errline << "\n";
}
runChecks<CheckFunctions>(&tokenizer, settings_, this);
}
@ -1819,6 +1829,7 @@ private:
void checkLibraryMatchFunctions() {
Settings s = settingsBuilder(settings).checkLibrary().build();
s.daca = true;
s.debugwarnings = true;
check("void f() {\n"
" lib_func();"
@ -1934,6 +1945,8 @@ private:
" q->push_back(1);\n"
"}\n", "test.cpp", &s);
TODO_ASSERT_EQUALS("",
"[test.cpp:2]: (debug) auto token with no type.\n"
"[test.cpp:4]: (debug) auto token with no type.\n"
"[test.cpp:3]: (information) --check-library: There is no matching configuration for function auto::push_back()\n"
"[test.cpp:5]: (information) --check-library: There is no matching configuration for function auto::push_back()\n",
errout.str());
@ -1949,7 +1962,9 @@ private:
check("auto f() {\n"
" return std::runtime_error(\"abc\");\n"
"}\n", "test.cpp", &s);
ASSERT_EQUALS("", errout.str());
TODO_ASSERT_EQUALS("",
"[test.cpp:1]: (debug) auto token with no type.\n",
errout.str());
check("struct S {\n" // #11543
" S() {}\n"
@ -2007,6 +2022,16 @@ private:
" void f(int i) { push_back(i); }\n"
"};\n", "test.cpp", &s);
ASSERT_EQUALS("", errout.str());
check("void f() {\n"
" auto g = []() -> std::string { return \"abc\"; };\n"
" auto s = g();\n"
" if (s.at(0)) {}\n"
" auto h{ []() -> std::string { return \"xyz\"; } };\n"
" auto t = h();\n"
" if (t.at(0)) {}\n"
"};\n", "test.cpp", &s);
ASSERT_EQUALS("", errout.str());
}
void checkUseStandardLibrary1() {

View File

@ -6336,6 +6336,7 @@ private:
ASSERT_EQUALS("var{{,{{,{", testAst("auto var{ {{},{}}, {} };"));
ASSERT_EQUALS("fXYabcfalse==CD:?,{,{(", testAst("f({X, {Y, abc == false ? C : D}});"));
ASSERT_EQUALS("stdvector::p0[{(return", testAst("return std::vector<int>({ p[0] });"));
ASSERT_EQUALS("vstdvector::{=", testAst("auto v = std::vector<int>{ };"));
// Initialization with decltype(expr) instead of a type
ASSERT_EQUALS("decltypex((", testAst("decltype(x)();"));

View File

@ -6611,7 +6611,7 @@ private:
ASSERT_EQUALS("", isKnownContainerSizeValue(tokenValues(code, "( ) ;"), 0));
code = "std::vector<int> f() { return std::vector<int>{}; }";
TODO_ASSERT_EQUALS("", "values.size():0", isKnownContainerSizeValue(tokenValues(code, "{ } ;"), 0));
ASSERT_EQUALS("", isKnownContainerSizeValue(tokenValues(code, "{ } ;"), 0));
code = "std::vector<int> f() { return {}; }";
ASSERT_EQUALS("", isKnownContainerSizeValue(tokenValues(code, "{ } ;"), 0));