From 3cc77fac57d1b1c0cc48b897ccc1e0ce17c92a5c Mon Sep 17 00:00:00 2001 From: firewave Date: Sat, 6 Jan 2024 21:19:17 +0100 Subject: [PATCH] make sure the language for a `TokenList`/`Token` is always determined --- lib/clangimport.cpp | 7 +++- lib/cppcheck.cpp | 10 ++++-- lib/importproject.cpp | 8 ++--- lib/library.cpp | 11 +++--- lib/library.h | 1 + lib/programmemory.cpp | 7 ++-- lib/programmemory.h | 3 +- lib/symboldatabase.cpp | 4 +-- lib/token.h | 1 - lib/tokenlist.cpp | 65 +++++++++++++++++++++++++++++++++++- lib/tokenlist.h | 19 ++++++----- lib/valueflow.cpp | 20 +++++------ test/testlibrary.cpp | 32 +++++++++--------- test/testsimplifytypedef.cpp | 2 +- test/testtoken.cpp | 6 ++-- 15 files changed, 137 insertions(+), 59 deletions(-) diff --git a/lib/clangimport.cpp b/lib/clangimport.cpp index 54c212ec2b86..b23e448b8932 100644 --- a/lib/clangimport.cpp +++ b/lib/clangimport.cpp @@ -330,8 +330,12 @@ namespace clangimport { void dumpAst(int num = 0, int indent = 0) const; void createTokens1(TokenList &tokenList) { //dumpAst(); - if (!tokenList.back()) + if (!tokenList.back()) { setLocations(tokenList, 0, 1, 1); + // FIXME: treat as C++ if no filename (i.e. no lang) is specified for now + if (tokenList.getSourceFilePath().empty()) + tokenList.setLang(Standards::Language::CPP); + } else setLocations(tokenList, tokenList.back()->fileIndex(), tokenList.back()->linenr(), 1); createTokens(tokenList); @@ -626,6 +630,7 @@ void clangimport::AstNode::setValueType(Token *tok) continue; TokenList decl(nullptr); + decl.setLang(tok->isCpp() ? Standards::Language::CPP : Standards::Language::C); addTypeTokens(decl, type, tok->scope()); if (!decl.front()) break; diff --git a/lib/cppcheck.cpp b/lib/cppcheck.cpp index 3a2915dbe2c8..d0fa9de1fcc3 100644 --- a/lib/cppcheck.cpp +++ b/lib/cppcheck.cpp @@ -633,10 +633,14 @@ unsigned int CppCheck::checkFile(const std::string& filename, const std::string try { if (mSettings.library.markupFile(filename)) { - if (mSettings.isUnusedFunctionCheckEnabled() && mSettings.buildDir.empty()) { + if (mSettings.isUnusedFunctionCheckEnabled() && + mSettings.buildDir.empty()) { + // this is not a real source file - we just want to tokenize it. treat it as C anyways as the language needs to be determined. Tokenizer tokenizer(mSettings, this); - if (fileStream) + tokenizer.list.setLang(Standards::Language::C); + if (fileStream) { tokenizer.list.createTokens(*fileStream, filename); + } else { std::ifstream in(filename); tokenizer.list.createTokens(in, filename); @@ -804,7 +808,7 @@ unsigned int CppCheck::checkFile(const std::string& filename, const std::string } Tokenizer tokenizer2(mSettings, this); std::istringstream istr2(code); - tokenizer2.list.createTokens(istr2); + tokenizer2.list.createTokens(istr2, Path::identify(*files.begin())); executeRules("define", tokenizer2); } #endif diff --git a/lib/importproject.cpp b/lib/importproject.cpp index e5849d3743f8..3208cb2c775d 100644 --- a/lib/importproject.cpp +++ b/lib/importproject.cpp @@ -560,11 +560,11 @@ namespace { replaceAll(c, "$(Configuration)", p.configuration); replaceAll(c, "$(Platform)", p.platformStr); - // TODO : Better evaluation - Settings s; - std::istringstream istr(c); + // TODO: evaluate without using the Tokenizer + const Settings s; Tokenizer tokenizer(s); - tokenizer.tokenize(istr,"vcxproj"); + std::istringstream istr(c); + tokenizer.tokenize(istr,"vcxproj.c"); for (const Token *tok = tokenizer.tokens(); tok; tok = tok->next()) { if (tok->str() == "(" && tok->astOperand1() && tok->astOperand2()) { if (tok->astOperand1()->expressionString() == "Configuration.Contains") diff --git a/lib/library.cpp b/lib/library.cpp index b89dcff958b3..05d92c047f02 100644 --- a/lib/library.cpp +++ b/lib/library.cpp @@ -53,10 +53,10 @@ static std::vector getnames(const char *names) return ret; } -static void gettokenlistfromvalid(const std::string& valid, TokenList& tokenList) +static void gettokenlistfromvalid(const std::string& valid, bool cpp, TokenList& tokenList) { std::istringstream istr(valid + ','); - tokenList.createTokens(istr); + tokenList.createTokens(istr, cpp ? Standards::Language::CPP : Standards::Language::C); for (Token *tok = tokenList.front(); tok; tok = tok->next()) { if (Token::Match(tok,"- %num%")) { tok->str("-" + tok->strAt(1)); @@ -929,7 +929,7 @@ bool Library::isIntArgValid(const Token *ftok, int argnr, const MathLib::bigint if (ac->valid.find('.') != std::string::npos) return isFloatArgValid(ftok, argnr, argvalue); TokenList tokenList(nullptr); - gettokenlistfromvalid(ac->valid, tokenList); + gettokenlistfromvalid(ac->valid, ftok->isCpp(), tokenList); for (const Token *tok = tokenList.front(); tok; tok = tok->next()) { if (tok->isNumber() && argvalue == MathLib::toBigNumber(tok->str())) return true; @@ -949,7 +949,7 @@ bool Library::isFloatArgValid(const Token *ftok, int argnr, double argvalue) con if (!ac || ac->valid.empty()) return true; TokenList tokenList(nullptr); - gettokenlistfromvalid(ac->valid, tokenList); + gettokenlistfromvalid(ac->valid, ftok->isCpp(), tokenList); for (const Token *tok = tokenList.front(); tok; tok = tok->next()) { if (Token::Match(tok, "%num% : %num%") && argvalue >= MathLib::toDoubleNumber(tok->str()) && argvalue <= MathLib::toDoubleNumber(tok->strAt(2))) return true; @@ -1738,13 +1738,14 @@ bool Library::hasAnyTypeCheck(const std::string& typeName) const std::shared_ptr createTokenFromExpression(const std::string& returnValue, const Settings* settings, + bool cpp, std::unordered_map* lookupVarId) { std::shared_ptr tokenList = std::make_shared(settings); { const std::string code = "return " + returnValue + ";"; std::istringstream istr(code); - if (!tokenList->createTokens(istr)) + if (!tokenList->createTokens(istr, cpp ? Standards::Language::CPP : Standards::Language::C)) return nullptr; } diff --git a/lib/library.h b/lib/library.h index 40d2c6187e81..11d59c676cde 100644 --- a/lib/library.h +++ b/lib/library.h @@ -607,6 +607,7 @@ CPPCHECKLIB const Library::Container * getLibraryContainer(const Token * tok); std::shared_ptr createTokenFromExpression(const std::string& returnValue, const Settings* settings, + bool cpp, std::unordered_map* lookupVarId = nullptr); /// @} diff --git a/lib/programmemory.cpp b/lib/programmemory.cpp index b5558233206f..5442df9a3852 100644 --- a/lib/programmemory.cpp +++ b/lib/programmemory.cpp @@ -1596,7 +1596,7 @@ namespace { arg_map[argn] = v; argn++; } - return evaluateLibraryFunction(arg_map, returnValue, settings); + return evaluateLibraryFunction(arg_map, returnValue, settings, ftok->isCpp()); } } } @@ -1752,7 +1752,8 @@ std::vector execute(const Scope* scope, ProgramMemory& pm, con ValueFlow::Value evaluateLibraryFunction(const std::unordered_map& args, const std::string& returnValue, - const Settings* settings) + const Settings* settings, + bool cpp) { thread_local static std::unordered_map& arg)>> @@ -1760,7 +1761,7 @@ ValueFlow::Value evaluateLibraryFunction(const std::unordered_map lookupVarId; - std::shared_ptr expr = createTokenFromExpression(returnValue, settings, &lookupVarId); + std::shared_ptr expr = createTokenFromExpression(returnValue, settings, cpp, &lookupVarId); functions[returnValue] = [lookupVarId, expr, settings](const std::unordered_map& xargs) { diff --git a/lib/programmemory.h b/lib/programmemory.h index 17ff751d4e35..717284efb24c 100644 --- a/lib/programmemory.h +++ b/lib/programmemory.h @@ -211,7 +211,8 @@ ProgramMemory getProgramMemory(const Token* tok, const Token* expr, const ValueF ValueFlow::Value evaluateLibraryFunction(const std::unordered_map& args, const std::string& returnValue, - const Settings* settings); + const Settings* settings, + bool cpp); #endif diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index ab8a6fe080f0..df3fe33aa588 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -7585,7 +7585,7 @@ void SymbolDatabase::setValueTypeInTokenList(bool reportDebugWarnings, Token *to ValueType valuetype; TokenList tokenList(&mSettings); std::istringstream istr(typestr+";"); - tokenList.createTokens(istr); + tokenList.createTokens(istr, tok->isCpp() ? Standards::Language::CPP : Standards::Language::C); tokenList.simplifyStdType(); if (parsedecl(tokenList.front(), &valuetype, mDefaultSignedness, mSettings, mIsCpp)) { valuetype.originalTypeName = typestr; @@ -7675,7 +7675,7 @@ void SymbolDatabase::setValueTypeInTokenList(bool reportDebugWarnings, Token *to } TokenList tokenList(&mSettings); std::istringstream istr(typestr+";"); - if (tokenList.createTokens(istr)) { + if (tokenList.createTokens(istr, tok->isCpp() ? Standards::Language::CPP : Standards::Language::C)) { ValueType vt; tokenList.simplifyPlatformTypes(); tokenList.simplifyStdType(); diff --git a/lib/token.h b/lib/token.h index a4594ba08652..0a4bd0591ea7 100644 --- a/lib/token.h +++ b/lib/token.h @@ -1479,7 +1479,6 @@ class CPPCHECKLIB Token { mImpl->mDebug = td; } - /** defaults to C++ if it cannot be determined */ bool isCpp() const; }; diff --git a/lib/tokenlist.cpp b/lib/tokenlist.cpp index b6e312625d93..b69e7c2fe955 100644 --- a/lib/tokenlist.cpp +++ b/lib/tokenlist.cpp @@ -17,6 +17,7 @@ */ //--------------------------------------------------------------------------- + #include "tokenlist.h" #include "astutils.h" @@ -40,6 +41,15 @@ #include +//#define N_ASSERT_LANG + +#ifndef N_ASSERT_LANG +#include +#define ASSERT_LANG(x) assert(x) +#else +#define ASSERT_LANG(x) +#endif + // How many compileExpression recursions are allowed? // For practical code this could be endless. But in some special torture test // there needs to be a limit. @@ -83,7 +93,7 @@ void TokenList::deallocateTokens() void TokenList::determineCppC() { - // only try to determine it if it wasn't enforced + // only try to determine if it wasn't enforced if (mLang == Standards::Language::None) { mLang = Path::identify(getSourceFilePath()); } @@ -317,8 +327,31 @@ void TokenList::insertTokens(Token *dest, const Token *src, nonneg int n) bool TokenList::createTokens(std::istream &code, const std::string& file0) { + ASSERT_LANG(!file0.empty()); + appendFileIfNew(file0); + return createTokensInternal(code, file0); +} + +//--------------------------------------------------------------------------- + +bool TokenList::createTokens(std::istream &code, Standards::Language lang) +{ + ASSERT_LANG(lang != Standards::Language::None); + if (mLang == Standards::Language::None) { + mLang = lang; + } else { + ASSERT_LANG(lang == mLang); + } + + return createTokensInternal(code, ""); +} + +//--------------------------------------------------------------------------- + +bool TokenList::createTokensInternal(std::istream &code, const std::string& file0) +{ simplecpp::OutputList outputList; simplecpp::TokenList tokens(code, mFiles, file0, &outputList); @@ -2096,3 +2129,33 @@ bool TokenList::isKeyword(const std::string &str) const static const auto& latest_c_keywords = Keywords::getAll(Standards::cstd_t::CLatest); return latest_c_keywords.find(str) != latest_c_keywords.end(); } + +bool TokenList::isC() const +{ + ASSERT_LANG(mLang != Standards::Language::None); + + // TODO: remove the fallback + if (mLang == Standards::Language::None) + return false; // treat as C++ by default + + return mLang == Standards::Language::C; +} + +bool TokenList::isCPP() const +{ + ASSERT_LANG(mLang != Standards::Language::None); + + // TODO: remove the fallback + if (mLang == Standards::Language::None) + return true; // treat as C++ by default + + return mLang == Standards::Language::CPP; +} + +void TokenList::setLang(Standards::Language lang) +{ + ASSERT_LANG(lang != Standards::Language::None); + ASSERT_LANG(mLang == Standards::Language::None); + + mLang = lang; +} diff --git a/lib/tokenlist.h b/lib/tokenlist.h index b359137cf33f..9c621a7eeac7 100644 --- a/lib/tokenlist.h +++ b/lib/tokenlist.h @@ -61,15 +61,13 @@ class CPPCHECKLIB TokenList { /** @return the source file path. e.g. "file.cpp" */ const std::string& getSourceFilePath() const; - /** Is the code C. Used for bailouts */ - bool isC() const { - return mLang == Standards::Language::C; - } + /** @return true if the code is C */ + bool isC() const; - /** Is the code CPP. Used for bailouts */ - bool isCPP() const { - return mLang == Standards::Language::CPP; - } + /** @return true if the code is C++ */ + bool isCPP() const; + + void setLang(Standards::Language lang); /** * Delete all tokens in given token list @@ -105,7 +103,8 @@ class CPPCHECKLIB TokenList { * @param code input stream for code * @param file0 source file name */ - bool createTokens(std::istream &code, const std::string& file0 = emptyString); + bool createTokens(std::istream &code, const std::string& file0); + bool createTokens(std::istream &code, Standards::Language lang); void createTokens(simplecpp::TokenList&& tokenList); @@ -203,6 +202,8 @@ class CPPCHECKLIB TokenList { private: void determineCppC(); + bool createTokensInternal(std::istream &code, const std::string& file0); + /** Token list */ TokensFrontBack mTokensFrontBack; diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index 062dfcc868ef..c9528664a9be 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -3810,20 +3810,20 @@ static bool isNotEqual(std::pair x, std::pair x, const std::string& y) +static bool isNotEqual(std::pair x, const std::string& y, bool cpp) { TokenList tokenList(nullptr); std::istringstream istr(y); - tokenList.createTokens(istr); + tokenList.createTokens(istr, cpp ? Standards::Language::CPP : Standards::Language::C); return isNotEqual(x, std::make_pair(tokenList.front(), tokenList.back())); } -static bool isNotEqual(std::pair x, const ValueType* y) +static bool isNotEqual(std::pair x, const ValueType* y, bool cpp) { if (y == nullptr) return false; if (y->originalTypeName.empty()) return false; - return isNotEqual(x, y->originalTypeName); + return isNotEqual(x, y->originalTypeName, cpp); } static bool isDifferentType(const Token* src, const Token* dst) @@ -3838,9 +3838,9 @@ static bool isDifferentType(const Token* src, const Token* dst) std::pair parentdecl = Token::typeDecl(dst); if (isNotEqual(decl, parentdecl)) return true; - if (isNotEqual(decl, dst->valueType())) + if (isNotEqual(decl, dst->valueType(), dst->isCpp())) return true; - if (isNotEqual(parentdecl, src->valueType())) + if (isNotEqual(parentdecl, src->valueType(), src->isCpp())) return true; } return false; @@ -7680,7 +7680,7 @@ static void valueFlowLibraryFunction(Token *tok, const std::string &returnValue, if (returnValue.find("arg") != std::string::npos && argValues.empty()) return; productParams(settings, argValues, [&](const std::unordered_map& arg) { - ValueFlow::Value value = evaluateLibraryFunction(arg, returnValue, &settings); + ValueFlow::Value value = evaluateLibraryFunction(arg, returnValue, &settings, tok->isCpp()); if (value.isUninitValue()) return; ValueFlow::Value::ValueKind kind = ValueFlow::Value::ValueKind::Known; @@ -9174,11 +9174,11 @@ static bool getMinMaxValues(const ValueType *vt, const Platform &platform, MathL return true; } -static bool getMinMaxValues(const std::string &typestr, const Settings &settings, MathLib::bigint &minvalue, MathLib::bigint &maxvalue) +static bool getMinMaxValues(const std::string &typestr, const Settings &settings, bool cpp, MathLib::bigint &minvalue, MathLib::bigint &maxvalue) { TokenList typeTokens(&settings); std::istringstream istr(typestr+";"); - if (!typeTokens.createTokens(istr)) + if (!typeTokens.createTokens(istr, cpp ? Standards::Language::CPP : Standards::Language::C)) return false; typeTokens.simplifyPlatformTypes(); typeTokens.simplifyStdType(); @@ -9300,7 +9300,7 @@ static void valueFlowUnknownFunctionReturn(TokenList &tokenlist, const Settings // Get min/max values for return type const std::string &typestr = settings.library.returnValueType(tok->previous()); MathLib::bigint minvalue, maxvalue; - if (!getMinMaxValues(typestr, settings, minvalue, maxvalue)) + if (!getMinMaxValues(typestr, settings, tok->isCpp(), minvalue, maxvalue)) continue; for (MathLib::bigint value : unknownValues) { diff --git a/test/testlibrary.cpp b/test/testlibrary.cpp index 6e1968064f61..f26fa3b28b61 100644 --- a/test/testlibrary.cpp +++ b/test/testlibrary.cpp @@ -119,7 +119,7 @@ class TestLibrary : public TestFixture { TokenList tokenList(nullptr); std::istringstream istr("foo();"); - tokenList.createTokens(istr); + tokenList.createTokens(istr, Standards::Language::CPP); tokenList.front()->next()->astOperand1(tokenList.front()); Library library; @@ -142,14 +142,14 @@ class TestLibrary : public TestFixture { { TokenList tokenList(nullptr); std::istringstream istr("fred.foo(123);"); // <- wrong scope, not library function - tokenList.createTokens(istr); + tokenList.createTokens(istr, Standards::Language::CPP); ASSERT(library.isNotLibraryFunction(tokenList.front()->tokAt(2))); } { TokenList tokenList(nullptr); std::istringstream istr("Fred::foo(123);"); // <- wrong scope, not library function - tokenList.createTokens(istr); + tokenList.createTokens(istr, Standards::Language::CPP); ASSERT(library.isNotLibraryFunction(tokenList.front()->tokAt(2))); } @@ -165,7 +165,7 @@ class TestLibrary : public TestFixture { TokenList tokenList(nullptr); std::istringstream istr("foo();"); // <- too few arguments, not library function - tokenList.createTokens(istr); + tokenList.createTokens(istr, Standards::Language::CPP); Token::createMutualLinks(tokenList.front()->next(), tokenList.back()->previous()); tokenList.createAst(); @@ -189,7 +189,7 @@ class TestLibrary : public TestFixture { { TokenList tokenList(nullptr); std::istringstream istr("foo();"); // <- too few arguments, not library function - tokenList.createTokens(istr); + tokenList.createTokens(istr, Standards::Language::CPP); Token::createMutualLinks(tokenList.front()->next(), tokenList.back()->previous()); tokenList.createAst(); @@ -198,7 +198,7 @@ class TestLibrary : public TestFixture { { TokenList tokenList(nullptr); std::istringstream istr("foo(a);"); // <- library function - tokenList.createTokens(istr); + tokenList.createTokens(istr, Standards::Language::CPP); Token::createMutualLinks(tokenList.front()->next(), tokenList.back()->previous()); tokenList.createAst(); @@ -207,7 +207,7 @@ class TestLibrary : public TestFixture { { TokenList tokenList(nullptr); std::istringstream istr("foo(a, b);"); // <- library function - tokenList.createTokens(istr); + tokenList.createTokens(istr, Standards::Language::CPP); Token::createMutualLinks(tokenList.front()->next(), tokenList.back()->previous()); tokenList.createAst(); @@ -216,7 +216,7 @@ class TestLibrary : public TestFixture { { TokenList tokenList(nullptr); std::istringstream istr("foo(a, b, c);"); // <- too much arguments, not library function - tokenList.createTokens(istr); + tokenList.createTokens(istr, Standards::Language::CPP); Token::createMutualLinks(tokenList.front()->next(), tokenList.back()->previous()); tokenList.createAst(); @@ -234,7 +234,7 @@ class TestLibrary : public TestFixture { TokenList tokenList(nullptr); std::istringstream istr("Fred foo(123);"); // <- Variable declaration, not library function - tokenList.createTokens(istr); + tokenList.createTokens(istr, Standards::Language::CPP); tokenList.front()->next()->astOperand1(tokenList.front()); tokenList.front()->next()->varId(1); @@ -294,7 +294,7 @@ class TestLibrary : public TestFixture { TokenList tokenList(nullptr); std::istringstream istr("foo(a,b,c,d,e);"); - tokenList.createTokens(istr); + tokenList.createTokens(istr, Standards::Language::CPP); tokenList.front()->next()->astOperand1(tokenList.front()); ASSERT_EQUALS(false, library.isuninitargbad(tokenList.front(), 1)); @@ -319,7 +319,7 @@ class TestLibrary : public TestFixture { TokenList tokenList(nullptr); std::istringstream istr("foo(a,b,c,d);"); - tokenList.createTokens(istr); + tokenList.createTokens(istr, Standards::Language::CPP); tokenList.front()->next()->astOperand1(tokenList.front()); ASSERT(Library::ArgumentChecks::Direction::DIR_IN == library.getArgDirection(tokenList.front(), 1)); @@ -351,7 +351,7 @@ class TestLibrary : public TestFixture { TokenList tokenList(nullptr); std::istringstream istr("foo(a,b,c,d,e,f,g,h,i,j,k);"); - tokenList.createTokens(istr); + tokenList.createTokens(istr, Standards::Language::CPP); tokenList.front()->next()->astOperand1(tokenList.front()); // 1- @@ -493,7 +493,7 @@ class TestLibrary : public TestFixture { TokenList tokenList(nullptr); std::istringstream istr("foo(a,b,c,d,e);"); - tokenList.createTokens(istr); + tokenList.createTokens(istr, Standards::Language::CPP); tokenList.front()->next()->astOperand1(tokenList.front()); // arg1: type=strlen arg2 @@ -556,14 +556,14 @@ class TestLibrary : public TestFixture { { TokenList tokenList(nullptr); std::istringstream istr("Foo::foo();"); - tokenList.createTokens(istr); + tokenList.createTokens(istr, Standards::Language::CPP); ASSERT(library.isnotnoreturn(tokenList.front()->tokAt(2))); } { TokenList tokenList(nullptr); std::istringstream istr("bar();"); - tokenList.createTokens(istr); + tokenList.createTokens(istr, Standards::Language::CPP); ASSERT(library.isnotnoreturn(tokenList.front())); } } @@ -637,7 +637,7 @@ class TestLibrary : public TestFixture { TokenList tokenList(nullptr); std::istringstream istr("a(); b();"); - tokenList.createTokens(istr); + tokenList.createTokens(istr, Standards::Language::CPP); const Library::WarnInfo* a = library.getWarnInfo(tokenList.front()); const Library::WarnInfo* b = library.getWarnInfo(tokenList.front()->tokAt(4)); diff --git a/test/testsimplifytypedef.cpp b/test/testsimplifytypedef.cpp index a63538f346b8..000820f354fb 100644 --- a/test/testsimplifytypedef.cpp +++ b/test/testsimplifytypedef.cpp @@ -254,7 +254,7 @@ class TestSimplifyTypedef : public TestFixture { Tokenizer tokenizer(settings1, this); std::istringstream istr(code); - tokenizer.list.createTokens(istr); + tokenizer.list.createTokens(istr, Standards::Language::CPP); tokenizer.createLinks(); tokenizer.simplifyTypedef(); diff --git a/test/testtoken.cpp b/test/testtoken.cpp index 8850d295e275..f6a782bcec23 100644 --- a/test/testtoken.cpp +++ b/test/testtoken.cpp @@ -33,10 +33,12 @@ class TestToken : public TestFixture { public: - TestToken() : TestFixture("TestToken") {} + TestToken() : TestFixture("TestToken") { + list.setLang(Standards::Language::C); + } private: - const TokenList list{nullptr}; + /*const*/ TokenList list{nullptr}; std::vector arithmeticalOps; std::vector logicalOps;