diff --git a/externals/simplecpp/simplecpp.cpp b/externals/simplecpp/simplecpp.cpp index 2e8ce9a91..52a82f905 100644 --- a/externals/simplecpp/simplecpp.cpp +++ b/externals/simplecpp/simplecpp.cpp @@ -2482,7 +2482,7 @@ long long simplecpp::characterLiteralToLL(const std::string& str) // Assuming this is a UTF-8 encoded code point. // This decoder may not completely validate the input. // Noncharacters are neither rejected nor replaced. - + int additional_bytes; if (value >= 0xf5) // higher values would result in code points above 0x10ffff throw std::runtime_error("assumed UTF-8 encoded source, but sequence is invalid"); @@ -2494,26 +2494,26 @@ long long simplecpp::characterLiteralToLL(const std::string& str) additional_bytes = 1; else throw std::runtime_error("assumed UTF-8 encoded source, but sequence is invalid"); - + value &= (1 << (6 - additional_bytes)) - 1; while (additional_bytes--) { - if(pos + 1 >= str.size()) + if (pos + 1 >= str.size()) throw std::runtime_error("assumed UTF-8 encoded source, but character literal ends unexpectedly"); - + unsigned char c = str[pos++]; - + if (((c >> 6) != 2) // ensure c has form 0xb10xxxxxx || (!value && additional_bytes == 1 && c < 0xa0) // overlong 3-bytes encoding || (!value && additional_bytes == 2 && c < 0x90)) // overlong 4-bytes encoding throw std::runtime_error("assumed UTF-8 encoded source, but sequence is invalid"); - + value = (value << 6) | (c & ((1 << 7) - 1)); } if (value >= 0xd800 && value <= 0xdfff) throw std::runtime_error("assumed UTF-8 encoded source, but sequence is invalid"); - + if ((utf8 && value > 0x7f) || (utf16 && value > 0xffff) || value > 0x10ffff) throw std::runtime_error("code point too large"); } @@ -2804,7 +2804,7 @@ static bool preprocessToken(simplecpp::TokenList &output, const simplecpp::Token return true; } -void simplecpp::preprocess(simplecpp::TokenList &output, const simplecpp::TokenList &rawtokens, std::vector &files, std::map &filedata, const simplecpp::DUI &dui, simplecpp::OutputList *outputList, std::list *macroUsage) +void simplecpp::preprocess(simplecpp::TokenList &output, const simplecpp::TokenList &rawtokens, std::vector &files, std::map &filedata, const simplecpp::DUI &dui, simplecpp::OutputList *outputList, std::list *macroUsage, std::list *ifCond) { std::map sizeOfType(rawtokens.sizeOfType); sizeOfType.insert(std::make_pair("char", sizeof(char))); @@ -3119,7 +3119,17 @@ void simplecpp::preprocess(simplecpp::TokenList &output, const simplecpp::TokenL tok = tmp->previous; } try { - conditionIsTrue = (evaluate(expr, sizeOfType) != 0); + if (ifCond) { + std::string E; + for (const simplecpp::Token *tok = expr.cfront(); tok; tok = tok->next) + E += (E.empty() ? "" : " ") + tok->str(); + const long long result = evaluate(expr, sizeOfType); + conditionIsTrue = (result != 0); + ifCond->push_back(IfCond(rawtok->location, E, result)); + } else { + const long long result = evaluate(expr, sizeOfType); + conditionIsTrue = (result != 0); + } } catch (const std::exception &e) { if (outputList) { Output out(rawtok->location.files); diff --git a/externals/simplecpp/simplecpp.h b/externals/simplecpp/simplecpp.h index 80d025d6f..82adad40d 100644 --- a/externals/simplecpp/simplecpp.h +++ b/externals/simplecpp/simplecpp.h @@ -287,6 +287,14 @@ namespace simplecpp { bool macroValueKnown; }; + /** Tracking #if/#elif expressions */ + struct SIMPLECPP_LIB IfCond { + explicit IfCond(const Location& location, const std::string &E, long long result) : location(location), E(E), result(result) {} + Location location; // location of #if/#elif + std::string E; // preprocessed condition + long long result; // condition result + }; + /** * Command line preprocessor settings. * On the command line these are configured by -D, -U, -I, --include, -std @@ -314,8 +322,9 @@ namespace simplecpp { * @param dui defines, undefs, and include paths * @param outputList output: list that will receive output messages * @param macroUsage output: macro usage + * @param ifCond output: #if/#elif expressions */ - SIMPLECPP_LIB void preprocess(TokenList &output, const TokenList &rawtokens, std::vector &files, std::map &filedata, const DUI &dui, OutputList *outputList = NULL, std::list *macroUsage = NULL); + SIMPLECPP_LIB void preprocess(TokenList &output, const TokenList &rawtokens, std::vector &files, std::map &filedata, const DUI &dui, OutputList *outputList = NULL, std::list *macroUsage = NULL, std::list *ifCond = NULL); /** * Deallocate data