template simplifier: fix 3 function forward declaration bugs (#1493)

* fix support for multi token types
* fix support for const member functions
* fix duplicate template parameters sometimes being inserted
This commit is contained in:
IOBYTE 2018-11-26 00:23:12 -05:00 committed by Daniel Marjamäki
parent 86f9fb778b
commit e20079a5d9
2 changed files with 61 additions and 4 deletions

View File

@ -1047,6 +1047,8 @@ void TemplateSimplifier::expandTemplate(
start = templateDeclarationToken->next();
end = templateDeclarationNameToken->linkAt(1)->next();
}
while (!Token::Match(end, ";|{"))
end = end->next();
std::map<const Token *, Token *> links;
while (start && start != end) {
@ -1055,12 +1057,30 @@ void TemplateSimplifier::expandTemplate(
++itype;
if (itype < typeParametersInDeclaration.size()) {
dst->insertToken(mTypesUsedInTemplateInstantiation[itype]->str(), "", true);
dst->previous()->isTemplateArg(true);
unsigned int typeindentlevel = 0;
for (const Token *typetok = mTypesUsedInTemplateInstantiation[itype];
typetok && (typeindentlevel > 0 || !Token::Match(typetok, ",|>"));
typetok = typetok->next()) {
if (Token::simpleMatch(typetok, ". . .")) {
typetok = typetok->tokAt(2);
continue;
}
if (Token::Match(typetok, "%name% <") && templateParameters(typetok->next()) > 0)
++typeindentlevel;
else if (typeindentlevel > 0 && typetok->str() == ">")
--typeindentlevel;
dst->insertToken(typetok->str(), typetok->originalName(), true);
dst->previous()->isTemplateArg(true);
dst->previous()->isSigned(typetok->isSigned());
dst->previous()->isUnsigned(typetok->isUnsigned());
dst->previous()->isLong(typetok->isLong());
}
} else {
if (start->str() == templateDeclarationNameToken->str())
if (start->str() == templateDeclarationNameToken->str()) {
dst->insertToken(newName, "", true);
else
if (start->strAt(1) == "<")
start = start->next()->findClosingBracket();
} else
dst->insertToken(start->str(), "", true);
if (start->link()) {
if (Token::Match(start, "[|{|(")) {

View File

@ -117,6 +117,8 @@ private:
TEST_CASE(template77);
TEST_CASE(template78);
TEST_CASE(template79); // #5133
TEST_CASE(template80);
TEST_CASE(template81);
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_enum); // #6299 Syntax error in complex enum declaration (including template)
@ -1517,6 +1519,41 @@ private:
ASSERT_EQUALS(exp, tok(code));
}
void template80() {
const char code[] = "class Fred {\n"
" template <typename T> T foo(T t) const { return t; }\n"
"};\n"
"const void * p = Fred::foo<const void *>(nullptr);";
const char exp[] = "class Fred { "
"const void * foo<constvoid*> ( const void * t ) const ; "
"} ; "
"const void * p ; p = Fred :: foo<constvoid*> ( nullptr ) ; "
"const void * Fred :: foo<constvoid*> ( const void * t ) const { return t ; }";
ASSERT_EQUALS(exp, tok(code));
}
void template81() {
const char code[] = "template <typename Type>\n"
"struct SortWith {\n"
" SortWith(Type);\n"
"};\n"
"template <typename Type>\n"
"SortWith<Type>::SortWith(Type) {}\n"
"int main() {\n"
" SortWith<int>(0);\n"
"}";
const char exp[] = "template < typename Type > "
"struct SortWith { "
"SortWith ( Type ) ; "
"} ; "
"SortWith<int> :: SortWith<int> ( int ) ; "
"int main ( ) { "
"SortWith<int> ( 0 ) ; "
"} "
"SortWith<int> :: SortWith<int> ( int ) { }";
ASSERT_EQUALS(exp, tok(code));
}
void template_specialization_1() { // #7868 - template specialization template <typename T> struct S<C<T>> {..};
const char code[] = "template <typename T> struct C {};\n"
"template <typename T> struct S {a};\n"