Skip to content

Commit

Permalink
Partial fix for #12182 (speedup valueFlow by only running valueFlowNu…
Browse files Browse the repository at this point in the history
…mber once)
  • Loading branch information
danmar committed Nov 19, 2023
1 parent e01e090 commit ce0d2a9
Show file tree
Hide file tree
Showing 2 changed files with 89 additions and 9 deletions.
24 changes: 15 additions & 9 deletions lib/valueflow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -9448,7 +9454,7 @@ void ValueFlow::setValues(TokenList& tokenlist,
VFA(valueFlowUnknownFunctionReturn(tokenlist, settings)),
VFA(valueFlowGlobalConstVar(tokenlist, settings)),
VFA(valueFlowEnumValue(symboldatabase, settings)),
VFA(valueFlowNumber(tokenlist, settings)),
//VFA(valueFlowCppInit(tokenlist, settings)),
VFA(valueFlowGlobalStaticVar(tokenlist, settings)),
VFA(valueFlowPointerAlias(tokenlist, settings)),
VFA(valueFlowLifetime(tokenlist, errorLogger, settings)),
Expand Down
74 changes: 74 additions & 0 deletions test/cli/test-other.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import os
import sys
import pytest
import time

from testutils import cppcheck, assert_cppcheck

Expand Down Expand Up @@ -191,6 +192,79 @@ 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;
""")
t1 = time.time()
cppcheck([filename])
t2 = time.time()
print(t2-t1)


def test_execute_addon_failure(tmpdir):
test_file = os.path.join(tmpdir, 'test.cpp')
with open(test_file, 'wt') as f:
Expand Down

0 comments on commit ce0d2a9

Please sign in to comment.