@@ -30,82 +30,6 @@ namespace {
3030 CheckType instance;
3131}
3232
33- static bool astIsIntResult (const Token *tok)
34- {
35- if (!tok)
36- return false ;
37- if (tok->astOperand1 ())
38- return astIsIntResult (tok->astOperand1 ()) && astIsIntResult (tok->astOperand2 ());
39- // todo: handle numbers
40- if (!tok->variable ())
41- return false ;
42- const Token *type = tok->variable ()->typeStartToken ();
43- return Token::Match (type, " char|short|int" ) && !type->isLong ();
44- }
45-
46- static bool astGetSizeSign (const Settings *settings, const Token *tok, unsigned int *size, char *sign)
47- {
48- if (!tok)
49- return false ;
50- if (tok->isArithmeticalOp ()) {
51- if (!astGetSizeSign (settings, tok->astOperand1 (), size, sign))
52- return false ;
53- return !tok->astOperand2 () || astGetSizeSign (settings, tok->astOperand2 (), size, sign);
54- }
55- if (tok->isNumber () && MathLib::isInt (tok->str ())) {
56- if (tok->str ().find (' L' ) != std::string::npos)
57- return false ;
58- MathLib::bigint value = MathLib::toLongNumber (tok->str ());
59- unsigned int sz;
60- if (value >= -(1 <<7 ) && value <= (1 <<7 )-1 )
61- sz = 8 ;
62- else if (value >= -(1 <<15 ) && value <= (1 <<15 )-1 )
63- sz = 16 ;
64- else if (value >= -(1LL <<31 ) && value <= (1LL <<31 )-1 )
65- sz = 32 ;
66- else
67- return false ;
68- if (sz < 8 * settings->sizeof_int )
69- sz = 8 * settings->sizeof_int ;
70- if (*size < sz)
71- *size = sz;
72- if (tok->str ().find (' U' ) != std::string::npos)
73- *sign = ' u' ;
74- if (*sign != ' u' )
75- *sign = ' s' ;
76- return true ;
77- }
78- if (tok->isName ()) {
79- const Variable *var = tok->variable ();
80- if (!var)
81- return false ;
82- unsigned int sz = 0 ;
83- for (const Token *type = var->typeStartToken (); type; type = type->next ()) {
84- if (type->str () == " *" )
85- return false ; // <- FIXME: handle pointers
86- if (Token::Match (type, " char|short|int" )) {
87- sz = 8 * settings->sizeof_int ;
88- if (type->isUnsigned ())
89- *sign = ' u' ;
90- else if (*sign != ' u' )
91- *sign = ' s' ;
92- } else if (Token::Match (type, " float|double|long" )) {
93- return false ;
94- } else {
95- // TODO: try to lookup type info in library
96- }
97- if (type == var->typeEndToken ())
98- break ;
99- }
100- if (sz == 0 )
101- return false ;
102- if (*size < sz)
103- *size = sz;
104- return true ;
105- }
106- return false ;
107- }
108-
10933// ---------------------------------------------------------------------------
11034// Checking for shift by too many bits
11135// ---------------------------------------------------------------------------
@@ -124,7 +48,7 @@ void CheckType::checkTooBigBitwiseShift()
12448 for (std::size_t i = 0 ; i < functions; ++i) {
12549 const Scope * scope = symbolDatabase->functionScopes [i];
12650 for (const Token* tok = scope->classStart ->next (); tok != scope->classEnd ; tok = tok->next ()) {
127- if (tok-> str () != " <<" && tok-> str () != " >> " )
51+ if (! Token::Match (tok, " <<|>>|<<=|>>= " ) )
12852 continue ;
12953
13054 if (!tok->astOperand1 () || !tok->astOperand2 ())
@@ -198,30 +122,29 @@ void CheckType::checkIntegerOverflow()
198122 if (!value)
199123 continue ;
200124
201- // get size and sign of result..
202- unsigned int size = 0 ;
203- char sign = 0 ;
204- if (!astGetSizeSign (_settings, tok, &size, &sign))
205- continue ;
206- if (sign != ' s' ) // only signed integer overflow is UB
207- continue ;
208-
209- integerOverflowError (tok, *value);
125+ // is result signed integer?
126+ const ValueType *vt = tok->valueType ();
127+ if (vt && vt->type == ValueType::Type::INT && vt->sign == ValueType::Sign::SIGNED )
128+ integerOverflowError (tok, *value);
210129 }
211130 }
212131}
213132
214133void CheckType::integerOverflowError (const Token *tok, const ValueFlow::Value &value)
215134{
216135 const std::string expr (tok ? tok->expressionString () : " " );
217- const std::string cond (value.condition ?
218- " . See condition at line " + MathLib::toString (value.condition ->linenr ()) + " ." :
219- " " );
136+
137+ std::string msg;
138+ if (value.condition )
139+ msg = ValueFlow::eitherTheConditionIsRedundant (value.condition ) +
140+ " or there is signed integer overflow for expression '" + expr + " '." ;
141+ else
142+ msg = " Signed integer overflow for expression '" + expr + " '." ;
220143
221144 reportError (tok,
222145 value.condition ? Severity::warning : Severity::error,
223146 " integerOverflow" ,
224- " Signed integer overflow for expression ' " +expr+ " ' " +cond ,
147+ msg ,
225148 0U ,
226149 value.inconclusive );
227150}
@@ -243,15 +166,11 @@ void CheckType::checkSignConversion()
243166 if (!tok->isArithmeticalOp () || Token::Match (tok," +|-" ))
244167 continue ;
245168
246- unsigned int size = 0 ;
247- char sign = 0 ;
248- if (!astGetSizeSign (_settings, tok, &size, &sign))
169+ // Is result unsigned?
170+ if (!(tok->valueType () && tok->valueType ()->sign == ValueType::Sign::UNSIGNED ))
249171 continue ;
250172
251- if (sign != ' u' )
252- continue ;
253-
254- // Check if there are signed operands that can be negative..
173+ // Check if an operand can be negative..
255174 std::stack<const Token *> tokens;
256175 tokens.push (tok->astOperand1 ());
257176 tokens.push (tok->astOperand2 ());
@@ -260,30 +179,10 @@ void CheckType::checkSignConversion()
260179 tokens.pop ();
261180 if (!tok1)
262181 continue ;
263- if (tok1->str () == " (" )
264- continue ; // Todo: properly handle casts, function calls, etc
265- const Variable *var = tok1->variable ();
266- if (var && tok1->getValueLE (-1 ,_settings)) {
267- bool signedvar = true ; // assume that variable is signed since it can have a negative value
268- for (const Token *type = var->typeStartToken ();; type = type->next ()) {
269- if (type->isUnsigned ()) {
270- signedvar = false ;
271- break ;
272- }
273- if (type->isSigned ())
274- break ;
275- if (type->isName () && !Token::Match (type, " char|short|int|long|const" )) {
276- signedvar = false ;
277- break ;
278- }
279- if (type == var->typeEndToken ())
280- break ;
281- }
282- if (signedvar) {
283- signConversionError (tok1);
284- break ;
285- }
286- }
182+ if (!tok1->getValueLE (-1 ,_settings))
183+ continue ;
184+ if (tok1->valueType () && tok1->valueType ()->sign != ValueType::Sign::UNSIGNED )
185+ signConversionError (tok1);
287186 }
288187 }
289188 }
@@ -311,13 +210,23 @@ void CheckType::checkLongCast()
311210
312211 // Assignments..
313212 for (const Token *tok = _tokenizer->tokens (); tok; tok = tok->next ()) {
314- if (!Token::Match (tok, " %var% =" ))
315- continue ;
316- if (!tok->variable () || !tok->variable ()->isConst () || tok->variable ()->typeStartToken ()->str () != " long" )
213+ if (tok->str () != " =" || !Token::Match (tok->astOperand2 (), " *|<<" ))
317214 continue ;
318- if (!tok->variable ()->typeStartToken ()->originalName ().empty ())
215+
216+ const ValueType *lhstype = tok->astOperand1 () ? tok->astOperand1 ()->valueType () : nullptr ;
217+ const ValueType *rhstype = tok->astOperand2 ()->valueType ();
218+
219+ if (!lhstype || !rhstype)
319220 continue ;
320- if (Token::Match (tok->next ()->astOperand2 (), " *|<<" ) && astIsIntResult (tok->next ()->astOperand2 ()))
221+
222+ // assign int result to long/longlong const nonpointer?
223+ if (rhstype->type == ValueType::Type::INT &&
224+ rhstype->pointer == 0U &&
225+ rhstype->originalTypeName .empty () &&
226+ (lhstype->type == ValueType::Type::LONG || lhstype->type == ValueType::Type::LONGLONG ) &&
227+ lhstype->pointer == 0U &&
228+ lhstype->constness == 1U &&
229+ lhstype->originalTypeName .empty ())
321230 longCastAssignError (tok);
322231 }
323232
@@ -340,21 +249,24 @@ void CheckType::checkLongCast()
340249 if (!islong)
341250 continue ;
342251
343- // find return statement
344- // todo.. this is slow, we should only check last statement in each child scope
252+ // return statements
345253 const Token *ret = nullptr ;
346254 for (const Token *tok = scope->classStart ; tok != scope->classEnd ; tok = tok->next ()) {
347255 if (tok->str () == " return" ) {
348- if (!ret)
349- ret = tok;
350- else {
351- ret = nullptr ;
256+ if (Token::Match (tok->astOperand1 (), " <<|*" )) {
257+ const ValueType *type = tok->astOperand1 ()->valueType ();
258+ if (type->type == ValueType::Type::INT && type->pointer == 0U && type->originalTypeName .empty ())
259+ ret = tok;
260+ }
261+ // All return statements must have problem otherwise no warning
262+ if (ret != tok) {
263+ ret = nullptr ;
352264 break ;
353265 }
354266 }
355267 }
356268
357- if (ret && Token::Match (ret-> astOperand1 (), " *|<< " ) && astIsIntResult (ret-> astOperand1 ()) )
269+ if (ret)
358270 longCastReturnError (ret);
359271 }
360272}
0 commit comments