Fixed #8122 (simplifyTemplates: constructor outside template class not simplified properly) (#1361)

This commit is contained in:
IOBYTE 2018-09-02 11:49:13 -04:00 committed by Daniel Marjamäki
parent 8d88f75f03
commit 7224ee27d9
3 changed files with 69 additions and 11 deletions

View File

@ -942,11 +942,11 @@ static bool getTemplateNamePositionTemplateMember(const Token *tok, int &namepos
if (!templateParmEnd) if (!templateParmEnd)
return false; return false;
if (Token::Match(templateParmEnd->next(), ":: %type% (")) { if (Token::Match(templateParmEnd->next(), ":: ~| %type% (")) {
// We have a match, and currPos points at the template list opening '<'. Move it to the closing '>' // We have a match, and currPos points at the template list opening '<'. Move it to the closing '>'
for (const Token *tok2 = tok->tokAt(currPos) ; tok2 != templateParmEnd ; tok2 = tok2->next()) for (const Token *tok2 = tok->tokAt(currPos) ; tok2 != templateParmEnd ; tok2 = tok2->next())
++currPos; ++currPos;
namepos = currPos + 2; namepos = currPos + (templateParmEnd->strAt(2) == "~" ? 3 : 2);
return true; return true;
} }
return false; return false;
@ -1053,6 +1053,11 @@ void TemplateSimplifier::expandTemplate(
tok5 = tok5->next(); tok5 = tok5->next();
// copy return type // copy return type
while (tok5 && tok5 != tok3) { while (tok5 && tok5 != tok3) {
// replace name if found
if (Token::Match(tok5, "%name% <") && tok5->str() == fullName) {
mTokenList.addtoken(newName, tok5->linenr(), tok5->fileIndex());
tok5 = tok5->next()->findClosingBracket();
} else
mTokenList.addtoken(tok5, tok5->linenr(), tok5->fileIndex()); mTokenList.addtoken(tok5, tok5->linenr(), tok5->fileIndex());
tok5 = tok5->next(); tok5 = tok5->next();
} }
@ -1100,9 +1105,7 @@ void TemplateSimplifier::expandTemplate(
// replace name.. // replace name..
if (tok3->str() == lastName) { if (tok3->str() == lastName) {
if (Token::Match(tok3->tokAt(-2), "> :: %name% ( )")) { if (!Token::simpleMatch(tok3->next(), "<")) {
; // Ticket #7942: Replacing for out-of-line constructors generates invalid syntax
} else if (!Token::simpleMatch(tok3->next(), "<")) {
mTokenList.addtoken(newName, tok3->linenr(), tok3->fileIndex()); mTokenList.addtoken(newName, tok3->linenr(), tok3->fileIndex());
continue; continue;
} else if (tok3 == templateDeclarationNameToken) { } else if (tok3 == templateDeclarationNameToken) {

View File

@ -104,6 +104,7 @@ private:
TEST_CASE(template64); // #8683 TEST_CASE(template64); // #8683
TEST_CASE(template65); // #8321 TEST_CASE(template65); // #8321
TEST_CASE(template66); // #8725 TEST_CASE(template66); // #8725
TEST_CASE(template67); // #8122
TEST_CASE(template_specialization_1); // #7868 - template specialization template <typename T> struct S<C<T>> {..}; TEST_CASE(template_specialization_1); // #7868 - template specialization template <typename T> struct S<C<T>> {..};
TEST_CASE(template_specialization_2); // #7868 - template specialization template <typename T> struct S<C<T>> {..}; TEST_CASE(template_specialization_2); // #7868 - template specialization template <typename T> struct S<C<T>> {..};
TEST_CASE(template_enum); // #6299 Syntax error in complex enum declaration (including template) TEST_CASE(template_enum); // #6299 Syntax error in complex enum declaration (including template)
@ -210,12 +211,16 @@ private:
"template <class T> Fred<T>::Fred() { }\n" "template <class T> Fred<T>::Fred() { }\n"
"Fred<float> fred;"; "Fred<float> fred;";
const char expected[] = "template < class T > Fred < T > :: Fred ( ) { } " // <- TODO: this should be removed const char expected[] = "Fred<float> fred ; "
"class Fred<float> { } ; "
"Fred<float> :: Fred<float> ( ) { }";
const char actual[] = "template < class T > Fred < T > :: Fred ( ) { } " // <- TODO: this should be removed
"Fred<float> fred ; " "Fred<float> fred ; "
"class Fred<float> { } ; " "class Fred<float> { } ; "
"Fred<float> :: Fred ( ) { }"; "Fred<float> :: Fred<float> ( ) { }";
ASSERT_EQUALS(expected, tok(code)); TODO_ASSERT_EQUALS(expected, actual, tok(code));
} }
void template6() { void template6() {
@ -1211,6 +1216,56 @@ private:
TODO_ASSERT_EQUALS(exp, curr, tok(code)); TODO_ASSERT_EQUALS(exp, curr, tok(code));
} }
void template67() { // ticket #8122
const char code[] = "template <class T> struct Containter {\n"
" Containter();\n"
" Containter(const Containter &);\n"
" Containter & operator = (const Containter &);\n"
" ~Containter();\n"
" T* mElements;\n"
" const Containter * c;\n"
"};\n"
"template <class T> Containter<T>::Containter() : mElements(nullptr), c(nullptr) {}\n"
"template <class T> Containter<T>::Containter(const Containter & x) { nElements = x.nElements; c = x.c; }\n"
"template <class T> Containter<T> & Containter<T>::operator = (const Containter & x) { mElements = x.mElements; c = x.c; return *this; }\n"
"template <class T> Containter<T>::~Containter() {}\n"
"Containter<int> intContainer;";
const char expected[] = "Containter<int> intContainer ; "
"struct Containter<int> { "
"Containter<int> ( ) ; "
"Containter<int> ( const Containter<int> & ) ; "
"Containter<int> & operator= ( const Containter<int> & ) ; "
"~ Containter<int> ( ) ; "
"int * mElements ; "
"const Containter<int> * c ; "
"} ; "
"Containter<int> :: Containter<int> ( ) : mElements ( nullptr ) , c ( nullptr ) { } "
"Containter<int> :: Containter<int> ( const Containter<int> & ) { nElements = x . nElements ; c = x . c ; } "
"Containter<int> & Containter<int> :: operator= ( const Containter<int> & x) { mElements = x . mElements ; c = x . c ; return * this ; }\n"
"Containter<int> :: ~ Containter<int> ( ) { }";
const char actual[] = "template < class T > Containter < T > :: Containter ( ) : mElements ( nullptr ) , c ( nullptr ) { } "
"template < class T > Containter < T > :: Containter ( const Containter & x ) { nElements = x . nElements ; c = x . c ; } "
"template < class T > Containter < T > & Containter < T > :: operator= ( const Containter & x ) { mElements = x . mElements ; c = x . c ; return * this ; } "
"template < class T > Containter < T > :: ~ Containter ( ) { } "
"Containter<int> intContainer ; "
"struct Containter<int> { "
"Containter<int> ( ) ; "
"Containter<int> ( const Containter<int> & ) ; "
"Containter<int> & operator= ( const Containter<int> & ) ; "
"~ Containter<int> ( ) ; "
"int * mElements ; "
"const Containter<int> * c ; "
"} ; "
"Containter<int> :: Containter<int> ( ) : mElements ( nullptr ) , c ( nullptr ) { } "
"Containter<int> :: Containter<int> ( const Containter<int> & x ) { nElements = x . nElements ; c = x . c ; } "
"Containter<int> & Containter<int> :: operator= ( const Containter<int> & x ) { mElements = x . mElements ; c = x . c ; return * this ; } "
"Containter<int> :: ~ Containter<int> ( ) { }";
TODO_ASSERT_EQUALS(expected, actual, tok(code));
}
void template_specialization_1() { // #7868 - template specialization template <typename T> struct S<C<T>> {..}; void template_specialization_1() { // #7868 - template specialization template <typename T> struct S<C<T>> {..};
const char code[] = "template <typename T> struct C {};\n" const char code[] = "template <typename T> struct C {};\n"
"template <typename T> struct S {a};\n" "template <typename T> struct S {a};\n"

View File

@ -843,7 +843,7 @@ private:
"2: Containter<int> ( ) ;\n" "2: Containter<int> ( ) ;\n"
"3: int * mElements@2 ;\n" "3: int * mElements@2 ;\n"
"4: } ;\n" "4: } ;\n"
"5: Containter<int> :: Containter ( ) : mElements@2 ( nullptr ) { }\n"; "5: Containter<int> :: Containter<int> ( ) : mElements@2 ( nullptr ) { }\n";
ASSERT_EQUALS(exp, tokenizeDebugListing(code, /*simplify=*/true)); ASSERT_EQUALS(exp, tokenizeDebugListing(code, /*simplify=*/true));
} }
} }