Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions lib/astutils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -547,6 +547,26 @@ bool isDifferentKnownValues(const Token * const tok1, const Token * const tok2)
return result;
}

static bool isSameConstantValue(bool macro, const Token * const tok1, const Token * const tok2)
{
if (tok1 == nullptr || tok2 == nullptr)
return false;

if (!tok1->isNumber() || !tok2->isNumber())
return false;

if (macro && (tok1->isExpandedMacro() || tok2->isExpandedMacro() || tok1->isTemplateArg() || tok2->isTemplateArg()))
return false;

const ValueType * v1 = tok1->valueType();
const ValueType * v2 = tok2->valueType();

if (!v1 || !v2 || v1->sign != v2->sign || v1->type != v2->type || v1->pointer != v2->pointer)
return false;

return isEqualKnownValue(tok1, tok2);
}

bool isSameExpression(bool cpp, bool macro, const Token *tok1, const Token *tok2, const Library& library, bool pure, bool followVar, ErrorPath* errors)
{
if (tok1 == nullptr && tok2 == nullptr)
Expand All @@ -568,6 +588,9 @@ bool isSameExpression(bool cpp, bool macro, const Token *tok1, const Token *tok2
}
if (tok1->str() != tok2->str() && isDifferentKnownValues(tok1, tok2))
return false;
if (isSameConstantValue(macro, tok1, tok2))
return true;

// Follow variable
if (followVar && tok1->str() != tok2->str() && (Token::Match(tok1, "%var%") || Token::Match(tok2, "%var%"))) {
const Token * varTok1 = followVariableExpression(tok1, cpp, tok2);
Expand Down
28 changes: 28 additions & 0 deletions test/testastutils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ class TestAstUtils : public TestFixture {
TEST_CASE(findLambdaEndToken);
TEST_CASE(findLambdaStartToken);
TEST_CASE(isReturnScope);
TEST_CASE(isSameExpression);
TEST_CASE(isVariableChanged);
TEST_CASE(isVariableChangedByFunctionCall);
TEST_CASE(nextAfterAstRightmostLeaf);
Expand Down Expand Up @@ -135,6 +136,33 @@ class TestAstUtils : public TestFixture {
ASSERT_EQUALS(true, isReturnScope("void positiveTokenOffset() { return; }", 7));
}

bool isSameExpression(const char code[], const char tokStr1[], const char tokStr2[]) {
Settings settings;
Library library;
Tokenizer tokenizer(&settings, this);
std::istringstream istr(code);
tokenizer.tokenize(istr, "test.cpp");
const Token * const tok1 = Token::findsimplematch(tokenizer.tokens(), tokStr1);
const Token * const tok2 = Token::findsimplematch(tok1->next(), tokStr2);
return ::isSameExpression(false, false, tok1, tok2, library, false, false, nullptr);
}

void isSameExpression() {
ASSERT_EQUALS(true, isSameExpression("x = 1 + 1;", "1", "1"));
ASSERT_EQUALS(false, isSameExpression("x = 1 + 1u;", "1", "1u"));
ASSERT_EQUALS(true, isSameExpression("x = 1.0 + 1.0;", "1.0", "1.0"));
ASSERT_EQUALS(false, isSameExpression("x = 1.0f + 1.0;", "1.0f", "1.0"));
ASSERT_EQUALS(false, isSameExpression("x = 1L + 1;", "1L", "1"));
ASSERT_EQUALS(true, isSameExpression("x = 0.0f + 0x0p+0f;", "0.0f", "0x0p+0f"));
ASSERT_EQUALS(true, isSameExpression("x < x;", "x", "x"));
ASSERT_EQUALS(false, isSameExpression("x < y;", "x", "y"));
ASSERT_EQUALS(true, isSameExpression("(x + 1) < (x + 1);", "+", "+"));
ASSERT_EQUALS(false, isSameExpression("(x + 1) < (x + 1L);", "+", "+"));
ASSERT_EQUALS(true, isSameExpression("(1 + x) < (x + 1);", "+", "+"));
ASSERT_EQUALS(false, isSameExpression("(1.0l + x) < (1.0 + x);", "+", "+"));
ASSERT_EQUALS(true, isSameExpression("(0.0 + x) < (x + 0x0p+0);", "+", "+"));
}

bool isVariableChanged(const char code[], const char startPattern[], const char endPattern[]) {
Settings settings;
Tokenizer tokenizer(&settings, this);
Expand Down