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:
parent
2364ff9765
commit
a4e224b65c
|
@ -6198,9 +6198,9 @@ void SymbolDatabase::setValueType(Token* tok, const ValueType& valuetype, Source
|
||||||
Token::Match(parent->tokAt(-1), "%var% ="))) {
|
Token::Match(parent->tokAt(-1), "%var% ="))) {
|
||||||
Token *var1Tok = parent->strAt(-2) == ";" ? parent->tokAt(-3) : parent->tokAt(-1);
|
Token *var1Tok = parent->strAt(-2) == ";" ? parent->tokAt(-3) : parent->tokAt(-1);
|
||||||
Token *autoTok = nullptr;
|
Token *autoTok = nullptr;
|
||||||
if (Token::Match(var1Tok->tokAt(-2), ";|{|}|(|const|constexpr auto"))
|
if (Token::simpleMatch(var1Tok->tokAt(-1), "auto"))
|
||||||
autoTok = var1Tok->previous();
|
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);
|
autoTok = var1Tok->tokAt(-2);
|
||||||
if (autoTok) {
|
if (autoTok) {
|
||||||
ValueType vt(*vt2);
|
ValueType vt(*vt2);
|
||||||
|
|
|
@ -4574,7 +4574,7 @@ void Tokenizer::setVarIdPass1()
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (tok3->isLiteral() ||
|
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->isOp() ||
|
||||||
tok3->str() == "(" ||
|
tok3->str() == "(" ||
|
||||||
notstart.find(tok3->str()) != notstart.end()) {
|
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)
|
static Token * matchMemberVarName(const Member &var, const std::list<ScopeInfo2> &scopeInfo)
|
||||||
{
|
{
|
||||||
Token *tok = matchMemberName(var, 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)
|
static Token * matchMemberFunctionName(const Member &func, const std::list<ScopeInfo2> &scopeInfo)
|
||||||
|
@ -4854,7 +4858,7 @@ void Tokenizer::setVarIdPass2()
|
||||||
}
|
}
|
||||||
if (!tok->next())
|
if (!tok->next())
|
||||||
syntaxError(tok);
|
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);
|
allMemberFunctions.emplace_back(scope, usingnamespaces, tok1);
|
||||||
else
|
else
|
||||||
allMemberVars.emplace_back(scope, usingnamespaces, tok1);
|
allMemberVars.emplace_back(scope, usingnamespaces, tok1);
|
||||||
|
|
|
@ -5262,7 +5262,7 @@ private:
|
||||||
|
|
||||||
void createSymbolDatabaseFindAllScopes5()
|
void createSymbolDatabaseFindAllScopes5()
|
||||||
{
|
{
|
||||||
GET_SYMBOL_DB("class C {\n"
|
GET_SYMBOL_DB("class C {\n" // #11444
|
||||||
"public:\n"
|
"public:\n"
|
||||||
" template<typename T>\n"
|
" template<typename T>\n"
|
||||||
" class D;\n"
|
" class D;\n"
|
||||||
|
@ -5282,7 +5282,12 @@ private:
|
||||||
ASSERT(db);
|
ASSERT(db);
|
||||||
ASSERT_EQUALS(6, db->scopeList.size());
|
ASSERT_EQUALS(6, db->scopeList.size());
|
||||||
const Token* const var = Token::findsimplematch(tokenizer.tokens(), "IN (");
|
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()
|
void createSymbolDatabaseFindAllScopes6()
|
||||||
|
@ -7686,23 +7691,35 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
void executableScopeWithUnknownFunction() {
|
void executableScopeWithUnknownFunction() {
|
||||||
GET_SYMBOL_DB("class Fred {\n"
|
{
|
||||||
" void foo(const std::string & a = \"\");\n"
|
GET_SYMBOL_DB("class Fred {\n"
|
||||||
"};\n"
|
" void foo(const std::string & a = \"\");\n"
|
||||||
"Fred::foo(const std::string & b) { }");
|
"};\n"
|
||||||
|
"Fred::foo(const std::string & b) { }");
|
||||||
|
|
||||||
ASSERT(db && db->scopeList.size() == 3);
|
ASSERT(db && db->scopeList.size() == 3);
|
||||||
std::list<Scope>::const_iterator scope = db->scopeList.cbegin();
|
std::list<Scope>::const_iterator scope = db->scopeList.cbegin();
|
||||||
ASSERT_EQUALS(Scope::eGlobal, scope->type);
|
ASSERT_EQUALS(Scope::eGlobal, scope->type);
|
||||||
++scope;
|
++scope;
|
||||||
ASSERT_EQUALS(Scope::eClass, scope->type);
|
ASSERT_EQUALS(Scope::eClass, scope->type);
|
||||||
const Scope * class_scope = &*scope;
|
const Scope* class_scope = &*scope;
|
||||||
++scope;
|
++scope;
|
||||||
ASSERT(class_scope->functionList.size() == 1);
|
ASSERT(class_scope->functionList.size() == 1);
|
||||||
ASSERT(class_scope->functionList.cbegin()->hasBody());
|
ASSERT(class_scope->functionList.cbegin()->hasBody());
|
||||||
ASSERT(class_scope->functionList.cbegin()->functionScope == &*scope);
|
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__)
|
#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) {
|
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);
|
Tokenizer tokenizer(settings ? settings : &settings2, this);
|
||||||
|
@ -8375,6 +8392,15 @@ private:
|
||||||
ASSERT(tok->variable() && tok->variable()->valueType());
|
ASSERT(tok->variable() && tok->variable()->valueType());
|
||||||
ASSERT_EQUALS("signed int * const &", tok->variable()->valueType()->str());
|
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() {
|
void valueTypeThis() {
|
||||||
|
|
|
@ -102,6 +102,7 @@ private:
|
||||||
TEST_CASE(varid63);
|
TEST_CASE(varid63);
|
||||||
TEST_CASE(varid64); // #9928 - extern const char (*x[256])
|
TEST_CASE(varid64); // #9928 - extern const char (*x[256])
|
||||||
TEST_CASE(varid65); // #10936
|
TEST_CASE(varid65); // #10936
|
||||||
|
TEST_CASE(varid66);
|
||||||
TEST_CASE(varid_for_1);
|
TEST_CASE(varid_for_1);
|
||||||
TEST_CASE(varid_for_2);
|
TEST_CASE(varid_for_2);
|
||||||
TEST_CASE(varid_cpp_keywords_in_c_code);
|
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() {
|
void varid_for_1() {
|
||||||
const char code[] = "void foo(int a, int b) {\n"
|
const char code[] = "void foo(int a, int b) {\n"
|
||||||
" for (int a=1,b=2;;) {}\n"
|
" for (int a=1,b=2;;) {}\n"
|
||||||
|
|
Loading…
Reference in New Issue