| 311 | |
| 312 | |
| 313 | const CTU::FileInfo *CTU::getFileInfo(const Tokenizer &tokenizer) |
| 314 | { |
| 315 | const SymbolDatabase * const symbolDatabase = tokenizer.getSymbolDatabase(); |
| 316 | |
| 317 | auto *fileInfo = new FileInfo; |
| 318 | |
| 319 | // Parse all functions in TU |
| 320 | for (const Scope &scope : symbolDatabase->scopeList) { |
| 321 | if (!scope.isExecutable() || scope.type != ScopeType::eFunction || !scope.function) |
| 322 | continue; |
| 323 | const Function *const scopeFunction = scope.function; |
| 324 | |
| 325 | // source function calls |
| 326 | for (const Token *tok = scope.bodyStart; tok != scope.bodyEnd; tok = tok->next()) { |
| 327 | if (tok->str() != "(" || !tok->astOperand1() || !tok->astOperand2()) |
| 328 | continue; |
| 329 | const Function* tokFunction = tok->astOperand1()->function(); |
| 330 | if (!tokFunction) |
| 331 | continue; |
| 332 | const std::vector<const Token *> args(getArguments(tok->previous())); |
| 333 | for (int argnr = 0; argnr < args.size(); ++argnr) { |
| 334 | const Token *argtok = args[argnr]; |
| 335 | if (!argtok) |
| 336 | continue; |
| 337 | for (const ValueFlow::Value &value : argtok->values()) { |
| 338 | if ((!value.isIntValue() || value.intvalue != 0 || value.isInconclusive()) && !value.isBufferSizeValue()) |
| 339 | continue; |
| 340 | // Skip impossible values since they cannot be represented |
| 341 | if (value.isImpossible()) |
| 342 | continue; |
| 343 | FileInfo::FunctionCall functionCall; |
| 344 | functionCall.callValueType = value.valueType; |
| 345 | functionCall.callId = getFunctionId(tokenizer, tokFunction); |
| 346 | functionCall.callFunctionName = tok->astOperand1()->expressionString(); |
| 347 | functionCall.location = FileInfo::Location(tokenizer,tok); |
| 348 | functionCall.callArgNr = argnr + 1; |
| 349 | functionCall.callArgumentExpression = argtok->expressionString(); |
| 350 | functionCall.callArgValue = value; |
| 351 | functionCall.warning = !value.errorSeverity(); |
| 352 | for (const ErrorPathItem &i : value.errorPath) { |
| 353 | const std::string& file = tokenizer.list.file(i.first); |
| 354 | const std::string& info = i.second; |
| 355 | const int line = i.first->linenr(); |
| 356 | const int column = i.first->column(); |
| 357 | ErrorMessage::FileLocation loc(file, info, line, column); |
| 358 | functionCall.callValuePath.push_back(std::move(loc)); |
| 359 | } |
| 360 | fileInfo->functionCalls.push_back(std::move(functionCall)); |
| 361 | } |
| 362 | // array |
| 363 | if (argtok->variable() && argtok->variable()->isArray() && argtok->variable()->dimensions().size() == 1 && argtok->variable()->dimensionKnown(0)) { |
| 364 | FileInfo::FunctionCall functionCall; |
| 365 | functionCall.callValueType = ValueFlow::Value::ValueType::BUFFER_SIZE; |
| 366 | functionCall.callId = getFunctionId(tokenizer, tokFunction); |
| 367 | functionCall.callFunctionName = tok->astOperand1()->expressionString(); |
| 368 | functionCall.location = FileInfo::Location(tokenizer, tok); |
| 369 | functionCall.callArgNr = argnr + 1; |
| 370 | functionCall.callArgumentExpression = argtok->expressionString(); |