Revert "Fixed #3648 (Internal error: Token::Match called with varid 0)"

This reverts commit 1fa1ddccba.
This commit is contained in:
Daniel Marjamäki 2012-03-20 19:00:16 +01:00
parent 1fa1ddccba
commit d6c8de104c
5 changed files with 118 additions and 24 deletions

View File

@ -620,6 +620,8 @@ void CheckUnusedVar::checkFunctionVariableUsage_iterateScopes(const Scope* const
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.
variables.read(i->nameToken()->tokAt(2)->varId());
@ -706,7 +708,7 @@ void CheckUnusedVar::checkFunctionVariableUsage_iterateScopes(const Scope* const
}
}
else if (Token::Match(tok, "return|throw %var%")) {
else if (Token::Match(tok, "return|throw")) {
for (const Token *tok2 = tok->next(); tok2; tok2 = tok2->next()) {
if (tok2->varId())
variables.readAll(tok2->varId());
@ -838,7 +840,12 @@ 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
else if (Token::Match(tok, "%var% >>|&") && Token::Match(tok->previous(), "[{};:]"))
variables.read(tok->varId());
@ -865,8 +872,8 @@ void CheckUnusedVar::checkFunctionVariableUsage_iterateScopes(const Scope* const
else if (Token::Match(tok, "%var% ."))
variables.use(tok->varId()); // use = read + write
else if ((Token::Match(tok, "[(=&!]") || tok->isExtendedOp()) &&
(Token::Match(tok->next(), "%var%") && !Token::Match(tok->next(), "true|false|new")) && tok->strAt(2) != "=")
else if (tok->isExtendedOp() &&
Token::Match(tok->next(), "%var%") && !Token::Match(tok->next(), "true|false|new") && tok->strAt(2) != "=")
variables.readAll(tok->next()->varId());
else if (Token::Match(tok, "%var%") && (tok->next()->str() == ")" || tok->next()->isExtendedOp()))
@ -994,9 +1001,9 @@ void CheckUnusedVar::checkStructMemberUsage()
if (Token::Match(tok, "struct|union %type% {")) {
structname.clear();
if (Token::simpleMatch(tok->previous(), "extern"))
if (tok->strAt(-1) == "extern")
continue;
if ((!tok->previous() || Token::simpleMatch(tok->previous(), ";")) && Token::Match(tok->linkAt(2), ("} ; " + tok->strAt(1) + " %var% ;").c_str()))
if ((!tok->previous() || tok->previous()->str() == ";") && Token::Match(tok->linkAt(2), ("} ; " + tok->strAt(1) + " %var% ;").c_str()))
continue;
structname = tok->strAt(1);

View File

@ -70,6 +70,7 @@ public:
/** @brief %Check that all struct members are used */
void checkStructMemberUsage();
private:
// Error messages..
void unusedStructMemberError(const Token *tok, const std::string &structname, const std::string &varname);
void unusedVariableError(const Token *tok, const std::string &varname);

View File

@ -2299,6 +2299,8 @@ bool Tokenizer::tokenize(std::istream &code,
if (!preprocessorCondition) {
setVarId();
createLinks2();
// Change initialisation of variable to assignment
simplifyInitVar();
}
@ -2814,7 +2816,7 @@ void Tokenizer::setVarId()
if (Token::Match(tok, "( %type% *|& %var% [),]") && !tok->next()->isStandardType()) {
if (!Token::Match(tok->previous(), "%type%"))
continue;
if (tok->previous() && tok->previous()->str() == "return")
if (Token::Match(tok->previous(), "return|if|while"))
continue;
if (tok->link() && !Token::Match(tok->link()->next(), "const| {") &&
(!tok->link()->next() || tok->link()->next()->str() != ":"))
@ -2865,7 +2867,7 @@ void Tokenizer::setVarId()
if (tok->str() == "unsigned")
tok = tok->next();
if (Token::Match(tok, "using namespace| %type% ;")) {
if (Token::Match(tok, "using namespace %type% ;")) {
tok = tok->next();
continue;
}
@ -3296,6 +3298,62 @@ bool Tokenizer::createLinks()
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()
{
for (Token *tok = _tokens; tok; tok = tok->next()) {
@ -8069,17 +8127,16 @@ bool Tokenizer::validate() const
const Token *lastTok = 0;
for (const Token *tok = tokens(); tok; tok = tok->next()) {
lastTok = tok;
if (Token::Match(tok, "[{([]")) {
if (Token::Match(tok, "[{([]") || (tok->str() == "<" && tok->link())) {
if (tok->link() == 0) {
cppcheckError(tok);
return false;
}
linktok.push(tok);
continue;
}
else if (Token::Match(tok, "[})]]")) {
else if (Token::Match(tok, "[})]]") || (tok->str() == ">" && tok->link())) {
if (tok->link() == 0) {
cppcheckError(tok);
return false;
@ -8101,10 +8158,9 @@ bool Tokenizer::validate() const
}
linktok.pop();
continue;
}
if (tok->link() != 0) {
else if (tok->link() != 0) {
cppcheckError(tok);
return false;
}

View File

@ -583,6 +583,11 @@ public:
*/
bool createLinks();
/**
* Setup links between < and >.
*/
void createLinks2();
/** Syntax error */
void syntaxError(const Token *tok);

View File

@ -206,6 +206,7 @@ private:
TEST_CASE(varid40); // ticket #3279
TEST_CASE(varid41); // ticket #3340 (varid for union type)
TEST_CASE(varid42); // ticket #3316 (varid for array)
TEST_CASE(varid43);
TEST_CASE(varid44);
TEST_CASE(varidFunctionCall1);
TEST_CASE(varidFunctionCall2);
@ -223,7 +224,6 @@ private:
TEST_CASE(varid_operator);
TEST_CASE(varid_throw);
TEST_CASE(varid_unknown_macro); // #2638 - unknown macro is not type
TEST_CASE(varid_using); // ticket #3648
TEST_CASE(varidclass1);
TEST_CASE(varidclass2);
@ -3249,6 +3249,13 @@ private:
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() {
const std::string code("class A:public B,public C,public D {};");
ASSERT_EQUALS("\n\n##file 0\n"
@ -3628,14 +3635,6 @@ private:
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() {
const std::string actual = tokenizeDebugListing(
"class Fred\n"
@ -5053,6 +5052,33 @@ private:
ASSERT_EQUALS(true, tok->linkAt(8) == tok->tokAt(9));
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() {
@ -5318,8 +5344,7 @@ private:
void cpp0xtemplate2() {
// tokenize ">>" into "> >"
const char *code = "list<list<int>> ints;\n";
TODO_ASSERT_EQUALS("list < list < int > > ints ;",
"list < list < int >> ints ;", tokenizeAndStringify(code));
ASSERT_EQUALS("list < list < int > > ints ;", tokenizeAndStringify(code));
}
void cpp0xtemplate3() {