Refactor void* checking. Use ValueType.

This commit is contained in:
Daniel Marjamäki 2015-12-30 11:48:20 +01:00
parent fdcab8f1bb
commit c0e8654649
2 changed files with 25 additions and 42 deletions

View File

@ -334,47 +334,30 @@ void CheckSizeof::sizeofVoid()
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) { for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) {
if (Token::simpleMatch(tok, "sizeof ( )")) { // "sizeof(void)" gets simplified to sizeof ( ) if (Token::simpleMatch(tok, "sizeof ( )")) { // "sizeof(void)" gets simplified to sizeof ( )
sizeofVoidError(tok); sizeofVoidError(tok);
} else if (Token::Match(tok, "sizeof ( * %var% )") && tok->tokAt(3)->variable() && } else if (Token::Match(tok, "sizeof (") && tok->next()->astOperand2()) {
(Token::Match(tok->tokAt(3)->variable()->typeStartToken(), "void * !!*")) && const ValueType *vt = tok->next()->astOperand2()->valueType();
(!tok->tokAt(3)->variable()->isArray())) { // sizeof(*p) where p is of type "void*" if (vt && vt->type == ValueType::Type::VOID && vt->pointer == 0U)
sizeofDereferencedVoidPointerError(tok, tok->strAt(3)); sizeofDereferencedVoidPointerError(tok, tok->strAt(3));
} else if (Token::Match(tok, "%name% +|-|++|--") || } else if (tok->str() == "-") {
Token::Match(tok, "+|-|++|-- %name%")) { // Arithmetic operations on variable of type "void*" // only warn for: 'void *' - 'integral'
const int index = (tok->isName()) ? 0 : 1; const ValueType *vt1 = tok->astOperand1() ? tok->astOperand1()->valueType() : nullptr;
const Variable* var = tok->tokAt(index)->variable(); const ValueType *vt2 = tok->astOperand2() ? tok->astOperand2()->valueType() : nullptr;
if (var && !var->isArray() && Token::Match(var->typeStartToken(), "void * !!*")) { bool op1IsvoidPointer = (vt1 && vt1->type == ValueType::Type::VOID && vt1->pointer == 1U);
std::string varname = tok->strAt(index); bool op2IsIntegral = (vt2 && vt2->isIntegral() && vt2->pointer == 0U);
// In case this 'void *' var is a member then go back to the main object if (op1IsvoidPointer && op2IsIntegral)
const Token* tok2 = tok->tokAt(index); arithOperationsOnVoidPointerError(tok, tok->astOperand1()->expressionString(), vt1->str());
if (index == 0) { } else if (Token::Match(tok, "+|++|--|+=|-=")) { // Arithmetic operations on variable of type "void*"
bool isMember = false; const ValueType *vt1 = tok->astOperand1() ? tok->astOperand1()->valueType() : nullptr;
while (Token::simpleMatch(tok2->previous(), ".")) { const ValueType *vt2 = tok->astOperand2() ? tok->astOperand2()->valueType() : nullptr;
isMember = true;
if (Token::simpleMatch(tok2->tokAt(-2), ")")) bool voidpointer1 = (vt1 && vt1->type == ValueType::Type::VOID && vt1->pointer == 1U);
tok2 = tok2->linkAt(-2); bool voidpointer2 = (vt2 && vt2->type == ValueType::Type::VOID && vt2->pointer == 1U);
else if (Token::simpleMatch(tok2->tokAt(-2), "]"))
tok2 = tok2->linkAt(-2)->previous(); if (voidpointer1)
else arithOperationsOnVoidPointerError(tok, tok->astOperand1()->expressionString(), vt1->str());
tok2 = tok2->tokAt(-2);
} if (!tok->isAssignmentOp() && voidpointer2)
if (isMember) { arithOperationsOnVoidPointerError(tok, tok->astOperand2()->expressionString(), vt2->str());
// Get 'struct.member' complete name (without spaces)
varname = tok2->stringifyList(tok->next());
varname.erase(std::remove_if(varname.begin(), varname.end(),
static_cast<int (*)(int)>(std::isspace)), varname.end());
}
}
// Check for cast on operations with '+|-'
if (Token::Match(tok, "%name% +|-")) {
// Check for cast expression
if (Token::simpleMatch(tok2->previous(), ")") && !Token::Match(tok2->previous()->link(), "( const| void *"))
continue;
if (tok2->strAt(-1) == "&") // Check for reference operator
continue;
}
arithOperationsOnVoidPointerError(tok, varname,
var->typeStartToken()->stringifyList(var->typeEndToken()->next()));
}
} }
} }
} }

View File

@ -659,7 +659,7 @@ private:
"[test.cpp:3]: (portability) 'data' is of type 'void *'. When using void pointers in calculations, the behaviour is undefined.\n", errout.str()); "[test.cpp:3]: (portability) 'data' is of type 'void *'. When using void pointers in calculations, the behaviour is undefined.\n", errout.str());
check("void f(void *data) {\n" check("void f(void *data) {\n"
" void* data2 = (void *)data + 1;\n" " void* data2 = data + 1;\n"
"}"); "}");
ASSERT_EQUALS("[test.cpp:2]: (portability) 'data' is of type 'void *'. When using void pointers in calculations, the behaviour is undefined.\n", errout.str()); ASSERT_EQUALS("[test.cpp:2]: (portability) 'data' is of type 'void *'. When using void pointers in calculations, the behaviour is undefined.\n", errout.str());