Fixed #3648 (Internal error: Token::Match called with varid 0)
This commit is contained in:
parent
cb2a754983
commit
1fa1ddccba
|
@ -620,8 +620,6 @@ void CheckUnusedVar::checkFunctionVariableUsage_iterateScopes(const Scope* const
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (i->isArray() && i->isClass()) // Array of class/struct members. Initialized by ctor.
|
|
||||||
variables.write(i->varId());
|
|
||||||
if (i->isArray() && Token::Match(i->nameToken(), "%var% [ %var% ]")) // Array index variable read.
|
if (i->isArray() && Token::Match(i->nameToken(), "%var% [ %var% ]")) // Array index variable read.
|
||||||
variables.read(i->nameToken()->tokAt(2)->varId());
|
variables.read(i->nameToken()->tokAt(2)->varId());
|
||||||
|
|
||||||
|
@ -708,7 +706,7 @@ void CheckUnusedVar::checkFunctionVariableUsage_iterateScopes(const Scope* const
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (Token::Match(tok, "return|throw")) {
|
else if (Token::Match(tok, "return|throw %var%")) {
|
||||||
for (const Token *tok2 = tok->next(); tok2; tok2 = tok2->next()) {
|
for (const Token *tok2 = tok->next(); tok2; tok2 = tok2->next()) {
|
||||||
if (tok2->varId())
|
if (tok2->varId())
|
||||||
variables.readAll(tok2->varId());
|
variables.readAll(tok2->varId());
|
||||||
|
@ -840,12 +838,7 @@ void CheckUnusedVar::checkFunctionVariableUsage_iterateScopes(const Scope* const
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (Token::Match(tok, "& %var%")) {
|
else if (Token::Match(tok, ">>|& %var%"))
|
||||||
if (tok->previous()->isName() || tok->previous()->isNumber()) { // bitop
|
|
||||||
variables.read(tok->next()->varId());
|
|
||||||
} else // addressof
|
|
||||||
variables.use(tok->next()->varId()); // use = read + write
|
|
||||||
} else if (Token::Match(tok, ">> %var%"))
|
|
||||||
variables.use(tok->next()->varId()); // use = read + write
|
variables.use(tok->next()->varId()); // use = read + write
|
||||||
else if (Token::Match(tok, "%var% >>|&") && Token::Match(tok->previous(), "[{};:]"))
|
else if (Token::Match(tok, "%var% >>|&") && Token::Match(tok->previous(), "[{};:]"))
|
||||||
variables.read(tok->varId());
|
variables.read(tok->varId());
|
||||||
|
@ -872,8 +865,8 @@ void CheckUnusedVar::checkFunctionVariableUsage_iterateScopes(const Scope* const
|
||||||
else if (Token::Match(tok, "%var% ."))
|
else if (Token::Match(tok, "%var% ."))
|
||||||
variables.use(tok->varId()); // use = read + write
|
variables.use(tok->varId()); // use = read + write
|
||||||
|
|
||||||
else if (tok->isExtendedOp() &&
|
else if ((Token::Match(tok, "[(=&!]") || tok->isExtendedOp()) &&
|
||||||
Token::Match(tok->next(), "%var%") && !Token::Match(tok->next(), "true|false|new") && tok->strAt(2) != "=")
|
(Token::Match(tok->next(), "%var%") && !Token::Match(tok->next(), "true|false|new")) && tok->strAt(2) != "=")
|
||||||
variables.readAll(tok->next()->varId());
|
variables.readAll(tok->next()->varId());
|
||||||
|
|
||||||
else if (Token::Match(tok, "%var%") && (tok->next()->str() == ")" || tok->next()->isExtendedOp()))
|
else if (Token::Match(tok, "%var%") && (tok->next()->str() == ")" || tok->next()->isExtendedOp()))
|
||||||
|
@ -1001,9 +994,9 @@ void CheckUnusedVar::checkStructMemberUsage()
|
||||||
|
|
||||||
if (Token::Match(tok, "struct|union %type% {")) {
|
if (Token::Match(tok, "struct|union %type% {")) {
|
||||||
structname.clear();
|
structname.clear();
|
||||||
if (tok->strAt(-1) == "extern")
|
if (Token::simpleMatch(tok->previous(), "extern"))
|
||||||
continue;
|
continue;
|
||||||
if ((!tok->previous() || tok->previous()->str() == ";") && Token::Match(tok->linkAt(2), ("} ; " + tok->strAt(1) + " %var% ;").c_str()))
|
if ((!tok->previous() || Token::simpleMatch(tok->previous(), ";")) && Token::Match(tok->linkAt(2), ("} ; " + tok->strAt(1) + " %var% ;").c_str()))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
structname = tok->strAt(1);
|
structname = tok->strAt(1);
|
||||||
|
|
|
@ -70,7 +70,6 @@ public:
|
||||||
/** @brief %Check that all struct members are used */
|
/** @brief %Check that all struct members are used */
|
||||||
void checkStructMemberUsage();
|
void checkStructMemberUsage();
|
||||||
|
|
||||||
private:
|
|
||||||
// Error messages..
|
// Error messages..
|
||||||
void unusedStructMemberError(const Token *tok, const std::string &structname, const std::string &varname);
|
void unusedStructMemberError(const Token *tok, const std::string &structname, const std::string &varname);
|
||||||
void unusedVariableError(const Token *tok, const std::string &varname);
|
void unusedVariableError(const Token *tok, const std::string &varname);
|
||||||
|
|
|
@ -2299,8 +2299,6 @@ bool Tokenizer::tokenize(std::istream &code,
|
||||||
if (!preprocessorCondition) {
|
if (!preprocessorCondition) {
|
||||||
setVarId();
|
setVarId();
|
||||||
|
|
||||||
createLinks2();
|
|
||||||
|
|
||||||
// Change initialisation of variable to assignment
|
// Change initialisation of variable to assignment
|
||||||
simplifyInitVar();
|
simplifyInitVar();
|
||||||
}
|
}
|
||||||
|
@ -2816,7 +2814,7 @@ void Tokenizer::setVarId()
|
||||||
if (Token::Match(tok, "( %type% *|& %var% [),]") && !tok->next()->isStandardType()) {
|
if (Token::Match(tok, "( %type% *|& %var% [),]") && !tok->next()->isStandardType()) {
|
||||||
if (!Token::Match(tok->previous(), "%type%"))
|
if (!Token::Match(tok->previous(), "%type%"))
|
||||||
continue;
|
continue;
|
||||||
if (Token::Match(tok->previous(), "return|if|while"))
|
if (tok->previous() && tok->previous()->str() == "return")
|
||||||
continue;
|
continue;
|
||||||
if (tok->link() && !Token::Match(tok->link()->next(), "const| {") &&
|
if (tok->link() && !Token::Match(tok->link()->next(), "const| {") &&
|
||||||
(!tok->link()->next() || tok->link()->next()->str() != ":"))
|
(!tok->link()->next() || tok->link()->next()->str() != ":"))
|
||||||
|
@ -2867,7 +2865,7 @@ void Tokenizer::setVarId()
|
||||||
if (tok->str() == "unsigned")
|
if (tok->str() == "unsigned")
|
||||||
tok = tok->next();
|
tok = tok->next();
|
||||||
|
|
||||||
if (Token::Match(tok, "using namespace %type% ;")) {
|
if (Token::Match(tok, "using namespace| %type% ;")) {
|
||||||
tok = tok->next();
|
tok = tok->next();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -3298,62 +3296,6 @@ bool Tokenizer::createLinks()
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Tokenizer::createLinks2()
|
|
||||||
{
|
|
||||||
std::stack<const Token*> type;
|
|
||||||
std::stack<Token*> links;
|
|
||||||
for (Token *token = _tokens; token; token = token->next()) {
|
|
||||||
if (token->link()) {
|
|
||||||
if (Token::Match(token, "{|[|("))
|
|
||||||
type.push(token);
|
|
||||||
else if (Token::Match(token, "}|]|)")) {
|
|
||||||
while (type.top()->str() == "<")
|
|
||||||
type.pop();
|
|
||||||
type.pop();
|
|
||||||
} else
|
|
||||||
token->link(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (token->str() == ";")
|
|
||||||
while (!links.empty())
|
|
||||||
links.pop();
|
|
||||||
else if (token->str() == "<" && token->previous() && token->previous()->isName() && !token->previous()->varId()) {
|
|
||||||
type.push(token);
|
|
||||||
links.push(token);
|
|
||||||
} else if (token->str() == ">" || token->str() == ">>") {
|
|
||||||
if (links.empty()) // < and > don't match.
|
|
||||||
continue;
|
|
||||||
if (token->next() && !token->next()->isName() && !Token::Match(token->next(), ">|&|*|::|,"))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// Check type of open link
|
|
||||||
if (type.empty() || type.top()->str() != "<" || (token->str() == ">>" && type.size() < 2)) {
|
|
||||||
if (!links.empty())
|
|
||||||
links.pop();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
const Token* top = type.top();
|
|
||||||
type.pop();
|
|
||||||
if (token->str() == ">>" && type.top()->str() != "<") {
|
|
||||||
type.push(top);
|
|
||||||
if (!links.empty())
|
|
||||||
links.pop();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (token->str() == ">>") { // C++11 right angle bracket
|
|
||||||
if (links.size() < 2)
|
|
||||||
continue;
|
|
||||||
token->str(">");
|
|
||||||
token->insertToken(">");
|
|
||||||
}
|
|
||||||
|
|
||||||
Token::createMutualLinks(links.top(), token);
|
|
||||||
links.pop();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Tokenizer::simplifySizeof()
|
void Tokenizer::simplifySizeof()
|
||||||
{
|
{
|
||||||
for (Token *tok = _tokens; tok; tok = tok->next()) {
|
for (Token *tok = _tokens; tok; tok = tok->next()) {
|
||||||
|
@ -8127,16 +8069,17 @@ bool Tokenizer::validate() const
|
||||||
const Token *lastTok = 0;
|
const Token *lastTok = 0;
|
||||||
for (const Token *tok = tokens(); tok; tok = tok->next()) {
|
for (const Token *tok = tokens(); tok; tok = tok->next()) {
|
||||||
lastTok = tok;
|
lastTok = tok;
|
||||||
if (Token::Match(tok, "[{([]") || (tok->str() == "<" && tok->link())) {
|
if (Token::Match(tok, "[{([]")) {
|
||||||
if (tok->link() == 0) {
|
if (tok->link() == 0) {
|
||||||
cppcheckError(tok);
|
cppcheckError(tok);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
linktok.push(tok);
|
linktok.push(tok);
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (Token::Match(tok, "[})]]") || (tok->str() == ">" && tok->link())) {
|
else if (Token::Match(tok, "[})]]")) {
|
||||||
if (tok->link() == 0) {
|
if (tok->link() == 0) {
|
||||||
cppcheckError(tok);
|
cppcheckError(tok);
|
||||||
return false;
|
return false;
|
||||||
|
@ -8158,9 +8101,10 @@ bool Tokenizer::validate() const
|
||||||
}
|
}
|
||||||
|
|
||||||
linktok.pop();
|
linktok.pop();
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (tok->link() != 0) {
|
if (tok->link() != 0) {
|
||||||
cppcheckError(tok);
|
cppcheckError(tok);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -583,11 +583,6 @@ public:
|
||||||
*/
|
*/
|
||||||
bool createLinks();
|
bool createLinks();
|
||||||
|
|
||||||
/**
|
|
||||||
* Setup links between < and >.
|
|
||||||
*/
|
|
||||||
void createLinks2();
|
|
||||||
|
|
||||||
/** Syntax error */
|
/** Syntax error */
|
||||||
void syntaxError(const Token *tok);
|
void syntaxError(const Token *tok);
|
||||||
|
|
||||||
|
|
|
@ -206,7 +206,6 @@ private:
|
||||||
TEST_CASE(varid40); // ticket #3279
|
TEST_CASE(varid40); // ticket #3279
|
||||||
TEST_CASE(varid41); // ticket #3340 (varid for union type)
|
TEST_CASE(varid41); // ticket #3340 (varid for union type)
|
||||||
TEST_CASE(varid42); // ticket #3316 (varid for array)
|
TEST_CASE(varid42); // ticket #3316 (varid for array)
|
||||||
TEST_CASE(varid43);
|
|
||||||
TEST_CASE(varid44);
|
TEST_CASE(varid44);
|
||||||
TEST_CASE(varidFunctionCall1);
|
TEST_CASE(varidFunctionCall1);
|
||||||
TEST_CASE(varidFunctionCall2);
|
TEST_CASE(varidFunctionCall2);
|
||||||
|
@ -224,6 +223,7 @@ private:
|
||||||
TEST_CASE(varid_operator);
|
TEST_CASE(varid_operator);
|
||||||
TEST_CASE(varid_throw);
|
TEST_CASE(varid_throw);
|
||||||
TEST_CASE(varid_unknown_macro); // #2638 - unknown macro is not type
|
TEST_CASE(varid_unknown_macro); // #2638 - unknown macro is not type
|
||||||
|
TEST_CASE(varid_using); // ticket #3648
|
||||||
|
|
||||||
TEST_CASE(varidclass1);
|
TEST_CASE(varidclass1);
|
||||||
TEST_CASE(varidclass2);
|
TEST_CASE(varidclass2);
|
||||||
|
@ -3249,13 +3249,6 @@ private:
|
||||||
tokenizeDebugListing(code));
|
tokenizeDebugListing(code));
|
||||||
}
|
}
|
||||||
|
|
||||||
void varid43() {
|
|
||||||
const std::string code("int main(int flag) { if(a & flag) { return 1; } }");
|
|
||||||
ASSERT_EQUALS("\n\n##file 0\n"
|
|
||||||
"1: int main ( int flag@1 ) { if ( a & flag@1 ) { return 1 ; } }\n",
|
|
||||||
tokenizeDebugListing(code));
|
|
||||||
}
|
|
||||||
|
|
||||||
void varid44() {
|
void varid44() {
|
||||||
const std::string code("class A:public B,public C,public D {};");
|
const std::string code("class A:public B,public C,public D {};");
|
||||||
ASSERT_EQUALS("\n\n##file 0\n"
|
ASSERT_EQUALS("\n\n##file 0\n"
|
||||||
|
@ -3635,6 +3628,14 @@ private:
|
||||||
ASSERT_EQUALS(expected, tokenizeDebugListing(code));
|
ASSERT_EQUALS(expected, tokenizeDebugListing(code));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void varid_using() {
|
||||||
|
// #3648
|
||||||
|
const char code[] = "using std::size_t;";
|
||||||
|
const char expected[] = "\n\n##file 0\n"
|
||||||
|
"1: using long ;\n";
|
||||||
|
ASSERT_EQUALS(expected, tokenizeDebugListing(code));
|
||||||
|
}
|
||||||
|
|
||||||
void varidclass1() {
|
void varidclass1() {
|
||||||
const std::string actual = tokenizeDebugListing(
|
const std::string actual = tokenizeDebugListing(
|
||||||
"class Fred\n"
|
"class Fred\n"
|
||||||
|
@ -5052,33 +5053,6 @@ private:
|
||||||
ASSERT_EQUALS(true, tok->linkAt(8) == tok->tokAt(9));
|
ASSERT_EQUALS(true, tok->linkAt(8) == tok->tokAt(9));
|
||||||
ASSERT_EQUALS(true, tok->linkAt(9) == tok->tokAt(8));
|
ASSERT_EQUALS(true, tok->linkAt(9) == tok->tokAt(8));
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
|
||||||
const char code[] = "bool foo(C<z> a, bar<int, x<float>>& f, int b) {\n"
|
|
||||||
" return(a<b && b>f);\n"
|
|
||||||
"}";
|
|
||||||
errout.str("");
|
|
||||||
Settings settings;
|
|
||||||
Tokenizer tokenizer(&settings, this);
|
|
||||||
std::istringstream istr(code);
|
|
||||||
tokenizer.tokenize(istr, "test.cpp");
|
|
||||||
const Token *tok = tokenizer.tokens();
|
|
||||||
// template<
|
|
||||||
ASSERT_EQUALS((long long)tok->tokAt(6), (long long)tok->linkAt(4));
|
|
||||||
ASSERT_EQUALS((long long)tok->tokAt(4), (long long)tok->linkAt(6));
|
|
||||||
|
|
||||||
// bar<
|
|
||||||
ASSERT_EQUALS((long long)tok->tokAt(17), (long long)tok->linkAt(10));
|
|
||||||
ASSERT_EQUALS((long long)tok->tokAt(10), (long long)tok->linkAt(17));
|
|
||||||
|
|
||||||
// x<
|
|
||||||
ASSERT_EQUALS((long long)tok->tokAt(16), (long long)tok->linkAt(14));
|
|
||||||
ASSERT_EQUALS((long long)tok->tokAt(14), (long long)tok->linkAt(16));
|
|
||||||
|
|
||||||
// a<b && b>f
|
|
||||||
ASSERT_EQUALS(0, (long long)tok->linkAt(28));
|
|
||||||
ASSERT_EQUALS(0, (long long)tok->linkAt(32));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void removeExceptionSpecification1() {
|
void removeExceptionSpecification1() {
|
||||||
|
@ -5344,7 +5318,8 @@ private:
|
||||||
void cpp0xtemplate2() {
|
void cpp0xtemplate2() {
|
||||||
// tokenize ">>" into "> >"
|
// tokenize ">>" into "> >"
|
||||||
const char *code = "list<list<int>> ints;\n";
|
const char *code = "list<list<int>> ints;\n";
|
||||||
ASSERT_EQUALS("list < list < int > > ints ;", tokenizeAndStringify(code));
|
TODO_ASSERT_EQUALS("list < list < int > > ints ;",
|
||||||
|
"list < list < int >> ints ;", tokenizeAndStringify(code));
|
||||||
}
|
}
|
||||||
|
|
||||||
void cpp0xtemplate3() {
|
void cpp0xtemplate3() {
|
||||||
|
|
Loading…
Reference in New Issue