From 8956ecb5fc6fedd1f13ccc71ef18a2bcd8a80363 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Tue, 3 Nov 2020 17:52:38 +0100 Subject: [PATCH] Clang import: Fixed data for inline static functions --- lib/clangimport.cpp | 6 +++ lib/symboldatabase.cpp | 74 +++++++++++++++++++---------------- lib/symboldatabase.h | 1 + test/cli/test-clang-import.py | 6 ++- test/testclangimport.cpp | 6 +++ 5 files changed, 57 insertions(+), 36 deletions(-) diff --git a/lib/clangimport.cpp b/lib/clangimport.cpp index 3e223f866..926fa8bd1 100644 --- a/lib/clangimport.cpp +++ b/lib/clangimport.cpp @@ -1083,11 +1083,17 @@ void clangimport::AstNode::createTokensFunctionDecl(TokenList *tokenList) { const bool prev = (std::find(mExtTokens.begin(), mExtTokens.end(), "prev") != mExtTokens.end()); const bool hasBody = mFile == 0 && !children.empty() && children.back()->nodeType == CompoundStmt; + const bool isStatic = (std::find(mExtTokens.begin(), mExtTokens.end(), "static") != mExtTokens.end()); + const bool isInline = (std::find(mExtTokens.begin(), mExtTokens.end(), "inline") != mExtTokens.end()); const Token *startToken = nullptr; SymbolDatabase *symbolDatabase = mData->mSymbolDatabase; if (nodeType != CXXConstructorDecl && nodeType != CXXDestructorDecl) { + if (isStatic) + addtoken(tokenList, "static"); + if (isInline) + addtoken(tokenList, "inline"); const Token * const before = tokenList->back(); addTypeTokens(tokenList, '\'' + getType() + '\''); startToken = before ? before->next() : tokenList->front(); diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index 5f2974022..c18f7e2aa 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -2102,40 +2102,7 @@ Function::Function(const Tokenizer *mTokenizer, isExplicit(tokenDef->previous()->str() == "explicit"); } - const Token *tok1 = tok; - - // look for end of previous statement - while (tok1->previous() && !Token::Match(tok1->previous(), ";|}|{|public:|protected:|private:")) { - tok1 = tok1->previous(); - - // extern function - if (tok1->str() == "extern") { - isExtern(true); - } - - // virtual function - else if (tok1->str() == "virtual") { - hasVirtualSpecifier(true); - } - - // static function - else if (tok1->str() == "static") { - isStatic(true); - if (scope->type == Scope::eNamespace || scope->type == Scope::eGlobal) - isStaticLocal(true); - } - - // friend function - else if (tok1->str() == "friend") { - isFriend(true); - } - - // Function template - else if (tok1->link() && tok1->str() == ">" && Token::simpleMatch(tok1->link()->previous(), "template <")) { - templateDef = tok1->link()->previous(); - break; - } - } + const Token *tok1 = setFlags(tok, scope); // find the return type if (!isConstructor() && !isDestructor() && !isLambda()) { @@ -2234,6 +2201,45 @@ Function::Function(const Token *tokenDef) if (tokenDef->str() == "operator=") type = Function::eOperatorEqual; } + + setFlags(tokenDef, tokenDef->scope()); +} + +const Token *Function::setFlags(const Token *tok1, const Scope *scope) +{ + // look for end of previous statement + while (tok1->previous() && !Token::Match(tok1->previous(), ";|}|{|public:|protected:|private:")) { + tok1 = tok1->previous(); + + // extern function + if (tok1->str() == "extern") { + isExtern(true); + } + + // virtual function + else if (tok1->str() == "virtual") { + hasVirtualSpecifier(true); + } + + // static function + else if (tok1->str() == "static") { + isStatic(true); + if (scope->type == Scope::eNamespace || scope->type == Scope::eGlobal) + isStaticLocal(true); + } + + // friend function + else if (tok1->str() == "friend") { + isFriend(true); + } + + // Function template + else if (tok1->link() && tok1->str() == ">" && Token::simpleMatch(tok1->link()->previous(), "template <")) { + templateDef = tok1->link()->previous(); + break; + } + } + return tok1; } std::string Function::fullName() const diff --git a/lib/symboldatabase.h b/lib/symboldatabase.h index cc4bf62f4..d07e5e6e6 100644 --- a/lib/symboldatabase.h +++ b/lib/symboldatabase.h @@ -978,6 +978,7 @@ private: void hasTrailingReturnType(bool state) { return setFlag(fHasTrailingReturnType, state); } + const Token *setFlags(const Token *tok1, const Scope *scope); }; class CPPCHECKLIB Scope { diff --git a/test/cli/test-clang-import.py b/test/cli/test-clang-import.py index 241719743..d8c7af31d 100644 --- a/test/cli/test-clang-import.py +++ b/test/cli/test-clang-import.py @@ -85,8 +85,7 @@ def test_symbol_database_1(): check_symbol_database('int main(){return 0;}') def test_symbol_database_2(): - code = 'struct Foo { void f(); }; void Foo::f() {}' - check_symbol_database(code) + check_symbol_database('struct Foo { void f(); }; void Foo::f() {}') def test_symbol_database_3(): check_symbol_database('struct Fred { int a; }; int b; void f(int c, int d) { int e; }') @@ -97,6 +96,9 @@ def test_symbol_database_4(): def test_symbol_database_5(): check_symbol_database('void f(int);') +def test_symbol_database_6(): + check_symbol_database('inline static int foo(int x) { return x; }') + def test_symbol_database_operator(): check_symbol_database('struct Fred { void operator=(int x); };') diff --git a/test/testclangimport.cpp b/test/testclangimport.cpp index 741729697..b93718a38 100644 --- a/test/testclangimport.cpp +++ b/test/testclangimport.cpp @@ -74,6 +74,7 @@ private: TEST_CASE(funcdecl2); TEST_CASE(funcdecl3); TEST_CASE(funcdecl4); + TEST_CASE(funcdecl5); TEST_CASE(functionTemplateDecl1); TEST_CASE(functionTemplateDecl2); TEST_CASE(initListExpr); @@ -684,6 +685,11 @@ private: ASSERT_EQUALS("unsigned long fwrite ( const void * , unsigned long , unsigned long , FILE * ) ;", parse(clang)); } + void funcdecl5() { + const char clang[] = "`-FunctionDecl 0x59d670 <1.c:1:1, col:28> col:20 foo 'void (void)' static inline"; + ASSERT_EQUALS("static inline void foo ( ) ;", parse(clang)); + } + void functionTemplateDecl1() { const char clang[] = "`-FunctionTemplateDecl 0x3242860 col:21 foo"; ASSERT_EQUALS("", parse(clang));