|
24 | 24 | #include "token.h" |
25 | 25 | #include "tokenlist.h" |
26 | 26 |
|
| 27 | +#include <iostream> |
| 28 | + |
| 29 | + |
| 30 | +static void printvalues(const Token *tok) |
| 31 | +{ |
| 32 | + if (tok->values.empty()) |
| 33 | + std::cout << "empty"; |
| 34 | + for (std::list<ValueFlow::Value>::const_iterator it = tok->values.begin(); it != tok->values.end(); ++it) |
| 35 | + std::cout << " " << (it->intvalue); |
| 36 | + std::cout << std::endl; |
| 37 | +} |
| 38 | + |
27 | 39 | static void bailout(TokenList *tokenlist, ErrorLogger *errorLogger, const Token *tok, const std::string &what) |
28 | 40 | { |
29 | 41 | std::list<ErrorLogger::ErrorMessage::FileLocation> callstack; |
@@ -110,10 +122,68 @@ static void valueFlowBeforeCondition(TokenList *tokenlist, ErrorLogger *errorLog |
110 | 122 | } |
111 | 123 | } |
112 | 124 |
|
| 125 | +static void valueFlowSubFunction(TokenList *tokenlist, ErrorLogger *errorLogger, const Settings *settings) |
| 126 | +{ |
| 127 | + std::list<ValueFlow::Value> argvalues; |
| 128 | + for (Token *tok = tokenlist->front(); tok; tok = tok->next()) { |
| 129 | + if (Token::Match(tok, "[(,] %var% [,)]") && !tok->next()->values.empty()) |
| 130 | + argvalues = tok->next()->values; |
| 131 | + else if (Token::Match(tok, "[(,] %num% [,)]")) { |
| 132 | + ValueFlow::Value val; |
| 133 | + val.condition = 0; |
| 134 | + val.intvalue = MathLib::toLongNumber(tok->next()->str()); |
| 135 | + argvalues.clear(); |
| 136 | + argvalues.push_back(val); |
| 137 | + } else { |
| 138 | + continue; |
| 139 | + } |
| 140 | + |
| 141 | + const Token * const argumentToken = tok->next(); |
| 142 | + |
| 143 | + // is this a function call? |
| 144 | + const Token *ftok = tok; |
| 145 | + while (ftok && ftok->str() != "(") |
| 146 | + ftok = ftok->astParent(); |
| 147 | + if (!ftok || !ftok->astOperand1() || !ftok->astOperand2() || !ftok->astOperand1()->function()) |
| 148 | + continue; |
| 149 | + |
| 150 | + // Get argument nr |
| 151 | + unsigned int argnr = 0; |
| 152 | + for (const Token *argtok = ftok->next(); argtok && argtok != argumentToken; argtok = argtok->nextArgument()) |
| 153 | + ++ argnr; |
| 154 | + |
| 155 | + // Get function argument, and check if parameter is passed by value |
| 156 | + const Function * const function = ftok->astOperand1()->function(); |
| 157 | + const Variable * const arg = function ? function->getArgumentVar(argnr) : NULL; |
| 158 | + if (!Token::Match(arg ? arg->typeStartToken() : NULL, "const| %type% %var% ,|)")) |
| 159 | + continue; |
| 160 | + |
| 161 | + // Function scope.. |
| 162 | + const Scope * const functionScope = function ? function->functionScope : NULL; |
| 163 | + if (!functionScope) |
| 164 | + continue; |
| 165 | + |
| 166 | + // Set value in function scope.. |
| 167 | + const unsigned int varid2 = arg->nameToken()->varId(); |
| 168 | + for (const Token *tok2 = functionScope->classStart->next(); tok2 != functionScope->classEnd; tok2 = tok2->next()) { |
| 169 | + if (Token::Match(tok2, "%cop%|return %varid%", varid2)) { |
| 170 | + tok2 = tok2->next(); |
| 171 | + std::list<ValueFlow::Value> &values = const_cast<Token*>(tok2)->values; |
| 172 | + values.insert(values.begin(), argvalues.begin(), argvalues.end()); |
| 173 | + } else if (tok2->varId() == varid2 || tok2->str() == "{") { |
| 174 | + if (settings->debugwarnings) |
| 175 | + bailout(tokenlist, errorLogger, tok2, "parameter " + arg->nameToken()->str()); |
| 176 | + continue; |
| 177 | + } |
| 178 | + } |
| 179 | + } |
| 180 | +} |
| 181 | + |
113 | 182 | void ValueFlow::setValues(TokenList *tokenlist, ErrorLogger *errorLogger, const Settings *settings) |
114 | 183 | { |
115 | 184 | for (Token *tok = tokenlist->front(); tok; tok = tok->next()) |
116 | 185 | tok->values.clear(); |
117 | 186 |
|
118 | 187 | valueFlowBeforeCondition(tokenlist, errorLogger, settings); |
| 188 | + valueFlowSubFunction(tokenlist, errorLogger, settings); |
119 | 189 | } |
0 commit comments