Use ValueType in CheckOther::invalidPointerCast()

False negative: operator new is currently not supported by ValueType.
This commit is contained in:
PKEuS 2016-02-05 19:51:45 +01:00 committed by PKEuS
parent 4b3feebbcd
commit b4b38fb7ce
2 changed files with 25 additions and 64 deletions

View File

@ -291,21 +291,6 @@ void CheckOther::cstyleCastError(const Token *tok)
// float* f; double* d = (double*)f; <-- Pointer cast to a type with an incompatible binary data representation
//---------------------------------------------------------------------------
static std::string analyzeType(const Token* tok)
{
if (tok->str() == "double") {
if (tok->isLong())
return "long double";
else
return "double";
}
if (tok->str() == "float")
return "float";
if (Token::Match(tok, "int|long|short|char|size_t"))
return "integer";
return "";
}
void CheckOther::invalidPointerCast()
{
if (!_settings->isEnabled("portability"))
@ -318,60 +303,35 @@ void CheckOther::invalidPointerCast()
const Scope * scope = symbolDatabase->functionScopes[i];
for (const Token* tok = scope->classStart->next(); tok != scope->classEnd; tok = tok->next()) {
const Token* toTok = nullptr;
const Token* nextTok = nullptr;
const Token* fromTok = nullptr;
// Find cast
if (Token::Match(tok, "( const| %type% %type%| const| * )")) {
toTok = tok->next();
nextTok = tok->link()->next();
if (nextTok && nextTok->str() == "(")
nextTok = nextTok->next();
} else if (Token::Match(tok, "reinterpret_cast < const| %type% %type%| const| * > (")) {
nextTok = tok->tokAt(5);
while (nextTok->str() != "(")
nextTok = nextTok->next();
nextTok = nextTok->next();
toTok = tok->tokAt(2);
toTok = tok;
fromTok = tok->astOperand1();
} else if (Token::Match(tok, "reinterpret_cast <") && tok->linkAt(1)) {
toTok = tok->linkAt(1)->next();
fromTok = toTok->astOperand2();
}
if (!nextTok)
continue;
if (toTok && toTok->str() == "const")
toTok = toTok->next();
if (!toTok || !toTok->isStandardType())
if (!fromTok)
continue;
// Find casted variable
const Variable *var = nullptr;
bool allocation = false;
bool ref = false;
if (_tokenizer->isCPP() && Token::Match(nextTok, "new %type%"))
allocation = true;
else if (Token::Match(nextTok, "%var% !!["))
var = nextTok->variable();
else if (Token::Match(nextTok, "& %var%") && !Token::Match(nextTok->tokAt(2), "(|[")) {
var = nextTok->next()->variable();
ref = true;
}
const ValueType* fromType = fromTok->valueType();
const ValueType* toType = toTok->valueType();
if (!fromType || !toType || !fromType->pointer || !toType->pointer)
continue;
const Token* fromTok = nullptr;
if (allocation) {
fromTok = nextTok->next();
} else {
if (!var || (!ref && !var->isPointer() && !var->isArray()) || (ref && (var->isPointer() || var->isArray())))
if (fromType->type != toType->type && fromType->type >= ValueType::Type::BOOL && toType->type >= ValueType::Type::BOOL && (toType->type != ValueType::Type::CHAR || printInconclusive)) {
if (toType->isIntegral() && fromType->isIntegral())
continue;
fromTok = var->typeStartToken();
std::string toStr = toType->isIntegral() ? "integer *" : toType->str();
toStr.pop_back();
toStr.pop_back();
std::string fromStr = fromType->isIntegral() ? "integer *" : fromType->str();
fromStr.pop_back();
fromStr.pop_back();
invalidPointerCastError(tok, fromStr, toStr, toType->type == ValueType::Type::CHAR);
}
while (Token::Match(fromTok, "static|const"))
fromTok = fromTok->next();
if (!fromTok->isStandardType())
continue;
std::string fromType = analyzeType(fromTok);
std::string toType = analyzeType(toTok);
if (fromType != toType && !fromType.empty() && !toType.empty() && (toTok->str() != "char" || printInconclusive))
invalidPointerCastError(tok, fromType, toType, toTok->str() == "char");
}
}
}

View File

@ -1246,13 +1246,14 @@ private:
" delete [] (double*)f;\n"
" delete [] (long double const*)(new float[10]);\n"
"}");
ASSERT_EQUALS("[test.cpp:3]: (portability) Casting between float* and double* which have an incompatible binary data representation.\n"
"[test.cpp:4]: (portability) Casting between float* and long double* which have an incompatible binary data representation.\n", errout.str());
TODO_ASSERT_EQUALS("[test.cpp:3]: (portability) Casting between float* and double* which have an incompatible binary data representation.\n"
"[test.cpp:4]: (portability) Casting between float* and const long double* which have an incompatible binary data representation.\n",
"[test.cpp:3]: (portability) Casting between float* and double* which have an incompatible binary data representation.\n", errout.str());
checkInvalidPointerCast("void test(const float* f) {\n"
" double *d = (double*)f;\n"
"}");
ASSERT_EQUALS("[test.cpp:2]: (portability) Casting between float* and double* which have an incompatible binary data representation.\n", errout.str());
ASSERT_EQUALS("[test.cpp:2]: (portability) Casting between const float* and double* which have an incompatible binary data representation.\n", errout.str());
checkInvalidPointerCast("void test(double* d1) {\n"
" long double *ld = (long double*)d1;\n"