Skip to content

Commit 9b892f3

Browse files
Partial fix for #11552 Handle lambda return types (danmar#5188)
1 parent 91dedf0 commit 9b892f3

File tree

5 files changed

+50
-12
lines changed

5 files changed

+50
-12
lines changed

lib/symboldatabase.cpp

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2447,7 +2447,7 @@ Function::Function(const Tokenizer *mTokenizer,
24472447
const Token *tok1 = setFlags(tok, scope);
24482448

24492449
// find the return type
2450-
if (!isConstructor() && !isDestructor() && !isLambda()) {
2450+
if (!isConstructor() && !isDestructor()) {
24512451
// @todo auto type deduction should be checked
24522452
// @todo attributes and exception specification can also precede trailing return type
24532453
if (Token::Match(argDef->link()->next(), "const|volatile| &|&&| .")) { // Trailing return type
@@ -2458,7 +2458,7 @@ Function::Function(const Tokenizer *mTokenizer,
24582458
retDef = argDef->link()->tokAt(3);
24592459
else if (argDef->link()->strAt(3) == ".")
24602460
retDef = argDef->link()->tokAt(4);
2461-
} else {
2461+
} else if (!isLambda()) {
24622462
if (tok1->str() == ">")
24632463
tok1 = tok1->next();
24642464
while (Token::Match(tok1, "extern|virtual|static|friend|struct|union|enum"))
@@ -6895,6 +6895,23 @@ static const Function *getOperatorFunction(const Token * const tok)
68956895
return nullptr;
68966896
}
68976897

6898+
static const Function* getFunction(const Token* tok) {
6899+
if (!tok)
6900+
return nullptr;
6901+
if (tok->function() && tok->function()->retDef)
6902+
return tok->function();
6903+
if (const Variable* lvar = tok->variable()) { // lambda
6904+
const Function* lambda{};
6905+
if (Token::Match(lvar->nameToken()->next(), "; %varid% = [", lvar->declarationId()))
6906+
lambda = lvar->nameToken()->tokAt(4)->function();
6907+
else if (Token::simpleMatch(lvar->nameToken()->next(), "{ ["))
6908+
lambda = lvar->nameToken()->tokAt(2)->function();
6909+
if (lambda && lambda->retDef)
6910+
return lambda;
6911+
}
6912+
return nullptr;
6913+
}
6914+
68986915
void SymbolDatabase::setValueTypeInTokenList(bool reportDebugWarnings, Token *tokens)
68996916
{
69006917
if (!tokens)
@@ -7012,10 +7029,10 @@ void SymbolDatabase::setValueTypeInTokenList(bool reportDebugWarnings, Token *to
70127029

70137030
}
70147031

7015-
// function
7016-
else if (tok->previous() && tok->previous()->function() && tok->previous()->function()->retDef) {
7032+
// function or lambda
7033+
else if (const Function* f = getFunction(tok->previous())) {
70177034
ValueType valuetype;
7018-
if (parsedecl(tok->previous()->function()->retDef, &valuetype, mDefaultSignedness, mSettings, mIsCpp))
7035+
if (parsedecl(f->retDef, &valuetype, mDefaultSignedness, mSettings, mIsCpp))
70197036
setValueType(tok, valuetype);
70207037
}
70217038

lib/tokenlist.cpp

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -735,11 +735,6 @@ static void compileTerm(Token *&tok, AST_state& state)
735735
tok = tok->next();
736736
else
737737
throw InternalError(tok, "Syntax error. Unexpected tokens in designated initializer.", InternalError::AST);
738-
} else if (Token::simpleMatch(tok, "{ }")) {
739-
tok->astOperand1(state.op.top());
740-
state.op.pop();
741-
state.op.push(tok);
742-
tok = tok->tokAt(2);
743738
}
744739
} else if (!state.cpp || !Token::Match(tok, "new|delete %name%|*|&|::|(|[")) {
745740
std::vector<Token*> inner;

test/testfunctions.cpp

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,16 @@ class TestFunctions : public TestFixture {
119119
std::istringstream istr(code);
120120
ASSERT_LOC(tokenizer.tokenize(istr, filename), file, line);
121121

122+
// filter out ValueFlow messages..
123+
const std::string debugwarnings = errout.str();
124+
errout.str("");
125+
std::istringstream istr2(debugwarnings);
126+
std::string errline;
127+
while (std::getline(istr2, errline)) {
128+
if (errline.find("valueflow.cpp") == std::string::npos)
129+
errout << errline << "\n";
130+
}
131+
122132
runChecks<CheckFunctions>(&tokenizer, settings_, this);
123133
}
124134

@@ -1819,6 +1829,7 @@ class TestFunctions : public TestFixture {
18191829
void checkLibraryMatchFunctions() {
18201830
Settings s = settingsBuilder(settings).checkLibrary().build();
18211831
s.daca = true;
1832+
s.debugwarnings = true;
18221833

18231834
check("void f() {\n"
18241835
" lib_func();"
@@ -1934,6 +1945,8 @@ class TestFunctions : public TestFixture {
19341945
" q->push_back(1);\n"
19351946
"}\n", "test.cpp", &s);
19361947
TODO_ASSERT_EQUALS("",
1948+
"[test.cpp:2]: (debug) auto token with no type.\n"
1949+
"[test.cpp:4]: (debug) auto token with no type.\n"
19371950
"[test.cpp:3]: (information) --check-library: There is no matching configuration for function auto::push_back()\n"
19381951
"[test.cpp:5]: (information) --check-library: There is no matching configuration for function auto::push_back()\n",
19391952
errout.str());
@@ -1949,7 +1962,9 @@ class TestFunctions : public TestFixture {
19491962
check("auto f() {\n"
19501963
" return std::runtime_error(\"abc\");\n"
19511964
"}\n", "test.cpp", &s);
1952-
ASSERT_EQUALS("", errout.str());
1965+
TODO_ASSERT_EQUALS("",
1966+
"[test.cpp:1]: (debug) auto token with no type.\n",
1967+
errout.str());
19531968

19541969
check("struct S {\n" // #11543
19551970
" S() {}\n"
@@ -2007,6 +2022,16 @@ class TestFunctions : public TestFixture {
20072022
" void f(int i) { push_back(i); }\n"
20082023
"};\n", "test.cpp", &s);
20092024
ASSERT_EQUALS("", errout.str());
2025+
2026+
check("void f() {\n"
2027+
" auto g = []() -> std::string { return \"abc\"; };\n"
2028+
" auto s = g();\n"
2029+
" if (s.at(0)) {}\n"
2030+
" auto h{ []() -> std::string { return \"xyz\"; } };\n"
2031+
" auto t = h();\n"
2032+
" if (t.at(0)) {}\n"
2033+
"};\n", "test.cpp", &s);
2034+
ASSERT_EQUALS("", errout.str());
20102035
}
20112036

20122037
void checkUseStandardLibrary1() {

test/testtokenize.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6336,6 +6336,7 @@ class TestTokenizer : public TestFixture {
63366336
ASSERT_EQUALS("var{{,{{,{", testAst("auto var{ {{},{}}, {} };"));
63376337
ASSERT_EQUALS("fXYabcfalse==CD:?,{,{(", testAst("f({X, {Y, abc == false ? C : D}});"));
63386338
ASSERT_EQUALS("stdvector::p0[{(return", testAst("return std::vector<int>({ p[0] });"));
6339+
ASSERT_EQUALS("vstdvector::{=", testAst("auto v = std::vector<int>{ };"));
63396340

63406341
// Initialization with decltype(expr) instead of a type
63416342
ASSERT_EQUALS("decltypex((", testAst("decltype(x)();"));

test/testvalueflow.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6611,7 +6611,7 @@ class TestValueFlow : public TestFixture {
66116611
ASSERT_EQUALS("", isKnownContainerSizeValue(tokenValues(code, "( ) ;"), 0));
66126612

66136613
code = "std::vector<int> f() { return std::vector<int>{}; }";
6614-
TODO_ASSERT_EQUALS("", "values.size():0", isKnownContainerSizeValue(tokenValues(code, "{ } ;"), 0));
6614+
ASSERT_EQUALS("", isKnownContainerSizeValue(tokenValues(code, "{ } ;"), 0));
66156615

66166616
code = "std::vector<int> f() { return {}; }";
66176617
ASSERT_EQUALS("", isKnownContainerSizeValue(tokenValues(code, "{ } ;"), 0));

0 commit comments

Comments
 (0)