parent
91dedf05b5
commit
9b892f3239
|
@ -2447,7 +2447,7 @@ Function::Function(const Tokenizer *mTokenizer,
|
||||||
const Token *tok1 = setFlags(tok, scope);
|
const Token *tok1 = setFlags(tok, scope);
|
||||||
|
|
||||||
// find the return type
|
// find the return type
|
||||||
if (!isConstructor() && !isDestructor() && !isLambda()) {
|
if (!isConstructor() && !isDestructor()) {
|
||||||
// @todo auto type deduction should be checked
|
// @todo auto type deduction should be checked
|
||||||
// @todo attributes and exception specification can also precede trailing return type
|
// @todo attributes and exception specification can also precede trailing return type
|
||||||
if (Token::Match(argDef->link()->next(), "const|volatile| &|&&| .")) { // 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);
|
retDef = argDef->link()->tokAt(3);
|
||||||
else if (argDef->link()->strAt(3) == ".")
|
else if (argDef->link()->strAt(3) == ".")
|
||||||
retDef = argDef->link()->tokAt(4);
|
retDef = argDef->link()->tokAt(4);
|
||||||
} else {
|
} else if (!isLambda()) {
|
||||||
if (tok1->str() == ">")
|
if (tok1->str() == ">")
|
||||||
tok1 = tok1->next();
|
tok1 = tok1->next();
|
||||||
while (Token::Match(tok1, "extern|virtual|static|friend|struct|union|enum"))
|
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;
|
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)
|
void SymbolDatabase::setValueTypeInTokenList(bool reportDebugWarnings, Token *tokens)
|
||||||
{
|
{
|
||||||
if (!tokens)
|
if (!tokens)
|
||||||
|
@ -7012,10 +7029,10 @@ void SymbolDatabase::setValueTypeInTokenList(bool reportDebugWarnings, Token *to
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// function
|
// function or lambda
|
||||||
else if (tok->previous() && tok->previous()->function() && tok->previous()->function()->retDef) {
|
else if (const Function* f = getFunction(tok->previous())) {
|
||||||
ValueType valuetype;
|
ValueType valuetype;
|
||||||
if (parsedecl(tok->previous()->function()->retDef, &valuetype, mDefaultSignedness, mSettings, mIsCpp))
|
if (parsedecl(f->retDef, &valuetype, mDefaultSignedness, mSettings, mIsCpp))
|
||||||
setValueType(tok, valuetype);
|
setValueType(tok, valuetype);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -735,11 +735,6 @@ static void compileTerm(Token *&tok, AST_state& state)
|
||||||
tok = tok->next();
|
tok = tok->next();
|
||||||
else
|
else
|
||||||
throw InternalError(tok, "Syntax error. Unexpected tokens in designated initializer.", InternalError::AST);
|
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%|*|&|::|(|[")) {
|
} else if (!state.cpp || !Token::Match(tok, "new|delete %name%|*|&|::|(|[")) {
|
||||||
std::vector<Token*> inner;
|
std::vector<Token*> inner;
|
||||||
|
|
|
@ -119,6 +119,16 @@ private:
|
||||||
std::istringstream istr(code);
|
std::istringstream istr(code);
|
||||||
ASSERT_LOC(tokenizer.tokenize(istr, filename), file, line);
|
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);
|
runChecks<CheckFunctions>(&tokenizer, settings_, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1819,6 +1829,7 @@ private:
|
||||||
void checkLibraryMatchFunctions() {
|
void checkLibraryMatchFunctions() {
|
||||||
Settings s = settingsBuilder(settings).checkLibrary().build();
|
Settings s = settingsBuilder(settings).checkLibrary().build();
|
||||||
s.daca = true;
|
s.daca = true;
|
||||||
|
s.debugwarnings = true;
|
||||||
|
|
||||||
check("void f() {\n"
|
check("void f() {\n"
|
||||||
" lib_func();"
|
" lib_func();"
|
||||||
|
@ -1934,6 +1945,8 @@ private:
|
||||||
" q->push_back(1);\n"
|
" q->push_back(1);\n"
|
||||||
"}\n", "test.cpp", &s);
|
"}\n", "test.cpp", &s);
|
||||||
TODO_ASSERT_EQUALS("",
|
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: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",
|
"[test.cpp:5]: (information) --check-library: There is no matching configuration for function auto::push_back()\n",
|
||||||
errout.str());
|
errout.str());
|
||||||
|
@ -1949,7 +1962,9 @@ private:
|
||||||
check("auto f() {\n"
|
check("auto f() {\n"
|
||||||
" return std::runtime_error(\"abc\");\n"
|
" return std::runtime_error(\"abc\");\n"
|
||||||
"}\n", "test.cpp", &s);
|
"}\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
|
check("struct S {\n" // #11543
|
||||||
" S() {}\n"
|
" S() {}\n"
|
||||||
|
@ -2007,6 +2022,16 @@ private:
|
||||||
" void f(int i) { push_back(i); }\n"
|
" void f(int i) { push_back(i); }\n"
|
||||||
"};\n", "test.cpp", &s);
|
"};\n", "test.cpp", &s);
|
||||||
ASSERT_EQUALS("", errout.str());
|
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() {
|
void checkUseStandardLibrary1() {
|
||||||
|
|
|
@ -6336,6 +6336,7 @@ private:
|
||||||
ASSERT_EQUALS("var{{,{{,{", testAst("auto var{ {{},{}}, {} };"));
|
ASSERT_EQUALS("var{{,{{,{", testAst("auto var{ {{},{}}, {} };"));
|
||||||
ASSERT_EQUALS("fXYabcfalse==CD:?,{,{(", testAst("f({X, {Y, abc == false ? C : D}});"));
|
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("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
|
// Initialization with decltype(expr) instead of a type
|
||||||
ASSERT_EQUALS("decltypex((", testAst("decltype(x)();"));
|
ASSERT_EQUALS("decltypex((", testAst("decltype(x)();"));
|
||||||
|
|
|
@ -6611,7 +6611,7 @@ private:
|
||||||
ASSERT_EQUALS("", isKnownContainerSizeValue(tokenValues(code, "( ) ;"), 0));
|
ASSERT_EQUALS("", isKnownContainerSizeValue(tokenValues(code, "( ) ;"), 0));
|
||||||
|
|
||||||
code = "std::vector<int> f() { return std::vector<int>{}; }";
|
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 {}; }";
|
code = "std::vector<int> f() { return {}; }";
|
||||||
ASSERT_EQUALS("", isKnownContainerSizeValue(tokenValues(code, "{ } ;"), 0));
|
ASSERT_EQUALS("", isKnownContainerSizeValue(tokenValues(code, "{ } ;"), 0));
|
||||||
|
|
Loading…
Reference in New Issue