bump simplecpp (#4524)

This commit is contained in:
Oliver Stöneberg 2022-09-30 07:26:48 +02:00 committed by GitHub
parent 4d13266e99
commit 88be6ec596
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 131 additions and 59 deletions

View File

@ -95,6 +95,7 @@ static const simplecpp::TokenString HAS_INCLUDE("__has_include");
template<class T> 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<char>(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<unsigned char>(istr.get()) << 8);
const unsigned short bom = (static_cast<unsigned char>(istr.get()) << 8);
if (istr.peek() >= 0xfe)
return bom | static_cast<unsigned char>(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<long long>::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<std::string> &f) : nameTokDef(nullptr), variadic(false), valueToken(nullptr), endToken(nullptr), files(f), tokenListDefine(f), valueDefinedInCode_(false) {}
explicit Macro(std::vector<std::string> &f) : nameTokDef(nullptr), valueToken(nullptr), endToken(nullptr), files(f), tokenListDefine(f), variadic(false), valueDefinedInCode_(false) {}
Macro(const Token *tok, std::vector<std::string> &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<TokenString> 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<Location> 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::map<std::strin
}
}
/** Evaluate __has_include(file) */
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)
{
for (simplecpp::Token *tok = expr.front(); tok; tok = tok->next) {
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<std::string> 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<std::string, std::size_t> &sizeOfType)
static long long evaluate(simplecpp::TokenList &expr, const simplecpp::DUI &dui, const std::map<std::string, std::size_t> &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<std::string, simplecpp::TokenList *> &filedat
return !getFileName(filedata, sourcefile, header, dui, systemheader).empty();
}
std::map<std::string, simplecpp::TokenList*> simplecpp::load(const simplecpp::TokenList &rawtokens, std::vector<std::string> &fileNumbers, const simplecpp::DUI &dui, simplecpp::OutputList *outputList)
std::map<std::string, simplecpp::TokenList*> simplecpp::load(const simplecpp::TokenList &rawtokens, std::vector<std::string> &filenames, const simplecpp::DUI &dui, simplecpp::OutputList *outputList)
{
std::map<std::string, simplecpp::TokenList*> ret;
@ -2856,16 +2915,16 @@ std::map<std::string, simplecpp::TokenList*> 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<std::string, simplecpp::TokenList*> 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<std::string, simplecpp::TokenList*> 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<std::string, simplecpp::TokenList*> simplecpp::load(const simplecpp::To
static bool preprocessToken(simplecpp::TokenList &output, const simplecpp::Token **tok1, simplecpp::MacroMap &macros, std::vector<std::string> &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 &macro = 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<TokenString, Macro>(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) {

View File

@ -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)