template simplifier: fix instantiated template names in forward declarations (#1495)

This now handles the revised example code in #8603.
This commit is contained in:
IOBYTE 2018-11-27 00:17:04 -05:00 committed by Daniel Marjamäki
parent 18c234e277
commit f2660ed203
2 changed files with 67 additions and 2 deletions

View File

@ -1080,8 +1080,34 @@ void TemplateSimplifier::expandTemplate(
dst->insertToken(newName, "", true);
if (start->strAt(1) == "<")
start = start->next()->findClosingBracket();
} else
dst->insertToken(start->str(), "", true);
} else {
// check if type is a template
if (start->strAt(1) == "<") {
// get the instantiated name
Token * closing = start->next()->findClosingBracket();
std::string name;
const Token * type = start;
while (type && type != closing->next()) {
if (!name.empty())
name += " ";
name += type->str();
type = type->next();
}
// check if type is instantiated
for (const auto & inst : mTemplateInstantiations) {
if (Token::simpleMatch(inst.nameToken, name.c_str())) {
// use the instantiated name
dst->insertToken(name, "", true);
start = closing;
break;
}
}
// just copy the token if it wasn't instantiated
if (start != closing)
dst->insertToken(start->str(), "", true);
} else
dst->insertToken(start->str(), "", true);
}
if (start->link()) {
if (Token::Match(start, "[|{|(")) {
links[start->link()] = dst->previous();

View File

@ -119,6 +119,7 @@ private:
TEST_CASE(template79); // #5133
TEST_CASE(template80);
TEST_CASE(template81);
TEST_CASE(template82); // 8603
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)
@ -1554,6 +1555,44 @@ private:
ASSERT_EQUALS(exp, tok(code));
}
void template82() { // 8603
const char code[] = "typedef int comp;\n"
"const int f16=16;\n"
"template<int x>\n"
"class tvec2 {};\n"
"template<int x>\n"
"class tvec3 {};\n"
"namespace swizzle {\n"
"template <comp> void swizzle(tvec2<f16> v) { }\n"
"template <comp x, comp y> void swizzle(tvec3<f16> v) { }\n"
"}\n"
"void foo() {\n"
" using namespace swizzle;\n"
" tvec2<f16> tt2;\n"
" swizzle<1>(tt2);\n"
" tvec3<f16> tt3;\n"
" swizzle<2,3>(tt3);\n"
"}";
const char exp[] = "class tvec2<f16> ; "
"class tvec3<f16> ; "
"namespace swizzle { "
"void swizzle<1> ( tvec2<f16> v ) ; "
"void swizzle<2,3> ( tvec3<f16> v ) ; "
"} "
"void foo ( ) { "
"using namespace swizzle ; "
"tvec2<f16> tt2 ; "
"swizzle<1> ( tt2 ) ; "
"tvec3<f16> tt3 ; "
"swizzle<2,3> ( tt3 ) ; "
"} "
"void swizzle :: swizzle<2,3> ( tvec3<f16> v ) { } "
"void swizzle :: swizzle<1> ( tvec2<f16> v ) { } "
"class tvec3<f16> { } ; "
"class tvec2<f16> { } ;";
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"