template simplifier: make sure all instantiations are found and expan… (#1696)

* template simplifier: make sure all instantiations are found and expanded in #5097

* template simplifier: check output on another test

* template simplifier: add output to another test
This commit is contained in:
IOBYTE 2019-02-26 00:41:04 -05:00 committed by Daniel Marjamäki
parent 3f257d6310
commit bf85767829
2 changed files with 82 additions and 18 deletions

View File

@ -696,7 +696,7 @@ void TemplateSimplifier::getTemplateInstantiations()
else if (!isUsing && tok2 && tok2->str() == ";")
tok = const_cast<Token *>(tok2);
}
} else if (Token::Match(tok->previous(), "(|{|}|;|=|>|<<|:|.|*|& %name% ::|<|(") ||
} else if (Token::Match(tok->previous(), "(|{|}|;|=|>|<<|:|.|*|&|return|< %name% ::|<|(") ||
Token::Match(tok->previous(), "%type% %name% ::|<") ||
Token::Match(tok->tokAt(-2), "[,:] private|protected|public %name% ::|<")) {
std::string scopeName = getScopeName(scopeList);

View File

@ -1010,16 +1010,54 @@ private:
}
void template43() { // #5097 - Assert due to '>>' in 'B<A<C>>' not being treated as end of template instantation
const char code[] = "template <typename T> struct C { };"
"template <typename T> struct D { static int f() { return C<T>::f(); } };"
"template <typename T> inline int f2() { return D<T>::f(); }"
"template <typename T> int f1(int x, T *) { int id = f2<T>(); return id; }"
"template <> struct C < B < A >> {"
" static int f() {"
" return f1 < B < A >> (0, reinterpret_cast< B<A> *>(E<void *>::Int(-1)));"
" }"
"};";
tok(code); // Don't assert
const char code[] = "template <typename T> struct E { typedef int Int; };\n"
"template <typename T> struct C { };\n"
"template <typename T> struct D { static int f() { return C<T>::f(); } };\n"
"template <typename T> inline int f2() { return D<T>::f(); }\n"
"template <typename T> int f1 (int x, T *) { int id = f2<T>(); return id; }\n"
"template <typename T> struct B { void f3(B<T> & other) { } };\n"
"struct A { };\n"
"template <> struct C<B<A>> {\n"
" static int f() { return f1<B<A>>(0, reinterpret_cast<B<A>*>(E<void*>::Int(-1))); }\n"
"};\n"
"int main(void) {\n"
" C<A> ca;\n"
" return 0;\n"
"}";
const char expected[] = "struct E<void*> ; "
"struct C<A> ; "
"struct D<B<A>> ; "
"int f2<B<A>> ( ) ; "
"int f1<B<A>> ( int x , B<A> * ) ; "
"struct B<A> ; "
"struct A { } ; "
"struct C<B<A>> { "
"static int f ( ) { "
"return f1<B<A>> ( 0 , reinterpret_cast < B<A> * > ( E<void*> :: Int ( -1 ) ) ) ; "
"} "
"} ; "
"int main ( ) { "
"C<A> ca ; "
"return 0 ; "
"} "
"struct B<A> { "
"void f3 ( B<A> & other ) { } "
"} ; "
"int f1<B<A>> ( int x , B<A> * ) { "
"int id ; id = f2<B<A>> ( ) ; "
"return id ; "
"} "
"int f2<B<A>> ( ) { "
"return D<B<A>> :: f ( ) ; "
"} "
"struct D<B<A>> { "
"static int f ( ) { "
"return C<B<A>> :: f ( ) ; "
"} "
"} ; "
"struct C<A> { } ; struct E<void*> { "
"} ;";
ASSERT_EQUALS(expected, tok(code, false));
}
void template44() { // #5297
@ -1249,12 +1287,19 @@ private:
}
void template56() { // #7117
tok("template<bool B> struct Foo { "
" std::array<int, B ? 1 : 2> mfoo; "
"}; "
"void foo() { "
" Foo<true> myFoo; "
"}", /*simplify=*/true, /*debugwarnings=*/true);
const char code[] = "template<bool B> struct Foo { "
" std::array<int, B ? 1 : 2> mfoo; "
"}; "
"void foo() { "
" Foo<true> myFoo; "
"}";
const char expected[] = "struct Foo<true> ; "
"void foo ( ) { "
"Foo<true> myFoo ; "
"} struct Foo<true> { "
"std :: array < int , true ? 1 : 2 > mfoo ; "
"} ;";
ASSERT_EQUALS(expected, tok(code, false, true));
ASSERT_EQUALS("", errout.str());
}
@ -1389,7 +1434,26 @@ private:
" t_func<1>();\n"
"}\n"
"};";
tok(code); // don't crash
const char exp [] = "bool foo<int> ( ) ; "
"struct A { "
"void t_func<0> ( ) ; "
"void t_func<1> ( ) ; "
"void t_caller ( ) "
"{ "
"t_func<0> ( ) ; "
"t_func<1> ( ) ; "
"} "
"} ; "
"void A :: t_func<0> ( ) "
"{ "
"if ( 0 || foo<int> ( ) ) { ; } "
"} "
"void A :: t_func<1> ( ) "
"{ "
"if ( 1 ) { ; } "
"} "
"bool foo<int> ( ) { return true ; }";
ASSERT_EQUALS(exp, tok(code, false));
}
void template65() { // #8321 (crash)