diff --git a/externals/simplecpp/simplecpp.cpp b/externals/simplecpp/simplecpp.cpp index 7d48a7159..d174cbacb 100644 --- a/externals/simplecpp/simplecpp.cpp +++ b/externals/simplecpp/simplecpp.cpp @@ -70,6 +70,8 @@ static const simplecpp::TokenString ENDIF("endif"); static const simplecpp::TokenString PRAGMA("pragma"); static const simplecpp::TokenString ONCE("once"); +static const simplecpp::TokenString HAS_INCLUDE("__has_include"); + template static std::string toString(T t) { std::ostringstream ostr; @@ -1287,7 +1289,10 @@ namespace simplecpp { rawtokens2.push_back(new Token(rawtok->str(), rawtok1->location)); rawtok = rawtok->next; } - if (expand(&output2, rawtok1->location, rawtokens2.cfront(), macros, expandedmacros)) + bool first = true; + if (valueToken && valueToken->str() == rawtok1->str()) + first = false; + if (expand(&output2, rawtok1->location, rawtokens2.cfront(), macros, expandedmacros, first)) rawtok = rawtok1->next; } else { rawtok = expand(&output2, rawtok->location, rawtok, macros, expandedmacros); @@ -1517,8 +1522,10 @@ namespace simplecpp { return sameline(lpar,tok) ? tok : NULL; } - const Token * expand(TokenList * const output, const Location &loc, const Token * const nameTokInst, const std::map ¯os, std::set expandedmacros) const { - expandedmacros.insert(nameTokInst->str()); + const Token * expand(TokenList * const output, const Location &loc, const Token * const nameTokInst, const std::map ¯os, std::set expandedmacros, bool first=false) const { + + if (!first) + expandedmacros.insert(nameTokInst->str()); usageList.push_back(loc); @@ -2510,7 +2517,6 @@ std::map simplecpp::load(const simplecpp::To continue; bool systemheader = (htok->str()[0] == '<'); - const std::string header(realFilename(htok->str().substr(1U, htok->str().size() - 2U))); if (hasFile(ret, sourcefile, header, dui, systemheader)) continue; @@ -2580,6 +2586,7 @@ void simplecpp::preprocess(simplecpp::TokenList &output, const simplecpp::TokenL sizeOfType.insert(std::make_pair("double *", sizeof(double *))); sizeOfType.insert(std::make_pair("long double *", sizeof(long double *))); + const bool hasInclude = (dui.std.size() == 5 && dui.std.compare(0,3,"c++") == 0 && dui.std >= "c++17"); std::map macros; for (std::list::const_iterator it = dui.defines.begin(); it != dui.defines.end(); ++it) { const std::string ¯ostr = *it; @@ -2598,6 +2605,15 @@ void simplecpp::preprocess(simplecpp::TokenList &output, const simplecpp::TokenL macros.insert(std::make_pair("__LINE__", Macro("__LINE__", "__LINE__", files))); macros.insert(std::make_pair("__COUNTER__", Macro("__COUNTER__", "__COUNTER__", files))); + if (dui.std == "c++11") + macros.insert(std::make_pair("__cplusplus", Macro("__cplusplus", "201103L", files))); + else if (dui.std == "c++14") + macros.insert(std::make_pair("__cplusplus", Macro("__cplusplus", "201402L", files))); + else if (dui.std == "c++17") + macros.insert(std::make_pair("__cplusplus", Macro("__cplusplus", "201703L", files))); + else if (dui.std == "c++20") + macros.insert(std::make_pair("__cplusplus", Macro("__cplusplus", "202002L", files))); + // TRUE => code in current #if block should be kept // ELSE_IS_TRUE => code in current #if block should be dropped. the code in the #else should be kept. // ALWAYS_FALSE => drop all code in #if and #else @@ -2782,9 +2798,9 @@ void simplecpp::preprocess(simplecpp::TokenList &output, const simplecpp::TokenL if (ifstates.top() == ALWAYS_FALSE || (ifstates.top() == ELSE_IS_TRUE && rawtok->str() != ELIF)) conditionIsTrue = false; else if (rawtok->str() == IFDEF) - conditionIsTrue = (macros.find(rawtok->next->str()) != macros.end()); + conditionIsTrue = (macros.find(rawtok->next->str()) != macros.end() || (hasInclude && rawtok->next->str() == HAS_INCLUDE)); else if (rawtok->str() == IFNDEF) - conditionIsTrue = (macros.find(rawtok->next->str()) == macros.end()); + conditionIsTrue = (macros.find(rawtok->next->str()) == macros.end() && !(hasInclude && rawtok->next->str() == HAS_INCLUDE)); else { /*if (rawtok->str() == IF || rawtok->str() == ELIF)*/ TokenList expr(files); for (const Token *tok = rawtok->next; tok && tok->location.sameline(rawtok->location); tok = tok->next) { @@ -2801,6 +2817,8 @@ void simplecpp::preprocess(simplecpp::TokenList &output, const simplecpp::TokenL if (tok) { if (macros.find(tok->str()) != macros.end()) expr.push_back(new Token("1", tok->location)); + else if (hasInclude && tok->str() == HAS_INCLUDE) + expr.push_back(new Token("1", tok->location)); else expr.push_back(new Token("0", tok->location)); } @@ -2820,6 +2838,35 @@ void simplecpp::preprocess(simplecpp::TokenList &output, const simplecpp::TokenL continue; } + if (hasInclude && tok->str() == HAS_INCLUDE) { + tok = tok->next; + const bool par = (tok && tok->op == '('); + if (par) + tok = tok->next; + if (tok) { + const std::string &sourcefile = rawtok->location.file(); + const bool systemheader = (tok->str()[0] == '<'); + const std::string header(realFilename(tok->str().substr(1U, tok->str().size() - 2U))); + std::ifstream f; + const std::string header2 = openHeader(f,dui,sourcefile,header,systemheader); + expr.push_back(new Token(header2.empty() ? "0" : "1", tok->location)); + } + if (par) + tok = tok ? tok->next : NULL; + if (!tok || !sameline(rawtok,tok) || (par && tok->op != ')')) { + if (outputList) { + Output out(rawtok->location.files); + out.type = Output::SYNTAX_ERROR; + out.location = rawtok->location; + out.msg = "failed to evaluate " + std::string(rawtok->str() == IF ? "#if" : "#elif") + " condition"; + outputList->push_back(out); + } + output.clear(); + return; + } + continue; + } + const Token *tmp = tok; if (!preprocessToken(expr, &tmp, macros, files, outputList)) { output.clear(); diff --git a/externals/simplecpp/simplecpp.h b/externals/simplecpp/simplecpp.h index 577711af5..5ca74a179 100644 --- a/externals/simplecpp/simplecpp.h +++ b/externals/simplecpp/simplecpp.h @@ -288,7 +288,7 @@ namespace simplecpp { /** * Command line preprocessor settings. - * On the command line these are configured by -D, -U, -I, --include + * On the command line these are configured by -D, -U, -I, --include, -std */ struct SIMPLECPP_LIB DUI { DUI() {} @@ -296,6 +296,7 @@ namespace simplecpp { std::set undefined; std::list includePaths; std::list includes; + std::string std; }; SIMPLECPP_LIB std::map load(const TokenList &rawtokens, std::vector &filenames, const DUI &dui, OutputList *outputList = NULL);