diff --git a/.github/workflows/CI-unixish.yml b/.github/workflows/CI-unixish.yml index f745a21e177..c69ae08dab0 100644 --- a/.github/workflows/CI-unixish.yml +++ b/.github/workflows/CI-unixish.yml @@ -542,7 +542,7 @@ jobs: ./cppcheck $selfcheck_options $cppcheck_options --cppcheck-build-dir=b1 --addon=naming.json --enable=internal lib || ec=1 # check gui with qt settings mkdir b2 - ./cppcheck $selfcheck_options $cppcheck_options --cppcheck-build-dir=b2 -DQT_VERSION=0x060000 -DQ_MOC_OUTPUT_REVISION=68 -DQT_CHARTS_LIB --library=qt --addon=naming.json -Icmake.output/gui -Ifrontend -Igui gui/*.cpp cmake.output/gui || ec=1 + ./cppcheck $selfcheck_options $cppcheck_options --cppcheck-build-dir=b2 -DQT_VERSION=0x060000 -DQ_MOC_OUTPUT_REVISION=68 -DQT_CHARTS_LIB -DQT_FEATURE_shortcut -DQT_FEATURE_tooltip -DQT_FEATURE_statustip --library=qt --addon=naming.json -Icmake.output/gui -Ifrontend -Igui gui/*.cpp cmake.output/gui || ec=1 # self check test and tools ./cppcheck $selfcheck_options $cppcheck_options -Ifrontend -Icli test/*.cpp || ec=1 ./cppcheck $selfcheck_options $cppcheck_options -Icli tools/dmake/*.cpp || ec=1 diff --git a/.github/workflows/selfcheck.yml b/.github/workflows/selfcheck.yml index d58178a5c1a..fa67e60346a 100644 --- a/.github/workflows/selfcheck.yml +++ b/.github/workflows/selfcheck.yml @@ -80,7 +80,7 @@ jobs: - name: Self check (unusedFunction) if: false # TODO: fails with preprocessorErrorDirective - see #10667 run: | - ./cppcheck -q --template=selfcheck --error-exitcode=1 --library=cppcheck-lib --library=qt -D__CPPCHECK__ -D__GNUC__ -DQT_VERSION=0x060000 -DQ_MOC_OUTPUT_REVISION=69 -DQT_CHARTS_LIB -DQT_MOC_HAS_STRINGDATA --enable=unusedFunction --exception-handling -rp=. --project=cmake.output/compile_commands.json --suppressions-list=.selfcheck_unused_suppressions --inline-suppr + ./cppcheck -q --template=selfcheck --error-exitcode=1 --library=cppcheck-lib --library=qt -D__CPPCHECK__ -D__GNUC__ -DQT_VERSION=0x060000 -DQ_MOC_OUTPUT_REVISION=69 -DQT_CHARTS_LIB -DQT_MOC_HAS_STRINGDATA --enable=unusedFunction --exception-handling -rp=. --project=cmake.output/compile_commands.json --suppressions-list=.selfcheck_unused_suppressions --inline-suppr -DQT_FEATURE_shortcut -DQT_FEATURE_tooltip -DQT_FEATURE_statustip env: DISABLE_VALUEFLOW: 1 UNUSEDFUNCTION_ONLY: 1 @@ -105,7 +105,7 @@ jobs: # TODO: find a way to report unmatched suppressions without need to add information checks - name: Self check (unusedFunction / no test) run: | - ./cppcheck -q --template=selfcheck --error-exitcode=1 --library=cppcheck-lib --library=qt -D__CPPCHECK__ -D__GNUC__ -DQT_VERSION=0x060000 -DQ_MOC_OUTPUT_REVISION=69 -DQT_CHARTS_LIB -DQT_MOC_HAS_STRINGDATA --enable=unusedFunction --exception-handling -rp=. --project=cmake.output.notest/compile_commands.json --suppressions-list=.selfcheck_unused_suppressions --inline-suppr + ./cppcheck -q --template=selfcheck --error-exitcode=1 --library=cppcheck-lib --library=qt -D__CPPCHECK__ -D__GNUC__ -DQT_VERSION=0x060000 -DQ_MOC_OUTPUT_REVISION=69 -DQT_CHARTS_LIB -DQT_MOC_HAS_STRINGDATA --enable=unusedFunction --exception-handling -rp=. --project=cmake.output.notest/compile_commands.json --suppressions-list=.selfcheck_unused_suppressions --inline-suppr -DQT_FEATURE_shortcut -DQT_FEATURE_tooltip -DQT_FEATURE_statustip env: DISABLE_VALUEFLOW: 1 UNUSEDFUNCTION_ONLY: 1 @@ -148,7 +148,7 @@ jobs: - name: Self check (unusedFunction / no test / no cli) if: false # TODO: the findings are currently too intrusive run: | - ./cppcheck -q --template=selfcheck --error-exitcode=1 --library=cppcheck-lib --library=qt -D__CPPCHECK__ -D__GNUC__ -DQT_VERSION=0x060000 -DQ_MOC_OUTPUT_REVISION=69 -DQT_CHARTS_LIB -DQT_MOC_HAS_STRINGDATA --enable=unusedFunction --exception-handling -rp=. --project=cmake.output.notest_nocli/compile_commands.json --suppressions-list=.selfcheck_unused_suppressions --inline-suppr + ./cppcheck -q --template=selfcheck --error-exitcode=1 --library=cppcheck-lib --library=qt -D__CPPCHECK__ -D__GNUC__ -DQT_VERSION=0x060000 -DQ_MOC_OUTPUT_REVISION=69 -DQT_CHARTS_LIB -DQT_MOC_HAS_STRINGDATA --enable=unusedFunction --exception-handling -rp=. --project=cmake.output.notest_nocli/compile_commands.json --suppressions-list=.selfcheck_unused_suppressions --inline-suppr -DQT_FEATURE_shortcut -DQT_FEATURE_tooltip -DQT_FEATURE_statustip env: DISABLE_VALUEFLOW: 1 UNUSEDFUNCTION_ONLY: 1 @@ -176,7 +176,7 @@ jobs: - name: Self check (unusedFunction / corpus / no test / callgrind) run: | # TODO: fix -rp so the suppressions actually work - valgrind --tool=callgrind ./cppcheck --template=selfcheck --error-exitcode=0 --library=cppcheck-lib --library=qt -D__GNUC__ -DQT_VERSION=0x060000 -DQ_MOC_OUTPUT_REVISION=69 -DQT_CHARTS_LIB -DQT_MOC_HAS_STRINGDATA --enable=unusedFunction --exception-handling -rp=. --project=cmake.output.corpus/compile_commands.json --suppressions-list=.selfcheck_unused_suppressions --inline-suppr 2>callgrind.log || (cat callgrind.log && false) + valgrind --tool=callgrind ./cppcheck --template=selfcheck --error-exitcode=0 --library=cppcheck-lib --library=qt -D__GNUC__ -DQT_VERSION=0x060000 -DQ_MOC_OUTPUT_REVISION=69 -DQT_CHARTS_LIB -DQT_MOC_HAS_STRINGDATA --enable=unusedFunction --exception-handling -rp=. --project=cmake.output.corpus/compile_commands.json --suppressions-list=.selfcheck_unused_suppressions --inline-suppr -DQT_FEATURE_shortcut -DQT_FEATURE_tooltip -DQT_FEATURE_statustip 2>callgrind.log || (cat callgrind.log && false) cat callgrind.log callgrind_annotate --auto=no > callgrind.annotated.log head -50 callgrind.annotated.log diff --git a/.github/workflows/ubsan.yml b/.github/workflows/ubsan.yml index 11dc26a8ec3..bf84c53a960 100644 --- a/.github/workflows/ubsan.yml +++ b/.github/workflows/ubsan.yml @@ -145,7 +145,7 @@ jobs: ./cmake.output/bin/cppcheck $selfcheck_options $cppcheck_options --addon=naming.json frontend || ec=1 ./cmake.output/bin/cppcheck $selfcheck_options $cppcheck_options --addon=naming.json -Ifrontend cli || ec=1 ./cmake.output/bin/cppcheck $selfcheck_options $cppcheck_options --addon=naming.json --enable=internal lib || ec=1 - ./cmake.output/bin/cppcheck $selfcheck_options $cppcheck_options -DQT_VERSION=0x060000 -DQ_MOC_OUTPUT_REVISION=69 -DQT_CHARTS_LIB -DQT_MOC_HAS_STRINGDATA --library=qt --addon=naming.json -Icmake.output/gui -Ifrontend -Igui gui/*.cpp cmake.output/gui/*.cpp || ec=1 + ./cmake.output/bin/cppcheck $selfcheck_options $cppcheck_options -DQT_VERSION=0x060000 -DQ_MOC_OUTPUT_REVISION=69 -DQT_CHARTS_LIB -DQT_MOC_HAS_STRINGDATA -DQT_FEATURE_shortcut -DQT_FEATURE_tooltip -DQT_FEATURE_statustip --library=qt --addon=naming.json -Icmake.output/gui -Ifrontend -Igui gui/*.cpp cmake.output/gui/*.cpp || ec=1 ./cmake.output/bin/cppcheck $selfcheck_options $cppcheck_options -Icli -Ifrontend test/*.cpp || ec=1 ./cmake.output/bin/cppcheck $selfcheck_options $cppcheck_options -Icli tools/dmake/*.cpp || ec=1 ./cmake.output/bin/cppcheck $selfcheck_options $cppcheck_options -DQ_MOC_OUTPUT_REVISION=69 -DQT_CHARTS_LIB -DQT_MOC_HAS_STRINGDATA --library=qt -Icmake.output/tools/triage -Igui tools/triage/*.cpp cmake.output/tools/triage/*.cpp || ec=1 diff --git a/cfg/qt.cfg b/cfg/qt.cfg index 12f31c4d0f6..5dc96e95ec7 100644 --- a/cfg/qt.cfg +++ b/cfg/qt.cfg @@ -5428,6 +5428,8 @@ + + diff --git a/cfg/wxwidgets.cfg b/cfg/wxwidgets.cfg index 685750f7ff2..a32c1f024a9 100644 --- a/cfg/wxwidgets.cfg +++ b/cfg/wxwidgets.cfg @@ -736,6 +736,7 @@ + diff --git a/externals/simplecpp/simplecpp.cpp b/externals/simplecpp/simplecpp.cpp index 599ffdfe408..c0f6e2c01b6 100755 --- a/externals/simplecpp/simplecpp.cpp +++ b/externals/simplecpp/simplecpp.cpp @@ -31,12 +31,10 @@ #include #include #include -#if __cplusplus >= 201103L #ifdef SIMPLECPP_WINDOWS #include #endif #include -#endif #include #include @@ -51,18 +49,6 @@ #undef ERROR #endif -#if __cplusplus >= 201103L -#define OVERRIDE override -#define EXPLICIT explicit -#else -#define OVERRIDE -#define EXPLICIT -#endif - -#if (__cplusplus < 201103L) && !defined(__APPLE__) -#define nullptr NULL -#endif - static bool isHex(const std::string &s) { return s.size()>2 && (s.compare(0,2,"0x")==0 || s.compare(0,2,"0X")==0); @@ -368,22 +354,22 @@ class simplecpp::TokenList::Stream { class StdIStream : public simplecpp::TokenList::Stream { public: // cppcheck-suppress uninitDerivedMemberVar - we call Stream::init() to initialize the private members - EXPLICIT StdIStream(std::istream &istr) + explicit StdIStream(std::istream &istr) : istr(istr) { assert(istr.good()); init(); } - virtual int get() OVERRIDE { + virtual int get() override { return istr.get(); } - virtual int peek() OVERRIDE { + virtual int peek() override { return istr.peek(); } - virtual void unget() OVERRIDE { + virtual void unget() override { istr.unget(); } - virtual bool good() OVERRIDE { + virtual bool good() override { return istr.good(); } @@ -402,20 +388,20 @@ class StdCharBufStream : public simplecpp::TokenList::Stream { init(); } - virtual int get() OVERRIDE { + virtual int get() override { if (pos >= size) return lastStatus = EOF; return str[pos++]; } - virtual int peek() OVERRIDE { + virtual int peek() override { if (pos >= size) return lastStatus = EOF; return str[pos]; } - virtual void unget() OVERRIDE { + virtual void unget() override { --pos; } - virtual bool good() OVERRIDE { + virtual bool good() override { return lastStatus != EOF; } @@ -429,7 +415,7 @@ class StdCharBufStream : public simplecpp::TokenList::Stream { class FileStream : public simplecpp::TokenList::Stream { public: // cppcheck-suppress uninitDerivedMemberVar - we call Stream::init() to initialize the private members - EXPLICIT FileStream(const std::string &filename, std::vector &files) + explicit FileStream(const std::string &filename, std::vector &files) : file(fopen(filename.c_str(), "rb")) , lastCh(0) , lastStatus(0) { @@ -440,25 +426,25 @@ class FileStream : public simplecpp::TokenList::Stream { init(); } - ~FileStream() OVERRIDE { + ~FileStream() override { fclose(file); file = nullptr; } - virtual int get() OVERRIDE { + virtual int get() override { lastStatus = lastCh = fgetc(file); return lastCh; } - virtual int peek() OVERRIDE{ + virtual int peek() override{ // keep lastCh intact const int ch = fgetc(file); unget_internal(ch); return ch; } - virtual void unget() OVERRIDE { + virtual void unget() override { unget_internal(lastCh); } - virtual bool good() OVERRIDE { + virtual bool good() override { return lastStatus != EOF; } @@ -519,12 +505,10 @@ simplecpp::TokenList::TokenList(const TokenList &other) : frontToken(nullptr), b *this = other; } -#if __cplusplus >= 201103L simplecpp::TokenList::TokenList(TokenList &&other) : frontToken(nullptr), backToken(nullptr), files(other.files) { *this = std::move(other); } -#endif simplecpp::TokenList::~TokenList() { @@ -543,7 +527,6 @@ simplecpp::TokenList &simplecpp::TokenList::operator=(const TokenList &other) return *this; } -#if __cplusplus >= 201103L simplecpp::TokenList &simplecpp::TokenList::operator=(TokenList &&other) { if (this != &other) { @@ -557,7 +540,6 @@ simplecpp::TokenList &simplecpp::TokenList::operator=(TokenList &&other) } return *this; } -#endif void simplecpp::TokenList::clear() { @@ -1477,15 +1459,11 @@ unsigned int simplecpp::TokenList::fileIndex(const std::string &filename) namespace simplecpp { class Macro; -#if __cplusplus >= 201103L using MacroMap = std::unordered_map; -#else - typedef std::map MacroMap; -#endif class Macro { public: - explicit Macro(std::vector &f) : nameTokDef(nullptr), valueToken(nullptr), endToken(nullptr), files(f), tokenListDefine(f), variadic(false), valueDefinedInCode_(false) {} + explicit Macro(std::vector &f) : nameTokDef(nullptr), valueToken(nullptr), endToken(nullptr), files(f), tokenListDefine(f), variadic(false), variadicOpt(false), optExpandValue(nullptr), optNoExpandValue(nullptr), valueDefinedInCode_(false) {} Macro(const Token *tok, std::vector &f) : nameTokDef(nullptr), files(f), tokenListDefine(f), valueDefinedInCode_(true) { if (sameline(tok->previousSkipComments(), tok)) @@ -1515,6 +1493,11 @@ namespace simplecpp { *this = other; } + ~Macro() { + delete optExpandValue; + delete optNoExpandValue; + } + Macro &operator=(const Macro &other) { if (this != &other) { files = other.files; @@ -1707,6 +1690,9 @@ namespace simplecpp { bool parseDefine(const Token *nametoken) { nameTokDef = nametoken; variadic = false; + variadicOpt = false; + optExpandValue = nullptr; + optNoExpandValue = nullptr; if (!nameTokDef) { valueToken = endToken = nullptr; args.clear(); @@ -1744,8 +1730,49 @@ namespace simplecpp { if (!sameline(valueToken, nameTokDef)) valueToken = nullptr; endToken = valueToken; - while (sameline(endToken, nameTokDef)) + while (sameline(endToken, nameTokDef)) { + if (variadic && endToken->str() == "__VA_OPT__") + variadicOpt = true; endToken = endToken->next; + } + + if (variadicOpt) { + TokenList expandValue(files); + TokenList noExpandValue(files); + for (const Token *tok = valueToken; tok && tok != endToken;) { + if (tok->str() == "__VA_OPT__") { + if (!sameline(tok, tok->next) || tok->next->op != '(') + throw Error(tok->location, "In definition of '" + nameTokDef->str() + "': Missing opening parenthesis for __VA_OPT__"); + tok = tok->next->next; + int par = 1; + while (tok && tok != endToken) { + if (tok->op == '(') + par++; + else if (tok->op == ')') + par--; + else if (tok->str() == "__VA_OPT__") + throw Error(tok->location, "In definition of '" + nameTokDef->str() + "': __VA_OPT__ cannot be nested"); + if (par == 0) { + tok = tok->next; + break; + } + expandValue.push_back(new Token(*tok)); + tok = tok->next; + } + if (par != 0) { + const Token *const lastTok = expandValue.back() ? expandValue.back() : valueToken->next; + throw Error(lastTok->location, "In definition of '" + nameTokDef->str() + "': Missing closing parenthesis for __VA_OPT__"); + } + } else { + expandValue.push_back(new Token(*tok)); + noExpandValue.push_back(new Token(*tok)); + tok = tok->next; + } + } + optExpandValue = new TokenList(std::move(expandValue)); + optNoExpandValue = new TokenList(std::move(noExpandValue)); + } + return true; } @@ -1900,8 +1927,22 @@ namespace simplecpp { Token * const output_end_1 = output->back(); + const Token *valueToken2; + const Token *endToken2; + + if (variadicOpt) { + if (parametertokens2.size() > args.size() && parametertokens2[args.size() - 1]->next->op != ')') + valueToken2 = optExpandValue->cfront(); + else + valueToken2 = optNoExpandValue->cfront(); + endToken2 = nullptr; + } else { + valueToken2 = valueToken; + endToken2 = endToken; + } + // expand - for (const Token *tok = valueToken; tok != endToken;) { + for (const Token *tok = valueToken2; tok != endToken2;) { if (tok->op != '#') { // A##B => AB if (sameline(tok, tok->next) && tok->next && tok->next->op == '#' && tok->next->next && tok->next->next->op == '#') { @@ -1950,7 +1991,7 @@ namespace simplecpp { } tok = tok->next; - if (tok == endToken) { + if (tok == endToken2) { output->push_back(new Token(*tok->previous)); break; } @@ -2020,24 +2061,6 @@ namespace simplecpp { // Macro parameter.. { TokenList temp(files); - if (tok->str() == "__VA_OPT__") { - if (sameline(tok, tok->next) && tok->next->str() == "(") { - tok = tok->next; - int paren = 1; - while (sameline(tok, tok->next)) { - if (tok->next->str() == "(") - ++paren; - else if (tok->next->str() == ")") - --paren; - if (paren == 0) - return tok->next->next; - tok = tok->next; - if (parametertokens.size() > args.size() && parametertokens.front()->next->str() != ")") - tok = expandToken(output, loc, tok, macros, expandedmacros, parametertokens)->previous; - } - } - throw Error(tok->location, "Missing parenthesis for __VA_OPT__(content)"); - } if (expandArg(&temp, tok, loc, macros, expandedmacros, parametertokens)) { if (tok->str() == "__VA_ARGS__" && temp.empty() && output->cback() && output->cback()->str() == "," && tok->nextSkipComments() && tok->nextSkipComments()->str() == ")") @@ -2338,6 +2361,13 @@ namespace simplecpp { /** is macro variadic? */ bool variadic; + /** does the macro expansion have __VA_OPT__? */ + bool variadicOpt; + + /** Expansion value for varadic macros with __VA_OPT__ expanded and discarded respectively */ + const TokenList *optExpandValue; + const TokenList *optNoExpandValue; + /** was the value of this macro actually defined in the code? */ bool valueDefinedInCode_; }; @@ -2380,47 +2410,9 @@ namespace simplecpp { #ifdef SIMPLECPP_WINDOWS -#if __cplusplus >= 201103L using MyMutex = std::mutex; template using MyLock = std::lock_guard; -#else -class MyMutex { -public: - MyMutex() { - InitializeCriticalSection(&m_criticalSection); - } - - ~MyMutex() { - DeleteCriticalSection(&m_criticalSection); - } - - CRITICAL_SECTION* lock() { - return &m_criticalSection; - } -private: - CRITICAL_SECTION m_criticalSection; -}; - -template -class MyLock { -public: - explicit MyLock(T& m) - : m_mutex(m) { - EnterCriticalSection(m_mutex.lock()); - } - - ~MyLock() { - LeaveCriticalSection(m_mutex.lock()); - } - -private: - MyLock& operator=(const MyLock&); - MyLock(const MyLock&); - - T& m_mutex; -}; -#endif class RealFileNameMap { public: @@ -2681,13 +2673,16 @@ static void simplifySizeof(simplecpp::TokenList &expr, const std::map= "201703L"); } +static bool isGnu(const simplecpp::DUI &dui) +{ + return dui.std.rfind("gnu", 0) != std::string::npos; +} static std::string currentDirectoryOSCalc() { const std::size_t size = 4096; @@ -2760,7 +2755,7 @@ static std::string extractRelativePathFromAbsolute(const std::string& absoluteSi static std::string openHeader(std::ifstream &f, const simplecpp::DUI &dui, const std::string &sourcefile, const std::string &header, bool systemheader); static void simplifyHasInclude(simplecpp::TokenList &expr, const simplecpp::DUI &dui) { - if (!isCpp17OrLater(dui)) + if (!isCpp17OrLater(dui) && !isGnu(dui)) return; for (simplecpp::Token *tok = expr.front(); tok; tok = tok->next) { @@ -2832,6 +2827,8 @@ static void simplifyName(simplecpp::TokenList &expr) if (alt) continue; } + if (tok->next && tok->next->str() == "(") + throw std::runtime_error("undefined function-like macro invocation: " + tok->str() + "( ... )"); tok->setstr("0"); } } @@ -3483,13 +3480,16 @@ void simplecpp::preprocess(simplecpp::TokenList &output, const simplecpp::TokenL // use a dummy vector for the macros because as this is not part of the file and would add an empty entry - e.g. /usr/include/poll.h std::vector dummy; - const bool hasInclude = isCpp17OrLater(dui); + const bool hasInclude = isCpp17OrLater(dui) || isGnu(dui); MacroMap macros; + bool strictAnsiDefined = false; for (std::list::const_iterator it = dui.defines.begin(); it != dui.defines.end(); ++it) { const std::string ¯ostr = *it; const std::string::size_type eq = macrostr.find('='); const std::string::size_type par = macrostr.find('('); const std::string macroname = macrostr.substr(0, std::min(eq,par)); + if (macroname == "__STRICT_ANSI__") + strictAnsiDefined = true; if (dui.undefined.find(macroname) != dui.undefined.end()) continue; const std::string lhs(macrostr.substr(0,eq)); @@ -3498,6 +3498,10 @@ void simplecpp::preprocess(simplecpp::TokenList &output, const simplecpp::TokenL macros.insert(std::pair(macro.name(), macro)); } + const bool strictAnsiUndefined = dui.undefined.find("__STRICT_ANSI__") != dui.undefined.cend(); + if (!isGnu(dui) && !strictAnsiDefined && !strictAnsiUndefined) + macros.insert(std::pair("__STRICT_ANSI__", Macro("__STRICT_ANSI__", "1", dummy))); + macros.insert(std::make_pair("__FILE__", Macro("__FILE__", "__FILE__", dummy))); macros.insert(std::make_pair("__LINE__", Macro("__LINE__", "__LINE__", dummy))); macros.insert(std::make_pair("__COUNTER__", Macro("__COUNTER__", "__COUNTER__", dummy))); @@ -3535,6 +3539,7 @@ void simplecpp::preprocess(simplecpp::TokenList &output, const simplecpp::TokenL // AlwaysFalse => drop all code in #if and #else enum IfState { True, ElseIsTrue, AlwaysFalse }; std::stack ifstates; + std::stack iftokens; ifstates.push(True); std::stack includetokenstack; @@ -3621,6 +3626,16 @@ void simplecpp::preprocess(simplecpp::TokenList &output, const simplecpp::TokenL } output.clear(); return; + } catch (simplecpp::Macro::Error &err) { + if (outputList) { + simplecpp::Output out(files); + out.type = simplecpp::Output::SYNTAX_ERROR; + out.location = err.location; + out.msg = "Failed to parse #define, " + err.what; + outputList->push_back(out); + } + output.clear(); + return; } } else if (ifstates.top() == True && rawtok->str() == INCLUDE) { TokenList inc1(files); @@ -3848,15 +3863,24 @@ void simplecpp::preprocess(simplecpp::TokenList &output, const simplecpp::TokenL ifstates.push(AlwaysFalse); else ifstates.push(conditionIsTrue ? True : ElseIsTrue); + iftokens.push(rawtok); } else if (ifstates.top() == True) { ifstates.top() = AlwaysFalse; + iftokens.top()->nextcond = rawtok; + iftokens.top() = rawtok; } else if (ifstates.top() == ElseIsTrue && conditionIsTrue) { ifstates.top() = True; + iftokens.top()->nextcond = rawtok; + iftokens.top() = rawtok; } } else if (rawtok->str() == ELSE) { ifstates.top() = (ifstates.top() == ElseIsTrue) ? True : AlwaysFalse; + iftokens.top()->nextcond = rawtok; + iftokens.top() = rawtok; } else if (rawtok->str() == ENDIF) { ifstates.pop(); + iftokens.top()->nextcond = rawtok; + iftokens.pop(); } else if (rawtok->str() == UNDEF) { if (ifstates.top() == True) { const Token *tok = rawtok->next; @@ -3868,7 +3892,10 @@ void simplecpp::preprocess(simplecpp::TokenList &output, const simplecpp::TokenL } else if (ifstates.top() == True && rawtok->str() == PRAGMA && rawtok->next && rawtok->next->str() == ONCE && sameline(rawtok,rawtok->next)) { pragmaOnce.insert(rawtok->location.file()); } - rawtok = gotoNextLine(rawtok); + if (ifstates.top() != True && rawtok->nextcond) + rawtok = rawtok->nextcond->previous; + else + rawtok = gotoNextLine(rawtok); continue; } @@ -4032,7 +4059,3 @@ std::string simplecpp::getCppStdString(const std::string &std) { return getCppStdString(getCppStd(std)); } - -#if (__cplusplus < 201103L) && !defined(__APPLE__) -#undef nullptr -#endif diff --git a/externals/simplecpp/simplecpp.h b/externals/simplecpp/simplecpp.h index f5c69593cb1..579e6e14ac6 100755 --- a/externals/simplecpp/simplecpp.h +++ b/externals/simplecpp/simplecpp.h @@ -27,10 +27,6 @@ # define SIMPLECPP_LIB #endif -#if (__cplusplus < 201103L) && !defined(__APPLE__) -#define nullptr NULL -#endif - #if defined(_MSC_VER) # pragma warning(push) // suppress warnings about "conversion from 'type1' to 'type2', possible loss of data" @@ -100,12 +96,12 @@ namespace simplecpp { class SIMPLECPP_LIB Token { public: Token(const TokenString &s, const Location &loc, bool wsahead = false) : - whitespaceahead(wsahead), location(loc), previous(nullptr), next(nullptr), string(s) { + whitespaceahead(wsahead), location(loc), previous(nullptr), next(nullptr), nextcond(nullptr), string(s) { flags(); } Token(const Token &tok) : - macro(tok.macro), op(tok.op), comment(tok.comment), name(tok.name), number(tok.number), whitespaceahead(tok.whitespaceahead), location(tok.location), previous(nullptr), next(nullptr), string(tok.string), mExpandedFrom(tok.mExpandedFrom) { + macro(tok.macro), op(tok.op), comment(tok.comment), name(tok.name), number(tok.number), whitespaceahead(tok.whitespaceahead), location(tok.location), previous(nullptr), next(nullptr), nextcond(nullptr), string(tok.string), mExpandedFrom(tok.mExpandedFrom) { } void flags() { @@ -141,6 +137,7 @@ namespace simplecpp { Location location; Token *previous; Token *next; + mutable const Token *nextcond; const Token *previousSkipComments() const { const Token *tok = this->previous; @@ -214,14 +211,10 @@ namespace simplecpp { /** generates a token list from the given filename parameter */ TokenList(const std::string &filename, std::vector &filenames, OutputList *outputList = nullptr); TokenList(const TokenList &other); -#if __cplusplus >= 201103L TokenList(TokenList &&other); -#endif ~TokenList(); TokenList &operator=(const TokenList &other); -#if __cplusplus >= 201103L TokenList &operator=(TokenList &&other); -#endif void clear(); bool empty() const { @@ -395,8 +388,4 @@ namespace simplecpp { # pragma warning(pop) #endif -#if (__cplusplus < 201103L) && !defined(__APPLE__) -#undef nullptr -#endif - #endif diff --git a/test/cli/inline-suppress_test.py b/test/cli/inline-suppress_test.py index 9c7421656d2..b84f45c209f 100644 --- a/test/cli/inline-suppress_test.py +++ b/test/cli/inline-suppress_test.py @@ -32,6 +32,8 @@ def test_1(): '-q', '--template=simple', '--inline-suppr', + '-DVER_CHECK(...)=0', + '--force', 'proj-inline-suppress' ] ret, stdout, stderr = cppcheck(args, cwd=__script_dir) @@ -44,6 +46,8 @@ def test_2(): args = [ '-q', '--template=simple', + '-DVER_CHECK(...)=0', + '--force', 'proj-inline-suppress' ] ret, stdout, stderr = cppcheck(args, cwd=__script_dir) @@ -461,6 +465,8 @@ def test_unmatched_cfg(): '--template=simple', '--enable=warning,information', '--inline-suppr', + '-DVER_CHECK(...)=0', + '--force', 'proj-inline-suppress/cfg.c' ]