diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index 97c2c453d..c1e642436 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 fcdf75392..2d39cc741 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: