void CheckType::checkLongCast() { if (!_settings->isEnabled("style")) return; // Assignments.. for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) { if (!Token::Match(tok, "%var% =")) continue; if (!tok->variable() || !tok->variable()->isConst() || tok->variable()->typeStartToken()->str() != "long") continue; if (!tok->variable()->typeStartToken()->originalName().empty()) continue; if (Token::Match(tok->next()->astOperand2(), "*|<<") && astIsIntResult(tok->next()->astOperand2())) longCastAssignError(tok); } // Return.. const SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase(); const std::size_t functions = symbolDatabase->functionScopes.size(); for (std::size_t i = 0; i < functions; ++i) { const Scope * scope = symbolDatabase->functionScopes[i]; // function must return long data const Token * def = scope->classDef; bool islong = false; while (Token::Match(def, "%type%|::")) { if (def->str() == "long" && def->originalName().empty()) { islong = true; break; } def = def->previous(); } if (!islong) continue; // find return statement // todo.. this is slow, we should only check last statement in each child scope const Token *ret = nullptr; for (const Token *tok = scope->classStart; tok != scope->classEnd; tok = tok->next()) { if (tok->str() == "return") { if (!ret) ret = tok; else { ret = nullptr; break; } } } if (ret && Token::Match(ret->astOperand1(), "*|<<") && astIsIntResult(ret->astOperand1())) longCastReturnError(ret); } }
void CheckType::checkLongCast() { if (!_settings->isEnabled("style")) return; // Assignments.. for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) { if (tok->str() != "=" || !Token::Match(tok->astOperand2(), "*|<<")) continue; const ValueType *lhstype = tok->astOperand1() ? tok->astOperand1()->valueType() : nullptr; const ValueType *rhstype = tok->astOperand2()->valueType(); if (!lhstype || !rhstype) continue; // assign int result to long/longlong const nonpointer? if (rhstype->type == ValueType::Type::INT && rhstype->pointer == 0U && rhstype->originalTypeName.empty() && (lhstype->type == ValueType::Type::LONG || lhstype->type == ValueType::Type::LONGLONG) && lhstype->pointer == 0U && lhstype->constness == 1U && lhstype->originalTypeName.empty()) longCastAssignError(tok); } // Return.. const SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase(); const std::size_t functions = symbolDatabase->functionScopes.size(); for (std::size_t i = 0; i < functions; ++i) { const Scope * scope = symbolDatabase->functionScopes[i]; // function must return long data const Token * def = scope->classDef; bool islong = false; while (Token::Match(def, "%type%|::")) { if (def->str() == "long" && def->originalName().empty()) { islong = true; break; } def = def->previous(); } if (!islong) continue; // return statements const Token *ret = nullptr; for (const Token *tok = scope->classStart; tok != scope->classEnd; tok = tok->next()) { if (tok->str() == "return") { if (Token::Match(tok->astOperand1(), "<<|*")) { const ValueType *type = tok->astOperand1()->valueType(); if (type && type->type == ValueType::Type::INT && type->pointer == 0U && type->originalTypeName.empty()) ret = tok; } // All return statements must have problem otherwise no warning if (ret != tok) { ret = nullptr; break; } } } if (ret) longCastReturnError(ret); } }