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,8 +115,9 @@ void CheckNullPointer::parseFunctionCall(const Token &tok, std::list<const Token
} }
// 2nd parameter.. // 2nd parameter..
if ((Token::Match(&tok, "%var% ( %any% , %var% ,|)") && tok.tokAt(4)->varId() > 0) || if (Token::Match(&tok, "%var% ( %any%")) {
(value == 0 && Token::Match(&tok, "%var% ( %any% , 0 ,|)"))) { 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()) if (functionNames2.find(tok.str()) != functionNames2.end())
var.push_back(tok.tokAt(4)); var.push_back(tok.tokAt(4));
} }
@ -125,16 +126,30 @@ void CheckNullPointer::parseFunctionCall(const Token &tok, std::list<const Token
const Token* argListTok = 0; // Points to first va_list argument const Token* argListTok = 0; // Points to first va_list argument
std::string formatString; std::string formatString;
bool scan = Token::Match(&tok, "scanf|sscanf|fscanf"); 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); formatString = tok.strAt(2);
if (tok.strAt(3) == ",")
argListTok = tok.tokAt(4); argListTok = tok.tokAt(4);
} else if (Token::Match(&tok, "sprintf|fprintf|sscanf|fscanf ( %var% , %str% , %any%")) { else
formatString = tok.strAt(4); argListTok = 0;
argListTok = tok.tokAt(6); } else if (Token::Match(&tok, "sprintf|fprintf|sscanf|fscanf ( %any%")) {
} else if (Token::Match(&tok, "snprintf|fnprintf ( %var% , %any% , %str% , %any%")) { const Token* formatStringTok = tok.tokAt(2)->nextArgument(); // Find second parameter (format string)
formatString = tok.strAt(6); if (formatStringTok && Token::Match(formatStringTok, "%str%")) {
argListTok = tok.tokAt(8); 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) { if (argListTok) {
bool percent = false; bool percent = false;
for (std::string::iterator i = formatString.begin(); i != formatString.end(); ++i) { 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 argListTok = argListTok->nextArgument(); // Find next argument
if (argListTok->str() == "(")
argListTok = argListTok->link();
if (argListTok == 0)
break;
if (argListTok->str() == ",") {
argListTok = argListTok->next();
break;
}
}
if (!argListTok) if (!argListTok)
break; break;
percent = false; 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 // Compare the first character of the string for optimization reasons
// before doing more detailed checks. // before doing more detailed checks.
bool patternUnderstood = false;
if (p[0] == '%') { if (p[0] == '%') {
bool patternUnderstood = false;
switch (p[1]) { switch (p[1]) {
case 'v': case 'v':
// TODO: %var% should match only for // TODO: %var% should match only for
@ -696,6 +696,19 @@ void Token::move(Token *srcStart, Token *srcEnd, Token *newLocation)
tok->_progressValue = newLocation->_progressValue; 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) 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; 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: private:
void next(Token *nextToken) { void next(Token *nextToken) {
_next = nextToken; _next = nextToken;

View File

@ -38,6 +38,7 @@ private:
TEST_CASE(strValue); TEST_CASE(strValue);
TEST_CASE(deleteLast); TEST_CASE(deleteLast);
TEST_CASE(nextArgument);
TEST_CASE(matchAny); TEST_CASE(matchAny);
TEST_CASE(matchSingleChar); TEST_CASE(matchSingleChar);
@ -129,6 +130,17 @@ private:
ASSERT_EQUALS(true, tokensBack == &tok); 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() { void matchAny() {
givenACodeSampleToTokenize varBitOrVar("abc|def"); givenACodeSampleToTokenize varBitOrVar("abc|def");