diff --git a/test/testgarbage.cpp b/test/testgarbage.cpp index 47af5b20b..06982a1d7 100644 --- a/test/testgarbage.cpp +++ b/test/testgarbage.cpp @@ -182,6 +182,8 @@ private: TEST_CASE(garbageCode130); // #7021 TEST_CASE(garbageCode131); // #7023 TEST_CASE(garbageCode132); // #7022 + TEST_CASE(garbageCode133); + TEST_CASE(garbageCode134); TEST_CASE(garbageValueFlow); TEST_CASE(garbageSymbolDatabase); @@ -991,6 +993,77 @@ private: checkCode("() () { } { () () ({}) i() } void i(void(*ptr) ()) { ptr(!) () }"); } + void garbageCode133() { + ASSERT_THROW(checkCode("void f() {{}"), InternalError); + + ASSERT_THROW(checkCode("void f()) {}"), InternalError); + + ASSERT_THROW(checkCode("void f()\n" + "{\n" + " foo(;\n" + "}\n"), InternalError); + + ASSERT_THROW(checkCode("void f()\n" + "{\n" + " for(;;){ foo();\n" + "}\n"), InternalError); + + ASSERT_THROW(checkCode("void f()\n" + "{\n" + " a[10;\n" + "}\n"), InternalError); + + { + errout.str(""); + const char code[] = "{\n" + " a(\n" + "}\n" + "{\n" + " b());\n" + "}\n"; + Tokenizer tokenizer(&settings, this); + std::istringstream istr(code); + try { + tokenizer.tokenize(istr, "test.cpp"); + assertThrowFail(__FILE__, __LINE__); + } catch (InternalError& e) { + ASSERT_EQUALS("Invalid number of character '(' when these macros are defined: ''.", e.errorMessage); + ASSERT_EQUALS("syntaxError", e.id); + ASSERT_EQUALS(2, e.token->linenr()); + } + } + } + + void garbageCode134() { + // Ticket #5605, #5759, #5762, #5774, #5823, #6059 + checkCode("template<>\n"); + checkCode("foo() template struct tuple Args> tuple { } main() { foo(); }"); + checkCode("( ) template < T1 = typename = unused> struct Args { } main ( ) { foo < int > ( ) ; }"); + checkCode("() template < T = typename = x > struct a {} { f () }"); + checkCode("template < T = typename = > struct a { f }"); + checkCode("struct S { int i, j; }; " + "template struct X {}; " + "X<&S::i, int> x = X<&S::i, int>(); " + "X<&S::j, int> y = X<&S::j, int>(); "); + checkCode("template struct A {}; " + "template <> struct A {}; " + "void foo(const void* f = 0) {}"); + checkCode("template struct A { " + " static const int s = 0; " + "}; " + "A a;"); + checkCode("template class A {}; " + "template > class B {}; " + "template > class C { " + " C() : _a(0), _b(0) {} " + " int _a, _b; " + "};"); + checkCode("template struct A { " + " static int i; " + "}; " + "void f() { A::i = 0; }"); + } + void garbageValueFlow() { // #6089 diff --git a/test/testsimplifytemplate.cpp b/test/testsimplifytemplate.cpp index 6c2967e71..640d334f9 100644 --- a/test/testsimplifytemplate.cpp +++ b/test/testsimplifytemplate.cpp @@ -94,6 +94,8 @@ private: TEST_CASE(template_default_type); TEST_CASE(template_typename); TEST_CASE(template_constructor); // #3152 - template constructor is removed + TEST_CASE(syntax_error_templates_1); + TEST_CASE(template_member_ptr); // Ticket #5786 - crash upon valid code // Test TemplateSimplifier::templateParameters TEST_CASE(templateParameters); @@ -1177,6 +1179,81 @@ private: ASSERT_EQUALS("class Fred { template < class T > Fred ( T t ) { } }", tok(code2)); } + void syntax_error_templates_1() { + // ok code.. using ">" for a comparison + tok("xz> xyz;\n"); + ASSERT_EQUALS("", errout.str()); + + // ok code + tok("template operator<(T a, T b) { }\n"); + ASSERT_EQUALS("", errout.str()); + + // ok code (ticket #1984) + tok("void f(a) int a;\n" + "{ ;x" + ASSERT_THROW(tok("x xyz;\n"), InternalError); + + // bad code + ASSERT_THROW(tok("typedef\n" + " typename boost::mpl::if_c<\n" + " _visitableIndex < boost::mpl::size< typename _Visitables::ConcreteVisitables >::value\n" + " , ConcreteVisitable\n" + " , Dummy< _visitableIndex >\n" + " >::type ConcreteVisitableOrDummy;\n"), InternalError); + + // code is ok, don't show syntax error + tok("struct A {int a;int b};\n" + "class Fred {" + "public:\n" + " Fred() : a({1,2}) {\n" + " for (int i=0;i<6;i++);\n" // <- no syntax error + " }\n" + "private:\n" + " A a;\n" + "};\n"); + ASSERT_EQUALS("", errout.str()); + } + + void template_member_ptr() { // Ticket #5786 + tok("struct A {}; " + "struct B { " + "template struct BB {}; " + "template static bool foo(int) { return true; } " + "void bar() { bool b = foo(0); }" + "};"); + tok("struct A {}; " + "struct B { " + "template struct BB {}; " + "template static bool foo(int) { return true; } " + "void bar() { bool b = foo(0); }" + "};"); + tok("struct A {}; " + "struct B { " + "template struct BB {}; " + "template static bool foo(int) { return true; } " + "void bar() { bool b = foo(0); }" + "};"); + tok("struct A {}; " + "struct B { " + "template struct BB {}; " + "template static bool foo(int) { return true; } " + "void bar() { bool b = foo(0); }" + "};"); + } + + unsigned int templateParameters(const char code[]) { Tokenizer tokenizer(&settings, this); diff --git a/test/testtokenize.cpp b/test/testtokenize.cpp index ebc7165c2..1e3edbcc2 100644 --- a/test/testtokenize.cpp +++ b/test/testtokenize.cpp @@ -287,11 +287,6 @@ private: TEST_CASE(vardecl_par2); // #3912 - set correct links TEST_CASE(vardecl_par3); // #6556 - Fred x1(a), x2(b); TEST_CASE(volatile_variables); - TEST_CASE(syntax_error); - TEST_CASE(syntax_error_templates_1); - TEST_CASE(syntax_error_templates_2); - TEST_CASE(syntax_error_templates_3); // Ticket #5605, #5759, #5762, #5774 - TEST_CASE(template_member_ptr); // Ticket #5786 - crash upon valid code // unsigned i; => unsigned int i; TEST_CASE(unsigned1); @@ -3996,244 +3991,6 @@ private: ASSERT_EQUALS("int a ; a = 0 ;\nint b ; b = 0 ;\nint c ; c = 0 ;", actual); } - void syntax_error() { - { - errout.str(""); - const char code[] = "void f() {}"; - Tokenizer tokenizer(&settings0, this); - std::istringstream istr(code); - ASSERT_EQUALS(true, tokenizer.tokenize(istr, "test.cpp")); - ASSERT_EQUALS("", errout.str()); - } - - { - errout.str(""); - const char code[] = "void f() {{}"; - Tokenizer tokenizer(&settings0, this); - std::istringstream istr(code); - ASSERT_THROW(tokenizer.tokenize(istr, "test.cpp"), InternalError); - } - - { - errout.str(""); - const char code[] = "void f()) {}"; - Tokenizer tokenizer(&settings0, this); - std::istringstream istr(code); - ASSERT_THROW(tokenizer.tokenize(istr, "test.cpp"), InternalError); - } - - { - errout.str(""); - const char code[] = "namespace extract{\nB(weighted_moment)\n}\nusing extract::weighted_moment;\n"; - Tokenizer tokenizer(&settings0, this); - std::istringstream istr(code); - ASSERT_EQUALS(true, tokenizer.tokenize(istr, "test.cpp")); - tokenizer.simplifyTokenList2(); - ASSERT_EQUALS("", errout.str()); - } - - { - errout.str(""); - const char code[] = "void f()\n" - "{\n" - " foo(;\n" - "}\n"; - Tokenizer tokenizer(&settings0, this); - std::istringstream istr(code); - ASSERT_THROW(tokenizer.tokenize(istr, "test.cpp", "ABC"), InternalError); - } - - { - errout.str(""); - const char code[] = "void f()\n" - "{\n" - " for(;;){ foo();\n" - "}\n"; - Tokenizer tokenizer(&settings0, this); - std::istringstream istr(code); - ASSERT_THROW(tokenizer.tokenize(istr, "test.cpp"), InternalError); - } - - { - errout.str(""); - const char code[] = "void f()\n" - "{\n" - " a[10;\n" - "}\n"; - Tokenizer tokenizer(&settings0, this); - std::istringstream istr(code); - ASSERT_THROW(tokenizer.tokenize(istr, "test.cpp"), InternalError); - } - - { - errout.str(""); - const char code[] = "{\n" - " a(\n" - "}\n" - "{\n" - " b());\n" - "}\n"; - Tokenizer tokenizer(&settings0, this); - std::istringstream istr(code); - try { - tokenizer.tokenize(istr, "test.cpp"); - assertThrowFail(__FILE__, __LINE__); - } catch (InternalError& e) { - ASSERT_EQUALS("Invalid number of character '(' when these macros are defined: ''.", e.errorMessage); - ASSERT_EQUALS("syntaxError", e.id); - ASSERT_EQUALS(2, e.token->linenr()); - } - } - } - - - void syntax_error_templates_1() { - // ok code.. using ">" for a comparison - { - errout.str(""); - std::istringstream istr("xz> xyz;\n"); - Tokenizer tokenizer(&settings0, this); - tokenizer.tokenize(istr, "test.cpp"); - ASSERT_EQUALS("", errout.str()); - } - - // ok code.. - { - errout.str(""); - std::istringstream istr("template operator<(T a, T b) { }\n"); - Tokenizer tokenizer(&settings0, this); - tokenizer.tokenize(istr, "test.cpp"); - ASSERT_EQUALS("", errout.str()); - } - - // ok code (ticket #1984).. - { - errout.str(""); - std::istringstream istr("void f(a) int a;\n" - "{ ;x" - { - errout.str(""); - std::istringstream istr("x xyz;\n"); - Tokenizer tokenizer(&settings0, this); - ASSERT_THROW(tokenizer.tokenize(istr, "test.cpp"), InternalError); - } - - // bad code - { - errout.str(""); - std::istringstream istr("typedef\n" - " typename boost::mpl::if_c<\n" - " _visitableIndex < boost::mpl::size< typename _Visitables::ConcreteVisitables >::value\n" - " , ConcreteVisitable\n" - " , Dummy< _visitableIndex >\n" - " >::type ConcreteVisitableOrDummy;\n"); - Tokenizer tokenizer(&settings0, this); - ASSERT_THROW(tokenizer.tokenize(istr, "test.cpp"), InternalError); - } - - // code is ok, don't show syntax error - { - errout.str(""); - std::istringstream istr("struct A {int a;int b};\n" - "class Fred {" - "public:\n" - " Fred() : a({1,2}) {\n" - " for (int i=0;i<6;i++);\n" // <- no syntax error - " }\n" - "private:\n" - " A a;\n" - "};\n"); - Tokenizer tokenizer(&settings0, this); - tokenizer.tokenize(istr, "test.cpp"); - ASSERT_EQUALS("", errout.str()); - } - } - - void syntax_error_templates_2() { - std::istringstream istr("template<>\n"); - Tokenizer tokenizer(&settings0, this); - tokenizer.tokenize(istr, "test.cpp"); // shouldn't segfault - } - - void syntax_error_templates_3() { // Ticket #5605, #5759, #5762, #5774, #5823, #6059 - tokenizeAndStringify("foo() template struct tuple Args> tuple { } main() { foo(); }"); - tokenizeAndStringify("( ) template < T1 = typename = unused> struct Args { } main ( ) { foo < int > ( ) ; }"); - tokenizeAndStringify("() template < T = typename = x > struct a {} { f () }"); - tokenizeAndStringify("template < T = typename = > struct a { f }"); - tokenizeAndStringify("struct S { int i, j; }; " - "template struct X {}; " - "X<&S::i, int> x = X<&S::i, int>(); " - "X<&S::j, int> y = X<&S::j, int>(); "); - tokenizeAndStringify("template struct A {}; " - "template <> struct A {}; " - "void foo(const void* f = 0) {}"); - tokenizeAndStringify("template struct A { " - " static const int s = 0; " - "}; " - "A a;"); - tokenizeAndStringify("template class A {}; " - "template > class B {}; " - "template > class C { " - " C() : _a(0), _b(0) {} " - " int _a, _b; " - "};"); - tokenizeAndStringify("template struct A { " - " static int i; " - "}; " - "void f() { A::i = 0; }"); - } - - void template_member_ptr() { // Ticket #5786 - tokenizeAndStringify("struct A {}; " - "struct B { " - "template struct BB {}; " - "template static bool foo(int) { return true; } " - "void bar() { bool b = foo(0); }" - "};"); - tokenizeAndStringify("struct A {}; " - "struct B { " - "template struct BB {}; " - "template static bool foo(int) { return true; } " - "void bar() { bool b = foo(0); }" - "};"); - tokenizeAndStringify("struct A {}; " - "struct B { " - "template struct BB {}; " - "template static bool foo(int) { return true; } " - "void bar() { bool b = foo(0); }" - "};"); - tokenizeAndStringify("struct A {}; " - "struct B { " - "template struct BB {}; " - "template static bool foo(int) { return true; } " - "void bar() { bool b = foo(0); }" - "};"); - } void simplifyKeyword() { {