Fixed #6350 (Tokenizer::simplifyCast: set Token::isCasted when cast is removed)
This commit is contained in:
parent
95940ff0ef
commit
1b2a23b3fe
|
@ -841,7 +841,7 @@ void CheckBufferOverrun::checkScope(const Token *tok, const ArrayInfo &arrayInfo
|
||||||
valueFlowCheckArrayIndex(tok->next(), arrayInfo);
|
valueFlowCheckArrayIndex(tok->next(), arrayInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (isPortabilityEnabled && tok->astParent() && tok->astParent()->str() == "+") {
|
else if (isPortabilityEnabled && !tok->isCasted() && tok->astParent() && tok->astParent()->str() == "+") {
|
||||||
const ValueFlow::Value *index;
|
const ValueFlow::Value *index;
|
||||||
if (tok == tok->astParent()->astOperand1())
|
if (tok == tok->astParent()->astOperand1())
|
||||||
index = tok->astParent()->astOperand2()->getMaxValue(false);
|
index = tok->astParent()->astOperand2()->getMaxValue(false);
|
||||||
|
|
23
lib/token.h
23
lib/token.h
|
@ -313,6 +313,12 @@ public:
|
||||||
void isExpandedMacro(bool m) {
|
void isExpandedMacro(bool m) {
|
||||||
setFlag(fIsExpandedMacro, m);
|
setFlag(fIsExpandedMacro, m);
|
||||||
}
|
}
|
||||||
|
bool isCasted() const {
|
||||||
|
return getFlag(fIsCasted);
|
||||||
|
}
|
||||||
|
void isCasted(bool c) {
|
||||||
|
setFlag(fIsCasted, c);
|
||||||
|
}
|
||||||
bool isAttributeConstructor() const {
|
bool isAttributeConstructor() const {
|
||||||
return getFlag(fIsAttributeConstructor);
|
return getFlag(fIsAttributeConstructor);
|
||||||
}
|
}
|
||||||
|
@ -753,14 +759,15 @@ private:
|
||||||
fIsLong = (1 << 3),
|
fIsLong = (1 << 3),
|
||||||
fIsStandardType = (1 << 4),
|
fIsStandardType = (1 << 4),
|
||||||
fIsExpandedMacro = (1 << 5),
|
fIsExpandedMacro = (1 << 5),
|
||||||
fIsAttributeConstructor = (1 << 6), // __attribute__((constructor)) __attribute__((constructor(priority)))
|
fIsCasted = (1 << 6),
|
||||||
fIsAttributeDestructor = (1 << 7), // __attribute__((destructor)) __attribute__((destructor(priority)))
|
fIsAttributeConstructor = (1 << 7), // __attribute__((constructor)) __attribute__((constructor(priority)))
|
||||||
fIsAttributeUnused = (1 << 8), // __attribute__((unused))
|
fIsAttributeDestructor = (1 << 8), // __attribute__((destructor)) __attribute__((destructor(priority)))
|
||||||
fIsAttributePure = (1 << 9), // __attribute__((pure))
|
fIsAttributeUnused = (1 << 9), // __attribute__((unused))
|
||||||
fIsAttributeConst = (1 << 10), // __attribute__((const))
|
fIsAttributePure = (1 << 10), // __attribute__((pure))
|
||||||
fIsAttributeNothrow = (1 << 11), // __attribute__((nothrow))
|
fIsAttributeConst = (1 << 11), // __attribute__((const))
|
||||||
fIsDeclspecNothrow = (1 << 12), // __declspec(nothrow)
|
fIsAttributeNothrow = (1 << 12), // __attribute__((nothrow))
|
||||||
fIsAttributeUsed = (1 << 13) // __attribute__((used))
|
fIsDeclspecNothrow = (1 << 13), // __declspec(nothrow)
|
||||||
|
fIsAttributeUsed = (1 << 14) // __attribute__((used))
|
||||||
};
|
};
|
||||||
|
|
||||||
unsigned int _flags;
|
unsigned int _flags;
|
||||||
|
|
|
@ -5004,6 +5004,7 @@ void Tokenizer::simplifyCasts()
|
||||||
if (!tok->tokAt(2)->isUnsigned() && bits > 0)
|
if (!tok->tokAt(2)->isUnsigned() && bits > 0)
|
||||||
bits--;
|
bits--;
|
||||||
if (bits < 31 && value >= 0 && value < (1LL << bits)) {
|
if (bits < 31 && value >= 0 && value < (1LL << bits)) {
|
||||||
|
tok->linkAt(1)->next()->isCasted(true);
|
||||||
Token::eraseTokens(tok, tok->next()->link()->next());
|
Token::eraseTokens(tok, tok->next()->link()->next());
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
|
@ -5023,6 +5024,15 @@ void Tokenizer::simplifyCasts()
|
||||||
// Remove cast..
|
// Remove cast..
|
||||||
Token::eraseTokens(tok, tok->next()->link()->next());
|
Token::eraseTokens(tok, tok->next()->link()->next());
|
||||||
|
|
||||||
|
// Set isCasted flag.
|
||||||
|
Token *tok2 = tok->next();
|
||||||
|
if (!Token::Match(tok2, "%var% [|."))
|
||||||
|
tok2->isCasted(true);
|
||||||
|
else {
|
||||||
|
// TODO: handle more complex expressions
|
||||||
|
tok2->next()->isCasted(true);
|
||||||
|
}
|
||||||
|
|
||||||
// Remove '* &'
|
// Remove '* &'
|
||||||
if (Token::simpleMatch(tok, "* &")) {
|
if (Token::simpleMatch(tok, "* &")) {
|
||||||
tok->deleteNext();
|
tok->deleteNext();
|
||||||
|
@ -5038,6 +5048,7 @@ void Tokenizer::simplifyCasts()
|
||||||
|
|
||||||
// Replace pointer casts of 0.. "(char *)0" => "0"
|
// Replace pointer casts of 0.. "(char *)0" => "0"
|
||||||
while (Token::Match(tok->next(), "( %type% %type%| * ) 0")) {
|
while (Token::Match(tok->next(), "( %type% %type%| * ) 0")) {
|
||||||
|
tok->linkAt(1)->next()->isCasted(true);
|
||||||
Token::eraseTokens(tok, tok->next()->link()->next());
|
Token::eraseTokens(tok, tok->next()->link()->next());
|
||||||
if (tok->str() == ")" && tok->link()->previous()) {
|
if (tok->str() == ")" && tok->link()->previous()) {
|
||||||
// If there was another cast before this, go back
|
// If there was another cast before this, go back
|
||||||
|
@ -5048,11 +5059,11 @@ void Tokenizer::simplifyCasts()
|
||||||
|
|
||||||
if (Token::Match(tok->next(), "dynamic_cast|reinterpret_cast|const_cast|static_cast <")) {
|
if (Token::Match(tok->next(), "dynamic_cast|reinterpret_cast|const_cast|static_cast <")) {
|
||||||
Token *tok2 = tok->linkAt(2);
|
Token *tok2 = tok->linkAt(2);
|
||||||
|
if (!Token::simpleMatch(tok2, "> ("))
|
||||||
if (Token::simpleMatch(tok2, "> ("))
|
|
||||||
Token::eraseTokens(tok, tok2->next());
|
|
||||||
else
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
tok2->tokAt(2)->isCasted(true);
|
||||||
|
Token::eraseTokens(tok, tok2->next());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2955,6 +2955,12 @@ private:
|
||||||
" return a + 100;\n"
|
" return a + 100;\n"
|
||||||
"}");
|
"}");
|
||||||
ASSERT_EQUALS("[test.cpp:3]: (portability) Undefined behaviour: Pointer arithmetic result does not point into or just past the end of the array.\n", errout.str());
|
ASSERT_EQUALS("[test.cpp:3]: (portability) Undefined behaviour: Pointer arithmetic result does not point into or just past the end of the array.\n", errout.str());
|
||||||
|
|
||||||
|
check("void f() {\n" // #6350 - fp when there is cast of buffer
|
||||||
|
" wchar_t buf[64];\n"
|
||||||
|
" p = (unsigned char *) buf + sizeof (buf);\n"
|
||||||
|
"}", false, "6350.c", false);
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void pointer_out_of_bounds_2() {
|
void pointer_out_of_bounds_2() {
|
||||||
|
|
Loading…
Reference in New Issue