Support array types in template simplifier (#3267)

This commit is contained in:
dummyunit 2021-05-23 11:40:09 +03:00 committed by GitHub
parent 47a4144b47
commit 247b2d8c83
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 38 additions and 6 deletions

View File

@ -528,7 +528,7 @@ unsigned int TemplateSimplifier::templateParameters(const Token *tok)
} }
tok = tok->next(); tok = tok->next();
if (Token::simpleMatch(tok,"(")) if (Token::Match(tok, "(|["))
tok = tok->link()->next(); tok = tok->link()->next();
if (!tok) if (!tok)
@ -2939,7 +2939,7 @@ std::string TemplateSimplifier::getNewName(
const Token * endToken = tok2->next()->findClosingBracket(); const Token * endToken = tok2->next()->findClosingBracket();
for (Token *tok3 = tok2->tokAt(2); tok3 != endToken && (indentlevel > 0 || tok3->str() != ">"); tok3 = tok3->next()) { for (Token *tok3 = tok2->tokAt(2); tok3 != endToken && (indentlevel > 0 || tok3->str() != ">"); tok3 = tok3->next()) {
// #2721 - unhandled [ => bail out // #2721 - unhandled [ => bail out
if (tok3->str() == "[") { if (tok3->str() == "[" && !Token::Match(tok3->next(), "%num%| ]")) {
typeForNewName.clear(); typeForNewName.clear();
break; break;
} }
@ -2954,9 +2954,9 @@ std::string TemplateSimplifier::getNewName(
if (indentlevel == 0 && Token::Match(tok3->previous(), "[<,]")) { if (indentlevel == 0 && Token::Match(tok3->previous(), "[<,]")) {
mTypesUsedInTemplateInstantiation.emplace_back(tok3, ""); mTypesUsedInTemplateInstantiation.emplace_back(tok3, "");
} }
if (tok3->str() == "(") if (Token::Match(tok3, "(|["))
++indentlevel; ++indentlevel;
else if (tok3->str() == ")") else if (Token::Match(tok3, ")|]"))
--indentlevel; --indentlevel;
const bool constconst = tok3->str() == "const" && tok3->strAt(1) == "const"; const bool constconst = tok3->str() == "const" && tok3->strAt(1) == "const";
if (!constconst) { if (!constconst) {

View File

@ -237,6 +237,7 @@ private:
TEST_CASE(template_namespace_10); TEST_CASE(template_namespace_10);
TEST_CASE(template_namespace_11); // #7145 TEST_CASE(template_namespace_11); // #7145
TEST_CASE(template_pointer_type); TEST_CASE(template_pointer_type);
TEST_CASE(template_array_type);
// Test TemplateSimplifier::templateParameters // Test TemplateSimplifier::templateParameters
TEST_CASE(templateParameters); TEST_CASE(templateParameters);
@ -875,8 +876,7 @@ private:
"class C: public A<char[M]> {};\n" "class C: public A<char[M]> {};\n"
"\n" "\n"
"C<2> a;\n"; "C<2> a;\n";
// TODO: expand A also ASSERT_EQUALS("class A<char[2]> ; class C<2> ; C<2> a ; class C<2> : public A<char[2]> { } ; class A<char[2]> { public: char [ 2 ] x ; } ;", tok(code));
ASSERT_EQUALS("template < class T > class A { public: T x ; } ; class C<2> ; C<2> a ; class C<2> : public A < char [ 2 ] > { } ;", tok(code));
} }
void template27() { void template27() {
@ -5104,6 +5104,36 @@ private:
"void foo<int*> ( int * const x ) { }", tok(code)); "void foo<int*> ( int * const x ) { }", tok(code));
} }
void template_array_type() {
ASSERT_EQUALS("void foo<int[]> ( int [ ] x ) ; "
"void bar ( ) { int [ 3 ] y ; foo<int[]> ( y ) ; } "
"void foo<int[]> ( int [ ] x ) { } ;",
tok("template <class T> void foo(T x) {};\n"
"void bar() {\n"
" int[3] y;\n"
" foo<int[]>(y);\n"
"}"));
ASSERT_EQUALS("struct A<int[2]> ; "
"A<int[2]> y ; "
"struct A<int[2]> { int [ 2 ] x ; } ;",
tok("template <class T> struct A { T x; };\n"
"A<int[2]> y;"));
// Previously resulted in:
// test.cpp:2:33: error: Syntax Error: AST broken, binary operator '>' doesn't have two operands. [internalAstError]
ASSERT_EQUALS("struct A<B<int>[]> ; "
"struct B<B<int>> ; "
"struct C<B<int>> ; "
"C<B<int>> y ; "
"struct C<B<int>> : B<B<int>> { } ; "
"struct B<B<int>> { A<B<int>[]> x ; } ; "
"struct A<B<int>[]> { } ;",
tok("template <class > struct A {};\n"
"template <class T> struct B { A<T[]> x; };\n"
"template <class T> struct C : B<T> {};\n"
"C<B<int>> y;"));
}
unsigned int templateParameters(const char code[]) { unsigned int templateParameters(const char code[]) {
Tokenizer tokenizer(&settings, this); Tokenizer tokenizer(&settings, this);
@ -5139,6 +5169,8 @@ private:
ASSERT_EQUALS(1U, templateParameters("X<int...> x;")); ASSERT_EQUALS(1U, templateParameters("X<int...> x;"));
ASSERT_EQUALS(2U, templateParameters("X<class, typename...> x;")); ASSERT_EQUALS(2U, templateParameters("X<class, typename...> x;"));
ASSERT_EQUALS(2U, templateParameters("X<1, T> x;")); ASSERT_EQUALS(2U, templateParameters("X<1, T> x;"));
ASSERT_EQUALS(1U, templateParameters("X<T[]> x;"));
ASSERT_EQUALS(1U, templateParameters("X<T[2]> x;"));
ASSERT_EQUALS(1U, templateParameters("X<i == 0> x;")); ASSERT_EQUALS(1U, templateParameters("X<i == 0> x;"));
ASSERT_EQUALS(2U, templateParameters("X<int, i>=0> x;")); ASSERT_EQUALS(2U, templateParameters("X<int, i>=0> x;"));
ASSERT_EQUALS(3U, templateParameters("X<int, i>=0, i - 2> x;")); ASSERT_EQUALS(3U, templateParameters("X<int, i>=0, i - 2> x;"));