2014-09-24 13:23:44 +02:00
/*
* Cppcheck - A tool for static C / C + + code analysis
2018-01-14 15:37:52 +01:00
* Copyright ( C ) 2007 - 2018 Cppcheck team .
2014-09-24 13:23:44 +02:00
*
* This program is free software : you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation , either version 3 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program . If not , see < http : //www.gnu.org/licenses/>.
*/
2017-05-27 04:33:47 +02:00
# include "config.h"
# include "platform.h"
2014-09-24 13:23:44 +02:00
# include "settings.h"
# include "templatesimplifier.h"
2017-05-27 04:33:47 +02:00
# include "testsuite.h"
# include "token.h"
# include "tokenize.h"
struct InternalError ;
2014-09-24 13:23:44 +02:00
class TestSimplifyTemplate : public TestFixture {
public :
2014-11-20 14:20:09 +01:00
TestSimplifyTemplate ( ) : TestFixture ( " TestSimplifyTemplate " ) {
2014-09-24 13:23:44 +02:00
}
private :
2015-10-07 18:33:57 +02:00
Settings settings ;
2014-09-24 13:23:44 +02:00
2019-01-12 15:45:25 +01:00
void run ( ) OVERRIDE {
2015-10-07 18:33:57 +02:00
settings . addEnabled ( " portability " ) ;
2014-09-24 13:23:44 +02:00
TEST_CASE ( template1 ) ;
TEST_CASE ( template2 ) ;
TEST_CASE ( template3 ) ;
TEST_CASE ( template4 ) ;
TEST_CASE ( template5 ) ;
TEST_CASE ( template6 ) ;
TEST_CASE ( template7 ) ;
TEST_CASE ( template8 ) ;
TEST_CASE ( template9 ) ;
TEST_CASE ( template10 ) ;
TEST_CASE ( template11 ) ;
TEST_CASE ( template12 ) ;
TEST_CASE ( template13 ) ;
TEST_CASE ( template14 ) ;
2016-01-30 11:22:44 +01:00
TEST_CASE ( template15 ) ; // recursive templates
2014-09-24 13:23:44 +02:00
TEST_CASE ( template16 ) ;
TEST_CASE ( template17 ) ;
TEST_CASE ( template18 ) ;
TEST_CASE ( template19 ) ;
TEST_CASE ( template20 ) ;
TEST_CASE ( template21 ) ;
TEST_CASE ( template22 ) ;
TEST_CASE ( template23 ) ;
TEST_CASE ( template24 ) ; // #2648 - using sizeof in template parameter
TEST_CASE ( template25 ) ; // #2648 - another test for sizeof template parameter
TEST_CASE ( template26 ) ; // #2721 - passing 'char[2]' as template parameter
TEST_CASE ( template27 ) ; // #3350 - removing unused template in macro call
TEST_CASE ( template28 ) ;
TEST_CASE ( template30 ) ; // #3529 - template < template < ..
TEST_CASE ( template31 ) ; // #4010 - reference type
TEST_CASE ( template32 ) ; // #3818 - mismatching template not handled well
TEST_CASE ( template33 ) ; // #3818,#4544 - inner templates in template instantiation not handled well
TEST_CASE ( template34 ) ; // #3706 - namespace => hang
TEST_CASE ( template35 ) ; // #4074 - A<'x'> a;
TEST_CASE ( template36 ) ; // #4310 - passing unknown template instantiation as template argument
TEST_CASE ( template37 ) ; // #4544 - A<class B> a;
TEST_CASE ( template38 ) ; // #4832 - crash on C++11 right angle brackets
TEST_CASE ( template39 ) ; // #4742 - freeze
TEST_CASE ( template40 ) ; // #5055 - template specialization outside struct
TEST_CASE ( template41 ) ; // #4710 - const in instantiation not handled perfectly
TEST_CASE ( template42 ) ; // #4878 - variadic templates
TEST_CASE ( template43 ) ; // #5097 - assert due to '>>' not treated as end of template instantiation
TEST_CASE ( template44 ) ; // #5297 - TemplateSimplifier::simplifyCalculations not eager enough
TEST_CASE ( template45 ) ; // #5814 - syntax error reported for valid code
TEST_CASE ( template46 ) ; // #5816 - syntax error reported for valid code
TEST_CASE ( template47 ) ; // #6023 - syntax error reported for valid code
TEST_CASE ( template48 ) ; // #6134 - 100% CPU upon invalid code
2014-11-01 22:07:24 +01:00
TEST_CASE ( template49 ) ; // #6237 - template instantiation
TEST_CASE ( template50 ) ; // #4272 - simple partial specialization
2014-12-14 13:50:32 +01:00
TEST_CASE ( template51 ) ; // #6172 - crash upon valid code
2015-03-14 18:46:17 +01:00
TEST_CASE ( template52 ) ; // #6437 - crash upon valid code
2015-03-15 00:28:33 +01:00
TEST_CASE ( template53 ) ; // #4335 - bail out for valid code
2015-03-21 16:30:00 +01:00
TEST_CASE ( template54 ) ; // #6587 - memory corruption upon valid code
2015-03-22 11:20:47 +01:00
TEST_CASE ( template55 ) ; // #6604 - simplify "const const" to "const" in template instantiations
2016-06-04 20:35:16 +02:00
TEST_CASE ( template56 ) ; // #7117 - const ternary operator simplification as template parameter
2017-02-05 17:30:24 +01:00
TEST_CASE ( template57 ) ; // #7891
2017-06-07 19:32:56 +02:00
TEST_CASE ( template58 ) ; // #6021 - use after free (deleted tokens in simplifyCalculations)
2017-06-08 19:22:01 +02:00
TEST_CASE ( template59 ) ; // #8051 - TemplateSimplifier::simplifyTemplateInstantiation failure
2017-12-25 08:19:46 +01:00
TEST_CASE ( template60 ) ; // handling of methods outside template definition
2018-01-03 23:05:57 +01:00
TEST_CASE ( template61 ) ; // daca2, kodi
2018-01-06 15:16:03 +01:00
TEST_CASE ( template62 ) ; // #8314 - inner template instantiation
2018-05-16 15:24:23 +02:00
TEST_CASE ( template63 ) ; // #8576 - qualified type
2018-09-01 11:26:10 +02:00
TEST_CASE ( template64 ) ; // #8683
TEST_CASE ( template65 ) ; // #8321
2018-09-02 08:35:05 +02:00
TEST_CASE ( template66 ) ; // #8725
2018-09-02 17:49:13 +02:00
TEST_CASE ( template67 ) ; // #8122
2018-09-26 06:23:12 +02:00
TEST_CASE ( template68 ) ; // union
2018-10-26 14:20:13 +02:00
TEST_CASE ( template69 ) ; // #8791
TEST_CASE ( template70 ) ; // #5289
2018-11-02 14:49:40 +01:00
TEST_CASE ( template71 ) ; // #8821
2018-11-23 11:36:09 +01:00
TEST_CASE ( template72 ) ;
TEST_CASE ( template73 ) ;
TEST_CASE ( template74 ) ;
TEST_CASE ( template75 ) ;
TEST_CASE ( template76 ) ;
TEST_CASE ( template77 ) ;
TEST_CASE ( template78 ) ;
TEST_CASE ( template79 ) ; // #5133
2018-11-26 06:23:12 +01:00
TEST_CASE ( template80 ) ;
TEST_CASE ( template81 ) ;
2018-11-27 06:17:04 +01:00
TEST_CASE ( template82 ) ; // 8603
2018-11-29 06:24:28 +01:00
TEST_CASE ( template83 ) ;
2018-12-06 21:47:48 +01:00
TEST_CASE ( template84 ) ; // #8880
2018-12-15 07:52:47 +01:00
TEST_CASE ( template85 ) ; // #8902 crash
2018-12-17 05:58:48 +01:00
TEST_CASE ( template86 ) ; // crash
2018-12-19 21:59:59 +01:00
TEST_CASE ( template87 ) ;
2018-12-29 11:19:53 +01:00
TEST_CASE ( template88 ) ; // #6183
TEST_CASE ( template89 ) ; // #8917
TEST_CASE ( template90 ) ; // crash
TEST_CASE ( template91 ) ;
2018-12-31 21:29:53 +01:00
TEST_CASE ( template92 ) ;
2019-01-02 07:15:45 +01:00
TEST_CASE ( template93 ) ; // crash
2019-01-05 11:14:09 +01:00
TEST_CASE ( template94 ) ; // #8927 crash
2019-01-18 21:12:39 +01:00
TEST_CASE ( template95 ) ; // #7417
TEST_CASE ( template96 ) ; // #7854
2019-01-23 08:53:01 +01:00
TEST_CASE ( template97 ) ;
2017-12-30 22:14:48 +01:00
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>> {..};
2015-08-14 18:27:03 +02:00
TEST_CASE ( template_enum ) ; // #6299 Syntax error in complex enum declaration (including template)
2014-09-24 13:23:44 +02:00
TEST_CASE ( template_unhandled ) ;
TEST_CASE ( template_default_parameter ) ;
2018-10-24 14:38:59 +02:00
TEST_CASE ( template_forward_declared_default_parameter ) ;
2014-09-24 13:23:44 +02:00
TEST_CASE ( template_default_type ) ;
TEST_CASE ( template_typename ) ;
TEST_CASE ( template_constructor ) ; // #3152 - template constructor is removed
2015-10-07 22:45:38 +02:00
TEST_CASE ( syntax_error_templates_1 ) ;
TEST_CASE ( template_member_ptr ) ; // Ticket #5786 - crash upon valid code
2017-12-26 10:55:18 +01:00
TEST_CASE ( template_namespace_1 ) ;
TEST_CASE ( template_namespace_2 ) ;
TEST_CASE ( template_namespace_3 ) ;
TEST_CASE ( template_namespace_4 ) ;
2017-12-30 09:00:19 +01:00
TEST_CASE ( template_namespace_5 ) ;
2018-10-26 14:20:13 +02:00
TEST_CASE ( template_namespace_6 ) ;
TEST_CASE ( template_namespace_7 ) ; // #8768
2018-11-05 19:55:21 +01:00
TEST_CASE ( template_namespace_8 ) ;
TEST_CASE ( template_namespace_9 ) ;
2018-11-07 21:25:42 +01:00
TEST_CASE ( template_namespace_10 ) ;
2018-11-10 16:41:14 +01:00
TEST_CASE ( template_namespace_11 ) ; // #7145
2014-09-24 13:23:44 +02:00
// Test TemplateSimplifier::templateParameters
TEST_CASE ( templateParameters ) ;
2015-03-07 21:52:12 +01:00
TEST_CASE ( templateNamePosition ) ;
2016-01-11 18:45:12 +01:00
2018-10-14 16:57:07 +02:00
TEST_CASE ( expandSpecialized1 ) ;
TEST_CASE ( expandSpecialized2 ) ;
TEST_CASE ( expandSpecialized3 ) ; // #8671
2018-10-15 19:35:26 +02:00
TEST_CASE ( expandSpecialized4 ) ;
2017-12-02 19:18:36 +01:00
2017-12-29 22:47:07 +01:00
TEST_CASE ( templateAlias1 ) ;
TEST_CASE ( templateAlias2 ) ;
2018-01-05 16:10:13 +01:00
TEST_CASE ( templateAlias3 ) ; // #8315
2017-12-29 22:47:07 +01:00
2017-12-02 19:18:36 +01:00
// Test TemplateSimplifier::instantiateMatch
TEST_CASE ( instantiateMatch ) ;
2018-05-30 17:09:31 +02:00
TEST_CASE ( templateParameterWithoutName ) ; // #8602 Template default parameter without name yields syntax error
2014-09-24 13:23:44 +02:00
}
2016-01-01 16:39:41 +01:00
std : : string tok ( const char code [ ] , bool simplify = true , bool debugwarnings = false , Settings : : PlatformType type = Settings : : Native ) {
2014-09-24 13:23:44 +02:00
errout . str ( " " ) ;
2015-03-15 00:28:33 +01:00
settings . debugwarnings = debugwarnings ;
2014-09-24 13:23:44 +02:00
settings . platform ( type ) ;
Tokenizer tokenizer ( & settings , this ) ;
std : : istringstream istr ( code ) ;
tokenizer . tokenize ( istr , " test.cpp " ) ;
if ( simplify )
tokenizer . simplifyTokenList2 ( ) ;
return tokenizer . tokens ( ) - > stringifyList ( 0 , ! simplify ) ;
}
2014-11-20 14:20:09 +01:00
std : : string tok ( const char code [ ] , const char filename [ ] ) {
2014-09-24 13:23:44 +02:00
errout . str ( " " ) ;
2015-10-07 18:33:57 +02:00
settings . debugwarnings = false ;
2014-09-24 13:23:44 +02:00
Tokenizer tokenizer ( & settings , this ) ;
std : : istringstream istr ( code ) ;
tokenizer . tokenize ( istr , filename ) ;
tokenizer . simplifyTokenList2 ( ) ;
return tokenizer . tokens ( ) - > stringifyList ( 0 , false ) ;
}
2014-11-20 14:20:09 +01:00
void template1 ( ) {
2016-02-14 13:32:58 +01:00
const char code [ ] = " template <class T> void f(T val) { T a; } \n "
2014-09-24 13:23:44 +02:00
" f<int>(10); " ;
2018-11-23 11:36:09 +01:00
const char expected [ ] = " void f<int> ( int val ) ; "
" f<int> ( 10 ) ; "
2017-12-25 23:16:51 +01:00
" void f<int> ( int val ) { } " ;
2014-09-24 13:23:44 +02:00
ASSERT_EQUALS ( expected , tok ( code ) ) ;
}
2014-11-20 14:20:09 +01:00
void template2 ( ) {
2016-02-14 13:32:58 +01:00
const char code [ ] = " template <class T> class Fred { T a; }; \n "
2014-09-24 13:23:44 +02:00
" Fred<int> fred; " ;
2018-11-07 21:25:42 +01:00
const char expected [ ] = " class Fred<int> ; "
" Fred<int> fred ; "
2017-12-25 23:16:51 +01:00
" class Fred<int> { int a ; } ; " ;
2014-09-24 13:23:44 +02:00
ASSERT_EQUALS ( expected , tok ( code ) ) ;
}
2014-11-20 14:20:09 +01:00
void template3 ( ) {
2016-02-14 13:32:58 +01:00
const char code [ ] = " template <class T, int sz> class Fred { T data[sz]; }; \n "
2014-09-24 13:23:44 +02:00
" Fred<float,4> fred; " ;
2018-11-07 21:25:42 +01:00
const char expected [ ] = " class Fred<float,4> ; "
" Fred<float,4> fred ; "
2017-12-25 23:16:51 +01:00
" class Fred<float,4> { float data [ 4 ] ; } ; " ;
2014-09-24 13:23:44 +02:00
ASSERT_EQUALS ( expected , tok ( code ) ) ;
}
2014-11-20 14:20:09 +01:00
void template4 ( ) {
2016-02-14 13:32:58 +01:00
const char code [ ] = " template <class T> class Fred { Fred(); }; \n "
2014-09-24 13:23:44 +02:00
" Fred<float> fred; " ;
2018-11-07 21:25:42 +01:00
const char expected [ ] = " class Fred<float> ; "
" Fred<float> fred ; "
2017-12-25 23:16:51 +01:00
" class Fred<float> { Fred<float> ( ) ; } ; " ;
2014-09-24 13:23:44 +02:00
ASSERT_EQUALS ( expected , tok ( code ) ) ;
}
2014-11-20 14:20:09 +01:00
void template5 ( ) {
2016-02-14 13:32:58 +01:00
const char code [ ] = " template <class T> class Fred { }; \n "
" template <class T> Fred<T>::Fred() { } \n "
2014-09-24 13:23:44 +02:00
" Fred<float> fred; " ;
2018-11-07 21:25:42 +01:00
const char expected [ ] = " class Fred<float> ; "
" Fred<float> fred ; "
2017-12-25 23:16:51 +01:00
" class Fred<float> { } ; "
2018-09-02 17:49:13 +02:00
" Fred<float> :: Fred<float> ( ) { } " ;
2014-09-24 13:23:44 +02:00
2018-09-14 14:16:34 +02:00
ASSERT_EQUALS ( expected , tok ( code ) ) ;
2014-09-24 13:23:44 +02:00
}
2014-11-20 14:20:09 +01:00
void template6 ( ) {
2016-02-14 13:32:58 +01:00
const char code [ ] = " template <class T> class Fred { }; \n "
2014-09-24 13:23:44 +02:00
" Fred<float> fred1; \n "
" Fred<float> fred2; " ;
2018-11-07 21:25:42 +01:00
const char expected [ ] = " class Fred<float> ; "
" Fred<float> fred1 ; "
2017-12-25 23:16:51 +01:00
" Fred<float> fred2 ; "
" class Fred<float> { } ; " ;
2014-09-24 13:23:44 +02:00
ASSERT_EQUALS ( expected , tok ( code ) ) ;
}
2014-11-20 14:20:09 +01:00
void template7 ( ) {
2014-09-24 13:23:44 +02:00
// A template class that is not used => no simplification
{
const char code [ ] = " template <class T> \n "
" class ABC \n "
" { \n "
" public: \n "
" typedef ABC<T> m; \n "
" }; \n " ;
2015-03-15 12:36:40 +01:00
const char expected [ ] = " template < class T > class ABC { public: } ; " ;
2014-09-24 13:23:44 +02:00
ASSERT_EQUALS ( expected , tok ( code ) ) ;
}
{
const char code [ ] = " template <typename T> class ABC { \n "
" public: \n "
" typedef std::vector<T> type; \n "
" }; \n "
" int main() { \n "
" ABC<int>::type v; \n "
" v.push_back(4); \n "
" return 0; \n "
" } \n " ;
2015-03-15 12:36:40 +01:00
const char wanted [ ] = " template < typename T > class ABC { public: } ; "
" int main ( ) { "
" std :: vector < int > v ; "
" v . push_back ( 4 ) ; "
" return 0 ; "
" } " ;
2014-09-24 13:23:44 +02:00
2015-03-15 12:36:40 +01:00
const char current [ ] = " template < typename T > class ABC { public: } ; "
" int main ( ) { "
" ABC < int > :: type v ; "
" v . push_back ( 4 ) ; "
" return 0 ; "
" } " ;
2014-09-24 13:23:44 +02:00
TODO_ASSERT_EQUALS ( wanted , current , tok ( code ) ) ;
}
{
const char code [ ] = " template <typename T> class ABC { \n "
" public: \n "
" typedef std::vector<T> type; \n "
" void f() \n "
" { \n "
" ABC<int>::type v; \n "
" v.push_back(4); \n "
" } \n "
" }; \n " ;
2015-03-15 12:36:40 +01:00
const char expected [ ] = " template < typename T > class ABC { "
" public: void f ( ) { "
" ABC < int > :: type v ; "
" v . push_back ( 4 ) ; "
" } "
" } ; " ;
2014-09-24 13:23:44 +02:00
ASSERT_EQUALS ( expected , tok ( code ) ) ;
}
}
// Template definitions but no usage => no expansion
2014-11-20 14:20:09 +01:00
void template8 ( ) {
2014-09-24 13:23:44 +02:00
const char code [ ] = " template<typename T> class A; \n "
" template<typename T> class B; \n "
" \n "
" typedef A<int> x; \n "
" typedef B<int> y; \n "
" \n "
" template<typename T> class A { \n "
" void f() { \n "
" B<T> a = B<T>::g(); \n "
" T b = 0; \n "
" if (b) \n "
" b = 0; \n "
" } \n "
" }; \n "
" \n "
" template<typename T> inline B<T> h() { return B<T>(); } \n " ;
ASSERT_EQUALS ( " template < typename T > class A ; "
" template < typename T > class B ; "
" template < typename T > class A { void f ( ) { B < T > a ; a = B < T > :: g ( ) ; T b ; b = 0 ; } } ; "
" template < typename T > B < T > h ( ) { return B < T > ( ) ; } " , tok ( code ) ) ;
ASSERT_EQUALS ( " class A { template < typename T > int foo ( T d ) ; } ; " , tok ( " class A{ template<typename T> int foo(T d);}; " ) ) ;
}
2014-11-20 14:20:09 +01:00
void template9 ( ) {
2014-09-24 13:23:44 +02:00
const char code [ ] = " template < typename T > class A { } ; \n "
" \n "
" void f ( ) { \n "
2017-02-05 17:30:24 +01:00
" A < int > a ; \n "
2014-09-24 13:23:44 +02:00
" } \n "
" \n "
" template < typename T > \n "
" class B { \n "
" void g ( ) { \n "
" A < T > b = A < T > :: h ( ) ; \n "
" } \n "
" } ; \n " ;
// The expected result..
2018-11-07 21:25:42 +01:00
const char expected [ ] = " class A<int> ; "
" void f ( ) { A<int> a ; } "
2017-02-05 17:30:24 +01:00
" template < typename T > class B { void g ( ) { A < T > b ; b = A < T > :: h ( ) ; } } ; "
2017-12-25 23:16:51 +01:00
" class A<int> { } ; " ;
2014-09-24 13:23:44 +02:00
ASSERT_EQUALS ( expected , tok ( code ) ) ;
}
2014-11-20 14:20:09 +01:00
void template10 ( ) {
2014-09-24 13:23:44 +02:00
const char code [ ] = " template <int ui, typename T> T * foo() \n "
" { return new T[ui]; } \n "
" \n "
" void f ( ) \n "
" { \n "
" foo<3,int>(); \n "
" } \n " ;
// The expected result..
2018-11-23 11:36:09 +01:00
const char expected [ ] = " int * foo<3,int> ( ) ; "
" void f ( ) "
2015-03-15 12:36:40 +01:00
" { "
2017-12-25 23:16:51 +01:00
" foo<3,int> ( ) ; "
2015-03-15 12:36:40 +01:00
" } "
2017-12-25 23:16:51 +01:00
" int * foo<3,int> ( ) { return new int [ 3 ] ; } " ;
2014-09-24 13:23:44 +02:00
ASSERT_EQUALS ( expected , tok ( code ) ) ;
}
2014-11-20 14:20:09 +01:00
void template11 ( ) {
2014-09-24 13:23:44 +02:00
const char code [ ] = " template <int ui, typename T> T * foo() \n "
" { return new T[ui]; } \n "
" \n "
" void f ( ) \n "
" { \n "
" char * p = foo<3,char>(); \n "
" } \n " ;
// The expected result..
2018-11-23 11:36:09 +01:00
const char expected [ ] = " char * foo<3,char> ( ) ; "
" void f ( ) "
2015-03-15 12:36:40 +01:00
" { "
2017-12-25 23:16:51 +01:00
" char * p ; p = foo<3,char> ( ) ; "
2015-03-15 12:36:40 +01:00
" } "
2017-12-25 23:16:51 +01:00
" char * foo<3,char> ( ) { return new char [ 3 ] ; } " ;
2014-09-24 13:23:44 +02:00
ASSERT_EQUALS ( expected , tok ( code ) ) ;
}
2014-11-20 14:20:09 +01:00
void template12 ( ) {
2014-09-24 13:23:44 +02:00
const char code [ ] = " template <int x, int y, int z> \n "
" class A : public B<x, y, (x - y) ? ((y < z) ? 1 : -1) : 0> \n "
" { }; \n "
" \n "
" void f() \n "
" { \n "
" A<12,12,11> a; \n "
" } \n " ;
// The expected result..
2018-11-07 21:25:42 +01:00
const char expected [ ] = " class A<12,12,11> ; "
" void f ( ) "
2015-03-15 12:36:40 +01:00
" { "
2017-12-25 23:16:51 +01:00
" A<12,12,11> a ; "
2015-03-15 12:36:40 +01:00
" } "
2017-12-25 23:16:51 +01:00
" class A<12,12,11> : public B < 12 , 12 , 0 > "
2015-03-15 12:36:40 +01:00
" { } ; " ;
2014-09-24 13:23:44 +02:00
ASSERT_EQUALS ( expected , tok ( code ) ) ;
}
2014-11-20 14:20:09 +01:00
void template13 ( ) {
2014-09-24 13:23:44 +02:00
const char code [ ] = " class BB {}; \n "
" \n "
" template <class T> \n "
" class AA \n "
" { \n "
" public: \n "
" static AA<T> create(T* newObject); \n "
" static int size(); \n "
" }; \n "
" \n "
" class CC { public: CC(AA<BB>, int) {} }; \n "
" \n "
" class XX { \n "
" AA<CC> y; \n "
" public: \n "
" XX(); \n "
" }; \n "
" \n "
" XX::XX(): \n "
" y(AA<CC>::create(new CC(AA<BB>(), 0))) \n "
" {} \n "
" \n "
" int yy[AA<CC>::size()]; " ;
// Just run it and check that there are not assertions.
tok ( code ) ;
}
2014-11-20 14:20:09 +01:00
void template14 ( ) {
2014-09-24 13:23:44 +02:00
const char code [ ] = " template <> void foo<int *>() \n "
" { x(); } \n "
" \n "
" int main() \n "
" { \n "
" foo<int*>(); \n "
" } \n " ;
// The expected result..
2018-12-29 11:19:53 +01:00
const char expected [ ] = " void foo<int*> ( ) ; "
" void foo<int*> ( ) "
2015-03-15 12:36:40 +01:00
" { x ( ) ; } "
" int main ( ) "
2017-12-25 23:16:51 +01:00
" { foo<int*> ( ) ; } " ;
2014-09-24 13:23:44 +02:00
ASSERT_EQUALS ( expected , tok ( code ) ) ;
}
2016-01-30 11:22:44 +01:00
void template15 ( ) { // recursive templates #3130 etc
2014-09-24 13:23:44 +02:00
const char code [ ] = " template <unsigned int i> void a() \n "
" { \n "
" a<i-1>(); \n "
" } \n "
" \n "
" template <> void a<0>() \n "
" { } \n "
" \n "
" int main() \n "
" { \n "
" a<2>(); \n "
" return 0; \n "
" } \n " ;
// The expected result..
2018-12-31 17:19:34 +01:00
const char expected [ ] = " void a<0> ( ) ; "
" void a<2> ( ) ; "
2018-11-23 11:36:09 +01:00
" void a<1> ( ) ; "
" void a<0> ( ) { } "
2015-03-15 12:36:40 +01:00
" int main ( ) "
2017-12-25 23:16:51 +01:00
" { a<2> ( ) ; return 0 ; } "
" void a<2> ( ) { a<1> ( ) ; } "
" void a<1> ( ) { a<0> ( ) ; } " ;
2014-09-24 13:23:44 +02:00
ASSERT_EQUALS ( expected , tok ( code ) ) ;
2016-01-30 11:22:44 +01:00
// #3130
const char code2 [ ] = " template <int n> struct vec { \n "
" vec() {} \n "
2016-11-27 11:40:42 +01:00
" vec(const vec<n-1>& v) {} \n " // <- never used don't instantiate
2016-01-30 11:22:44 +01:00
" }; \n "
" \n "
" vec<4> v; " ;
2018-11-07 21:25:42 +01:00
const char expected2 [ ] = " struct vec<4> ; "
" vec<4> v ; "
2017-12-25 23:16:51 +01:00
" struct vec<4> { "
" vec<4> ( ) { } "
" vec<4> ( const vec < 4 - 1 > & v ) { } "
2016-01-30 11:22:44 +01:00
" } ; " ;
ASSERT_EQUALS ( expected2 , tok ( code2 ) ) ;
2014-09-24 13:23:44 +02:00
}
2014-11-20 14:20:09 +01:00
void template16 ( ) {
2014-09-24 13:23:44 +02:00
const char code [ ] = " template <unsigned int i> void a() \n "
" { } \n "
" \n "
" template <unsigned int i> void b() \n "
" { a<i>(); } \n "
" \n "
" int main() \n "
" { \n "
" b<2>(); \n "
" return 0; \n "
" } \n " ;
2018-11-23 11:36:09 +01:00
const char expected [ ] = " void a<2> ( ) ; "
" void b<2> ( ) ; "
" int main ( ) { b<2> ( ) ; return 0 ; } "
2017-12-25 23:16:51 +01:00
" void b<2> ( ) { a<2> ( ) ; } "
" void a<2> ( ) { } " ;
2014-09-24 13:23:44 +02:00
ASSERT_EQUALS ( expected , tok ( code ) ) ;
}
2014-11-20 14:20:09 +01:00
void template17 ( ) {
2014-09-24 13:23:44 +02:00
const char code [ ] = " template<class T> \n "
" class Fred \n "
" { \n "
" template<class T> \n "
" static shared_ptr< Fred<T> > CreateFred() \n "
" { \n "
" } \n "
" }; \n "
" \n "
" shared_ptr<int> i; \n " ;
// Assert that there is no segmentation fault..
tok ( code ) ;
}
2014-11-20 14:20:09 +01:00
void template18 ( ) {
2014-09-24 13:23:44 +02:00
const char code [ ] = " template <class T> class foo { T a; }; \n "
" foo<int> *f; " ;
2018-11-07 21:25:42 +01:00
const char expected [ ] = " class foo<int> ; "
" foo<int> * f ; "
2017-12-25 23:16:51 +01:00
" class foo<int> { int a ; } ; " ;
2014-09-24 13:23:44 +02:00
ASSERT_EQUALS ( expected , tok ( code ) ) ;
}
2014-11-20 14:20:09 +01:00
void template19 ( ) {
2014-09-24 13:23:44 +02:00
const char code [ ] = " template <typename T> T & foo() \n "
" { static T temp; return temp; } \n "
" \n "
" void f ( ) \n "
" { \n "
" char p = foo<char>(); \n "
" } \n " ;
// The expected result..
2018-11-23 11:36:09 +01:00
const char expected [ ] = " char & foo<char> ( ) ; "
" void f ( ) "
2015-03-15 12:36:40 +01:00
" { "
2017-12-25 23:16:51 +01:00
" char p ; p = foo<char> ( ) ; "
2015-03-15 12:36:40 +01:00
" } "
2017-12-25 23:16:51 +01:00
" char & foo<char> ( ) { static char temp ; return temp ; } " ;
2014-09-24 13:23:44 +02:00
ASSERT_EQUALS ( expected , tok ( code ) ) ;
}
2014-11-20 14:20:09 +01:00
void template20 ( ) {
2014-09-24 13:23:44 +02:00
// Ticket #1788 - the destructor implementation is lost
2018-01-06 15:16:03 +01:00
const char code [ ] = " template <class T> class A { public: ~A(); }; \n "
" template <class T> A<T>::~A() {} \n "
2014-09-24 13:23:44 +02:00
" A<int> a; \n " ;
// The expected result..
2018-11-07 21:25:42 +01:00
const char expected [ ] = " class A<int> ; "
" A<int> a ; "
2017-12-25 23:16:51 +01:00
" class A<int> { public: ~ A<int> ( ) ; } ; "
" A<int> :: ~ A<int> ( ) { } " ;
2014-09-24 13:23:44 +02:00
ASSERT_EQUALS ( expected , tok ( code ) ) ;
}
2014-11-20 14:20:09 +01:00
void template21 ( ) {
2014-09-24 13:23:44 +02:00
{
2016-02-14 13:32:58 +01:00
const char code [ ] = " template <class T> struct Fred { T a; }; \n "
2014-09-24 13:23:44 +02:00
" Fred<int> fred; " ;
2018-11-07 21:25:42 +01:00
const char expected [ ] = " struct Fred<int> ; "
" Fred<int> fred ; "
2017-12-25 23:16:51 +01:00
" struct Fred<int> { int a ; } ; " ;
2014-09-24 13:23:44 +02:00
ASSERT_EQUALS ( expected , tok ( code ) ) ;
}
{
2016-02-14 13:32:58 +01:00
const char code [ ] = " template <class T, int sz> struct Fred { T data[sz]; }; \n "
2014-09-24 13:23:44 +02:00
" Fred<float,4> fred; " ;
2018-11-07 21:25:42 +01:00
const char expected [ ] = " struct Fred<float,4> ; "
" Fred<float,4> fred ; "
2017-12-25 23:16:51 +01:00
" struct Fred<float,4> { float data [ 4 ] ; } ; " ;
2014-09-24 13:23:44 +02:00
ASSERT_EQUALS ( expected , tok ( code ) ) ;
}
{
2016-02-14 13:32:58 +01:00
const char code [ ] = " template <class T> struct Fred { Fred(); }; \n "
2014-09-24 13:23:44 +02:00
" Fred<float> fred; " ;
2018-11-07 21:25:42 +01:00
const char expected [ ] = " struct Fred<float> ; "
" Fred<float> fred ; "
2017-12-25 23:16:51 +01:00
" struct Fred<float> { Fred<float> ( ) ; } ; " ;
2014-09-24 13:23:44 +02:00
ASSERT_EQUALS ( expected , tok ( code ) ) ;
}
{
2016-02-14 13:32:58 +01:00
const char code [ ] = " template <class T> struct Fred { }; \n "
2014-09-24 13:23:44 +02:00
" Fred<float> fred1; \n "
" Fred<float> fred2; " ;
2018-11-07 21:25:42 +01:00
const char expected [ ] = " struct Fred<float> ; "
" Fred<float> fred1 ; "
2017-12-25 23:16:51 +01:00
" Fred<float> fred2 ; "
" struct Fred<float> { } ; " ;
2014-09-24 13:23:44 +02:00
ASSERT_EQUALS ( expected , tok ( code ) ) ;
}
}
2014-11-20 14:20:09 +01:00
void template22 ( ) {
2016-02-14 13:32:58 +01:00
const char code [ ] = " template <class T> struct Fred { T a; }; \n "
2014-09-24 13:23:44 +02:00
" Fred<std::string> fred; " ;
2018-11-07 21:25:42 +01:00
const char expected [ ] = " struct Fred<std::string> ; "
" Fred<std::string> fred ; "
2017-12-25 23:16:51 +01:00
" struct Fred<std::string> { std :: string a ; } ; " ;
2014-09-24 13:23:44 +02:00
ASSERT_EQUALS ( expected , tok ( code ) ) ;
}
2014-11-20 14:20:09 +01:00
void template23 ( ) {
2016-02-14 13:32:58 +01:00
const char code [ ] = " template <class T> void foo() { } \n "
2014-09-24 13:23:44 +02:00
" void bar() { \n "
" std::cout << (foo<double>()); \n "
" } " ;
2018-11-23 11:36:09 +01:00
const char expected [ ] = " void foo<double> ( ) ; "
" void bar ( ) { "
2017-12-25 23:16:51 +01:00
" std :: cout << ( foo<double> ( ) ) ; "
2015-03-15 12:36:40 +01:00
" } "
2017-12-25 23:16:51 +01:00
" void foo<double> ( ) { } " ;
2014-09-24 13:23:44 +02:00
ASSERT_EQUALS ( expected , tok ( code ) ) ;
}
2014-11-20 14:20:09 +01:00
void template24 ( ) {
2014-09-24 13:23:44 +02:00
// #2648
const char code [ ] = " template<int n> struct B \n "
" { \n "
" int a[n]; \n "
" }; \n "
" \n "
" template<int x> class bitset: B<sizeof(int)> \n "
" {}; \n "
" \n "
" bitset<1> z; " ;
2018-11-07 21:25:42 +01:00
const char expected [ ] = " struct B<4> ; "
" class bitset<1> ; "
2018-10-26 14:20:13 +02:00
" bitset<1> z ; "
2017-12-25 23:16:51 +01:00
" class bitset<1> : B<4> { } ; "
" struct B<4> { int a [ 4 ] ; } ; " ;
2014-09-24 13:23:44 +02:00
ASSERT_EQUALS ( expected , tok ( code ) ) ;
}
2014-11-20 14:20:09 +01:00
void template25 ( ) {
2014-09-24 13:23:44 +02:00
const char code [ ] = " template<int n> struct B \n "
" { \n "
" int a[n]; \n "
" }; \n "
" \n "
" template<int x> class bitset: B<((sizeof(int)) ? : 1)> \n "
" {}; \n "
" \n "
" bitset<1> z; " ;
const char actual [ ] = " template < int n > struct B { int a [ n ] ; } ; "
2018-10-26 14:20:13 +02:00
" class bitset<1> ; "
2017-12-25 23:16:51 +01:00
" bitset<1> z ; "
" class bitset<1> : B < 4 > { } ; " ;
2014-09-24 13:23:44 +02:00
2018-10-26 14:20:13 +02:00
const char expected [ ] = " class bitset<1> ; "
" bitset<1> z ; "
2017-12-25 23:16:51 +01:00
" class bitset<1> : B < 4 > { } ; "
2017-02-05 17:30:24 +01:00
" struct B < 4 > { int a [ 4 ] ; } ; " ;
2014-09-24 13:23:44 +02:00
TODO_ASSERT_EQUALS ( expected , actual , tok ( code ) ) ;
}
2014-11-20 14:20:09 +01:00
void template26 ( ) {
2014-09-24 13:23:44 +02:00
// #2721
const char code [ ] = " template<class T> \n "
" class A { public: T x; }; \n "
" \n "
" template<class M> \n "
" class C: public A<char[M]> {}; \n "
" \n "
" C<2> a; \n " ;
// TODO: expand A also
2018-10-26 14:20:13 +02:00
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 ) ) ;
2014-09-24 13:23:44 +02:00
}
2014-11-20 14:20:09 +01:00
void template27 ( ) {
2014-09-24 13:23:44 +02:00
// #3350 - template inside macro call
const char code [ ] = " X(template<class T> class Fred); " ;
2017-12-29 22:47:07 +01:00
ASSERT_THROW ( tok ( code ) , InternalError ) ;
2014-09-24 13:23:44 +02:00
}
2014-11-20 14:20:09 +01:00
void template28 ( ) {
2014-09-24 13:23:44 +02:00
// #3226 - inner template
const char code [ ] = " template<class A, class B> class Fred {}; \n "
" Fred<int,Fred<int,int> > x; \n " ;
2018-11-07 21:25:42 +01:00
ASSERT_EQUALS ( " class Fred<int,int> ; "
" class Fred<int,Fred<int,int>> ; "
" Fred<int,Fred<int,int>> x ; "
" class Fred<int,int> { } ; "
" class Fred<int,Fred<int,int>> { } ; " , tok ( code ) ) ;
2014-09-24 13:23:44 +02:00
}
2014-11-20 14:20:09 +01:00
void template30 ( ) {
2014-09-24 13:23:44 +02:00
// #3529 - template < template < ..
const char code [ ] = " template<template<class> class A, class B> void f(){} " ;
ASSERT_EQUALS ( " template < template < class > class A , class B > void f ( ) { } " , tok ( code ) ) ;
}
2014-11-20 14:20:09 +01:00
void template31 ( ) {
2014-09-24 13:23:44 +02:00
// #4010 - template reference type
const char code [ ] = " template<class T> struct A{}; A<int&> a; " ;
2018-11-07 21:25:42 +01:00
ASSERT_EQUALS ( " struct A<int&> ; "
" A<int&> a ; "
" struct A<int&> { } ; " , tok ( code ) ) ;
2016-03-18 11:09:41 +01:00
// #7409 - rvalue
const char code2 [ ] = " template<class T> struct A{}; A<int&&> a; " ;
2018-11-07 21:25:42 +01:00
ASSERT_EQUALS ( " struct A<int&&> ; "
" A<int&&> a ; "
" struct A<int&&> { } ; " , tok ( code2 ) ) ;
2014-09-24 13:23:44 +02:00
}
2014-11-20 14:20:09 +01:00
void template32 ( ) {
2014-09-24 13:23:44 +02:00
// #3818 - mismatching template not handled well
const char code [ ] = " template <class T1, class T2, class T3, class T4 > struct A { }; \n "
" \n "
" template <class T> \n "
" struct B \n "
" { \n "
" public: \n "
" A < int, Pair<T, int>, int > a; \n " // mismatching parameters => don't instantiate
" }; \n "
" \n "
" B<int> b; \n " ;
ASSERT_EQUALS ( " template < class T1 , class T2 , class T3 , class T4 > struct A { } ; "
2018-10-26 14:20:13 +02:00
" struct B<int> ; "
2017-12-25 23:16:51 +01:00
" B<int> b ; "
" struct B<int> { public: A < int , Pair < int , int > , int > a ; } ; " , tok ( code ) ) ;
2014-09-24 13:23:44 +02:00
}
2014-11-20 14:20:09 +01:00
void template33 ( ) {
2014-09-24 13:23:44 +02:00
{
// #3818 - inner templates in template instantiation not handled well
const char code [ ] = " template<class T> struct A { }; \n "
" template<class T> struct B { }; \n "
" template<class T> struct C { A<B<X<T> > > ab; }; \n "
" C<int> c; " ;
2018-11-07 21:25:42 +01:00
ASSERT_EQUALS ( " struct A<B<X<int>>> ; "
" struct B<X<int>> ; "
2018-10-26 14:20:13 +02:00
" struct C<int> ; "
" C<int> c ; "
2017-12-26 22:34:39 +01:00
" struct C<int> { A<B<X<int>>> ab ; } ; "
2017-12-25 23:16:51 +01:00
" struct B<X<int>> { } ; " // <- redundant.. but nevermind
" struct A<B<X<int>>> { } ; " , tok ( code ) ) ;
2014-09-24 13:23:44 +02:00
}
{
// #4544
const char code [ ] = " struct A { }; \n "
" template<class T> struct B { }; \n "
" template<class T> struct C { }; \n "
" C< B<A> > c; " ;
ASSERT_EQUALS ( " struct A { } ; "
" template < class T > struct B { } ; " // <- redundant.. but nevermind
2018-10-26 14:20:13 +02:00
" struct C<B<A>> ; "
" C<B<A>> c ; "
" struct C<B<A>> { } ; " ,
2014-09-24 13:23:44 +02:00
tok ( code ) ) ;
}
}
2014-11-20 14:20:09 +01:00
void template34 ( ) {
2014-09-24 13:23:44 +02:00
// #3706 - namespace => hang
const char code [ ] = " namespace abc { \n "
" template <typename T> struct X { void f(X<T> &x) {} }; \n "
" } \n "
" template <> int X<int>::Y(0); " ;
2018-10-26 14:20:13 +02:00
tok ( code ) ;
2014-09-24 13:23:44 +02:00
}
2014-11-20 14:20:09 +01:00
void template35 ( ) { // #4074 - "A<'x'> a;" is not recognized as template instantiation
2014-09-24 13:23:44 +02:00
const char code [ ] = " template <char c> class A {}; \n "
2017-02-05 17:30:24 +01:00
" A <'x'> a; " ;
2018-11-07 21:25:42 +01:00
ASSERT_EQUALS ( " class A<'x'> ; "
" A<'x'> a ; "
" class A<'x'> { } ; " , tok ( code ) ) ;
2014-09-24 13:23:44 +02:00
}
2014-11-20 14:20:09 +01:00
void template36 ( ) { // #4310 - Passing unknown template instantiation as template argument
2014-09-24 13:23:44 +02:00
const char code [ ] = " template <class T> struct X { T t; }; \n "
" template <class C> struct Y { Foo < X< Bar<C> > > _foo; }; \n " // <- Bar is unknown
" Y<int> bar; " ;
2018-11-07 21:25:42 +01:00
ASSERT_EQUALS ( " struct X<Bar<int>> ; "
" struct Y<int> ; "
2018-10-26 14:20:13 +02:00
" Y<int> bar ; "
2017-12-25 23:16:51 +01:00
" struct Y<int> { Foo < X<Bar<int>> > _foo ; } ; "
" struct X<Bar<int>> { Bar < int > t ; } ; " ,
2014-09-24 13:23:44 +02:00
tok ( code ) ) ;
}
2014-11-20 14:20:09 +01:00
void template37 ( ) { // #4544 - A<class B> a;
2017-04-17 11:24:28 +02:00
{
const char code [ ] = " class A { }; \n "
" template<class T> class B {}; \n "
" B<class A> b1; \n "
" B<A> b2; " ;
2018-10-26 14:20:13 +02:00
ASSERT_EQUALS ( " class A { } ; class B<A> ; B<A> b1 ; B<A> b2 ; class B<A> { } ; " ,
2017-04-17 11:24:28 +02:00
tok ( code ) ) ;
}
{
const char code [ ] = " struct A { }; \n "
" template<class T> class B {}; \n "
" B<struct A> b1; \n "
" B<A> b2; " ;
2018-10-26 14:20:13 +02:00
ASSERT_EQUALS ( " struct A { } ; class B<A> ; B<A> b1 ; B<A> b2 ; class B<A> { } ; " ,
2017-04-17 11:24:28 +02:00
tok ( code ) ) ;
}
{
const char code [ ] = " enum A { }; \n "
" template<class T> class B {}; \n "
" B<enum A> b1; \n "
" B<A> b2; " ;
2018-10-26 14:20:13 +02:00
ASSERT_EQUALS ( " enum A { } ; class B<A> ; B<A> b1 ; B<A> b2 ; class B<A> { } ; " ,
2017-04-17 11:24:28 +02:00
tok ( code ) ) ;
}
2014-09-24 13:23:44 +02:00
}
2014-11-20 14:20:09 +01:00
void template_unhandled ( ) {
2014-09-24 13:23:44 +02:00
// An unhandled template usage should be simplified..
ASSERT_EQUALS ( " x<int> ( ) ; " , tok ( " x<int>(); " ) ) ;
}
2014-11-20 14:20:09 +01:00
void template38 ( ) { // #4832 - Crash on C++11 right angle brackets
2014-09-24 13:23:44 +02:00
const char code [ ] = " template <class T> class A { \n "
" T mT; \n "
" public: \n "
" void foo() {} \n "
" }; \n "
" \n "
" int main() { \n "
" A<A<BLA>> gna1; \n "
" A<BLA> gna2; \n "
" } \n " ;
tok ( code ) ; // Don't crash or freeze
}
2014-11-20 14:20:09 +01:00
void template39 ( ) { // #4742 - Used to freeze in 1.60
2014-09-24 13:23:44 +02:00
const char code [ ] = " template<typename T> struct vector { "
" operator T() const; "
" }; "
" void f() { "
" vector<vector<int>> v; "
" const vector<int> vi = static_cast<vector<int>>(v); "
" } " ;
tok ( code ) ;
}
2014-11-20 14:20:09 +01:00
void template40 ( ) { // #5055 - false negatives when there is template specialization outside struct
2014-09-24 13:23:44 +02:00
const char code [ ] = " struct A { "
" template<typename T> struct X { T t; }; "
" }; "
" template<> struct A::X<int> { int *t; }; " ;
2019-01-05 11:14:09 +01:00
ASSERT_EQUALS ( " struct A { struct X<int> ; } ; struct A :: X<int> { int t ; } ; " , tok ( code ) ) ;
2014-09-24 13:23:44 +02:00
}
2014-11-20 14:20:09 +01:00
void template41 ( ) { // #4710 - const in template instantiation not handled perfectly
2014-09-24 13:23:44 +02:00
const char code1 [ ] = " template<class T> struct X { }; \n "
" void f(const X<int> x) { } " ;
2018-11-07 21:25:42 +01:00
ASSERT_EQUALS ( " struct X<int> ; "
" void f ( const X<int> x ) { } "
" struct X<int> { } ; " , tok ( code1 ) ) ;
2014-09-24 13:23:44 +02:00
const char code2 [ ] = " template<class T> T f(T t) { return t; } \n "
" int x() { return f<int>(123); } " ;
2018-11-23 11:36:09 +01:00
ASSERT_EQUALS ( " int f<int> ( int t ) ; "
" int x ( ) { return f<int> ( 123 ) ; } "
" int f<int> ( int t ) { return t ; } " , tok ( code2 ) ) ;
2014-09-24 13:23:44 +02:00
}
2014-11-20 14:20:09 +01:00
void template42 ( ) { // #4878 cpcheck aborts in ext-blocks.cpp (clang testcode)
2014-09-24 13:23:44 +02:00
const char code [ ] = " template<typename ...Args> \n "
" int f0(Args ...args) { \n "
" return ^ { \n "
" return sizeof...(Args); \n "
" }() + ^ { \n "
" return sizeof...(args); \n "
" }(); \n "
" } " ;
2015-11-02 22:14:41 +01:00
tok ( code ) ;
2014-09-24 13:23:44 +02:00
}
2014-11-20 14:20:09 +01:00
void template43 ( ) { // #5097 - Assert due to '>>' in 'B<A<C>>' not being treated as end of template instantation
2014-09-24 13:23:44 +02:00
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
}
2014-11-20 14:20:09 +01:00
void template44 ( ) { // #5297
2014-09-24 13:23:44 +02:00
tok ( " template<class T> struct StackContainer { "
" void foo(int i) { "
" if (0 >= 1 && i<0) {} "
" } "
" }; "
" template<class T> class ZContainer : public StackContainer<T> {}; "
" struct FGSTensor {}; "
" class FoldedZContainer : public ZContainer<FGSTensor> {}; " ) ;
}
2014-11-20 14:20:09 +01:00
void template45 ( ) { // #5814
2014-09-24 13:23:44 +02:00
tok ( " namespace Constants { const int fourtytwo = 42; } "
" template <class T, int U> struct TypeMath { "
" static const int mult = sizeof(T) * U; "
" }; "
" template <class T> struct FOO { "
" enum { value = TypeMath<T, Constants::fourtytwo>::something }; "
" }; " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void template46 ( ) { // #5816
2014-09-24 13:23:44 +02:00
tok ( " template<class T, class U> struct A { static const int value = 0; }; "
" template <class T> struct B { "
" enum { value = A<typename T::type, int>::value }; "
" }; " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
tok ( " template <class T, class U> struct A {}; "
" enum { e = sizeof(A<int, int>) }; "
" template <class T, class U> struct B {}; " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
tok ( " template<class T, class U> struct A { static const int value = 0; }; "
" template<class T> struct B { typedef int type; }; "
" template <class T> struct C { "
" enum { value = A<typename B<T>::type, int>::value }; "
" }; " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void template47 ( ) { // #6023
2014-09-24 13:23:44 +02:00
tok ( " template <typename T1, typename T2 = T3<T1> > class C1 {}; "
" class C2 : public C1<C2> {}; " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void template48 ( ) { // #6134
2014-09-24 13:23:44 +02:00
tok ( " template <int> int f( { } ); "
" int foo = f<1>(0); " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void template49 ( ) { // #6237
2016-02-14 13:32:58 +01:00
const char code [ ] = " template <class T> class Fred { void f(); void g(); }; \n "
" template <class T> void Fred<T>::f() { } \n "
" template <class T> void Fred<T>::g() { } \n "
2014-11-01 22:07:24 +01:00
" template void Fred<float>::f(); \n "
" template void Fred<int>::g(); \n " ;
2018-11-07 21:25:42 +01:00
const char expected [ ] = " class Fred<float> ; "
" class Fred<int> ; "
2017-12-25 23:16:51 +01:00
" class Fred<float> { void f ( ) ; void g ( ) ; } ; "
2018-09-02 08:35:05 +02:00
" void Fred<float> :: f ( ) { } "
" void Fred<float> :: g ( ) { } "
2017-12-25 23:16:51 +01:00
" class Fred<int> { void f ( ) ; void g ( ) ; } ; "
2018-09-02 08:35:05 +02:00
" void Fred<int> :: f ( ) { } "
" void Fred<int> :: g ( ) { } " ;
2014-11-01 22:07:24 +01:00
ASSERT_EQUALS ( expected , tok ( code ) ) ;
}
2014-11-20 14:20:09 +01:00
void template50 ( ) { // #4272
2016-02-14 13:32:58 +01:00
const char code [ ] = " template <class T> class Fred { void f(); }; \n "
" template <class T> void Fred<T>::f() { } \n "
2014-11-01 22:07:24 +01:00
" template<> void Fred<float>::f() { } \n "
2019-01-05 11:14:09 +01:00
" template<> void Fred<int>::f() { } \n " ;
2014-11-01 22:07:24 +01:00
2019-01-05 11:14:09 +01:00
const char expected [ ] = " class Fred<float> ; "
" class Fred<int> ; "
" template < > void Fred<float> :: f ( ) { } "
" template < > void Fred<int> :: f ( ) { } "
" class Fred<float> { void f ( ) ; } ; "
" void Fred<float> :: f ( ) { } "
" class Fred<int> { void f ( ) ; } ; "
" void Fred<int> :: f ( ) { } " ;
2014-11-01 22:07:24 +01:00
ASSERT_EQUALS ( expected , tok ( code ) ) ;
}
2014-12-14 13:50:32 +01:00
void template51 ( ) { // #6172
tok ( " template<int N, int ... M> struct A { "
" static void foo() { "
" int i = N; "
" } "
" }; "
" void bar() { "
" A<0>::foo(); "
" } " ) ;
}
2014-11-01 22:07:24 +01:00
2015-03-14 18:46:17 +01:00
void template52 ( ) { // #6437
tok ( " template <int value> int sum() { "
" return value + sum<value/2>(); "
" } "
" template<int x, int y> int calculate_value() { "
" return sum<x - y>(); "
" } "
" int value = calculate_value<1,1>(); " ) ;
}
2015-03-15 00:28:33 +01:00
void template53 ( ) { // #4335
tok ( " template<int N> struct Factorial { "
" enum { value = N * Factorial<N - 1>::value }; "
" }; "
" template <> struct Factorial<0> { "
" enum { value = 1 }; "
" }; "
" const int x = Factorial<4>::value; " , /*simplify=*/ true , /*debugwarnings=*/ true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2015-03-21 16:30:00 +01:00
void template54 ( ) { // #6587
tok ( " template<typename _Tp> _Tp* fn(); "
" template <class T> struct A { "
" template <class U, class S = decltype(fn<T>())> "
" struct B { }; "
" }; "
" A<int> a; " ) ;
}
2015-03-22 11:20:47 +01:00
void template55 ( ) { // #6604
2015-04-13 17:02:48 +02:00
// Avoid constconstconst in macro instantiations
2015-03-22 11:20:47 +01:00
ASSERT_EQUALS (
2017-02-11 10:13:41 +01:00
" template < class T > class AtSmartPtr : public ConstCastHelper < AtSmartPtr < const T > , T > { "
2017-02-05 17:30:24 +01:00
" friend struct ConstCastHelper < AtSmartPtr < const T > , T > ; "
2017-02-11 10:13:41 +01:00
" AtSmartPtr ( const AtSmartPtr < T > & r ) ; "
" } ; " ,
2015-03-22 11:20:47 +01:00
tok ( " template<class T> class AtSmartPtr : public ConstCastHelper<AtSmartPtr<const T>, T> \n "
" { \n "
" friend struct ConstCastHelper<AtSmartPtr<const T>, T>; \n "
" AtSmartPtr(const AtSmartPtr<T>& r); \n "
" }; " ) ) ;
2015-04-13 17:02:48 +02:00
// Similar problem can also happen with ...
ASSERT_EQUALS (
2018-11-07 21:25:42 +01:00
" struct A<int> ; "
" struct A<int...> ; "
" A<int> a ( 0 ) ; "
" struct A<int> { "
2017-12-25 23:16:51 +01:00
" A<int> ( int * p ) { p ; } "
2015-04-13 17:02:48 +02:00
" } ; "
2017-12-25 23:16:51 +01:00
" struct A<int...> { "
" A<int...> ( int * p ) { "
2015-04-13 17:02:48 +02:00
" p ; "
" } } ; " ,
tok ( " template <typename... T> struct A \n "
" { \n "
" A(T* p) { \n "
" (A<T...>*)(p); \n "
" } \n "
" }; \n "
" A<int> a(0); " ) ) ;
2015-03-22 11:20:47 +01:00
}
2016-06-04 20:35:16 +02:00
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 ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2017-02-05 17:30:24 +01:00
void template57 ( ) { // #7891
const char code [ ] = " template<class T> struct Test { Test(T); }; \n "
" Test<unsigned long> test( 0 ); " ;
2018-11-07 21:25:42 +01:00
const char exp [ ] = " struct Test<unsignedlong> ; "
" Test<unsignedlong> test ( 0 ) ; "
2017-12-25 23:16:51 +01:00
" struct Test<unsignedlong> { Test<unsignedlong> ( long ) ; } ; " ;
2017-02-05 17:30:24 +01:00
ASSERT_EQUALS ( exp , tok ( code ) ) ;
}
2017-06-07 19:32:56 +02:00
void template58 ( ) { // #6021
const char code [ ] = " template <typename A> \n "
" void TestArithmetic() { \n "
" x(1 * CheckedNumeric<A>()); \n "
" } \n "
" void foo() { \n "
" TestArithmetic<int>(); \n "
" } " ;
2018-11-23 11:36:09 +01:00
const char exp [ ] = " void TestArithmetic<int> ( ) ; "
" void foo ( ) { "
2017-12-25 23:16:51 +01:00
" TestArithmetic<int> ( ) ; "
2017-06-08 00:49:46 +02:00
" } "
2017-12-25 23:16:51 +01:00
" void TestArithmetic<int> ( ) { "
2017-06-08 00:49:46 +02:00
" x ( CheckedNumeric < int > ( ) ) ; "
" } " ;
ASSERT_EQUALS ( exp , tok ( code ) ) ;
2017-06-07 19:32:56 +02:00
}
2017-06-08 19:22:01 +02:00
void template59 ( ) { // #8051
const char code [ ] = " template<int N> \n "
" struct Factorial { \n "
" enum FacHelper { value = N * Factorial<N - 1>::value }; \n "
" }; \n "
" template <> \n "
" struct Factorial<0> { \n "
" enum FacHelper { value = 1 }; \n "
" }; \n "
" template<int DiagonalDegree> \n "
" int diagonalGroupTest() { \n "
" return Factorial<DiagonalDegree>::value; \n "
" } \n "
" int main () { \n "
" return diagonalGroupTest<4>(); \n "
" } " ;
2018-11-07 21:25:42 +01:00
const char exp [ ] = " struct Factorial<4> ; "
" struct Factorial<3> ; "
" struct Factorial<2> ; "
" struct Factorial<1> ; "
" struct Factorial<0> { enum FacHelper { value = 1 } ; } ; "
2018-11-23 11:36:09 +01:00
" int diagonalGroupTest<4> ( ) ; "
2017-12-25 23:16:51 +01:00
" int main ( ) { return diagonalGroupTest<4> ( ) ; } "
" int diagonalGroupTest<4> ( ) { return Factorial<4> :: value ; } "
" struct Factorial<4> { enum FacHelper { value = 4 * Factorial<3> :: value } ; } ; "
" struct Factorial<3> { enum FacHelper { value = 3 * Factorial<2> :: value } ; } ; "
" struct Factorial<2> { enum FacHelper { value = 2 * Factorial<1> :: value } ; } ; "
2018-10-14 16:57:07 +02:00
" struct Factorial<1> { enum FacHelper { value = Factorial<0> :: value } ; } ; " ;
2017-06-08 19:22:01 +02:00
ASSERT_EQUALS ( exp , tok ( code ) ) ;
}
2017-12-25 08:19:46 +01:00
void template60 ( ) { // Extracted from Clang testfile
const char code [ ] = " template <typename T> struct S { typedef int type; }; \n "
" template <typename T> void f() {} \n "
" template <typename T> void h() { f<typename S<T>::type(0)>(); } \n "
" \n "
" void j() { h<int>(); } " ;
2018-11-07 21:25:42 +01:00
const char exp [ ] = " struct S<int> ; "
" template < typename T > void f ( ) { } " // <- TODO: This template is not expanded
2018-11-23 11:36:09 +01:00
" void h<int> ( ) ; "
2017-12-25 23:16:51 +01:00
" void j ( ) { h<int> ( ) ; } "
" void h<int> ( ) { f < S<int> :: type ( 0 ) > ( ) ; } "
" struct S<int> { } ; " ;
2017-12-25 08:19:46 +01:00
ASSERT_EQUALS ( exp , tok ( code ) ) ;
}
2018-01-03 23:05:57 +01:00
void template61 ( ) { // hang in daca, code extracted from kodi
const char code [ ] = " template <typename T> struct Foo {}; \n "
" template <typename T> struct Bar { \n "
" void f1(Bar<T> x) {} \n "
" Foo<Bar<T>> f2() { } \n "
" }; \n "
" Bar<int> c; " ;
2018-11-07 21:25:42 +01:00
const char exp [ ] = " struct Foo<Bar<int>> ; "
" struct Bar<int> ; "
2018-10-26 14:20:13 +02:00
" Bar<int> c ; "
2018-01-03 23:05:57 +01:00
" struct Bar<int> { "
" void f1 ( Bar<int> x ) { } "
" Foo<Bar<int>> f2 ( ) { } "
" } ; "
" struct Foo<Bar<int>> { } ; " ;
ASSERT_EQUALS ( exp , tok ( code ) ) ;
}
2018-01-06 15:16:03 +01:00
void template62 ( ) { // #8314
const char code [ ] = " template <class T> struct C1 {}; \n "
" template <class T> void f() { x = y ? C1<int>::allocate(1) : 0; } \n "
" template <class T, unsigned S> class C3 {}; \n "
" template <class T, unsigned S> C3<T, S>::C3(const C3<T, S> &v) { C1<T *> c1; } \n "
" C3<int,6> c3; " ;
2018-11-07 21:25:42 +01:00
const char exp [ ] = " struct C1<int*> ; "
" template < class T > void f ( ) { x = y ? ( C1 < int > :: allocate ( 1 ) ) : 0 ; } "
2018-10-26 14:20:13 +02:00
" class C3<int,6> ; "
2018-01-06 15:16:03 +01:00
" C3<int,6> c3 ; "
" class C3<int,6> { } ; "
" C3<int,6> :: C3<int,6> ( const C3<int,6> & v ) { C1<int*> c1 ; } "
" struct C1<int*> { } ; " ;
ASSERT_EQUALS ( exp , tok ( code ) ) ;
}
2018-05-16 15:24:23 +02:00
void template63 ( ) { // #8576
2018-11-07 21:25:42 +01:00
const char code [ ] = " template<class T> struct TestClass { T m_hi; }; "
" TestClass<std::auto_ptr<v>> objTest3; " ;
const char exp [ ] = " struct TestClass<std::auto_ptr<v>> ; "
" TestClass<std::auto_ptr<v>> objTest3 ; "
" struct TestClass<std::auto_ptr<v>> { std :: auto_ptr < v > m_hi ; } ; " ;
2018-05-16 15:24:23 +02:00
ASSERT_EQUALS ( exp , tok ( code ) ) ;
}
2018-09-01 11:26:10 +02:00
void template64 ( ) { // #8683
const char code [ ] = " template <typename T> \n "
" bool foo(){return true;} \n "
" struct A { \n "
" template<int n> \n "
" void t_func() \n "
" { \n "
" if( n != 0 || foo<int>()); \n "
" } \n "
" void t_caller() \n "
" { \n "
" t_func<0>(); \n "
" t_func<1>(); \n "
" } \n "
" }; " ;
tok ( code ) ; // don't crash
}
void template65 ( ) { // #8321
const char code [ ] = " namespace bpp \n "
" { \n "
" template<class N, class E, class DAGraphImpl> \n "
" class AssociationDAGraphImplObserver : \n "
" public AssociationGraphImplObserver<N, E, DAGraphImpl> \n "
" {}; \n "
" template<class N, class E> \n "
" using AssociationDAGlobalGraphObserver = AssociationDAGraphImplObserver<N, E, DAGlobalGraph>; \n "
" } \n "
" using namespace bpp; \n "
" using namespace std; \n "
" int main() { \n "
" AssociationDAGlobalGraphObserver<string,unsigned int> grObs; \n "
" return 1; \n "
" } " ;
tok ( code ) ; // don't crash
}
2018-09-02 08:35:05 +02:00
void template66 ( ) { // #8725
const char code [ ] = " template <class T> struct Fred { \n "
" const int ** foo(); \n "
" }; \n "
" template <class T> const int ** Fred<T>::foo() { return nullptr; } \n "
" Fred<int> fred; " ;
2018-11-07 21:25:42 +01:00
const char exp [ ] = " struct Fred<int> ; "
" Fred<int> fred ; "
" struct Fred<int> { "
2018-09-02 08:35:05 +02:00
" const int * * foo ( ) ; "
" } ; "
" const int * * Fred<int> :: foo ( ) { return nullptr ; } " ;
2018-09-14 14:16:34 +02:00
ASSERT_EQUALS ( exp , tok ( code ) ) ;
2018-09-02 08:35:05 +02:00
}
2018-09-02 17:49:13 +02:00
void template67 ( ) { // ticket #8122
2019-01-06 17:15:57 +01:00
const char code [ ] = " template <class T> struct Container { \n "
" Container(); \n "
" Container(const Container &); \n "
" Container & operator = (const Container &); \n "
" ~Container(); \n "
2018-09-02 17:49:13 +02:00
" T* mElements; \n "
2019-01-06 17:15:57 +01:00
" const Container * c; \n "
2018-09-02 17:49:13 +02:00
" }; \n "
2019-01-06 17:15:57 +01:00
" template <class T> Container<T>::Container() : mElements(nullptr), c(nullptr) {} \n "
" template <class T> Container<T>::Container(const Container & x) { nElements = x.nElements; c = x.c; } \n "
" template <class T> Container<T> & Container<T>::operator = (const Container & x) { mElements = x.mElements; c = x.c; return *this; } \n "
" template <class T> Container<T>::~Container() {} \n "
" Container<int> intContainer; " ;
const char expected [ ] = " struct Container<int> ; "
" Container<int> intContainer ; "
" struct Container<int> { "
" Container<int> ( ) ; "
" Container<int> ( const Container<int> & ) ; "
" Container<int> & operator= ( const Container<int> & ) ; "
" ~ Container<int> ( ) ; "
2018-09-02 17:49:13 +02:00
" int * mElements ; "
2019-01-06 17:15:57 +01:00
" const Container<int> * c ; "
2018-09-02 17:49:13 +02:00
" } ; "
2019-01-06 17:15:57 +01:00
" Container<int> :: Container<int> ( ) : mElements ( nullptr ) , c ( nullptr ) { } "
" Container<int> :: Container<int> ( const Container<int> & x ) { nElements = x . nElements ; c = x . c ; } "
" Container<int> & Container<int> :: operator= ( const Container<int> & x ) { mElements = x . mElements ; c = x . c ; return * this ; } "
" Container<int> :: ~ Container<int> ( ) { } " ;
2018-09-02 17:49:13 +02:00
2018-09-14 14:16:34 +02:00
ASSERT_EQUALS ( expected , tok ( code ) ) ;
2018-09-02 17:49:13 +02:00
}
2018-09-26 06:23:12 +02:00
void template68 ( ) {
const char code [ ] = " template <class T> union Fred { \n "
" char dummy[sizeof(T)]; \n "
" T value; \n "
" }; \n "
" Fred<int> fred; " ;
2018-11-07 21:25:42 +01:00
const char exp [ ] = " union Fred<int> ; "
" Fred<int> fred ; "
" union Fred<int> { "
2018-09-26 06:23:12 +02:00
" char dummy [ 4 ] ; "
" int value ; "
" } ; " ;
ASSERT_EQUALS ( exp , tok ( code ) ) ;
}
2018-10-26 14:20:13 +02:00
void template69 ( ) { // #8791
const char code [ ] = " class Test { \n "
" int test; \n "
" template <class T> T lookup() { return test; } \n "
" int Fun() { return lookup<int>(); } \n "
" }; " ;
const char exp [ ] = " class Test { "
" int test ; "
2018-11-23 11:36:09 +01:00
" int lookup<int> ( ) ; "
2018-10-26 14:20:13 +02:00
" int Fun ( ) { return lookup<int> ( ) ; } "
" } ; "
" int Test :: lookup<int> ( ) { return test ; } " ;
ASSERT_EQUALS ( exp , tok ( code ) ) ;
}
void template70 ( ) { // #5289
const char code [ ] = " template<typename T, typename V, int KeySize = 0> class Bar; \n "
" template<> \n "
" class Bar<void, void> { \n "
" }; \n "
" template<typename K, typename V, int KeySize> \n "
" class Bar : private Bar<void, void> { \n "
" void foo() { } \n "
" }; " ;
const char exp [ ] = " template < typename T , typename V , int KeySize = 0 > class Bar ; "
" class Bar<void,void> { "
" } ; "
" template < typename K , typename V , int KeySize = 0 > "
" class Bar : private Bar<void,void> { "
" void foo ( ) { } "
" } ; " ;
ASSERT_EQUALS ( exp , tok ( code ) ) ;
}
2018-11-02 14:49:40 +01:00
void template71 ( ) { // #8821
const char code [ ] = " int f1(int * pInterface, int x) { return 0; } \n "
" \n "
" template< class interface_type > class Reference { \n "
" template< class interface_type > int i(); \n "
" int *pInterface; \n "
" }; \n "
" \n "
" template< class interface_type > int Reference< interface_type >::i() { \n "
" return f1(pInterface, interface_type::static_type()); \n "
" } \n "
" \n "
" Reference< class XPropertyList > dostuff(); " ;
const char exp [ ] = " int f1 ( int * pInterface , int x ) { return 0 ; } "
" class Reference<XPropertyList> ; "
" Reference<XPropertyList> dostuff ( ) ; "
" class Reference<XPropertyList> { template < class XPropertyList > int i ( ) ; int * pInterface ; } ; "
" int Reference<XPropertyList> :: i ( ) { return f1 ( pInterface , XPropertyList :: static_type ( ) ) ; } " ;
ASSERT_EQUALS ( exp , tok ( code ) ) ;
}
2018-11-23 11:36:09 +01:00
void template72 ( ) {
const char code [ ] = " template <typename N, typename P> class Tokenizer; \n "
" const Tokenizer<Node, Path> *tokenizer() const; \n "
" template <typename N, typename P> \n "
" Tokenizer<N, P>::Tokenizer() { } " ;
const char exp [ ] = " template < typename N , typename P > class Tokenizer ; "
" const Tokenizer < Node , Path > * tokenizer ( ) const ; "
" template < typename N , typename P > "
" Tokenizer < N , P > :: Tokenizer ( ) { } " ;
ASSERT_EQUALS ( exp , tok ( code ) ) ;
}
void template73 ( ) {
const char code [ ] = " template<typename T> \n "
" void keep_range(T& value, const T mini, const T maxi){} \n "
" template void keep_range<float>(float& v, const float l, const float u); \n "
" template void keep_range<int>(int& v, const int l, const int u); " ;
2018-12-17 05:58:48 +01:00
const char exp [ ] = " void keep_range<float> ( float & value , const float mini , const float maxi ) ; "
" void keep_range<int> ( int & value , const int mini , const int maxi ) ; "
2018-11-23 11:36:09 +01:00
" void keep_range<float> ( float & value , const float mini , const float maxi ) { } "
" void keep_range<int> ( int & value , const int mini , const int maxi ) { } " ;
ASSERT_EQUALS ( exp , tok ( code ) ) ;
}
void template74 ( ) {
const char code [ ] = " template <class T> class BTlist { }; \n "
" class PushBackStreamBuf { \n "
" public: \n "
" void pushBack(const BTlist<int> &vec); \n "
" }; " ;
const char exp [ ] = " class BTlist<int> ; "
" class PushBackStreamBuf { "
" public: "
" void pushBack ( const BTlist<int> & vec ) ; "
" } ; "
" class BTlist<int> { } ; " ;
ASSERT_EQUALS ( exp , tok ( code ) ) ;
}
void template75 ( ) {
const char code [ ] = " template<typename T> \n "
" T foo(T& value){ return value; } \n "
" template std::vector<std::vector<int>> foo<std::vector<std::vector<int>>>(std::vector<std::vector<int>>& v); " ;
2018-12-17 05:58:48 +01:00
const char exp [ ] = " std :: vector < std :: vector < int > > foo<std::vector<std::vector<int>>> ( std :: vector < std :: vector < int > > & value ) ; "
2018-11-23 11:36:09 +01:00
" std :: vector < std :: vector < int > > foo<std::vector<std::vector<int>>> ( std :: vector < std :: vector < int > > & value ) { return value ; } " ;
ASSERT_EQUALS ( exp , tok ( code ) ) ;
}
void template76 ( ) {
const char code [ ] = " namespace NS { \n "
" template<typename T> T foo(T& value) { return value; } \n "
" template std::vector<std::vector<int>> foo<std::vector<std::vector<int>>>(std::vector<std::vector<int>>& v); \n "
" } \n "
" std::vector<std::vector<int>> v; \n "
" v = foo<std::vector<std::vector<int>>>(v); \n " ;
const char exp [ ] = " namespace NS { "
2018-12-17 05:58:48 +01:00
" std :: vector < std :: vector < int > > foo<std::vector<std::vector<int>>> ( std :: vector < std :: vector < int > > & value ) ; "
2018-11-23 11:36:09 +01:00
" } "
" std :: vector < std :: vector < int > > v ; "
" v = foo<std::vector<std::vector<int>>> ( v ) ; "
" std :: vector < std :: vector < int > > NS :: foo<std::vector<std::vector<int>>> ( std :: vector < std :: vector < int > > & value ) { return value ; } " ;
ASSERT_EQUALS ( exp , tok ( code ) ) ;
}
void template77 ( ) {
const char code [ ] = " template<typename T> \n "
" struct is_void : std::false_type { }; \n "
" template<> \n "
" struct is_void<void> : std::true_type { }; \n "
" int main() { \n "
" std::cout << is_void<char>::value << std::endl; \n "
" std::cout << is_void<void>::value << std::endl; \n "
" } " ;
const char exp [ ] = " struct is_void<char> ; "
" struct is_void<void> : std :: true_type { } ; "
" int main ( ) { "
" std :: cout << is_void<char> :: value << std :: endl ; "
" std :: cout << is_void<void> :: value << std :: endl ; "
" } "
" struct is_void<char> : std :: false_type { } ; " ;
ASSERT_EQUALS ( exp , tok ( code ) ) ;
}
void template78 ( ) {
const char code [ ] = " template <typename> \n "
" struct Base { }; \n "
" struct S : Base <void>::Type { }; " ;
const char exp [ ] = " struct Base<void> ; "
" struct S : Base<void> :: Type { } ; "
" struct Base<void> { } ; " ;
ASSERT_EQUALS ( exp , tok ( code ) ) ;
}
void template79 ( ) { // #5133
const char code [ ] = " class Foo { \n "
" public: \n "
" template<typename T> void foo() { bar<T>(); } \n "
" private: \n "
" template<typename T> void bar() { bazz(); } \n "
" void bazz() { } \n "
" }; \n "
" void some_func() { \n "
" Foo x; \n "
" x.foo<int>(); \n "
" } " ;
const char exp [ ] = " class Foo { "
" public: "
" void foo<int> ( ) ; "
" private: "
" void bar<int> ( ) ; "
" void bazz ( ) { } "
" } ; "
" void some_func ( ) { "
" Foo x ; "
" x . foo<int> ( ) ; "
" } "
" void Foo :: foo<int> ( ) { bar<int> ( ) ; } "
" void Foo :: bar<int> ( ) { bazz ( ) ; } " ;
ASSERT_EQUALS ( exp , tok ( code ) ) ;
}
2018-11-26 06:23:12 +01:00
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 ) ) ;
}
2018-11-27 06:17:04 +01:00
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 ; "
2019-01-23 08:53:01 +01:00
" swizzle :: swizzle<1> ( tt2 ) ; "
2018-11-27 06:17:04 +01:00
" tvec3<f16> tt3 ; "
2019-01-23 08:53:01 +01:00
" swizzle :: swizzle<2,3> ( tt3 ) ; "
2018-11-27 06:17:04 +01:00
" } "
" 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 ) ) ;
}
2018-11-29 06:24:28 +01:00
void template83 ( ) {
const char code [ ] = " template<typename Task> \n "
" MultiConsumer<Task>::MultiConsumer() : sizeBuffer(0) {} \n "
" MultiReads::MultiReads() { \n "
" mc = new MultiConsumer<reads_packet>(); \n "
" } " ;
const char exp [ ] = " MultiConsumer<reads_packet> :: MultiConsumer<reads_packet> ( ) ; "
" MultiReads :: MultiReads ( ) { "
" mc = new MultiConsumer<reads_packet> ( ) ; "
" } "
" MultiConsumer<reads_packet> :: MultiConsumer<reads_packet> ( ) : sizeBuffer ( 0 ) { } " ;
ASSERT_EQUALS ( exp , tok ( code ) ) ;
}
2018-12-06 21:47:48 +01:00
void template84 ( ) { // #8880
const char code [ ] = " template <class b, int c, class> \n "
" auto d() -> typename a<decltype(b{})>::e { \n "
" d<int, c, int>(); \n "
" } " ;
const char exp [ ] = " auto d<int,c,int> ( ) . a < decltype ( int { } ) > :: e ; "
" auto d<int,c,int> ( ) . a < decltype ( int { } ) > :: e { "
" d<int,c,int> ( ) ; "
" } " ;
ASSERT_EQUALS ( exp , tok ( code ) ) ;
}
2018-12-15 07:52:47 +01:00
void template85 ( ) { // #8902 - crash
const char code [ ] = " template<typename T> \n "
" struct C \n "
" { \n "
" template<typename U, typename std::enable_if<(!std::is_fundamental<U>::value)>::type* = nullptr> \n "
" void foo(); \n "
" }; \n "
" extern template void C<int>::foo<int, nullptr>(); \n "
" template<typename T> \n "
" template<typename U, typename std::enable_if<(!std::is_fundamental<U>::value)>::type> \n "
" void C<T>::foo() {} " ;
// @todo the output is very wrong but we are only worried about the crash for now
tok ( code ) ;
}
2018-12-17 05:58:48 +01:00
void template86 ( ) { // crash
const char code [ ] = " struct S { \n "
" S(); \n "
" }; \n "
" template <typename T> \n "
" struct U { \n "
" static S<T> u; \n "
" }; \n "
" template <typename T> \n "
" S<T> U<T>::u; \n "
" template S<int> U<int>::u; \n "
" S<int> &i = U<int>::u; " ;
tok ( code ) ;
}
2018-12-19 21:59:59 +01:00
void template87 ( ) {
const char code [ ] = " template<typename T> \n "
" T f1(T t) { return t; } \n "
" template const char * f1<const char *>(); \n "
" template const char & f1<const char &>(); " ;
const char exp [ ] = " const char * f1<constchar*> ( const char * t ) ; "
" const char & f1<constchar&> ( const char & t ) ; "
" const char * f1<constchar*> ( const char * t ) { return t ; } "
" const char & f1<constchar&> ( const char & t ) { return t ; } " ;
ASSERT_EQUALS ( exp , tok ( code ) ) ;
}
2018-12-29 11:19:53 +01:00
void template88 ( ) { // #6183.cpp
const char code [ ] = " class CTest { \n "
" public: \n "
" template <typename T> \n "
" static void Greeting(T val) { \n "
" std::cout << val << std::endl; \n "
" } \n "
" private: \n "
" static void SayHello() { \n "
" std::cout << \" Hello World! \" << std::endl; \n "
" } \n "
" }; \n "
" template<> \n "
" void CTest::Greeting(bool) { \n "
" CTest::SayHello(); \n "
" } \n "
" int main() { \n "
" CTest::Greeting<bool>(true); \n "
" return 0; \n "
" } " ;
const char exp [ ] = " class CTest { "
" public: "
" static void Greeting<bool> ( bool ) ; "
" template < typename T > "
" static void Greeting ( T val ) { "
" std :: cout << val << std :: endl ; "
" } "
" private: "
" static void SayHello ( ) { "
" std :: cout << \" Hello World! \" << std :: endl ; "
" } "
" } ; "
" void CTest :: Greeting<bool> ( bool ) { "
" CTest :: SayHello ( ) ; "
" } "
" int main ( ) { "
" CTest :: Greeting<bool> ( true ) ; "
" return 0 ; "
" } " ;
ASSERT_EQUALS ( exp , tok ( code ) ) ;
}
void template89 ( ) { // #8917
const char code [ ] = " struct Fred { \n "
" template <typename T> static void foo() { } \n "
" }; \n "
" template void Fred::foo<char>(); \n "
" template void Fred::foo<float>(); \n "
" template <> void Fred::foo<bool>() { } \n "
" template <> void Fred::foo<int>() { } " ;
const char exp [ ] = " struct Fred { "
" static void foo<int> ( ) ; "
2018-12-31 17:19:34 +01:00
" static void foo<bool> ( ) ; "
2018-12-29 11:19:53 +01:00
" static void foo<char> ( ) ; "
" static void foo<float> ( ) ; "
" } ; "
" void Fred :: foo<bool> ( ) { } "
" void Fred :: foo<int> ( ) { } "
" void Fred :: foo<char> ( ) { } "
" void Fred :: foo<float> ( ) { } " ;
2018-12-31 17:19:34 +01:00
ASSERT_EQUALS ( exp , tok ( code ) ) ;
2018-12-29 11:19:53 +01:00
}
void template90 ( ) { // crash
const char code [ ] = " template <typename T> struct S1 {}; \n "
" void f(S1<double>) {} \n "
" template <typename T> \n "
" decltype(S1<T>().~S1<T>()) fun1() {}; " ;
const char exp [ ] = " struct S1<double> ; "
" void f ( S1<double> ) { } "
" template < typename T > "
" decltype ( S1 < T > ( ) . ~ S1 < T > ( ) ) fun1 ( ) { } ; "
" struct S1<double> { } ; " ;
ASSERT_EQUALS ( exp , tok ( code ) ) ;
}
void template91 ( ) {
{
const char code [ ] = " template<typename T> T foo(T t) { return t; } \n "
" template<> char foo<char>(char a) { return a; } \n "
" template<> int foo<int>(int a) { return a; } \n "
" template float foo<float>(float); \n "
" template double foo<double>(double); " ;
2018-12-31 17:19:34 +01:00
const char exp [ ] = " int foo<int> ( int a ) ; "
2018-12-29 11:19:53 +01:00
" char foo<char> ( char a ) ; "
2018-12-31 17:19:34 +01:00
" float foo<float> ( float t ) ; "
" double foo<double> ( double t ) ; "
2018-12-29 11:19:53 +01:00
" char foo<char> ( char a ) { return a ; } "
" int foo<int> ( int a ) { return a ; } "
" float foo<float> ( float t ) { return t ; } "
" double foo<double> ( double t ) { return t ; } " ;
ASSERT_EQUALS ( exp , tok ( code ) ) ;
}
{
const char code [ ] = " struct Fred { \n "
" template<typename T> T foo(T t) { return t; } \n "
" template<> char foo<char>(char a) { return a; } \n "
" template<> int foo<int>(int a) { return a; } \n "
" }; \n "
" template float Fred::foo<float>(float); \n "
" template double Fred::foo<double>(double); " ;
const char exp [ ] = " struct Fred { "
2018-12-31 17:19:34 +01:00
" int foo<int> ( int a ) ; "
" char foo<char> ( char a ) ; "
2018-12-29 11:19:53 +01:00
" float foo<float> ( float t ) ; "
" double foo<double> ( double t ) ; "
" char foo<char> ( char a ) { return a ; } "
" int foo<int> ( int a ) { return a ; } "
" } ; "
" float Fred :: foo<float> ( float t ) { return t ; } "
" double Fred :: foo<double> ( double t ) { return t ; } " ;
ASSERT_EQUALS ( exp , tok ( code ) ) ;
}
{
const char code [ ] = " namespace NS1 { \n "
" namespace NS2 { \n "
" template<typename T> T foo(T t) { return t; } \n "
" template<> char foo<char>(char a) { return a; } \n "
" template<> int foo<int>(int a) { return a; } \n "
" } \n "
" template float NS2::foo<float>(float); \n "
" } \n "
" template double NS1::NS2::foo<double>(double); " ;
const char exp [ ] = " namespace NS1 { "
" namespace NS2 { "
2018-12-31 17:19:34 +01:00
" int foo<int> ( int a ) ; "
" char foo<char> ( char a ) ; "
2018-12-29 11:19:53 +01:00
" float foo<float> ( float t ) ; "
" double foo<double> ( double t ) ; "
" char foo<char> ( char a ) { return a ; } "
" int foo<int> ( int a ) { return a ; } "
" } "
" } "
" float NS1 :: NS2 :: foo<float> ( float t ) { return t ; } "
" double NS1 :: NS2 :: foo<double> ( double t ) { return t ; } " ;
ASSERT_EQUALS ( exp , tok ( code ) ) ;
}
}
2018-12-31 21:29:53 +01:00
void template92 ( ) {
const char code [ ] = " template<class T> void foo(T const& t) { } \n "
" template<> void foo<double>(double const& d) { } \n "
" template void foo<float>(float const& f); \n "
" int main() { \n "
" foo<int>(2); \n "
" foo<double>(3.14); \n "
" foo<float>(3.14f); \n "
" } " ;
const char exp [ ] = " void foo<double> ( const double & d ) ; "
" void foo<float> ( const float & t ) ; "
" void foo<int> ( const int & t ) ; "
" void foo<double> ( const double & d ) { } "
" int main ( ) { "
" foo<int> ( 2 ) ; "
" foo<double> ( 3.14 ) ; "
" foo<float> ( 3.14f ) ; "
" } "
" void foo<float> ( const float & t ) { } "
" void foo<int> ( const int & t ) { } " ;
ASSERT_EQUALS ( exp , tok ( code ) ) ;
}
2019-01-02 07:15:45 +01:00
void template93 ( ) { // crash
const char code [ ] = " template <typename Iterator> \n "
" void ForEach() { } \n "
" template <typename Type> \n "
" class Vector2 : public Vector { \n "
" template <typename Iterator> \n "
" void ForEach(); \n "
" public: \n "
" void process(); \n "
" }; \n "
" template <typename Type> \n "
" void Vector2<Type>::process() { \n "
" ForEach<iterator>(); \n "
" } \n "
" Vector2<string> c; " ;
const char exp [ ] = " void ForEach<iterator> ( ) ; "
" class Vector2<string> ; "
" Vector2<string> c ; "
" class Vector2<string> : public Vector { "
" template < typename Iterator > "
" void ForEach ( ) ; "
" public: "
" void process ( ) ; "
" } ; "
" void Vector2<string> :: process ( ) { "
" ForEach<iterator> ( ) ; "
" } "
" void ForEach<iterator> ( ) { "
" } " ;
ASSERT_EQUALS ( exp , tok ( code ) ) ;
}
2019-01-05 11:14:09 +01:00
void template94 ( ) { // #8927 crash
const char code [ ] = " template <typename T> \n "
" class Array { }; \n "
" template<typename T> \n "
" Array<T> foo() {}; \n "
" template <> Array<double> foo<double>() { } \n "
" template <> Array<std::complex<float>> foo<std::complex<float>>() { } \n "
" template <> Array<float> foo<float>() { } \n "
" template < typename T > \n "
" Array<T> matmul() { \n "
" return foo<T>( ); \n "
" } \n "
" template Array<std::complex<float>> matmul<std::complex<float>>(); " ;
const char exp [ ] = " class Array<double> ; "
" class Array<std::complex<float>> ; "
" class Array<float> ; "
" Array<float> foo<float> ( ) ; "
" Array<std::complex<float>> foo<std::complex<float>> ( ) ; "
" Array<double> foo<double> ( ) ; "
" template < typename T > "
" Array < T > foo ( ) { } ; "
" Array<double> foo<double> ( ) { } "
" Array<std::complex<float>> foo<std::complex<float>> ( ) { } "
" Array<float> foo<float> ( ) { } "
" Array<std::complex<float>> matmul<std::complex<float>> ( ) ; "
" Array<std::complex<float>> matmul<std::complex<float>> ( ) { "
" return foo<std::complex<float>> ( ) ; "
" } "
" class Array<double> { } ; "
" class Array<std::complex<float>> { } ; "
" class Array<float> { } ; " ;
ASSERT_EQUALS ( exp , tok ( code ) ) ;
}
2019-01-18 21:12:39 +01:00
void template95 ( ) { // #7417
const char code [ ] = " template <typename T> \n "
" T Value = 123; \n "
" template<> \n "
" int Value<int> = 456; \n "
" float f = Value<float>; \n "
" int i = Value<int>; " ;
const char exp [ ] = " float Value<float> ; Value<float> = 123 ; "
" int Value<int> ; Value<int> = 456 ; "
" float f ; f = Value<float> ; "
" int i ; i = Value<int> ; " ;
ASSERT_EQUALS ( exp , tok ( code ) ) ;
}
void template96 ( ) { // #7854
const char code [ ] = " template<unsigned int n> \n "
" constexpr long fib = fib<n-1> + fib<n-2>; \n "
" template<> \n "
" constexpr long fib<0> = 0; \n "
" template<> \n "
" constexpr long fib<1> = 1; \n "
" long f0 = fib<0>; \n "
" long f1 = fib<1>; \n "
" long f2 = fib<2>; \n "
" long f3 = fib<3>; " ;
const char act [ ] = " const long fib<2> = fib < 1 > + fib < 0 > ; "
" const long fib<0> = 0 ; "
" const long fib<1> = 1 ; "
" long f0 ; f0 = fib<0> ; "
" long f1 ; f1 = fib<1> ; "
" long f2 ; f2 = fib<2> ; "
" long f3 ; f3 = fib < 3 > ; " ;
const char exp [ ] = " const long fib<3> = fib<2> + fib<1> ; "
" const long fib<2> = fib<1> + fib<0> ; "
" const long fib<0> = 0 ; "
" const long fib<1> = 1 ; "
" long f0 ; f0 = fib<0> ; "
" long f1 ; f1 = fib<1> ; "
" long f2 ; f2 = fib<2> ; "
" long f3 ; f3 = fib<3> ; " ;
TODO_ASSERT_EQUALS ( exp , act , tok ( code , false ) ) ;
}
2019-01-23 08:53:01 +01:00
void template97 ( ) {
const char code [ ] = " namespace NS1 { \n "
" namespace NS2 { \n "
" namespace NS3 { \n "
" namespace NS4 { \n "
" template<class T> \n "
" class Fred { \n "
" T * t; \n "
" public: \n "
" Fred<T>() : t(nullptr) {} \n "
" }; \n "
" } \n "
" using namespace NS4; \n "
" Fred<bool> fred_bool; \n "
" NS4::Fred<char> fred_char; \n "
" } \n "
" using namespace NS3; \n "
" NS4::Fred<short> fred_short; \n "
" using namespace NS3::NS4; \n "
" Fred<int> fred_int; \n "
" NS3::NS4::Fred<long> fred_long; \n "
" NS2::NS3::NS4::Fred<float> fred_float; \n "
" NS1::NS2::NS3::NS4::Fred<double> fred_double; \n "
" } \n "
" using namespace NS2; \n "
" NS3::NS4::Fred<float> fred_float1; \n "
" NS2::NS3::NS4::Fred<double> fred_double1; \n "
" } \n "
" using namespace NS1::NS2::NS3::NS4; \n "
" Fred<bool> fred_bool1; \n "
" NS1::NS2::NS3::NS4::Fred<int> fred_int1; " ;
const char exp [ ] = " namespace NS1 { "
" namespace NS2 { "
" namespace NS3 { "
" namespace NS4 { "
" class Fred<bool> ; "
" class Fred<char> ; "
" class Fred<short> ; "
" class Fred<int> ; "
" class Fred<long> ; "
" class Fred<float> ; "
" class Fred<double> ; "
" } "
" using namespace NS4 ; "
" NS4 :: Fred<bool> fred_bool ; "
" NS4 :: Fred<char> fred_char ; "
" } "
" using namespace NS3 ; "
" NS3 :: NS4 :: Fred<short> fred_short ; "
" using namespace NS3 :: NS4 ; "
" NS3 :: NS4 :: Fred<int> fred_int ; "
" NS3 :: NS4 :: Fred<long> fred_long ; "
" NS2 :: NS3 :: NS4 :: Fred<float> fred_float ; "
" NS1 :: NS2 :: NS3 :: NS4 :: Fred<double> fred_double ; "
" } "
" using namespace NS2 ; "
" NS2 :: NS3 :: NS4 :: Fred<float> fred_float1 ; "
" NS2 :: NS3 :: NS4 :: Fred<double> fred_double1 ; "
" } "
" using namespace NS1 :: NS2 :: NS3 :: NS4 ; "
" NS1 :: NS2 :: NS3 :: NS4 :: Fred<bool> fred_bool1 ; "
" NS1 :: NS2 :: NS3 :: NS4 :: Fred<int> fred_int1 ; "
" class NS1 :: NS2 :: NS3 :: NS4 :: Fred<bool> { "
" bool * t ; "
" public: "
" Fred<bool> ( ) : t ( nullptr ) { } "
" } ; "
" class NS1 :: NS2 :: NS3 :: NS4 :: Fred<char> { "
" char * t ; "
" public: "
" Fred<char> ( ) : t ( nullptr ) { } "
" } ; "
" class NS1 :: NS2 :: NS3 :: NS4 :: Fred<short> { "
" short * t ; "
" public: "
" Fred<short> ( ) : t ( nullptr ) { } "
" } ; "
" class NS1 :: NS2 :: NS3 :: NS4 :: Fred<int> { "
" int * t ; "
" public: "
" Fred<int> ( ) : t ( nullptr ) { } "
" } ; "
" class NS1 :: NS2 :: NS3 :: NS4 :: Fred<long> { "
" long * t ; "
" public: "
" Fred<long> ( ) : t ( nullptr ) { } "
" } ; "
" class NS1 :: NS2 :: NS3 :: NS4 :: Fred<float> { "
" float * t ; "
" public: "
" Fred<float> ( ) : t ( nullptr ) { } "
" } ; "
" class NS1 :: NS2 :: NS3 :: NS4 :: Fred<double> { "
" double * t ; "
" public: "
" Fred<double> ( ) : t ( nullptr ) { } "
" } ; " ;
ASSERT_EQUALS ( exp , tok ( code ) ) ;
}
2017-12-30 22:14:48 +01:00
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 "
" template <typename T> struct S<C<T>> {b}; \n "
" S<int> s; " ;
2018-10-26 14:20:13 +02:00
const char exp [ ] = " template < typename T > struct C { } ; struct S<int> ; template < typename T > struct S < C < T > > { b } ; S<int> s ; struct S<int> { a } ; " ;
2017-12-30 22:14:48 +01:00
ASSERT_EQUALS ( exp , tok ( code ) ) ;
}
void template_specialization_2 ( ) { // #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 "
" template <typename T> struct S<C<T>> {b}; \n "
" S<C<int>> s; " ;
2018-10-26 14:20:13 +02:00
const char exp [ ] = " template < typename T > struct C { } ; template < typename T > struct S { a } ; struct S<C<int>> ; S<C<int>> s ; struct S<C<int>> { b } ; " ;
2017-12-30 22:14:48 +01:00
ASSERT_EQUALS ( exp , tok ( code ) ) ;
}
2015-08-14 18:27:03 +02:00
void template_enum ( ) {
const char code1 [ ] = " template <class T> \n "
" struct Unconst { \n "
" typedef T type; \n "
" }; \n "
" template <class T> \n "
" struct Unconst<const T> { \n "
" typedef T type; \n "
" }; \n "
" template <class T> \n "
" struct Unconst<const T&> { \n "
" typedef T& type; \n "
" }; \n "
" template <class T> \n "
" struct Unconst<T* const> { \n "
" typedef T* type; \n "
" }; \n "
" template <class T1, class T2> \n "
" struct type_equal { \n "
" enum { value = 0 }; \n "
" }; \n "
" template <class T> \n "
" struct type_equal<T, T> { \n "
" enum { value = 1 }; \n "
" }; \n "
" template<class T> \n "
" struct template_is_const \n "
" { \n "
" enum {value = !type_equal<T, typename Unconst<T>::type>::value }; \n "
" }; " ;
2017-02-05 17:30:24 +01:00
const char exp1 [ ] = " template < class T > struct Unconst { } ; "
2017-02-11 10:13:41 +01:00
" template < class T > struct Unconst < const T > { } ; "
" template < class T > struct Unconst < const T & > { } ; "
" template < class T > struct Unconst < T * const > { } ; "
" template < class T1 , class T2 > struct type_equal { enum Anonymous0 { value = 0 } ; } ; "
2017-02-05 17:30:24 +01:00
" template < class T > struct type_equal < T , T > { enum Anonymous1 { value = 1 } ; } ; "
2017-02-11 10:13:41 +01:00
" template < class T > struct template_is_const { enum Anonymous2 { value = ! type_equal < T , Unconst < T > :: type > :: value } ; } ; " ;
2017-02-05 17:30:24 +01:00
ASSERT_EQUALS ( exp1 , tok ( code1 ) ) ;
2015-08-14 18:27:03 +02:00
}
2014-11-20 14:20:09 +01:00
void template_default_parameter ( ) {
2014-09-24 13:23:44 +02:00
{
const char code [ ] = " template <class T, int n=3> \n "
" class A \n "
" { T ar[n]; }; \n "
" \n "
" void f() \n "
" { \n "
" A<int,2> a1; \n "
" A<int> a2; \n "
" } \n " ;
// The expected result..
2018-11-07 21:25:42 +01:00
const char expected [ ] = " class A<int,2> ; "
" class A<int,3> ; "
" void f ( ) "
2015-03-15 12:36:40 +01:00
" { "
2017-12-25 23:16:51 +01:00
" A<int,2> a1 ; "
" A<int,3> a2 ; "
2015-03-15 12:36:40 +01:00
" } "
2017-12-25 23:16:51 +01:00
" class A<int,2> "
2015-03-15 12:36:40 +01:00
" { int ar [ 2 ] ; } ; "
2017-12-25 23:16:51 +01:00
" class A<int,3> "
2015-03-15 12:36:40 +01:00
" { int ar [ 3 ] ; } ; " ;
2014-09-24 13:23:44 +02:00
ASSERT_EQUALS ( expected , tok ( code ) ) ;
}
{
const char code [ ] = " template <class T, int n1=3, int n2=2> \n "
" class A \n "
" { T ar[n1+n2]; }; \n "
" \n "
" void f() \n "
" { \n "
" A<int> a1; \n "
" A<int,3> a2; \n "
" } \n " ;
// The expected result..
2018-11-07 21:25:42 +01:00
const char expected [ ] = " class A<int,3,2> ; "
" void f ( ) "
2015-03-15 12:36:40 +01:00
" { "
2017-12-25 23:16:51 +01:00
" A<int,3,2> a1 ; "
" A<int,3,2> a2 ; "
2015-03-15 12:36:40 +01:00
" } "
2017-12-25 23:16:51 +01:00
" class A<int,3,2> "
2015-03-15 12:36:40 +01:00
" { int ar [ 5 ] ; } ; " ;
2014-09-24 13:23:44 +02:00
ASSERT_EQUALS ( expected , tok ( code ) ) ;
}
{
const char code [ ] = " template <class T, int n=3> \n "
" class A \n "
" { T ar[n]; }; \n "
" \n "
" void f() \n "
" { \n "
" A<int,(int)2> a1; \n "
" A<int> a2; \n "
" } \n " ;
2015-03-15 12:36:40 +01:00
const char wanted [ ] = " template < class T , int n > "
" class A "
" { T ar [ n ] ; } ; "
" void f ( ) "
" { "
" A<int,(int)2> a1 ; "
" A<int,3> a2 ; "
" } "
" class A<int,2> "
" { int ar [ 2 ] ; } "
" class A<int,3> "
" { int ar [ 3 ] ; } " ;
2018-11-07 21:25:42 +01:00
const char current [ ] = " class A<int,3> ; "
" void f ( ) "
2015-03-15 12:36:40 +01:00
" { "
" A < int , ( int ) 2 > a1 ; "
2017-12-25 23:16:51 +01:00
" A<int,3> a2 ; "
2015-03-15 12:36:40 +01:00
" } "
2017-12-25 23:16:51 +01:00
" class A<int,3> "
2015-03-15 12:36:40 +01:00
" { int ar [ 3 ] ; } ; " ;
2014-09-24 13:23:44 +02:00
TODO_ASSERT_EQUALS ( wanted , current , tok ( code ) ) ;
}
{
2015-03-07 11:06:04 +01:00
const char code [ ] = " class A { }; "
" template<class T> class B { }; "
" template<class T1, class T2 = B<T1>> class C { }; "
" template<class T1 = A, typename T2 = B<A>> class D { }; " ;
ASSERT_EQUALS ( " class A { } ; "
" template < class T > class B { } ; "
2015-03-21 16:30:00 +01:00
" template < class T1 , class T2 = B < T1 > > class C { } ; "
" template < class T1 = A , typename T2 = B < A > > class D { } ; " , tok ( code ) ) ;
2014-09-24 13:23:44 +02:00
}
2017-01-08 09:38:29 +01:00
{
// #7548
const char code [ ] = " template<class T, class U> class DefaultMemory {}; "
" template<class Key, class Val, class Mem=DefaultMemory<Key,Val> > class thv_table_c {}; "
" thv_table_c<void *,void *> id_table_m; " ;
const char exp [ ] = " template < class T , class U > class DefaultMemory { } ; "
2017-02-05 17:30:24 +01:00
" thv_table_c<void * , void * , DefaultMemory < void * , void *>> id_table_m ; "
" class thv_table_c<void * , void * , DefaultMemory < void * , void * >> { } ; " ;
2017-01-08 09:38:29 +01:00
const char curr [ ] = " template < class T , class U > class DefaultMemory { } ; "
2018-10-26 14:20:13 +02:00
" class thv_table_c<void*,void*,DefaultMemory<Key,Val>> ; "
2017-12-25 23:16:51 +01:00
" thv_table_c<void*,void*,DefaultMemory<Key,Val>> id_table_m ; "
" class thv_table_c<void*,void*,DefaultMemory<Key,Val>> { } ; " ;
2017-01-08 09:38:29 +01:00
TODO_ASSERT_EQUALS ( exp , curr , tok ( code ) ) ;
}
2014-09-24 13:23:44 +02:00
}
2018-10-24 14:38:59 +02:00
void template_forward_declared_default_parameter ( ) {
{
const char code [ ] = " template <class T, int n=3> class A; \n "
" template <class T, int n> \n "
" class A \n "
" { T ar[n]; }; \n "
" \n "
" void f() \n "
" { \n "
" A<int,2> a1; \n "
" A<int> a2; \n "
" } \n " ;
2018-12-20 20:55:27 +01:00
const char exp [ ] = " class A<int,2> ; "
" class A<int,3> ; "
" void f ( ) "
" { "
" A<int,2> a1 ; "
" A<int,3> a2 ; "
" } "
" class A<int,2> "
" { int ar [ 2 ] ; } ; "
" class A<int,3> "
" { int ar [ 3 ] ; } ; " ;
ASSERT_EQUALS ( exp , tok ( code ) ) ;
2018-10-24 14:38:59 +02:00
}
{
const char code [ ] = " template <class, int = 3> class A; \n "
" template <class T, int n> \n "
" class A \n "
" { T ar[n]; }; \n "
" \n "
" void f() \n "
" { \n "
" A<int,2> a1; \n "
" A<int> a2; \n "
" } \n " ;
2018-12-20 20:55:27 +01:00
const char exp [ ] = " class A<int,2> ; "
" class A<int,3> ; "
" void f ( ) "
" { "
" A<int,2> a1 ; "
" A<int,3> a2 ; "
" } "
" class A<int,2> "
" { int ar [ 2 ] ; } ; "
" class A<int,3> "
" { int ar [ 3 ] ; } ; " ;
ASSERT_EQUALS ( exp , tok ( code ) ) ;
2018-10-24 14:38:59 +02:00
}
}
2014-11-20 14:20:09 +01:00
void template_default_type ( ) {
2014-09-24 13:23:44 +02:00
const char code [ ] = " template <typename T, typename U=T> \n "
" class A \n "
" { \n "
" public: \n "
" void foo() { \n "
" int a; \n "
" a = static_cast<U>(a); \n "
" } \n "
" }; \n "
" \n "
" template <typename T> \n "
" class B \n "
" { \n "
" protected: \n "
" A<int> a; \n "
" }; \n "
" \n "
" class C \n "
" : public B<int> \n "
" { \n "
" }; \n " ;
tok ( code ) ;
//ASSERT_EQUALS("[file1.cpp:15]: (error) Internal error: failed to instantiate template. The checking continues anyway.\n", errout.str());
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void template_typename ( ) {
2014-09-24 13:23:44 +02:00
{
const char code [ ] = " template <class T> \n "
" void foo(typename T::t *) \n "
" { } " ;
// The expected result..
2015-03-15 12:36:40 +01:00
const char expected [ ] = " template < class T > void foo ( T :: t * ) { } " ;
2014-09-24 13:23:44 +02:00
ASSERT_EQUALS ( expected , tok ( code ) ) ;
}
{
const char code [ ] = " void f() { \n "
" x(sizeof typename); \n "
" type = 0; \n "
" } " ;
ASSERT_EQUALS ( " void f ( ) { x ( sizeof ( typename ) ) ; type = 0 ; } " , tok ( code ) ) ;
}
}
2014-11-20 14:20:09 +01:00
void template_constructor ( ) {
2014-09-24 13:23:44 +02:00
// #3152 - if template constructor is removed then there might be
// "no constructor" false positives
const char code [ ] = " class Fred { \n "
" template<class T> explicit Fred(T t) { } \n "
" } " ;
ASSERT_EQUALS ( " class Fred { template < class T > explicit Fred ( T t ) { } } " , tok ( code ) ) ;
// #3532
const char code2 [ ] = " class Fred { \n "
" template<class T> Fred(T t) { } \n "
" } " ;
ASSERT_EQUALS ( " class Fred { template < class T > Fred ( T t ) { } } " , tok ( code2 ) ) ;
}
2015-10-07 22:45:38 +02:00
void syntax_error_templates_1 ( ) {
// ok code.. using ">" for a comparison
tok ( " x<y>z> xyz; \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
// ok code
tok ( " template<class T> operator<(T a, T b) { } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
// ok code (ticket #1984)
tok ( " void f(a) int a; \n "
" { ;x<y; } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
// ok code (ticket #1985)
tok ( " void f() \n "
" try { ;x<y; } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
// ok code (ticket #3183)
tok ( " MACRO(({ i < x })) " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
// bad code.. missing ">"
ASSERT_THROW ( tok ( " x<y<int> xyz; \n " ) , InternalError ) ;
// bad code
ASSERT_THROW ( tok ( " typedef \n "
" typename boost::mpl::if_c< \n "
" _visitableIndex < boost::mpl::size< typename _Visitables::ConcreteVisitables >::value \n "
" , ConcreteVisitable \n "
" , Dummy< _visitableIndex > \n "
" >::type ConcreteVisitableOrDummy; \n " ) , InternalError ) ;
// code is ok, don't show syntax error
tok ( " struct A {int a;int b}; \n "
" class Fred { "
" public: \n "
" Fred() : a({1,2}) { \n "
" for (int i=0;i<6;i++); \n " // <- no syntax error
" } \n "
" private: \n "
" A a; \n "
" }; \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
void template_member_ptr ( ) { // Ticket #5786
tok ( " struct A {}; "
" struct B { "
" template <void (A::*)() const> struct BB {}; "
" template <bool BT> static bool foo(int) { return true; } "
" void bar() { bool b = foo<true>(0); } "
" }; " ) ;
tok ( " struct A {}; "
" struct B { "
" template <void (A::*)() volatile> struct BB {}; "
" template <bool BT> static bool foo(int) { return true; } "
" void bar() { bool b = foo<true>(0); } "
" }; " ) ;
tok ( " struct A {}; "
" struct B { "
" template <void (A::*)() const volatile> struct BB {}; "
" template <bool BT> static bool foo(int) { return true; } "
" void bar() { bool b = foo<true>(0); } "
" }; " ) ;
tok ( " struct A {}; "
" struct B { "
" template <void (A::*)() volatile const> struct BB {}; "
" template <bool BT> static bool foo(int) { return true; } "
" void bar() { bool b = foo<true>(0); } "
" }; " ) ;
}
2017-12-26 10:55:18 +01:00
void template_namespace_1 ( ) {
2017-06-30 14:34:28 +02:00
// #6570
const char code [ ] = " namespace { \n "
" template<class T> void Fred(T value) { } \n "
" } \n "
" Fred<int>(123); " ;
2018-11-23 11:36:09 +01:00
ASSERT_EQUALS ( " namespace { "
" void Fred<int> ( int value ) ; "
" } "
2017-12-25 23:16:51 +01:00
" Fred<int> ( 123 ) ; "
" void Fred<int> ( int value ) { } " , tok ( code ) ) ;
2017-06-30 14:34:28 +02:00
}
2015-10-07 22:45:38 +02:00
2017-12-26 10:55:18 +01:00
void template_namespace_2 ( ) {
// #8283
const char code [ ] = " namespace X { \n "
" template<class T> struct S { }; \n "
" } \n "
" X::S<int> s; " ;
2018-10-26 14:20:13 +02:00
ASSERT_EQUALS ( " namespace X { "
" struct S<int> ; "
" } "
" X :: S<int> s ; "
" struct X :: S<int> { } ; " , tok ( code ) ) ;
2017-12-26 10:55:18 +01:00
}
void template_namespace_3 ( ) {
const char code [ ] = " namespace test16 { \n "
" template <class T> struct foo { \n "
" static void *bar(); \n "
" }; \n "
" void *test() { return foo<int>::bar(); } \n "
" } " ;
ASSERT_EQUALS ( " namespace test16 { "
2018-10-26 14:20:13 +02:00
" struct foo<int> ; "
2017-12-26 10:55:18 +01:00
" void * test ( ) { "
2018-10-26 14:20:13 +02:00
" return foo<int> :: bar ( ) ; "
2017-12-26 10:55:18 +01:00
" } "
" } "
2018-10-26 14:20:13 +02:00
" struct test16 :: foo<int> { "
2017-12-26 10:55:18 +01:00
" static void * bar ( ) ; "
" } ; " , tok ( code ) ) ;
}
void template_namespace_4 ( ) {
const char code [ ] = " namespace foo { \n "
" template<class T> class A { void dostuff() {} }; \n "
" struct S : public A<int> { \n "
" void f() { \n "
" A<int>::dostuff(); \n "
" } \n "
" }; \n "
" } " ;
ASSERT_EQUALS ( " namespace foo { "
2018-10-26 14:20:13 +02:00
" class A<int> ; "
" struct S : public A<int> { "
2017-12-26 10:55:18 +01:00
" void f ( ) { "
2018-10-26 14:20:13 +02:00
" A<int> :: dostuff ( ) ; "
2017-12-26 10:55:18 +01:00
" } "
" } ; "
" } "
2018-10-26 14:20:13 +02:00
" class foo :: A<int> { void dostuff ( ) { } } ; " , tok ( code ) ) ;
2017-12-26 10:55:18 +01:00
}
2017-12-30 09:00:19 +01:00
void template_namespace_5 ( ) {
const char code [ ] = " template<class C> struct S {}; \n "
" namespace X { S<int> s; } " ;
2018-11-07 21:25:42 +01:00
ASSERT_EQUALS ( " struct S<int> ; "
" namespace X { S<int> s ; } "
" struct S<int> { } ; " , tok ( code ) ) ;
2017-12-30 09:00:19 +01:00
}
2018-10-26 14:20:13 +02:00
void template_namespace_6 ( ) {
const char code [ ] = " namespace NS { \n "
" template <typename T> union C { \n "
" char dummy[sizeof(T)]; \n "
" T value; \n "
" C(); \n "
" ~C(); \n "
" C(const C &); \n "
" C & operator = (const C &); \n "
" }; \n "
" } \n "
" NS::C<int> intC; \n "
" template <typename T> NS::C<T>::C() {} \n "
" template <typename T> NS::C<T>::~C() {} \n "
" template <typename T> NS::C<T>::C(const NS::C<T> &) {} \n "
" template <typename T> NS::C<T> & NS::C<T>::operator=(const NS::C<T> &) {} " ;
ASSERT_EQUALS ( " namespace NS { "
" union C<int> ; "
" } "
" NS :: C<int> intC ; union NS :: C<int> { "
" char dummy [ 4 ] ; "
" int value ; "
" C<int> ( ) ; "
" ~ C<int> ( ) ; "
" C<int> ( const NS :: C<int> & ) ; "
" NS :: C<int> & operator= ( const NS :: C<int> & ) ; "
" } ; "
" NS :: C<int> :: C<int> ( ) { } "
" NS :: C<int> :: ~ C<int> ( ) { } "
" NS :: C<int> :: C<int> ( const NS :: C<int> & ) { } "
" NS :: C<int> & NS :: C<int> :: operator= ( const NS :: C<int> & ) { } " , tok ( code ) ) ;
}
void template_namespace_7 ( ) { // #8768
const char code [ ] = " namespace N1 { \n "
" namespace N2 { \n "
" struct C { }; \n "
" template <class T> struct CT { }; \n "
" C c1; \n "
" CT<int> ct1; \n "
" } \n "
" N2::C c2; \n "
" N2::CT<int> ct2; \n "
" } \n "
" N1::N2::C c3; \n "
" N1::N2::CT<int> ct3; " ;
ASSERT_EQUALS ( " namespace N1 { "
" namespace N2 { "
" struct C { } ; "
" struct CT<int> ; "
" C c1 ; "
" CT<int> ct1 ; "
" } "
" N2 :: C c2 ; "
" N2 :: CT<int> ct2 ; "
" } "
" N1 :: N2 :: C c3 ; "
" N1 :: N2 :: CT<int> ct3 ; struct N1 :: N2 :: CT<int> { } ; " , tok ( code ) ) ;
}
2018-11-05 19:55:21 +01:00
void template_namespace_8 ( ) { // #8768
const char code [ ] = " namespace NS1 { \n "
" namespace NS2 { \n "
" template <typename T> \n "
" struct Fred { \n "
" Fred(); \n "
" Fred(const Fred &); \n "
" Fred & operator = (const Fred &); \n "
" ~Fred(); \n "
" }; \n "
" template <typename T> \n "
" Fred<T>::Fred() { } \n "
" template <typename T> \n "
" Fred<T>::Fred(const Fred<T> & f) { } \n "
" template <typename T> \n "
" Fred<T> & Fred<T>::operator = (const Fred<T> & f) { } \n "
" template <typename T> \n "
" Fred<T>::~Fred() { } \n "
" } \n "
" } \n "
" NS1::NS2::Fred<int> fred; " ;
ASSERT_EQUALS ( " namespace NS1 { "
" namespace NS2 { "
" struct Fred<int> ; "
" } "
" } "
" NS1 :: NS2 :: Fred<int> fred ; struct NS1 :: NS2 :: Fred<int> { "
" Fred<int> ( ) ; "
" Fred<int> ( const NS1 :: NS2 :: Fred<int> & ) ; "
" NS1 :: NS2 :: Fred<int> & operator= ( const NS1 :: NS2 :: Fred<int> & ) ; "
" ~ Fred<int> ( ) ; "
" } ; "
" NS1 :: NS2 :: Fred<int> :: Fred<int> ( ) { } "
" NS1 :: NS2 :: Fred<int> :: Fred<int> ( const NS1 :: NS2 :: Fred<int> & f ) { } "
" NS1 :: NS2 :: Fred<int> & NS1 :: NS2 :: Fred<int> :: operator= ( const NS1 :: NS2 :: Fred<int> & f ) { } "
" NS1 :: NS2 :: Fred<int> :: ~ Fred<int> ( ) { } " , tok ( code ) ) ;
}
void template_namespace_9 ( ) {
const char code [ ] = " namespace NS { \n "
" template<int type> struct Barney; \n "
" template<> struct Barney<1> { }; \n "
" template<int type> \n "
" class Fred { \n "
" public: \n "
" Fred(); \n "
" private: \n "
" Barney<type> m_data; \n "
" }; \n "
" template class Fred<1>; \n "
" } \n " ;
ASSERT_EQUALS ( " namespace NS { "
" template < int type > struct Barney ; "
" struct Barney<1> { } ; "
" class Fred<1> ; "
" } "
" class NS :: Fred<1> { "
" public: "
" Fred<1> ( ) ; "
" private: "
" Barney<1> m_data ; "
" } ; " , tok ( code ) ) ;
}
2018-11-07 21:25:42 +01:00
void template_namespace_10 ( ) {
const char code [ ] = " namespace NS1 { \n "
" namespace NS2 { \n "
" template<class T> \n "
" class Fred { \n "
" T * t; \n "
" public: \n "
" Fred<T>() : t(nullptr) {} \n "
" }; \n "
" } \n "
" } \n "
" NS1::NS2::Fred<int> fred; " ;
ASSERT_EQUALS ( " namespace NS1 { "
" namespace NS2 { "
" class Fred<int> ; "
" } "
" } "
" NS1 :: NS2 :: Fred<int> fred ; class NS1 :: NS2 :: Fred<int> "
" { "
" int * t ; "
" public: "
" Fred<int> ( ) : t ( nullptr ) { } "
" } ; " , tok ( code ) ) ;
}
2018-11-10 16:41:14 +01:00
void template_namespace_11 ( ) { // #7145
const char code [ ] = " namespace MyNamespace { \n "
" class TestClass { \n "
" public: \n "
" TestClass() { \n "
" SomeFunction(); \n "
2019-01-24 07:21:22 +01:00
" TemplatedMethod< int >( 0 ); \n "
2018-11-10 16:41:14 +01:00
" } \n "
" void SomeFunction() { } \n "
" private: \n "
2018-11-23 11:36:09 +01:00
" template< typename T > T TemplatedMethod(T); \n "
2018-11-10 16:41:14 +01:00
" }; \n "
2018-11-23 11:36:09 +01:00
" template< typename T > T TestClass::TemplatedMethod(T t) { return t; } \n "
2018-11-10 16:41:14 +01:00
" } " ;
ASSERT_EQUALS ( " namespace MyNamespace { "
" class TestClass { "
" public: "
" TestClass ( ) { "
" SomeFunction ( ) ; "
2019-01-24 07:21:22 +01:00
" TemplatedMethod<int> ( 0 ) ; "
2018-11-10 16:41:14 +01:00
" } "
" void SomeFunction ( ) { } "
" private: "
2018-11-23 11:36:09 +01:00
" int TemplatedMethod<int> ( int ) ; "
2018-11-10 16:41:14 +01:00
" } ; "
2018-11-23 11:36:09 +01:00
" } int MyNamespace :: TestClass :: TemplatedMethod<int> ( int t ) { return t ; } " , tok ( code ) ) ;
2018-11-10 16:41:14 +01:00
}
2014-11-20 14:20:09 +01:00
unsigned int templateParameters ( const char code [ ] ) {
2014-09-24 13:23:44 +02:00
Tokenizer tokenizer ( & settings , this ) ;
std : : istringstream istr ( code ) ;
2016-07-25 12:12:11 +02:00
tokenizer . tokenize ( istr , " test.cpp " , " " ) ;
2014-09-24 13:23:44 +02:00
2016-11-20 17:59:50 +01:00
return TemplateSimplifier : : templateParameters ( tokenizer . tokens ( ) - > next ( ) ) ;
2014-09-24 13:23:44 +02:00
}
2014-11-20 14:20:09 +01:00
void templateParameters ( ) {
2014-09-24 13:23:44 +02:00
// Test that the function TemplateSimplifier::templateParameters works
2016-11-20 17:59:50 +01:00
ASSERT_EQUALS ( 1U , templateParameters ( " X<struct C> x; " ) ) ;
ASSERT_EQUALS ( 1U , templateParameters ( " X<union C> x; " ) ) ;
ASSERT_EQUALS ( 1U , templateParameters ( " X<const int> x; " ) ) ;
ASSERT_EQUALS ( 1U , templateParameters ( " X<int const *> x; " ) ) ;
ASSERT_EQUALS ( 1U , templateParameters ( " X<const struct C> x; " ) ) ;
ASSERT_EQUALS ( 0U , templateParameters ( " X<len>>x; " ) ) ;
ASSERT_EQUALS ( 1U , templateParameters ( " X<typename> x; " ) ) ;
ASSERT_EQUALS ( 0U , templateParameters ( " X<...> x; " ) ) ;
ASSERT_EQUALS ( 0U , templateParameters ( " X<class T...> x; " ) ) ; // Invalid syntax
ASSERT_EQUALS ( 1U , templateParameters ( " X<class... T> x; " ) ) ;
ASSERT_EQUALS ( 0U , templateParameters ( " X<class, typename T...> x; " ) ) ; // Invalid syntax
ASSERT_EQUALS ( 2U , templateParameters ( " X<class, typename... T> x; " ) ) ;
ASSERT_EQUALS ( 2U , templateParameters ( " X<int(&)(), class> x; " ) ) ;
ASSERT_EQUALS ( 3U , templateParameters ( " X<char, int(*)(), bool> x; " ) ) ;
TODO_ASSERT_EQUALS ( 1U , 0U , templateParameters ( " X<int...> x; " ) ) ; // Mishandled valid syntax
TODO_ASSERT_EQUALS ( 2U , 0U , templateParameters ( " X<class, typename...> x; " ) ) ; // Mishandled valid syntax
2017-02-11 10:13:41 +01:00
ASSERT_EQUALS ( 2U , templateParameters ( " X<1, T> x; " ) ) ;
ASSERT_EQUALS ( 1U , templateParameters ( " X<i == 0> x; " ) ) ;
ASSERT_EQUALS ( 2U , templateParameters ( " X<int, i>=0> x; " ) ) ;
ASSERT_EQUALS ( 3U , templateParameters ( " X<int, i>=0, i - 2> x; " ) ) ;
2014-09-24 13:23:44 +02:00
}
2015-03-07 21:52:12 +01:00
// Helper function to unit test TemplateSimplifier::getTemplateNamePosition
2018-12-22 10:05:10 +01:00
int templateNamePositionHelper ( const char code [ ] , unsigned offset = 0 ) {
2015-03-07 21:52:12 +01:00
Tokenizer tokenizer ( & settings , this ) ;
std : : istringstream istr ( code ) ;
2018-12-22 10:05:10 +01:00
tokenizer . tokenize ( istr , " test.cpp " , emptyString ) ;
2015-03-07 21:52:12 +01:00
2015-04-03 12:19:08 +02:00
const Token * _tok = tokenizer . tokens ( ) ;
2015-03-07 21:52:12 +01:00
for ( unsigned i = 0 ; i < offset ; + + i )
2015-04-03 12:19:08 +02:00
_tok = _tok - > next ( ) ;
2018-12-22 10:05:10 +01:00
return tokenizer . mTemplateSimplifier - > getTemplateNamePosition ( _tok ) ;
2015-03-07 21:52:12 +01:00
}
void templateNamePosition ( ) {
// Template class
ASSERT_EQUALS ( 2 , templateNamePositionHelper ( " template<class T> class A {}; " , 4 ) ) ;
ASSERT_EQUALS ( 2 , templateNamePositionHelper ( " template<class T> struct A {}; " , 4 ) ) ;
ASSERT_EQUALS ( 2 , templateNamePositionHelper ( " template<class T> class A : B {}; " , 4 ) ) ;
ASSERT_EQUALS ( 2 , templateNamePositionHelper ( " template<class T> struct A : B {}; " , 4 ) ) ;
// Template function definitions
ASSERT_EQUALS ( 2 , templateNamePositionHelper ( " template<class T> unsigned foo() { return 0; } " , 4 ) ) ;
ASSERT_EQUALS ( 3 , templateNamePositionHelper ( " template<class T> unsigned* foo() { return 0; } " , 4 ) ) ;
2018-12-22 10:05:10 +01:00
ASSERT_EQUALS ( 4 , templateNamePositionHelper ( " template<class T> unsigned** foo() { return 0; } " , 4 ) ) ;
2015-03-07 21:52:12 +01:00
ASSERT_EQUALS ( 3 , templateNamePositionHelper ( " template<class T> const unsigned foo() { return 0; } " , 4 ) ) ;
ASSERT_EQUALS ( 4 , templateNamePositionHelper ( " template<class T> const unsigned& foo() { return 0; } " , 4 ) ) ;
2018-12-22 10:05:10 +01:00
ASSERT_EQUALS ( 5 , templateNamePositionHelper ( " template<class T> const unsigned** foo() { return 0; } " , 4 ) ) ;
ASSERT_EQUALS ( 4 , templateNamePositionHelper ( " template<class T> std::string foo() { static str::string str; return str; } " , 4 ) ) ;
ASSERT_EQUALS ( 5 , templateNamePositionHelper ( " template<class T> std::string & foo() { static str::string str; return str; } " , 4 ) ) ;
ASSERT_EQUALS ( 6 , templateNamePositionHelper ( " template<class T> const std::string & foo() { static str::string str; return str; } " , 4 ) ) ;
ASSERT_EQUALS ( 9 , templateNamePositionHelper ( " template<class T> std::map<int, int> foo() { static std::map<int, int> m; return m; } " , 4 ) ) ;
ASSERT_EQUALS ( 10 , templateNamePositionHelper ( " template<class T> std::map<int, int> & foo() { static std::map<int, int> m; return m; } " , 4 ) ) ;
ASSERT_EQUALS ( 11 , templateNamePositionHelper ( " template<class T> const std::map<int, int> & foo() { static std::map<int, int> m; return m; } " , 4 ) ) ;
2015-03-07 21:52:12 +01:00
// Class template members
2018-12-22 10:05:10 +01:00
ASSERT_EQUALS ( 4 , templateNamePositionHelper (
" class A { template<class T> unsigned foo(); }; "
" template<class T> unsigned A::foo() { return 0; } " , 19 ) ) ;
ASSERT_EQUALS ( 5 , templateNamePositionHelper (
" class A { template<class T> const unsigned foo(); }; "
" template<class T> const unsigned A::foo() { return 0; } " , 20 ) ) ;
ASSERT_EQUALS ( 7 , templateNamePositionHelper (
" class A { class B { template<class T> const unsigned foo(); }; } ; "
" template<class T> const unsigned A::B::foo() { return 0; } " , 25 ) ) ;
ASSERT_EQUALS ( 8 , templateNamePositionHelper (
" class A { class B { template<class T> const unsigned * foo(); }; } ; "
" template<class T> const unsigned * A::B::foo() { return 0; } " , 26 ) ) ;
ASSERT_EQUALS ( 9 , templateNamePositionHelper (
" class A { class B { template<class T> const unsigned ** foo(); }; } ; "
" template<class T> const unsigned ** A::B::foo() { return 0; } " , 27 ) ) ;
2015-03-07 21:52:12 +01:00
// Template class member
2018-12-22 10:05:10 +01:00
ASSERT_EQUALS ( 6 , templateNamePositionHelper (
" template<class T> class A { A(); }; "
" template<class T> A<T>::A() {} " , 18 ) ) ;
ASSERT_EQUALS ( 8 , templateNamePositionHelper (
" template<class T, class U> class A { A(); }; "
" template<class T, class U> A<T, U>::A() {} " , 24 ) ) ;
ASSERT_EQUALS ( 7 , templateNamePositionHelper (
" template<class T> class A { unsigned foo(); }; "
" template<class T> unsigned A<T>::foo() { return 0; } " , 19 ) ) ;
ASSERT_EQUALS ( 9 , templateNamePositionHelper (
" template<class T, class U> class A { unsigned foo(); }; "
" template<class T, class U> unsigned A<T, U>::foo() { return 0; } " , 25 ) ) ;
ASSERT_EQUALS ( 12 , templateNamePositionHelper (
2019-01-05 11:14:09 +01:00
" template<> unsigned A<int, v<char> >::foo() { return 0; } " , 2 ) ) ;
2015-03-07 21:52:12 +01:00
}
2016-01-11 18:45:12 +01:00
2018-10-14 16:57:07 +02:00
void expandSpecialized1 ( ) {
2017-12-25 23:16:51 +01:00
ASSERT_EQUALS ( " class A<int> { } ; " , tok ( " template<> class A<int> {}; " ) ) ;
ASSERT_EQUALS ( " class A<int> : public B { } ; " , tok ( " template<> class A<int> : public B {}; " ) ) ;
2018-10-14 16:57:07 +02:00
ASSERT_EQUALS ( " class A<int> { A<int> ( ) ; ~ A<int> ( ) ; } ; " , tok ( " template<> class A<int> { A(); ~A(); }; " ) ) ;
ASSERT_EQUALS ( " class A<int> { A<int> ( ) { } ~ A<int> ( ) { } } ; " , tok ( " template<> class A<int> { A() {} ~A() {} }; " ) ) ;
ASSERT_EQUALS ( " class A<int> { A<int> ( ) ; ~ A<int> ( ) ; } ; A<int> :: A<int> ( ) { } ~ A<int> :: A<int> ( ) { } " ,
tok ( " template<> class A<int> { A(); ~A(); }; A<int>::A() { } ~A<int>::A() {} " ) ) ;
ASSERT_EQUALS ( " class A<int> { A<int> ( ) ; A<int> ( const A<int> & ) ; A<int> foo ( ) ; } ; A<int> :: A<int> ( ) { } A<int> :: A<int> ( const A<int> & ) { } A<int> A<int> :: foo ( ) { A<int> a ; return a ; } " ,
tok ( " template<> class A<int> { A(); A(const A &) ; A foo(); }; A<int>::A() { } A<int>::A(const A &) { } A<int> A<int>::foo() { A a; return a; } " ) ) ;
}
void expandSpecialized2 ( ) {
{
const char code [ ] = " template <> \n "
" class C<float> { \n "
" public: \n "
" C() { } \n "
" C(const C &) { } \n "
" ~C() { } \n "
" C & operator=(const C &) { return *this; } \n "
" }; \n "
" C<float> b; \n " ;
const char expected [ ] = " class C<float> { "
" public: "
" C<float> ( ) { } "
" C<float> ( const C<float> & ) { } "
" ~ C<float> ( ) { } "
" C<float> & operator= ( const C<float> & ) { return * this ; } "
" } ; "
" C<float> b ; " ;
ASSERT_EQUALS ( expected , tok ( code ) ) ;
}
{
const char code [ ] = " template <> \n "
" class C<float> { \n "
" public: \n "
" C() { } \n "
" C(const C &) { } \n "
" ~C() { } \n "
" C & operator=(const C &) { return *this; } \n "
" }; " ;
const char expected [ ] = " class C<float> { "
" public: "
" C<float> ( ) { } "
" C<float> ( const C<float> & ) { } "
" ~ C<float> ( ) { } "
" C<float> & operator= ( const C<float> & ) { return * this ; } "
" } ; " ;
ASSERT_EQUALS ( expected , tok ( code ) ) ;
}
{
const char code [ ] = " template <> \n "
" class C<float> { \n "
" public: \n "
" C(); \n "
" C(const C &); \n "
" ~C(); \n "
" C & operator=(const C &); \n "
" }; \n "
" C::C() { } \n "
" C::C(const C &) { } \n "
" C::~C() { } \n "
" C & C::operator=(const C &) { return *this; } \n "
" C<float> b; \n " ;
const char expected [ ] = " class C<float> { "
" public: "
" C<float> ( ) ; "
" C<float> ( const C<float> & ) ; "
" ~ C<float> ( ) ; "
" C<float> & operator= ( const C<float> & ) ; "
" } ; "
" C<float> :: C<float> ( ) { } "
" C<float> :: C<float> ( const C<float> & ) { } "
" C<float> :: ~ C<float> ( ) { } "
" C<float> & C<float> :: operator= ( const C<float> & ) { return * this ; } "
" C<float> b ; " ;
ASSERT_EQUALS ( expected , tok ( code ) ) ;
}
{
const char code [ ] = " template <> \n "
" class C<float> { \n "
" public: \n "
" C(); \n "
" C(const C &); \n "
" ~C(); \n "
" C & operator=(const C &); \n "
" }; \n "
" C::C() { } \n "
" C::C(const C &) { } \n "
" C::~C() { } \n "
" C & C::operator=(const C &) { return *this; } " ;
const char expected [ ] = " class C<float> { "
" public: "
" C<float> ( ) ; "
" C<float> ( const C<float> & ) ; "
" ~ C<float> ( ) ; "
" C<float> & operator= ( const C<float> & ) ; "
" } ; "
" C<float> :: C<float> ( ) { } "
" C<float> :: C<float> ( const C<float> & ) { } "
" C<float> :: ~ C<float> ( ) { } "
" C<float> & C<float> :: operator= ( const C<float> & ) { return * this ; } " ;
ASSERT_EQUALS ( expected , tok ( code ) ) ;
}
}
void expandSpecialized3 ( ) { // #8671
const char code [ ] = " template <> struct OutputU16<unsigned char> final { \n "
" explicit OutputU16(std::basic_ostream<unsigned char> &t) : outputStream_(t) {} \n "
" void operator()(unsigned short) const; \n "
" private: \n "
" std::basic_ostream<unsigned char> &outputStream_; \n "
" }; " ;
const char expected [ ] = " struct OutputU16<unsignedchar> final { "
" explicit OutputU16<unsignedchar> ( std :: basic_ostream < char > & t ) : outputStream_ ( t ) { } "
" void operator() ( short ) const ; "
" private: "
" std :: basic_ostream < char > & outputStream_ ; "
" } ; " ;
ASSERT_EQUALS ( expected , tok ( code ) ) ;
2016-01-11 18:45:12 +01:00
}
2017-12-02 19:18:36 +01:00
2018-10-15 19:35:26 +02:00
void expandSpecialized4 ( ) {
{
const char code [ ] = " template<> class C<char> { }; \n "
" map<int> m; " ;
const char expected [ ] = " class C<char> { } ; "
" map < int > m ; " ;
ASSERT_EQUALS ( expected , tok ( code ) ) ;
}
{
const char code [ ] = " template<> class C<char> { }; \n "
" map<int> m; \n "
" C<char> c; " ;
const char expected [ ] = " class C<char> { } ; "
" map < int > m ; "
" C<char> c ; " ;
ASSERT_EQUALS ( expected , tok ( code ) ) ;
}
{
const char code [ ] = " template<typename T> class C { }; \n "
" template<> class C<char> { }; \n "
" map<int> m; \n " ;
const char expected [ ] = " template < typename T > class C { } ; "
" class C<char> { } ; "
" map < int > m ; " ;
ASSERT_EQUALS ( expected , tok ( code ) ) ;
}
{
const char code [ ] = " template<typename T> class C { }; \n "
" template<> class C<char> { }; \n "
" map<int> m; \n "
" C<int> i; " ;
2018-11-07 21:25:42 +01:00
const char expected [ ] = " class C<int> ; "
" class C<char> { } ; "
2018-10-15 19:35:26 +02:00
" map < int > m ; "
" C<int> i ; "
" class C<int> { } ; " ;
ASSERT_EQUALS ( expected , tok ( code ) ) ;
}
{
const char code [ ] = " template<typename T> class C { }; \n "
" template<> class C<char> { }; \n "
" map<int> m; \n "
" C<int> i; \n "
" C<char> c; " ;
2018-11-07 21:25:42 +01:00
const char expected [ ] = " class C<int> ; "
" class C<char> { } ; "
2018-10-15 19:35:26 +02:00
" map < int > m ; "
" C<int> i ; "
" C<char> c ; "
" class C<int> { } ; " ;
ASSERT_EQUALS ( expected , tok ( code ) ) ;
}
}
2017-12-29 22:47:07 +01:00
void templateAlias1 ( ) {
const char code [ ] = " template<class T, int N> struct Foo {}; \n "
" template<class T> using Bar = Foo<T,3>; \n "
" Bar<int> b; \n " ;
2018-11-07 21:25:42 +01:00
const char expected [ ] = " struct Foo<int,3> ; "
" Foo<int,3> b ; "
" struct Foo<int,3> { } ; " ;
2017-12-29 22:47:07 +01:00
ASSERT_EQUALS ( expected , tok ( code ) ) ;
}
void templateAlias2 ( ) {
const char code [ ] = " namespace A { template<class T, int N> struct Foo {}; } \n "
" template<class T> using Bar = A::Foo<T,3>; \n "
" Bar<int> b; \n " ;
2018-10-26 14:20:13 +02:00
const char expected [ ] = " namespace A { struct Foo<int,3> ; } "
" ; "
" A :: Foo<int,3> b ; "
" struct A :: Foo<int,3> { } ; " ;
2017-12-29 22:47:07 +01:00
ASSERT_EQUALS ( expected , tok ( code ) ) ;
}
2018-01-05 16:10:13 +01:00
void templateAlias3 ( ) { // #8315
const char code [ ] = " template <int> struct Tag {}; \n "
" template <int ID> using SPtr = std::shared_ptr<void(Tag<ID>)>; \n "
" SPtr<0> s; " ;
2018-11-07 21:25:42 +01:00
const char expected [ ] = " struct Tag<0> ; "
" std :: shared_ptr < void ( Tag<0> ) > s ; "
" struct Tag<0> { } ; " ;
2018-01-05 16:10:13 +01:00
ASSERT_EQUALS ( expected , tok ( code ) ) ;
}
2017-12-26 10:55:18 +01:00
unsigned int instantiateMatch ( const char code [ ] , const std : : size_t numberOfArguments , const char patternAfter [ ] ) {
2017-12-02 19:18:36 +01:00
Tokenizer tokenizer ( & settings , this ) ;
std : : istringstream istr ( code ) ;
tokenizer . tokenize ( istr , " test.cpp " , " " ) ;
2017-12-26 10:55:18 +01:00
return TemplateSimplifier : : instantiateMatch ( tokenizer . tokens ( ) , numberOfArguments , patternAfter ) ;
2017-12-02 19:18:36 +01:00
}
void instantiateMatch ( ) {
// Ticket #8175
ASSERT_EQUALS ( false ,
instantiateMatch ( " ConvertHelper < From, To > c ; " ,
2017-12-26 10:55:18 +01:00
2 , " :: %name% ( " ) ) ;
2017-12-02 19:18:36 +01:00
ASSERT_EQUALS ( true ,
instantiateMatch ( " ConvertHelper < From, To > :: Create ( ) ; " ,
2017-12-26 10:55:18 +01:00
2 , " :: %name% ( " ) ) ;
2017-12-02 19:18:36 +01:00
ASSERT_EQUALS ( false ,
instantiateMatch ( " integral_constant < bool, sizeof ( ConvertHelper < From, To > :: Create ( ) ) > ; " ,
2017-12-26 10:55:18 +01:00
2 , " :: %name% ( " ) ) ;
2017-12-02 19:18:36 +01:00
ASSERT_EQUALS ( false ,
instantiateMatch ( " integral_constant < bool, sizeof ( ns :: ConvertHelper < From, To > :: Create ( ) ) > ; " ,
2017-12-26 10:55:18 +01:00
2 , " :: %name% ( " ) ) ;
2017-12-02 19:18:36 +01:00
}
2018-05-30 17:09:31 +02:00
2018-05-31 07:02:08 +02:00
void templateParameterWithoutName ( ) {
2018-05-30 17:09:31 +02:00
ASSERT_EQUALS ( 1U , templateParameters ( " template<typename = void> struct s; " ) ) ;
ASSERT_EQUALS ( 1U , templateParameters ( " template<template<typename = float> typename T> struct A { \n "
" void f();n "
" void g(); \n "
" };n " ) ) ;
2018-05-31 07:02:08 +02:00
}
2014-09-24 13:23:44 +02:00
} ;
REGISTER_TEST ( TestSimplifyTemplate )