From 56c7ac37718c6bacf9cad4e93ff752d2136e2437 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Sun, 19 Nov 2023 18:56:48 +0100 Subject: [PATCH] Fix #12182 (speedup valueFlow by only running valueFlowNumber once) (#5678) --- lib/valueflow.cpp | 23 ++++++++------ test/cli/test-other.py | 71 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 85 insertions(+), 9 deletions(-) diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index 97c2c453dee..c1e6424362f 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -1042,6 +1042,16 @@ static void setTokenValue(Token* tok, } } + // C++ init + else if (parent->str() == "{" && Token::simpleMatch(parent->previous(), "= {") && Token::simpleMatch(parent->link(), "} ;")) { + const Token* lhs = parent->previous()->astOperand1(); + if (lhs && lhs->valueType()) { + if (lhs->valueType()->isIntegral() || lhs->valueType()->isFloat() || (lhs->valueType()->pointer > 0 && value.isIntValue())) { + setTokenValue(parent, value, settings); + } + } + } + else if (Token::Match(parent, ":: %name%") && parent->astOperand2() == tok) { setTokenValue(parent, value, settings); } @@ -1335,16 +1345,12 @@ static Token * valueFlowSetConstantValue(Token *tok, const Settings *settings, b if (!tok->isTemplateArg()) value.setKnown(); setTokenValue(tok->next(), std::move(value), settings); - } else if (Token::Match(tok, "%name% = {") && tok->variable() && - (tok->variable()->isPointer() || (tok->variable()->valueType() && tok->variable()->valueType()->isIntegral()))) { - if (Token::simpleMatch(tok->tokAt(3), "}")) { + } else if (Token::simpleMatch(tok, "= { } ;")) { + const Token* lhs = tok->astOperand1(); + if (lhs && lhs->valueType() && (lhs->valueType()->isIntegral() || lhs->valueType()->pointer > 0)) { ValueFlow::Value value(0); value.setKnown(); - setTokenValue(tok->tokAt(2), std::move(value), settings); - } else if (tok->tokAt(2)->astOperand1() && tok->tokAt(2)->astOperand1()->hasKnownIntValue()) { - ValueFlow::Value value(tok->tokAt(2)->astOperand1()->getKnownIntValue()); - value.setKnown(); - setTokenValue(tok->tokAt(2), std::move(value), settings); + setTokenValue(tok->next(), std::move(value), settings); } } return tok->next(); @@ -9448,7 +9454,6 @@ void ValueFlow::setValues(TokenList& tokenlist, VFA(valueFlowUnknownFunctionReturn(tokenlist, settings)), VFA(valueFlowGlobalConstVar(tokenlist, settings)), VFA(valueFlowEnumValue(symboldatabase, settings)), - VFA(valueFlowNumber(tokenlist, settings)), VFA(valueFlowGlobalStaticVar(tokenlist, settings)), VFA(valueFlowPointerAlias(tokenlist, settings)), VFA(valueFlowLifetime(tokenlist, errorLogger, settings)), diff --git a/test/cli/test-other.py b/test/cli/test-other.py index fcdf7539295..2d39cc74179 100644 --- a/test/cli/test-other.py +++ b/test/cli/test-other.py @@ -191,6 +191,77 @@ def test_slow_long_line(tmpdir): cppcheck([filename]) # should not take more than ~1 second +@pytest.mark.timeout(60) +def test_slow_large_constant_expression(tmpdir): + # 12182 + filename = os.path.join(tmpdir, 'hang.c') + with open(filename, 'wt') as f: + f.write(""" +#define FLAG1 0 +#define FLAG2 0 +#define FLAG3 0 +#define FLAG4 0 +#define FLAG5 0 +#define FLAG6 0 +#define FLAG7 0 +#define FLAG8 0 +#define FLAG9 0 +#define FLAG10 0 +#define FLAG11 0 +#define FLAG12 0 +#define FLAG13 0 +#define FLAG14 0 +#define FLAG15 0 +#define FLAG16 0 +#define FLAG17 0 +#define FLAG18 0 +#define FLAG19 0 +#define FLAG20 0 +#define FLAG21 0 +#define FLAG22 0 +#define FLAG23 0 +#define FLAG24 0 + +#define maxval(x, y) ((x) > (y) ? (x) : (y)) + +#define E_SAMPLE_SIZE maxval( FLAG1, \ + maxval( FLAG2, \ + maxval( FLAG3, \ + maxval( FLAG4, \ + maxval( FLAG5, \ + maxval( FLAG6, \ + maxval( FLAG7, \ + maxval( FLAG8, \ + maxval( FLAG9, \ + maxval( FLAG10, \ + maxval( FLAG11, \ + maxval( FLAG12, \ + maxval( FLAG13, \ + maxval( FLAG14, \ + FLAG15 )))))))))))))) + +#define SAMPLE_SIZE maxval( E_SAMPLE_SIZE, \ + maxval( sizeof(st), \ + maxval( FLAG16, \ + maxval( FLAG17, \ + maxval( FLAG18, \ + maxval( FLAG19, \ + maxval( FLAG20, \ + maxval( FLAG21, \ + maxval( FLAG22, \ + maxval( FLAG23, \ + FLAG24 )))))))))) + +typedef struct { + int n; +} st; + +x = SAMPLE_SIZE; + """) + + cppcheck([filename]) + + def test_execute_addon_failure(tmpdir): test_file = os.path.join(tmpdir, 'test.cpp') with open(test_file, 'wt') as f: