CheckUnsignedDivision: Refactoring

This commit is contained in:
Daniel Marjamäki 2008-09-15 06:40:26 +00:00
parent 259e0ce238
commit 528deafe68
2 changed files with 33 additions and 46 deletions

View File

@ -3,6 +3,7 @@
#include "tokenize.h" #include "tokenize.h"
#include "CommonCheck.h" #include "CommonCheck.h"
#include <list> #include <list>
#include <map>
#include <sstream> #include <sstream>
#include <stdlib.h> // <- atoi #include <stdlib.h> // <- atoi
#include <cstring> #include <cstring>
@ -320,57 +321,27 @@ void CheckIfAssignment()
void CheckUnsignedDivision() void CheckUnsignedDivision()
{ {
// Check for "ivar / uvar" and "uvar / ivar" // Check for "ivar / uvar" and "uvar / ivar"
// Todo: Much better checking for declared variables std::map<std::string, char> varsign;
const char *div_pattern[] = {"", "/", "", NULL}; for ( TOKEN *tok = tokens; tok; tok = tok->next )
for (const TOKEN *div_tok = findtoken(tokens, div_pattern); div_tok; div_tok = findtoken(div_tok->next, div_pattern))
{ {
const char *varname1 = div_tok->str; if ( Match(tok, "[{};(,] %type% %var% [;=,)]") )
const char *varname2 = div_tok->next->next->str; varsign[getstr(tok,2)] = 's';
if ( IsName(varname1) && IsName(varname2) )
else if ( Match(tok, "[{};(,] unsigned %type% %var% [;=,)]") )
varsign[getstr(tok,3)] = 'u';
else if ( tok->str[0] != ')' && Match(tok->next, "%var% / %var%") )
{ {
char var1_sign=0, var2_sign=0; const char *varname1 = getstr(tok,1);
const char *varname2 = getstr(tok,3);
char sign1 = varsign[varname1];
char sign2 = varsign[varname2];
// Check if any of the variables are unsigned.. if ( sign1 && sign2 && sign1 != sign2 )
const char *pattern_declvar[] = { "unsigned", "", "", NULL };
pattern_declvar[2] = varname1;
if ( findtoken(tokens, pattern_declvar) )
var1_sign = 'u';
pattern_declvar[2] = varname2;
if ( findtoken(tokens, pattern_declvar) )
var2_sign = 'u';
if (var1_sign == var2_sign)
continue;
// Check if any of the variables are signed..
pattern_declvar[0] = ";";
pattern_declvar[1] = "int";
pattern_declvar[2] = varname1;
if ( findtoken(tokens, pattern_declvar) )
var1_sign = 's';
pattern_declvar[2] = varname2;
if ( findtoken(tokens, pattern_declvar) )
var2_sign = 's';
pattern_declvar[0] = "{";
pattern_declvar[2] = varname1;
if ( findtoken(tokens, pattern_declvar) )
var1_sign = 's';
pattern_declvar[2] = varname2;
if ( findtoken(tokens, pattern_declvar) )
var2_sign = 's';
if ( var1_sign && var2_sign && var1_sign != var2_sign )
{ {
// One of the operands are signed, the other is unsigned.. // One of the operands are signed, the other is unsigned..
std::ostringstream ostr; std::ostringstream ostr;
ostr << FileLine(div_tok) << ": Warning: Division with signed and unsigned operators"; ostr << FileLine(tok->next) << ": Warning: Division with signed and unsigned operators";
ReportErr(ostr.str()); ReportErr(ostr.str());
} }
} }

View File

@ -37,6 +37,7 @@ public:
TEST_CASE( division1 ); TEST_CASE( division1 );
TEST_CASE( division2 ); TEST_CASE( division2 );
TEST_CASE( division3 ); TEST_CASE( division3 );
TEST_CASE( division4 );
} }
void division1() void division1()
@ -73,6 +74,21 @@ public:
"}\n" ); "}\n" );
ASSERT_EQUALS( std::string("[test.cpp:7]: Warning: Division with signed and unsigned operators\n"), errout.str() ); ASSERT_EQUALS( std::string("[test.cpp:7]: Warning: Division with signed and unsigned operators\n"), errout.str() );
} }
void division4()
{
check( "void f1()\n"
"{\n"
" int i1;\n"
"}\n"
"\n"
"void f2(unsigned int i1)\n"
"{\n"
" unsigned int i2;\n"
" result = i2 / i1;\n"
);
ASSERT_EQUALS( std::string(""), errout.str() );
}
}; };
REGISTER_FIXTURE( TestDivision ) REGISTER_FIXTURE( TestDivision )