diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 51a596c0a..1e2c31ba8 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -9060,7 +9060,7 @@ static const std::set keywords = { , "__restrict__" , "__thread" }; -// Remove "inline", "register", "restrict", "override", "final", "static" and "constexpr" +// Remove "inline", "register", "restrict", "override", "static" and "constexpr" // "restrict" keyword // - New to 1999 ANSI/ISO C standard // - Not in C++ standard yet @@ -9110,7 +9110,7 @@ void Tokenizer::simplifyKeyword() // final: // 1) struct name final { }; <- struct is final - if (Token::Match(tok, "%type% final [:{]")) { + if (Token::Match(tok->previous(), "struct|class|union %type% final [:{]")) { tok->deleteNext(); } diff --git a/test/testsymboldatabase.cpp b/test/testsymboldatabase.cpp index 663670794..aba087797 100644 --- a/test/testsymboldatabase.cpp +++ b/test/testsymboldatabase.cpp @@ -294,6 +294,7 @@ private: TEST_CASE(symboldatabase71); TEST_CASE(symboldatabase72); // #8600 TEST_CASE(symboldatabase73); // #8603 + TEST_CASE(symboldatabase74); // #8838 - final TEST_CASE(createSymbolDatabaseFindAllScopes1); @@ -4135,6 +4136,17 @@ private: ASSERT_EQUALS(3, f2->function->token->linenr()); } + void symboldatabase74() { // #8838 - final + GET_SYMBOL_DB("class Base { virtual int f() const = 0; };\n" + "class Derived : Base { virtual int f() const final { return 6; } };"); + + ASSERT_EQUALS(4, db->scopeList.size()); + ASSERT_EQUALS(1, db->functionScopes.size()); + + const Scope *f1 = db->functionScopes[0]; + ASSERT(f1->function->hasFinalSpecifier()); + } + void createSymbolDatabaseFindAllScopes1() { GET_SYMBOL_DB("void f() { union {int x; char *p;} a={0}; }"); ASSERT(db->scopeList.size() == 3);