diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index 1f50548fc..06bb064a3 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -4365,9 +4365,14 @@ void Function::addArguments(const SymbolDatabase *symbolDatabase, const Scope *s if (Token::Match(typeTok, ",|)")) { // #8333 symbolDatabase->mTokenizer.syntaxError(typeTok); } + if (Token::Match(typeTok, "%type% <") && Token::Match(typeTok->linkAt(1), "> :: %type%")) + typeTok = typeTok->linkAt(1)->tokAt(2); // skip over qualification - while (Token::Match(typeTok, "%type% ::")) + while (Token::Match(typeTok, "%type% ::")) { typeTok = typeTok->tokAt(2); + if (Token::Match(typeTok, "%type% <") && Token::Match(typeTok->linkAt(1), "> :: %type%")) + typeTok = typeTok->linkAt(1)->tokAt(2); + } // check for argument with no name or missing varid if (!endTok) { diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 3b5704d1c..39e495824 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -4640,6 +4640,10 @@ void Tokenizer::setVarIdPass1() } catch (const Token * errTok) { syntaxError(errTok); } + + if (tok->str() == "(" && isFunctionHead(tok, "{") && scopeStack.top().isExecutable) + inlineFunction = true; + if (decl) { if (isCPP()) { if (Token *declTypeTok = Token::findsimplematch(tok, "decltype (", tok2)) { @@ -4650,9 +4654,6 @@ void Tokenizer::setVarIdPass1() } } - if (tok->str() == "(" && isFunctionHead(tok,"{") && scopeStack.top().isExecutable) - inlineFunction = true; - const Token* prev2 = tok2->previous(); if (Token::Match(prev2, "%type% [;[=,)]") && tok2->previous()->str() != "const") ; diff --git a/test/testsymboldatabase.cpp b/test/testsymboldatabase.cpp index 9bf295a29..2941fb60c 100644 --- a/test/testsymboldatabase.cpp +++ b/test/testsymboldatabase.cpp @@ -248,6 +248,7 @@ private: TEST_CASE(functionArgs18); // #10376 TEST_CASE(functionArgs19); // #10376 TEST_CASE(functionArgs20); + TEST_CASE(functionArgs21); TEST_CASE(functionImplicitlyVirtual); TEST_CASE(functionGetOverridden); @@ -2765,6 +2766,28 @@ private: TODO_ASSERT(arg->hasDefault()); } + void functionArgs21() { + const char code[] = "void f(std::vector::size_type) {}\n" // #11408 + "template\n" + "struct S { using t = int; };\n" + "template\n" + "S operator+(const S&lhs, typename S::t) { return lhs; }"; + GET_SYMBOL_DB(code); + ASSERT(db != nullptr); + auto it = db->functionScopes.begin(); + const Function *func = (*it)->function; + ASSERT_EQUALS("f", func->name()); + ASSERT_EQUALS(1, func->argCount()); + const Variable* arg = func->getArgumentVar(0); + ASSERT_EQUALS("", arg->name()); + ++it; + func = (*it)->function; + ASSERT_EQUALS("operator+", func->name()); + ASSERT_EQUALS(2, func->argCount()); + arg = func->getArgumentVar(1); + ASSERT_EQUALS("", arg->name()); + } + void functionImplicitlyVirtual() { GET_SYMBOL_DB("class base { virtual void f(); };\n" "class derived : base { void f(); };\n" diff --git a/test/testvarid.cpp b/test/testvarid.cpp index c3d2fcd76..a4d709b69 100644 --- a/test/testvarid.cpp +++ b/test/testvarid.cpp @@ -100,6 +100,7 @@ private: TEST_CASE(varid66); TEST_CASE(varid67); // #11711 - NOT function pointer TEST_CASE(varid68); // #11740 - switch (str_chars(&strOut)[0]) + TEST_CASE(varid69); TEST_CASE(varid_for_1); TEST_CASE(varid_for_2); TEST_CASE(varid_cpp_keywords_in_c_code); @@ -1241,6 +1242,16 @@ private: ASSERT_EQUALS(expected1, tokenize(code1, "test.cpp")); } + void varid69() { + const char code1[] = "void f() {\n" + " auto g = [](int&, int& r, int i) {};\n" + "}"; + const char expected1[] = "1: void f ( ) {\n" + "2: auto g@1 ; g@1 = [ ] ( int & , int & r@2 , int i@3 ) { } ;\n" + "3: }\n"; + ASSERT_EQUALS(expected1, tokenize(code1, "test.cpp")); + } + void varid_for_1() { const char code[] = "void foo(int a, int b) {\n" " for (int a=1,b=2;;) {}\n"