make ellipsis ... a single token (#2143)

* make ellipsis ... a single token

Using cppcheck -E to preprocess code with ellipsis produces output that
can't be compiled because ... is split into 3 tokens.

* try to fix addon
This commit is contained in:
IOBYTE 2019-09-04 02:07:30 -04:00 committed by Daniel Marjamäki
parent 6e00db379f
commit e5220bdf0c
12 changed files with 65 additions and 64 deletions

View File

@ -745,10 +745,14 @@ void simplecpp::TokenList::combineOperators()
} }
if (tok->op == '.') { if (tok->op == '.') {
if (tok->previous && tok->previous->op == '.') // ellipsis ...
continue; if (tok->next && tok->next->op == '.' && tok->next->location.col == (tok->location.col + 1) &&
if (tok->next && tok->next->op == '.') tok->next->next && tok->next->next->op == '.' && tok->next->next->location.col == (tok->location.col + 2)) {
tok->setstr("...");
deleteToken(tok->next);
deleteToken(tok->next);
continue; continue;
}
// float literals.. // float literals..
if (tok->previous && tok->previous->number) { if (tok->previous && tok->previous->number) {
tok->setstr(tok->previous->str() + '.'); tok->setstr(tok->previous->str() + '.');
@ -1376,14 +1380,12 @@ namespace simplecpp {
args.clear(); args.clear();
const Token *argtok = nameTokDef->next->next; const Token *argtok = nameTokDef->next->next;
while (sameline(nametoken, argtok) && argtok->op != ')') { while (sameline(nametoken, argtok) && argtok->op != ')') {
if (argtok->op == '.' && if (argtok->str() == "..." &&
argtok->next && argtok->next->op == '.' && argtok->next && argtok->next->op == ')') {
argtok->next->next && argtok->next->next->op == '.' &&
argtok->next->next->next && argtok->next->next->next->op == ')') {
variadic = true; variadic = true;
if (!argtok->previous->name) if (!argtok->previous->name)
args.push_back("__VA_ARGS__"); args.push_back("__VA_ARGS__");
argtok = argtok->next->next->next; // goto ')' argtok = argtok->next; // goto ')'
break; break;
} }
if (argtok->op != ',') if (argtok->op != ',')

View File

@ -1229,7 +1229,7 @@ void CheckOther::checkPassByReference()
if (!var || !var->isArgument() || !var->isClass() || var->isPointer() || var->isArray() || var->isReference() || var->isEnumType()) if (!var || !var->isArgument() || !var->isClass() || var->isPointer() || var->isArray() || var->isReference() || var->isEnumType())
continue; continue;
if (var->scope() && var->scope()->function->arg->link()->strAt(-1) == ".") if (var->scope() && var->scope()->function->arg->link()->strAt(-1) == "...")
continue; // references could not be used as va_start parameters (#5824) continue; // references could not be used as va_start parameters (#5824)
bool inconclusive = false; bool inconclusive = false;
@ -2447,7 +2447,7 @@ void CheckOther::checkVarFuncNullUB()
if (f && f->argCount() <= argnr) { if (f && f->argCount() <= argnr) {
const Token *tok2 = f->argDef; const Token *tok2 = f->argDef;
tok2 = tok2 ? tok2->link() : nullptr; // goto ')' tok2 = tok2 ? tok2->link() : nullptr; // goto ')'
if (tok2 && Token::simpleMatch(tok2->tokAt(-3), ". . .")) if (tok2 && Token::simpleMatch(tok2->tokAt(-1), "..."))
varFuncNullUBError(tok); varFuncNullUBError(tok);
} }
} }

View File

@ -1776,7 +1776,7 @@ void Variable::evaluate(const Settings* settings)
std::string strtype = mTypeStartToken->str(); std::string strtype = mTypeStartToken->str();
for (const Token *typeToken = mTypeStartToken; Token::Match(typeToken, "%type% :: %type%"); typeToken = typeToken->tokAt(2)) for (const Token *typeToken = mTypeStartToken; Token::Match(typeToken, "%type% :: %type%"); typeToken = typeToken->tokAt(2))
strtype += "::" + typeToken->strAt(2); strtype += "::" + typeToken->strAt(2);
setFlag(fIsClass, !lib->podtype(strtype) && !mTypeStartToken->isStandardType() && !isEnumType() && !isPointer() && !isReference()); setFlag(fIsClass, !lib->podtype(strtype) && !mTypeStartToken->isStandardType() && !isEnumType() && !isPointer() && !isReference() && strtype != "...");
setFlag(fIsStlType, Token::simpleMatch(mTypeStartToken, "std ::")); setFlag(fIsStlType, Token::simpleMatch(mTypeStartToken, "std ::"));
setFlag(fIsStlString, isStlType() && (Token::Match(mTypeStartToken->tokAt(2), "string|wstring|u16string|u32string !!::") || (Token::simpleMatch(mTypeStartToken->tokAt(2), "basic_string <") && !Token::simpleMatch(mTypeStartToken->linkAt(3), "> ::")))); setFlag(fIsStlString, isStlType() && (Token::Match(mTypeStartToken->tokAt(2), "string|wstring|u16string|u32string !!::") || (Token::simpleMatch(mTypeStartToken->tokAt(2), "basic_string <") && !Token::simpleMatch(mTypeStartToken->linkAt(3), "> ::"))));
setFlag(fIsSmartPointer, lib->isSmartPointer(mTypeStartToken)); setFlag(fIsSmartPointer, lib->isSmartPointer(mTypeStartToken));

View File

@ -459,7 +459,7 @@ unsigned int TemplateSimplifier::templateParameters(const Token *tok)
if ((tok->previous()->isName() && !Token::Match(tok->tokAt(-2), "<|,|::")) || if ((tok->previous()->isName() && !Token::Match(tok->tokAt(-2), "<|,|::")) ||
(!tok->previous()->isName() && tok->strAt(-1) != ">")) (!tok->previous()->isName() && tok->strAt(-1) != ">"))
return 0; // syntax error return 0; // syntax error
tok = tok->tokAt(3); tok = tok->next();
if (!tok) if (!tok)
return 0; return 0;
if (tok->str() == ">") { if (tok->str() == ">") {
@ -726,7 +726,7 @@ bool TemplateSimplifier::getTemplateDeclarations()
if (!tok->tokAt(2)) if (!tok->tokAt(2))
syntaxError(tok->next()); syntaxError(tok->next());
if (tok->strAt(2)=="typename" && if (tok->strAt(2)=="typename" &&
!Token::Match(tok->tokAt(3), "%name%|.|,|=|>")) !Token::Match(tok->tokAt(3), "%name%|...|,|=|>"))
syntaxError(tok->next()); syntaxError(tok->next());
codeWithTemplates = true; codeWithTemplates = true;
const Token * const parmEnd = tok1->next()->findClosingBracket(); const Token * const parmEnd = tok1->next()->findClosingBracket();
@ -1630,10 +1630,8 @@ void TemplateSimplifier::expandTemplate(
for (const Token *typetok = mTypesUsedInTemplateInstantiation[itype].token(); for (const Token *typetok = mTypesUsedInTemplateInstantiation[itype].token();
typetok && (typeindentlevel > 0 || !Token::Match(typetok, ",|>")); typetok && (typeindentlevel > 0 || !Token::Match(typetok, ",|>"));
typetok = typetok->next()) { typetok = typetok->next()) {
if (Token::simpleMatch(typetok, ". . .")) { if (Token::simpleMatch(typetok, "..."))
typetok = typetok->tokAt(2);
continue; continue;
}
if (Token::Match(typetok, "%name% <") && (typetok->strAt(2) == ">" || templateParameters(typetok->next()))) if (Token::Match(typetok, "%name% <") && (typetok->strAt(2) == ">" || templateParameters(typetok->next())))
++typeindentlevel; ++typeindentlevel;
else if (typeindentlevel > 0 && typetok->str() == ">") else if (typeindentlevel > 0 && typetok->str() == ">")
@ -1856,9 +1854,7 @@ void TemplateSimplifier::expandTemplate(
for (const Token *typetok = mTypesUsedInTemplateInstantiation[itype].token(); for (const Token *typetok = mTypesUsedInTemplateInstantiation[itype].token();
typetok && (typeindentlevel>0 || !Token::Match(typetok, ",|>")); typetok && (typeindentlevel>0 || !Token::Match(typetok, ",|>"));
typetok = typetok->next()) { typetok = typetok->next()) {
if (Token::simpleMatch(typetok, ". . .")) { if (!Token::simpleMatch(typetok, "...")) {
typetok = typetok->tokAt(2);
} else {
if (Token::Match(typetok, "%name% <") && (typetok->strAt(2) == ">" || templateParameters(typetok->next()))) if (Token::Match(typetok, "%name% <") && (typetok->strAt(2) == ">" || templateParameters(typetok->next())))
++typeindentlevel; ++typeindentlevel;
else if (typeindentlevel > 0 && typetok->str() == ">") else if (typeindentlevel > 0 && typetok->str() == ">")
@ -1960,10 +1956,8 @@ void TemplateSimplifier::expandTemplate(
for (const Token *typetok = mTypesUsedInTemplateInstantiation[itype].token(); for (const Token *typetok = mTypesUsedInTemplateInstantiation[itype].token();
typetok && (typeindentlevel > 0 || !Token::Match(typetok, ",|>")); typetok && (typeindentlevel > 0 || !Token::Match(typetok, ",|>"));
typetok = typetok->next()) { typetok = typetok->next()) {
if (Token::simpleMatch(typetok, ". . .")) { if (Token::simpleMatch(typetok, "..."))
typetok = typetok->tokAt(2);
continue; continue;
}
if (Token::Match(typetok, "%name% <") && if (Token::Match(typetok, "%name% <") &&
(typetok->strAt(2) == ">" || templateParameters(typetok->next()))) { (typetok->strAt(2) == ">" || templateParameters(typetok->next()))) {
brackets1.push(typetok->next()); brackets1.push(typetok->next());

View File

@ -128,6 +128,8 @@ void Token::update_property_info()
tokType(eIncDecOp); tokType(eIncDecOp);
else if (mStr.size() == 1 && (mStr.find_first_of("{}") != std::string::npos || (mLink && mStr.find_first_of("<>") != std::string::npos))) else if (mStr.size() == 1 && (mStr.find_first_of("{}") != std::string::npos || (mLink && mStr.find_first_of("<>") != std::string::npos)))
tokType(eBracket); tokType(eBracket);
else if (mStr == "...")
tokType(eEllipsis);
else else
tokType(eOther); tokType(eOther);
} else { } else {

View File

@ -176,6 +176,7 @@ public:
eArithmeticalOp, eComparisonOp, eAssignmentOp, eLogicalOp, eBitOp, eIncDecOp, eExtendedOp, // Operators: Arithmetical, Comparison, Assignment, Logical, Bitwise, ++/--, Extended eArithmeticalOp, eComparisonOp, eAssignmentOp, eLogicalOp, eBitOp, eIncDecOp, eExtendedOp, // Operators: Arithmetical, Comparison, Assignment, Logical, Bitwise, ++/--, Extended
eBracket, // {, }, <, >: < and > only if link() is set. Otherwise they are comparison operators. eBracket, // {, }, <, >: < and > only if link() is set. Otherwise they are comparison operators.
eLambda, // A function without a name eLambda, // A function without a name
eEllipsis, // "..."
eOther, eOther,
eNone eNone
}; };

View File

@ -2799,13 +2799,12 @@ void Tokenizer::simplifyCaseRange()
for (Token* tok = list.front(); tok; tok = tok->next()) { for (Token* tok = list.front(); tok; tok = tok->next()) {
if (Token::Match(tok, "case %num% ... %num% :")) { if (Token::Match(tok, "case %num% ... %num% :")) {
const MathLib::bigint start = MathLib::toLongNumber(tok->strAt(1)); const MathLib::bigint start = MathLib::toLongNumber(tok->strAt(1));
MathLib::bigint end = MathLib::toLongNumber(tok->strAt(5)); MathLib::bigint end = MathLib::toLongNumber(tok->strAt(3));
end = std::min(start + 50, end); // Simplify it 50 times at maximum end = std::min(start + 50, end); // Simplify it 50 times at maximum
if (start < end) { if (start < end) {
tok = tok->tokAt(2); tok = tok->tokAt(2);
tok->str(":"); tok->str(":");
tok->deleteNext(); tok->insertToken("case");
tok->next()->str("case");
for (MathLib::bigint i = end-1; i > start; i--) { for (MathLib::bigint i = end-1; i > start; i--) {
tok->insertToken(":"); tok->insertToken(":");
tok->insertToken(MathLib::toString(i)); tok->insertToken(MathLib::toString(i));
@ -2814,12 +2813,11 @@ void Tokenizer::simplifyCaseRange()
} }
} else if (Token::Match(tok, "case %char% ... %char% :")) { } else if (Token::Match(tok, "case %char% ... %char% :")) {
const char start = tok->strAt(1)[1]; const char start = tok->strAt(1)[1];
const char end = tok->strAt(5)[1]; const char end = tok->strAt(3)[1];
if (start < end) { if (start < end) {
tok = tok->tokAt(2); tok = tok->tokAt(2);
tok->str(":"); tok->str(":");
tok->deleteNext(); tok->insertToken("case");
tok->next()->str("case");
for (char i = end - 1; i > start; i--) { for (char i = end - 1; i > start; i--) {
tok->insertToken(":"); tok->insertToken(":");
if (i == '\\') { if (i == '\\') {
@ -3976,7 +3974,7 @@ void Tokenizer::createLinks2()
} }
// if > is followed by [ .. "new a<b>[" is expected // if > is followed by [ .. "new a<b>[" is expected
// unless this is from varidiac expansion // unless this is from varidiac expansion
if (token->strAt(1) == "[" && !Token::simpleMatch(token->tokAt(-3), ". . . >")) { if (token->strAt(1) == "[" && !Token::simpleMatch(token->tokAt(-1), "... >")) {
Token *prev = type.top()->previous(); Token *prev = type.top()->previous();
while (prev && Token::Match(prev->previous(), ":: %name%")) while (prev && Token::Match(prev->previous(), ":: %name%"))
prev = prev->tokAt(-2); prev = prev->tokAt(-2);
@ -4089,7 +4087,8 @@ bool Tokenizer::simplifySizeof()
continue; continue;
if (Token::simpleMatch(tok->next(), "...")) { if (Token::simpleMatch(tok->next(), "...")) {
tok->deleteNext(3); //tok->deleteNext(3);
tok->deleteNext();
} }
// sizeof('x') // sizeof('x')
@ -4993,7 +4992,7 @@ void Tokenizer::simplifyHeaders()
const Token *tok2 = tok->tokAt(3); const Token *tok2 = tok->tokAt(3);
while (Token::Match(tok2, "%name% %name% [,=>]") || Token::Match(tok2, "typename ... %name% [,>]")) { while (Token::Match(tok2, "%name% %name% [,=>]") || Token::Match(tok2, "typename ... %name% [,>]")) {
if (Token::simpleMatch(tok2, "typename ...")) if (Token::simpleMatch(tok2, "typename ..."))
tok2 = tok2->tokAt(5); tok2 = tok2->tokAt(3);
else else
tok2 = tok2->tokAt(2); tok2 = tok2->tokAt(2);
if (Token::Match(tok2, "= %name% [,>]")) if (Token::Match(tok2, "= %name% [,>]"))

View File

@ -689,7 +689,7 @@ static void compileTerm(Token *&tok, AST_state& state)
if (Token::Match(tok, "%name% <") && tok->linkAt(1)) if (Token::Match(tok, "%name% <") && tok->linkAt(1))
tok = tok->linkAt(1); tok = tok->linkAt(1);
else if (Token::Match(tok, "%name% ...")) else if (Token::Match(tok, "%name% ..."))
tok = tok->tokAt(3); tok = tok->next();
tok = tok->next(); tok = tok->next();
if (Token::Match(tok, "%str%")) { if (Token::Match(tok, "%str%")) {
while (Token::Match(tok, "%name%|%str%")) while (Token::Match(tok, "%name%|%str%"))
@ -767,6 +767,9 @@ static void compilePrecedence2(Token *&tok, AST_state& state)
while (tok) { while (tok) {
if (tok->tokType() == Token::eIncDecOp && !isPrefixUnary(tok, state.cpp)) { if (tok->tokType() == Token::eIncDecOp && !isPrefixUnary(tok, state.cpp)) {
compileUnaryOp(tok, state, compileScope); compileUnaryOp(tok, state, compileScope);
} else if (tok->str() == "...") {
state.op.push(tok);
break;
} else if (tok->str() == "." && tok->strAt(1) != "*") { } else if (tok->str() == "." && tok->strAt(1) != "*") {
if (tok->strAt(1) == ".") { if (tok->strAt(1) == ".") {
state.op.push(tok); state.op.push(tok);

View File

@ -7275,7 +7275,7 @@ private:
ASSERT_EQUALS("abc.1:?1+bd.1:?+=", testAst("a =(b.c ? : 1) + 1 + (b.d ? : 1);")); ASSERT_EQUALS("abc.1:?1+bd.1:?+=", testAst("a =(b.c ? : 1) + 1 + (b.d ? : 1);"));
ASSERT_EQUALS("catch.(", testAst("try {} catch (...) {}")); ASSERT_EQUALS("catch...(", testAst("try {} catch (...) {}"));
ASSERT_EQUALS("FooBar(", testAst("void Foo(Bar&);")); ASSERT_EQUALS("FooBar(", testAst("void Foo(Bar&);"));
ASSERT_EQUALS("FooBar(", testAst("void Foo(Bar& &);")); // Rvalue reference - simplified from && to & & by real tokenizer ASSERT_EQUALS("FooBar(", testAst("void Foo(Bar& &);")); // Rvalue reference - simplified from && to & & by real tokenizer
@ -7536,7 +7536,7 @@ private:
ASSERT_EQUALS("1f2a&,(+", testAst("1+f(2,&a)")); ASSERT_EQUALS("1f2a&,(+", testAst("1+f(2,&a)"));
ASSERT_EQUALS("fargv[(", testAst("int f(char argv[]);")); ASSERT_EQUALS("fargv[(", testAst("int f(char argv[]);"));
ASSERT_EQUALS("fchar(", testAst("extern unsigned f(const char *);")); ASSERT_EQUALS("fchar(", testAst("extern unsigned f(const char *);"));
ASSERT_EQUALS("fcharformat*.,(", testAst("extern void f(const char *format, ...);")); ASSERT_EQUALS("fcharformat*...,(", testAst("extern void f(const char *format, ...);"));
ASSERT_EQUALS("for_each_commit_graftint((void,(", testAst("extern int for_each_commit_graft(int (*)(int*), void *);")); ASSERT_EQUALS("for_each_commit_graftint((void,(", testAst("extern int for_each_commit_graft(int (*)(int*), void *);"));
ASSERT_EQUALS("for;;(", testAst("for (;;) {}")); ASSERT_EQUALS("for;;(", testAst("for (;;) {}"));
ASSERT_EQUALS("xsizeofvoid(=", testAst("x=sizeof(void*)")); ASSERT_EQUALS("xsizeofvoid(=", testAst("x=sizeof(void*)"));