Handle auto as first token, set varid (#4991)

* Handle auto as first token

* Set varid when initialized by function

* Fix TODO from #11444

* Fix function parsing

* Add parentheses

* Format
This commit is contained in:
chrchr-github 2023-04-21 10:13:25 +02:00 committed by GitHub
parent 2364ff9765
commit a4e224b65c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 61 additions and 22 deletions

View File

@ -6198,9 +6198,9 @@ void SymbolDatabase::setValueType(Token* tok, const ValueType& valuetype, Source
Token::Match(parent->tokAt(-1), "%var% ="))) {
Token *var1Tok = parent->strAt(-2) == ";" ? parent->tokAt(-3) : parent->tokAt(-1);
Token *autoTok = nullptr;
if (Token::Match(var1Tok->tokAt(-2), ";|{|}|(|const|constexpr auto"))
if (Token::simpleMatch(var1Tok->tokAt(-1), "auto"))
autoTok = var1Tok->previous();
else if (Token::Match(var1Tok->tokAt(-3), ";|{|}|(|const|constexpr auto *|&|&&"))
else if (Token::Match(var1Tok->tokAt(-2), "auto *|&|&&"))
autoTok = var1Tok->tokAt(-2);
if (autoTok) {
ValueType vt(*vt2);

View File

@ -4574,7 +4574,7 @@ void Tokenizer::setVarIdPass1()
continue;
if (tok3->isLiteral() ||
(tok3->isName() && variableMap.hasVariable(tok3->str())) ||
(tok3->isName() && (variableMap.hasVariable(tok3->str()) || (tok3->strAt(-1) == "(" && Token::simpleMatch(tok3->next(), "(")))) ||
tok3->isOp() ||
tok3->str() == "(" ||
notstart.find(tok3->str()) != notstart.end()) {
@ -4786,7 +4786,11 @@ static Token * matchMemberName(const Member &member, const std::list<ScopeInfo2>
static Token * matchMemberVarName(const Member &var, const std::list<ScopeInfo2> &scopeInfo)
{
Token *tok = matchMemberName(var, scopeInfo);
return Token::Match(tok, "%name% !!(") ? tok : nullptr;
if (Token::Match(tok, "%name%")) {
if (!tok->next() || tok->strAt(1) != "(" || (tok->tokAt(2) && tok->tokAt(2)->isLiteral()))
return tok;
}
return nullptr;
}
static Token * matchMemberFunctionName(const Member &func, const std::list<ScopeInfo2> &scopeInfo)
@ -4854,7 +4858,7 @@ void Tokenizer::setVarIdPass2()
}
if (!tok->next())
syntaxError(tok);
if (Token::Match(tok, "%name% ("))
if (Token::Match(tok, "%name% (") && !(tok->tokAt(2) && tok->tokAt(2)->isLiteral()))
allMemberFunctions.emplace_back(scope, usingnamespaces, tok1);
else
allMemberVars.emplace_back(scope, usingnamespaces, tok1);

View File

@ -5262,7 +5262,7 @@ private:
void createSymbolDatabaseFindAllScopes5()
{
GET_SYMBOL_DB("class C {\n"
GET_SYMBOL_DB("class C {\n" // #11444
"public:\n"
" template<typename T>\n"
" class D;\n"
@ -5282,7 +5282,12 @@ private:
ASSERT(db);
ASSERT_EQUALS(6, db->scopeList.size());
const Token* const var = Token::findsimplematch(tokenizer.tokens(), "IN (");
TODO_ASSERT(var && var->variable());
ASSERT(var && var->variable());
ASSERT_EQUALS(var->variable()->name(), "IN");
auto it = db->scopeList.begin();
std::advance(it, 4);
ASSERT_EQUALS(it->className, "S");
ASSERT_EQUALS(var->variable()->scope(), &*it);
}
void createSymbolDatabaseFindAllScopes6()
@ -7686,23 +7691,35 @@ private:
}
void executableScopeWithUnknownFunction() {
GET_SYMBOL_DB("class Fred {\n"
" void foo(const std::string & a = \"\");\n"
"};\n"
"Fred::foo(const std::string & b) { }");
{
GET_SYMBOL_DB("class Fred {\n"
" void foo(const std::string & a = \"\");\n"
"};\n"
"Fred::foo(const std::string & b) { }");
ASSERT(db && db->scopeList.size() == 3);
std::list<Scope>::const_iterator scope = db->scopeList.cbegin();
ASSERT_EQUALS(Scope::eGlobal, scope->type);
++scope;
ASSERT_EQUALS(Scope::eClass, scope->type);
const Scope * class_scope = &*scope;
++scope;
ASSERT(class_scope->functionList.size() == 1);
ASSERT(class_scope->functionList.cbegin()->hasBody());
ASSERT(class_scope->functionList.cbegin()->functionScope == &*scope);
ASSERT(db && db->scopeList.size() == 3);
std::list<Scope>::const_iterator scope = db->scopeList.cbegin();
ASSERT_EQUALS(Scope::eGlobal, scope->type);
++scope;
ASSERT_EQUALS(Scope::eClass, scope->type);
const Scope* class_scope = &*scope;
++scope;
ASSERT(class_scope->functionList.size() == 1);
ASSERT(class_scope->functionList.cbegin()->hasBody());
ASSERT(class_scope->functionList.cbegin()->functionScope == &*scope);
}
{
GET_SYMBOL_DB("bool f(bool (*g)(int));\n"
"bool f(bool (*g)(int)) { return g(0); }\n");
ASSERT(db && db->scopeList.size() == 2);
std::list<Scope>::const_iterator scope = db->scopeList.cbegin();
ASSERT_EQUALS(Scope::eGlobal, scope->type);
ASSERT(scope->functionList.size() == 1);
++scope;
ASSERT_EQUALS(Scope::eFunction, scope->type);
}
}
#define typeOf(...) typeOf_(__FILE__, __LINE__, __VA_ARGS__)
std::string typeOf_(const char* file, int line, const char code[], const char pattern[], const char filename[] = "test.cpp", const Settings *settings = nullptr) {
Tokenizer tokenizer(settings ? settings : &settings2, this);
@ -8375,6 +8392,15 @@ private:
ASSERT(tok->variable() && tok->variable()->valueType());
ASSERT_EQUALS("signed int * const &", tok->variable()->valueType()->str());
}
{
GET_SYMBOL_DB("auto a = 1;\n");
ASSERT_EQUALS("", errout.str());
const Token* tok = tokenizer.tokens();
tok = Token::findsimplematch(tok, "auto");
ASSERT(tok && tok->valueType());
ASSERT_EQUALS("signed int", tok->valueType()->str());
}
}
void valueTypeThis() {

View File

@ -102,6 +102,7 @@ private:
TEST_CASE(varid63);
TEST_CASE(varid64); // #9928 - extern const char (*x[256])
TEST_CASE(varid65); // #10936
TEST_CASE(varid66);
TEST_CASE(varid_for_1);
TEST_CASE(varid_for_2);
TEST_CASE(varid_cpp_keywords_in_c_code);
@ -1195,6 +1196,14 @@ private:
}
}
void varid66() {
const char code[] = "std::string g();\n"
"const std::string s(g() + \"abc\");\n";
const char expected[] = "1: std :: string g ( ) ;\n"
"2: const std :: string s@1 ( g ( ) + \"abc\" ) ;\n";
ASSERT_EQUALS(expected, tokenize(code));
}
void varid_for_1() {
const char code[] = "void foo(int a, int b) {\n"
" for (int a=1,b=2;;) {}\n"