Skip to content

Commit c98732d

Browse files
IOBYTEdanmar
authored andcommitted
fix using type aliases in out of class destructors (cppcheck-opensource#2250)
1 parent 1abf70a commit c98732d

3 files changed

Lines changed: 54 additions & 20 deletions

File tree

lib/tokenize.cpp

Lines changed: 27 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1723,8 +1723,11 @@ namespace {
17231723
}
17241724
if (tok1->strAt(-1) == ">")
17251725
tok1 = tok1->previous()->findOpeningBracket();
1726-
if (tok1 && Token::Match(tok1->tokAt(-3), "%name% :: %name%")) {
1726+
if (tok1 && (Token::Match(tok1->tokAt(-3), "%name% :: %name%") ||
1727+
Token::Match(tok1->tokAt(-4), "%name% :: ~ %name%"))) {
17271728
tok1 = tok1->tokAt(-2);
1729+
if (tok1->str() == "~")
1730+
tok1 = tok1->previous();
17281731
std::string scope = tok1->strAt(-1);
17291732
while (Token::Match(tok1->tokAt(-2), ":: %name%")) {
17301733
scope = tok1->strAt(-3) + " :: " + scope;
@@ -1874,8 +1877,28 @@ namespace {
18741877

18751878
return false;
18761879
}
1880+
1881+
std::string memberFunctionScope(const Token *tok)
1882+
{
1883+
std::string qualification;
1884+
const Token *qualTok = tok->strAt(-2) == "~" ? tok->tokAt(-4) : tok->tokAt(-3);
1885+
while (Token::Match(qualTok, "%type% ::")) {
1886+
if (!qualification.empty())
1887+
qualification = " :: " + qualification;
1888+
qualification = qualTok->str() + qualification;
1889+
qualTok = qualTok->tokAt(-2);
1890+
}
1891+
return qualification;
1892+
}
18771893
} // namespace
18781894

1895+
bool Tokenizer::isMemberFunction(const Token *openParen) const
1896+
{
1897+
return (Token::Match(openParen->tokAt(-2), ":: %name% (") ||
1898+
Token::Match(openParen->tokAt(-3), ":: ~ %name% (")) &&
1899+
isFunctionHead(openParen, "{|:");
1900+
}
1901+
18791902
bool Tokenizer::simplifyUsing()
18801903
{
18811904
bool substitute = false;
@@ -2007,20 +2030,11 @@ bool Tokenizer::simplifyUsing()
20072030
continue;
20082031
}
20092032

2010-
// check for member function
2011-
if (Token::Match(tok1->tokAt(-2), ":: %name% (") && isFunctionHead(tok1, "{|:")) {
2012-
std::string qualification;
2013-
const Token *qualTok = tok1->tokAt(-3);
2014-
while (Token::Match(qualTok, "%type% ::")) {
2015-
if (!qualification.empty())
2016-
qualification = " :: " + qualification;
2017-
qualification = qualTok->str() + qualification;
2018-
qualTok = qualTok->tokAt(-2);
2019-
}
2020-
2033+
// check for member function and adjust scope
2034+
if (isMemberFunction(tok1)) {
20212035
if (!scope1.empty())
20222036
scope1 += " :: ";
2023-
scope1 += qualification;
2037+
scope1 += memberFunctionScope(tok1);
20242038
}
20252039

20262040
if (!usingMatch(nameToken, scope, &tok1, scope1, scopeList1))

lib/tokenize.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -374,6 +374,10 @@ class CPPCHECKLIB Tokenizer {
374374
*/
375375
void simplifyTypedef();
376376

377+
/**
378+
*/
379+
bool isMemberFunction(const Token *openParen) const;
380+
377381
/**
378382
*/
379383
bool simplifyUsing();

test/testsimplifyusing.cpp

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -555,33 +555,49 @@ class TestSimplifyUsing : public TestFixture {
555555
{
556556
const char code[] = "class A {\n"
557557
"public:\n"
558-
" using Foo = Bar;\n"
558+
" using Foo = int;\n"
559+
" A(Foo foo);\n"
560+
" ~A();\n"
559561
" void func(Foo foo);\n"
560562
"};\n"
563+
"A::A(Foo) { }\n"
564+
"A::~A() { Foo foo; }\n"
561565
"void A::func(Foo) { }";
562566
const char exp[] = "class A { "
563567
"public: "
564-
"void func ( Bar foo ) ; "
568+
"A ( int foo ) ; "
569+
"~ A ( ) ; "
570+
"void func ( int foo ) ; "
565571
"} ; "
566-
"void A :: func ( Bar ) { }";
572+
"A :: A ( int ) { } "
573+
"A :: ~ A ( ) { int foo ; } "
574+
"void A :: func ( int ) { }";
567575
ASSERT_EQUALS(exp, tok(code, false));
568576
}
569577
{
570578
const char code[] = "class A {\n"
571579
"public:\n"
572580
" struct B {\n"
573-
" using Foo = Bar;\n"
574-
" void func(Foo foo);\n"
581+
" using Foo = int;\n"
582+
" B(Foo foo);\n"
583+
" ~B();\n"
584+
" void func(Foo foo);\n"
575585
" };\n"
576586
"};\n"
587+
"A::B::B(Foo) { }\n"
588+
"A::B::~B() { Foo foo; }\n"
577589
"void A::B::func(Foo) { }";
578590
const char exp[] = "class A { "
579591
"public: "
580592
"struct B { "
581-
"void func ( Bar foo ) ; "
593+
"B ( int foo ) ; "
594+
"~ B ( ) ; "
595+
"void func ( int foo ) ; "
582596
"} ; "
583597
"} ; "
584-
"void A :: B :: func ( Bar ) { }";
598+
"A :: B :: B ( int ) { } "
599+
"A :: B :: ~ B ( ) { int foo ; } "
600+
"void A :: B :: func ( int ) { }";
585601
ASSERT_EQUALS(exp, tok(code, false));
586602
}
587603
}

0 commit comments

Comments
 (0)