From 5f9bf441afa520cd5691ce9776c26ef9a42c3aa1 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 [skip ci] --- lib/clangimport.cpp | 7 +++- lib/cppcheck.cpp | 7 ++-- 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.cpp | 1 + lib/token.h | 2 +- lib/tokenlist.cpp | 65 +++++++++++++++++++++++++++++++++++- lib/tokenlist.h | 15 +++++---- lib/valueflow.cpp | 20 +++++------ test/testlibrary.cpp | 32 +++++++++--------- test/testsimplifytypedef.cpp | 2 +- test/testtoken.cpp | 2 ++ 16 files changed, 133 insertions(+), 54 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 cc8829c0a335..d35c7e6d120e 100644 --- a/lib/cppcheck.cpp +++ b/lib/cppcheck.cpp @@ -635,9 +635,12 @@ unsigned int CppCheck::checkFile(const std::string& filename, const std::string try { if (mSettings.library.markupFile(filename)) { + // 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 +807,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 ea3878ebe079..868a39d2bddb 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 6b082514f141..2e74d3797110 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 ae2bc481ed9f..96a8e8d71ffb 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -7491,7 +7491,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; @@ -7581,7 +7581,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.cpp b/lib/token.cpp index 82c0081dc6fc..a3d2f91ab99f 100644 --- a/lib/token.cpp +++ b/lib/token.cpp @@ -2752,5 +2752,6 @@ bool Token::isCpp() const if (mTokensFrontBack) { return mTokensFrontBack->list.isCPP(); } + assert(false); return true; // assume C++ by default } diff --git a/lib/token.h b/lib/token.h index a889416d1de6..c6be8b4d6802 100644 --- a/lib/token.h +++ b/lib/token.h @@ -154,7 +154,7 @@ class CPPCHECKLIB Token { // for usage in TestToken only Token(); - TokensFrontBack* mTokensFrontBack{}; + TokensFrontBack* const mTokensFrontBack{}; public: Token(const Token &) = delete; diff --git a/lib/tokenlist.cpp b/lib/tokenlist.cpp index f2568cb8691d..df1750c518a7 100644 --- a/lib/tokenlist.cpp +++ b/lib/tokenlist.cpp @@ -17,6 +17,9 @@ */ //--------------------------------------------------------------------------- + +#define ASSERT_LANG + #include "tokenlist.h" #include "astutils.h" @@ -30,6 +33,9 @@ #include "standards.h" #include "token.h" +#ifdef ASSERT_LANG +#include +#endif #include #include #include @@ -83,7 +89,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 +323,37 @@ void TokenList::insertTokens(Token *dest, const Token *src, nonneg int n) bool TokenList::createTokens(std::istream &code, const std::string& file0) { +#ifdef ASSERT_LANG + assert(!file0.empty()); +#endif + appendFileIfNew(file0); + return createTokensInternal(code, file0); +} + +//--------------------------------------------------------------------------- + +bool TokenList::createTokens(std::istream &code, Standards::Language lang) +{ +#ifdef ASSERT_LANG + assert(lang != Standards::Language::None); +#endif + if (mLang == Standards::Language::None) { + mLang = lang; + } else { +#ifdef ASSERT_LANG + assert(lang == mLang); +#endif + } + + 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 +2131,31 @@ 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 +{ +#ifdef ASSERT_LANG + assert(mLang != Standards::Language::None); +#endif + + return mLang == Standards::Language::C; +} + +bool TokenList::isCPP() const +{ +#ifdef ASSERT_LANG + assert(mLang != Standards::Language::None); +#endif + + return mLang == Standards::Language::CPP; +} + +void TokenList::setLang(Standards::Language lang) +{ +#ifdef ASSERT_LANG + assert(lang != Standards::Language::None); + assert(mLang == Standards::Language::None); +#endif + + mLang = lang; +} diff --git a/lib/tokenlist.h b/lib/tokenlist.h index b359137cf33f..6e022710fd52 100644 --- a/lib/tokenlist.h +++ b/lib/tokenlist.h @@ -62,14 +62,12 @@ class CPPCHECKLIB TokenList { const std::string& getSourceFilePath() const; /** Is the code C. Used for bailouts */ - bool isC() const { - return mLang == Standards::Language::C; - } + bool isC() const; /** Is the code CPP. Used for bailouts */ - bool isCPP() const { - return mLang == Standards::Language::CPP; - } + 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 e181bf3cc89e..8c6708b219d8 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -3808,20 +3808,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) @@ -3836,9 +3836,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; @@ -7668,7 +7668,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; @@ -9162,11 +9162,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(); @@ -9288,7 +9288,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 b3096edffcbc..63c5480a2dcf 100644 --- a/test/testsimplifytypedef.cpp +++ b/test/testsimplifytypedef.cpp @@ -252,7 +252,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 19ba3df23403..325756c395ca 100644 --- a/test/testtoken.cpp +++ b/test/testtoken.cpp @@ -483,6 +483,7 @@ class TestToken : public TestFixture { void deleteLast() const { TokenList list(nullptr); + list.setLang(Standards::Language::C); TokensFrontBack listEnds(list); Token ** const tokensBack = &(listEnds.back); Token tok(&listEnds); @@ -494,6 +495,7 @@ class TestToken : public TestFixture { void deleteFirst() const { TokenList list(nullptr); + list.setLang(Standards::Language::C); TokensFrontBack listEnds(list); Token ** const tokensFront = &(listEnds.front); Token tok(&listEnds);