Added Token::nextArgument()

This commit is contained in:
PKEuS 2011-10-23 11:23:48 +02:00 committed by Daniel Marjamäki
parent b7ab1e7d7e
commit 54b3d72ee3
4 changed files with 61 additions and 23 deletions

View File

@ -115,26 +115,41 @@ void CheckNullPointer::parseFunctionCall(const Token &tok, std::list<const Token
}
// 2nd parameter..
if ((Token::Match(&tok, "%var% ( %any% , %var% ,|)") && tok.tokAt(4)->varId() > 0) ||
(value == 0 && Token::Match(&tok, "%var% ( %any% , 0 ,|)"))) {
if (functionNames2.find(tok.str()) != functionNames2.end())
var.push_back(tok.tokAt(4));
if (Token::Match(&tok, "%var% ( %any%")) {
const Token* secondParameter = tok.tokAt(2)->nextArgument();
if (secondParameter && ((value == 0 && secondParameter->str() == "0") || (Token::Match(secondParameter, "%var%") && secondParameter->varId() > 0)))
if (functionNames2.find(tok.str()) != functionNames2.end())
var.push_back(tok.tokAt(4));
}
if (Token::Match(&tok, "printf|sprintf|snprintf|fprintf|fnprintf|scanf|sscanf|fscanf")) {
const Token* argListTok = 0; // Points to first va_list argument
std::string formatString;
bool scan = Token::Match(&tok, "scanf|sscanf|fscanf");
if (Token::Match(&tok, "printf|scanf ( %str% , %any%")) {
if (Token::Match(&tok, "printf|scanf ( %str%")) {
formatString = tok.strAt(2);
argListTok = tok.tokAt(4);
} else if (Token::Match(&tok, "sprintf|fprintf|sscanf|fscanf ( %var% , %str% , %any%")) {
formatString = tok.strAt(4);
argListTok = tok.tokAt(6);
} else if (Token::Match(&tok, "snprintf|fnprintf ( %var% , %any% , %str% , %any%")) {
formatString = tok.strAt(6);
argListTok = tok.tokAt(8);
if (tok.strAt(3) == ",")
argListTok = tok.tokAt(4);
else
argListTok = 0;
} else if (Token::Match(&tok, "sprintf|fprintf|sscanf|fscanf ( %any%")) {
const Token* formatStringTok = tok.tokAt(2)->nextArgument(); // Find second parameter (format string)
if (formatStringTok && Token::Match(formatStringTok, "%str%")) {
argListTok = formatStringTok->nextArgument(); // Find third parameter (first argument of va_args)
formatString = formatStringTok->str();
}
} else if (Token::Match(&tok, "snprintf|fnprintf ( %any%")) {
const Token* formatStringTok = tok.tokAt(2);
for (int i = 0; i < 2 && formatStringTok; i++) {
formatStringTok = formatStringTok->nextArgument(); // Find third parameter (format string)
}
if (formatStringTok && Token::Match(formatStringTok, "%str%")) {
argListTok = formatStringTok->nextArgument(); // Find fourth parameter (first argument of va_args)
formatString = formatStringTok->str();
}
}
if (argListTok) {
bool percent = false;
for (std::string::iterator i = formatString.begin(); i != formatString.end(); ++i) {
@ -147,18 +162,10 @@ void CheckNullPointer::parseFunctionCall(const Token &tok, std::list<const Token
}
}
for (; argListTok; argListTok = argListTok->next()) { // Find next argument
if (argListTok->str() == "(")
argListTok = argListTok->link();
if (argListTok == 0)
break;
if (argListTok->str() == ",") {
argListTok = argListTok->next();
break;
}
}
argListTok = argListTok->nextArgument(); // Find next argument
if (!argListTok)
break;
percent = false;
}
}

View File

@ -429,8 +429,8 @@ bool Token::Match(const Token *tok, const char pattern[], unsigned int varid)
// Compare the first character of the string for optimization reasons
// before doing more detailed checks.
bool patternUnderstood = false;
if (p[0] == '%') {
bool patternUnderstood = false;
switch (p[1]) {
case 'v':
// TODO: %var% should match only for
@ -696,6 +696,19 @@ void Token::move(Token *srcStart, Token *srcEnd, Token *newLocation)
tok->_progressValue = newLocation->_progressValue;
}
const Token* Token::nextArgument() const
{
for (const Token* tok = this; tok; tok = tok->next()) {
if (tok->str() == ",")
return(tok->next());
else if (tok->str() == "(" || tok->str() == "{" || tok->str() == "[")
tok = tok->link();
else if (tok->str() == ")")
return(0);
}
return(0);
}
//---------------------------------------------------------------------------
const Token *Token::findmatch(const Token *tok, const char pattern[], unsigned int varId)

View File

@ -388,6 +388,12 @@ public:
tok->_progressValue = count++ * 100 / total_count;
}
/**
* Returns the first token of the next argument. Does only work on argument
* lists. Returns 0, if there is no next argument
*/
const Token* nextArgument() const;
private:
void next(Token *nextToken) {
_next = nextToken;

View File

@ -38,6 +38,7 @@ private:
TEST_CASE(strValue);
TEST_CASE(deleteLast);
TEST_CASE(nextArgument);
TEST_CASE(matchAny);
TEST_CASE(matchSingleChar);
@ -129,6 +130,17 @@ private:
ASSERT_EQUALS(true, tokensBack == &tok);
}
void nextArgument() {
givenACodeSampleToTokenize example1("foo(1, 2, 3, 4);");
ASSERT_EQUALS(true, Token::Match(example1.tokens()->tokAt(2)->nextArgument(), "2 , 3"));
givenACodeSampleToTokenize example2("foo();");
ASSERT_EQUALS(true, example2.tokens()->tokAt(2)->nextArgument() == 0);
givenACodeSampleToTokenize example3("foo(bar(a, b), 2, 3);");
ASSERT_EQUALS(true, Token::Match(example3.tokens()->tokAt(2)->nextArgument(), "2 , 3"));
}
void matchAny() {
givenACodeSampleToTokenize varBitOrVar("abc|def");