Fixed #9860 (unused template not removed properly by default)
This commit is contained in:
parent
28bc823264
commit
2cd8ea83a7
|
@ -293,18 +293,14 @@ void Token::deleteThis()
|
|||
takeData(mNext);
|
||||
mNext->link(nullptr); // mark as unlinked
|
||||
deleteNext();
|
||||
} else if (mPrevious && mPrevious->mPrevious) { // Copy previous to this and delete previous
|
||||
} else if (mPrevious) { // Copy previous to this and delete previous
|
||||
takeData(mPrevious);
|
||||
|
||||
Token* toDelete = mPrevious;
|
||||
mPrevious = mPrevious->mPrevious;
|
||||
mPrevious->mNext = this;
|
||||
|
||||
delete toDelete;
|
||||
mPrevious->link(nullptr);
|
||||
deletePrevious();
|
||||
} else {
|
||||
// We are the last token in the list, we can't delete
|
||||
// ourselves, so just make us empty
|
||||
str("");
|
||||
str(";");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -4365,7 +4365,7 @@ bool Tokenizer::simplifyTokenList1(const char FileName[])
|
|||
|
||||
reportUnknownMacros();
|
||||
|
||||
simplifyHeaders();
|
||||
simplifyHeadersAndUnusedTemplates();
|
||||
|
||||
// Remove __asm..
|
||||
simplifyAsm();
|
||||
|
@ -5027,7 +5027,7 @@ void Tokenizer::dump(std::ostream &out) const
|
|||
list.front()->printValueFlow(true, out);
|
||||
}
|
||||
|
||||
void Tokenizer::simplifyHeaders()
|
||||
void Tokenizer::simplifyHeadersAndUnusedTemplates()
|
||||
{
|
||||
if (mSettings->checkHeaders && mSettings->checkUnusedTemplates)
|
||||
// Full analysis. All information in the headers are kept.
|
||||
|
@ -5053,7 +5053,13 @@ void Tokenizer::simplifyHeaders()
|
|||
// functions and types to keep
|
||||
std::set<std::string> keep;
|
||||
for (const Token *tok = list.front(); tok; tok = tok->next()) {
|
||||
if (!tok->isName())
|
||||
if (isCPP() && Token::simpleMatch(tok, "template <")) {
|
||||
const Token *closingBracket = tok->next()->findClosingBracket();
|
||||
if (Token::Match(closingBracket, "> class|struct %name% {"))
|
||||
tok = closingBracket->linkAt(3);
|
||||
}
|
||||
|
||||
if (!tok->isName() || tok->isKeyword())
|
||||
continue;
|
||||
|
||||
if (!checkHeaders && tok->fileIndex() != 0)
|
||||
|
@ -5088,49 +5094,42 @@ void Tokenizer::simplifyHeaders()
|
|||
}
|
||||
}
|
||||
|
||||
if (Token::Match(tok, "[;{}]")) {
|
||||
if (!tok->previous() || Token::Match(tok->previous(), "[;{}]")) {
|
||||
// Remove unused function declarations
|
||||
if (isIncluded && removeUnusedIncludedFunctions) {
|
||||
while (1) {
|
||||
Token *start = tok->next();
|
||||
Token *start = tok;
|
||||
while (start && functionStart.find(start->str()) != functionStart.end())
|
||||
start = start->next();
|
||||
if (Token::Match(start, "%name% (") && Token::Match(start->linkAt(1), ") const| ;") && keep.find(start->str()) == keep.end())
|
||||
if (Token::Match(start, "%name% (") && Token::Match(start->linkAt(1), ") const| ;") && keep.find(start->str()) == keep.end()) {
|
||||
Token::eraseTokens(tok, start->linkAt(1)->tokAt(2));
|
||||
else
|
||||
tok->deleteThis();
|
||||
} else
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (isIncluded && removeUnusedIncludedClasses) {
|
||||
if (Token::Match(tok, "[;{}] class|struct %name% [:{]") && keep.find(tok->strAt(2)) == keep.end()) {
|
||||
if (Token::Match(tok, "class|struct %name% [:{]") && keep.find(tok->strAt(1)) == keep.end()) {
|
||||
// Remove this class/struct
|
||||
const Token *endToken = tok->tokAt(3);
|
||||
const Token *endToken = tok->tokAt(2);
|
||||
if (endToken->str() == ":") {
|
||||
endToken = endToken->next();
|
||||
while (Token::Match(endToken, "%name%|,"))
|
||||
endToken = endToken->next();
|
||||
}
|
||||
if (endToken && endToken->str() == "{" && Token::simpleMatch(endToken->link(), "} ;"))
|
||||
if (endToken && endToken->str() == "{" && Token::simpleMatch(endToken->link(), "} ;")) {
|
||||
Token::eraseTokens(tok, endToken->link()->next());
|
||||
tok->deleteThis();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (removeUnusedTemplates || (isIncluded && removeUnusedIncludedTemplates)) {
|
||||
if (Token::Match(tok->next(), "template < %name%")) {
|
||||
const Token *tok2 = tok->tokAt(3);
|
||||
while (Token::Match(tok2, "%name% %name% [,=>]") || Token::Match(tok2, "typename|class ... %name% [,>]")) {
|
||||
if (Token::Match(tok2, "typename|class ..."))
|
||||
tok2 = tok2->tokAt(3);
|
||||
else
|
||||
tok2 = tok2->tokAt(2);
|
||||
if (Token::Match(tok2, "= %name% [,>]"))
|
||||
tok2 = tok2->tokAt(2);
|
||||
if (tok2->str() == ",")
|
||||
tok2 = tok2->next();
|
||||
}
|
||||
if (Token::Match(tok2, "> class|struct %name% [;:{]") && keep.find(tok2->strAt(2)) == keep.end()) {
|
||||
const Token *endToken = tok2->tokAt(3);
|
||||
if (Token::Match(tok, "template < %name%")) {
|
||||
const Token *closingBracket = tok->next()->findClosingBracket();
|
||||
if (Token::Match(closingBracket, "> class|struct %name% [;:{]") && keep.find(closingBracket->strAt(2)) == keep.end()) {
|
||||
const Token *endToken = closingBracket->tokAt(3);
|
||||
if (endToken->str() == ":") {
|
||||
endToken = endToken->next();
|
||||
while (Token::Match(endToken, "%name%|,"))
|
||||
|
@ -5138,11 +5137,14 @@ void Tokenizer::simplifyHeaders()
|
|||
}
|
||||
if (endToken && endToken->str() == "{")
|
||||
endToken = endToken->link()->next();
|
||||
if (endToken && endToken->str() == ";")
|
||||
if (endToken && endToken->str() == ";") {
|
||||
Token::eraseTokens(tok, endToken);
|
||||
} else if (Token::Match(tok2, "> %type% %name% (") && Token::simpleMatch(tok2->linkAt(3), ") {") && keep.find(tok2->strAt(2)) == keep.end()) {
|
||||
const Token *endToken = tok2->linkAt(3)->linkAt(1)->next();
|
||||
tok->deleteThis();
|
||||
}
|
||||
} else if (Token::Match(closingBracket, "> %type% %name% (") && Token::simpleMatch(closingBracket->linkAt(3), ") {") && keep.find(closingBracket->strAt(2)) == keep.end()) {
|
||||
const Token *endToken = closingBracket->linkAt(3)->linkAt(1)->next();
|
||||
Token::eraseTokens(tok, endToken);
|
||||
tok->deleteThis();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -169,7 +169,7 @@ public:
|
|||
* - All executable code.
|
||||
* - Unused types/variables/etc
|
||||
*/
|
||||
void simplifyHeaders();
|
||||
void simplifyHeadersAndUnusedTemplates();
|
||||
|
||||
/**
|
||||
* Deletes dead code between 'begin' and 'end'.
|
||||
|
|
|
@ -31,11 +31,11 @@ public:
|
|||
private:
|
||||
Settings settings;
|
||||
|
||||
void check(const char code[], bool showAll = false) {
|
||||
void check(const char code[], bool inconclusive = false) {
|
||||
// Clear the error buffer..
|
||||
errout.str("");
|
||||
|
||||
settings.inconclusive = showAll;
|
||||
settings.inconclusive = inconclusive;
|
||||
|
||||
// Tokenize..
|
||||
Tokenizer tokenizer(&settings, this);
|
||||
|
@ -348,16 +348,6 @@ private:
|
|||
" int x;\n"
|
||||
"};");
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
|
||||
check("template <class T> struct A {\n"
|
||||
" A<T>() : x(0) { }\n"
|
||||
" A<T>(const T & t) : x(t.x) { }\n"
|
||||
"private:\n"
|
||||
" int x;\n"
|
||||
" int y;\n"
|
||||
"};");
|
||||
ASSERT_EQUALS("[test.cpp:2]: (warning) Member variable 'A::y' is not initialized in the constructor.\n"
|
||||
"[test.cpp:3]: (warning) Member variable 'A::y' is not initialized in the constructor.\n", errout.str());
|
||||
}
|
||||
|
||||
void simple7() { // ticket #4531
|
||||
|
|
|
@ -1378,7 +1378,7 @@ private:
|
|||
);
|
||||
|
||||
// #3449
|
||||
ASSERT_EQUALS("template < typename T > struct A ;\n"
|
||||
ASSERT_EQUALS(";\n"
|
||||
"struct B { template < typename T > struct C } ;\n"
|
||||
"{ } ;",
|
||||
checkCode("template<typename T> struct A;\n"
|
||||
|
|
|
@ -6101,10 +6101,14 @@ private:
|
|||
ASSERT_EQUALS("", errout.str());
|
||||
}
|
||||
|
||||
{
|
||||
Settings keepTemplates;
|
||||
keepTemplates.checkUnusedTemplates = true;
|
||||
check("template<int n> void foo(unsigned int x) {\n"
|
||||
"if (x <= 0);\n"
|
||||
"}\n");
|
||||
"}\n", &keepTemplates);
|
||||
ASSERT_EQUALS("[test.cpp:2]: (style) Checking if unsigned expression 'x' is less than zero.\n", errout.str());
|
||||
}
|
||||
|
||||
// #8836
|
||||
check("uint32_t value = 0xFUL;\n"
|
||||
|
@ -8743,11 +8747,14 @@ private:
|
|||
}
|
||||
|
||||
void forwardAndUsed() {
|
||||
Settings keepTemplates;
|
||||
keepTemplates.checkUnusedTemplates = true;
|
||||
|
||||
check("template<typename T>\n"
|
||||
"void f(T && t) {\n"
|
||||
" g(std::forward<T>(t));\n"
|
||||
" T s = t;\n"
|
||||
"}");
|
||||
"}", &keepTemplates);
|
||||
ASSERT_EQUALS("[test.cpp:4]: (warning) Access of forwarded variable 't'.\n", errout.str());
|
||||
}
|
||||
|
||||
|
|
|
@ -41,6 +41,9 @@ private:
|
|||
void run() OVERRIDE {
|
||||
settings.addEnabled("portability");
|
||||
|
||||
// If there are unused templates, keep those
|
||||
settings.checkUnusedTemplates = true;
|
||||
|
||||
TEST_CASE(template1);
|
||||
TEST_CASE(template2);
|
||||
TEST_CASE(template3);
|
||||
|
@ -458,7 +461,8 @@ private:
|
|||
|
||||
// The expected result..
|
||||
const char expected[] = "class A<int> ; "
|
||||
"void f ( ) { A<int> a ; } ; "
|
||||
"void f ( ) { A<int> a ; } "
|
||||
"template < typename T > class B { void g ( ) { A < T > b ; b = A < T > :: h ( ) ; } } ; "
|
||||
"class A<int> { } ;";
|
||||
|
||||
ASSERT_EQUALS(expected, tok(code));
|
||||
|
@ -1472,6 +1476,7 @@ private:
|
|||
"template <class T, unsigned S> C3<T, S>::C3(const C3<T, S> &v) { C1<T *> c1; }\n"
|
||||
"C3<int,6> c3;";
|
||||
const char exp[] = "struct C1<int*> ; "
|
||||
"template < class T > void f ( ) { x = y ? ( C1 < int > :: allocate ( 1 ) ) : 0 ; } "
|
||||
"class C3<int,6> ; "
|
||||
"C3<int,6> c3 ; "
|
||||
"class C3<int,6> { } ; "
|
||||
|
@ -2549,8 +2554,8 @@ private:
|
|||
"template <typename T> class Fred {};\n"
|
||||
"ObjectCache<Fred> _cache;";
|
||||
const char exp[] = "class ObjectCache<Fred> ; "
|
||||
"ObjectCache<Fred> _cache ; "
|
||||
"class ObjectCache<Fred> { } ;";
|
||||
"template < typename T > class Fred { } ; "
|
||||
"ObjectCache<Fred> _cache ; class ObjectCache<Fred> { } ;";
|
||||
ASSERT_EQUALS(exp, tok(code));
|
||||
}
|
||||
|
||||
|
@ -4092,7 +4097,8 @@ private:
|
|||
"template < class T > struct Unconst < const T & > { } ; "
|
||||
"template < class T > struct Unconst < T * const > { } ; "
|
||||
"template < class T1 , class T2 > struct type_equal { enum Anonymous0 { value = 0 } ; } ; "
|
||||
"template < class T > struct type_equal < T , T > { enum Anonymous1 { value = 1 } ; } ;";
|
||||
"template < class T > struct type_equal < T , T > { enum Anonymous1 { value = 1 } ; } ; "
|
||||
"template < class T > struct template_is_const { enum Anonymous2 { value = ! type_equal < T , Unconst < T > :: type > :: value } ; } ;";
|
||||
ASSERT_EQUALS(exp1, tok(code1));
|
||||
}
|
||||
|
||||
|
@ -4372,7 +4378,7 @@ private:
|
|||
const char code[] = "class Fred {\n"
|
||||
" template<class T> explicit Fred(T t) { }\n"
|
||||
"}";
|
||||
ASSERT_EQUALS("class Fred { }", tok(code));
|
||||
ASSERT_EQUALS("class Fred { template < class T > explicit Fred ( T t ) { } }", tok(code));
|
||||
|
||||
// #3532
|
||||
const char code2[] = "class Fred {\n"
|
||||
|
|
|
@ -46,6 +46,12 @@ private:
|
|||
settings1.addEnabled("style");
|
||||
settings_windows.addEnabled("portability");
|
||||
|
||||
// If there are unused templates, keep those
|
||||
settings0.checkUnusedTemplates = true;
|
||||
settings1.checkUnusedTemplates = true;
|
||||
settings_std.checkUnusedTemplates = true;
|
||||
settings_windows.checkUnusedTemplates = true;
|
||||
|
||||
// Make sure the Tokenizer::simplifyTokenList works.
|
||||
// The order of the simplifications is important. So this test
|
||||
// case shall make sure the simplifications are done in the
|
||||
|
@ -2883,7 +2889,7 @@ private:
|
|||
{
|
||||
const char code[] = "namespace std { }";
|
||||
|
||||
ASSERT_EQUALS("", tok(code));
|
||||
ASSERT_EQUALS(";", tok(code));
|
||||
}
|
||||
|
||||
{
|
||||
|
|
|
@ -42,6 +42,11 @@ private:
|
|||
settings0.addEnabled("style");
|
||||
settings2.addEnabled("style");
|
||||
|
||||
// If there are unused templates, keep those
|
||||
settings0.checkUnusedTemplates = true;
|
||||
settings1.checkUnusedTemplates = true;
|
||||
settings2.checkUnusedTemplates = true;
|
||||
|
||||
TEST_CASE(simplifyTypedef1);
|
||||
TEST_CASE(simplifyTypedef2);
|
||||
TEST_CASE(simplifyTypedef3);
|
||||
|
@ -1797,7 +1802,7 @@ private:
|
|||
|
||||
void simplifyTypedef75() { // ticket #2426
|
||||
const char code[] = "typedef _Packed struct S { long l; };";
|
||||
ASSERT_EQUALS("", tok(code, true, Settings::Native, false));
|
||||
ASSERT_EQUALS(";", tok(code, true, Settings::Native, false));
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
}
|
||||
|
||||
|
@ -2047,7 +2052,7 @@ private:
|
|||
const char code[] = "typedef long Long;\n"
|
||||
"namespace NS {\n"
|
||||
"}";
|
||||
ASSERT_EQUALS("", tok(code));
|
||||
ASSERT_EQUALS(";", tok(code));
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
}
|
||||
|
||||
|
@ -2532,7 +2537,8 @@ private:
|
|||
"template <long, class> struct c; "
|
||||
"template <int g> struct d { enum { e = c<g, b>::f }; };";
|
||||
const char exp [] = "class a ; "
|
||||
"template < long , class > struct c ;";
|
||||
"template < long , class > struct c ; "
|
||||
"template < int g > struct d { enum Anonymous0 { e = c < g , int ( a :: * ) > :: f } ; } ;";
|
||||
ASSERT_EQUALS(exp, tok(code, false));
|
||||
}
|
||||
|
||||
|
|
|
@ -42,6 +42,11 @@ private:
|
|||
settings0.addEnabled("style");
|
||||
settings2.addEnabled("style");
|
||||
|
||||
// If there are unused templates, keep those
|
||||
settings0.checkUnusedTemplates = true;
|
||||
settings1.checkUnusedTemplates = true;
|
||||
settings2.checkUnusedTemplates = true;
|
||||
|
||||
TEST_CASE(simplifyUsing1);
|
||||
TEST_CASE(simplifyUsing2);
|
||||
TEST_CASE(simplifyUsing3);
|
||||
|
@ -492,7 +497,8 @@ private:
|
|||
"class c { "
|
||||
"int i ; i = 0 ; "
|
||||
"c ( ) { i -- ; } "
|
||||
"} ;";
|
||||
"} ; "
|
||||
"template < class T > class s { } ;";
|
||||
|
||||
ASSERT_EQUALS(exp, tok(code, true, Settings::Win64));
|
||||
}
|
||||
|
|
|
@ -115,6 +115,10 @@ private:
|
|||
LOAD_LIB_2(settings1.library, "std.cfg");
|
||||
settings2.platform(Settings::Unspecified);
|
||||
|
||||
// If there are unused templates, keep those
|
||||
settings1.checkUnusedTemplates = true;
|
||||
settings2.checkUnusedTemplates = true;
|
||||
|
||||
TEST_CASE(array);
|
||||
TEST_CASE(stlarray1);
|
||||
TEST_CASE(stlarray2);
|
||||
|
|
|
@ -47,6 +47,12 @@ private:
|
|||
void run() OVERRIDE {
|
||||
LOAD_LIB_2(settings_windows.library, "windows.cfg");
|
||||
|
||||
// If there are unused templates, keep those
|
||||
settings0.checkUnusedTemplates = true;
|
||||
settings1.checkUnusedTemplates = true;
|
||||
settings2.checkUnusedTemplates = true;
|
||||
settings_windows.checkUnusedTemplates = true;
|
||||
|
||||
TEST_CASE(tokenize1);
|
||||
TEST_CASE(tokenize2);
|
||||
TEST_CASE(tokenize4);
|
||||
|
@ -95,7 +101,8 @@ private:
|
|||
|
||||
TEST_CASE(longtok);
|
||||
|
||||
TEST_CASE(removeUnusedTemplates);
|
||||
TEST_CASE(simplifyHeadersAndUnusedTemplates1);
|
||||
TEST_CASE(simplifyHeadersAndUnusedTemplates2);
|
||||
|
||||
TEST_CASE(simplifyCasts1);
|
||||
TEST_CASE(simplifyCasts2);
|
||||
|
@ -1028,7 +1035,7 @@ private:
|
|||
}
|
||||
|
||||
|
||||
void removeUnusedTemplates() {
|
||||
void simplifyHeadersAndUnusedTemplates1() {
|
||||
Settings s;
|
||||
s.checkUnusedTemplates = false;
|
||||
ASSERT_EQUALS(";",
|
||||
|
@ -1044,6 +1051,22 @@ private:
|
|||
"}", s));
|
||||
}
|
||||
|
||||
void simplifyHeadersAndUnusedTemplates2() {
|
||||
const char code[] = "; template< typename T, u_int uBAR = 0 >\n"
|
||||
"class Foo {\n"
|
||||
"public:\n"
|
||||
" void FooBar() {\n"
|
||||
" new ( (uBAR ? uBAR : sizeof(T))) T;\n"
|
||||
" }\n"
|
||||
"};";
|
||||
|
||||
Settings s;
|
||||
s.checkUnusedTemplates = false;
|
||||
ASSERT_EQUALS(";", tokenizeAndStringify(code, s));
|
||||
|
||||
s.checkUnusedTemplates = true;
|
||||
ASSERT_THROW(tokenizeAndStringify(code, s), InternalError);
|
||||
}
|
||||
|
||||
// Don’t remove "(int *)"..
|
||||
void simplifyCasts1() {
|
||||
|
@ -7467,11 +7490,11 @@ private:
|
|||
}
|
||||
|
||||
void simplifyEmptyNamespaces() {
|
||||
ASSERT_EQUALS("", tokenizeAndStringify("namespace { }"));
|
||||
ASSERT_EQUALS("", tokenizeAndStringify("namespace foo { }"));
|
||||
ASSERT_EQUALS("", tokenizeAndStringify("namespace foo { namespace { } }"));
|
||||
ASSERT_EQUALS("", tokenizeAndStringify("namespace { namespace { } }")); // Ticket #9512
|
||||
ASSERT_EQUALS("", tokenizeAndStringify("namespace foo { namespace bar { } }"));
|
||||
ASSERT_EQUALS(";", tokenizeAndStringify("namespace { }"));
|
||||
ASSERT_EQUALS(";", tokenizeAndStringify("namespace foo { }"));
|
||||
ASSERT_EQUALS(";", tokenizeAndStringify("namespace foo { namespace { } }"));
|
||||
ASSERT_EQUALS(";", tokenizeAndStringify("namespace { namespace { } }")); // Ticket #9512
|
||||
ASSERT_EQUALS(";", tokenizeAndStringify("namespace foo { namespace bar { } }"));
|
||||
}
|
||||
|
||||
void prepareTernaryOpForAST() {
|
||||
|
@ -8625,12 +8648,12 @@ private:
|
|||
}
|
||||
}
|
||||
|
||||
std::string checkHeaders(const char code[], bool f) {
|
||||
std::string checkHeaders(const char code[], bool checkHeadersFlag) {
|
||||
// Clear the error buffer..
|
||||
errout.str("");
|
||||
|
||||
Settings settings;
|
||||
settings.checkHeaders = f;
|
||||
settings.checkHeaders = checkHeadersFlag;
|
||||
|
||||
// Raw tokens..
|
||||
std::vector<std::string> files(1, "test.cpp");
|
||||
|
@ -8670,12 +8693,11 @@ private:
|
|||
"5: } ; void A :: g<int> ( int x ) { a = 2 ; }\n",
|
||||
checkHeaders(code, true));
|
||||
|
||||
ASSERT_EQUALS("\n\n##file 1\n"
|
||||
"1: struct A {\n"
|
||||
"2: int a ; a = 1 ;\n"
|
||||
"3: void f ( ) ;\n"
|
||||
ASSERT_EQUALS("\n\n##file 1\n\n"
|
||||
"1:\n"
|
||||
"|\n"
|
||||
"4:\n"
|
||||
"5: } ;\n",
|
||||
"5: ;\n",
|
||||
checkHeaders(code, false));
|
||||
}
|
||||
};
|
||||
|
|
|
@ -221,6 +221,7 @@ private:
|
|||
settings.platform(Settings::Unix64);
|
||||
settings.standards.c = Standards::C89;
|
||||
settings.standards.cpp = Standards::CPP11;
|
||||
settings.checkUnusedTemplates = true;
|
||||
|
||||
Tokenizer tokenizer(&settings, this);
|
||||
std::istringstream istr(code);
|
||||
|
@ -239,6 +240,7 @@ private:
|
|||
settings.platform(Settings::Unix64);
|
||||
settings.standards.c = Standards::C89;
|
||||
settings.standards.cpp = Standards::CPP11;
|
||||
settings.checkUnusedTemplates = true;
|
||||
|
||||
Tokenizer tokenizer(&settings, this);
|
||||
std::istringstream istr(code);
|
||||
|
@ -257,6 +259,7 @@ private:
|
|||
settings.platform(Settings::Unix64);
|
||||
settings.standards.c = Standards::C89;
|
||||
settings.standards.cpp = Standards::CPP11;
|
||||
settings.checkUnusedTemplates = true;
|
||||
|
||||
Tokenizer tokenizer(&settings, this);
|
||||
std::istringstream istr(code);
|
||||
|
|
Loading…
Reference in New Issue