File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -2588,11 +2588,13 @@ void CheckClass::checkVirtualFunctionCallInConstructor()
25882588 getFirstVirtualFunctionCallStack (virtualFunctionCallsMap, callToken, callstack);
25892589 if (callstack.empty ())
25902590 continue ;
2591- if (!(callstack.back ()->function ()->hasVirtualSpecifier () || callstack.back ()->function ()->hasOverrideSpecifier ()))
2591+ const Function* const func = callstack.back ()->function ();
2592+ if (!(func->hasVirtualSpecifier () || func->hasOverrideSpecifier ()))
25922593 continue ;
2593- if (callstack. back ()-> function () ->isPure ())
2594+ if (func ->isPure ())
25942595 pureVirtualFunctionCallInConstructorError (scope->function , callstack, callstack.back ()->str ());
2595- else if (!callstack.back ()->function ()->hasFinalSpecifier ())
2596+ else if (!func->hasFinalSpecifier () &&
2597+ !(func->nestedIn && func->nestedIn ->classDef && func->nestedIn ->classDef ->isFinalType ()))
25962598 virtualFunctionCallInConstructorError (scope->function , callstack, callstack.back ()->str ());
25972599 }
25982600 }
Original file line number Diff line number Diff line change @@ -680,6 +680,13 @@ class CPPCHECKLIB Token {
680680 setFlag (fIsSimplifedScope , b);
681681 }
682682
683+ bool isFinalType () const {
684+ return getFlag (fIsFinalType );
685+ }
686+ void isFinalType (bool b) {
687+ setFlag (fIsFinalType , b);
688+ }
689+
683690 bool isBitfield () const {
684691 return mImpl ->mBits > 0 ;
685692 }
@@ -1287,6 +1294,7 @@ class CPPCHECKLIB Token {
12871294 fIsIncompleteConstant = (1ULL << 36 ),
12881295 fIsRestrict = (1ULL << 37 ), // Is this a restrict pointer type
12891296 fIsSimplifiedTypedef = (1ULL << 38 ),
1297+ fIsFinalType = (1ULL << 39 ), // Is this a type with final specifier
12901298 };
12911299
12921300 Token::Type mTokType ;
Original file line number Diff line number Diff line change @@ -8427,8 +8427,17 @@ void Tokenizer::simplifyKeyword()
84278427
84288428 // final:
84298429 // 1) struct name final { }; <- struct is final
8430- if (Token::Match (tok->previous (), " struct|class|union %type% final [:{]" )) {
8431- tok->deleteNext ();
8430+ if (Token::Match (tok->previous (), " struct|class|union %type%" )) {
8431+ Token* finalTok = tok->next ();
8432+ if (Token::simpleMatch (finalTok, " <" )) { // specialization
8433+ finalTok = finalTok->findClosingBracket ();
8434+ if (finalTok)
8435+ finalTok = finalTok->next ();
8436+ }
8437+ if (Token::Match (finalTok, " final [:{]" )) {
8438+ finalTok->deleteThis ();
8439+ tok->previous ()->isFinalType (true );
8440+ }
84328441 }
84338442
84348443 // noexcept -> noexcept(true)
Original file line number Diff line number Diff line change @@ -7439,6 +7439,14 @@ class TestClass : public TestFixture {
74397439 " }\n "
74407440 " S::~S() = default;\n " );
74417441 ASSERT_EQUALS (" " , errout.str ());
7442+
7443+ checkVirtualFunctionCall (" struct Base: { virtual void wibble() = 0; virtual ~Base() {} };\n " // #11167
7444+ " struct D final : public Base {\n "
7445+ " void wibble() override;\n "
7446+ " D() {}\n "
7447+ " virtual ~D() { wibble(); }\n "
7448+ " };\n " );
7449+ ASSERT_EQUALS (" " , errout.str ());
74427450 }
74437451
74447452 void pureVirtualFunctionCall () {
Original file line number Diff line number Diff line change @@ -5531,7 +5531,7 @@ class TestSimplifyTemplate : public TestFixture {
55315531 " private:\n "
55325532 " std::basic_ostream<unsigned char> &outputStream_;\n "
55335533 " };" ;
5534- const char expected[] = " struct OutputU16<unsignedchar> final { "
5534+ const char expected[] = " struct OutputU16<unsignedchar> { "
55355535 " explicit OutputU16<unsignedchar> ( std :: basic_ostream < unsigned char > & t ) : outputStream_ ( t ) { } "
55365536 " void operator() ( unsigned short ) const ; "
55375537 " private: "
Original file line number Diff line number Diff line change @@ -156,6 +156,7 @@ class TestVarID : public TestFixture {
156156 TEST_CASE (varid_templateParameter); // #7046 set varid for "X": std::array<int,X> Y;
157157 TEST_CASE (varid_templateParameterFunctionPointer); // #11050
158158 TEST_CASE (varid_templateUsing); // #5781 #7273
159+ TEST_CASE (varid_templateSpecializationFinal);
159160 TEST_CASE (varid_not_template_in_condition); // #7988
160161 TEST_CASE (varid_cppcast); // #6190
161162 TEST_CASE (varid_variadicFunc);
@@ -2379,6 +2380,19 @@ class TestVarID : public TestFixture {
23792380 tokenize (code));
23802381 }
23812382
2383+ void varid_templateSpecializationFinal () {
2384+ const char code[] = " template <typename T>\n "
2385+ " struct S;\n "
2386+ " template <>\n "
2387+ " struct S<void> final {};\n " ;
2388+ ASSERT_EQUALS (" 4: struct S<void> ;\n "
2389+ " 1: template < typename T >\n "
2390+ " 2: struct S ;\n "
2391+ " 3:\n "
2392+ " 4: struct S<void> { } ;\n " ,
2393+ tokenize (code));
2394+ }
2395+
23822396 void varid_not_template_in_condition () {
23832397 const char code1[] = " void f() { if (x<a||x>b); }" ;
23842398 ASSERT_EQUALS (" 1: void f ( ) { if ( x < a || x > b ) { ; } }\n " , tokenize (code1));
You can’t perform that action at this time.
0 commit comments