diff --git a/test/testrunner.vcxproj b/test/testrunner.vcxproj
index 19ee8072b..672017f98 100644
--- a/test/testrunner.vcxproj
+++ b/test/testrunner.vcxproj
@@ -63,7 +63,9 @@
+
+
@@ -86,6 +88,7 @@
+
diff --git a/test/testrunner.vcxproj.filters b/test/testrunner.vcxproj.filters
index 85adeec95..e75af2a1d 100644
--- a/test/testrunner.vcxproj.filters
+++ b/test/testrunner.vcxproj.filters
@@ -190,6 +190,15 @@
Source Files
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
diff --git a/test/testsimplifytemplate.cpp b/test/testsimplifytemplate.cpp
new file mode 100644
index 000000000..30d6be6cc
--- /dev/null
+++ b/test/testsimplifytemplate.cpp
@@ -0,0 +1,1062 @@
+/*
+ * Cppcheck - A tool for static C/C++ code analysis
+ * Copyright (C) 2007-2014 Daniel Marjamäki and Cppcheck team.
+ *
+ * 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 .
+ */
+
+#include "testsuite.h"
+#include "tokenize.h"
+#include "token.h"
+#include "settings.h"
+#include "templatesimplifier.h"
+
+#include
+
+extern std::ostringstream errout;
+
+
+class TestSimplifyTemplate : public TestFixture {
+public:
+ TestSimplifyTemplate() : TestFixture("TestSimplifyTemplate") {
+ }
+
+private:
+
+ void run() {
+ 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);
+ TEST_CASE(template15);
+ 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(template29); // #3449 - don't crash for garbage code
+ 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 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
+ TEST_CASE(template_unhandled);
+ TEST_CASE(template_default_parameter);
+ TEST_CASE(template_default_type);
+ TEST_CASE(template_typename);
+ TEST_CASE(template_constructor); // #3152 - template constructor is removed
+
+ // Test TemplateSimplifier::templateParameters
+ TEST_CASE(templateParameters);
+ TEST_CASE(templateParameters1); // #4169 - segmentation fault
+ }
+
+ std::string tok(const char code[], bool simplify = true, Settings::PlatformType type = Settings::Unspecified) {
+ errout.str("");
+
+ Settings settings;
+ settings.addEnabled("portability");
+ settings.platform(type);
+ Tokenizer tokenizer(&settings, this);
+
+ std::istringstream istr(code);
+ tokenizer.tokenize(istr, "test.cpp");
+
+ if (simplify)
+ tokenizer.simplifyTokenList2();
+
+ return tokenizer.tokens()->stringifyList(0, !simplify);
+ }
+
+ std::string tok(const char code[], const char filename[]) {
+ errout.str("");
+
+ Settings settings;
+ Tokenizer tokenizer(&settings, this);
+
+ std::istringstream istr(code);
+ tokenizer.tokenize(istr, filename);
+ tokenizer.simplifyTokenList2();
+
+ return tokenizer.tokens()->stringifyList(0, false);
+ }
+
+ void template1() {
+ const char code[] = "template void f(T val) { T a; }\n"
+ "f(10);";
+
+ const std::string expected("f ( 10 ) ; "
+ "void f ( int val ) { }");
+
+ ASSERT_EQUALS(expected, tok(code));
+ }
+
+ void template2() {
+ const char code[] = "template class Fred { T a; };\n"
+ "Fred fred;";
+
+ const std::string expected("Fred fred ; "
+ "class Fred { int a ; } ;");
+
+ ASSERT_EQUALS(expected, tok(code));
+ }
+
+ void template3() {
+ const char code[] = "template class Fred { T data[sz]; };\n"
+ "Fred fred;";
+
+ const std::string expected("Fred fred ; "
+ "class Fred { float data [ 4 ] ; } ;");
+
+ ASSERT_EQUALS(expected, tok(code));
+ }
+
+ void template4() {
+ const char code[] = "template class Fred { Fred(); };\n"
+ "Fred fred;";
+
+ const std::string expected("Fred fred ; "
+ "class Fred { Fred ( ) ; } ;");
+
+ ASSERT_EQUALS(expected, tok(code));
+ }
+
+ void template5() {
+ const char code[] = "template class Fred { };\n"
+ "template Fred::Fred() { }\n"
+ "Fred fred;";
+
+ const std::string expected("template < classname T > Fred < T > :: Fred ( ) { } " // <- TODO: this should be removed
+ "Fred fred ; "
+ "class Fred { } ; "
+ "Fred :: Fred ( ) { }");
+
+ ASSERT_EQUALS(expected, tok(code));
+ }
+
+ void template6() {
+ const char code[] = "template class Fred { };\n"
+ "Fred fred1;\n"
+ "Fred fred2;";
+
+ const std::string expected("Fred fred1 ; "
+ "Fred fred2 ; "
+ "class Fred { } ;");
+
+ ASSERT_EQUALS(expected, tok(code));
+ }
+
+ void template7() {
+ // A template class that is not used => no simplification
+ {
+ const char code[] = "template \n"
+ "class ABC\n"
+ "{\n"
+ "public:\n"
+ " typedef ABC m;\n"
+ "};\n";
+
+ const std::string expected("template < class T > class ABC { public: } ;");
+
+ ASSERT_EQUALS(expected, tok(code));
+ }
+
+ {
+ const char code[] = "template class ABC {\n"
+ "public:\n"
+ " typedef std::vector type;\n"
+ "};\n"
+ "int main() {\n"
+ " ABC::type v;\n"
+ " v.push_back(4);\n"
+ " return 0;\n"
+ "}\n";
+
+ const std::string wanted("template < typename T > class ABC { public: } ; "
+ "int main ( ) { "
+ "std :: vector < int > v ; "
+ "v . push_back ( 4 ) ; "
+ "return 0 ; "
+ "}");
+
+ const std::string current("template < typename T > class ABC { public: } ; "
+ "int main ( ) { "
+ "ABC < int > :: type v ; "
+ "v . push_back ( 4 ) ; "
+ "return 0 ; "
+ "}");
+
+ TODO_ASSERT_EQUALS(wanted, current, tok(code));
+ }
+
+ {
+ const char code[] = "template class ABC {\n"
+ "public:\n"
+ " typedef std::vector type;\n"
+ " void f()\n"
+ " {\n"
+ " ABC::type v;\n"
+ " v.push_back(4);\n"
+ " }\n"
+ "};\n";
+
+ const std::string expected("template < typename T > class ABC { "
+ "public: void f ( ) { "
+ "ABC < int > :: type v ; "
+ "v . push_back ( 4 ) ; "
+ "} "
+ "} ;");
+
+ ASSERT_EQUALS(expected, tok(code));
+ }
+ }
+
+ // Template definitions but no usage => no expansion
+ void template8() {
+ const char code[] = "template class A;\n"
+ "template class B;\n"
+ "\n"
+ "typedef A x;\n"
+ "typedef B y;\n"
+ "\n"
+ "template class A {\n"
+ " void f() {\n"
+ " B a = B::g();\n"
+ " T b = 0;\n"
+ " if (b)\n"
+ " b = 0;\n"
+ " }\n"
+ "};\n"
+ "\n"
+ "template inline B h() { return B(); }\n";
+
+ ASSERT_EQUALS("template < typename T > class A ; "
+ "template < typename T > class B ; "
+ "template < typename T > class A { void f ( ) { B < T > a ; a = B < T > :: g ( ) ; T b ; b = 0 ; } } ; "
+ "template < typename T > B < T > h ( ) { return B < T > ( ) ; }", tok(code));
+
+ ASSERT_EQUALS("class A { template < typename T > int foo ( T d ) ; } ;", tok("class A{ template int foo(T d);};"));
+ }
+
+ void template9() {
+ const char code[] = "template < typename T > class A { } ;\n"
+ "\n"
+ "void f ( ) {\n"
+ " A a ;\n"
+ "}\n"
+ "\n"
+ "template < typename T >\n"
+ "class B {\n"
+ " void g ( ) {\n"
+ " A < T > b = A < T > :: h ( ) ;\n"
+ " }\n"
+ "} ;\n";
+
+ // The expected result..
+ std::string expected("void f ( ) { A a ; } "
+ "template < typename T > class B { void g ( ) { A b ; b = A :: h ( ) ; } } ; "
+ "class A { } ; class A { } ;");
+
+ ASSERT_EQUALS(expected, tok(code));
+ }
+
+ void template10() {
+ const char code[] = "template T * foo()\n"
+ "{ return new T[ui]; }\n"
+ "\n"
+ "void f ( )\n"
+ "{\n"
+ " foo<3,int>();\n"
+ "}\n";
+
+ // The expected result..
+ const std::string expected("void f ( ) "
+ "{"
+ " foo<3,int> ( ) ; "
+ "} "
+ "int * foo<3,int> ( ) { return new int [ 3 ] ; }");
+ ASSERT_EQUALS(expected, tok(code));
+ }
+
+ void template11() {
+ const char code[] = "template T * foo()\n"
+ "{ return new T[ui]; }\n"
+ "\n"
+ "void f ( )\n"
+ "{\n"
+ " char * p = foo<3,char>();\n"
+ "}\n";
+
+ // The expected result..
+ const std::string expected("void f ( ) "
+ "{"
+ " char * p ; p = foo<3,char> ( ) ; "
+ "} "
+ "char * foo<3,char> ( ) { return new char [ 3 ] ; }");
+ ASSERT_EQUALS(expected, tok(code));
+ }
+
+ void template12() {
+ const char code[] = "template \n"
+ "class A : public B\n"
+ "{ };\n"
+ "\n"
+ "void f()\n"
+ "{\n"
+ " A<12,12,11> a;\n"
+ "}\n";
+
+ // The expected result..
+ const std::string expected("void f ( ) "
+ "{"
+ " A<12,12,11> a ; "
+ "} "
+ "class A<12,12,11> : public B < 12 , 12 , 0 > "
+ "{ } ;");
+ ASSERT_EQUALS(expected, tok(code));
+ }
+
+ void template13() {
+ const char code[] = "class BB {};\n"
+ "\n"
+ "template \n"
+ "class AA\n"
+ "{\n"
+ "public:\n"
+ " static AA create(T* newObject);\n"
+ " static int size();\n"
+ "};\n"
+ "\n"
+ "class CC { public: CC(AA, int) {} };\n"
+ "\n"
+ "class XX {\n"
+ " AA y;\n"
+ "public:\n"
+ " XX();\n"
+ "};\n"
+ "\n"
+ "XX::XX():\n"
+ " y(AA::create(new CC(AA(), 0)))\n"
+ " {}\n"
+ "\n"
+ "int yy[AA::size()];";
+
+ // Just run it and check that there are not assertions.
+ tok(code);
+ }
+
+ void template14() {
+ const char code[] = "template <> void foo()\n"
+ "{ x(); }\n"
+ "\n"
+ "int main()\n"
+ "{\n"
+ "foo();\n"
+ "}\n";
+
+ // The expected result..
+ const std::string expected("void foo ( ) "
+ "{ x ( ) ; } "
+ "int main ( ) "
+ "{ foo ( ) ; }");
+
+ ASSERT_EQUALS(expected, tok(code));
+ }
+
+ void template15() {
+ const char code[] = "template void a()\n"
+ "{\n"
+ " a();\n"
+ "}\n"
+ "\n"
+ "template <> void a<0>()\n"
+ "{ }\n"
+ "\n"
+ "int main()\n"
+ "{\n"
+ " a<2>();\n"
+ " return 0;\n"
+ "}\n";
+
+ // The expected result..
+ const std::string expected("void a<0> ( ) { } "
+ "int main ( ) "
+ "{ a<2> ( ) ; return 0 ; } "
+ "void a<2> ( ) { a<1> ( ) ; } "
+ "void a<1> ( ) { a<0> ( ) ; }");
+
+ ASSERT_EQUALS(expected, tok(code));
+ }
+
+ void template16() {
+ const char code[] = "template void a()\n"
+ "{ }\n"
+ "\n"
+ "template void b()\n"
+ "{ a(); }\n"
+ "\n"
+ "int main()\n"
+ "{\n"
+ " b<2>();\n"
+ " return 0;\n"
+ "}\n";
+
+ const std::string expected("int main ( ) { b<2> ( ) ; return 0 ; } "
+ "void b<2> ( ) { a<2> ( ) ; } "
+ "void a ( ) { } "
+ "void a<2> ( ) { }");
+
+ ASSERT_EQUALS(expected, tok(code));
+ }
+
+ void template17() {
+ const char code[] = "template\n"
+ "class Fred\n"
+ "{\n"
+ " template\n"
+ " static shared_ptr< Fred > CreateFred()\n"
+ " {\n"
+ " }\n"
+ "};\n"
+ "\n"
+ "shared_ptr i;\n";
+
+ // Assert that there is no segmentation fault..
+ tok(code);
+ }
+
+ void template18() {
+ const char code[] = "template class foo { T a; };\n"
+ "foo *f;";
+
+ const std::string expected("foo * f ; "
+ "class foo { int a ; } ;");
+
+ ASSERT_EQUALS(expected, tok(code));
+ }
+
+ void template19() {
+ const char code[] = "template T & foo()\n"
+ "{ static T temp; return temp; }\n"
+ "\n"
+ "void f ( )\n"
+ "{\n"
+ " char p = foo();\n"
+ "}\n";
+
+ // The expected result..
+ const std::string expected("void f ( ) "
+ "{"
+ " char p ; p = foo ( ) ; "
+ "} "
+ "char & foo ( ) { static char temp ; return temp ; }");
+ ASSERT_EQUALS(expected, tok(code));
+ }
+
+ void template20() {
+ // Ticket #1788 - the destructor implementation is lost
+ const char code[] = "template class A\n"
+ "{\n"
+ "public:\n"
+ " ~A();\n"
+ "};\n"
+ "\n"
+ "template A::~A()\n"
+ "{\n"
+ "}\n"
+ "\n"
+ "A a;\n";
+
+ // The expected result..
+ const std::string expected("template < class T > A < T > :: ~ A ( ) { } " // <- TODO: this should be removed
+ "A a ; "
+ "class A { public: ~ A ( ) ; } ; "
+ "A :: ~ A ( ) { }");
+ ASSERT_EQUALS(expected, tok(code));
+ }
+
+ void template21() {
+ {
+ const char code[] = "template struct Fred { T a; };\n"
+ "Fred fred;";
+
+ const std::string expected("Fred fred ; "
+ "struct Fred { int a ; } ;");
+
+ ASSERT_EQUALS(expected, tok(code));
+ }
+
+ {
+ const char code[] = "template struct Fred { T data[sz]; };\n"
+ "Fred fred;";
+
+ const std::string expected("Fred fred ; "
+ "struct Fred { float data [ 4 ] ; } ;");
+
+ ASSERT_EQUALS(expected, tok(code));
+ }
+
+ {
+ const char code[] = "template struct Fred { Fred(); };\n"
+ "Fred fred;";
+
+ const std::string expected("Fred fred ; "
+ "struct Fred { Fred ( ) ; } ;");
+
+ ASSERT_EQUALS(expected, tok(code));
+ }
+
+ {
+ const char code[] = "template struct Fred { };\n"
+ "Fred fred1;\n"
+ "Fred fred2;";
+
+ const std::string expected("Fred fred1 ; "
+ "Fred fred2 ; "
+ "struct Fred { } ;");
+
+ ASSERT_EQUALS(expected, tok(code));
+ }
+ }
+
+ void template22() {
+ const char code[] = "template struct Fred { T a; };\n"
+ "Fred fred;";
+
+ const std::string expected("Fred fred ; "
+ "struct Fred { std :: string a ; } ;");
+
+ ASSERT_EQUALS(expected, tok(code));
+ }
+
+ void template23() {
+ const char code[] = "template void foo() { }\n"
+ "void bar() {\n"
+ " std::cout << (foo());\n"
+ "}";
+
+ const std::string expected("void bar ( ) {"
+ " std :: cout << ( foo ( ) ) ; "
+ "} "
+ "void foo ( ) { }");
+
+ ASSERT_EQUALS(expected, tok(code));
+ }
+
+ void template24() {
+ // #2648
+ const char code[] = "template struct B\n"
+ "{\n"
+ " int a[n];\n"
+ "};\n"
+ "\n"
+ "template class bitset: B\n"
+ "{};\n"
+ "\n"
+ "bitset<1> z;";
+ const char expected[] = "bitset<1> z ; "
+ "class bitset<1> : B<4> { } ; "
+ "struct B<4> { int a [ 4 ] ; } ;";
+ ASSERT_EQUALS(expected, tok(code));
+ }
+
+ void template25() {
+ const char code[] = "template struct B\n"
+ "{\n"
+ " int a[n];\n"
+ "};\n"
+ "\n"
+ "template class bitset: B<((sizeof(int)) ? : 1)>\n"
+ "{};\n"
+ "\n"
+ "bitset<1> z;";
+
+ const char actual[] = "template < int n > struct B { int a [ n ] ; } ; "
+ "bitset<1> z ; "
+ "class bitset<1> : B < 4 > { } ;";
+
+ const char expected[] = "bitset<1> z ; "
+ "class bitset<1> : B<4> { } ; "
+ "struct B<4> { int a [ 4 ] ; } ;";
+
+ TODO_ASSERT_EQUALS(expected, actual, tok(code));
+
+ }
+
+ void template26() {
+ // #2721
+ const char code[] = "template\n"
+ "class A { public: T x; };\n"
+ "\n"
+ "template\n"
+ "class C: public A {};\n"
+ "\n"
+ "C<2> a;\n";
+ // TODO: expand A also
+ ASSERT_EQUALS("template < class T > class A { public: T x ; } ; C<2> a ; class C<2> : public A < char [ 2 ] > { } ;", tok(code));
+ }
+
+ void template27() {
+ // #3350 - template inside macro call
+ const char code[] = "X(template class Fred);";
+ ASSERT_EQUALS("X ( template < class T > class Fred ) ;", tok(code));
+ }
+
+ void template28() {
+ // #3226 - inner template
+ const char code[] = "template class Fred {};\n"
+ "Fred > x;\n";
+ ASSERT_EQUALS("Fred> x ; class Fred { } ; class Fred> { } ;", tok(code));
+ }
+
+ void template29() {
+ // #3449 - garbage code (don't segfault)
+ const char code[] = "template struct A;\n"
+ "struct B { template struct C };\n"
+ "{};";
+ ASSERT_EQUALS("template < typename T > struct A ; struct B { template < typename T > struct C } ; { } ;", tok(code));
+ }
+
+ void template30() {
+ // #3529 - template < template < ..
+ const char code[] = "template class A, class B> void f(){}";
+ ASSERT_EQUALS("template < template < class > class A , class B > void f ( ) { }", tok(code));
+ }
+
+ void template31() {
+ // #4010 - template reference type
+ const char code[] = "template struct A{}; A a;";
+ ASSERT_EQUALS("A a ; struct A { } ;", tok(code));
+ }
+
+ void template32() {
+ // #3818 - mismatching template not handled well
+ const char code[] = "template struct A { };\n"
+ "\n"
+ "template \n"
+ "struct B\n"
+ "{\n"
+ " public:\n"
+ " A < int, Pair, int > a;\n" // mismatching parameters => don't instantiate
+ "};\n"
+ "\n"
+ "B b;\n";
+ ASSERT_EQUALS("template < class T1 , class T2 , class T3 , class T4 > struct A { } ; "
+ "B b ; "
+ "struct B { public: A < int , Pair < int , int > , int > a ; } ;", tok(code));
+ }
+
+ void template33() {
+ {
+ // #3818 - inner templates in template instantiation not handled well
+ const char code[] = "template struct A { };\n"
+ "template struct B { };\n"
+ "template struct C { A > > ab; };\n"
+ "C c;";
+ ASSERT_EQUALS("C c ; "
+ "struct C { A>> ab ; } ; "
+ "struct B> { } ; " // <- redundant.. but nevermind
+ "struct A>> { } ; " // <- redundant.. but nevermind
+ "struct A>> { } ;", tok(code));
+ }
+
+ {
+ // #4544
+ const char code[] = "struct A { };\n"
+ "template struct B { };\n"
+ "template struct C { };\n"
+ "C< B > c;";
+ ASSERT_EQUALS("struct A { } ; "
+ "template < class T > struct B { } ; " // <- redundant.. but nevermind
+ "C> c ; struct C> { } ;",
+ tok(code));
+ }
+ }
+
+ void template34() {
+ // #3706 - namespace => hang
+ const char code[] = "namespace abc {\n"
+ "template struct X { void f(X &x) {} };\n"
+ "}\n"
+ "template <> int X::Y(0);";
+ ASSERT_EQUALS("namespace abc { "
+ "template < typename T > struct X { void f ( X < T > & x ) { } } ; "
+ "} "
+ "template < > int X < int > :: Y ( 0 ) ;", tok(code));
+ }
+
+ void template35() { // #4074 - "A<'x'> a;" is not recognized as template instantiation
+ const char code[] = "template class A {};\n"
+ "A<'x'> a;";
+ ASSERT_EQUALS("A<'x'> a ; class A<'x'> { } ;", tok(code));
+ }
+
+ void template36() { // #4310 - Passing unknown template instantiation as template argument
+ const char code[] = "template struct X { T t; };\n"
+ "template struct Y { Foo < X< Bar > > _foo; };\n" // <- Bar is unknown
+ "Y bar;";
+ ASSERT_EQUALS("Y bar ; "
+ "struct Y { Foo < X> > _foo ; } ; "
+ "struct X> { Bar < int > t ; } ;",
+ tok(code));
+ }
+
+ void template37() { // #4544 - A a;
+ const char code[] = "class A { };\n"
+ "template class B {};\n"
+ "B b1;\n"
+ "B b2;";
+ ASSERT_EQUALS("class A { } ; B b1 ; B b2 ; class B { } ;",
+ tok(code));
+ }
+
+ void template_unhandled() {
+ // An unhandled template usage should be simplified..
+ ASSERT_EQUALS("x ( ) ;", tok("x();"));
+ }
+
+ void template38() { // #4832 - Crash on C++11 right angle brackets
+ const char code[] = "template class A {\n"
+ " T mT;\n"
+ "public:\n"
+ " void foo() {}\n"
+ "};\n"
+ "\n"
+ "int main() {\n"
+ " A> gna1;\n"
+ " A gna2;\n"
+ "}\n";
+ tok(code); // Don't crash or freeze
+ }
+
+ void template39() { // #4742 - Used to freeze in 1.60
+ const char code[] = "template struct vector {"
+ " operator T() const;"
+ "};"
+ "void f() {"
+ " vector> v;"
+ " const vector vi = static_cast>(v);"
+ "}";
+ tok(code);
+ }
+
+ void template40() { // #5055 - false negatives when there is template specialization outside struct
+ const char code[] = "struct A {"
+ " template struct X { T t; };"
+ "};"
+ "template<> struct A::X { int *t; };";
+ ASSERT_EQUALS("struct A { template < typename T > struct X { T t ; } ; } ;", tok(code));
+ }
+
+ void template41() { // #4710 - const in template instantiation not handled perfectly
+ const char code1[] = "template struct X { };\n"
+ "void f(const X x) { }";
+ ASSERT_EQUALS("void f ( const X x ) { } struct X { } ;", tok(code1));
+
+ const char code2[] = "template T f(T t) { return t; }\n"
+ "int x() { return f(123); }";
+ ASSERT_EQUALS("int x ( ) { return f ( 123 ) ; } int f ( int t ) { return t ; }", tok(code2));
+ }
+
+ void template42() { // #4878 cpcheck aborts in ext-blocks.cpp (clang testcode)
+ const char code[] = "template\n"
+ "int f0(Args ...args) {\n"
+ " return ^ {\n"
+ " return sizeof...(Args);\n"
+ " }() + ^ {\n"
+ " return sizeof...(args);\n"
+ " }();\n"
+ "}";
+ ASSERT_THROW(tok(code), InternalError);
+ }
+
+ void template43() { // #5097 - Assert due to '>>' in 'B>' not being treated as end of template instantation
+ const char code[] = "template struct C { };"
+ "template struct D { static int f() { return C::f(); } };"
+ "template inline int f2() { return D::f(); }"
+ "template int f1(int x, T *) { int id = f2(); return id; }"
+ "template <> struct C < B < A >> {"
+ " static int f() {"
+ " return f1 < B < A >> (0, reinterpret_cast< B *>(E::Int(-1)));"
+ " }"
+ "};";
+ tok(code); // Don't assert
+ }
+
+ void template44() { // #5297
+ tok("template struct StackContainer {"
+ " void foo(int i) {"
+ " if (0 >= 1 && i<0) {}"
+ " }"
+ "};"
+ "template class ZContainer : public StackContainer {};"
+ "struct FGSTensor {};"
+ "class FoldedZContainer : public ZContainer {};");
+ }
+
+ void template45() { // #5814
+ tok("namespace Constants { const int fourtytwo = 42; } "
+ "template struct TypeMath { "
+ " static const int mult = sizeof(T) * U; "
+ "}; "
+ "template struct FOO { "
+ " enum { value = TypeMath::something }; "
+ "};");
+ ASSERT_EQUALS("", errout.str());
+ }
+
+ void template46() { // #5816
+ tok("template struct A { static const int value = 0; }; "
+ "template struct B { "
+ " enum { value = A::value }; "
+ "};");
+ ASSERT_EQUALS("", errout.str());
+ tok("template struct A {}; "
+ "enum { e = sizeof(A) }; "
+ "template struct B {};");
+ ASSERT_EQUALS("", errout.str());
+ tok("template struct A { static const int value = 0; }; "
+ "template struct B { typedef int type; }; "
+ "template struct C { "
+ " enum { value = A::type, int>::value }; "
+ "};");
+ ASSERT_EQUALS("", errout.str());
+ }
+
+ void template47() { // #6023
+ tok("template > class C1 {}; "
+ "class C2 : public C1 {};");
+ ASSERT_EQUALS("", errout.str());
+ }
+
+ void template48() { // #6134
+ tok("template int f( { } ); "
+ "int foo = f<1>(0);");
+ ASSERT_EQUALS("", errout.str());
+ }
+
+ void template_default_parameter() {
+ {
+ const char code[] = "template \n"
+ "class A\n"
+ "{ T ar[n]; };\n"
+ "\n"
+ "void f()\n"
+ "{\n"
+ " A a1;\n"
+ " A a2;\n"
+ "}\n";
+
+ // The expected result..
+ const std::string expected("void f ( ) "
+ "{"
+ " A a1 ;"
+ " A a2 ; "
+ "} "
+ "class A "
+ "{ int ar [ 2 ] ; } ; "
+ "class A "
+ "{ int ar [ 3 ] ; } ;");
+ ASSERT_EQUALS(expected, tok(code));
+ }
+ {
+ const char code[] = "template \n"
+ "class A\n"
+ "{ T ar[n1+n2]; };\n"
+ "\n"
+ "void f()\n"
+ "{\n"
+ " A a1;\n"
+ " A a2;\n"
+ "}\n";
+
+ // The expected result..
+ const std::string expected("void f ( ) "
+ "{"
+ " A a1 ;"
+ " A a2 ; "
+ "} "
+ "class A "
+ "{ int ar [ 5 ] ; } ;");
+ ASSERT_EQUALS(expected, tok(code));
+ }
+ {
+ const char code[] = "template \n"
+ "class A\n"
+ "{ T ar[n]; };\n"
+ "\n"
+ "void f()\n"
+ "{\n"
+ " A a1;\n"
+ " A a2;\n"
+ "}\n";
+
+ const std::string wanted("template < class T , int n >"
+ " class A"
+ " { T ar [ n ] ; } ;"
+ " void f ( )"
+ " {"
+ " A