Blame test/testsimplifytemplate.cpp

Packit 2035a7
/*
Packit 2035a7
 * Cppcheck - A tool for static C/C++ code analysis
Packit 2035a7
 * Copyright (C) 2007-2018 Cppcheck team.
Packit 2035a7
 *
Packit 2035a7
 * This program is free software: you can redistribute it and/or modify
Packit 2035a7
 * it under the terms of the GNU General Public License as published by
Packit 2035a7
 * the Free Software Foundation, either version 3 of the License, or
Packit 2035a7
 * (at your option) any later version.
Packit 2035a7
 *
Packit 2035a7
 * This program is distributed in the hope that it will be useful,
Packit 2035a7
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 2035a7
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit 2035a7
 * GNU General Public License for more details.
Packit 2035a7
 *
Packit 2035a7
 * You should have received a copy of the GNU General Public License
Packit 2035a7
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
Packit 2035a7
 */
Packit 2035a7
Packit 2035a7
Packit 2035a7
#include "config.h"
Packit 2035a7
#include "platform.h"
Packit 2035a7
#include "settings.h"
Packit 2035a7
#include "templatesimplifier.h"
Packit 2035a7
#include "testsuite.h"
Packit 2035a7
#include "token.h"
Packit 2035a7
#include "tokenize.h"
Packit 2035a7
Packit 2035a7
struct InternalError;
Packit 2035a7
Packit 2035a7
Packit 2035a7
class TestSimplifyTemplate : public TestFixture {
Packit 2035a7
public:
Packit 2035a7
    TestSimplifyTemplate() : TestFixture("TestSimplifyTemplate") {
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
private:
Packit 2035a7
    Settings settings;
Packit 2035a7
Packit 2035a7
    void run() {
Packit 2035a7
        settings.addEnabled("portability");
Packit 2035a7
Packit 2035a7
        TEST_CASE(template1);
Packit 2035a7
        TEST_CASE(template2);
Packit 2035a7
        TEST_CASE(template3);
Packit 2035a7
        TEST_CASE(template4);
Packit 2035a7
        TEST_CASE(template5);
Packit 2035a7
        TEST_CASE(template6);
Packit 2035a7
        TEST_CASE(template7);
Packit 2035a7
        TEST_CASE(template8);
Packit 2035a7
        TEST_CASE(template9);
Packit 2035a7
        TEST_CASE(template10);
Packit 2035a7
        TEST_CASE(template11);
Packit 2035a7
        TEST_CASE(template12);
Packit 2035a7
        TEST_CASE(template13);
Packit 2035a7
        TEST_CASE(template14);
Packit 2035a7
        TEST_CASE(template15);  // recursive templates
Packit 2035a7
        TEST_CASE(template16);
Packit 2035a7
        TEST_CASE(template17);
Packit 2035a7
        TEST_CASE(template18);
Packit 2035a7
        TEST_CASE(template19);
Packit 2035a7
        TEST_CASE(template20);
Packit 2035a7
        TEST_CASE(template21);
Packit 2035a7
        TEST_CASE(template22);
Packit 2035a7
        TEST_CASE(template23);
Packit 2035a7
        TEST_CASE(template24);  // #2648 - using sizeof in template parameter
Packit 2035a7
        TEST_CASE(template25);  // #2648 - another test for sizeof template parameter
Packit 2035a7
        TEST_CASE(template26);  // #2721 - passing 'char[2]' as template parameter
Packit 2035a7
        TEST_CASE(template27);  // #3350 - removing unused template in macro call
Packit 2035a7
        TEST_CASE(template28);
Packit 2035a7
        TEST_CASE(template30);  // #3529 - template < template < ..
Packit 2035a7
        TEST_CASE(template31);  // #4010 - reference type
Packit 2035a7
        TEST_CASE(template32);  // #3818 - mismatching template not handled well
Packit 2035a7
        TEST_CASE(template33);  // #3818,#4544 - inner templates in template instantiation not handled well
Packit 2035a7
        TEST_CASE(template34);  // #3706 - namespace => hang
Packit 2035a7
        TEST_CASE(template35);  // #4074 - A<'x'> a;
Packit 2035a7
        TEST_CASE(template36);  // #4310 - passing unknown template instantiation as template argument
Packit 2035a7
        TEST_CASE(template37);  // #4544 - A<class B> a;
Packit 2035a7
        TEST_CASE(template38);  // #4832 - crash on C++11 right angle brackets
Packit 2035a7
        TEST_CASE(template39);  // #4742 - freeze
Packit 2035a7
        TEST_CASE(template40);  // #5055 - template specialization outside struct
Packit 2035a7
        TEST_CASE(template41);  // #4710 - const in instantiation not handled perfectly
Packit 2035a7
        TEST_CASE(template42);  // #4878 - variadic templates
Packit 2035a7
        TEST_CASE(template43);  // #5097 - assert due to '>>' not treated as end of template instantiation
Packit 2035a7
        TEST_CASE(template44);  // #5297 - TemplateSimplifier::simplifyCalculations not eager enough
Packit 2035a7
        TEST_CASE(template45);  // #5814 - syntax error reported for valid code
Packit 2035a7
        TEST_CASE(template46);  // #5816 - syntax error reported for valid code
Packit 2035a7
        TEST_CASE(template47);  // #6023 - syntax error reported for valid code
Packit 2035a7
        TEST_CASE(template48);  // #6134 - 100% CPU upon invalid code
Packit 2035a7
        TEST_CASE(template49);  // #6237 - template instantiation
Packit 2035a7
        TEST_CASE(template50);  // #4272 - simple partial specialization
Packit 2035a7
        TEST_CASE(template51);  // #6172 - crash upon valid code
Packit 2035a7
        TEST_CASE(template52);  // #6437 - crash upon valid code
Packit 2035a7
        TEST_CASE(template53);  // #4335 - bail out for valid code
Packit 2035a7
        TEST_CASE(template54);  // #6587 - memory corruption upon valid code
Packit 2035a7
        TEST_CASE(template55);  // #6604 - simplify "const const" to "const" in template instantiations
Packit 2035a7
        TEST_CASE(template56);  // #7117 - const ternary operator simplification as template parameter
Packit 2035a7
        TEST_CASE(template57);  // #7891
Packit 2035a7
        TEST_CASE(template58);  // #6021 - use after free (deleted tokens in simplifyCalculations)
Packit 2035a7
        TEST_CASE(template59);  // #8051 - TemplateSimplifier::simplifyTemplateInstantiation failure
Packit 2035a7
        TEST_CASE(template60);  // handling of methods outside template definition
Packit 2035a7
        TEST_CASE(template61);  // daca2, kodi
Packit 2035a7
        TEST_CASE(template62);  // #8314 - inner template instantiation
Packit 2035a7
        TEST_CASE(template_specialization_1);  // #7868 - template specialization template <typename T> struct S<C<T>> {..};
Packit 2035a7
        TEST_CASE(template_specialization_2);  // #7868 - template specialization template <typename T> struct S<C<T>> {..};
Packit 2035a7
        TEST_CASE(template_enum);  // #6299 Syntax error in complex enum declaration (including template)
Packit 2035a7
        TEST_CASE(template_unhandled);
Packit 2035a7
        TEST_CASE(template_default_parameter);
Packit 2035a7
        TEST_CASE(template_default_type);
Packit 2035a7
        TEST_CASE(template_typename);
Packit 2035a7
        TEST_CASE(template_constructor);    // #3152 - template constructor is removed
Packit 2035a7
        TEST_CASE(syntax_error_templates_1);
Packit 2035a7
        TEST_CASE(template_member_ptr); // Ticket #5786 - crash upon valid code
Packit 2035a7
        TEST_CASE(template_namespace_1);
Packit 2035a7
        TEST_CASE(template_namespace_2);
Packit 2035a7
        TEST_CASE(template_namespace_3);
Packit 2035a7
        TEST_CASE(template_namespace_4);
Packit 2035a7
        TEST_CASE(template_namespace_5);
Packit 2035a7
Packit 2035a7
        // Test TemplateSimplifier::templateParameters
Packit 2035a7
        TEST_CASE(templateParameters);
Packit 2035a7
Packit 2035a7
        TEST_CASE(templateNamePosition);
Packit 2035a7
Packit 2035a7
        TEST_CASE(expandSpecialized);
Packit 2035a7
Packit 2035a7
        TEST_CASE(templateAlias1);
Packit 2035a7
        TEST_CASE(templateAlias2);
Packit 2035a7
        TEST_CASE(templateAlias3); // #8315
Packit 2035a7
Packit 2035a7
        // Test TemplateSimplifier::instantiateMatch
Packit 2035a7
        TEST_CASE(instantiateMatch);
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    std::string tok(const char code[], bool simplify = true, bool debugwarnings = false, Settings::PlatformType type = Settings::Native) {
Packit 2035a7
        errout.str("");
Packit 2035a7
Packit 2035a7
        settings.debugwarnings = debugwarnings;
Packit 2035a7
        settings.platform(type);
Packit 2035a7
        Tokenizer tokenizer(&settings, this);
Packit 2035a7
Packit 2035a7
        std::istringstream istr(code);
Packit 2035a7
        tokenizer.tokenize(istr, "test.cpp");
Packit 2035a7
Packit 2035a7
        if (simplify)
Packit 2035a7
            tokenizer.simplifyTokenList2();
Packit 2035a7
Packit 2035a7
        return tokenizer.tokens()->stringifyList(0, !simplify);
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    std::string tok(const char code[], const char filename[]) {
Packit 2035a7
        errout.str("");
Packit 2035a7
Packit 2035a7
        settings.debugwarnings = false;
Packit 2035a7
        Tokenizer tokenizer(&settings, this);
Packit 2035a7
Packit 2035a7
        std::istringstream istr(code);
Packit 2035a7
        tokenizer.tokenize(istr, filename);
Packit 2035a7
        tokenizer.simplifyTokenList2();
Packit 2035a7
Packit 2035a7
        return tokenizer.tokens()->stringifyList(0, false);
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void template1() {
Packit 2035a7
        const char code[] = "template <class T> void f(T val) { T a; }\n"
Packit 2035a7
                            "f<int>(10);";
Packit 2035a7
Packit 2035a7
        const char expected[] = "f<int> ( 10 ) ; "
Packit 2035a7
                                "void f<int> ( int val ) { }";
Packit 2035a7
Packit 2035a7
        ASSERT_EQUALS(expected, tok(code));
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void template2() {
Packit 2035a7
        const char code[] = "template <class T> class Fred { T a; };\n"
Packit 2035a7
                            "Fred<int> fred;";
Packit 2035a7
Packit 2035a7
        const char expected[] = "Fred<int> fred ; "
Packit 2035a7
                                "class Fred<int> { int a ; } ;";
Packit 2035a7
Packit 2035a7
        ASSERT_EQUALS(expected, tok(code));
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void template3() {
Packit 2035a7
        const char code[] = "template <class T, int sz> class Fred { T data[sz]; };\n"
Packit 2035a7
                            "Fred<float,4> fred;";
Packit 2035a7
Packit 2035a7
        const char expected[] = "Fred<float,4> fred ; "
Packit 2035a7
                                "class Fred<float,4> { float data [ 4 ] ; } ;";
Packit 2035a7
Packit 2035a7
        ASSERT_EQUALS(expected, tok(code));
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void template4() {
Packit 2035a7
        const char code[] = "template <class T> class Fred { Fred(); };\n"
Packit 2035a7
                            "Fred<float> fred;";
Packit 2035a7
Packit 2035a7
        const char expected[] = "Fred<float> fred ; "
Packit 2035a7
                                "class Fred<float> { Fred<float> ( ) ; } ;";
Packit 2035a7
Packit 2035a7
        ASSERT_EQUALS(expected, tok(code));
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void template5() {
Packit 2035a7
        const char code[] = "template <class T> class Fred { };\n"
Packit 2035a7
                            "template <class T> Fred<T>::Fred() { }\n"
Packit 2035a7
                            "Fred<float> fred;";
Packit 2035a7
Packit 2035a7
        const char expected[] = "template < class T > Fred < T > :: Fred ( ) { } " // <- TODO: this should be removed
Packit 2035a7
                                "Fred<float> fred ; "
Packit 2035a7
                                "class Fred<float> { } ; "
Packit 2035a7
                                "Fred<float> :: Fred ( ) { }";
Packit 2035a7
Packit 2035a7
        ASSERT_EQUALS(expected, tok(code));
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void template6() {
Packit 2035a7
        const char code[] = "template <class T> class Fred { };\n"
Packit 2035a7
                            "Fred<float> fred1;\n"
Packit 2035a7
                            "Fred<float> fred2;";
Packit 2035a7
Packit 2035a7
        const char expected[] = "Fred<float> fred1 ; "
Packit 2035a7
                                "Fred<float> fred2 ; "
Packit 2035a7
                                "class Fred<float> { } ;";
Packit 2035a7
Packit 2035a7
        ASSERT_EQUALS(expected, tok(code));
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void template7() {
Packit 2035a7
        // A template class that is not used => no simplification
Packit 2035a7
        {
Packit 2035a7
            const char code[] = "template <class T>\n"
Packit 2035a7
                                "class ABC\n"
Packit 2035a7
                                "{\n"
Packit 2035a7
                                "public:\n"
Packit 2035a7
                                "    typedef ABC<T> m;\n"
Packit 2035a7
                                "};\n";
Packit 2035a7
Packit 2035a7
            const char expected[] = "template < class T > class ABC { public: } ;";
Packit 2035a7
Packit 2035a7
            ASSERT_EQUALS(expected, tok(code));
Packit 2035a7
        }
Packit 2035a7
Packit 2035a7
        {
Packit 2035a7
            const char code[] = "template <typename T> class ABC {\n"
Packit 2035a7
                                "public:\n"
Packit 2035a7
                                "    typedef std::vector<T> type;\n"
Packit 2035a7
                                "};\n"
Packit 2035a7
                                "int main() {\n"
Packit 2035a7
                                "    ABC<int>::type v;\n"
Packit 2035a7
                                "    v.push_back(4);\n"
Packit 2035a7
                                "    return 0;\n"
Packit 2035a7
                                "}\n";
Packit 2035a7
Packit 2035a7
            const char wanted[] = "template < typename T > class ABC { public: } ; "
Packit 2035a7
                                  "int main ( ) { "
Packit 2035a7
                                  "std :: vector < int > v ; "
Packit 2035a7
                                  "v . push_back ( 4 ) ; "
Packit 2035a7
                                  "return 0 ; "
Packit 2035a7
                                  "}";
Packit 2035a7
Packit 2035a7
            const char current[] = "template < typename T > class ABC { public: } ; "
Packit 2035a7
                                   "int main ( ) { "
Packit 2035a7
                                   "ABC < int > :: type v ; "
Packit 2035a7
                                   "v . push_back ( 4 ) ; "
Packit 2035a7
                                   "return 0 ; "
Packit 2035a7
                                   "}";
Packit 2035a7
Packit 2035a7
            TODO_ASSERT_EQUALS(wanted, current, tok(code));
Packit 2035a7
        }
Packit 2035a7
Packit 2035a7
        {
Packit 2035a7
            const char code[] = "template <typename T> class ABC {\n"
Packit 2035a7
                                "public:\n"
Packit 2035a7
                                "    typedef std::vector<T> type;\n"
Packit 2035a7
                                "    void f()\n"
Packit 2035a7
                                "    {\n"
Packit 2035a7
                                "      ABC<int>::type v;\n"
Packit 2035a7
                                "      v.push_back(4);\n"
Packit 2035a7
                                "    }\n"
Packit 2035a7
                                "};\n";
Packit 2035a7
Packit 2035a7
            const char expected[] = "template < typename T > class ABC { "
Packit 2035a7
                                    "public: void f ( ) { "
Packit 2035a7
                                    "ABC < int > :: type v ; "
Packit 2035a7
                                    "v . push_back ( 4 ) ; "
Packit 2035a7
                                    "} "
Packit 2035a7
                                    "} ;";
Packit 2035a7
Packit 2035a7
            ASSERT_EQUALS(expected, tok(code));
Packit 2035a7
        }
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    // Template definitions but no usage => no expansion
Packit 2035a7
    void template8() {
Packit 2035a7
        const char code[] = "template<typename T> class A;\n"
Packit 2035a7
                            "template<typename T> class B;\n"
Packit 2035a7
                            "\n"
Packit 2035a7
                            "typedef A<int> x;\n"
Packit 2035a7
                            "typedef B<int> y;\n"
Packit 2035a7
                            "\n"
Packit 2035a7
                            "template<typename T> class A {\n"
Packit 2035a7
                            "    void f() {\n"
Packit 2035a7
                            "        B<T> a = B<T>::g();\n"
Packit 2035a7
                            "        T b = 0;\n"
Packit 2035a7
                            "        if (b)\n"
Packit 2035a7
                            "            b = 0;\n"
Packit 2035a7
                            "    }\n"
Packit 2035a7
                            "};\n"
Packit 2035a7
                            "\n"
Packit 2035a7
                            "template<typename T> inline B<T> h() { return B<T>(); }\n";
Packit 2035a7
Packit 2035a7
        ASSERT_EQUALS("template < typename T > class A ; "
Packit 2035a7
                      "template < typename T > class B ; "
Packit 2035a7
                      "template < typename T > class A { void f ( ) { B < T > a ; a = B < T > :: g ( ) ; T b ; b = 0 ; } } ; "
Packit 2035a7
                      "template < typename T > B < T > h ( ) { return B < T > ( ) ; }", tok(code));
Packit 2035a7
Packit 2035a7
        ASSERT_EQUALS("class A { template < typename T > int foo ( T d ) ; } ;", tok("class A{ template<typename T> int foo(T d);};"));
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void template9() {
Packit 2035a7
        const char code[] = "template < typename T > class A { } ;\n"
Packit 2035a7
                            "\n"
Packit 2035a7
                            "void f ( ) {\n"
Packit 2035a7
                            "    A < int > a ;\n"
Packit 2035a7
                            "}\n"
Packit 2035a7
                            "\n"
Packit 2035a7
                            "template < typename T >\n"
Packit 2035a7
                            "class B {\n"
Packit 2035a7
                            "    void g ( ) {\n"
Packit 2035a7
                            "        A < T > b = A < T > :: h ( ) ;\n"
Packit 2035a7
                            "    }\n"
Packit 2035a7
                            "} ;\n";
Packit 2035a7
Packit 2035a7
        // The expected result..
Packit 2035a7
        const char expected[] = "void f ( ) { A<int> a ; } "
Packit 2035a7
                                "template < typename T > class B { void g ( ) { A < T > b ; b = A < T > :: h ( ) ; } } ; "
Packit 2035a7
                                "class A<int> { } ;";
Packit 2035a7
Packit 2035a7
        ASSERT_EQUALS(expected, tok(code));
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void template10() {
Packit 2035a7
        const char code[] = "template <int ui, typename T> T * foo()\n"
Packit 2035a7
                            "{ return new T[ui]; }\n"
Packit 2035a7
                            "\n"
Packit 2035a7
                            "void f ( )\n"
Packit 2035a7
                            "{\n"
Packit 2035a7
                            "    foo<3,int>();\n"
Packit 2035a7
                            "}\n";
Packit 2035a7
Packit 2035a7
        // The expected result..
Packit 2035a7
        const char expected[] = "void f ( ) "
Packit 2035a7
                                "{"
Packit 2035a7
                                " foo<3,int> ( ) ; "
Packit 2035a7
                                "} "
Packit 2035a7
                                "int * foo<3,int> ( ) { return new int [ 3 ] ; }";
Packit 2035a7
        ASSERT_EQUALS(expected, tok(code));
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void template11() {
Packit 2035a7
        const char code[] = "template <int ui, typename T> T * foo()\n"
Packit 2035a7
                            "{ return new T[ui]; }\n"
Packit 2035a7
                            "\n"
Packit 2035a7
                            "void f ( )\n"
Packit 2035a7
                            "{\n"
Packit 2035a7
                            "    char * p = foo<3,char>();\n"
Packit 2035a7
                            "}\n";
Packit 2035a7
Packit 2035a7
        // The expected result..
Packit 2035a7
        const char expected[] = "void f ( ) "
Packit 2035a7
                                "{"
Packit 2035a7
                                " char * p ; p = foo<3,char> ( ) ; "
Packit 2035a7
                                "} "
Packit 2035a7
                                "char * foo<3,char> ( ) { return new char [ 3 ] ; }";
Packit 2035a7
        ASSERT_EQUALS(expected, tok(code));
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void template12() {
Packit 2035a7
        const char code[] = "template <int x, int y, int z>\n"
Packit 2035a7
                            "class A : public B<x, y, (x - y) ? ((y < z) ? 1 : -1) : 0>\n"
Packit 2035a7
                            "{ };\n"
Packit 2035a7
                            "\n"
Packit 2035a7
                            "void f()\n"
Packit 2035a7
                            "{\n"
Packit 2035a7
                            "    A<12,12,11> a;\n"
Packit 2035a7
                            "}\n";
Packit 2035a7
Packit 2035a7
        // The expected result..
Packit 2035a7
        const char expected[] = "void f ( ) "
Packit 2035a7
                                "{"
Packit 2035a7
                                " A<12,12,11> a ; "
Packit 2035a7
                                "} "
Packit 2035a7
                                "class A<12,12,11> : public B < 12 , 12 , 0 > "
Packit 2035a7
                                "{ } ;";
Packit 2035a7
        ASSERT_EQUALS(expected, tok(code));
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void template13() {
Packit 2035a7
        const char code[] = "class BB {};\n"
Packit 2035a7
                            "\n"
Packit 2035a7
                            "template <class T>\n"
Packit 2035a7
                            "class AA\n"
Packit 2035a7
                            "{\n"
Packit 2035a7
                            "public:\n"
Packit 2035a7
                            "    static AA<T> create(T* newObject);\n"
Packit 2035a7
                            "    static int size();\n"
Packit 2035a7
                            "};\n"
Packit 2035a7
                            "\n"
Packit 2035a7
                            "class CC { public: CC(AA<BB>, int) {} };\n"
Packit 2035a7
                            "\n"
Packit 2035a7
                            "class XX {\n"
Packit 2035a7
                            "    AA<CC> y;\n"
Packit 2035a7
                            "public:\n"
Packit 2035a7
                            "    XX();\n"
Packit 2035a7
                            "};\n"
Packit 2035a7
                            "\n"
Packit 2035a7
                            "XX::XX():\n"
Packit 2035a7
                            "    y(AA<CC>::create(new CC(AA<BB>(), 0)))\n"
Packit 2035a7
                            "    {}\n"
Packit 2035a7
                            "\n"
Packit 2035a7
                            "int yy[AA<CC>::size()];";
Packit 2035a7
Packit 2035a7
        // Just run it and check that there are not assertions.
Packit 2035a7
        tok(code);
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void template14() {
Packit 2035a7
        const char code[] = "template <> void foo<int *>()\n"
Packit 2035a7
                            "{ x(); }\n"
Packit 2035a7
                            "\n"
Packit 2035a7
                            "int main()\n"
Packit 2035a7
                            "{\n"
Packit 2035a7
                            "foo<int*>();\n"
Packit 2035a7
                            "}\n";
Packit 2035a7
Packit 2035a7
        // The expected result..
Packit 2035a7
        const char expected[] = "void foo<int*> ( ) "
Packit 2035a7
                                "{ x ( ) ; } "
Packit 2035a7
                                "int main ( ) "
Packit 2035a7
                                "{ foo<int*> ( ) ; }";
Packit 2035a7
Packit 2035a7
        ASSERT_EQUALS(expected, tok(code));
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void template15() { // recursive templates  #3130 etc
Packit 2035a7
        const char code[] = "template <unsigned int i> void a()\n"
Packit 2035a7
                            "{\n"
Packit 2035a7
                            "    a<i-1>();\n"
Packit 2035a7
                            "}\n"
Packit 2035a7
                            "\n"
Packit 2035a7
                            "template <> void a<0>()\n"
Packit 2035a7
                            "{ }\n"
Packit 2035a7
                            "\n"
Packit 2035a7
                            "int main()\n"
Packit 2035a7
                            "{\n"
Packit 2035a7
                            "    a<2>();\n"
Packit 2035a7
                            "    return 0;\n"
Packit 2035a7
                            "}\n";
Packit 2035a7
Packit 2035a7
        // The expected result..
Packit 2035a7
        const char expected[] = "void a<0> ( ) { } "
Packit 2035a7
                                "int main ( ) "
Packit 2035a7
                                "{ a<2> ( ) ; return 0 ; } "
Packit 2035a7
                                "void a<2> ( ) { a<1> ( ) ; } "
Packit 2035a7
                                "void a<1> ( ) { a<0> ( ) ; }";
Packit 2035a7
Packit 2035a7
        ASSERT_EQUALS(expected, tok(code));
Packit 2035a7
Packit 2035a7
        // #3130
Packit 2035a7
        const char code2[] = "template <int n> struct vec {\n"
Packit 2035a7
                             "  vec() {}\n"
Packit 2035a7
                             "  vec(const vec<n-1>& v) {}\n" // <- never used don't instantiate
Packit 2035a7
                             "};\n"
Packit 2035a7
                             "\n"
Packit 2035a7
                             "vec<4> v;";
Packit 2035a7
        const char expected2[] = "vec<4> v ; "
Packit 2035a7
                                 "struct vec<4> { "
Packit 2035a7
                                 "vec<4> ( ) { } "
Packit 2035a7
                                 "vec<4> ( const vec < 4 - 1 > & v ) { } "
Packit 2035a7
                                 "} ;";
Packit 2035a7
Packit 2035a7
        ASSERT_EQUALS(expected2, tok(code2));
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void template16() {
Packit 2035a7
        const char code[] = "template <unsigned int i> void a()\n"
Packit 2035a7
                            "{ }\n"
Packit 2035a7
                            "\n"
Packit 2035a7
                            "template <unsigned int i> void b()\n"
Packit 2035a7
                            "{ a(); }\n"
Packit 2035a7
                            "\n"
Packit 2035a7
                            "int main()\n"
Packit 2035a7
                            "{\n"
Packit 2035a7
                            "    b<2>();\n"
Packit 2035a7
                            "    return 0;\n"
Packit 2035a7
                            "}\n";
Packit 2035a7
Packit 2035a7
        const char expected[] = "int main ( ) { b<2> ( ) ; return 0 ; } "
Packit 2035a7
                                "void b<2> ( ) { a<2> ( ) ; } "
Packit 2035a7
                                "void a<2> ( ) { }";
Packit 2035a7
Packit 2035a7
        ASSERT_EQUALS(expected, tok(code));
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void template17() {
Packit 2035a7
        const char code[] = "template<class T>\n"
Packit 2035a7
                            "class Fred\n"
Packit 2035a7
                            "{\n"
Packit 2035a7
                            "    template<class T>\n"
Packit 2035a7
                            "    static shared_ptr< Fred<T> > CreateFred()\n"
Packit 2035a7
                            "    {\n"
Packit 2035a7
                            "    }\n"
Packit 2035a7
                            "};\n"
Packit 2035a7
                            "\n"
Packit 2035a7
                            "shared_ptr<int> i;\n";
Packit 2035a7
Packit 2035a7
        // Assert that there is no segmentation fault..
Packit 2035a7
        tok(code);
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void template18() {
Packit 2035a7
        const char code[] = "template <class T> class foo { T a; };\n"
Packit 2035a7
                            "foo<int> *f;";
Packit 2035a7
Packit 2035a7
        const char expected[] = "foo<int> * f ; "
Packit 2035a7
                                "class foo<int> { int a ; } ;";
Packit 2035a7
Packit 2035a7
        ASSERT_EQUALS(expected, tok(code));
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void template19() {
Packit 2035a7
        const char code[] = "template <typename T> T & foo()\n"
Packit 2035a7
                            "{ static T temp; return temp; }\n"
Packit 2035a7
                            "\n"
Packit 2035a7
                            "void f ( )\n"
Packit 2035a7
                            "{\n"
Packit 2035a7
                            "    char p = foo<char>();\n"
Packit 2035a7
                            "}\n";
Packit 2035a7
Packit 2035a7
        // The expected result..
Packit 2035a7
        const char expected[] = "void f ( ) "
Packit 2035a7
                                "{"
Packit 2035a7
                                " char p ; p = foo<char> ( ) ; "
Packit 2035a7
                                "} "
Packit 2035a7
                                "char & foo<char> ( ) { static char temp ; return temp ; }";
Packit 2035a7
        ASSERT_EQUALS(expected, tok(code));
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void template20() {
Packit 2035a7
        // Ticket #1788 - the destructor implementation is lost
Packit 2035a7
        const char code[] = "template <class T> class A { public:  ~A(); };\n"
Packit 2035a7
                            "template <class T> A<T>::~A() {}\n"
Packit 2035a7
                            "A<int> a;\n";
Packit 2035a7
Packit 2035a7
        // The expected result..
Packit 2035a7
        const char expected[] = "template < class T > A < T > :: ~ A ( ) { } "  // <- TODO: this should be removed
Packit 2035a7
                                "A<int> a ; "
Packit 2035a7
                                "class A<int> { public: ~ A<int> ( ) ; } ; "
Packit 2035a7
                                "A<int> :: ~ A<int> ( ) { }";
Packit 2035a7
        ASSERT_EQUALS(expected, tok(code));
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void template21() {
Packit 2035a7
        {
Packit 2035a7
            const char code[] = "template <class T> struct Fred { T a; };\n"
Packit 2035a7
                                "Fred<int> fred;";
Packit 2035a7
Packit 2035a7
            const char expected[] = "Fred<int> fred ; "
Packit 2035a7
                                    "struct Fred<int> { int a ; } ;";
Packit 2035a7
Packit 2035a7
            ASSERT_EQUALS(expected, tok(code));
Packit 2035a7
        }
Packit 2035a7
Packit 2035a7
        {
Packit 2035a7
            const char code[] = "template <class T, int sz> struct Fred { T data[sz]; };\n"
Packit 2035a7
                                "Fred<float,4> fred;";
Packit 2035a7
Packit 2035a7
            const char expected[] = "Fred<float,4> fred ; "
Packit 2035a7
                                    "struct Fred<float,4> { float data [ 4 ] ; } ;";
Packit 2035a7
Packit 2035a7
            ASSERT_EQUALS(expected, tok(code));
Packit 2035a7
        }
Packit 2035a7
Packit 2035a7
        {
Packit 2035a7
            const char code[] = "template <class T> struct Fred { Fred(); };\n"
Packit 2035a7
                                "Fred<float> fred;";
Packit 2035a7
Packit 2035a7
            const char expected[] = "Fred<float> fred ; "
Packit 2035a7
                                    "struct Fred<float> { Fred<float> ( ) ; } ;";
Packit 2035a7
Packit 2035a7
            ASSERT_EQUALS(expected, tok(code));
Packit 2035a7
        }
Packit 2035a7
Packit 2035a7
        {
Packit 2035a7
            const char code[] = "template <class T> struct Fred { };\n"
Packit 2035a7
                                "Fred<float> fred1;\n"
Packit 2035a7
                                "Fred<float> fred2;";
Packit 2035a7
Packit 2035a7
            const char expected[] = "Fred<float> fred1 ; "
Packit 2035a7
                                    "Fred<float> fred2 ; "
Packit 2035a7
                                    "struct Fred<float> { } ;";
Packit 2035a7
Packit 2035a7
            ASSERT_EQUALS(expected, tok(code));
Packit 2035a7
        }
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void template22() {
Packit 2035a7
        const char code[] = "template <class T> struct Fred { T a; };\n"
Packit 2035a7
                            "Fred<std::string> fred;";
Packit 2035a7
Packit 2035a7
        const char expected[] = "Fred<std::string> fred ; "
Packit 2035a7
                                "struct Fred<std::string> { std :: string a ; } ;";
Packit 2035a7
Packit 2035a7
        ASSERT_EQUALS(expected, tok(code));
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void template23() {
Packit 2035a7
        const char code[] = "template <class T> void foo() { }\n"
Packit 2035a7
                            "void bar() {\n"
Packit 2035a7
                            "    std::cout << (foo<double>());\n"
Packit 2035a7
                            "}";
Packit 2035a7
Packit 2035a7
        const char expected[] = "void bar ( ) {"
Packit 2035a7
                                " std :: cout << ( foo<double> ( ) ) ; "
Packit 2035a7
                                "} "
Packit 2035a7
                                "void foo<double> ( ) { }";
Packit 2035a7
Packit 2035a7
        ASSERT_EQUALS(expected, tok(code));
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void template24() {
Packit 2035a7
        // #2648
Packit 2035a7
        const char code[] = "template<int n> struct B\n"
Packit 2035a7
                            "{\n"
Packit 2035a7
                            "  int a[n];\n"
Packit 2035a7
                            "};\n"
Packit 2035a7
                            "\n"
Packit 2035a7
                            "template<int x> class bitset: B<sizeof(int)>\n"
Packit 2035a7
                            "{};\n"
Packit 2035a7
                            "\n"
Packit 2035a7
                            "bitset<1> z;";
Packit 2035a7
        const char expected[] = "bitset<1> z ; "
Packit 2035a7
                                "class bitset<1> : B<4> { } ; "
Packit 2035a7
                                "struct B<4> { int a [ 4 ] ; } ;";
Packit 2035a7
        ASSERT_EQUALS(expected, tok(code));
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void template25() {
Packit 2035a7
        const char code[] = "template<int n> struct B\n"
Packit 2035a7
                            "{\n"
Packit 2035a7
                            "  int a[n];\n"
Packit 2035a7
                            "};\n"
Packit 2035a7
                            "\n"
Packit 2035a7
                            "template<int x> class bitset: B<((sizeof(int)) ? : 1)>\n"
Packit 2035a7
                            "{};\n"
Packit 2035a7
                            "\n"
Packit 2035a7
                            "bitset<1> z;";
Packit 2035a7
Packit 2035a7
        const char actual[] = "template < int n > struct B { int a [ n ] ; } ; "
Packit 2035a7
                              "bitset<1> z ; "
Packit 2035a7
                              "class bitset<1> : B < 4 > { } ;";
Packit 2035a7
Packit 2035a7
        const char expected[] = "bitset<1> z ; "
Packit 2035a7
                                "class bitset<1> : B < 4 > { } ; "
Packit 2035a7
                                "struct B < 4 > { int a [ 4 ] ; } ;";
Packit 2035a7
Packit 2035a7
        TODO_ASSERT_EQUALS(expected, actual, tok(code));
Packit 2035a7
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void template26() {
Packit 2035a7
        // #2721
Packit 2035a7
        const char code[] = "template<class T>\n"
Packit 2035a7
                            "class A { public: T x; };\n"
Packit 2035a7
                            "\n"
Packit 2035a7
                            "template<class M>\n"
Packit 2035a7
                            "class C: public A<char[M]> {};\n"
Packit 2035a7
                            "\n"
Packit 2035a7
                            "C<2> a;\n";
Packit 2035a7
        // TODO: expand A also
Packit 2035a7
        ASSERT_EQUALS("template < class T > class A { public: T x ; } ; C<2> a ; class C<2> : public A < char [ 2 ] > { } ;", tok(code));
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void template27() {
Packit 2035a7
        // #3350 - template inside macro call
Packit 2035a7
        const char code[] = "X(template<class T> class Fred);";
Packit 2035a7
        ASSERT_THROW(tok(code), InternalError);
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void template28() {
Packit 2035a7
        // #3226 - inner template
Packit 2035a7
        const char code[] = "template<class A, class B> class Fred {};\n"
Packit 2035a7
                            "Fred<int,Fred<int,int> > x;\n";
Packit 2035a7
        ASSERT_EQUALS("Fred<int,Fred<int,int>> x ; class Fred<int,int> { } ; class Fred<int,Fred<int,int>> { } ;", tok(code));
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void template30() {
Packit 2035a7
        // #3529 - template < template < ..
Packit 2035a7
        const char code[] = "template<template<class> class A, class B> void f(){}";
Packit 2035a7
        ASSERT_EQUALS("template < template < class > class A , class B > void f ( ) { }", tok(code));
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void template31() {
Packit 2035a7
        // #4010 - template reference type
Packit 2035a7
        const char code[] = "template<class T> struct A{}; A<int&> a;";
Packit 2035a7
        ASSERT_EQUALS("A<int&> a ; struct A<int&> { } ;", tok(code));
Packit 2035a7
Packit 2035a7
        // #7409 - rvalue
Packit 2035a7
        const char code2[] = "template<class T> struct A{}; A<int&&> a;";
Packit 2035a7
        ASSERT_EQUALS("A<int&&> a ; struct A<int&&> { } ;", tok(code2));
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void template32() {
Packit 2035a7
        // #3818 - mismatching template not handled well
Packit 2035a7
        const char code[] = "template <class T1, class T2, class T3, class T4 > struct A { };\n"
Packit 2035a7
                            "\n"
Packit 2035a7
                            "template <class T>\n"
Packit 2035a7
                            "struct B\n"
Packit 2035a7
                            "{\n"
Packit 2035a7
                            "    public:\n"
Packit 2035a7
                            "        A < int, Pair<T, int>, int > a;\n"  // mismatching parameters => don't instantiate
Packit 2035a7
                            "};\n"
Packit 2035a7
                            "\n"
Packit 2035a7
                            "B<int> b;\n";
Packit 2035a7
        ASSERT_EQUALS("template < class T1 , class T2 , class T3 , class T4 > struct A { } ; "
Packit 2035a7
                      "B<int> b ; "
Packit 2035a7
                      "struct B<int> { public: A < int , Pair < int , int > , int > a ; } ;", tok(code));
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void template33() {
Packit 2035a7
        {
Packit 2035a7
            // #3818 - inner templates in template instantiation not handled well
Packit 2035a7
            const char code[] = "template<class T> struct A { };\n"
Packit 2035a7
                                "template<class T> struct B { };\n"
Packit 2035a7
                                "template<class T> struct C { A<B<X<T> > > ab; };\n"
Packit 2035a7
                                "C<int> c;";
Packit 2035a7
            ASSERT_EQUALS("C<int> c ; "
Packit 2035a7
                          "struct C<int> { A<B<X<int>>> ab ; } ; "
Packit 2035a7
                          "struct B<X<int>> { } ; "  // <- redundant.. but nevermind
Packit 2035a7
                          "struct A<B<X<int>>> { } ;", tok(code));
Packit 2035a7
        }
Packit 2035a7
Packit 2035a7
        {
Packit 2035a7
            // #4544
Packit 2035a7
            const char code[] = "struct A { };\n"
Packit 2035a7
                                "template<class T> struct B { };\n"
Packit 2035a7
                                "template<class T> struct C { };\n"
Packit 2035a7
                                "C< B > c;";
Packit 2035a7
            ASSERT_EQUALS("struct A { } ; "
Packit 2035a7
                          "template < class T > struct B { } ; "  // <- redundant.. but nevermind
Packit 2035a7
                          "C<B<A>> c ; struct C<B<A>> { } ;",
Packit 2035a7
                          tok(code));
Packit 2035a7
        }
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void template34() {
Packit 2035a7
        // #3706 - namespace => hang
Packit 2035a7
        const char code[] = "namespace abc {\n"
Packit 2035a7
                            "template <typename T> struct X { void f(X<T> &x) {} };\n"
Packit 2035a7
                            "}\n"
Packit 2035a7
                            "template <> int X<int>::Y(0);";
Packit 2035a7
        ASSERT_EQUALS("namespace abc { "
Packit 2035a7
                      "template < typename T > struct X { void f ( X < T > & x ) { } } ; "
Packit 2035a7
                      "} "
Packit 2035a7
                      "template < > int X < int > :: Y ( 0 ) ;", tok(code));
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void template35() { // #4074 - "A<'x'> a;" is not recognized as template instantiation
Packit 2035a7
        const char code[] = "template <char c> class A {};\n"
Packit 2035a7
                            "A <'x'> a;";
Packit 2035a7
        ASSERT_EQUALS("A<'x'> a ; class A<'x'> { } ;", tok(code));
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void template36() { // #4310 - Passing unknown template instantiation as template argument
Packit 2035a7
        const char code[] = "template <class T> struct X { T t; };\n"
Packit 2035a7
                            "template <class C> struct Y { Foo < X< Bar<C> > > _foo; };\n" // <- Bar is unknown
Packit 2035a7
                            "Y<int> bar;";
Packit 2035a7
        ASSERT_EQUALS("Y<int> bar ; "
Packit 2035a7
                      "struct Y<int> { Foo < X<Bar<int>> > _foo ; } ; "
Packit 2035a7
                      "struct X<Bar<int>> { Bar < int > t ; } ;",
Packit 2035a7
                      tok(code));
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void template37() { // #4544 - A<class B> a;
Packit 2035a7
        {
Packit 2035a7
            const char code[] = "class A { };\n"
Packit 2035a7
                                "template<class T> class B {};\n"
Packit 2035a7
                                "B<class A> b1;\n"
Packit 2035a7
                                "B b2;";
Packit 2035a7
            ASSERT_EQUALS("class A { } ; B b1 ; B b2 ; class B { } ;",
Packit 2035a7
                          tok(code));
Packit 2035a7
        }
Packit 2035a7
        {
Packit 2035a7
            const char code[] = "struct A { };\n"
Packit 2035a7
                                "template<class T> class B {};\n"
Packit 2035a7
                                "B<struct A> b1;\n"
Packit 2035a7
                                "B b2;";
Packit 2035a7
            ASSERT_EQUALS("struct A { } ; B b1 ; B b2 ; class B { } ;",
Packit 2035a7
                          tok(code));
Packit 2035a7
        }
Packit 2035a7
        {
Packit 2035a7
            const char code[] = "enum A { };\n"
Packit 2035a7
                                "template<class T> class B {};\n"
Packit 2035a7
                                "B<enum A> b1;\n"
Packit 2035a7
                                "B b2;";
Packit 2035a7
            ASSERT_EQUALS("enum A { } ; B b1 ; B b2 ; class B { } ;",
Packit 2035a7
                          tok(code));
Packit 2035a7
        }
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void template_unhandled() {
Packit 2035a7
        // An unhandled template usage should be simplified..
Packit 2035a7
        ASSERT_EQUALS("x<int> ( ) ;", tok("x<int>();"));
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void template38() { // #4832 - Crash on C++11 right angle brackets
Packit 2035a7
        const char code[] = "template <class T> class A {\n"
Packit 2035a7
                            "  T mT;\n"
Packit 2035a7
                            "public:\n"
Packit 2035a7
                            "  void foo() {}\n"
Packit 2035a7
                            "};\n"
Packit 2035a7
                            "\n"
Packit 2035a7
                            "int main() {\n"
Packit 2035a7
                            "    A<A<BLA>>   gna1;\n"
Packit 2035a7
                            "    A<BLA>      gna2;\n"
Packit 2035a7
                            "}\n";
Packit 2035a7
        tok(code); // Don't crash or freeze
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void template39() { // #4742 - Used to freeze in 1.60
Packit 2035a7
        const char code[] = "template<typename T> struct vector {"
Packit 2035a7
                            "  operator T() const;"
Packit 2035a7
                            "};"
Packit 2035a7
                            "void f() {"
Packit 2035a7
                            "  vector<vector<int>> v;"
Packit 2035a7
                            "  const vector<int> vi = static_cast<vector<int>>(v);"
Packit 2035a7
                            "}";
Packit 2035a7
        tok(code);
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void template40() { // #5055 - false negatives when there is template specialization outside struct
Packit 2035a7
        const char code[] = "struct A {"
Packit 2035a7
                            "  template<typename T> struct X { T t; };"
Packit 2035a7
                            "};"
Packit 2035a7
                            "template<> struct A::X<int> { int *t; };";
Packit 2035a7
        ASSERT_EQUALS("struct A { template < typename T > struct X { T t ; } ; } ;", tok(code));
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void template41() { // #4710 - const in template instantiation not handled perfectly
Packit 2035a7
        const char code1[] = "template<class T> struct X { };\n"
Packit 2035a7
                             "void f(const X<int> x) { }";
Packit 2035a7
        ASSERT_EQUALS("void f ( const X<int> x ) { } struct X<int> { } ;", tok(code1));
Packit 2035a7
Packit 2035a7
        const char code2[] = "template<class T> T f(T t) { return t; }\n"
Packit 2035a7
                             "int x() { return f<int>(123); }";
Packit 2035a7
        ASSERT_EQUALS("int x ( ) { return f<int> ( 123 ) ; } int f<int> ( int t ) { return t ; }", tok(code2));
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void template42() { // #4878 cpcheck aborts in ext-blocks.cpp (clang testcode)
Packit 2035a7
        const char code[] = "template<typename ...Args>\n"
Packit 2035a7
                            "int f0(Args ...args) {\n"
Packit 2035a7
                            "  return ^ {\n"
Packit 2035a7
                            "    return sizeof...(Args);\n"
Packit 2035a7
                            "  }() + ^ {\n"
Packit 2035a7
                            "    return sizeof...(args);\n"
Packit 2035a7
                            "  }();\n"
Packit 2035a7
                            "}";
Packit 2035a7
        tok(code);
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void template43() { // #5097 - Assert due to '>>' in 'B<A<C>>' not being treated as end of template instantation
Packit 2035a7
        const char code[] = "template <typename T> struct C { };"
Packit 2035a7
                            "template <typename T> struct D { static int f() { return C<T>::f(); } };"
Packit 2035a7
                            "template <typename T> inline int f2() { return D<T>::f(); }"
Packit 2035a7
                            "template <typename T> int f1(int x, T *) { int id = f2<T>(); return id; }"
Packit 2035a7
                            "template <> struct C < B < A >> {"
Packit 2035a7
                            "  static int f() {"
Packit 2035a7
                            "    return f1 < B < A >> (0, reinterpret_cast< B *>(E<void *>::Int(-1)));"
Packit 2035a7
                            "  }"
Packit 2035a7
                            "};";
Packit 2035a7
        tok(code); // Don't assert
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void template44() { // #5297
Packit 2035a7
        tok("template<class T> struct StackContainer {"
Packit 2035a7
            "  void foo(int i) {"
Packit 2035a7
            "    if (0 >= 1 && i<0) {}"
Packit 2035a7
            "  }"
Packit 2035a7
            "};"
Packit 2035a7
            "template<class T> class ZContainer : public StackContainer<T> {};"
Packit 2035a7
            "struct FGSTensor {};"
Packit 2035a7
            "class FoldedZContainer : public ZContainer<FGSTensor> {};");
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void template45() { // #5814
Packit 2035a7
        tok("namespace Constants { const int fourtytwo = 42; } "
Packit 2035a7
            "template <class T, int U> struct TypeMath { "
Packit 2035a7
            "  static const int mult = sizeof(T) * U; "
Packit 2035a7
            "}; "
Packit 2035a7
            "template <class T> struct FOO { "
Packit 2035a7
            "  enum { value = TypeMath<T, Constants::fourtytwo>::something }; "
Packit 2035a7
            "};");
Packit 2035a7
        ASSERT_EQUALS("", errout.str());
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void template46() { // #5816
Packit 2035a7
        tok("template<class T, class U> struct A { static const int value = 0; }; "
Packit 2035a7
            "template <class T> struct B { "
Packit 2035a7
            "  enum { value = A<typename T::type, int>::value }; "
Packit 2035a7
            "};");
Packit 2035a7
        ASSERT_EQUALS("", errout.str());
Packit 2035a7
        tok("template <class T, class U> struct A {}; "
Packit 2035a7
            "enum { e = sizeof(A<int, int>) }; "
Packit 2035a7
            "template <class T, class U> struct B {};");
Packit 2035a7
        ASSERT_EQUALS("", errout.str());
Packit 2035a7
        tok("template<class T, class U> struct A { static const int value = 0; }; "
Packit 2035a7
            "template<class T> struct B { typedef int type; }; "
Packit 2035a7
            "template <class T> struct C { "
Packit 2035a7
            "  enum { value = A<typename B<T>::type, int>::value }; "
Packit 2035a7
            "};");
Packit 2035a7
        ASSERT_EQUALS("", errout.str());
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void template47() { // #6023
Packit 2035a7
        tok("template <typename T1, typename T2 = T3<T1> > class C1 {}; "
Packit 2035a7
            "class C2 : public C1<C2> {};");
Packit 2035a7
        ASSERT_EQUALS("", errout.str());
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void template48() { // #6134
Packit 2035a7
        tok("template <int> int f( {  } ); "
Packit 2035a7
            "int foo = f<1>(0);");
Packit 2035a7
        ASSERT_EQUALS("", errout.str());
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void template49() { // #6237
Packit 2035a7
        const char code[] = "template <class T> class Fred { void f(); void g(); };\n"
Packit 2035a7
                            "template <class T> void Fred<T>::f() { }\n"
Packit 2035a7
                            "template <class T> void Fred<T>::g() { }\n"
Packit 2035a7
                            "template void Fred<float>::f();\n"
Packit 2035a7
                            "template void Fred<int>::g();\n";
Packit 2035a7
Packit 2035a7
        const char expected[] = "template < class T > void Fred < T > :: f ( ) { } "
Packit 2035a7
                                "template < class T > void Fred < T > :: g ( ) { } "
Packit 2035a7
                                "template void Fred<float> :: f ( ) ; "
Packit 2035a7
                                "template void Fred<int> :: g ( ) ; "
Packit 2035a7
                                "class Fred<float> { void f ( ) ; void g ( ) ; } ; "
Packit 2035a7
                                "Fred<float> :: f ( ) { } "
Packit 2035a7
                                "Fred<float> :: g ( ) { } "
Packit 2035a7
                                "class Fred<int> { void f ( ) ; void g ( ) ; } ; "
Packit 2035a7
                                "Fred<int> :: f ( ) { } "
Packit 2035a7
                                "Fred<int> :: g ( ) { }";
Packit 2035a7
Packit 2035a7
        ASSERT_EQUALS(expected, tok(code));
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void template50() { // #4272
Packit 2035a7
        const char code[] = "template <class T> class Fred { void f(); };\n"
Packit 2035a7
                            "template <class T> void Fred<T>::f() { }\n"
Packit 2035a7
                            "template<> void Fred<float>::f() { }\n"
Packit 2035a7
                            "template<> void Fred<int>::g() { }\n";
Packit 2035a7
Packit 2035a7
        const char expected[] = "template < class T > class Fred { void f ( ) ; } ; "
Packit 2035a7
                                "template < class T > void Fred < T > :: f ( ) { } "
Packit 2035a7
                                "template < > void Fred < float > :: f ( ) { } "
Packit 2035a7
                                "template < > void Fred < int > :: g ( ) { }";
Packit 2035a7
Packit 2035a7
        ASSERT_EQUALS(expected, tok(code));
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void template51() { // #6172
Packit 2035a7
        tok("template<int N, int ... M> struct A { "
Packit 2035a7
            "  static void foo() { "
Packit 2035a7
            "    int i = N; "
Packit 2035a7
            "  } "
Packit 2035a7
            "}; "
Packit 2035a7
            "void bar() { "
Packit 2035a7
            "  A<0>::foo(); "
Packit 2035a7
            "}");
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void template52() { // #6437
Packit 2035a7
        tok("template <int value> int sum() { "
Packit 2035a7
            "  return value + sum<value/2>(); "
Packit 2035a7
            "} "
Packit 2035a7
            "template<int x, int y> int calculate_value() { "
Packit 2035a7
            "  return sum<x - y>(); "
Packit 2035a7
            "} "
Packit 2035a7
            "int value = calculate_value<1,1>();");
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void template53() { // #4335
Packit 2035a7
        tok("template<int N> struct Factorial { "
Packit 2035a7
            "  enum { value = N * Factorial<N - 1>::value }; "
Packit 2035a7
            "};"
Packit 2035a7
            "template <> struct Factorial<0> { "
Packit 2035a7
            "  enum { value = 1 }; "
Packit 2035a7
            "};"
Packit 2035a7
            "const int x = Factorial<4>::value;", /*simplify=*/true, /*debugwarnings=*/true);
Packit 2035a7
        ASSERT_EQUALS("", errout.str());
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void template54() { // #6587
Packit 2035a7
        tok("template<typename _Tp> _Tp* fn(); "
Packit 2035a7
            "template <class T> struct A { "
Packit 2035a7
            "  template <class U, class S = decltype(fn<T>())> "
Packit 2035a7
            "  struct B { }; "
Packit 2035a7
            "}; "
Packit 2035a7
            "A<int> a;");
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void template55() { // #6604
Packit 2035a7
        // Avoid constconstconst in macro instantiations
Packit 2035a7
        ASSERT_EQUALS(
Packit 2035a7
            "template < class T > class AtSmartPtr : public ConstCastHelper < AtSmartPtr < const T > , T > { "
Packit 2035a7
            "friend struct ConstCastHelper < AtSmartPtr < const T > , T > ; "
Packit 2035a7
            "AtSmartPtr ( const AtSmartPtr < T > & r ) ; "
Packit 2035a7
            "} ;",
Packit 2035a7
            tok("template<class T> class AtSmartPtr : public ConstCastHelper<AtSmartPtr<const T>, T>\n"
Packit 2035a7
                "{\n"
Packit 2035a7
                "    friend struct ConstCastHelper<AtSmartPtr<const T>, T>;\n"
Packit 2035a7
                "    AtSmartPtr(const AtSmartPtr<T>& r);\n"
Packit 2035a7
                "};"));
Packit 2035a7
Packit 2035a7
        // Similar problem can also happen with ...
Packit 2035a7
        ASSERT_EQUALS(
Packit 2035a7
            "A<int> a ( 0 ) ; struct A<int> { "
Packit 2035a7
            "A<int> ( int * p ) { p ; } "
Packit 2035a7
            "} ; "
Packit 2035a7
            "struct A<int...> { "
Packit 2035a7
            "A<int...> ( int * p ) { "
Packit 2035a7
            "p ; "
Packit 2035a7
            "} } ;",
Packit 2035a7
            tok("template <typename... T> struct A\n"
Packit 2035a7
                "{\n"
Packit 2035a7
                "    A(T* p) {\n"
Packit 2035a7
                "        (A<T...>*)(p);\n"
Packit 2035a7
                "    }\n"
Packit 2035a7
                "};\n"
Packit 2035a7
                "A<int> a(0);"));
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void template56() { // #7117
Packit 2035a7
        tok("template<bool B> struct Foo { "
Packit 2035a7
            "  std::array<int, B ? 1 : 2> mfoo; "
Packit 2035a7
            "}; "
Packit 2035a7
            "void foo() { "
Packit 2035a7
            "  Foo<true> myFoo; "
Packit 2035a7
            "}", /*simplify=*/true, /*debugwarnings=*/true);
Packit 2035a7
        ASSERT_EQUALS("", errout.str());
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void template57() { // #7891
Packit 2035a7
        const char code[] = "template<class T> struct Test { Test(T); };\n"
Packit 2035a7
                            "Test<unsigned long> test( 0 );";
Packit 2035a7
        const char exp [] = "Test<unsignedlong> test ( 0 ) ; "
Packit 2035a7
                            "struct Test<unsignedlong> { Test<unsignedlong> ( long ) ; } ;";
Packit 2035a7
        ASSERT_EQUALS(exp, tok(code));
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void template58() { // #6021
Packit 2035a7
        const char code[] = "template <typename A>\n"
Packit 2035a7
                            "void TestArithmetic() {\n"
Packit 2035a7
                            "  x(1 * CheckedNumeric());\n"
Packit 2035a7
                            "}\n"
Packit 2035a7
                            "void foo() {\n"
Packit 2035a7
                            "  TestArithmetic<int>();\n"
Packit 2035a7
                            "}";
Packit 2035a7
        const char exp[] = "void foo ( ) {"
Packit 2035a7
                           " TestArithmetic<int> ( ) ; "
Packit 2035a7
                           "} "
Packit 2035a7
                           "void TestArithmetic<int> ( ) {"
Packit 2035a7
                           " x ( CheckedNumeric < int > ( ) ) ; "
Packit 2035a7
                           "}";
Packit 2035a7
        ASSERT_EQUALS(exp, tok(code));
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void template59() { // #8051
Packit 2035a7
        const char code[] = "template<int N>\n"
Packit 2035a7
                            "struct Factorial {\n"
Packit 2035a7
                            "    enum FacHelper { value = N * Factorial<N - 1>::value };\n"
Packit 2035a7
                            "};\n"
Packit 2035a7
                            "template <>\n"
Packit 2035a7
                            "struct Factorial<0> {\n"
Packit 2035a7
                            "    enum FacHelper { value = 1 };\n"
Packit 2035a7
                            "};\n"
Packit 2035a7
                            "template<int DiagonalDegree>\n"
Packit 2035a7
                            "int diagonalGroupTest() {\n"
Packit 2035a7
                            "    return Factorial<DiagonalDegree>::value;\n"
Packit 2035a7
                            "}\n"
Packit 2035a7
                            "int main () {\n"
Packit 2035a7
                            "    return diagonalGroupTest<4>();\n"
Packit 2035a7
                            "}";
Packit 2035a7
        const char exp[] = "struct Factorial<0> { enum FacHelper { value = 1 } ; } ; "
Packit 2035a7
                           "int main ( ) { return diagonalGroupTest<4> ( ) ; } "
Packit 2035a7
                           "int diagonalGroupTest<4> ( ) { return Factorial<4> :: value ; } "
Packit 2035a7
                           "struct Factorial<4> { enum FacHelper { value = 4 * Factorial<3> :: value } ; } ; "
Packit 2035a7
                           "struct Factorial<3> { enum FacHelper { value = 3 * Factorial<2> :: value } ; } ; "
Packit 2035a7
                           "struct Factorial<2> { enum FacHelper { value = 2 * Factorial<1> :: value } ; } ; "
Packit 2035a7
                           "struct Factorial<1> { enum FacHelper { value = Factorial < 0 > :: value } ; } ;";
Packit 2035a7
        ASSERT_EQUALS(exp, tok(code));
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void template60() { // Extracted from Clang testfile
Packit 2035a7
        const char code[] = "template <typename T> struct S { typedef int type; };\n"
Packit 2035a7
                            "template <typename T> void f() {}\n"
Packit 2035a7
                            "template <typename T> void h() { f<typename S<T>::type(0)>(); }\n"
Packit 2035a7
                            "\n"
Packit 2035a7
                            "void j() { h<int>(); }";
Packit 2035a7
        const char exp[] = "template < typename T > void f ( ) { } " // <- TODO: This template is not expanded
Packit 2035a7
                           "void j ( ) { h<int> ( ) ; } "
Packit 2035a7
                           "void h<int> ( ) { f < S<int> :: type ( 0 ) > ( ) ; } "
Packit 2035a7
                           "struct S<int> { } ;";
Packit 2035a7
        ASSERT_EQUALS(exp, tok(code));
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void template61() { // hang in daca, code extracted from kodi
Packit 2035a7
        const char code[] = "template <typename T> struct Foo {};\n"
Packit 2035a7
                            "template <typename T> struct Bar {\n"
Packit 2035a7
                            "  void f1(Bar<T> x) {}\n"
Packit 2035a7
                            "  Foo<Bar<T>> f2() { }\n"
Packit 2035a7
                            "};\n"
Packit 2035a7
                            "Bar<int> c;";
Packit 2035a7
        const char exp[] = "Bar<int> c ; "
Packit 2035a7
                           "struct Bar<int> {"
Packit 2035a7
                           " void f1 ( Bar<int> x ) { }"
Packit 2035a7
                           " Foo<Bar<int>> f2 ( ) { } "
Packit 2035a7
                           "} ; "
Packit 2035a7
                           "struct Foo<Bar<int>> { } ;";
Packit 2035a7
        ASSERT_EQUALS(exp, tok(code));
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void template62() { // #8314
Packit 2035a7
        const char code[] = "template <class T> struct C1 {};\n"
Packit 2035a7
                            "template <class T> void f() { x = y ? C1<int>::allocate(1) : 0; }\n"
Packit 2035a7
                            "template <class T, unsigned S> class C3 {};\n"
Packit 2035a7
                            "template <class T, unsigned S> C3<T, S>::C3(const C3<T, S> &v) { C1<T *> c1; }\n"
Packit 2035a7
                            "C3<int,6> c3;";
Packit 2035a7
        const char exp[] = "template < class T > void f ( ) { x = y ? C1 < int > :: allocate ( 1 ) : 0 ; } "
Packit 2035a7
                           "template < class T , int S > C3 < T , S > :: C3 ( const C3 < T , S > & v ) { C1 < T * > c1 ; } "
Packit 2035a7
                           "C3<int,6> c3 ; "
Packit 2035a7
                           "class C3<int,6> { } ; "
Packit 2035a7
                           "C3<int,6> :: C3<int,6> ( const C3<int,6> & v ) { C1<int*> c1 ; } "
Packit 2035a7
                           "struct C1<int*> { } ;";
Packit 2035a7
        ASSERT_EQUALS(exp, tok(code));
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void template_specialization_1() {  // #7868 - template specialization template <typename T> struct S<C<T>> {..};
Packit 2035a7
        const char code[] = "template <typename T> struct C {};\n"
Packit 2035a7
                            "template <typename T> struct S {a};\n"
Packit 2035a7
                            "template <typename T> struct S<C<T>> {b};\n"
Packit 2035a7
                            "S<int> s;";
Packit 2035a7
        const char exp[]  = "template < typename T > struct C { } ; template < typename T > struct S < C < T > > { b } ; S<int> s ; struct S<int> { a } ;";
Packit 2035a7
        ASSERT_EQUALS(exp, tok(code));
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void template_specialization_2() {  // #7868 - template specialization template <typename T> struct S<C<T>> {..};
Packit 2035a7
        const char code[] = "template <typename T> struct C {};\n"
Packit 2035a7
                            "template <typename T> struct S {a};\n"
Packit 2035a7
                            "template <typename T> struct S<C<T>> {b};\n"
Packit 2035a7
                            "S<C<int>> s;";
Packit 2035a7
        const char exp[]  = "template < typename T > struct C { } ; template < typename T > struct S { a } ; S<C<int>> s ; struct S<C<int>> { b } ;";
Packit 2035a7
        ASSERT_EQUALS(exp, tok(code));
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void template_enum() {
Packit 2035a7
        const char code1[] = "template <class T>\n"
Packit 2035a7
                             "struct Unconst {\n"
Packit 2035a7
                             "    typedef T type;\n"
Packit 2035a7
                             "};\n"
Packit 2035a7
                             "template <class T>\n"
Packit 2035a7
                             "struct Unconst<const T> {\n"
Packit 2035a7
                             "    typedef T type;\n"
Packit 2035a7
                             "};\n"
Packit 2035a7
                             "template <class T>\n"
Packit 2035a7
                             "struct Unconst<const T&> {\n"
Packit 2035a7
                             "    typedef T& type;\n"
Packit 2035a7
                             "};\n"
Packit 2035a7
                             "template <class T>\n"
Packit 2035a7
                             "struct Unconst<T* const> {\n"
Packit 2035a7
                             "    typedef T* type;\n"
Packit 2035a7
                             "};\n"
Packit 2035a7
                             "template <class T1, class T2>\n"
Packit 2035a7
                             "struct type_equal {\n"
Packit 2035a7
                             "    enum {  value = 0   };\n"
Packit 2035a7
                             "};\n"
Packit 2035a7
                             "template <class T>\n"
Packit 2035a7
                             "struct type_equal<T, T> {\n"
Packit 2035a7
                             "    enum {  value = 1   };\n"
Packit 2035a7
                             "};\n"
Packit 2035a7
                             "template<class T>\n"
Packit 2035a7
                             "struct template_is_const\n"
Packit 2035a7
                             "{\n"
Packit 2035a7
                             "    enum {value = !type_equal<T, typename Unconst<T>::type>::value  };\n"
Packit 2035a7
                             "};";
Packit 2035a7
        const char exp1[] = "template < class T > struct Unconst { } ; "
Packit 2035a7
                            "template < class T > struct Unconst < const T > { } ; "
Packit 2035a7
                            "template < class T > struct Unconst < const T & > { } ; "
Packit 2035a7
                            "template < class T > struct Unconst < T * const > { } ; "
Packit 2035a7
                            "template < class T1 , class T2 > struct type_equal { enum Anonymous0 { value = 0 } ; } ; "
Packit 2035a7
                            "template < class T > struct type_equal < T , T > { enum Anonymous1 { value = 1 } ; } ; "
Packit 2035a7
                            "template < class T > struct template_is_const { enum Anonymous2 { value = ! type_equal < T , Unconst < T > :: type > :: value } ; } ;";
Packit 2035a7
        ASSERT_EQUALS(exp1, tok(code1));
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void template_default_parameter() {
Packit 2035a7
        {
Packit 2035a7
            const char code[] = "template <class T, int n=3>\n"
Packit 2035a7
                                "class A\n"
Packit 2035a7
                                "{ T ar[n]; };\n"
Packit 2035a7
                                "\n"
Packit 2035a7
                                "void f()\n"
Packit 2035a7
                                "{\n"
Packit 2035a7
                                "    A<int,2> a1;\n"
Packit 2035a7
                                "    A<int> a2;\n"
Packit 2035a7
                                "}\n";
Packit 2035a7
Packit 2035a7
            // The expected result..
Packit 2035a7
            const char expected[] = "void f ( ) "
Packit 2035a7
                                    "{"
Packit 2035a7
                                    " A<int,2> a1 ;"
Packit 2035a7
                                    " A<int,3> a2 ; "
Packit 2035a7
                                    "} "
Packit 2035a7
                                    "class A<int,2> "
Packit 2035a7
                                    "{ int ar [ 2 ] ; } ; "
Packit 2035a7
                                    "class A<int,3> "
Packit 2035a7
                                    "{ int ar [ 3 ] ; } ;";
Packit 2035a7
            ASSERT_EQUALS(expected, tok(code));
Packit 2035a7
        }
Packit 2035a7
        {
Packit 2035a7
            const char code[] = "template <class T, int n1=3, int n2=2>\n"
Packit 2035a7
                                "class A\n"
Packit 2035a7
                                "{ T ar[n1+n2]; };\n"
Packit 2035a7
                                "\n"
Packit 2035a7
                                "void f()\n"
Packit 2035a7
                                "{\n"
Packit 2035a7
                                "    A<int> a1;\n"
Packit 2035a7
                                "    A<int,3> a2;\n"
Packit 2035a7
                                "}\n";
Packit 2035a7
Packit 2035a7
            // The expected result..
Packit 2035a7
            const char expected[] = "void f ( ) "
Packit 2035a7
                                    "{"
Packit 2035a7
                                    " A<int,3,2> a1 ;"
Packit 2035a7
                                    " A<int,3,2> a2 ; "
Packit 2035a7
                                    "} "
Packit 2035a7
                                    "class A<int,3,2> "
Packit 2035a7
                                    "{ int ar [ 5 ] ; } ;";
Packit 2035a7
            ASSERT_EQUALS(expected, tok(code));
Packit 2035a7
        }
Packit 2035a7
        {
Packit 2035a7
            const char code[] = "template <class T, int n=3>\n"
Packit 2035a7
                                "class A\n"
Packit 2035a7
                                "{ T ar[n]; };\n"
Packit 2035a7
                                "\n"
Packit 2035a7
                                "void f()\n"
Packit 2035a7
                                "{\n"
Packit 2035a7
                                "    A<int,(int)2> a1;\n"
Packit 2035a7
                                "    A<int> a2;\n"
Packit 2035a7
                                "}\n";
Packit 2035a7
Packit 2035a7
            const char wanted[] = "template < class T , int n >"
Packit 2035a7
                                  " class A"
Packit 2035a7
                                  " { T ar [ n ] ; } ;"
Packit 2035a7
                                  " void f ( )"
Packit 2035a7
                                  " {"
Packit 2035a7
                                  " A<int,(int)2> a1 ;"
Packit 2035a7
                                  " A<int,3> a2 ;"
Packit 2035a7
                                  " }"
Packit 2035a7
                                  " class A<int,2>"
Packit 2035a7
                                  " { int ar [ 2 ] ; }"
Packit 2035a7
                                  " class A<int,3>"
Packit 2035a7
                                  " { int ar [ 3 ] ; }";
Packit 2035a7
Packit 2035a7
            const char current[] = "void f ( ) "
Packit 2035a7
                                   "{ "
Packit 2035a7
                                   "A < int , ( int ) 2 > a1 ; "
Packit 2035a7
                                   "A<int,3> a2 ; "
Packit 2035a7
                                   "} "
Packit 2035a7
                                   "class A<int,3> "
Packit 2035a7
                                   "{ int ar [ 3 ] ; } ;";
Packit 2035a7
            TODO_ASSERT_EQUALS(wanted, current, tok(code));
Packit 2035a7
        }
Packit 2035a7
        {
Packit 2035a7
            const char code[] = "class A { }; "
Packit 2035a7
                                "template<class T> class B { }; "
Packit 2035a7
                                "template<class T1, class T2 = B<T1>> class C { }; "
Packit 2035a7
                                "template<class T1 = A, typename T2 = B<A>> class D { };";
Packit 2035a7
            ASSERT_EQUALS("class A { } ; "
Packit 2035a7
                          "template < class T > class B { } ; "
Packit 2035a7
                          "template < class T1 , class T2 = B < T1 > > class C { } ; "
Packit 2035a7
                          "template < class T1 = A , typename T2 = B < A > > class D { } ;", tok(code));
Packit 2035a7
        }
Packit 2035a7
        {
Packit 2035a7
            // #7548
Packit 2035a7
            const char code[] = "template<class T, class U> class DefaultMemory {}; "
Packit 2035a7
                                "template<class Key, class Val, class Mem=DefaultMemory<Key,Val> > class thv_table_c  {}; "
Packit 2035a7
                                "thv_table_c<void *,void *> id_table_m;";
Packit 2035a7
            const char exp [] = "template < class T , class U > class DefaultMemory { } ; "
Packit 2035a7
                                "thv_table_c<void * , void * , DefaultMemory < void * , void *>> id_table_m ; "
Packit 2035a7
                                "class thv_table_c<void * , void * , DefaultMemory < void * , void * >> { } ;";
Packit 2035a7
            const char curr[] = "template < class T , class U > class DefaultMemory { } ; "
Packit 2035a7
                                "thv_table_c<void*,void*,DefaultMemory<Key,Val>> id_table_m ; "
Packit 2035a7
                                "class thv_table_c<void*,void*,DefaultMemory<Key,Val>> { } ;";
Packit 2035a7
            TODO_ASSERT_EQUALS(exp, curr, tok(code));
Packit 2035a7
        }
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void template_default_type() {
Packit 2035a7
        const char code[] = "template <typename T, typename U=T>\n"
Packit 2035a7
                            "class A\n"
Packit 2035a7
                            "{\n"
Packit 2035a7
                            "public:\n"
Packit 2035a7
                            "  void foo() {\n"
Packit 2035a7
                            "    int a;\n"
Packit 2035a7
                            "    a = static_cast<U>(a);\n"
Packit 2035a7
                            "  }\n"
Packit 2035a7
                            "};\n"
Packit 2035a7
                            "\n"
Packit 2035a7
                            "template <typename T>\n"
Packit 2035a7
                            "class B\n"
Packit 2035a7
                            "{\n"
Packit 2035a7
                            "protected:\n"
Packit 2035a7
                            "  A<int> a;\n"
Packit 2035a7
                            "};\n"
Packit 2035a7
                            "\n"
Packit 2035a7
                            "class C\n"
Packit 2035a7
                            "  : public B<int>\n"
Packit 2035a7
                            "{\n"
Packit 2035a7
                            "};\n";
Packit 2035a7
Packit 2035a7
        tok(code);
Packit 2035a7
Packit 2035a7
        //ASSERT_EQUALS("[file1.cpp:15]: (error) Internal error: failed to instantiate template. The checking continues anyway.\n", errout.str());
Packit 2035a7
        ASSERT_EQUALS("", errout.str());
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void template_typename() {
Packit 2035a7
        {
Packit 2035a7
            const char code[] = "template <class T>\n"
Packit 2035a7
                                "void foo(typename T::t *)\n"
Packit 2035a7
                                "{ }";
Packit 2035a7
Packit 2035a7
            // The expected result..
Packit 2035a7
            const char expected[] = "template < class T > void foo ( T :: t * ) { }";
Packit 2035a7
            ASSERT_EQUALS(expected, tok(code));
Packit 2035a7
        }
Packit 2035a7
Packit 2035a7
        {
Packit 2035a7
            const char code[] = "void f() {\n"
Packit 2035a7
                                "    x(sizeof typename);\n"
Packit 2035a7
                                "    type = 0;\n"
Packit 2035a7
                                "}";
Packit 2035a7
Packit 2035a7
            ASSERT_EQUALS("void f ( ) { x ( sizeof ( typename ) ) ; type = 0 ; }", tok(code));
Packit 2035a7
        }
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void template_constructor() {
Packit 2035a7
        // #3152 - if template constructor is removed then there might be
Packit 2035a7
        //         "no constructor" false positives
Packit 2035a7
        const char code[] = "class Fred {\n"
Packit 2035a7
                            "    template<class T> explicit Fred(T t) { }\n"
Packit 2035a7
                            "}";
Packit 2035a7
        ASSERT_EQUALS("class Fred { template < class T > explicit Fred ( T t ) { } }", tok(code));
Packit 2035a7
Packit 2035a7
        // #3532
Packit 2035a7
        const char code2[] = "class Fred {\n"
Packit 2035a7
                             "    template<class T> Fred(T t) { }\n"
Packit 2035a7
                             "}";
Packit 2035a7
        ASSERT_EQUALS("class Fred { template < class T > Fred ( T t ) { } }", tok(code2));
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void syntax_error_templates_1() {
Packit 2035a7
        // ok code.. using ">" for a comparison
Packit 2035a7
        tok("x<y>z> xyz;\n");
Packit 2035a7
        ASSERT_EQUALS("", errout.str());
Packit 2035a7
Packit 2035a7
        // ok code
Packit 2035a7
        tok("template<class T> operator<(T a, T b) { }\n");
Packit 2035a7
        ASSERT_EQUALS("", errout.str());
Packit 2035a7
Packit 2035a7
        // ok code (ticket #1984)
Packit 2035a7
        tok("void f(a) int a;\n"
Packit 2035a7
            "{ ;x
Packit 2035a7
        ASSERT_EQUALS("", errout.str());
Packit 2035a7
Packit 2035a7
        // ok code (ticket #1985)
Packit 2035a7
        tok("void f()\n"
Packit 2035a7
            "try { ;x
Packit 2035a7
        ASSERT_EQUALS("", errout.str());
Packit 2035a7
Packit 2035a7
        // ok code (ticket #3183)
Packit 2035a7
        tok("MACRO(({ i < x }))");
Packit 2035a7
        ASSERT_EQUALS("", errout.str());
Packit 2035a7
Packit 2035a7
        // bad code.. missing ">"
Packit 2035a7
        ASSERT_THROW(tok("x<y<int> xyz;\n"), InternalError);
Packit 2035a7
Packit 2035a7
        // bad code
Packit 2035a7
        ASSERT_THROW(tok("typedef\n"
Packit 2035a7
                         "    typename boost::mpl::if_c<\n"
Packit 2035a7
                         "          _visitableIndex < boost::mpl::size< typename _Visitables::ConcreteVisitables >::value\n"
Packit 2035a7
                         "          , ConcreteVisitable\n"
Packit 2035a7
                         "          , Dummy< _visitableIndex >\n"
Packit 2035a7
                         "    >::type ConcreteVisitableOrDummy;\n"), InternalError);
Packit 2035a7
Packit 2035a7
        // code is ok, don't show syntax error
Packit 2035a7
        tok("struct A {int a;int b};\n"
Packit 2035a7
            "class Fred {"
Packit 2035a7
            "public:\n"
Packit 2035a7
            "    Fred() : a({1,2}) {\n"
Packit 2035a7
            "        for (int i=0;i<6;i++);\n" // <- no syntax error
Packit 2035a7
            "    }\n"
Packit 2035a7
            "private:\n"
Packit 2035a7
            "    A a;\n"
Packit 2035a7
            "};\n");
Packit 2035a7
        ASSERT_EQUALS("", errout.str());
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void template_member_ptr() { // Ticket #5786
Packit 2035a7
        tok("struct A {}; "
Packit 2035a7
            "struct B { "
Packit 2035a7
            "template <void (A::*)() const> struct BB {}; "
Packit 2035a7
            "template <bool BT> static bool foo(int) { return true; } "
Packit 2035a7
            "void bar() { bool b = foo<true>(0); }"
Packit 2035a7
            "};");
Packit 2035a7
        tok("struct A {}; "
Packit 2035a7
            "struct B { "
Packit 2035a7
            "template <void (A::*)() volatile> struct BB {}; "
Packit 2035a7
            "template <bool BT> static bool foo(int) { return true; } "
Packit 2035a7
            "void bar() { bool b = foo<true>(0); }"
Packit 2035a7
            "};");
Packit 2035a7
        tok("struct A {}; "
Packit 2035a7
            "struct B { "
Packit 2035a7
            "template <void (A::*)() const volatile> struct BB {}; "
Packit 2035a7
            "template <bool BT> static bool foo(int) { return true; } "
Packit 2035a7
            "void bar() { bool b = foo<true>(0); }"
Packit 2035a7
            "};");
Packit 2035a7
        tok("struct A {}; "
Packit 2035a7
            "struct B { "
Packit 2035a7
            "template <void (A::*)() volatile const> struct BB {}; "
Packit 2035a7
            "template <bool BT> static bool foo(int) { return true; } "
Packit 2035a7
            "void bar() { bool b = foo<true>(0); }"
Packit 2035a7
            "};");
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void template_namespace_1() {
Packit 2035a7
        // #6570
Packit 2035a7
        const char code[] = "namespace {\n"
Packit 2035a7
                            "  template<class T> void Fred(T value) { }\n"
Packit 2035a7
                            "}\n"
Packit 2035a7
                            "Fred<int>(123);";
Packit 2035a7
        ASSERT_EQUALS("namespace { } "
Packit 2035a7
                      "Fred<int> ( 123 ) ; "
Packit 2035a7
                      "void Fred<int> ( int value ) { }", tok(code));
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void template_namespace_2() {
Packit 2035a7
        // #8283
Packit 2035a7
        const char code[] = "namespace X {\n"
Packit 2035a7
                            "  template<class T> struct S { };\n"
Packit 2035a7
                            "}\n"
Packit 2035a7
                            "X::S<int> s;";
Packit 2035a7
        ASSERT_EQUALS("X::S<int> s ; "
Packit 2035a7
                      "struct X::S<int> { } ;", tok(code));
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void template_namespace_3() {
Packit 2035a7
        const char code[] = "namespace test16 {\n"
Packit 2035a7
                            "  template <class T> struct foo {\n"
Packit 2035a7
                            "    static void *bar();\n"
Packit 2035a7
                            "  };\n"
Packit 2035a7
                            "  void *test() { return foo<int>::bar(); }\n"
Packit 2035a7
                            "}";
Packit 2035a7
        ASSERT_EQUALS("namespace test16 {"
Packit 2035a7
                      " void * test ( ) {"
Packit 2035a7
                      " return test16::foo<int> :: bar ( ) ;"
Packit 2035a7
                      " } "
Packit 2035a7
                      "} "
Packit 2035a7
                      "struct test16::foo<int> {"
Packit 2035a7
                      " static void * bar ( ) ; "
Packit 2035a7
                      "} ;", tok(code));
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void template_namespace_4() {
Packit 2035a7
        const char code[] = "namespace foo {\n"
Packit 2035a7
                            "  template<class T> class A { void dostuff() {} };\n"
Packit 2035a7
                            "  struct S : public A<int> {\n"
Packit 2035a7
                            "    void f() {\n"
Packit 2035a7
                            "      A<int>::dostuff();\n"
Packit 2035a7
                            "    }\n"
Packit 2035a7
                            "  };\n"
Packit 2035a7
                            "}";
Packit 2035a7
        ASSERT_EQUALS("namespace foo {"
Packit 2035a7
                      " struct S : public foo::A<int> {"
Packit 2035a7
                      " void f ( ) {"
Packit 2035a7
                      " foo::A<int> :: dostuff ( ) ;"
Packit 2035a7
                      " }"
Packit 2035a7
                      " } ; "
Packit 2035a7
                      "} "
Packit 2035a7
                      "class foo::A<int> { void dostuff ( ) { } } ;", tok(code));
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void template_namespace_5() {
Packit 2035a7
        const char code[] = "template<class C> struct S {};\n"
Packit 2035a7
                            "namespace X { S<int> s; }";
Packit 2035a7
        ASSERT_EQUALS("namespace X { S<int> s ; } struct S<int> { } ;", tok(code));
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    unsigned int templateParameters(const char code[]) {
Packit 2035a7
        Tokenizer tokenizer(&settings, this);
Packit 2035a7
Packit 2035a7
        std::istringstream istr(code);
Packit 2035a7
        tokenizer.tokenize(istr, "test.cpp", "");
Packit 2035a7
Packit 2035a7
        return TemplateSimplifier::templateParameters(tokenizer.tokens()->next());
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void templateParameters() {
Packit 2035a7
        // Test that the function TemplateSimplifier::templateParameters works
Packit 2035a7
        ASSERT_EQUALS(1U, templateParameters("X<struct C> x;"));
Packit 2035a7
        ASSERT_EQUALS(1U, templateParameters("X<union C> x;"));
Packit 2035a7
        ASSERT_EQUALS(1U, templateParameters("X<const int> x;"));
Packit 2035a7
        ASSERT_EQUALS(1U, templateParameters("X<int const *> x;"));
Packit 2035a7
        ASSERT_EQUALS(1U, templateParameters("X<const struct C> x;"));
Packit 2035a7
        ASSERT_EQUALS(0U, templateParameters("X<len>>x;"));
Packit 2035a7
        ASSERT_EQUALS(1U, templateParameters("X<typename> x;"));
Packit 2035a7
        ASSERT_EQUALS(0U, templateParameters("X<...> x;"));
Packit 2035a7
        ASSERT_EQUALS(0U, templateParameters("X<class T...> x;")); // Invalid syntax
Packit 2035a7
        ASSERT_EQUALS(1U, templateParameters("X<class... T> x;"));
Packit 2035a7
        ASSERT_EQUALS(0U, templateParameters("X<class, typename T...> x;")); // Invalid syntax
Packit 2035a7
        ASSERT_EQUALS(2U, templateParameters("X<class, typename... T> x;"));
Packit 2035a7
        ASSERT_EQUALS(2U, templateParameters("X<int(&)(), class> x;"));
Packit 2035a7
        ASSERT_EQUALS(3U, templateParameters("X<char, int(*)(), bool> x;"));
Packit 2035a7
        TODO_ASSERT_EQUALS(1U, 0U, templateParameters("X<int...> x;")); // Mishandled valid syntax
Packit 2035a7
        TODO_ASSERT_EQUALS(2U, 0U, templateParameters("X<class, typename...> x;")); // Mishandled valid syntax
Packit 2035a7
        ASSERT_EQUALS(2U, templateParameters("X<1, T> x;"));
Packit 2035a7
        ASSERT_EQUALS(1U, templateParameters("X x;"));
Packit 2035a7
        ASSERT_EQUALS(2U, templateParameters("X<int, i>=0> x;"));
Packit 2035a7
        ASSERT_EQUALS(3U, templateParameters("X<int, i>=0, i - 2> x;"));
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    // Helper function to unit test TemplateSimplifier::getTemplateNamePosition
Packit 2035a7
    int templateNamePositionHelper(const char code[], unsigned offset = 0, bool onlyCreateTokens = false) {
Packit 2035a7
        Tokenizer tokenizer(&settings, this);
Packit 2035a7
Packit 2035a7
        std::istringstream istr(code);
Packit 2035a7
        if (onlyCreateTokens)
Packit 2035a7
            tokenizer.createTokens(istr, "test.cpp");
Packit 2035a7
        else
Packit 2035a7
            tokenizer.tokenize(istr, "test.cpp", emptyString);
Packit 2035a7
Packit 2035a7
        const Token *_tok = tokenizer.tokens();
Packit 2035a7
        for (unsigned i = 0 ; i < offset ; ++i)
Packit 2035a7
            _tok = _tok->next();
Packit 2035a7
        return TemplateSimplifier::getTemplateNamePosition(_tok);
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void templateNamePosition() {
Packit 2035a7
        // Template class
Packit 2035a7
        ASSERT_EQUALS(2, templateNamePositionHelper("template<class T> class A {};", 4));
Packit 2035a7
        ASSERT_EQUALS(2, templateNamePositionHelper("template<class T> struct A {};", 4));
Packit 2035a7
        ASSERT_EQUALS(2, templateNamePositionHelper("template<class T> class A : B {};", 4));
Packit 2035a7
        ASSERT_EQUALS(2, templateNamePositionHelper("template<class T> struct A : B {};", 4));
Packit 2035a7
        // Template function definitions
Packit 2035a7
        ASSERT_EQUALS(2, templateNamePositionHelper("template<class T> unsigned foo() { return 0; }", 4));
Packit 2035a7
        ASSERT_EQUALS(3, templateNamePositionHelper("template<class T> unsigned* foo() { return 0; }", 4));
Packit 2035a7
        ASSERT_EQUALS(3, templateNamePositionHelper("template<class T> const unsigned foo() { return 0; }", 4));
Packit 2035a7
        ASSERT_EQUALS(4, templateNamePositionHelper("template<class T> const unsigned& foo() { return 0; }", 4));
Packit 2035a7
        // Class template members
Packit 2035a7
        ASSERT_EQUALS(4, templateNamePositionHelper("class A { template<class T> unsigned foo(); }; "
Packit 2035a7
                      "template<class T> unsigned A::foo() { return 0; }", 19));
Packit 2035a7
        ASSERT_EQUALS(5, templateNamePositionHelper("class A { template<class T> const unsigned foo(); }; "
Packit 2035a7
                      "template<class T> const unsigned A::foo() { return 0; }", 20));
Packit 2035a7
        TODO_ASSERT_EQUALS(7, -1, templateNamePositionHelper("class A { class B { template<class T> const unsigned foo(); }; } ; "
Packit 2035a7
                           "template<class T> const unsigned A::B::foo() { return 0; }", 25));
Packit 2035a7
        // Template class member
Packit 2035a7
        ASSERT_EQUALS(6, templateNamePositionHelper("template<class T> class A { A(); }; "
Packit 2035a7
                      "template<class T> A<T>::A() {}", 18));
Packit 2035a7
        ASSERT_EQUALS(8, templateNamePositionHelper("template<class T, class U> class A { A(); }; "
Packit 2035a7
                      "template<class T, class U> A<T, U>::A() {}", 24));
Packit 2035a7
        ASSERT_EQUALS(7, templateNamePositionHelper("template<class T> class A { unsigned foo(); }; "
Packit 2035a7
                      "template<class T> unsigned A<T>::foo() { return 0; }", 19));
Packit 2035a7
        ASSERT_EQUALS(9, templateNamePositionHelper("template<class T, class U> class A { unsigned foo(); }; "
Packit 2035a7
                      "template<class T, class U> unsigned A<T, U>::foo() { return 0; }", 25));
Packit 2035a7
        ASSERT_EQUALS(9, templateNamePositionHelper("template<class T, class U> class A { unsigned foo(); }; "
Packit 2035a7
                      "template<class T, class U> unsigned A<T, U>::foo() { return 0; }", 25, /*onlyCreateTokens=*/true));
Packit 2035a7
        ASSERT_EQUALS(12, templateNamePositionHelper("template<class T> class v {}; "
Packit 2035a7
                      "template<class T, class U> class A { unsigned foo(); }; "
Packit 2035a7
                      "template<> unsigned A<int, v<char> >::foo() { return 0; }", 30, /*onlyCreateTokens=*/true));
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void expandSpecialized() {
Packit 2035a7
        ASSERT_EQUALS("class A<int> { } ;", tok("template<> class A<int> {};"));
Packit 2035a7
        ASSERT_EQUALS("class A<int> : public B { } ;", tok("template<> class A<int> : public B {};"));
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void templateAlias1() {
Packit 2035a7
        const char code[] = "template<class T, int N> struct Foo {};\n"
Packit 2035a7
                            "template<class T> using Bar = Foo<T,3>;\n"
Packit 2035a7
                            "Bar<int> b;\n";
Packit 2035a7
Packit 2035a7
        const char expected[] = "; Foo<int,3> b ; struct Foo<int,3> { } ;";
Packit 2035a7
Packit 2035a7
        ASSERT_EQUALS(expected, tok(code));
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void templateAlias2() {
Packit 2035a7
        const char code[] = "namespace A { template<class T, int N> struct Foo {}; }\n"
Packit 2035a7
                            "template<class T> using Bar = A::Foo<T,3>;\n"
Packit 2035a7
                            "Bar<int> b;\n";
Packit 2035a7
Packit 2035a7
        const char expected[] = "; A::Foo<int,3> b ; struct A::Foo<int,3> { } ;";
Packit 2035a7
Packit 2035a7
        ASSERT_EQUALS(expected, tok(code));
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void templateAlias3() { // #8315
Packit 2035a7
        const char code[] = "template <int> struct Tag {};\n"
Packit 2035a7
                            "template <int ID> using SPtr = std::shared_ptr<void(Tag<ID>)>;\n"
Packit 2035a7
                            "SPtr<0> s;";
Packit 2035a7
        const char expected[] = "; std :: shared_ptr < void ( Tag<0> ) > s ; struct Tag<0> { } ;";
Packit 2035a7
        ASSERT_EQUALS(expected, tok(code));
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    unsigned int instantiateMatch(const char code[], const std::size_t numberOfArguments, const char patternAfter[]) {
Packit 2035a7
        Tokenizer tokenizer(&settings, this);
Packit 2035a7
Packit 2035a7
        std::istringstream istr(code);
Packit 2035a7
        tokenizer.tokenize(istr, "test.cpp", "");
Packit 2035a7
Packit 2035a7
        return TemplateSimplifier::instantiateMatch(tokenizer.tokens(), numberOfArguments, patternAfter);
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void instantiateMatch() {
Packit 2035a7
        // Ticket #8175
Packit 2035a7
        ASSERT_EQUALS(false,
Packit 2035a7
                      instantiateMatch("ConvertHelper < From, To > c ;",
Packit 2035a7
                                       2, ":: %name% ("));
Packit 2035a7
        ASSERT_EQUALS(true,
Packit 2035a7
                      instantiateMatch("ConvertHelper < From, To > :: Create ( ) ;",
Packit 2035a7
                                       2, ":: %name% ("));
Packit 2035a7
        ASSERT_EQUALS(false,
Packit 2035a7
                      instantiateMatch("integral_constant < bool, sizeof ( ConvertHelper < From, To > :: Create ( ) ) > ;",
Packit 2035a7
                                       2, ":: %name% ("));
Packit 2035a7
        ASSERT_EQUALS(false,
Packit 2035a7
                      instantiateMatch("integral_constant < bool, sizeof ( ns :: ConvertHelper < From, To > :: Create ( ) ) > ;",
Packit 2035a7
                                       2, ":: %name% ("));
Packit 2035a7
    }
Packit 2035a7
};
Packit 2035a7
Packit 2035a7
REGISTER_TEST(TestSimplifyTemplate)