Fix 10588: crash (#3691)

This commit is contained in:
Paul Fultz II 2022-01-16 05:33:31 -06:00 committed by GitHub
parent 9220c8175d
commit 4af98f21d6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 48 additions and 0 deletions

View File

@ -1704,6 +1704,11 @@ bool SymbolDatabase::isFunction(const Token *tok, const Scope* outerScope, const
while (Token::Match(tok1, "%type%|*|&") && !endsWith(tok1->str(), ':') && (!isReservedName(tok1->str()) || tok1->str() == "const")) while (Token::Match(tok1, "%type%|*|&") && !endsWith(tok1->str(), ':') && (!isReservedName(tok1->str()) || tok1->str() == "const"))
tok1 = tok1->previous(); tok1 = tok1->previous();
// skip over decltype
if (Token::simpleMatch(tok1, ")") && tok1->link() &&
Token::simpleMatch(tok1->link()->previous(), "decltype ("))
tok1 = tok1->link()->tokAt(-2);
// skip over template // skip over template
if (tok1 && tok1->str() == ">") { if (tok1 && tok1->str() == ">") {
if (tok1->link()) if (tok1->link())
@ -1730,6 +1735,9 @@ bool SymbolDatabase::isFunction(const Token *tok, const Scope* outerScope, const
tok1 = tok1->previous(); tok1 = tok1->previous();
else if (tok1 && tok1->str() == ">" && tok1->link() && Token::Match(tok1->link()->previous(), "%name%")) else if (tok1 && tok1->str() == ">" && tok1->link() && Token::Match(tok1->link()->previous(), "%name%"))
tok1 = tok1->link()->tokAt(-2); tok1 = tok1->link()->tokAt(-2);
else if (Token::simpleMatch(tok1, ")") && tok1->link() &&
Token::simpleMatch(tok1->link()->previous(), "decltype ("))
tok1 = tok1->link()->tokAt(-2);
} }
// skip over modifiers and other stuff // skip over modifiers and other stuff
@ -2348,6 +2356,11 @@ const Token *Function::setFlags(const Token *tok1, const Scope *scope)
isConstexpr(true); isConstexpr(true);
} }
// decltype
else if (tok1->str() == ")" && Token::simpleMatch(tok1->link()->previous(), "decltype (")) {
tok1 = tok1->link()->previous();
}
// Function template // Function template
else if (tok1->link() && tok1->str() == ">" && Token::simpleMatch(tok1->link()->previous(), "template <")) { else if (tok1->link() && tok1->str() == ">" && Token::simpleMatch(tok1->link()->previous(), "template <")) {
templateDef = tok1->link()->previous(); templateDef = tok1->link()->previous();

View File

@ -192,6 +192,7 @@ private:
TEST_CASE(hasMissingInlineClassFunction); TEST_CASE(hasMissingInlineClassFunction);
TEST_CASE(hasClassFunction); TEST_CASE(hasClassFunction);
TEST_CASE(hasClassFunction_trailingReturnType); TEST_CASE(hasClassFunction_trailingReturnType);
TEST_CASE(hasClassFunction_decltype_auto);
TEST_CASE(hasRegularFunctionReturningFunctionPointer); TEST_CASE(hasRegularFunctionReturningFunctionPointer);
TEST_CASE(hasInlineClassFunctionReturningFunctionPointer); TEST_CASE(hasInlineClassFunctionReturningFunctionPointer);
@ -1629,6 +1630,28 @@ private:
ASSERT(function && function->functionScope == scope && scope->function == function && function->nestedIn == db->findScopeByName("Fred")); ASSERT(function && function->functionScope == scope && scope->function == function && function->nestedIn == db->findScopeByName("Fred"));
} }
void hasClassFunction_decltype_auto()
{
GET_SYMBOL_DB("struct d { decltype(auto) f() {} };");
// 3 scopes: Global, Class, and Function
ASSERT(db && db->scopeList.size() == 3);
const Token* const functionToken = Token::findsimplematch(tokenizer.tokens(), "f");
const Scope* scope = findFunctionScopeByToken(db, functionToken);
ASSERT(scope && scope->className == "f");
ASSERT(scope->functionOf && scope->functionOf == db->findScopeByName("d"));
const Function* function = findFunctionByName("f", &db->scopeList.back());
ASSERT(function && function->token->str() == "f");
ASSERT(function && function->token == functionToken);
ASSERT(function && function->hasBody());
}
void hasRegularFunctionReturningFunctionPointer() { void hasRegularFunctionReturningFunctionPointer() {
GET_SYMBOL_DB("void (*func(int f))(char) { }"); GET_SYMBOL_DB("void (*func(int f))(char) { }");

View File

@ -6185,6 +6185,18 @@ private:
" } while (last > 0);\n" " } while (last > 0);\n"
"}\n"; "}\n";
valueOfTok(code, "last"); valueOfTok(code, "last");
code = "struct a {\n"
" void clear();\n"
" int b();\n"
"};\n"
"struct d {\n"
" void c(int);\n"
" decltype(auto) f() { c(0 != e.b()); }\n"
" a e;\n"
"};\n"
"void d::c(int) { e.clear(); }\n";
valueOfTok(code, "e");
} }
void valueFlowHang() { void valueFlowHang() {