From c3e33875cf3ae58f748671221bf725c6b88a924a Mon Sep 17 00:00:00 2001 From: chrchr-github <78114321+chrchr-github@users.noreply.github.com> Date: Fri, 11 Oct 2024 17:28:59 +0200 Subject: [PATCH] Fix #13202 FP oppositeInnerCondition for string defines (#6889) --- lib/astutils.cpp | 10 ++++++++-- test/cfg/bsd.c | 4 ++++ test/testcondition.cpp | 28 ++++++++++++++++++++++++++++ test/testother.cpp | 15 +++++++++++++++ 4 files changed, 55 insertions(+), 2 deletions(-) diff --git a/lib/astutils.cpp b/lib/astutils.cpp index 9b590dff290..2eb998fb8e3 100644 --- a/lib/astutils.cpp +++ b/lib/astutils.cpp @@ -1544,8 +1544,14 @@ bool isUsedAsBool(const Token* const tok, const Settings& settings) } bool compareTokenFlags(const Token* tok1, const Token* tok2, bool macro) { - if (macro && (tok1->isExpandedMacro() || tok2->isExpandedMacro() || tok1->isTemplateArg() || tok2->isTemplateArg())) - return false; + if (macro) { + if (tok1->isExpandedMacro() != tok2->isExpandedMacro()) + return false; + if (tok1->isExpandedMacro() && tok1->getMacroName() != tok2->getMacroName()) + return false; + if (tok1->isTemplateArg() || tok2->isTemplateArg()) + return false; + } if (tok1->isComplex() != tok2->isComplex()) return false; if (tok1->isLong() != tok2->isLong()) diff --git a/test/cfg/bsd.c b/test/cfg/bsd.c index d64746d2a3a..4727ea6f542 100644 --- a/test/cfg/bsd.c +++ b/test/cfg/bsd.c @@ -32,11 +32,15 @@ void nullPointer_setlinebuf(FILE *stream) // #9323, #9331 void verify_timercmp(struct timeval t) { + // cppcheck-suppress duplicateExpression (void)timercmp(&t, &t, <); + // cppcheck-suppress duplicateExpression (void)timercmp(&t, &t, <=); (void)timercmp(&t, &t, ==); (void)timercmp(&t, &t, !=); + // cppcheck-suppress duplicateExpression (void)timercmp(&t, &t, >=); + // cppcheck-suppress duplicateExpression (void)timercmp(&t, &t, >); } diff --git a/test/testcondition.cpp b/test/testcondition.cpp index 1e080755a65..8042692b60b 100644 --- a/test/testcondition.cpp +++ b/test/testcondition.cpp @@ -144,6 +144,22 @@ class TestCondition : public TestFixture { check_(file, line, code, settings, filename); } +#define checkP(...) checkP_(__FILE__, __LINE__, __VA_ARGS__) + void checkP_(const char* file, int line, const char code[], const char* filename = "test.cpp") + { + const Settings settings = settingsBuilder(settings0).severity(Severity::performance).certainty(Certainty::inconclusive).build(); + + std::vector files(1, filename); + Tokenizer tokenizer(settings, *this); + PreprocessorHelper::preprocess(code, files, tokenizer, *this); + + // Tokenizer.. + ASSERT_LOC(tokenizer.simplifyTokens1(""), file, line); + + // Run checks.. + runChecks(tokenizer, this); + } + void assignAndCompare() { // & check("void foo(int x)\n" @@ -2754,6 +2770,18 @@ class TestCondition : public TestFixture { " }\n" "}"); ASSERT_EQUALS("", errout_str()); + + checkP("#define TYPE_1 \"a\"\n" // #13202 + "#define TYPE_2 \"b\"\n" + "#define TYPE_3 \"c\"\n" + "void f(const std::string& s) {\n" + " if (s == TYPE_1) {}\n" + " else if (s == TYPE_2 || s == TYPE_3) {\n" + " if (s == TYPE_2) {}\n" + " else if (s == TYPE_3) {}\n" + " }\n" + "}"); + ASSERT_EQUALS("", errout_str()); } void identicalConditionAfterEarlyExit() { diff --git a/test/testother.cpp b/test/testother.cpp index 6fd52f2e06c..8f7fce676ec 100644 --- a/test/testother.cpp +++ b/test/testother.cpp @@ -7074,6 +7074,21 @@ class TestOther : public TestFixture { " if ($a == $a) { }\n" "}"); ASSERT_EQUALS("", errout_str()); + + checkP("#define X 1\n" + "#define Y 1\n" + "void f() {\n" + " if (X == X) {}\n" + " if (X == Y) {}\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:4]: (style) Same expression on both sides of '=='.\n", errout_str()); + + checkP("#define X 1\n" + "#define Y X\n" + "void f() {\n" + " if (X == Y) {}\n" + "}\n"); + ASSERT_EQUALS("", errout_str()); } void duplicateExpression6() { // #4639