Fix #12182 (speedup valueFlow by only running valueFlowNumber once) (#5678)

This commit is contained in:
Daniel Marjamäki 2023-11-19 18:56:48 +01:00 committed by GitHub
parent 61bd8fddbf
commit 56c7ac3771
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 85 additions and 9 deletions

View File

@ -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) { else if (Token::Match(parent, ":: %name%") && parent->astOperand2() == tok) {
setTokenValue(parent, value, settings); setTokenValue(parent, value, settings);
} }
@ -1335,16 +1345,12 @@ static Token * valueFlowSetConstantValue(Token *tok, const Settings *settings, b
if (!tok->isTemplateArg()) if (!tok->isTemplateArg())
value.setKnown(); value.setKnown();
setTokenValue(tok->next(), std::move(value), settings); setTokenValue(tok->next(), std::move(value), settings);
} else if (Token::Match(tok, "%name% = {") && tok->variable() && } else if (Token::simpleMatch(tok, "= { } ;")) {
(tok->variable()->isPointer() || (tok->variable()->valueType() && tok->variable()->valueType()->isIntegral()))) { const Token* lhs = tok->astOperand1();
if (Token::simpleMatch(tok->tokAt(3), "}")) { if (lhs && lhs->valueType() && (lhs->valueType()->isIntegral() || lhs->valueType()->pointer > 0)) {
ValueFlow::Value value(0); ValueFlow::Value value(0);
value.setKnown(); value.setKnown();
setTokenValue(tok->tokAt(2), std::move(value), settings); setTokenValue(tok->next(), 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);
} }
} }
return tok->next(); return tok->next();
@ -9448,7 +9454,6 @@ void ValueFlow::setValues(TokenList& tokenlist,
VFA(valueFlowUnknownFunctionReturn(tokenlist, settings)), VFA(valueFlowUnknownFunctionReturn(tokenlist, settings)),
VFA(valueFlowGlobalConstVar(tokenlist, settings)), VFA(valueFlowGlobalConstVar(tokenlist, settings)),
VFA(valueFlowEnumValue(symboldatabase, settings)), VFA(valueFlowEnumValue(symboldatabase, settings)),
VFA(valueFlowNumber(tokenlist, settings)),
VFA(valueFlowGlobalStaticVar(tokenlist, settings)), VFA(valueFlowGlobalStaticVar(tokenlist, settings)),
VFA(valueFlowPointerAlias(tokenlist, settings)), VFA(valueFlowPointerAlias(tokenlist, settings)),
VFA(valueFlowLifetime(tokenlist, errorLogger, settings)), VFA(valueFlowLifetime(tokenlist, errorLogger, settings)),

View File

@ -191,6 +191,77 @@ def test_slow_long_line(tmpdir):
cppcheck([filename]) # should not take more than ~1 second 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): def test_execute_addon_failure(tmpdir):
test_file = os.path.join(tmpdir, 'test.cpp') test_file = os.path.join(tmpdir, 'test.cpp')
with open(test_file, 'wt') as f: with open(test_file, 'wt') as f: