void Check64BitPortability::pointerassignment() { if (!_settings->isEnabled("portability")) return; const SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase(); // Check return values const std::size_t functions = symbolDatabase->functionScopes.size(); for (std::size_t i = 0; i < functions; ++i) { const Scope * scope = symbolDatabase->functionScopes[i]; if (scope->function == 0 || !scope->function->hasBody()) // We only look for functions with a body continue; bool retPointer = false; if (scope->function->token->strAt(-1) == "*") // Function returns a pointer retPointer = true; else if (Token::Match(scope->function->token->previous(), "int|long|DWORD")) // Function returns an integer ; else continue; for (const Token* tok = scope->classStart->next(); tok != scope->classEnd; tok = tok->next()) { // skip nested functions if (tok->str() == "{") { if (tok->scope()->type == Scope::ScopeType::eFunction) tok = tok->link(); } if (tok->str() != "return") continue; if (!tok->astOperand1() || tok->astOperand1()->isNumber()) continue; const ValueType * const returnType = tok->astOperand1()->valueType(); if (!returnType) continue; if (retPointer && returnType->pointer == 0U) returnIntegerError(tok); if (!retPointer && returnType->pointer >= 1U) returnPointerError(tok); } } // Check assignments for (std::size_t i = 0; i < functions; ++i) { const Scope * scope = symbolDatabase->functionScopes[i]; for (const Token *tok = scope->classStart; tok && tok != scope->classEnd; tok = tok->next()) { if (tok->str() != "=") continue; const ValueType *lhstype = tok->astOperand1() ? tok->astOperand1()->valueType() : nullptr; const ValueType *rhstype = tok->astOperand2() ? tok->astOperand2()->valueType() : nullptr; if (!lhstype || !rhstype) continue; // Assign integer to pointer.. if (lhstype->pointer >= 1U && !tok->astOperand2()->isNumber() && rhstype->pointer == 0U && rhstype->originalTypeName.empty() && rhstype->type == ValueType::Type::INT) assignmentIntegerToAddressError(tok); // Assign pointer to integer.. if (rhstype->pointer >= 1U && lhstype->pointer == 0U && lhstype->originalTypeName.empty() && lhstype->type == ValueType::Type::INT) assignmentAddressToIntegerError(tok); } } }
void Check64BitPortability::pointerassignment() { if (!_settings->isEnabled("portability")) return; const SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase(); // Check return values const std::size_t functions = symbolDatabase->functionScopes.size(); for (std::size_t i = 0; i < functions; ++i) { const Scope * scope = symbolDatabase->functionScopes[i]; if (scope->function == 0 || !scope->function->hasBody) // We only look for functions with a body continue; bool retPointer = false; if (scope->function->token->strAt(-1) == "*") // Function returns a pointer retPointer = true; else if (Token::Match(scope->function->token->previous(), "int|long|DWORD")) // Function returns an integer ; else continue; for (const Token* tok = scope->classStart->next(); tok != scope->classEnd; tok = tok->next()) { if (Token::Match(tok, "return %var%|%num% [;+]") && !Token::simpleMatch(tok, "return 0 ;")) { enum { NO, INT, PTR, PTRDIFF } type = NO; for (const Token *tok2 = tok->next(); tok2; tok2 = tok2->next()) { if ((type == NO || type == INT) && isaddr(tok2->variable())) type = PTR; else if (type == NO && (tok2->isNumber() || isint(tok2->variable()))) type = INT; else if (type == PTR && Token::Match(tok2, "- %var%") && isaddr(tok2->next()->variable())) type = PTRDIFF; else if (Token::Match(tok2, "%type% (")) { type = NO; break; } else if (tok2->str() == ";") break; } if (retPointer && (type == INT || type == PTRDIFF)) returnIntegerError(tok); else if (!retPointer && type == PTR) returnPointerError(tok); } } } // Check assignments for (std::size_t i = 0; i < functions; ++i) { const Scope * scope = symbolDatabase->functionScopes[i]; for (const Token *tok = scope->classStart; tok && tok != scope->classEnd; tok = tok->next()) { if (Token::Match(tok, "[;{}] %var% = %var% [;+]")) { const Variable *var1(tok->next()->variable()); const Variable *var2(tok->tokAt(3)->variable()); if (isaddr(var1) && isint(var2) && tok->strAt(4) != "+") assignmentIntegerToAddressError(tok->next()); else if (isint(var1) && isaddr(var2) && !tok->tokAt(3)->isPointerCompare()) { // assigning address => warning // some trivial addition => warning if (Token::Match(tok->tokAt(4), "+ %any% !!;")) continue; assignmentAddressToIntegerError(tok->next()); } } } } }