diff --git a/externals/simplecpp/simplecpp.cpp b/externals/simplecpp/simplecpp.cpp index 4b1f6d24f..4aac986f6 100644 --- a/externals/simplecpp/simplecpp.cpp +++ b/externals/simplecpp/simplecpp.cpp @@ -95,6 +95,7 @@ static const simplecpp::TokenString HAS_INCLUDE("__has_include"); template static std::string toString(T t) { + // NOLINTNEXTLINE(misc-const-correctness) - false positive std::ostringstream ostr; ostr << t; return ostr.str(); @@ -241,7 +242,7 @@ simplecpp::TokenList::TokenList(const TokenList &other) : frontToken(nullptr), b } #if __cplusplus >= 201103L -simplecpp::TokenList::TokenList(TokenList &&other) : TokenList(other) +simplecpp::TokenList::TokenList(TokenList &&other) : frontToken(nullptr), backToken(nullptr), files(other.files) { *this = std::move(other); } @@ -284,7 +285,7 @@ void simplecpp::TokenList::clear() { backToken = nullptr; while (frontToken) { - Token *next = frontToken->next; + Token * const next = frontToken->next; delete frontToken; frontToken = next; } @@ -350,9 +351,9 @@ static unsigned char readChar(std::istream &istr, unsigned int bom) if (bom == 0 && static_cast(istr.peek()) == '\n') (void)istr.get(); else if (bom == 0xfeff || bom == 0xfffe) { - int c1 = istr.get(); - int c2 = istr.get(); - int ch16 = (bom == 0xfeff) ? (c1<<8 | c2) : (c2<<8 | c1); + const int c1 = istr.get(); + const int c2 = istr.get(); + const int ch16 = (bom == 0xfeff) ? (c1<<8 | c2) : (c2<<8 | c1); if (ch16 != '\n') { istr.unget(); istr.unget(); @@ -397,7 +398,7 @@ static unsigned short getAndSkipBOM(std::istream &istr) // The UTF-16 BOM is 0xfffe or 0xfeff. if (ch1 >= 0xfe) { - unsigned short bom = (static_cast(istr.get()) << 8); + const unsigned short bom = (static_cast(istr.get()) << 8); if (istr.peek() >= 0xfe) return bom | static_cast(istr.get()); istr.unget(); @@ -428,7 +429,7 @@ static std::string escapeString(const std::string &str) std::ostringstream ostr; ostr << '\"'; for (std::size_t i = 1U; i < str.size() - 1; ++i) { - char c = str[i]; + const char c = str[i]; if (c == '\\' || c == '\"' || c == '\'') ostr << '\\'; ostr << c; @@ -859,7 +860,7 @@ void simplecpp::TokenList::combineOperators() start = start->previous; } if (indentlevel == -1 && start) { - const Token *ftok = start; + const Token * const ftok = start; bool isFuncDecl = ftok->name; while (isFuncDecl) { if (!start->name && start->str() != "::" && start->op != '*' && start->op != '&') @@ -957,10 +958,10 @@ void simplecpp::TokenList::constFoldMulDivRem(Token *tok) if (tok->op == '*') result = (stringToLL(tok->previous->str()) * stringToLL(tok->next->str())); else if (tok->op == '/' || tok->op == '%') { - long long rhs = stringToLL(tok->next->str()); + const long long rhs = stringToLL(tok->next->str()); if (rhs == 0) throw std::overflow_error("division/modulo by zero"); - long long lhs = stringToLL(tok->previous->str()); + const long long lhs = stringToLL(tok->previous->str()); if (rhs == -1 && lhs == std::numeric_limits::min()) throw std::overflow_error("division overflow"); if (tok->op == '/') @@ -1159,7 +1160,7 @@ void simplecpp::TokenList::removeComments() { Token *tok = frontToken; while (tok) { - Token *tok1 = tok; + Token * const tok1 = tok; tok = tok->next; if (tok1->comment) deleteToken(tok1); @@ -1276,7 +1277,7 @@ namespace simplecpp { class Macro { public: - explicit Macro(std::vector &f) : nameTokDef(nullptr), variadic(false), valueToken(nullptr), endToken(nullptr), files(f), tokenListDefine(f), valueDefinedInCode_(false) {} + explicit Macro(std::vector &f) : nameTokDef(nullptr), valueToken(nullptr), endToken(nullptr), files(f), tokenListDefine(f), variadic(false), valueDefinedInCode_(false) {} Macro(const Token *tok, std::vector &f) : nameTokDef(nullptr), files(f), tokenListDefine(f), valueDefinedInCode_(true) { if (sameline(tok->previous, tok)) @@ -1395,7 +1396,7 @@ namespace simplecpp { TokenList rawtokens2(inputFiles); const Location loc(macro2tok->location); while (macro2tok) { - Token *next = macro2tok->next; + Token * const next = macro2tok->next; rawtokens2.push_back(new Token(macro2tok->str(), loc)); output2.deleteToken(macro2tok); macro2tok = next; @@ -1791,7 +1792,7 @@ namespace simplecpp { TokenList temp2(files); temp2.push_back(new Token(temp.cback()->str(), tok->location)); - const Token *tok2 = appendTokens(&temp2, loc, tok->next, macros, expandedmacros, parametertokens); + const Token * const tok2 = appendTokens(&temp2, loc, tok->next, macros, expandedmacros, parametertokens); if (!tok2) return tok->next; output->takeTokens(temp); @@ -1832,7 +1833,7 @@ namespace simplecpp { } TokenList tokens(files); tokens.push_back(new Token(*tok)); - const Token *tok2 = appendTokens(&tokens, loc, tok->next, macros, expandedmacros, parametertokens); + const Token * const tok2 = appendTokens(&tokens, loc, tok->next, macros, expandedmacros, parametertokens); if (!tok2) { output->push_back(newMacroToken(tok->str(), loc, true, tok)); return tok->next; @@ -1842,10 +1843,10 @@ namespace simplecpp { return recursiveExpandToken(output, temp, loc, tok2, macros, expandedmacros2, parametertokens); } - else if (tok->str() == DEFINED) { - const Token *tok2 = tok->next; - const Token *tok3 = tok2 ? tok2->next : nullptr; - const Token *tok4 = tok3 ? tok3->next : nullptr; + if (tok->str() == DEFINED) { + const Token * const tok2 = tok->next; + const Token * const tok3 = tok2 ? tok2->next : nullptr; + const Token * const tok4 = tok3 ? tok3->next : nullptr; const Token *defToken = nullptr; const Token *lastToken = nullptr; if (sameline(tok, tok4) && tok2->op == '(' && tok3->name && tok4->op == ')') { @@ -1955,12 +1956,12 @@ namespace simplecpp { if (!sameline(tok, tok->next) || !sameline(tok, tok->next->next)) throw invalidHashHash::unexpectedNewline(tok->location, name()); - bool canBeConcatenatedWithEqual = A->isOneOf("+-*/%&|^") || A->str() == "<<" || A->str() == ">>"; - bool canBeConcatenatedStringOrChar = isStringLiteral_(A->str()) || isCharLiteral_(A->str()); + const bool canBeConcatenatedWithEqual = A->isOneOf("+-*/%&|^") || A->str() == "<<" || A->str() == ">>"; + const bool canBeConcatenatedStringOrChar = isStringLiteral_(A->str()) || isCharLiteral_(A->str()); if (!A->name && !A->number && A->op != ',' && !A->str().empty() && !canBeConcatenatedWithEqual && !canBeConcatenatedStringOrChar) throw invalidHashHash::unexpectedToken(tok->location, name(), A); - Token *B = tok->next->next; + Token * const B = tok->next->next; if (!B->name && !B->number && B->op && !B->isOneOf("#=")) throw invalidHashHash::unexpectedToken(tok->location, name(), B); @@ -1989,7 +1990,7 @@ namespace simplecpp { } else { std::string strAB; - const bool varargs = variadic && args.size() >= 1U && B->str() == args[args.size()-1U]; + const bool varargs = variadic && !args.empty() && B->str() == args[args.size()-1U]; if (expandArg(&tokensB, B, parametertokens)) { if (tokensB.empty()) @@ -2008,7 +2009,7 @@ namespace simplecpp { if (A->previous && A->previous->str() == "\\") { if (strAB[0] == 'u' && strAB.size() == 5) throw invalidHashHash::universalCharacterUB(tok->location, name(), A, strAB); - else if (strAB[0] == 'U' && strAB.size() == 9) + if (strAB[0] == 'U' && strAB.size() == 9) throw invalidHashHash::universalCharacterUB(tok->location, name(), A, strAB); } @@ -2033,7 +2034,7 @@ namespace simplecpp { if (tokensB.empty() && sameline(B,B->next) && B->next->op=='(') { const MacroMap::const_iterator it = macros.find(strAB); if (it != macros.end() && expandedmacros.find(strAB) == expandedmacros.end() && it->second.functionLike()) { - const Token *tok2 = appendTokens(&tokens, loc, B->next, macros, expandedmacros, parametertokens); + const Token * const tok2 = appendTokens(&tokens, loc, B->next, macros, expandedmacros, parametertokens); if (tok2) nextTok = tok2->next; } @@ -2063,9 +2064,6 @@ namespace simplecpp { /** arguments for macro */ std::vector args; - /** is macro variadic? */ - bool variadic; - /** first token in replacement string */ const Token *valueToken; @@ -2081,6 +2079,9 @@ namespace simplecpp { /** usage of this macro */ mutable std::list usageList; + /** is macro variadic? */ + bool variadic; + /** was the value of this macro actually defined in the code? */ bool valueDefinedInCode_; }; @@ -2094,7 +2095,7 @@ namespace simplecpp { std::string::size_type pos = 0; if (cygwinPath.size() >= 11 && startsWith(cygwinPath, "/cygdrive/")) { - unsigned char driveLetter = cygwinPath[10]; + const unsigned char driveLetter = cygwinPath[10]; if (std::isalpha(driveLetter)) { if (cygwinPath.size() == 11) { windowsPath = toupper(driveLetter); @@ -2403,6 +2404,63 @@ static void simplifySizeof(simplecpp::TokenList &expr, const std::mapnext) { + if (tok->str() != "__has_include") + continue; + simplecpp::Token *tok1 = tok->next; + if (!tok1) { + throw std::runtime_error("missing __has_include argument"); + } + simplecpp::Token *tok2 = tok1->next; + if (!tok2) { + throw std::runtime_error("missing __has_include argument"); + } + if (tok1->op == '(') { + tok1 = tok1->next; + while (tok2->op != ')') { + tok2 = tok2->next; + if (!tok2) { + throw std::runtime_error("invalid __has_include expression"); + } + } + } + + const std::string &sourcefile = tok->location.file(); + const bool systemheader = (tok1 && tok1->op == '<'); + std::string header; + if (systemheader) { + simplecpp::Token *tok3 = tok1->next; + if (!tok3) { + throw std::runtime_error("missing __has_include closing angular bracket"); + } + while (tok3->op != '>') { + tok3 = tok3->next; + if (!tok3) { + throw std::runtime_error("invalid __has_include expression"); + } + } + + for (simplecpp::Token *headerToken = tok1->next; headerToken != tok3; headerToken = headerToken->next) + header += headerToken->str(); + header = realFilename(header); + } + else { + header = realFilename(tok1->str().substr(1U, tok1->str().size() - 2U)); + } + std::ifstream f; + const std::string header2 = openHeader(f,dui,sourcefile,header,systemheader); + tok->setstr(header2.empty() ? "0" : "1"); + + tok2 = tok2->next; + while (tok->next != tok2) + expr.deleteToken(tok->next); + } +} + static const char * const altopData[] = {"and","or","bitand","bitor","compl","not","not_eq","xor"}; static const std::set altop(&altopData[0], &altopData[8]); static void simplifyName(simplecpp::TokenList &expr) @@ -2440,10 +2498,10 @@ static unsigned long long stringToULLbounded( std::size_t maxlen = std::string::npos ) { - std::string sub = s.substr(pos, maxlen); - const char* start = sub.c_str(); + const std::string sub = s.substr(pos, maxlen); + const char * const start = sub.c_str(); char* end; - unsigned long long value = std::strtoull(start, &end, base); + const unsigned long long value = std::strtoull(start, &end, base); pos += end - start; if (end - start < minlen) throw std::runtime_error("expected digit"); @@ -2487,7 +2545,7 @@ long long simplecpp::characterLiteralToLL(const std::string& str) std::size_t pos; - if (str.size() >= 1 && str[0] == '\'') { + if (!str.empty() && str[0] == '\'') { narrow = true; pos = 1; } else if (str.size() >= 2 && str[0] == 'u' && str[1] == '\'') { @@ -2516,7 +2574,7 @@ long long simplecpp::characterLiteralToLL(const std::string& str) if (str[pos] == '\\') { pos++; - char escape = str[pos++]; + const char escape = str[pos++]; if (pos >= str.size()) throw std::runtime_error("unexpected end of character literal"); @@ -2583,7 +2641,7 @@ long long simplecpp::characterLiteralToLL(const std::string& str) case 'u': case 'U': { // universal character names have exactly 4 or 8 digits - std::size_t ndigits = (escape == 'u' ? 4 : 8); + const std::size_t ndigits = (escape == 'u' ? 4 : 8); value = stringToULLbounded(str, pos, 16, ndigits, ndigits); // UTF-8 encodes code points above 0x7f in multiple code units @@ -2611,7 +2669,7 @@ long long simplecpp::characterLiteralToLL(const std::string& str) 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"); - else if (value >= 0xf0) + if (value >= 0xf0) additional_bytes = 3; else if (value >= 0xe0) additional_bytes = 2; @@ -2626,7 +2684,7 @@ long long simplecpp::characterLiteralToLL(const std::string& str) if (pos + 1 >= str.size()) throw std::runtime_error("assumed UTF-8 encoded source, but character literal ends unexpectedly"); - unsigned char c = str[pos++]; + const unsigned char c = str[pos++]; if (((c >> 6) != 2) // ensure c has form 0xb10xxxxxx || (!value && additional_bytes == 1 && c < 0xa0) // overlong 3-bytes encoding @@ -2678,7 +2736,7 @@ static void simplifyNumbers(simplecpp::TokenList &expr) continue; if (tok->str().compare(0,2,"0x") == 0) tok->setstr(toString(stringToULL(tok->str()))); - else if (!tok->number && tok->str().find('\'') != tok->str().npos) + else if (!tok->number && tok->str().find('\'') != std::string::npos) tok->setstr(toString(simplecpp::characterLiteralToLL(tok->str()))); } } @@ -2686,17 +2744,18 @@ static void simplifyNumbers(simplecpp::TokenList &expr) static void simplifyComments(simplecpp::TokenList &expr) { for (simplecpp::Token *tok = expr.front(); tok;) { - simplecpp::Token *d = tok; + simplecpp::Token * const d = tok; tok = tok->next; if (d->comment) expr.deleteToken(d); } } -static long long evaluate(simplecpp::TokenList &expr, const std::map &sizeOfType) +static long long evaluate(simplecpp::TokenList &expr, const simplecpp::DUI &dui, const std::map &sizeOfType) { simplifyComments(expr); simplifySizeof(expr, sizeOfType); + simplifyHasInclude(expr, dui); simplifyName(expr); simplifyNumbers(expr); expr.constFold(); @@ -2840,7 +2899,7 @@ static bool hasFile(const std::map &filedat return !getFileName(filedata, sourcefile, header, dui, systemheader).empty(); } -std::map simplecpp::load(const simplecpp::TokenList &rawtokens, std::vector &fileNumbers, const simplecpp::DUI &dui, simplecpp::OutputList *outputList) +std::map simplecpp::load(const simplecpp::TokenList &rawtokens, std::vector &filenames, const simplecpp::DUI &dui, simplecpp::OutputList *outputList) { std::map ret; @@ -2856,16 +2915,16 @@ std::map simplecpp::load(const simplecpp::To std::ifstream fin(filename.c_str()); if (!fin.is_open()) { if (outputList) { - simplecpp::Output err(fileNumbers); + simplecpp::Output err(filenames); err.type = simplecpp::Output::EXPLICIT_INCLUDE_NOT_FOUND; - err.location = Location(fileNumbers); + err.location = Location(filenames); err.msg = "Can not open include file '" + filename + "' that is explicitly included."; outputList->push_back(err); } continue; } - TokenList *tokenlist = new TokenList(fin, fileNumbers, filename, outputList); + TokenList *tokenlist = new TokenList(fin, filenames, filename, outputList); if (!tokenlist->front()) { delete tokenlist; continue; @@ -2890,11 +2949,11 @@ std::map simplecpp::load(const simplecpp::To const std::string &sourcefile = rawtok->location.file(); - const Token *htok = rawtok->nextSkipComments(); + const Token * const htok = rawtok->nextSkipComments(); if (!sameline(rawtok, htok)) continue; - bool systemheader = (htok->str()[0] == '<'); + const 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; @@ -2904,7 +2963,7 @@ std::map simplecpp::load(const simplecpp::To if (!f.is_open()) continue; - TokenList *tokens = new TokenList(f, fileNumbers, header2, outputList); + TokenList *tokens = new TokenList(f, filenames, header2, outputList); ret[header2] = tokens; if (tokens->front()) filelist.push_back(tokens->front()); @@ -2915,7 +2974,7 @@ std::map simplecpp::load(const simplecpp::To static bool preprocessToken(simplecpp::TokenList &output, const simplecpp::Token **tok1, simplecpp::MacroMap ¯os, std::vector &files, simplecpp::OutputList *outputList) { - const simplecpp::Token *tok = *tok1; + const simplecpp::Token * const tok = *tok1; const simplecpp::MacroMap::const_iterator it = macros.find(tok->str()); if (it != macros.end()) { simplecpp::TokenList value(files); @@ -3098,7 +3157,7 @@ void simplecpp::preprocess(simplecpp::TokenList &output, const simplecpp::TokenL try { const Macro ¯o = Macro(rawtok->previous, files); if (dui.undefined.find(macro.name()) == dui.undefined.end()) { - MacroMap::iterator it = macros.find(macro.name()); + const MacroMap::iterator it = macros.find(macro.name()); if (it == macros.end()) macros.insert(std::pair(macro.name(), macro)); else @@ -3156,7 +3215,7 @@ void simplecpp::preprocess(simplecpp::TokenList &output, const simplecpp::TokenL return; } - const Token *inctok = inc2.cfront(); + const Token * const inctok = inc2.cfront(); const bool systemheader = (inctok->op == '<'); const std::string header(realFilename(inctok->str().substr(1U, inctok->str().size() - 2U))); @@ -3166,7 +3225,7 @@ void simplecpp::preprocess(simplecpp::TokenList &output, const simplecpp::TokenL std::ifstream f; header2 = openHeader(f, dui, rawtok->location.file(), header, systemheader); if (f.is_open()) { - TokenList *tokens = new TokenList(f, files, header2, outputList); + TokenList * const tokens = new TokenList(f, files, header2, outputList); filedata[header2] = tokens; } } @@ -3188,7 +3247,7 @@ void simplecpp::preprocess(simplecpp::TokenList &output, const simplecpp::TokenL } } else if (pragmaOnce.find(header2) == pragmaOnce.end()) { includetokenstack.push(gotoNextLine(rawtok)); - const TokenList *includetokens = filedata.find(header2)->second; + const TokenList * const includetokens = filedata.find(header2)->second; rawtok = includetokens ? includetokens->cfront() : nullptr; continue; } @@ -3257,17 +3316,30 @@ void simplecpp::preprocess(simplecpp::TokenList &output, const simplecpp::TokenL const bool par = (tok && tok->op == '('); if (par) tok = tok->next; + bool closingAngularBracket = false; 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))); + const bool systemheader = (tok && tok->op == '<'); + std::string header; + + if (systemheader) { + while ((tok = tok->next) && tok->op != '>') + header += tok->str(); + header = realFilename(header); + if (tok && tok->op == '>') + closingAngularBracket = true; + } + else { + header = realFilename(tok->str().substr(1U, tok->str().size() - 2U)); + closingAngularBracket = true; + } 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 : nullptr; - if (!tok || !sameline(rawtok,tok) || (par && tok->op != ')')) { + if (!tok || !sameline(rawtok,tok) || (par && tok->op != ')') || (!closingAngularBracket)) { if (outputList) { Output out(rawtok->location.files); out.type = Output::SYNTAX_ERROR; @@ -3297,11 +3369,11 @@ void simplecpp::preprocess(simplecpp::TokenList &output, const simplecpp::TokenL 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); + const long long result = evaluate(expr, dui, sizeOfType); conditionIsTrue = (result != 0); ifCond->push_back(IfCond(rawtok->location, E, result)); } else { - const long long result = evaluate(expr, sizeOfType); + const long long result = evaluate(expr, dui, sizeOfType); conditionIsTrue = (result != 0); } } catch (const std::exception &e) { diff --git a/externals/simplecpp/simplecpp.h b/externals/simplecpp/simplecpp.h index 87dad2486..8e04a571b 100644 --- a/externals/simplecpp/simplecpp.h +++ b/externals/simplecpp/simplecpp.h @@ -239,8 +239,8 @@ namespace simplecpp { void deleteToken(Token *tok) { if (!tok) return; - Token *prev = tok->previous; - Token *next = tok->next; + Token * const prev = tok->previous; + Token * const next = tok->next; if (prev) prev->next = next; if (next)