diff --git a/.selfcheck_suppressions b/.selfcheck_suppressions index ec7f8fcb705..1b6dcc1965b 100644 --- a/.selfcheck_suppressions +++ b/.selfcheck_suppressions @@ -2,7 +2,7 @@ missingIncludeSystem # should not be reported - see #13387 checkersReport # false positive - see #14308 -nullPointerRedundantCheck:externals/simplecpp/simplecpp.cpp:3247 +nullPointerRedundantCheck:externals/simplecpp/simplecpp.cpp:3246 # warnings in Qt generated code we cannot fix funcArgNamesDifferent:*/moc_checkthread.cpp diff --git a/externals/simplecpp/simplecpp.cpp b/externals/simplecpp/simplecpp.cpp index 8e10ca54d9e..581c9b10990 100644 --- a/externals/simplecpp/simplecpp.cpp +++ b/externals/simplecpp/simplecpp.cpp @@ -33,7 +33,6 @@ #include #include #include -#include #include #include #include @@ -182,8 +181,6 @@ static std::string replaceAll(std::string s, const std::string& from, const std: return s; } -const std::string simplecpp::Location::emptyFileName; - void simplecpp::Location::adjust(const std::string &str) { if (strpbrk(str.c_str(), "\r\n") == nullptr) { @@ -416,13 +413,16 @@ class StdCharBufStream : public simplecpp::TokenList::Stream { class FileStream : public simplecpp::TokenList::Stream { public: + /** + * @throws simplecpp::Output thrown if file is not found + */ // cppcheck-suppress uninitDerivedMemberVar - we call Stream::init() to initialize the private members explicit FileStream(const std::string &filename, std::vector &files) : file(fopen(filename.c_str(), "rb")) { if (!file) { files.push_back(filename); - throw simplecpp::Output(simplecpp::Output::FILE_NOT_FOUND, simplecpp::Location(files), "File is missing: " + filename); + throw simplecpp::Output(simplecpp::Output::FILE_NOT_FOUND, {}, "File is missing: " + filename); } init(); } @@ -489,7 +489,7 @@ simplecpp::TokenList::TokenList(const std::string &filename, std::vectorpush_back(e); } } @@ -564,11 +564,11 @@ void simplecpp::TokenList::dump(bool linenrs) const std::string simplecpp::TokenList::stringify(bool linenrs) const { std::ostringstream ret; - Location loc(files); + Location loc; bool filechg = true; for (const Token *tok = cfront(); tok; tok = tok->next) { if (tok->location.line < loc.line || tok->location.fileIndex != loc.fileIndex) { - ret << "\n#line " << tok->location.line << " \"" << tok->location.file() << "\"\n"; + ret << "\n#line " << tok->location.line << " \"" << file(tok->location) << "\"\n"; loc = tok->location; filechg = true; } @@ -633,16 +633,16 @@ static bool isStringLiteralPrefix(const std::string &str) str == "R" || str == "uR" || str == "UR" || str == "LR" || str == "u8R"; } -void simplecpp::TokenList::lineDirective(unsigned int fileIndex, unsigned int line, Location *location) +void simplecpp::TokenList::lineDirective(unsigned int fileIndex, unsigned int line, Location &location) { - if (fileIndex != location->fileIndex || line >= location->line) { - location->fileIndex = fileIndex; - location->line = line; + if (fileIndex != location.fileIndex || line >= location.line) { + location.fileIndex = fileIndex; + location.line = line; return; } - if (line + 2 >= location->line) { - location->line = line; + if (line + 2 >= location.line) { + location.line = line; while (cback()->op != '#') deleteToken(back()); deleteToken(back()); @@ -660,10 +660,7 @@ void simplecpp::TokenList::readfile(Stream &stream, const std::string &filename, const Token *oldLastToken = nullptr; - Location location(files); - location.fileIndex = fileIndex(filename); - location.line = 1U; - location.col = 1U; + Location location(fileIndex(filename), 1, 1); while (stream.good()) { unsigned char ch = stream.readChar(); if (!stream.good()) @@ -732,7 +729,7 @@ void simplecpp::TokenList::readfile(Stream &stream, const std::string &filename, while (numtok->comment) numtok = numtok->previous; lineDirective(fileIndex(replaceAll(strtok->str().substr(1U, strtok->str().size() - 2U),"\\\\","\\")), - std::atol(numtok->str().c_str()), &location); + std::atol(numtok->str().c_str()), location); } // #line 3 else if (llNextToken->str() == "line" && @@ -741,7 +738,7 @@ void simplecpp::TokenList::readfile(Stream &stream, const std::string &filename, const Token *numtok = cback(); while (numtok->comment) numtok = numtok->previous; - lineDirective(location.fileIndex, std::atol(numtok->str().c_str()), &location); + lineDirective(location.fileIndex, std::atol(numtok->str().c_str()), location); } } // #endfile @@ -1478,6 +1475,12 @@ unsigned int simplecpp::TokenList::fileIndex(const std::string &filename) return files.size() - 1U; } +const std::string& simplecpp::TokenList::file(const Location& loc) const +{ + static const std::string s_emptyFileName; + return loc.fileIndex < files.size() ? files[loc.fileIndex] : s_emptyFileName; +} + namespace simplecpp { class Macro; @@ -1487,6 +1490,9 @@ namespace simplecpp { public: explicit Macro(std::vector &f) : nameTokDef(nullptr), valueToken(nullptr), endToken(nullptr), files(f), tokenListDefine(f), variadic(false), variadicOpt(false), valueDefinedInCode_(false) {} + /** + * @throws std::runtime_error thrown on bad macro syntax + */ Macro(const Token *tok, std::vector &f) : nameTokDef(nullptr), files(f), tokenListDefine(f), valueDefinedInCode_(true) { if (sameline(tok->previousSkipComments(), tok)) throw std::runtime_error("bad macro syntax"); @@ -1503,6 +1509,9 @@ namespace simplecpp { throw std::runtime_error("bad macro syntax"); } + /** + * @throws std::runtime_error thrown on bad macro syntax + */ Macro(const std::string &name, const std::string &value, std::vector &f) : nameTokDef(nullptr), files(f), tokenListDefine(f), valueDefinedInCode_(false) { const std::string def(name + ' ' + value); StdCharBufStream stream(reinterpret_cast(def.data()), def.size()); @@ -1551,7 +1560,9 @@ namespace simplecpp { * @param macros list of macros * @param inputFiles the input files * @return token after macro - * @throw Can throw wrongNumberOfParameters or invalidHashHash + * @throws Error thrown on missing or invalid preprocessor directives + * @throws wrongNumberOfParameters thrown on invalid number of parameters + * @throws invalidHashHash thrown on invalid ## usage */ const Token * expand(TokenList & output, const Token * rawtok, @@ -1885,7 +1896,7 @@ namespace simplecpp { usageList.push_back(loc); if (nameTokInst->str() == "__FILE__") { - output.push_back(new Token('\"'+loc.file()+'\"', loc)); + output.push_back(new Token('\"'+output.file(loc)+'\"', loc)); return nameTokInst->next; } if (nameTokInst->str() == "__LINE__") { @@ -2543,7 +2554,9 @@ namespace simplecpp { } } -/** Evaluate sizeof(type) */ +/** Evaluate sizeof(type) + * @throws std::runtime_error thrown on missing arguments or invalid expression + */ static void simplifySizeof(simplecpp::TokenList &expr, const std::map &sizeOfType) { for (simplecpp::Token *tok = expr.front(); tok; tok = tok->next) { @@ -2611,6 +2624,10 @@ static std::string dirPath(const std::string& path, bool withTrailingSlash=true) } static std::string openHeader(std::ifstream &f, const simplecpp::DUI &dui, const std::string &sourcefile, const std::string &header, bool systemheader); + +/** Evaluate __has_include(include) + * @throws std::runtime_error thrown on missing arguments or invalid expression + */ static void simplifyHasInclude(simplecpp::TokenList &expr, const simplecpp::DUI &dui) { if (!isCpp17OrLater(dui) && !isGnu(dui)) @@ -2637,7 +2654,7 @@ static void simplifyHasInclude(simplecpp::TokenList &expr, const simplecpp::DUI } } - const std::string &sourcefile = tok->location.file(); + const std::string &sourcefile = expr.file(tok->location); const bool systemheader = (tok1 && tok1->op == '<'); std::string header; if (systemheader) { @@ -2667,6 +2684,9 @@ static void simplifyHasInclude(simplecpp::TokenList &expr, const simplecpp::DUI } } +/** Evaluate name + * @throws std::runtime_error thrown on undefined function-like macro + */ static void simplifyName(simplecpp::TokenList &expr) { for (simplecpp::Token *tok = expr.front(); tok; tok = tok->next) { @@ -2695,7 +2715,7 @@ static void simplifyName(simplecpp::TokenList &expr) * unsigned long long value, updating pos to point to the first * unused element of s. * Returns ULLONG_MAX if the result is not representable and - * throws if the above requirements were not possible to satisfy. + * @throws std::runtime_error thrown if the above requirements were not possible to satisfy. */ static unsigned long long stringToULLbounded( const std::string& s, @@ -2715,34 +2735,6 @@ static unsigned long long stringToULLbounded( return value; } -/* Converts character literal (including prefix, but not ud-suffix) - * to long long value. - * - * Assumes ASCII-compatible single-byte encoded str for narrow literals - * and UTF-8 otherwise. - * - * For target assumes - * - execution character set encoding matching str - * - UTF-32 execution wide-character set encoding - * - requirements for __STDC_UTF_16__, __STDC_UTF_32__ and __STDC_ISO_10646__ satisfied - * - char16_t is 16bit wide - * - char32_t is 32bit wide - * - wchar_t is 32bit wide and unsigned - * - matching char signedness to host - * - matching sizeof(int) to host - * - * For host assumes - * - ASCII-compatible execution character set - * - * For host and target assumes - * - CHAR_BIT == 8 - * - two's complement - * - * Implements multi-character narrow literals according to GCC's behavior, - * except multi code unit universal character names are not supported. - * Multi-character wide literals are not supported. - * Limited support of universal character names for non-UTF-8 execution character set encodings. - */ long long simplecpp::characterLiteralToLL(const std::string& str) { // default is wide/utf32 @@ -2936,6 +2928,9 @@ long long simplecpp::characterLiteralToLL(const std::string& str) return multivalue; } +/** + * @throws std::runtime_error thrown on invalid literal + */ static void simplifyNumbers(simplecpp::TokenList &expr) { for (simplecpp::Token *tok = expr.front(); tok; tok = tok->next) { @@ -2958,6 +2953,10 @@ static void simplifyComments(simplecpp::TokenList &expr) } } +/** + * @throws std::runtime_error thrown on invalid literals, missing sizeof arguments or invalid expressions, + * missing __has_include() arguments or expressions, undefined function-like macros, invalid number literals + */ static long long evaluate(simplecpp::TokenList &expr, const simplecpp::DUI &dui, const std::map &sizeOfType) { simplifyComments(expr); @@ -3179,7 +3178,7 @@ simplecpp::FileDataCache simplecpp::load(const simplecpp::TokenList &rawtokens, if (outputList) { simplecpp::Output err = { simplecpp::Output::EXPLICIT_INCLUDE_NOT_FOUND, - Location(filenames), + {}, "Can not open include file '" + filename + "' that is explicitly included." }; outputList->push_back(std::move(err)); @@ -3212,7 +3211,7 @@ simplecpp::FileDataCache simplecpp::load(const simplecpp::TokenList &rawtokens, if (!rawtok || rawtok->str() != INCLUDE) continue; - const std::string &sourcefile = rawtok->location.file(); + const std::string &sourcefile = rawtokens.file(rawtok->location); const Token * const htok = rawtok->nextSkipComments(); if (!sameline(rawtok, htok)) @@ -3369,7 +3368,7 @@ void simplecpp::preprocess(simplecpp::TokenList &output, const simplecpp::TokenL if (outputList) { simplecpp::Output err = { Output::DUI_ERROR, - Location(files), + {}, "unknown standard specified: '" + dui.std + "'" }; outputList->push_back(std::move(err)); @@ -3539,7 +3538,7 @@ void simplecpp::preprocess(simplecpp::TokenList &output, const simplecpp::TokenL const bool systemheader = (inctok->str()[0] == '<'); const std::string header(inctok->str().substr(1U, inctok->str().size() - 2U)); - const FileData *const filedata = cache.get(rawtok->location.file(), header, dui, systemheader, files, outputList).first; + const FileData *const filedata = cache.get(rawtokens.file(rawtok->location), header, dui, systemheader, files, outputList).first; if (filedata == nullptr) { if (outputList) { simplecpp::Output out = { @@ -3632,7 +3631,7 @@ void simplecpp::preprocess(simplecpp::TokenList &output, const simplecpp::TokenL tok = tok->next; bool closingAngularBracket = false; if (tok) { - const std::string &sourcefile = rawtok->location.file(); + const std::string &sourcefile = rawtokens.file(rawtok->location); const bool systemheader = (tok && tok->op == '<'); std::string header; @@ -3691,7 +3690,7 @@ void simplecpp::preprocess(simplecpp::TokenList &output, const simplecpp::TokenL const long long result = evaluate(expr, dui, sizeOfType); conditionIsTrue = (result != 0); } - } catch (const std::exception &e) { + } catch (const std::runtime_error &e) { if (outputList) { std::string msg = "failed to evaluate " + std::string(rawtok->str() == IF ? "#if" : "#elif") + " condition"; if (e.what() && *e.what()) @@ -3740,7 +3739,7 @@ void simplecpp::preprocess(simplecpp::TokenList &output, const simplecpp::TokenL macros.erase(tok->str()); } } else if (ifstates.top() == True && rawtok->str() == PRAGMA && rawtok->next && rawtok->next->str() == ONCE && sameline(rawtok,rawtok->next)) { - pragmaOnce.insert(rawtok->location.file()); + pragmaOnce.insert(rawtokens.file(rawtok->location)); } if (ifstates.top() != True && rawtok->nextcond) rawtok = rawtok->nextcond->previous; @@ -3796,7 +3795,7 @@ void simplecpp::preprocess(simplecpp::TokenList &output, const simplecpp::TokenL const std::list& temp = maybeUsedMacros[macro.name()]; usage.insert(usage.end(), temp.begin(), temp.end()); for (std::list::const_iterator usageIt = usage.begin(); usageIt != usage.end(); ++usageIt) { - MacroUsage mu(usageIt->files, macro.valueDefinedInCode()); + MacroUsage mu(macro.valueDefinedInCode()); mu.macroName = macro.name(); mu.macroLocation = macro.defineLocation(); mu.useLocation = *usageIt; diff --git a/externals/simplecpp/simplecpp.h b/externals/simplecpp/simplecpp.h index 15187063c90..9a847d14969 100644 --- a/externals/simplecpp/simplecpp.h +++ b/externals/simplecpp/simplecpp.h @@ -69,25 +69,61 @@ namespace simplecpp { enum cppstd_t : std::int8_t { CPPUnknown=-1, CPP03, CPP11, CPP14, CPP17, CPP20, CPP23, CPP26 }; using TokenString = std::string; + +#if defined(__cpp_lib_string_view) && !defined(__cpp_lib_span) + using View = std::string_view; +#else + struct View + { + // cppcheck-suppress noExplicitConstructor + View(const char* data) + : mData(data) + , mSize(strlen(data)) + {} + + // only provide when std::span is not available so using untyped initilization won't use View +#if !defined(__cpp_lib_span) + View(const char* data, std::size_t size) + : mData(data) + , mSize(size) + {} + + // cppcheck-suppress noExplicitConstructor + View(const std::string& str) + : mData(str.data()) + , mSize(str.size()) + {} +#endif // !defined(__cpp_lib_span) + + const char* data() const { + return mData; + } + + std::size_t size() const { + return mSize; + } + + private: + const char* mData; + std::size_t mSize; + }; +#endif // defined(__cpp_lib_string_view) && !defined(__cpp_lib_span) + class Macro; /** * Location in source code */ - class SIMPLECPP_LIB Location { - public: - explicit Location(const std::vector &f) : files(f) {} + struct SIMPLECPP_LIB Location { + Location() = default; + Location(unsigned int fileIndex, unsigned int line, unsigned int col) + : fileIndex(fileIndex) + , line(line) + , col(col) + {} Location(const Location &loc) = default; - - Location &operator=(const Location &other) { - if (this != &other) { - fileIndex = other.fileIndex; - line = other.line; - col = other.col; - } - return *this; - } + Location &operator=(const Location &other) = default; /** increment this location by string */ void adjust(const std::string &str); @@ -104,16 +140,9 @@ namespace simplecpp { return fileIndex == other.fileIndex && line == other.line; } - const std::string& file() const { - return fileIndex < files.size() ? files[fileIndex] : emptyFileName; - } - - const std::vector &files; unsigned int fileIndex{}; unsigned int line{1}; unsigned int col{}; - private: - static const std::string emptyFileName; }; /** @@ -228,7 +257,6 @@ namespace simplecpp { explicit TokenList(std::vector &filenames); /** generates a token list from the given std::istream parameter */ TokenList(std::istream &istr, std::vector &filenames, const std::string &filename=std::string(), OutputList *outputList = nullptr); -#ifdef SIMPLECPP_TOKENLIST_ALLOW_PTR /** generates a token list from the given buffer */ template TokenList(const char (&data)[size], std::vector &filenames, const std::string &filename=std::string(), OutputList *outputList = nullptr) @@ -239,7 +267,7 @@ namespace simplecpp { TokenList(const unsigned char (&data)[size], std::vector &filenames, const std::string &filename=std::string(), OutputList *outputList = nullptr) : TokenList(data, size-1, filenames, filename, outputList, 0) {} - +#ifdef SIMPLECPP_TOKENLIST_ALLOW_PTR /** generates a token list from the given buffer */ TokenList(const unsigned char* data, std::size_t size, std::vector &filenames, const std::string &filename=std::string(), OutputList *outputList = nullptr) : TokenList(data, size, filenames, filename, outputList, 0) @@ -248,13 +276,11 @@ namespace simplecpp { TokenList(const char* data, std::size_t size, std::vector &filenames, const std::string &filename=std::string(), OutputList *outputList = nullptr) : TokenList(reinterpret_cast(data), size, filenames, filename, outputList, 0) {} -#endif -#if defined(__cpp_lib_string_view) && !defined(__cpp_lib_span) +#endif // SIMPLECPP_TOKENLIST_ALLOW_PTR /** generates a token list from the given buffer */ - TokenList(std::string_view data, std::vector &filenames, const std::string &filename=std::string(), OutputList *outputList = nullptr) + TokenList(View data, std::vector &filenames, const std::string &filename=std::string(), OutputList *outputList = nullptr) : TokenList(reinterpret_cast(data.data()), data.size(), filenames, filename, outputList, 0) {} -#endif #ifdef __cpp_lib_span /** generates a token list from the given buffer */ TokenList(std::span data, std::vector &filenames, const std::string &filename=std::string(), OutputList *outputList = nullptr) @@ -265,7 +291,7 @@ namespace simplecpp { TokenList(std::span data, std::vector &filenames, const std::string &filename=std::string(), OutputList *outputList = nullptr) : TokenList(data.data(), data.size(), filenames, filename, outputList, 0) {} -#endif +#endif // __cpp_lib_span /** generates a token list from the given filename parameter */ TokenList(const std::string &filename, std::vector &filenames, OutputList *outputList = nullptr); @@ -341,22 +367,30 @@ namespace simplecpp { return files; } + const std::string& file(const Location& loc) const; + private: TokenList(const unsigned char* data, std::size_t size, std::vector &filenames, const std::string &filename, OutputList *outputList, int unused); void combineOperators(); void constFoldUnaryNotPosNeg(Token *tok); + /** + * @throws std::overflow_error thrown on overflow or division by zero + */ void constFoldMulDivRem(Token *tok); void constFoldAddSub(Token *tok); void constFoldShift(Token *tok); void constFoldComparison(Token *tok); void constFoldBitwise(Token *tok); void constFoldLogicalOp(Token *tok); + /** + * @throws std::runtime_error thrown on invalid expressions + */ void constFoldQuestionOp(Token *&tok1); std::string readUntil(Stream &stream, const Location &location, char start, char end, OutputList *outputList); - void lineDirective(unsigned int fileIndex, unsigned int line, Location *location); + void lineDirective(unsigned int fileIndex, unsigned int line, Location &location); const Token* lastLineTok(int maxsize=1000) const; const Token* isLastLinePreprocessor(int maxsize=1000) const; @@ -370,7 +404,7 @@ namespace simplecpp { /** Tracking how macros are used */ struct SIMPLECPP_LIB MacroUsage { - explicit MacroUsage(const std::vector &f, bool macroValueKnown_) : macroLocation(f), useLocation(f), macroValueKnown(macroValueKnown_) {} + explicit MacroUsage(bool macroValueKnown_) : macroValueKnown(macroValueKnown_) {} std::string macroName; Location macroLocation; Location useLocation; @@ -510,6 +544,34 @@ namespace simplecpp { id_map_type mIdMap; }; + /** Converts character literal (including prefix, but not ud-suffix) to long long value. + * + * Assumes ASCII-compatible single-byte encoded str for narrow literals + * and UTF-8 otherwise. + * + * For target assumes + * - execution character set encoding matching str + * - UTF-32 execution wide-character set encoding + * - requirements for __STDC_UTF_16__, __STDC_UTF_32__ and __STDC_ISO_10646__ satisfied + * - char16_t is 16bit wide + * - char32_t is 32bit wide + * - wchar_t is 32bit wide and unsigned + * - matching char signedness to host + * - matching sizeof(int) to host + * + * For host assumes + * - ASCII-compatible execution character set + * + * For host and target assumes + * - CHAR_BIT == 8 + * - two's complement + * + * Implements multi-character narrow literals according to GCC's behavior, + * except multi code unit universal character names are not supported. + * Multi-character wide literals are not supported. + * Limited support of universal character names for non-UTF-8 execution character set encodings. + * @throws std::runtime_error thrown on invalid literal + */ SIMPLECPP_LIB long long characterLiteralToLL(const std::string& str); SIMPLECPP_LIB FileDataCache load(const TokenList &rawtokens, std::vector &filenames, const DUI &dui, OutputList *outputList = nullptr, FileDataCache cache = {}); diff --git a/lib/cppcheck.cpp b/lib/cppcheck.cpp index 7a637c8b7b3..c9eaa6fadaa 100644 --- a/lib/cppcheck.cpp +++ b/lib/cppcheck.cpp @@ -1154,12 +1154,12 @@ unsigned int CppCheck::checkInternal(const FileWithDetails& file, const std::str } else { // #error etc during preprocessing - configurationError.push_back((currentConfig.empty() ? "\'\'" : currentConfig) + " : [" + o->location.file() + ':' + std::to_string(o->location.line) + "] " + o->msg); + configurationError.push_back((currentConfig.empty() ? "\'\'" : currentConfig) + " : [" + tokensP.file(o->location) + ':' + std::to_string(o->location.line) + "] " + o->msg); --checkCount; // don't count invalid configurations if (!hasValidConfig && currCfg == *configurations.rbegin()) { // If there is no valid configuration then report error.. - preprocessor.error(o->location.file(), o->location.line, o->location.col, o->msg, o->type); + preprocessor.error(tokensP.file(o->location), o->location.line, o->location.col, o->msg, o->type); } skipCfg = true; } diff --git a/lib/preprocessor.cpp b/lib/preprocessor.cpp index 636e5a848a1..5979dc4b45a 100644 --- a/lib/preprocessor.cpp +++ b/lib/preprocessor.cpp @@ -45,8 +45,8 @@ static bool sameline(const simplecpp::Token *tok1, const simplecpp::Token *tok2) return tok1 && tok2 && tok1->location.sameline(tok2->location); } -Directive::Directive(const simplecpp::Location & _loc, std::string _str) : - file(_loc.file()), +Directive::Directive(const simplecpp::TokenList &tokens, const simplecpp::Location & _loc, std::string _str) : + file(tokens.file(_loc)), linenr(_loc.line), str(std::move(_str)) {} @@ -78,7 +78,7 @@ namespace { }; } -static bool parseInlineSuppressionCommentToken(const simplecpp::Token *tok, std::list &inlineSuppressions, std::list &bad) +static bool parseInlineSuppressionCommentToken(const simplecpp::TokenList &tokens, const simplecpp::Token *tok, std::list &inlineSuppressions, std::list &bad) { const std::string cppchecksuppress("cppcheck-suppress"); @@ -91,7 +91,7 @@ static bool parseInlineSuppressionCommentToken(const simplecpp::Token *tok, std: if (comment.substr(pos1, cppchecksuppress.size()) != cppchecksuppress) return false; if (pos1 + cppchecksuppress.size() >= comment.size()) { - bad.emplace_back(tok->location.file(), tok->location.line, 0, "suppression without error ID"); + bad.emplace_back(tokens.file(tok->location), tok->location.line, 0, "suppression without error ID"); return false; } @@ -101,7 +101,7 @@ static bool parseInlineSuppressionCommentToken(const simplecpp::Token *tok, std: // skip spaces after "cppcheck-suppress" and its possible prefix const std::string::size_type pos2 = comment.find_first_not_of(' ', posEndComment); if (pos2 == std::string::npos) { - bad.emplace_back(tok->location.file(), tok->location.line, 0, "suppression without error ID"); + bad.emplace_back(tokens.file(tok->location), tok->location.line, 0, "suppression without error ID"); return false; } @@ -111,7 +111,7 @@ static bool parseInlineSuppressionCommentToken(const simplecpp::Token *tok, std: if (posEndComment >= (pos1 + cppchecksuppress.size() + 1)) { const std::string suppressCmdString = comment.substr(pos1, pos2-pos1-1); if (comment.at(pos1 + cppchecksuppress.size()) != '-') { - bad.emplace_back(tok->location.file(), tok->location.line, 0, "unknown suppression type '" + suppressCmdString + "'"); // TODO: set column + bad.emplace_back(tokens.file(tok->location), tok->location.line, 0, "unknown suppression type '" + suppressCmdString + "'"); // TODO: set column return false; } @@ -130,7 +130,7 @@ static bool parseInlineSuppressionCommentToken(const simplecpp::Token *tok, std: else if ("macro" == suppressTypeString) errorType = SuppressionList::Type::macro; else { - bad.emplace_back(tok->location.file(), tok->location.line, 0, "unknown suppression type '" + suppressCmdString + "'"); // TODO: set column + bad.emplace_back(tokens.file(tok->location), tok->location.line, 0, "unknown suppression type '" + suppressCmdString + "'"); // TODO: set column return false; } } @@ -148,7 +148,7 @@ static bool parseInlineSuppressionCommentToken(const simplecpp::Token *tok, std: // TODO: return false? if (!errmsg.empty()) - bad.emplace_back(tok->location.file(), tok->location.line, tok->location.col, std::move(errmsg)); + bad.emplace_back(tokens.file(tok->location), tok->location.line, tok->location.col, std::move(errmsg)); // TODO: report ones without ID - return false? std::copy_if(suppressions.cbegin(), suppressions.cend(), std::back_inserter(inlineSuppressions), [](const SuppressionList::Suppression& s) { @@ -172,16 +172,16 @@ static bool parseInlineSuppressionCommentToken(const simplecpp::Token *tok, std: // TODO: unreachable? // TODO: return false? if (!errmsg.empty()) - bad.emplace_back(tok->location.file(), tok->location.line, tok->location.col, std::move(errmsg)); + bad.emplace_back(tokens.file(tok->location), tok->location.line, tok->location.col, std::move(errmsg)); } return true; } -static std::string getRelativeFilename(const simplecpp::Token* tok, const Settings &settings) { +static std::string getRelativeFilename(const simplecpp::TokenList &tokens, const simplecpp::Token* tok, const Settings &settings) { if (!tok) return ""; - std::string relativeFilename(tok->location.file()); + std::string relativeFilename(tokens.file(tok->location)); if (settings.relativePaths) { for (const std::string & basePath : settings.basePaths) { const std::string bp = basePath + "/"; @@ -206,7 +206,7 @@ static void addInlineSuppressions(const simplecpp::TokenList &tokens, const Sett } std::list inlineSuppressions; - if (!parseInlineSuppressionCommentToken(tok, inlineSuppressions, bad)) + if (!parseInlineSuppressionCommentToken(tokens, tok, inlineSuppressions, bad)) continue; if (!sameline(tok->previous, tok)) { @@ -215,7 +215,7 @@ static void addInlineSuppressions(const simplecpp::TokenList &tokens, const Sett tok = tok->next; while (tok->comment) { - parseInlineSuppressionCommentToken(tok, inlineSuppressions, bad); + parseInlineSuppressionCommentToken(tokens, tok, inlineSuppressions, bad); if (tok->next) { tok = tok->next; } else { @@ -233,7 +233,7 @@ static void addInlineSuppressions(const simplecpp::TokenList &tokens, const Sett continue; // Relative filename - const std::string relativeFilename = getRelativeFilename(tok, settings); + const std::string relativeFilename = getRelativeFilename(tokens, tok, settings); // Macro name std::string macroName; @@ -354,7 +354,7 @@ std::list Preprocessor::createDirectives() const continue; if (tok->next && tok->next->str() == "endfile") continue; - Directive directive(tok->location, ""); + Directive directive(mTokens, tok->location, ""); for (const simplecpp::Token *tok2 = tok; tok2 && tok2->location.line == directive.linenr; tok2 = tok2->next) { if (tok2->comment) continue; @@ -825,7 +825,7 @@ std::string Preprocessor::getcode(const std::string &cfg, std::vectornext) { if (writeLocations && tok->location.fileIndex != prevfile) { - ret << "\n#line " << tok->location.line << " \"" << tok->location.file() << "\"\n"; + ret << "\n#line " << tok->location.line << " \"" << mTokens.file(tok->location) << "\"\n"; prevfile = tok->location.fileIndex; line = tok->location.line; } @@ -853,7 +853,7 @@ const simplecpp::Output* Preprocessor::reportOutput(const simplecpp::OutputList case simplecpp::Output::ERROR: out_ret = &out; if (!startsWith(out.msg,"#error") || showerror) - error(out.location.file(), out.location.line, out.location.col, out.msg, out.type); + error(mTokens.file(out.location), out.location.line, out.location.col, out.msg, out.type); break; case simplecpp::Output::WARNING: case simplecpp::Output::PORTABILITY_BACKSLASH: @@ -863,14 +863,14 @@ const simplecpp::Output* Preprocessor::reportOutput(const simplecpp::OutputList const std::string::size_type pos1 = out.msg.find_first_of("<\""); const std::string::size_type pos2 = out.msg.find_first_of(">\"", pos1 + 1U); if (pos1 < pos2 && pos2 != std::string::npos) - missingInclude(out.location.file(), out.location.line, out.location.col, out.msg.substr(pos1+1, pos2-pos1-1), out.msg[pos1] == '\"' ? UserHeader : SystemHeader); + missingInclude(mTokens.file(out.location), out.location.line, out.location.col, out.msg.substr(pos1+1, pos2-pos1-1), out.msg[pos1] == '\"' ? UserHeader : SystemHeader); } break; case simplecpp::Output::INCLUDE_NESTED_TOO_DEEPLY: case simplecpp::Output::SYNTAX_ERROR: case simplecpp::Output::UNHANDLED_CHAR_ERROR: out_ret = &out; - error(out.location.file(), out.location.line, out.location.col, out.msg, out.type); + error(mTokens.file(out.location), out.location.line, out.location.col, out.msg, out.type); break; case simplecpp::Output::EXPLICIT_INCLUDE_NOT_FOUND: case simplecpp::Output::FILE_NOT_FOUND: @@ -983,10 +983,10 @@ void Preprocessor::dump(std::ostream &out) const for (const simplecpp::MacroUsage ¯oUsage: mMacroUsage) { out << " " << std::endl; for (const simplecpp::IfCond &ifCond: mIfCond) { out << " location.line, remarkText); diff --git a/lib/preprocessor.h b/lib/preprocessor.h index 3264566f855..f8f213b13df 100644 --- a/lib/preprocessor.h +++ b/lib/preprocessor.h @@ -68,7 +68,7 @@ struct CPPCHECKLIB Directive { std::vector strTokens; /** record a directive (possibly filtering src) */ - Directive(const simplecpp::Location & _loc, std::string _str); + Directive(const simplecpp::TokenList &tokens, const simplecpp::Location & _loc, std::string _str); }; class CPPCHECKLIB RemarkComment { diff --git a/test/testunusedvar.cpp b/test/testunusedvar.cpp index 5b94a1f7fba..ef3bba226f4 100644 --- a/test/testunusedvar.cpp +++ b/test/testunusedvar.cpp @@ -1633,9 +1633,10 @@ class TestUnusedVar : public TestFixture { void structmember15() { // #3088 std::list directives; std::vector f = { "test.cpp" }; - simplecpp::Location loc(f); + simplecpp::TokenList tokenList(f); + simplecpp::Location loc; loc.line = 1; - directives.emplace_back(loc, "#pragma pack(1)"); + directives.emplace_back(tokenList, loc, "#pragma pack(1)"); checkStructMemberUsage("\nstruct Foo { int x; int y; };", dinit(CheckStructMemberUsageOptions, $.directives = &directives)); ASSERT_EQUALS("", errout_str()); }