void CheckType::checkSignConversion() { if (!_settings->isEnabled("warning")) 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]; for (const Token* tok = scope->classStart->next(); tok != scope->classEnd; tok = tok->next()) { if (!tok->isArithmeticalOp() || Token::Match(tok,"+|-")) continue; // Is result unsigned? if (!(tok->valueType() && tok->valueType()->sign == ValueType::Sign::UNSIGNED)) continue; // Check if an operand can be negative.. std::stack<const Token *> tokens; tokens.push(tok->astOperand1()); tokens.push(tok->astOperand2()); while (!tokens.empty()) { const Token *tok1 = tokens.top(); tokens.pop(); if (!tok1) continue; if (!tok1->getValueLE(-1,_settings)) continue; if (tok1->valueType() && tok1->valueType()->sign != ValueType::Sign::UNSIGNED) signConversionError(tok1, tok1->isNumber()); } } } }
void CheckType::checkSignConversion() { if (!_settings->isEnabled("warning")) 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]; for (const Token* tok = scope->classStart->next(); tok != scope->classEnd; tok = tok->next()) { if (!tok->isArithmeticalOp() || Token::Match(tok,"+|-")) continue; unsigned int size = 0; char sign = 0; if (!astGetSizeSign(_settings, tok, &size, &sign)) continue; if (sign != 'u') continue; // Check if there are signed operands that can be negative.. std::stack<const Token *> tokens; tokens.push(tok->astOperand1()); tokens.push(tok->astOperand2()); while (!tokens.empty()) { const Token *tok1 = tokens.top(); tokens.pop(); if (!tok1) continue; if (tok1->str() == "(") continue; // Todo: properly handle casts, function calls, etc const Variable *var = tok1->variable(); if (var && tok1->getValueLE(-1,_settings)) { bool signedvar = true; // assume that variable is signed since it can have a negative value for (const Token *type = var->typeStartToken();; type = type->next()) { if (type->isUnsigned()) { signedvar = false; break; } if (type->isSigned()) break; if (type->isName() && !Token::Match(type, "char|short|int|long|const")) { signedvar = false; break; } if (type == var->typeEndToken()) break; } if (signedvar) { signConversionError(tok1); break; } } } } } }