2014-09-24 13:23:44 +02:00
/*
* Cppcheck - A tool for static C / C + + code analysis
2019-02-09 07:24:06 +01:00
* Copyright ( C ) 2007 - 2019 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 ) ;
2019-03-01 08:18:53 +01:00
TEST_CASE ( template82 ) ; // #8603
TEST_CASE ( template83 ) ; // #8867
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 ) ;
2019-01-31 23:57:37 +01:00
TEST_CASE ( template98 ) ; // #8959
2019-02-05 08:52:23 +01:00
TEST_CASE ( template99 ) ; // #8960
2019-02-07 08:50:49 +01:00
TEST_CASE ( template100 ) ; // #8967
2019-02-09 08:34:59 +01:00
TEST_CASE ( template101 ) ; // #8968
2019-03-01 08:18:53 +01:00
TEST_CASE ( template102 ) ; // #9005
2019-03-03 19:42:46 +01:00
TEST_CASE ( template103 ) ;
2019-03-25 14:56:51 +01:00
TEST_CASE ( template104 ) ; // #9021
2019-04-03 06:02:38 +02:00
TEST_CASE ( template105 ) ; // #9076
2019-04-04 06:07:49 +02:00
TEST_CASE ( template106 ) ;
2019-04-21 06:46:16 +02:00
TEST_CASE ( template107 ) ; // #8663
2019-05-24 10:44:08 +02:00
TEST_CASE ( template108 ) ; // #9109
2019-05-27 06:54:21 +02:00
TEST_CASE ( template109 ) ; // #9144
2019-06-01 10:52:29 +02:00
TEST_CASE ( template110 ) ;
TEST_CASE ( template111 ) ; // crash
2019-06-02 10:23:47 +02:00
TEST_CASE ( template112 ) ; // #9146 syntax error
2019-06-08 07:27:53 +02:00
TEST_CASE ( template113 ) ;
2019-06-12 07:44:48 +02:00
TEST_CASE ( template114 ) ; // #9155
2019-06-15 09:46:32 +02:00
TEST_CASE ( template115 ) ; // #9153
2019-06-17 21:18:27 +02:00
TEST_CASE ( template116 ) ; // #9178
2019-06-28 11:14:20 +02:00
TEST_CASE ( template117 ) ;
TEST_CASE ( template118 ) ;
TEST_CASE ( template119 ) ; // #9186
2019-07-01 07:01:14 +02:00
TEST_CASE ( template120 ) ;
2019-07-02 11:40:57 +02:00
TEST_CASE ( template121 ) ; // #9193
2019-07-03 08:35:48 +02:00
TEST_CASE ( template122 ) ; // #9147
TEST_CASE ( template123 ) ; // #9183
2019-07-07 10:20:43 +02:00
TEST_CASE ( template124 ) ; // #9197
2019-07-15 12:41:06 +02:00
TEST_CASE ( template125 ) ;
2019-07-23 21:28:24 +02:00
TEST_CASE ( template126 ) ; // #9217
2019-07-24 19:20:19 +02:00
TEST_CASE ( template127 ) ; // #9225
2019-07-28 09:25:18 +02:00
TEST_CASE ( template128 ) ; // #9224
2019-07-31 09:18:43 +02:00
TEST_CASE ( template129 ) ;
2019-08-03 08:15:06 +02:00
TEST_CASE ( template130 ) ; // #9246
2019-08-04 10:24:44 +02:00
TEST_CASE ( template131 ) ; // #9249
2019-08-07 08:05:02 +02:00
TEST_CASE ( template132 ) ; // #9250
2019-08-17 07:38:07 +02:00
TEST_CASE ( template133 ) ;
TEST_CASE ( template134 ) ;
TEST_CASE ( template135 ) ;
2019-08-20 20:25:18 +02:00
TEST_CASE ( template136 ) ; // #9287
TEST_CASE ( template137 ) ; // #9288
2019-08-27 06:37:58 +02:00
TEST_CASE ( template138 ) ;
2019-09-01 09:56:33 +02:00
TEST_CASE ( template139 ) ;
2019-09-02 06:51:19 +02:00
TEST_CASE ( template140 ) ;
2019-09-07 09:09:04 +02:00
TEST_CASE ( template141 ) ; // #9337
2019-09-09 21:46:21 +02:00
TEST_CASE ( template142 ) ; // #9338
2019-09-11 19:31:15 +02:00
TEST_CASE ( template143 ) ;
2019-09-20 12:35:01 +02:00
TEST_CASE ( template144 ) ; // #9046
TEST_CASE ( template145 ) ; // syntax error
TEST_CASE ( template146 ) ; // syntax error
TEST_CASE ( template147 ) ; // syntax error
2019-09-26 10:31:19 +02:00
TEST_CASE ( template148 ) ; // syntax error
2019-09-26 16:01:01 +02:00
TEST_CASE ( template149 ) ; // unknown macro
2019-10-03 12:26:45 +02:00
TEST_CASE ( template150 ) ; // syntax error
2019-10-30 12:12:47 +01:00
TEST_CASE ( template151 ) ; // crash
2019-11-13 21:34:27 +01:00
TEST_CASE ( template152 ) ; // #9467
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
2019-07-07 18:33:33 +02:00
TEST_CASE ( findTemplateDeclarationEnd ) ;
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
2019-03-30 06:53:17 +01:00
TEST_CASE ( templateAlias4 ) ; // #9070
2019-06-12 07:44:48 +02:00
TEST_CASE ( templateAlias5 ) ;
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
2019-02-14 11:48:59 +01:00
TEST_CASE ( templateTypeDeduction1 ) ; // #8962
TEST_CASE ( templateTypeDeduction2 ) ;
2019-03-25 14:56:51 +01:00
2019-09-25 12:06:29 +02:00
TEST_CASE ( simplifyTemplateArgs1 ) ;
TEST_CASE ( simplifyTemplateArgs2 ) ;
2019-05-23 20:53:26 +02:00
TEST_CASE ( template_variadic_1 ) ; // #9144
2019-06-01 10:52:29 +02:00
TEST_CASE ( template_variable_1 ) ;
TEST_CASE ( template_variable_2 ) ;
TEST_CASE ( template_variable_3 ) ;
2019-06-28 11:14:20 +02:00
TEST_CASE ( template_variable_4 ) ;
2019-07-28 21:52:52 +02:00
TEST_CASE ( simplifyDecltype ) ;
2014-09-24 13:23:44 +02:00
}
2019-02-27 07:06:34 +01:00
std : : string tok ( const char code [ ] , 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 " ) ;
2019-06-30 21:39:22 +02:00
return tokenizer . tokens ( ) - > stringifyList ( nullptr , true ) ;
2014-09-24 13:23:44 +02:00
}
2014-11-20 14:20:09 +01:00
void template1 ( ) {
2019-02-27 07:06:34 +01:00
const char code [ ] = " template <class T> T f(T val) { T a; } \n "
2014-09-24 13:23:44 +02:00
" f<int>(10); " ;
2019-02-27 07:06:34 +01:00
const char expected [ ] = " int f<int> ( int val ) ; "
2018-11-23 11:36:09 +01:00
" f<int> ( 10 ) ; "
2019-02-27 07:06:34 +01:00
" int f<int> ( int val ) { int a ; } " ;
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 " ;
2019-02-25 21:01:34 +01:00
const char wanted [ ] = " class ABC<int> ; "
2015-03-15 12:36:40 +01:00
" int main ( ) { "
" std :: vector < int > v ; "
" v . push_back ( 4 ) ; "
" return 0 ; "
2019-02-25 21:01:34 +01:00
" } "
" class ABC<int> { public: } ; " ;
2014-09-24 13:23:44 +02:00
2019-02-25 21:01:34 +01:00
const char current [ ] = " class ABC<int> ; "
2015-03-15 12:36:40 +01:00
" int main ( ) { "
2019-02-25 21:01:34 +01:00
" ABC<int> :: type v ; "
2015-03-15 12:36:40 +01:00
" v . push_back ( 4 ) ; "
" return 0 ; "
2019-02-25 21:01:34 +01:00
" } "
" class ABC<int> { public: } ; " ;
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 ; "
2019-02-27 07:06:34 +01:00
" template < typename T > class A { void f ( ) { B < T > a ; a = B < T > :: g ( ) ; T b ; b = 0 ; if ( b ) { b = 0 ; } } } ; "
2014-09-24 13:23:44 +02:00
" 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> ; "
2019-05-16 21:11:04 +02:00
" void f ( ) { A<int> a ; } ; "
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 " ;
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
" } "
2019-03-03 07:40:55 +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 "
2019-02-24 10:31:49 +01:00
" class AA { \n "
2014-09-24 13:23:44 +02:00
" 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()]; " ;
2019-02-24 10:31:49 +01:00
const char expected [ ] = " class BB { } ; "
" class AA<BB> ; "
" class AA<CC> ; "
" class CC { public: CC ( AA<BB> , int ) { } } ; "
" class XX { "
" AA<CC> y ; "
" public: "
" XX ( ) ; "
" } ; "
" XX :: XX ( ) : "
" y ( AA<CC> :: create ( new CC ( AA<BB> ( ) , 0 ) ) ) "
" { } "
" int yy [ AA<CC> :: size ( ) ] ; "
" class AA<BB> { "
" public: "
" static AA<BB> create ( BB * newObject ) ; "
" static int size ( ) ; "
" } ; "
" class AA<CC> { "
" public: "
" static AA<CC> create ( CC * newObject ) ; "
" static int size ( ) ; "
" } ; " ;
ASSERT_EQUALS ( expected , tok ( code ) ) ;
2014-09-24 13:23:44 +02:00
}
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 " ;
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 " ;
2019-02-24 10:31:49 +01:00
const char expected [ ] = " template < class T > "
" class Fred "
" { "
" template < class T > "
" static shared_ptr < Fred < T > > CreateFred ( ) "
" { "
" } "
" } ; "
" shared_ptr < int > i ; " ;
ASSERT_EQUALS ( expected , tok ( code ) ) ;
2014-09-24 13:23:44 +02:00
}
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; " ;
2019-03-03 07:40:55 +01:00
const char expected [ ] = " struct B<4> ; "
" class bitset<1> ; "
2018-10-26 14:20:13 +02:00
" bitset<1> z ; "
2019-03-03 07:40:55 +01:00
" class bitset<1> : B<4> { } ; "
" struct B<4> { int a [ 4 ] ; } ; " ;
ASSERT_EQUALS ( expected , tok ( code ) ) ;
2014-09-24 13:23:44 +02:00
}
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 " ;
2019-06-28 11:14:20 +02:00
const char expected [ ] = " class A<BLA> ; "
" class A<A<BLA>> ; "
2019-02-24 10:31:49 +01:00
" int main ( ) { "
" A<A<BLA>> gna1 ; "
" A<BLA> gna2 ; "
" } "
2019-06-28 11:14:20 +02:00
" class A<BLA> { "
" BLA mT ; "
2019-02-24 10:31:49 +01:00
" public: "
" void foo ( ) { } "
" } ; "
2019-06-28 11:14:20 +02:00
" class A<A<BLA>> { "
" A<BLA> mT ; "
2019-02-24 10:31:49 +01:00
" public: "
" void foo ( ) { } "
" } ; " ;
ASSERT_EQUALS ( expected , tok ( code ) ) ;
2014-09-24 13:23:44 +02:00
}
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-06-09 08:11:59 +02:00
const char expected [ ] = " struct A { "
" struct X<int> ; "
" template < typename T > struct X { T t ; } ; "
" } ; "
" struct A :: X<int> { int * t ; } ; " ;
ASSERT_EQUALS ( expected , 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
}
2019-03-01 01:01:39 +01:00
void template42 ( ) { // #4878 cppcheck 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 "
" } " ;
2019-04-19 20:53:07 +02:00
ASSERT_THROW ( tok ( code ) , InternalError ) ;
2014-09-24 13:23:44 +02:00
}
2019-03-01 01:01:39 +01:00
void template43 ( ) { // #5097 - Assert due to '>>' in 'B<A<C>>' not being treated as end of template instantiation
2019-02-26 06:41:04 +01:00
const char code [ ] = " template <typename T> struct E { typedef int Int; }; \n "
" template <typename T> struct C { }; \n "
" template <typename T> struct D { static int f() { return C<T>::f(); } }; \n "
" template <typename T> inline int f2() { return D<T>::f(); } \n "
" template <typename T> int f1 (int x, T *) { int id = f2<T>(); return id; } \n "
" template <typename T> struct B { void f3(B<T> & other) { } }; \n "
" struct A { }; \n "
" template <> struct C<B<A>> { \n "
" static int f() { return f1<B<A>>(0, reinterpret_cast<B<A>*>(E<void*>::Int(-1))); } \n "
" }; \n "
" int main(void) { \n "
" C<A> ca; \n "
" return 0; \n "
" } " ;
const char expected [ ] = " struct E<void*> ; "
2019-06-09 08:11:59 +02:00
" struct C<B<A>> ; "
2019-02-26 06:41:04 +01:00
" struct C<A> ; "
" struct D<B<A>> ; "
" int f2<B<A>> ( ) ; "
" int f1<B<A>> ( int x , B<A> * ) ; "
" struct B<A> ; "
" struct A { } ; "
" struct C<B<A>> { "
" static int f ( ) { "
" return f1<B<A>> ( 0 , reinterpret_cast < B<A> * > ( E<void*> :: Int ( -1 ) ) ) ; "
" } "
" } ; "
" int main ( ) { "
" C<A> ca ; "
" return 0 ; "
" } "
" struct B<A> { "
" void f3 ( B<A> & other ) { } "
" } ; "
" int f1<B<A>> ( int x , B<A> * ) { "
" int id ; id = f2<B<A>> ( ) ; "
" return id ; "
" } "
" int f2<B<A>> ( ) { "
" return D<B<A>> :: f ( ) ; "
" } "
" struct D<B<A>> { "
" static int f ( ) { "
" return C<B<A>> :: f ( ) ; "
" } "
" } ; "
" struct C<A> { } ; struct E<void*> { "
" } ; " ;
2019-02-27 07:06:34 +01:00
ASSERT_EQUALS ( expected , tok ( code ) ) ;
2014-09-24 13:23:44 +02:00
}
2014-11-20 14:20:09 +01:00
void template44 ( ) { // #5297
2019-02-24 10:31:49 +01:00
const char code [ ] = " 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> {}; " ;
const char expected [ ] = " struct StackContainer<FGSTensor> ; "
" class ZContainer<FGSTensor> ; "
" struct FGSTensor { } ; "
" class FoldedZContainer : public ZContainer<FGSTensor> { } ; "
" class ZContainer<FGSTensor> : public StackContainer<FGSTensor> { } ; "
" struct StackContainer<FGSTensor> { "
" void foo ( int i ) { "
" if ( 0 >= 1 && i < 0 ) { } "
" } "
" } ; " ;
2019-02-27 07:06:34 +01:00
ASSERT_EQUALS ( expected , tok ( code ) ) ;
2014-09-24 13:23:44 +02:00
}
2014-11-20 14:20:09 +01:00
void template45 ( ) { // #5814
2019-02-25 21:01:34 +01:00
const char code [ ] = " 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>::mult }; "
" }; "
" FOO<int> foo; " ;
const char expected [ ] = " namespace Constants { const int fourtytwo = 42 ; } "
" struct TypeMath<int,Constants::fourtytwo> ; "
" struct FOO<int> ; "
" FOO<int> foo ; "
" struct FOO<int> { "
" enum Anonymous0 { value = TypeMath<int,Constants::fourtytwo> :: mult } ; "
" } ; "
" struct TypeMath<int,Constants::fourtytwo> { "
" static const int mult = sizeof ( int ) * Constants :: fourtytwo ; "
" } ; " ;
2019-02-27 07:06:34 +01:00
ASSERT_EQUALS ( expected , tok ( code , true ) ) ;
2014-09-24 13:23:44 +02:00
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
2019-02-24 10:31:49 +01:00
const char code [ ] = " template <int value> int sum() { "
" return value + sum<value/2>(); "
" } "
" template<int x, int y> int calculate_value() { "
" if (x != y) { "
" return sum<x - y>(); "
" } else { "
" return 0; "
" } "
" } "
" int value = calculate_value<1,1>(); " ;
const char expected [ ] = " int sum<0> ( ) ; "
" int calculate_value<1,1> ( ) ; "
" int value ; value = calculate_value<1,1> ( ) ; "
" int calculate_value<1,1> ( ) { "
" if ( 1 != 1 ) { "
" return sum<0> ( ) ; "
" } else { "
" return 0 ; "
" } "
" } "
" int sum<0> ( ) { "
" return 0 + sum<0> ( ) ; "
" } " ;
2019-02-27 07:06:34 +01:00
ASSERT_EQUALS ( expected , tok ( code ) ) ;
2015-03-14 18:46:17 +01:00
}
2015-03-15 00:28:33 +01:00
void template53 ( ) { // #4335
2019-02-25 21:01:34 +01:00
const char code [ ] = " 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; " ;
2019-06-09 08:11:59 +02:00
const char expected [ ] = " struct Factorial<0> ; "
" struct Factorial<4> ; "
2019-02-25 21:01:34 +01:00
" struct Factorial<3> ; "
" struct Factorial<2> ; "
" struct Factorial<1> ; "
" struct Factorial<0> { "
" enum Anonymous1 { value = 1 } ; "
" } ; "
" const int x = Factorial<4> :: value ; "
" struct Factorial<4> { "
" enum Anonymous0 { value = 4 * Factorial<3> :: value } ; "
" } ; "
" struct Factorial<3> { "
" enum Anonymous0 { value = 3 * Factorial<2> :: value } ; "
" } ; "
" struct Factorial<2> { "
" enum Anonymous0 { value = 2 * Factorial<1> :: value } ; "
" } ; "
" struct Factorial<1> { "
" enum Anonymous0 { value = 1 * Factorial<0> :: value } ; "
" } ; " ;
2019-02-27 07:06:34 +01:00
ASSERT_EQUALS ( expected , tok ( code , true ) ) ;
2015-03-15 00:28:33 +01:00
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> { "
2019-02-27 07:06:34 +01:00
" A<int> ( int * p ) { ( A<int...> * ) ( p ) ; } "
2015-04-13 17:02:48 +02:00
" } ; "
2017-12-25 23:16:51 +01:00
" struct A<int...> { "
" A<int...> ( int * p ) { "
2019-02-27 07:06:34 +01:00
" ( A<int...> * ) ( p ) ; "
2015-04-13 17:02:48 +02:00
" } } ; " ,
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
2019-02-26 06:41:04 +01:00
const char code [ ] = " template<bool B> struct Foo { "
" std::array<int, B ? 1 : 2> mfoo; "
" }; "
" void foo() { "
" Foo<true> myFoo; "
" } " ;
const char expected [ ] = " struct Foo<true> ; "
" void foo ( ) { "
" Foo<true> myFoo ; "
" } struct Foo<true> { "
2019-03-25 14:56:51 +01:00
" std :: array < int , 1 > mfoo ; "
2019-02-26 06:41:04 +01:00
" } ; " ;
2019-02-27 07:06:34 +01:00
ASSERT_EQUALS ( expected , tok ( code , true ) ) ;
2016-06-04 20:35:16 +02:00
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 ) ; "
2019-02-27 07:06:34 +01:00
" struct Test<unsignedlong> { Test<unsignedlong> ( unsigned 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> ( ) { "
2019-02-27 07:06:34 +01:00
" x ( 1 * CheckedNumeric < int > ( ) ) ; "
2017-06-08 00:49:46 +02:00
" } " ;
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 "
" } " ;
2019-06-09 08:11:59 +02:00
const char exp [ ] = " struct Factorial<0> ; "
" struct Factorial<4> ; "
2018-11-07 21:25:42 +01:00
" 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 } ; } ; "
2019-02-27 07:06:34 +01:00
" struct Factorial<1> { enum FacHelper { value = 1 * 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> ; "
2019-06-01 10:52:29 +02:00
" void f<S<int>::type(0)> ( ) ; "
2018-11-23 11:36:09 +01:00
" void h<int> ( ) ; "
2017-12-25 23:16:51 +01:00
" void j ( ) { h<int> ( ) ; } "
2019-06-01 10:52:29 +02:00
" void h<int> ( ) { f<S<int>::type(0)> ( ) ; } "
" struct S<int> { } ; "
" void f<S<int>::type(0)> ( ) { } " ;
const char act [ ] = " template < typename T > struct S { } ; "
" void f<S<int>::type(0)> ( ) ; "
" void h<int> ( ) ; "
" void j ( ) { h<int> ( ) ; } "
" void h<int> ( ) { f<S<int>::type(0)> ( ) ; } "
" void f<S<int>::type(0)> ( ) { } " ;
TODO_ASSERT_EQUALS ( exp , act , tok ( code ) ) ;
2017-12-25 08:19:46 +01:00
}
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*> ; "
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 "
" }; " ;
2019-02-26 06:41:04 +01:00
const char exp [ ] = " bool foo<int> ( ) ; "
" struct A { "
" void t_func<0> ( ) ; "
" void t_func<1> ( ) ; "
" void t_caller ( ) "
" { "
" t_func<0> ( ) ; "
" t_func<1> ( ) ; "
" } "
" } ; "
" void A :: t_func<0> ( ) "
" { "
2019-03-03 07:40:55 +01:00
" if ( 0 != 0 || foo<int> ( ) ) { ; } "
2019-02-26 06:41:04 +01:00
" } "
" void A :: t_func<1> ( ) "
" { "
2019-03-03 07:40:55 +01:00
" if ( 1 != 0 || foo<int> ( ) ) { ; } "
2019-02-26 06:41:04 +01:00
" } "
" bool foo<int> ( ) { return true ; } " ;
2019-02-27 07:06:34 +01:00
ASSERT_EQUALS ( exp , tok ( code ) ) ;
2018-09-01 11:26:10 +02:00
}
2019-02-01 06:59:49 +01:00
void template65 ( ) { // #8321 (crash)
2018-09-01 11:26:10 +02:00
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 "
" } " ;
2019-02-01 06:59:49 +01:00
const char exp [ ] = " namespace bpp "
" { "
" class AssociationDAGraphImplObserver<string,unsignedint,DAGlobalGraph> ; "
" } "
" using namespace bpp ; "
" int main ( ) { "
" bpp :: AssociationDAGraphImplObserver<string,unsignedint,DAGlobalGraph> grObs ; "
" return 1 ; "
" } class bpp :: AssociationDAGraphImplObserver<string,unsignedint,DAGlobalGraph> : "
2019-02-27 07:06:34 +01:00
" public AssociationGraphImplObserver < std :: string , unsigned int , DAGlobalGraph > "
2019-02-01 06:59:49 +01:00
" { } ; " ;
ASSERT_EQUALS ( exp , tok ( code ) ) ;
2018-09-01 11:26:10 +02:00
}
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> { "
2019-02-27 07:06:34 +01:00
" char dummy [ sizeof ( int ) ] ; "
2018-09-26 06:23:12 +02:00
" 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 ; "
2019-06-09 08:11:59 +02:00
" class Bar<void,void> ; "
2018-10-26 14:20:13 +02:00
" class Bar<void,void> { "
" } ; "
" template < typename K , typename V , int KeySize = 0 > "
" class Bar : private Bar<void,void> { "
" void foo ( ) { } "
" } ; " ;
2019-06-09 08:11:59 +02:00
const char act [ ] = " template < typename T , typename V , int KeySize = 0 > class Bar ; "
" class Bar<void,void> { "
" } ; "
" class Bar<void,void> ; "
" template < typename K , typename V , int KeySize = 0 > "
" class Bar : private Bar<void,void> { "
" void foo ( ) { } "
" } ; " ;
TODO_ASSERT_EQUALS ( exp , act , tok ( code ) ) ;
2018-10-26 14:20:13 +02:00
}
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 "
" } " ;
2019-06-09 08:11:59 +02:00
const char exp [ ] = " struct is_void<void> ; "
" struct is_void<char> ; "
2018-11-23 11:36:09 +01:00
" 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 "
" } " ;
2019-02-27 07:06:34 +01:00
const char exp [ ] = " const int f16 = 16 ; "
" class tvec2<f16> ; "
2018-11-27 06:17:04 +01:00
" 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 ) ) ;
}
2019-03-01 08:18:53 +01:00
void template83 ( ) { // #8867
2018-11-29 06:24:28 +01:00
const char code [ ] = " template<typename Task> \n "
2019-03-01 08:18:53 +01:00
" class MultiConsumer { \n "
" MultiConsumer(); \n "
" }; \n "
" template<typename Task> \n "
2018-11-29 06:24:28 +01:00
" MultiConsumer<Task>::MultiConsumer() : sizeBuffer(0) {} \n "
" MultiReads::MultiReads() { \n "
" mc = new MultiConsumer<reads_packet>(); \n "
" } " ;
2019-03-01 08:18:53 +01:00
const char exp [ ] = " template < typename Task > " // TODO: this should be expanded
" class MultiConsumer { "
" MultiConsumer ( ) ; "
" } ; "
" MultiConsumer<reads_packet> :: MultiConsumer<reads_packet> ( ) ; "
2018-11-29 06:24:28 +01:00
" 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
2019-06-17 21:18:27 +02:00
{
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 [ ] = " template < class b , int c , class > "
" auto d ( ) . a < decltype ( b { } ) > :: e { "
" d < int , c , int > ( ) ; "
" } " ;
ASSERT_EQUALS ( exp , tok ( code ) ) ;
}
{
const char code [ ] = " template <class b, int c, class> \n "
" auto d() -> typename a<decltype(b{})>::e { \n "
" d<int, c, int>(); \n "
" } "
" void foo() { d<char, 1, int>(); } " ;
const char exp [ ] = " auto d<char,1,int> ( ) . a < char > :: e ; "
" auto d<int,1,int> ( ) . a < int > :: e ; "
" void foo ( ) { d<char,1,int> ( ) ; } "
" auto d<char,1,int> ( ) . a < char > :: e { "
" d<int,1,int> ( ) ; "
" } "
" auto d<int,1,int> ( ) . a < int > :: e { "
" d<int,1,int> ( ) ; "
" } " ;
ASSERT_EQUALS ( exp , tok ( code ) ) ;
}
2018-12-06 21:47:48 +01:00
}
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
2019-02-28 08:30:04 +01:00
{
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 exp [ ] = " const long fib<2> = fib<1> + fib<0> ; "
" const long fib<3> = fib<2> + fib<1> ; "
" 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> ; " ;
ASSERT_EQUALS ( exp , tok ( code ) ) ;
}
{
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 f5 = fib<5>; \n " ;
const char exp [ ] = " const long fib<5> = fib<4> + fib<3> ; "
" const long fib<4> = fib<3> + fib<2> ; "
" 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 f5 ; f5 = fib<5> ; " ;
ASSERT_EQUALS ( exp , tok ( code ) ) ;
}
2019-01-18 21:12:39 +01:00
}
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 ) ) ;
}
2019-01-31 23:57:37 +01:00
void template98 ( ) { // #8959
const char code [ ] = " template <typename T> \n "
" using unique_ptr_with_deleter = std::unique_ptr<T, std::function<void(T*)>>; \n "
" class A {}; \n "
" static void func() { \n "
" unique_ptr_with_deleter<A> tmp(new A(), [](A* a) { \n "
" delete a; \n "
" }); \n "
" } " ;
2019-06-01 10:52:29 +02:00
const char exp [ ] = " class A { } ; "
2019-01-31 23:57:37 +01:00
" static void func ( ) { "
" std :: unique_ptr < A , std :: function < void ( A * ) > > tmp ( new A ( ) , [ ] ( A * a ) { "
" delete a ; "
" } ) ; "
" } " ;
ASSERT_EQUALS ( exp , tok ( code ) ) ;
}
2019-02-05 08:52:23 +01:00
void template99 ( ) { // #8960
const char code [ ] = " template <typename T> \n "
" class Base { \n "
" public: \n "
" using ArrayType = std::vector<Base<T>>; \n "
" }; \n "
" using A = Base<int>; \n "
" static A::ArrayType array; \n " ;
const char exp [ ] = " class Base<int> ; "
" static std :: vector < Base<int> > array ; "
" class Base<int> { "
" public: "
" } ; " ;
ASSERT_EQUALS ( exp , tok ( code ) ) ;
}
2019-02-07 08:50:49 +01:00
void template100 ( ) { // #8967
const char code [ ] = " enum class Device { I2C0, I2C1 }; \n "
" template <Device D> \n "
" const char* deviceFile; \n "
" template <> \n "
" const char* deviceFile<Device::I2C0> = \" /tmp/i2c-0 \" ; \n " ;
const char exp [ ] = " enum class Device { I2C0 , I2C1 } ; "
" template < Device D > "
" const char * deviceFile ; "
" const char * deviceFile<Device::I2C0> ; deviceFile<Device::I2C0> = \" /tmp/i2c-0 \" ; " ;
ASSERT_EQUALS ( exp , tok ( code ) ) ;
}
2019-02-09 08:34:59 +01:00
void template101 ( ) { // #8968
const char code [ ] = " class A { \n "
" public: \n "
" using ArrayType = std::vector<int>; \n "
" void func(typename ArrayType::size_type i) { \n "
" } \n "
" }; " ;
const char exp [ ] = " class A { "
" public: "
" void func ( std :: vector < int > :: size_type i ) { "
" } "
" } ; " ;
ASSERT_EQUALS ( exp , tok ( code ) ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2019-03-01 08:18:53 +01:00
void template102 ( ) { // #9005
const char code [ ] = " namespace ns { \n "
" template <class T> \n "
" struct is_floating_point \n "
" : std::integral_constant<bool, std::is_floating_point<T>::value || true> \n "
" {}; \n "
" } \n "
" void f() { \n "
" if(std::is_floating_point<float>::value) {} \n "
" } " ;
const char exp [ ] = " namespace ns { "
" template < class T > "
" struct is_floating_point "
" : std :: integral_constant < bool , std :: is_floating_point < T > :: value || true > "
" { } ; "
" } "
" void f ( ) { "
" if ( std :: is_floating_point < float > :: value ) { } "
" } " ;
ASSERT_EQUALS ( exp , tok ( code ) ) ;
}
2019-03-03 19:42:46 +01:00
void template103 ( ) {
const char code [ ] = " namespace sample { \n "
" template <typename T> \n "
" class Sample { \n "
" public: \n "
" T function(T t); \n "
" }; \n "
" template <typename T> \n "
" T Sample<T>::function(T t) { \n "
" return t; \n "
" } \n "
" } \n "
" sample::Sample<int> s1; " ;
const char exp [ ] = " namespace sample { "
" class Sample<int> ; "
" } "
" sample :: Sample<int> s1 ; "
" class sample :: Sample<int> { "
" public: "
" int function ( int t ) ; "
" } ; "
" int sample :: Sample<int> :: function ( int t ) { "
" return t ; "
" } " ;
ASSERT_EQUALS ( exp , tok ( code ) ) ;
}
2019-03-25 14:56:51 +01:00
void template104 ( ) { // #9021
const char code [ ] = " template < int i > \n "
" auto key ( ) { return hana :: test :: ct_eq < i > { } ; } \n "
" template < int i > \n "
" auto val ( ) { return hana :: test :: ct_eq < - i > { } ; } \n "
" template < int i , int j > \n "
" auto p ( ) { return :: minimal_product ( key < i > ( ) , val < j > ( ) ) ; } \n "
" int main ( ) { \n "
" BOOST_HANA_CONSTANT_CHECK ( hana :: equal ( \n "
" hana :: at_key ( hana :: make_map ( p < 0 , 0 > ( ) ) , key < 0 > ( ) ) , \n "
" val < 0 > ( ) ) ) ; \n "
" } " ;
const char exp [ ] = " auto key<0> ( ) ; "
" auto val<0> ( ) ; "
" auto p<0,0> ( ) ; "
" int main ( ) { "
" BOOST_HANA_CONSTANT_CHECK ( hana :: equal ( "
" hana :: at_key ( hana :: make_map ( p<0,0> ( ) ) , key<0> ( ) ) , "
" val<0> ( ) ) ) ; "
" } "
" auto p<0,0> ( ) { return :: minimal_product ( key<0> ( ) , val<0> ( ) ) ; } "
" auto val<0> ( ) { return hana :: test :: ct_eq < - 0 > { } ; } "
" auto key<0> ( ) { return hana :: test :: ct_eq < 0 > { } ; } " ;
ASSERT_EQUALS ( exp , tok ( code ) ) ;
}
2019-04-03 06:02:38 +02:00
void template105 ( ) { // #9076
const char code [ ] = " template <template <typename> class TOUT> class ObjectCache; \n "
" template <template <typename> class TOUT> \n "
" class ObjectCache { }; \n "
" template <typename T> class Fred {}; \n "
" ObjectCache<Fred> _cache; " ;
const char exp [ ] = " class ObjectCache<Fred> ; "
" ObjectCache<Fred> _cache ; "
" class ObjectCache<Fred> { } ; " ;
ASSERT_EQUALS ( exp , tok ( code ) ) ;
}
2019-04-04 06:07:49 +02:00
void template106 ( ) {
const char code [ ] = " template<class T, class U> class A { \n "
" public: \n "
" int x; \n "
" }; \n "
" template<template<class T, class U> class V> class B { \n "
" V<char, char> i; \n "
" }; \n "
" B<A> c; " ;
const char exp [ ] = " class A<char,char> ; "
" class B<A> ; "
" B<A> c ; "
" class B<A> { "
" A<char,char> i ; "
" } ; class A<char,char> { "
" public: "
" int x ; "
" } ; " ;
ASSERT_EQUALS ( exp , tok ( code ) ) ;
}
2019-04-21 06:46:16 +02:00
void template107 ( ) { // #8663
const char code [ ] = " template <class T1, class T2> \n "
" void f() { \n "
" using T3 = typename T1::template T3<T2>; \n "
" T3 t; \n "
" } \n "
" struct C3 { \n "
" template <typename T> \n "
" class T3 \n "
" {}; \n "
" }; \n "
" void foo() { \n "
" f<C3, long>(); \n "
" } " ;
const char exp [ ] = " void f<C3,long> ( ) ; "
" struct C3 { "
" class T3<long> ; "
" } ; "
" void foo ( ) { "
" f<C3,long> ( ) ; "
" } "
" void f<C3,long> ( ) { "
" C3 :: T3<long> t ; "
" } "
" class C3 :: T3<long> { } ; " ;
ASSERT_EQUALS ( exp , tok ( code ) ) ;
}
2019-05-24 10:44:08 +02:00
void template108 ( ) { // #9109
{
const char code [ ] = " template <typename> struct a; \n "
" template <typename> struct b {}; \n "
" template <typename> struct c; \n "
" template <typename d> struct e { \n "
" using f = a<b<typename c<d>::g>>; \n "
" bool h = f::h; \n "
" }; \n "
" struct i { \n "
" e<int> j(); \n "
" }; \n " ;
const char exp [ ] = " template < typename > struct a ; "
" struct b<c<int>::g> ; "
" template < typename > struct c ; "
" struct e<int> ; "
" struct i { e<int> j ( ) ; "
" } ; "
" struct e<int> { bool h ; "
" h = a < b<c<int>::g> > :: h ; "
" } ; "
" struct b<c<int>::g> { } ; " ;
ASSERT_EQUALS ( exp , tok ( code ) ) ;
}
{
const char code [ ] = " namespace { \n "
" template <typename> struct a; \n "
" template <typename> struct b {}; \n "
" } \n "
" namespace { \n "
" template <typename> struct c; \n "
" template <typename d> struct e { \n "
" using f = a<b<typename c<d>::g>>; \n "
" bool h = f::h; \n "
" }; \n "
" template <typename i> using j = typename e<i>::g; \n "
" } " ;
const char exp [ ] = " namespace { "
" template < typename > struct a ; "
" template < typename > struct b { } ; "
" } "
" namespace { "
" template < typename > struct c ; "
" template < typename d > struct e { "
" using f = a < b < c < d > :: g > > ; "
" bool h ; h = f :: h ; "
" } ; "
" template < typename i > using j = typename e < i > :: g ; "
" } " ;
ASSERT_EQUALS ( exp , tok ( code ) ) ;
}
{
const char code [ ] = " namespace { \n "
" template <typename> struct a; \n "
" template <typename> struct b {}; \n "
" } \n "
" namespace { \n "
" template <typename> struct c; \n "
" template <typename d> struct e { \n "
" using f = a<b<typename c<d>::g>>; \n "
" bool h = f::h; \n "
" }; \n "
" template <typename i> using j = typename e<i>::g; \n "
" } \n "
" j<int> foo; " ;
const char exp [ ] = " namespace { "
" template < typename > struct a ; "
" struct b<c<int>::g> ; "
" } "
" namespace { "
" template < typename > struct c ; "
" struct e<int> ; "
" } "
2019-06-12 07:44:48 +02:00
" e<int> :: g foo ; "
2019-05-24 10:44:08 +02:00
" struct e<int> { "
" bool h ; h = a < b<c<int>::g> > :: h ; "
" } ; "
" struct b<c<int>::g> { } ; " ;
ASSERT_EQUALS ( exp , tok ( code ) ) ;
}
}
2019-05-27 06:54:21 +02:00
void template109 ( ) { // #9144
{
const char code [ ] = " namespace a { \n "
" template <typename b, bool = __is_empty(b) && __is_final(b)> struct c; \n "
" } \n "
" template <typename...> struct e {}; \n "
" static_assert(sizeof(e<>) == sizeof(e<c<int>, c<int>, int>), \" \" ); \n " ;
const char exp [ ] = " namespace a { "
2019-05-27 20:51:52 +02:00
" template < typename b , bool > struct c ; "
2019-05-27 06:54:21 +02:00
" } "
2019-06-01 10:52:29 +02:00
" struct e<> ; "
" struct e<c<int>,c<int>,int> ; "
" static_assert ( sizeof ( e<> ) == sizeof ( e<c<int>,c<int>,int> ) , \" \" ) ; "
" struct e<> { } ; "
" struct e<c<int>,c<int>,int> { } ; " ;
ASSERT_EQUALS ( exp , tok ( code ) ) ;
}
{
const char code [ ] = " namespace a { \n "
" template <typename b, bool = __is_empty(b) && __is_final(b)> struct c; \n "
" } \n "
" template <typename...> struct e {}; \n "
" static_assert(sizeof(e<>) == sizeof(e<a::c<int>, a::c<int>, int>), \" \" ); \n " ;
const char exp [ ] = " namespace a { "
" template < typename b , bool > struct c ; "
2019-05-27 20:51:52 +02:00
" } "
2019-05-27 06:54:21 +02:00
" struct e<> ; "
2019-06-01 10:52:29 +02:00
" struct e<a::c<int,std::is_empty<int>{}&&std::is_final<int>{}>,a::c<int,std::is_empty<int>{}&&std::is_final<int>{}>,int> ; "
" static_assert ( sizeof ( e<> ) == sizeof ( e<a::c<int,std::is_empty<int>{}&&std::is_final<int>{}>,a::c<int,std::is_empty<int>{}&&std::is_final<int>{}>,int> ) , \" \" ) ; "
2019-05-27 06:54:21 +02:00
" struct e<> { } ; "
2019-06-01 10:52:29 +02:00
" struct e<a::c<int,std::is_empty<int>{}&&std::is_final<int>{}>,a::c<int,std::is_empty<int>{}&&std::is_final<int>{}>,int> { } ; " ;
2019-05-28 21:32:37 +02:00
ASSERT_EQUALS ( exp , tok ( code ) ) ;
2019-05-27 06:54:21 +02:00
}
{
const char code [ ] = " template <typename b, bool = __is_empty(b) && __is_final(b)> struct c; \n "
" template <typename...> struct e {}; \n "
2019-05-27 20:51:52 +02:00
" static_assert(sizeof(e<>) == sizeof(e<c<int>, c<int>, int>), \" \" ); \n " ;
const char exp [ ] = " template < typename b , bool > struct c ; "
2019-05-27 06:54:21 +02:00
" struct e<> ; "
2019-05-27 20:51:52 +02:00
" struct e<c<int,std::is_empty<int>{}&&std::is_final<int>{}>,c<int,std::is_empty<int>{}&&std::is_final<int>{}>,int> ; "
" static_assert ( sizeof ( e<> ) == sizeof ( e<c<int,std::is_empty<int>{}&&std::is_final<int>{}>,c<int,std::is_empty<int>{}&&std::is_final<int>{}>,int> ) , \" \" ) ; "
2019-05-27 06:54:21 +02:00
" struct e<> { } ; "
2019-05-27 20:51:52 +02:00
" struct e<c<int,std::is_empty<int>{}&&std::is_final<int>{}>,c<int,std::is_empty<int>{}&&std::is_final<int>{}>,int> { } ; " ;
2019-05-28 21:32:37 +02:00
ASSERT_EQUALS ( exp , tok ( code ) ) ;
2019-05-27 06:54:21 +02:00
}
{
const char code [ ] = " template <typename b, bool = __is_empty(b) && __is_final(b)> struct c{}; \n "
" c<int> cc; \n " ;
2019-05-27 20:51:52 +02:00
const char exp [ ] = " struct c<int,std::is_empty<int>{}&&std::is_final<int>{}> ; "
2019-05-28 21:32:37 +02:00
" c<int,std::is_empty<int>{}&&std::is_final<int>{}> cc ; "
2019-05-27 20:51:52 +02:00
" struct c<int,std::is_empty<int>{}&&std::is_final<int>{}> { } ; " ;
2019-05-28 21:32:37 +02:00
ASSERT_EQUALS ( exp , tok ( code ) ) ;
2019-05-27 06:54:21 +02:00
}
2019-06-01 10:52:29 +02:00
{
const char code [ ] = " template <typename b, bool = unknown1(b) && unknown2(b)> struct c{}; \n "
" c<int> cc; \n " ;
const char exp [ ] = " struct c<int,unknown1(int)&&unknown2(int)> ; "
" c<int,unknown1(int)&&unknown2(int)> cc ; "
" struct c<int,unknown1(int)&&unknown2(int)> { } ; " ;
ASSERT_EQUALS ( exp , tok ( code ) ) ;
}
}
void template110 ( ) {
const char code [ ] = " template<typename T> using A = int; \n "
" template<typename T> using A<T*> = char; \n "
" template<> using A<char> = char; \n "
" template using A<char> = char; \n "
" using A<char> = char; " ;
const char exp [ ] = " template < typename T > using A = int ; "
" template < typename T > using A < T * > = char ; "
" template < > using A < char > = char ; "
" template using A < char > = char ; "
" using A < char > = char ; " ;
ASSERT_EQUALS ( exp , tok ( code ) ) ;
}
void template111 ( ) { // crash
const char code [ ] = " template<typename T, typename U> struct pair; \n "
" template<typename T> using cell = pair<T*, cell<T>*>; " ;
const char exp [ ] = " template < typename T , typename U > struct pair ; "
" template < typename T > using cell = pair < T * , cell < T > * > ; " ;
ASSERT_EQUALS ( exp , tok ( code ) ) ;
2019-05-27 06:54:21 +02:00
}
2019-06-02 10:23:47 +02:00
void template112 ( ) { // #9146 syntax error
const char code [ ] = " template <int> struct a; \n "
" template <class, class b> using c = typename a<int{b::d}>::e; \n "
" template <class> struct f; \n "
" template <class b> using g = typename f<c<int, b>>::e; " ;
const char exp [ ] = " template < int > struct a ; "
" template < class , class b > using c = typename a < int { b :: d } > :: e ; "
" template < class > struct f ; "
" template < class b > using g = typename f < c < int , b > > :: e ; " ;
ASSERT_EQUALS ( exp , tok ( code ) ) ;
}
2019-06-08 07:27:53 +02:00
void template113 ( ) {
{
const char code [ ] = " template <class> class A { void f(); }; \n "
" A<int> a; " ;
const char exp [ ] = " class A<int> ; "
" A<int> a ; "
" class A<int> { void f ( ) ; } ; " ;
ASSERT_EQUALS ( exp , tok ( code ) ) ;
}
{
const char code [ ] = " template <struct> struct A { void f(); }; \n "
" A<int> a; " ;
const char exp [ ] = " struct A<int> ; "
" A<int> a ; "
" struct A<int> { void f ( ) ; } ; " ;
ASSERT_EQUALS ( exp , tok ( code ) ) ;
}
}
2019-06-12 07:44:48 +02:00
void template114 ( ) { // #9155
2019-06-15 09:48:22 +02:00
{
const char code [ ] = " template <typename a, a> struct b {}; \n "
" template <typename> struct c; \n "
" template <typename> struct d : b<bool, std::is_polymorphic<int>{}> {}; \n "
" template <bool> struct e; \n "
" template <typename a> using f = typename e<c<d<a>>::g>::h; " ;
const char exp [ ] = " template < typename a , a > struct b { } ; "
" template < typename > struct c ; "
" template < typename > struct d : b < bool , std :: is_polymorphic < int > { } > { } ; "
" template < bool > struct e ; "
" template < typename a > using f = typename e < c < d < a > > :: g > :: h ; " ;
ASSERT_EQUALS ( exp , tok ( code ) ) ;
}
{
const char code [ ] = " template <typename a, a> struct b; \n "
" template <bool, typename> struct c; \n "
" template <typename a> struct d : b<bool, std::is_empty<a>{}> {}; \n "
" template <typename a> using e = typename c<std::is_final<a>{}, d<a>>::f; \n " ;
const char exp [ ] = " template < typename a , a > struct b ; "
" template < bool , typename > struct c ; "
2019-06-17 21:18:27 +02:00
" template < typename a > struct d : b < bool , std :: is_empty < a > { } > { } ; "
" template < typename a > using e = typename c < std :: is_final < a > { } , d < a > > :: f ; " ;
2019-06-15 09:48:22 +02:00
ASSERT_EQUALS ( exp , tok ( code ) ) ;
}
2019-06-12 07:44:48 +02:00
}
2019-06-15 09:46:32 +02:00
void template115 ( ) { // #9153
const char code [ ] = " namespace { \n "
" namespace b { \n "
" template <int c> struct B { using B<c / 2>::d; }; \n "
" } \n "
" template <class, class> using e = typename b::B<int{}>; \n "
" namespace b { \n "
" template <class> struct f {}; \n "
" } \n "
" template <class c> using g = b::f<e<int, c>>; \n "
" } \n "
" g<int> g1; " ;
const char exp [ ] = " namespace { "
" namespace b { "
" struct B<0> ; "
" } "
" namespace b { "
" struct f<b::B<0>> ; "
" } "
" } "
" b :: f<b::B<0>> g1 ; struct b :: B<0> { using B<0> :: d ; } ; "
" struct b :: f<b::B<0>> { } ; " ;
ASSERT_EQUALS ( exp , tok ( code ) ) ;
}
2019-06-17 21:18:27 +02:00
void template116 ( ) { // #9178
2019-08-02 07:53:39 +02:00
{
const char code [ ] = " template <class, class a> auto b() -> decltype(a{}.template b<void(int, int)>); \n "
" template <class, class a> auto b() -> decltype(a{}.template b<void(int, int)>){} " ;
const char exp [ ] = " template < class , class a > auto b ( ) . decltype ( a { } . template b < void ( int , int ) > ) ; "
" template < class , class a > auto b ( ) . decltype ( a { } . template b < void ( int , int ) > ) { } " ;
ASSERT_EQUALS ( exp , tok ( code ) ) ;
}
{
const char code [ ] = " template <class, class a> \n "
" auto b() -> decltype(a{}.template b<void(int, int)>()) {} \n "
" struct c { \n "
" template <class> void b(); \n "
" }; \n "
" void d() { b<c, c>(); } " ;
const char exp [ ] = " auto b<c,c> ( ) . decltype ( c { } . template b < void ( int , int ) > ( ) ) ; "
" struct c { "
" template < class > void b ( ) ; "
" } ; "
" void d ( ) { b<c,c> ( ) ; } "
" auto b<c,c> ( ) . decltype ( c { } . template b < void ( int , int ) > ( ) ) { } " ;
ASSERT_EQUALS ( exp , tok ( code ) ) ;
}
2019-06-17 21:18:27 +02:00
}
2019-06-28 11:14:20 +02:00
void template117 ( ) {
const char code [ ] = " template<typename T = void> struct X {}; \n "
" X<X<>> x; " ;
const char exp [ ] = " struct X<void> ; "
" struct X<X<void>> ; "
" X<X<void>> x ; "
" struct X<void> { } ; "
" struct X<X<void>> { } ; " ;
ASSERT_EQUALS ( exp , tok ( code ) ) ;
}
void template118 ( ) {
const char code [ ] = " template<int> struct S { void f(int i); }; \n "
" S<1> s; " ;
const char exp [ ] = " struct S<1> ; "
" S<1> s ; struct S<1> { "
" void f ( int i ) ; "
" } ; " ;
ASSERT_EQUALS ( exp , tok ( code ) ) ;
}
void template119 ( ) { // #9186
{
const char code [ ] = " template <typename T> \n "
" constexpr auto func = [](auto x){ return T(x);}; \n "
" template <typename T> \n "
" constexpr auto funcBraced = [](auto x){ return T{x};}; \n "
" double f(int x) { return func<double>(x); } \n "
" double fBraced(int x) { return funcBraced<int>(x); } " ;
const char exp [ ] = " const auto func<double> = [ ] ( auto x ) { return double ( x ) ; } ; "
" const auto funcBraced<int> = [ ] ( auto x ) { return int { x } ; } ; "
" double f ( int x ) { return func<double> ( x ) ; } "
" double fBraced ( int x ) { return funcBraced<int> ( x ) ; } " ;
ASSERT_EQUALS ( exp , tok ( code ) ) ;
}
{
const char code [ ] = " template <typename T> \n "
" constexpr auto func = [](auto x){ return T(x);}; \n "
" void foo() { \n "
" func<int>(x); \n "
" func<double>(x); \n "
" } " ;
const char exp [ ] = " const auto func<int> = [ ] ( auto x ) { return int ( x ) ; } ; "
" const auto func<double> = [ ] ( auto x ) { return double ( x ) ; } ; "
" void foo ( ) { "
" func<int> ( x ) ; "
" func<double> ( x ) ; "
" } " ;
ASSERT_EQUALS ( exp , tok ( code ) ) ;
}
}
2019-07-01 07:01:14 +02:00
void template120 ( ) {
const char code [ ] = " template<typename Tuple> \n "
" struct lambda_context { \n "
" template<typename Sig> struct result; \n "
" template<typename This, typename I> \n "
" struct result<This(terminal, placeholder)> : at<Tuple, I> {}; \n "
" }; \n "
" template<typename T> \n "
" struct lambda { \n "
" template<typename Sig> struct result; \n "
" template<typename This> \n "
" struct result<This()> : lambda_context<tuple<> > {}; \n "
" }; \n "
" lambda<int> l; " ;
const char exp [ ] = " template < typename Tuple > "
" struct lambda_context { "
" template < typename Sig > struct result ; "
" template < typename This , typename I > "
" struct result < This ( terminal , placeholder ) > : at < Tuple , I > { } ; "
" } ; "
" struct lambda<int> ; "
" lambda<int> l ; struct lambda<int> { "
" template < typename Sig > struct result ; "
" template < typename This > "
" struct result < This ( ) > : lambda_context < tuple < > > { } ; "
" } ; " ;
ASSERT_EQUALS ( exp , tok ( code ) ) ;
}
2019-07-02 11:40:57 +02:00
void template121 ( ) { // #9193
const char code [ ] = " template <class VALUE_T, class LIST_T = std::list<VALUE_T>> \n "
" class TestList { }; \n "
" TestList<std::shared_ptr<int>> m_test; " ;
const char exp [ ] = " class TestList<std::shared_ptr<int>,std::list<std::shared_ptr<int>>> ; "
" TestList<std::shared_ptr<int>,std::list<std::shared_ptr<int>>> m_test ; "
" class TestList<std::shared_ptr<int>,std::list<std::shared_ptr<int>>> { } ; " ;
ASSERT_EQUALS ( exp , tok ( code ) ) ;
}
2019-07-03 08:35:48 +02:00
void template122 ( ) { // #9147
const char code [ ] = " template <class...> struct a; \n "
" namespace { \n "
" template <class, class> struct b; \n "
" template <template <class> class c, class... f, template <class...> class d> \n "
" struct b<c<f...>, d<>>; \n "
" } \n "
" void e() { using c = a<>; } " ;
2019-09-04 08:07:30 +02:00
const char exp [ ] = " template < class ... > struct a ; "
2019-07-03 08:35:48 +02:00
" namespace { "
" template < class , class > struct b ; "
2019-09-04 08:07:30 +02:00
" template < template < class > class c , class ... f , template < class ... > class d > "
" struct b < c < f ... > , d < > > ; "
2019-07-03 08:35:48 +02:00
" } "
" void e ( ) { } " ;
ASSERT_EQUALS ( exp , tok ( code ) ) ;
}
void template123 ( ) { // #9183
const char code [ ] = " template <class...> struct a; \n "
" namespace { \n "
" template <class, class, class, class> \n "
" struct b; \n "
" template <template <class> class c, class... d, template <class> class e, class... f> \n "
" struct b<c<d...>, e<f...>>; \n "
" } \n "
" void fn1() { \n "
" using c = a<>; \n "
" using e = a<>; \n "
" } " ;
2019-09-04 08:07:30 +02:00
const char exp [ ] = " template < class ... > struct a ; "
2019-07-03 08:35:48 +02:00
" namespace { "
" template < class , class , class , class > "
" struct b ; "
2019-09-04 08:07:30 +02:00
" template < template < class > class c , class ... d , template < class > class e , class ... f > "
" struct b < c < d ... > , e < f ... > > ; "
2019-07-03 08:35:48 +02:00
" } "
" void fn1 ( ) { "
" } " ;
ASSERT_EQUALS ( exp , tok ( code ) ) ;
}
2019-07-07 10:20:43 +02:00
void template124 ( ) { // #9197
const char code [ ] = " template <bool> struct a; \n "
" template <bool b> using c = typename a<b>::d; \n "
" template <typename> struct e; \n "
" template <typename> struct h { \n "
" template <typename... f, c<h<e<typename f::d...>>::g>> void i(); \n "
" }; " ;
const char exp [ ] = " template < bool > struct a ; "
" template < bool b > using c = typename a < b > :: d ; "
" template < typename > struct e ; "
" template < typename > struct h { "
2019-09-04 08:07:30 +02:00
" template < typename ... f , c < h < e < typename f :: d ... > > :: g > > void i ( ) ; "
2019-07-07 10:20:43 +02:00
" } ; " ;
ASSERT_EQUALS ( exp , tok ( code ) ) ;
}
2019-07-15 12:41:06 +02:00
void template125 ( ) {
ASSERT_THROW ( tok ( " template<int M, int N> \n "
" class GCD { \n "
" public: \n "
" enum { val = (N == 0) ? M : GCD<N, M % N>::val }; \n "
" }; \n "
" int main() { \n "
" GCD< 1, 0 >::val; \n "
" } " ) , InternalError ) ;
}
2019-07-23 21:28:24 +02:00
void template126 ( ) { // #9217
const char code [ ] = " template <typename b> using d = a<b>; \n "
" static_assert(i<d<l<b>>>{}, \" \" ); " ;
const char exp [ ] = " static_assert ( i < a < l < b > > > { } , \" \" ) ; " ;
ASSERT_EQUALS ( exp , tok ( code ) ) ;
}
2019-07-24 19:20:19 +02:00
void template127 ( ) { // #9225
{
const char code [ ] = " template <typename> struct a { \n "
" template <typename b> constexpr decltype(auto) operator()(b &&) const; \n "
" }; \n "
" a<int> c; \n "
" template <typename d> \n "
" template <typename b> \n "
" constexpr decltype(auto) a<d>::operator()(b &&) const {} " ;
const char exp [ ] = " struct a<int> ; "
" a<int> c ; "
" template < typename d > "
" template < typename b > "
2019-10-04 12:30:11 +02:00
" const decltype ( auto ) a < d > :: operator() ( b && ) const { } "
2019-07-24 19:20:19 +02:00
" struct a<int> { "
2019-10-04 12:30:11 +02:00
" template < typename b > const decltype ( auto ) operator() ( b && ) const ; "
2019-07-24 19:20:19 +02:00
" } ; " ;
const char act [ ] = " struct a<int> ; "
" a<int> c ; "
" template < typename d > "
" template < typename b > "
2019-10-04 12:30:11 +02:00
" const decltype ( auto ) a < d > :: operator() ( b && ) const { } "
2019-07-24 19:20:19 +02:00
" struct a<int> { "
2019-10-04 12:30:11 +02:00
" template < typename b > const decltype ( auto ) operator() ( b && ) const ; "
2019-07-24 19:20:19 +02:00
" } ; "
2019-10-04 12:30:11 +02:00
" const decltype ( auto ) a<int> :: operator() ( b && ) const { } " ;
2019-07-24 19:20:19 +02:00
TODO_ASSERT_EQUALS ( exp , act , tok ( code ) ) ;
}
{
const char code [ ] = " template <typename> struct a { \n "
" template <typename b> static void foo(); \n "
" }; \n "
" a<int> c; \n "
" template <typename d> \n "
" template <typename b> \n "
" void a<d>::foo() {} \n "
" void bar() { a<int>::foo<char>(); } " ;
const char exp [ ] = " struct a<int> ; "
" a<int> c ; "
" template < typename d > "
" template < typename b > "
" void a < d > :: foo ( ) { } "
" void bar ( ) { a<int> :: foo < char > ( ) ; } "
" struct a<int> { "
" template < typename b > static void foo ( ) ; "
" static void foo<char> ( ) ; "
" } ; "
" void a<int> :: foo<char> ( ) { } " ;
const char act [ ] = " struct a<int> ; "
" a<int> c ; "
" template < typename d > "
" template < typename b > "
" void a < d > :: foo ( ) { } "
" void bar ( ) { a<int> :: foo < char > ( ) ; } "
" struct a<int> { "
" template < typename b > static void foo ( ) ; "
" } ; "
" void a<int> :: foo ( ) { } " ;
TODO_ASSERT_EQUALS ( exp , act , tok ( code ) ) ;
}
{
const char code [ ] = " template <typename> struct a { \n "
" template <typename b> static void foo(); \n "
" }; \n "
" template <typename d> \n "
" template <typename b> \n "
" void a<d>::foo() {} \n "
" void bar() { a<int>::foo<char>(); } " ;
const char exp [ ] = " struct a<int> ; "
" template < typename d > "
" template < typename b > "
" void a < d > :: foo ( ) { } "
" void bar ( ) { a<int> :: foo < char > ( ) ; } "
" struct a<int> { "
" static void foo<char> ( ) ; "
" } ; "
" void a<int> :: foo<char> ( ) { } " ;
const char act [ ] = " struct a<int> ; "
" template < typename d > "
" template < typename b > "
" void a < d > :: foo ( ) { } "
" void bar ( ) { a<int> :: foo < char > ( ) ; } "
" struct a<int> { "
" template < typename b > static void foo ( ) ; "
" } ; "
" void a<int> :: foo ( ) { } " ;
TODO_ASSERT_EQUALS ( exp , act , tok ( code ) ) ;
}
}
2019-07-28 09:25:18 +02:00
void template128 ( ) { // #9224
const char code [ ] = " template <typename> struct a { }; \n "
" template <typename j> void h() { k.h<a<j>>; } \n "
" void foo() { h<int>(); } " ;
const char exp [ ] = " struct a<int> ; "
" void h<int> ( ) ; "
" void foo ( ) { h<int> ( ) ; } "
" void h<int> ( ) { k . h < a<int> > ; } "
" struct a<int> { } ; " ;
ASSERT_EQUALS ( exp , tok ( code ) ) ;
}
2019-07-31 09:18:43 +02:00
void template129 ( ) {
const char code [ ] = " class LuaContext { \n "
" public: \n "
" template <typename TFunctionType, typename TType> \n "
" void registerFunction(TType fn) { } \n "
" }; \n "
" void setupLuaBindingsDNSQuestion() { \n "
" g_lua.registerFunction<void (DNSQuestion ::*)(std ::string, std ::string)>(); \n "
" } " ;
const char exp [ ] = " class LuaContext { "
" public: "
" template < typename TFunctionType , typename TType > "
" void registerFunction ( TType fn ) { } "
" } ; "
" void setupLuaBindingsDNSQuestion ( ) { "
" g_lua . registerFunction < void ( DNSQuestion :: * ) ( std :: string , std :: string ) > ( ) ; "
" } " ;
ASSERT_EQUALS ( exp , tok ( code ) ) ;
}
2019-08-03 08:15:06 +02:00
void template130 ( ) { // #9246
const char code [ ] = " template <typename...> using a = int; \n "
" template <typename, typename> using b = a<>; \n "
" template <typename, typename> void c(); \n "
" template <typename d, typename> void e() { c<b<d, int>, int>; } \n "
" void f() { e<int(int, ...), int>(); } " ;
const char exp [ ] = " template < typename , typename > void c ( ) ; "
" void e<int(int,...),int> ( ) ; "
" void f ( ) { e<int(int,...),int> ( ) ; } "
" void e<int(int,...),int> ( ) { c < int , int > ; } " ;
ASSERT_EQUALS ( exp , tok ( code ) ) ;
}
2019-08-04 10:24:44 +02:00
void template131 ( ) { // #9249
{
const char code [ ] = " template <long a, bool = 0 == a> struct b {}; \n "
" b<1> b1; " ;
const char exp [ ] = " struct b<1,false> ; "
" b<1,false> b1 ; "
" struct b<1,false> { } ; " ;
ASSERT_EQUALS ( exp , tok ( code ) ) ;
}
{
const char code [ ] = " template <long a, bool = a < 0> struct b {}; \n "
" b<1> b1; " ;
const char exp [ ] = " struct b<1,false> ; "
" b<1,false> b1 ; "
" struct b<1,false> { } ; " ;
ASSERT_EQUALS ( exp , tok ( code ) ) ;
}
{
const char code [ ] = " template <long a, bool = 0 < a> struct b {}; \n "
" b<1> b1; " ;
const char exp [ ] = " struct b<1,true> ; "
" b<1,true> b1 ; "
" struct b<1,true> { } ; " ;
ASSERT_EQUALS ( exp , tok ( code ) ) ;
}
}
2019-08-07 08:05:02 +02:00
void template132 ( ) { // #9250
const char code [ ] = " struct TrueFalse { \n "
" static constexpr bool v() { return true; } \n "
" }; \n "
" int global; \n "
" template<typename T> int foo() { \n "
" __transaction_atomic noexcept(T::v()) { global += 1; } \n "
" return __transaction_atomic noexcept(T::v()) (global + 2); \n "
" } \n "
" int f1() { \n "
" return foo<TrueFalse>(); \n "
" } " ;
const char exp [ ] = " struct TrueFalse { "
" static const bool v ( ) { return true ; } "
" } ; "
" int global ; "
" int foo<TrueFalse> ( ) ; "
" int f1 ( ) { "
" return foo<TrueFalse> ( ) ; "
" } "
" int foo<TrueFalse> ( ) { "
" __transaction_atomic noexcept ( TrueFalse :: v ( ) ) { global += 1 ; } "
" return __transaction_atomic noexcept ( TrueFalse :: v ( ) ) ( global + 2 ) ; "
" } " ;
ASSERT_EQUALS ( exp , tok ( code ) ) ;
}
2019-08-17 07:38:07 +02:00
void template133 ( ) {
const char code [ ] = " template <typename a> struct bar { \n "
" template <typename b> static bar foo(const bar<b> &c) { \n "
" return bar(); \n "
" } \n "
" }; \n "
" bar<short> bs; \n "
" bar<std::array<int,4>> ba; \n "
" bar<short> b1 = bar<short>::foo<std::array<int,4>>(ba); \n "
" bar<std::array<int,4>> b2 = bar<std::array<int,4>>::foo<short>(bs); " ;
const char act [ ] = " struct bar<short> ; struct bar<std::array<int,4>> ; "
" bar<short> bs ; "
" bar<std::array<int,4>> ba ; "
" bar<short> b1 ; b1 = bar<short> :: foo<std::array<int,4>> ( ba ) ; "
" bar<std::array<int,4>> b2 ; b2 = bar<std::array<int,4>> :: foo<short> ( bs ) ; "
" struct bar<short> { "
" static bar<short> foo<std::array<int,4>> ( const bar < std :: array < int , 4 > > & c ) ; "
" } ; "
" struct bar<std::array<int,4>> { "
" static bar<std::array<int,4>> foo<short> ( const bar < short > & c ) ; "
" } ; "
" bar<std::array<int,4>> bar<std::array<int,4>> :: foo<short> ( const bar < short > & c ) { "
" return bar<std::array<int,4>> ( ) ; "
" } "
" bar<short> bar<short> :: foo<std::array<int,4>> ( const bar < std :: array < int , 4 > > & c ) { "
" return bar<short> ( ) ; "
" } " ;
const char exp [ ] = " struct bar<short> ; struct bar<std::array<int,4>> ; "
" bar<short> bs ; "
" bar<std::array<int,4>> ba ; "
" bar<short> b1 ; b1 = bar<short> :: foo<std::array<int,4>> ( ba ) ; "
" bar<std::array<int,4>> b2 ; b2 = bar<std::array<int,4>> :: foo<short> ( bs ) ; "
" struct bar<short> { "
" static bar<short> foo<std::array<int,4>> ( const bar<std::array<int,4>> & c ) ; "
" } ; "
" struct bar<std::array<int,4>> { "
" static bar<std::array<int,4>> foo<short> ( const bar<short> & c ) ; "
" } ; "
" bar<std::array<int,4>> bar<std::array<int,4>> :: foo<short> ( const bar<short> & c ) { "
" return bar<std::array<int,4>> ( ) ; "
" } "
" bar<short> bar<short> :: foo<std::array<int,4>> ( const bar<std::array<int,4>> & c ) { "
" return bar<short> ( ) ; "
" } " ;
TODO_ASSERT_EQUALS ( exp , act , tok ( code ) ) ;
}
void template134 ( ) {
const char code [ ] = " template <int a> class e { }; \n "
" template <int a> class b { e<(c > a ? 1 : 0)> d; }; \n "
" b<0> b0; \n "
" b<1> b1; " ;
const char exp [ ] = " class e<(c>0)> ; class e<(c>1)> ; "
" class b<0> ; class b<1> ; "
" b<0> b0 ; "
" b<1> b1 ; "
" class b<0> { e<(c>0)> d ; } ; class b<1> { e<(c>1)> d ; } ; "
" class e<(c>0)> { } ; class e<(c>1)> { } ; " ;
ASSERT_EQUALS ( exp , tok ( code ) ) ;
}
void template135 ( ) {
const char code [ ] = " template <int> struct a { template <int b> void c(a<b>); }; \n "
" a<2> d; " ;
const char exp [ ] = " struct a<2> ; "
" a<2> d ; "
" struct a<2> { template < int b > void c ( a < b > ) ; } ; " ;
ASSERT_EQUALS ( exp , tok ( code ) ) ;
}
2019-08-20 20:25:18 +02:00
void template136 ( ) { // #9287
const char code [ ] = " namespace a { \n "
" template <typename> struct b; \n "
" template <int> struct c; \n "
" template <typename> struct d; \n "
" template <typename> struct f; \n "
" template <typename> struct g; \n "
" template <typename h> \n "
" struct i : c<b<f<typename h ::j>>::k && b<g<typename h ::j>>::k> {}; \n "
" } \n "
" namespace hana = a; \n "
" using e = int; \n "
" void l(hana::d<hana::i<e>>); " ;
const char exp [ ] = " namespace a { "
" template < typename > struct b ; "
" template < int > struct c ; "
" template < typename > struct d ; "
" template < typename > struct f ; "
" template < typename > struct g ; "
" struct i<int> ; "
" } "
" void l ( a :: d < a :: i<int> > ) ; "
" struct a :: i<int> : c < b < f < int :: j > > :: k && b < g < int :: j > > :: k > { } ; " ;
ASSERT_EQUALS ( exp , tok ( code ) ) ;
}
void template137 ( ) { // #9288
const char code [ ] = " template <bool> struct a; \n "
" template <bool b, class> using c = typename a<b>::d; \n "
" template <class, template <class> class, class> struct e; \n "
" template <class f, class g, class... h> \n "
" using i = typename e<f, g::template fn, h...>::d; \n "
" template <class... j> struct k : c<sizeof...(j), int>::template fn<j...> {}; " ;
const char exp [ ] = " template < bool > struct a ; "
" template < bool b , class > using c = typename a < b > :: d ; "
" template < class , template < class > class , class > struct e ; "
2019-09-04 08:07:30 +02:00
" template < class f , class g , class ... h > "
" using i = typename e < f , g :: template fn , h ... > :: d ; "
2019-09-09 21:46:21 +02:00
" template < class ... j > struct k : c < sizeof... ( j ) , int > :: template fn < j ... > { } ; " ;
2019-08-20 20:25:18 +02:00
ASSERT_EQUALS ( exp , tok ( code ) ) ;
}
2019-08-27 06:37:58 +02:00
void template138 ( ) {
{
const char code [ ] = " struct inferior { \n "
" using visitor = int; \n "
" template <typename T> \n "
" bool operator()(const T &a, const T &b) const { \n "
" return 1 < b; \n "
" } \n "
" }; \n "
" int main() { \n "
" return 0; \n "
" } " ;
const char exp [ ] = " struct inferior { "
" template < typename T > "
" bool operator() ( const T & a , const T & b ) const { "
" return 1 < b ; "
" } "
" } ; "
" int main ( ) { "
" return 0 ; "
" } " ;
ASSERT_EQUALS ( exp , tok ( code ) ) ;
}
{
const char code [ ] = " struct inferior { \n "
" template <typename T> \n "
" bool operator()(const T &a, const T &b) const { \n "
" return 1 < b; \n "
" } \n "
" }; \n "
" int main() { \n "
" return 0; \n "
" } " ;
const char exp [ ] = " struct inferior { "
" template < typename T > "
" bool operator() ( const T & a , const T & b ) const { "
" return 1 < b ; "
" } "
" } ; "
" int main ( ) { "
" return 0 ; "
" } " ;
ASSERT_EQUALS ( exp , tok ( code ) ) ;
}
{
const char code [ ] = " struct inferior { \n "
" using visitor = int; \n "
" template <typename T> \n "
" bool operator()(const T &a, const T &b) const { \n "
" return a < b; \n "
" } \n "
" }; \n "
" int main() { \n "
" return 0; \n "
" } " ;
const char exp [ ] = " struct inferior { "
" template < typename T > "
" bool operator() ( const T & a , const T & b ) const { "
" return a < b ; "
" } "
" } ; "
" int main ( ) { "
" return 0 ; "
" } " ;
ASSERT_EQUALS ( exp , tok ( code ) ) ;
}
{
const char code [ ] = " struct inferior { \n "
" template <typename T> \n "
" bool operator()(const T &a, const T &b) const { \n "
" return a < b; \n "
" } \n "
" }; \n "
" int main() { \n "
" return 0; \n "
" } " ;
const char exp [ ] = " struct inferior { "
" template < typename T > "
" bool operator() ( const T & a , const T & b ) const { "
" return a < b ; "
" } "
" } ; "
" int main ( ) { "
" return 0 ; "
" } " ;
ASSERT_EQUALS ( exp , tok ( code ) ) ;
}
}
2019-09-01 09:56:33 +02:00
void template139 ( ) {
{
const char code [ ] = " template<typename T> \n "
" struct Foo { \n "
" template<typename> friend struct Foo; \n "
" }; " ;
const char exp [ ] = " template < typename T > "
" struct Foo { "
" template < typename > friend struct Foo ; "
" } ; " ;
ASSERT_EQUALS ( exp , tok ( code ) ) ;
}
{
const char code [ ] = " template<typename T> \n "
" struct Foo { \n "
" template<typename> friend struct Foo; \n "
" } ; \n "
" Foo<int> foo; " ;
const char exp [ ] = " struct Foo<int> ; "
" Foo<int> foo ; "
" struct Foo<int> { "
" template < typename > friend struct Foo ; "
" } ; " ;
ASSERT_EQUALS ( exp , tok ( code ) ) ;
}
}
2019-09-02 06:51:19 +02:00
void template140 ( ) {
{
const char code [ ] = " template <typename> struct a { }; \n "
" template <typename b> struct d { \n "
" d(); \n "
" d(d<a<b>> e); \n "
" }; \n "
" void foo() { d<char> c; } " ;
const char exp [ ] = " struct a<char> ; "
" struct d<char> ; "
" void foo ( ) { d<char> c ; } "
" struct d<char> { "
" d<char> ( ) ; "
" d<char> ( d < a<char> > e ) ; "
" } ; "
" struct a<char> { } ; " ;
ASSERT_EQUALS ( exp , tok ( code ) ) ;
}
{
const char code [ ] = " namespace a { \n "
" template <typename b> using c = typename b ::d; \n "
" template <typename> constexpr bool e() { return false; } \n "
" template <typename b> class f { f(f<c<b>>); }; \n "
" static_assert(!e<f<char>>()); \n "
" } " ;
const char exp [ ] = " namespace a { "
" const bool e<f<char>> ( ) ; "
" class f<char> ; "
" static_assert ( ! e<f<char>> ( ) ) ; } "
" class a :: f<char> { f<char> ( a :: f < b :: d > ) ; } ; "
" const bool a :: e<f<char>> ( ) { return false ; } " ;
ASSERT_EQUALS ( exp , tok ( code ) ) ;
}
}
2019-09-07 09:09:04 +02:00
void template141 ( ) { // #9337
const char code [ ] = " struct a { \n "
" int c; \n "
" template <typename b> void d(b e) const { c < *e; } \n "
" }; " ;
const char exp [ ] = " struct a { "
" int c ; "
" template < typename b > void d ( b e ) const { c < * e ; } "
" } ; " ;
ASSERT_EQUALS ( exp , tok ( code ) ) ;
}
2019-09-09 21:46:21 +02:00
void template142 ( ) { // #9338
const char code [ ] = " template <typename...> struct a; \n "
" template <typename b, typename c, typename... d> struct a<b c::*, d...> { \n "
" using typename b ::e; \n "
" static_assert(e::f ? sizeof...(d) : sizeof...(d), \" \" ); \n "
" }; " ;
const char exp [ ] = " template < typename ... > struct a ; "
" template < typename b , typename c , typename ... d > struct a < b c :: * , d ... > { "
" using b :: e ; "
" static_assert ( e :: f ? sizeof... ( d ) : sizeof... ( d ) , \" \" ) ; "
" } ; " ;
ASSERT_EQUALS ( exp , tok ( code ) ) ;
}
2019-09-11 19:31:15 +02:00
void template143 ( ) {
const char code [ ] = " template<int N> \n "
" using A1 = struct B1 { static auto constexpr value = N; }; \n "
" A1<0> a1; \n "
" template<class T> \n "
" using A2 = struct B2 { void f(T){} }; \n "
" A2<bool> a2; \n "
" template<class T> \n "
" using A3 = enum B3 {b = 0;}; \n "
" A3<int> a3; " ;
const char exp [ ] = " template < int N > "
" using A1 = struct B1 { static const auto value = N ; } ; "
" A1 < 0 > a1 ; "
" template < class T > "
" using A2 = struct B2 { void f ( T ) { } } ; "
" A2 < bool > a2 ; "
" template < class T > "
" using A3 = enum B3 { b = 0 ; } ; "
" A3 < int > a3 ; " ;
ASSERT_EQUALS ( exp , tok ( code ) ) ;
}
2019-09-20 12:35:01 +02:00
void template144 ( ) { // #9046
const char code [ ] = " namespace a { \n "
" template <typename T, typename enable = void> \n "
" struct promote { \n "
" using type = T; \n "
" }; \n "
" template <typename T> \n "
" struct promote <T, typename std::enable_if< std::is_integral<T>::value && sizeof(T) < sizeof(int) >::type>{ \n "
" }; \n "
" } " ;
const char exp [ ] = " namespace a { "
" template < typename T , typename enable = void > "
" struct promote { "
" using type = T ; "
" } ; "
" template < typename T > "
" struct promote < T , std :: enable_if < std :: is_integral < T > :: value && sizeof ( T ) < sizeof ( int ) > :: type > { "
" } ; "
" } " ;
ASSERT_EQUALS ( exp , tok ( code ) ) ;
}
void template145 ( ) { // syntax error
const char code [ ] = " template<template<typename, Ts = 0> class ...Cs, Cs<Ts> ...Vs> struct B { }; " ;
const char exp [ ] = " template < template < typename , Ts = 0 > class ... Cs , Cs < Ts > ... Vs > struct B { } ; " ;
ASSERT_EQUALS ( exp , tok ( code ) ) ;
}
void template146 ( ) { // syntax error
const char code [ ] = " template<class T> struct C { }; \n "
" template<class T, template<class TT_T0, template<class TT_T1> class TT_TT> class TT, class U = TT<int, C> > \n "
" struct S { \n "
" void foo(TT<T, C>); \n "
" }; " ;
const char exp [ ] = " template < class T > struct C { } ; "
" template < class T , template < class TT_T0 , template < class TT_T1 > class TT_TT > class TT , class U = TT < int , C > > "
" struct S { "
" void foo ( TT < T , C > ) ; "
" } ; " ;
ASSERT_EQUALS ( exp , tok ( code ) ) ;
}
void template147 ( ) { // syntax error
const char code [ ] = " template <template <typename> class C, typename X, C<X>*> struct b { }; " ;
const char exp [ ] = " template < template < typename > class C , typename X , C < X > * > struct b { } ; " ;
ASSERT_EQUALS ( exp , tok ( code ) ) ;
}
2019-09-26 10:31:19 +02:00
void template148 ( ) { // syntax error
const char code [ ] = " static_assert(var<S1<11, 100>> == var<S1<199, 23>> / 2 \n "
" && var<S1<50, 120>> == var<S1<150, var<S1<10, 10>>>> \n "
" && var<S1<53, 23>> != 222, \" \" ); " ;
const char exp [ ] = " static_assert ( var < S1 < 11 , 100 > > == var < S1 < 199 , 23 > > / 2 "
" && var < S1 < 50 , 120 > > == var < S1 < 150 , var < S1 < 10 , 10 > > > > "
" && var < S1 < 53 , 23 > > != 222 , \" \" ) ; " ;
ASSERT_EQUALS ( exp , tok ( code ) ) ;
}
2019-09-26 16:01:01 +02:00
void template149 ( ) { // unknown macro
const char code [ ] = " BEGIN_VERSIONED_NAMESPACE_DECL \n "
" template<typename T> class Fred { }; \n "
" END_VERSIONED_NAMESPACE_DECL " ;
ASSERT_THROW_EQUALS ( tok ( code ) , InternalError , " There is an unknown macro here somewhere. Configuration is required. If BEGIN_VERSIONED_NAMESPACE_DECL is a macro then please configure it. " ) ;
}
2019-10-03 12:26:45 +02:00
void template150 ( ) { // syntax error
const char code [ ] = " struct Test { \n "
" template <typename T> \n "
" T &operator[] (T) {} \n "
" }; \n "
" void foo() { \n "
" Test test; \n "
" const string type = test.operator[]<string>( \" type \" ); \n "
" } " ;
const char exp [ ] = " struct Test { "
" string & operator[]<string> ( string ) ; "
" } ; "
" void foo ( ) { "
" Test test ; "
" const string type = test . operator[]<string> ( \" type \" ) ; "
" } string & Test :: operator[]<string> ( string ) { } " ;
ASSERT_EQUALS ( exp , tok ( code ) ) ;
}
2019-10-30 12:12:47 +01:00
void template151 ( ) { // crash
{
const char code [ ] = " class SimulationComponentGroupGenerator { \n "
" std::list<int, std::allocator<int>> build() const; \n "
" }; \n "
" template < \n "
" class obj_type, \n "
" template<class> class allocator = std::allocator, \n "
" template<class, class> class data_container = std::list> \n "
" class GenericConfigurationHandler { \n "
" data_container<int, std::allocator<int>> m_target_configurations; \n "
" }; \n "
" class TargetConfigurationHandler : public GenericConfigurationHandler<int> { }; " ;
const char exp [ ] = " class SimulationComponentGroupGenerator { "
" std :: list < int , std :: allocator < int > > build ( ) const ; "
" } ; "
" class GenericConfigurationHandler<int,std::allocator,std::list> ; "
" class TargetConfigurationHandler : public GenericConfigurationHandler<int,std::allocator,std::list> { } ; "
" class GenericConfigurationHandler<int,std::allocator,std::list> { "
" std :: list < int , std :: std :: allocator < int > > m_target_configurations ; "
" } ; " ;
ASSERT_EQUALS ( exp , tok ( code ) ) ;
}
{
const char code [ ] = " std::list<std::allocator<int>> a; \n "
" template <class, template <class> class allocator = std::allocator> class b {}; \n "
" class c : b<int> {}; " ;
const char exp [ ] = " std :: list < std :: allocator < int > > a ; "
" class b<int,std::allocator> ; "
" class c : b<int,std::allocator> { } ; "
" class b<int,std::allocator> { } ; " ;
ASSERT_EQUALS ( exp , tok ( code ) ) ;
}
{
const char code [ ] = " template <typename> class a {}; \n "
" template class a<char>; \n "
" template <class, template <class> class a = a> class b {}; \n "
" class c : b<int> {}; " ;
const char exp [ ] = " class a<char> ; "
" class b<int,a> ; "
" class c : b<int,a> { } ; "
" class b<int,a> { } ; "
" class a<char> { } ; " ;
ASSERT_EQUALS ( exp , tok ( code ) ) ;
}
}
2019-11-13 21:34:27 +01:00
void template152 ( ) { // #9467
const char code [ ] = " class Foo { \n "
" template <unsigned int i> \n "
" bool bar() { \n "
" return true; \n "
" } \n "
" }; \n "
" template <> \n "
" bool Foo::bar<9>() { \n "
" return true; \n "
" } \n "
" int global() { \n "
" int bar = 1; \n "
" return bar; \n "
" } " ;
const char exp [ ] = " class Foo { "
" bool bar<9> ( ) ; "
" template < unsigned int i > "
" bool bar ( ) { "
" return true ; "
" } "
" } ; "
" bool Foo :: bar<9> ( ) { "
" return true ; "
" } "
" int global ( ) { "
" int bar ; bar = 1 ; "
" return bar ; "
" } " ;
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 } ; } ; "
2019-05-16 21:11:04 +02:00
" template < class T > struct type_equal < T , T > { enum Anonymous1 { value = 1 } ; } ; " ;
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 " ;
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 " ;
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> "
2019-02-27 07:06:34 +01:00
" { int ar [ 3 + 2 ] ; } ; " ;
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 " ;
2019-06-01 10:52:29 +02:00
const char expected [ ] = " class A<int,(int)2> ; "
" class A<int,3> ; "
" void f ( ) "
" { "
" A<int,(int)2> a1 ; "
" A<int,3> a2 ; "
" } "
" class A<int,(int)2> "
" { int ar [ ( int ) 2 ] ; } ; "
" class A<int,3> "
" { int ar [ 3 ] ; } ; " ;
ASSERT_EQUALS ( expected , tok ( code ) ) ;
2014-09-24 13:23:44 +02:00
}
{
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 { } ; "
2019-05-28 21:32:37 +02:00
" class thv_table_c<void*,void*,DefaultMemory<void*,void*>> ; "
" thv_table_c<void*,void*,DefaultMemory<void*,void*>> id_table_m ; "
" class thv_table_c<void*,void*,DefaultMemory<void*,void*>> { } ; " ;
ASSERT_EQUALS ( exp , tok ( code ) ) ;
2017-01-08 09:38:29 +01:00
}
2019-05-19 19:19:57 +02:00
{
// #8890
const char code [ ] = " template <typename = void> struct a { \n "
" void c(); \n "
" }; \n "
" void f() { \n "
" a<> b; \n "
" b.a<>::c(); \n "
" } " ;
ASSERT_EQUALS ( " struct a<void> ; "
" void f ( ) { "
" a<void> b ; "
" b . a<void> :: c ( ) ; "
" } "
" struct a<void> { "
" void c ( ) ; "
" } ; " , tok ( code ) ) ;
}
{
// #8890
const char code [ ] = " template< typename T0 = void > class A; \n "
" template<> \n "
" class A< void > { \n "
" public: \n "
" A() { } \n "
" ~A() { } \n "
" void Print() { std::cout << \" A \" << std::endl; } \n "
" }; \n "
" class B : public A<> { \n "
" public: \n "
" B() { } \n "
" ~B() { } \n "
" }; \n "
" int main( int argc, char* argv[] ) { \n "
" B b; \n "
" b.A<>::Print(); \n "
" return 0; \n "
" } " ;
2019-06-09 08:11:59 +02:00
ASSERT_EQUALS ( " class A<void> ; "
" template < typename T0 > class A ; "
2019-05-19 19:19:57 +02:00
" class A<void> { "
" public: "
" A<void> ( ) { } "
" ~ A<void> ( ) { } "
" void Print ( ) { std :: cout << \" A \" << std :: endl ; } "
" } ; "
" class B : public A<void> { "
" public: "
" B ( ) { } "
" ~ B ( ) { } "
" } ; "
" int main ( int argc , char * argv [ ] ) { "
" B b ; "
" b . A<void> :: Print ( ) ; "
" return 0 ; "
" } " , 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
}
2019-02-09 08:34:59 +01:00
{
const char code [ ] = " template<typename Lhs, int TriangularPart = (int(Lhs::Flags) & LowerTriangularBit)> \n "
" struct ei_solve_triangular_selector; \n "
" template<typename Lhs, int UpLo> \n "
" struct ei_solve_triangular_selector<Lhs,UpLo> { \n "
" }; \n "
" template<typename Lhs, int TriangularPart> \n "
" struct ei_solve_triangular_selector { }; " ;
const char exp [ ] = " template < typename Lhs , int TriangularPart = ( int ( Lhs :: Flags ) & LowerTriangularBit ) > "
" struct ei_solve_triangular_selector ; "
" template < typename Lhs , int UpLo > "
" struct ei_solve_triangular_selector < Lhs , UpLo > { "
" } ; "
" template < typename Lhs , int TriangularPart = ( int ( Lhs :: Flags ) & LowerTriangularBit ) > "
" struct ei_solve_triangular_selector { } ; " ;
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 "
" } " ;
2019-05-16 21:11:04 +02:00
ASSERT_EQUALS ( " class Fred { } " , tok ( code ) ) ;
2014-09-24 13:23:44 +02:00
// #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> { "
2019-02-27 07:06:34 +01:00
" char dummy [ sizeof ( int ) ] ; "
2018-10-26 14:20:13 +02:00
" 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 { "
2019-06-09 08:11:59 +02:00
" struct Barney<1> ; "
2018-11-05 19:55:21 +01:00
" 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 ) ;
2019-06-28 11:14:20 +02:00
tokenizer . createTokens ( istr , " test.cpp " ) ;
tokenizer . createLinks ( ) ;
tokenizer . mTemplateSimplifier - > fixAngleBrackets ( ) ;
2014-09-24 13:23:44 +02:00
2019-06-28 11:14:20 +02:00
for ( const Token * tok1 = tokenizer . tokens ( ) ; tok1 ; tok1 = tok1 - > next ( ) ) {
if ( tok1 - > str ( ) = = " var1 " )
( const_cast < Token * > ( tok1 ) ) - > varId ( 1 ) ;
2019-03-31 16:29:28 +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; " ) ) ;
2019-06-28 11:14:20 +02:00
ASSERT_EQUALS ( 1U , templateParameters ( " X<int...> x; " ) ) ;
ASSERT_EQUALS ( 2U , templateParameters ( " X<class, typename...> x; " ) ) ;
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; " ) ) ;
2019-03-31 16:29:28 +02:00
ASSERT_EQUALS ( 0U , templateParameters ( " var1<1> x; " ) ) ;
ASSERT_EQUALS ( 0U , templateParameters ( " X<1>2; " ) ) ;
2019-06-28 11:14:20 +02:00
ASSERT_EQUALS ( 2U , templateParameters ( " template<typename...B,typename=SameSize<B...>> x; " ) ) ;
ASSERT_EQUALS ( 2U , templateParameters ( " template<typename...B,typename=SameSize<B...> > x; " ) ) ;
ASSERT_EQUALS ( 1U , templateParameters ( " template<template<typename>...Foo> x; " ) ) ;
ASSERT_EQUALS ( 1U , templateParameters ( " template<template<typename>> x; " ) ) ;
ASSERT_EQUALS ( 1U , templateParameters ( " template<template<template<typename>>> x; " ) ) ;
ASSERT_EQUALS ( 1U , templateParameters ( " template<template<template<template<typename>>>> x; " ) ) ;
ASSERT_EQUALS ( 1U , templateParameters ( " template<template<template<template<template<typename>>>>> x; " ) ) ;
ASSERT_EQUALS ( 2U , templateParameters ( " template<template<typename>,int> x; " ) ) ;
ASSERT_EQUALS ( 2U , templateParameters ( " template<template<template<typename>>,int> x; " ) ) ;
ASSERT_EQUALS ( 2U , templateParameters ( " template<template<template<template<typename>>>,int> x; " ) ) ;
ASSERT_EQUALS ( 2U , templateParameters ( " template<template<template<template<template<typename>>>>,int> x; " ) ) ;
ASSERT_EQUALS ( 2U , templateParameters ( " template<template<typename>...Foo,template<template<template<typename>>>> x; " ) ) ;
ASSERT_EQUALS ( 3U , templateParameters ( " template<template<typename>...Foo,int,template<template<template<typename>>>> x; " ) ) ;
ASSERT_EQUALS ( 4U , templateParameters ( " template<template<typename>...Foo,int,template<template<template<typename>>>,int> 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 ) ;
2019-06-28 11:14:20 +02:00
tokenizer . createTokens ( istr , " test.cpp " ) ;
tokenizer . createLinks ( ) ;
tokenizer . mTemplateSimplifier - > fixAngleBrackets ( ) ;
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
2019-07-07 18:33:33 +02:00
// Helper function to unit test TemplateSimplifier::findTemplateDeclarationEnd
bool findTemplateDeclarationEndHelper ( const char code [ ] , const char pattern [ ] , unsigned offset = 0 ) {
Tokenizer tokenizer ( & settings , this ) ;
std : : istringstream istr ( code ) ;
tokenizer . createTokens ( istr , " test.cpp " ) ;
tokenizer . createLinks ( ) ;
tokenizer . mTemplateSimplifier - > fixAngleBrackets ( ) ;
const Token * _tok = tokenizer . tokens ( ) ;
for ( unsigned i = 0 ; i < offset ; + + i )
_tok = _tok - > next ( ) ;
2019-09-20 21:54:30 +02:00
const Token * tok1 = TemplateSimplifier : : findTemplateDeclarationEnd ( _tok ) ;
2019-07-07 18:33:33 +02:00
return ( tok1 = = Token : : findsimplematch ( tokenizer . list . front ( ) , pattern ) ) ;
}
void findTemplateDeclarationEnd ( ) {
ASSERT ( findTemplateDeclarationEndHelper ( " template <typename T> class Fred { }; int x; " , " ; int x ; " ) ) ;
ASSERT ( findTemplateDeclarationEndHelper ( " template <typename T> void Fred() { } int x; " , " } int x ; " ) ) ;
ASSERT ( findTemplateDeclarationEndHelper ( " template <typename T> int Fred = 0; int x; " , " ; int x ; " ) ) ;
ASSERT ( findTemplateDeclarationEndHelper ( " template <typename T> constexpr auto func = [](auto x){ return T(x);}; int x; " , " ; int x ; " ) ) ;
ASSERT ( findTemplateDeclarationEndHelper ( " template <class, class a> auto b() -> decltype(a{}.template b<void(int, int)>); int x; " , " ; int x ; " ) ) ;
ASSERT ( findTemplateDeclarationEndHelper ( " template <class, class a> auto b() -> decltype(a{}.template b<void(int, int)>){} int x; " , " } int x ; " ) ) ;
ASSERT ( findTemplateDeclarationEndHelper ( " template <typename... f, c<h<e<typename f::d...>>::g>> void i(); int x; " , " ; int x ; " ) ) ;
ASSERT ( findTemplateDeclarationEndHelper ( " template <typename... f, c<h<e<typename f::d...>>::g>> void i(){} int x; " , " } int x ; " ) ) ;
}
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 { "
2019-02-27 07:06:34 +01:00
" explicit OutputU16<unsignedchar> ( std :: basic_ostream < unsigned char > & t ) : outputStream_ ( t ) { } "
" void operator() ( unsigned short ) const ; "
2018-10-14 16:57:07 +02:00
" private: "
2019-02-27 07:06:34 +01:00
" std :: basic_ostream < unsigned char > & outputStream_ ; "
2018-10-14 16:57:07 +02:00
" } ; " ;
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 " ;
2019-06-09 08:11:59 +02:00
const char expected [ ] = " class C<char> ; "
" template < typename T > class C { } ; "
2018-10-15 19:35:26 +02:00
" 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; " ;
2019-06-09 08:11:59 +02:00
const char expected [ ] = " class C<char> ; "
" class C<int> ; "
2018-11-07 21:25:42 +01:00
" 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; " ;
2019-06-09 08:11:59 +02:00
const char expected [ ] = " class C<char> ; "
" class C<int> ; "
2018-11-07 21:25:42 +01:00
" 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 ) ) ;
}
2019-03-30 06:53:17 +01:00
void templateAlias4 ( ) { // #9070
const char code [ ] = " template <class T> \n "
" using IntrusivePtr = boost::intrusive_ptr<T>; \n "
" template <class T> class Vertex { }; \n "
" IntrusivePtr<Vertex<int>> p; " ;
2019-06-01 10:52:29 +02:00
const char expected [ ] = " class Vertex<int> ; "
2019-05-06 19:06:46 +02:00
" boost :: intrusive_ptr < Vertex<int> > p ; "
2019-03-30 06:53:17 +01:00
" class Vertex<int> { } ; " ;
2019-05-06 19:06:46 +02:00
ASSERT_EQUALS ( expected , tok ( code ) ) ;
2019-03-30 06:53:17 +01:00
}
2019-06-12 07:44:48 +02:00
void templateAlias5 ( ) {
const char code [ ] = " template<typename T> using A = int; \n "
" template<typename T> using B = T; \n "
" A<char> a; \n "
" B<char> b; " ;
const char expected [ ] = " int a ; "
" char b ; " ;
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 "
2019-04-04 06:07:49 +02:00
" void f(); \n "
2018-05-30 17:09:31 +02:00
" void g(); \n "
" };n " ) ) ;
2018-05-31 07:02:08 +02:00
}
2019-02-14 11:48:59 +01:00
void templateTypeDeduction1 ( ) { // #8962
const char code [ ] = " template<typename T> \n "
" void f(T n) { (void)n; } \n "
" static void func() { \n "
" f(0); \n "
" f(0u); \n "
" f(0U); \n "
" f(0l); \n "
" f(0L); \n "
" f(0ul); \n "
" f(0UL); \n "
" f(0ll); \n "
" f(0LL); \n "
" f(0ull); \n "
" f(0ULL); \n "
" f(0.0); \n "
" f(0.0f); \n "
" f(0.0F); \n "
" f(0.0l); \n "
" f(0.0L); \n "
" f('c'); \n "
" f(L'c'); \n "
" f( \" string \" ); \n "
" f(L \" string \" ); \n "
" f(true); \n "
" f(false); \n "
" } " ;
const char expected [ ] = " void f<int> ( int n ) ; "
" void f<unsignedint> ( unsigned int n ) ; "
" void f<long> ( long n ) ; "
" void f<unsignedlong> ( unsigned long n ) ; "
" void f<longlong> ( long long n ) ; "
" void f<unsignedlonglong> ( unsigned long long n ) ; "
" void f<double> ( double n ) ; "
" void f<float> ( float n ) ; "
" void f<longdouble> ( long double n ) ; "
" void f<char> ( char n ) ; "
" void f<wchar_t> ( wchar_t n ) ; "
" void f<constchar*> ( const char * n ) ; "
" void f<constwchar_t*> ( const wchar_t * n ) ; "
" void f<bool> ( bool n ) ; "
" static void func ( ) { "
" f<int> ( 0 ) ; "
" f<unsignedint> ( 0u ) ; "
" f<unsignedint> ( 0U ) ; "
" f<long> ( 0l ) ; "
" f<long> ( 0L ) ; "
" f<unsignedlong> ( 0ul ) ; "
" f<unsignedlong> ( 0UL ) ; "
" f<longlong> ( 0ll ) ; "
" f<longlong> ( 0LL ) ; "
" f<unsignedlonglong> ( 0ull ) ; "
" f<unsignedlonglong> ( 0ULL ) ; "
" f<double> ( 0.0 ) ; "
" f<float> ( 0.0f ) ; "
" f<float> ( 0.0F ) ; "
" f<longdouble> ( 0.0l ) ; "
" f<longdouble> ( 0.0L ) ; "
" f<char> ( 'c' ) ; "
" f<wchar_t> ( L'c' ) ; "
" f<constchar*> ( \" string \" ) ; "
" f<constwchar_t*> ( L \" string \" ) ; "
" f<bool> ( true ) ; "
" f<bool> ( false ) ; "
" } "
" void f<int> ( int n ) { ( void ) n ; } "
" void f<unsignedint> ( unsigned int n ) { ( void ) n ; } "
" void f<long> ( long n ) { ( void ) n ; } "
" void f<unsignedlong> ( unsigned long n ) { ( void ) n ; } "
" void f<longlong> ( long long n ) { ( void ) n ; } "
" void f<unsignedlonglong> ( unsigned long long n ) { ( void ) n ; } "
" void f<double> ( double n ) { ( void ) n ; } "
" void f<float> ( float n ) { ( void ) n ; } "
" void f<longdouble> ( long double n ) { ( void ) n ; } "
" void f<char> ( char n ) { ( void ) n ; } "
" void f<wchar_t> ( wchar_t n ) { ( void ) n ; } "
" void f<constchar*> ( const char * n ) { ( void ) n ; } "
" void f<constwchar_t*> ( const wchar_t * n ) { ( void ) n ; } "
" void f<bool> ( bool n ) { ( void ) n ; } " ;
2019-02-27 07:06:34 +01:00
ASSERT_EQUALS ( expected , tok ( code ) ) ;
2019-02-14 11:48:59 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
void templateTypeDeduction2 ( ) {
const char code [ ] = " template<typename T, typename U> \n "
" void f(T t, U u) { } \n "
" static void func() { \n "
" f(0, 0.0); \n "
" f(0.0, 0); \n "
" } " ;
const char expected [ ] = " void f<int,double> ( int t , double u ) ; "
" void f<double,int> ( double t , int u ) ; "
" static void func ( ) { "
" f<int,double> ( 0 , 0.0 ) ; "
" f<double,int> ( 0.0, 0 ) ; "
" void f<int,double> ( int t , double u ) { } "
" void f<double,int> ( double t , int u ) { } " ;
const char actual [ ] = " template < typename T , typename U > "
" void f ( T t , U u ) { } "
" static void func ( ) { "
" f ( 0 , 0.0 ) ; "
" f ( 0.0 , 0 ) ; "
" } " ;
2019-02-27 07:06:34 +01:00
TODO_ASSERT_EQUALS ( expected , actual , tok ( code ) ) ;
2019-02-14 11:48:59 +01:00
}
2019-09-25 12:06:29 +02:00
void simplifyTemplateArgs1 ( ) {
2019-03-25 14:56:51 +01:00
ASSERT_EQUALS ( " foo<2> = 2 ; foo<2> ; " , tok ( " template<int N> foo = N; foo < ( 2 ) >; " ) ) ;
ASSERT_EQUALS ( " foo<2> = 2 ; foo<2> ; " , tok ( " template<int N> foo = N; foo < 1 + 1 >; " ) ) ;
ASSERT_EQUALS ( " foo<2> = 2 ; foo<2> ; " , tok ( " template<int N> foo = N; foo < ( 1 + 1 ) >; " ) ) ;
ASSERT_EQUALS ( " foo<2,2> = 4 ; foo<2,2> ; " , tok ( " template<int N, int M> foo = N * M; foo < ( 2 ), ( 2 ) >; " ) ) ;
ASSERT_EQUALS ( " foo<2,2> = 4 ; foo<2,2> ; " , tok ( " template<int N, int M> foo = N * M; foo < 1 + 1, 1 + 1 >; " ) ) ;
ASSERT_EQUALS ( " foo<2,2> = 4 ; foo<2,2> ; " , tok ( " template<int N, int M> foo = N * M; foo < ( 1 + 1 ), ( 1 + 1 ) >; " ) ) ;
ASSERT_EQUALS ( " foo<true> = true ; foo<true> ; " , tok ( " template<bool N> foo = N; foo < true ? true : false >; " ) ) ;
ASSERT_EQUALS ( " foo<false> = false ; foo<false> ; " , tok ( " template<bool N> foo = N; foo < false ? true : false >; " ) ) ;
ASSERT_EQUALS ( " foo<true> = true ; foo<true> ; " , tok ( " template<bool N> foo = N; foo < 1 ? true : false >; " ) ) ;
ASSERT_EQUALS ( " foo<false> = false ; foo<false> ; " , tok ( " template<bool N> foo = N; foo < 0 ? true : false >; " ) ) ;
ASSERT_EQUALS ( " foo<true> = true ; foo<true> ; " , tok ( " template<bool N> foo = N; foo < (1 + 1 ) ? true : false >; " ) ) ;
ASSERT_EQUALS ( " foo<false> = false ; foo<false> ; " , tok ( " template<bool N> foo = N; foo < ( 1 - 1) ? true : false >; " ) ) ;
}
2019-09-25 12:06:29 +02:00
void simplifyTemplateArgs2 ( ) {
const char code [ ] = " template<bool T> struct a_t { static const bool t = T; }; \n "
" typedef a_t<sizeof(void*) == sizeof(char)> a; \n "
" void foo() { bool b = a::t; } " ;
const char expected [ ] = " struct a_t<false> ; "
" void foo ( ) { bool b ; b = a_t<false> :: t ; } "
" struct a_t<false> { static const bool t = false ; } ; " ;
ASSERT_EQUALS ( expected , tok ( code ) ) ;
}
2019-05-23 20:53:26 +02:00
void template_variadic_1 ( ) { // #9144
const char code [ ] = " template <typename...> struct e {}; \n "
" static_assert(sizeof(e<>) == sizeof(e<int,int>), \" \" ); " ;
const char expected [ ] = " struct e<> ; struct e<int,int> ; "
" static_assert ( sizeof ( e<> ) == sizeof ( e<int,int> ) , \" \" ) ; "
" struct e<> { } ; struct e<int,int> { } ; " ;
ASSERT_EQUALS ( expected , tok ( code ) ) ;
}
2019-06-01 10:52:29 +02:00
void template_variable_1 ( ) {
{
const char code [ ] = " template <int N> const int foo = N*N; \n "
" int x = foo<7>; " ;
const char expected [ ] = " const int foo<7> = 49 ; "
" int x ; x = foo<7> ; " ;
ASSERT_EQUALS ( expected , tok ( code ) ) ;
}
{
const char code [ ] = " template <int> const int foo = 7; \n "
" int x = foo<7>; " ;
const char expected [ ] = " const int foo<7> = 7 ; "
" int x ; x = foo<7> ; " ;
ASSERT_EQUALS ( expected , tok ( code ) ) ;
}
{
const char code [ ] = " template <int N = 7> const int foo = N*N; \n "
" int x = foo<7>; " ;
const char expected [ ] = " const int foo<7> = 49 ; "
" int x ; x = foo<7> ; " ;
ASSERT_EQUALS ( expected , tok ( code ) ) ;
}
{
const char code [ ] = " template <int N = 7> const int foo = N*N; \n "
" int x = foo<>; " ;
const char expected [ ] = " const int foo<7> = 49 ; "
" int x ; x = foo<7> ; " ;
ASSERT_EQUALS ( expected , tok ( code ) ) ;
}
}
void template_variable_2 ( ) {
{
const char code [ ] = " template<class T> constexpr T pi = T(3.1415926535897932385L); \n "
" float x = pi<float>; " ;
const char expected [ ] = " const float pi<float> = float ( 3.1415926535897932385L ) ; "
" float x ; x = pi<float> ; " ;
ASSERT_EQUALS ( expected , tok ( code ) ) ;
}
{
const char code [ ] = " template<class> constexpr float pi = float(3.1415926535897932385L); \n "
" float x = pi<float>; " ;
const char expected [ ] = " const float pi<float> = float ( 3.1415926535897932385L ) ; "
" float x ; x = pi<float> ; " ;
ASSERT_EQUALS ( expected , tok ( code ) ) ;
}
{
const char code [ ] = " template<class T = float> constexpr T pi = T(3.1415926535897932385L); \n "
" float x = pi<float>; " ;
const char expected [ ] = " const float pi<float> = float ( 3.1415926535897932385L ) ; "
" float x ; x = pi<float> ; " ;
ASSERT_EQUALS ( expected , tok ( code ) ) ;
}
{
const char code [ ] = " template<class T = float> constexpr T pi = T(3.1415926535897932385L); \n "
" float x = pi<>; " ;
const char expected [ ] = " const float pi<float> = float ( 3.1415926535897932385L ) ; "
" float x ; x = pi<float> ; " ;
ASSERT_EQUALS ( expected , tok ( code ) ) ;
}
}
void template_variable_3 ( ) {
{
const char code [ ] = " template<class T, int N> constexpr T foo = T(N*N); \n "
" float x = foo<float,7>; " ;
const char expected [ ] = " const float foo<float,7> = float ( 49 ) ; "
" float x ; x = foo<float,7> ; " ;
ASSERT_EQUALS ( expected , tok ( code ) ) ;
}
{
const char code [ ] = " template<class,int> constexpr float foo = float(7); \n "
" float x = foo<float,7>; " ;
const char expected [ ] = " const float foo<float,7> = float ( 7 ) ; "
" float x ; x = foo<float,7> ; " ;
ASSERT_EQUALS ( expected , tok ( code ) ) ;
}
{
const char code [ ] = " template<class T = float, int N = 7> constexpr T foo = T(7); \n "
" double x = foo<double, 14>; " ;
const char expected [ ] = " const double foo<double,14> = double ( 7 ) ; "
" double x ; x = foo<double,14> ; " ;
ASSERT_EQUALS ( expected , tok ( code ) ) ;
}
{
const char code [ ] = " template<class T = float, int N = 7> constexpr T foo = T(7); \n "
" float x = foo<>; " ;
const char expected [ ] = " const float foo<float,7> = float ( 7 ) ; "
" float x ; x = foo<float,7> ; " ;
ASSERT_EQUALS ( expected , tok ( code ) ) ;
}
{
const char code [ ] = " template<class T = float, int N = 7> constexpr T foo = T(7); \n "
" double x = foo<double>; " ;
const char expected [ ] = " const double foo<double,7> = double ( 7 ) ; "
" double x ; x = foo<double,7> ; " ;
ASSERT_EQUALS ( expected , tok ( code ) ) ;
}
}
2019-06-28 11:14:20 +02:00
void template_variable_4 ( ) {
const char code [ ] = " template<typename T> void test() { } \n "
" template<typename T> decltype(test<T>)* foo = &(test<T>); \n "
" void bar() { foo<int>(); } " ;
const char expected [ ] = " void test<int> ( ) ; "
" decltype ( test<int> ) * foo<int> = & ( test<int> ) ; "
" void bar ( ) { foo<int> ( ) ; } "
" void test<int> ( ) { } " ;
ASSERT_EQUALS ( expected , tok ( code ) ) ;
}
2019-07-28 21:52:52 +02:00
void simplifyDecltype ( ) {
const char code [ ] = " template<typename T> class type { }; \n "
" type<decltype(true)> b; \n "
" type<decltype(0)> i; \n "
" type<decltype(0U)> ui; \n "
" type<decltype(0L)> l; \n "
" type<decltype(0UL)> ul; \n "
" type<decltype(0LL)> ll; \n "
" type<decltype(0ULL)> ull; \n "
" type<decltype(0.0)> d; \n "
" type<decltype(0.0F)> f; \n "
" type<decltype(0.0L)> ld; " ;
const char expected [ ] = " class type<bool> ; "
" class type<int> ; "
" class type<unsignedint> ; "
" class type<long> ; "
" class type<unsignedlong> ; "
" class type<longlong> ; "
" class type<unsignedlonglong> ; "
" class type<double> ; "
" class type<float> ; "
" class type<longdouble> ; "
" type<bool> b ; "
" type<int> i ; "
" type<unsignedint> ui ; "
" type<long> l ; "
" type<unsignedlong> ul ; "
" type<longlong> ll ; "
" type<unsignedlonglong> ull ; "
" type<double> d ; "
" type<float> f ; "
" type<longdouble> ld ; "
" class type<bool> { } ; "
" class type<int> { } ; "
" class type<unsignedint> { } ; "
" class type<long> { } ; "
" class type<unsignedlong> { } ; "
" class type<longlong> { } ; "
" class type<unsignedlonglong> { } ; "
" class type<double> { } ; "
" class type<float> { } ; "
" class type<longdouble> { } ; " ;
ASSERT_EQUALS ( expected , tok ( code ) ) ;
}
2014-09-24 13:23:44 +02:00
} ;
REGISTER_TEST ( TestSimplifyTemplate )