From 9cf0342f9d2df389a4c2c74272bb2e04448f6eab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20St=C3=B6neberg?= Date: Thu, 16 Nov 2023 14:35:25 +0100 Subject: [PATCH] optimized `ProgramMemory` a bit (#5668) Scanning `common/file.c` of the `xrdp` project with `--force --std=c11 --std=c++11 --inline-suppr --enable=warning`: Clang 16 `4,208,373,435` -> `4,156,024,955` GCC 13 `4,336,042,153` -> `4,277,293,971` --- lib/programmemory.cpp | 65 +++++++++++++++++++++---------------------- lib/vfvalue.cpp | 6 ---- lib/vfvalue.h | 6 +++- 3 files changed, 37 insertions(+), 40 deletions(-) diff --git a/lib/programmemory.cpp b/lib/programmemory.cpp index 72519c164..cdca90e67 100644 --- a/lib/programmemory.cpp +++ b/lib/programmemory.cpp @@ -1206,10 +1206,9 @@ struct Executor { ValueFlow::Value executeImpl(const Token* expr) { - ValueFlow::Value unknown = ValueFlow::Value::unknown(); const ValueFlow::Value* value = nullptr; if (!expr) - return unknown; + return ValueFlow::Value::unknown(); if (expr->hasKnownIntValue() && !expr->isAssignmentOp() && expr->str() != ",") return expr->values().front(); if ((value = expr->getKnownValue(ValueFlow::Value::ValueType::FLOAT)) || @@ -1221,10 +1220,10 @@ struct Executor { } if (expr->isNumber()) { if (MathLib::isFloat(expr->str())) - return unknown; + return ValueFlow::Value::unknown(); MathLib::bigint i = MathLib::toBigNumber(expr->str()); if (i < 0 && astIsUnsigned(expr)) - return unknown; + return ValueFlow::Value::unknown(); return ValueFlow::Value{i}; } if (expr->isBoolean()) @@ -1235,14 +1234,14 @@ struct Executor { if (yield == Library::Container::Yield::SIZE) { ValueFlow::Value v = execute(containerTok); if (!v.isContainerSizeValue()) - return unknown; + return ValueFlow::Value::unknown(); v.valueType = ValueFlow::Value::ValueType::INT; return v; } if (yield == Library::Container::Yield::EMPTY) { ValueFlow::Value v = execute(containerTok); if (!v.isContainerSizeValue()) - return unknown; + return ValueFlow::Value::unknown(); if (v.isImpossible() && v.intvalue == 0) return ValueFlow::Value{0}; if (!v.isImpossible()) @@ -1252,10 +1251,10 @@ struct Executor { expr->astOperand1()->exprId() > 0) { ValueFlow::Value rhs = execute(expr->astOperand2()); if (rhs.isUninitValue()) - return unknown; + return ValueFlow::Value::unknown(); if (expr->str() != "=") { if (!pm->hasValue(expr->astOperand1()->exprId())) - return unknown; + return ValueFlow::Value::unknown(); ValueFlow::Value& lhs = pm->at(expr->astOperand1()->exprId()); rhs = evaluate(removeAssign(expr->str()), lhs, rhs); if (lhs.isIntValue()) @@ -1264,7 +1263,7 @@ struct Executor { ValueFlow::Value::visitValue(rhs, std::bind(assign{}, std::ref(lhs.floatValue), std::placeholders::_1)); else - return unknown; + return ValueFlow::Value::unknown(); return lhs; } pm->setValue(expr->astOperand1(), rhs); @@ -1272,33 +1271,33 @@ struct Executor { } else if (expr->str() == "&&" && expr->astOperand1() && expr->astOperand2()) { ValueFlow::Value lhs = execute(expr->astOperand1()); if (!lhs.isIntValue()) - return unknown; + return ValueFlow::Value::unknown(); if (isFalse(lhs)) return lhs; if (isTrue(lhs)) return execute(expr->astOperand2()); - return unknown; + return ValueFlow::Value::unknown(); } else if (expr->str() == "||" && expr->astOperand1() && expr->astOperand2()) { ValueFlow::Value lhs = execute(expr->astOperand1()); if (!lhs.isIntValue() || lhs.isImpossible()) - return unknown; + return ValueFlow::Value::unknown(); if (isTrue(lhs)) return lhs; if (isFalse(lhs)) return execute(expr->astOperand2()); - return unknown; + return ValueFlow::Value::unknown(); } else if (expr->str() == "," && expr->astOperand1() && expr->astOperand2()) { execute(expr->astOperand1()); return execute(expr->astOperand2()); } else if (expr->tokType() == Token::eIncDecOp && expr->astOperand1() && expr->astOperand1()->exprId() != 0) { if (!pm->hasValue(expr->astOperand1()->exprId())) - return unknown; + return ValueFlow::Value::unknown(); ValueFlow::Value& lhs = pm->at(expr->astOperand1()->exprId()); if (!lhs.isIntValue()) - return unknown; + return ValueFlow::Value::unknown(); // overflow if (!lhs.isImpossible() && lhs.intvalue == 0 && expr->str() == "--" && astIsUnsigned(expr->astOperand1())) - return unknown; + return ValueFlow::Value::unknown(); if (expr->str() == "++") lhs.intvalue++; @@ -1312,17 +1311,17 @@ struct Executor { expr->astOperand1()->values().cend(), std::mem_fn(&ValueFlow::Value::isTokValue)); if (tokvalue_it == expr->astOperand1()->values().cend() || !tokvalue_it->isKnown()) { - return unknown; + return ValueFlow::Value::unknown(); } tokvalue = tokvalue_it->tokvalue; } if (!tokvalue || !tokvalue->isLiteral()) { - return unknown; + return ValueFlow::Value::unknown(); } const std::string strValue = tokvalue->strValue(); ValueFlow::Value rhs = execute(expr->astOperand2()); if (!rhs.isIntValue()) - return unknown; + return ValueFlow::Value::unknown(); const MathLib::bigint index = rhs.intvalue; if (index >= 0 && index < strValue.size()) return ValueFlow::Value{strValue[index]}; @@ -1331,23 +1330,23 @@ struct Executor { } else if (Token::Match(expr, "%cop%") && expr->astOperand1() && expr->astOperand2()) { ValueFlow::Value lhs = execute(expr->astOperand1()); ValueFlow::Value rhs = execute(expr->astOperand2()); - ValueFlow::Value r = unknown; + ValueFlow::Value r = ValueFlow::Value::unknown(); if (!lhs.isUninitValue() && !rhs.isUninitValue()) r = evaluate(expr->str(), lhs, rhs); if (expr->isComparisonOp() && (r.isUninitValue() || r.isImpossible())) { if (rhs.isIntValue()) { std::vector result = - infer(ValueFlow::makeIntegralInferModel(), expr->str(), expr->astOperand1()->values(), {rhs}); + infer(ValueFlow::makeIntegralInferModel(), expr->str(), expr->astOperand1()->values(), {std::move(rhs)}); if (!result.empty() && result.front().isKnown()) return result.front(); } if (lhs.isIntValue()) { std::vector result = - infer(ValueFlow::makeIntegralInferModel(), expr->str(), {lhs}, expr->astOperand2()->values()); + infer(ValueFlow::makeIntegralInferModel(), expr->str(), {std::move(lhs)}, expr->astOperand2()->values()); if (!result.empty() && result.front().isKnown()) return result.front(); } - return unknown; + return ValueFlow::Value::unknown(); } return r; } @@ -1355,14 +1354,14 @@ struct Executor { else if (Token::Match(expr, "!|+|-") && expr->astOperand1() && !expr->astOperand2()) { ValueFlow::Value lhs = execute(expr->astOperand1()); if (!lhs.isIntValue()) - return unknown; + return ValueFlow::Value::unknown(); if (expr->str() == "!") { if (isTrue(lhs)) { lhs.intvalue = 0; } else if (isFalse(lhs)) { lhs.intvalue = 1; } else { - return unknown; + return ValueFlow::Value::unknown(); } lhs.setPossible(); lhs.bound = ValueFlow::Value::Bound::Point; @@ -1373,14 +1372,14 @@ struct Executor { } else if (expr->str() == "?" && expr->astOperand1() && expr->astOperand2()) { ValueFlow::Value cond = execute(expr->astOperand1()); if (!cond.isIntValue()) - return unknown; + return ValueFlow::Value::unknown(); const Token* child = expr->astOperand2(); if (isFalse(cond)) return execute(child->astOperand2()); if (isTrue(cond)) return execute(child->astOperand1()); - return unknown; + return ValueFlow::Value::unknown(); } else if (expr->str() == "(" && expr->isCast()) { if (Token::simpleMatch(expr->previous(), ">") && expr->previous()->link()) return execute(expr->astOperand2()); @@ -1398,7 +1397,7 @@ struct Executor { if (Token::Match(expr->previous(), ">|%name% {|(")) { const Token* ftok = expr->previous(); const Function* f = ftok->function(); - ValueFlow::Value result = unknown; + ValueFlow::Value result = ValueFlow::Value::unknown(); if (settings && expr->str() == "(") { std::vector tokArgs = getArguments(expr); std::vector args(tokArgs.size()); @@ -1411,7 +1410,7 @@ struct Executor { for (std::size_t i = 0; i < args.size(); ++i) { const Variable* const arg = f->getArgumentVar(i); if (!arg) - return unknown; + return ValueFlow::Value::unknown(); functionState.setValue(arg->nameToken(), args[i]); } Executor ex = *this; @@ -1419,7 +1418,7 @@ struct Executor { ex.fdepth--; auto r = ex.execute(f->functionScope); if (!r.empty()) - result = r.front(); + result = std::move(r.front()); // TODO: Track values changed by reference } } else { @@ -1445,10 +1444,10 @@ struct Executor { ValueFlow::Value& v = pm->at(child->exprId()); if (v.valueType == ValueFlow::Value::ValueType::CONTAINER_SIZE) { if (ValueFlow::isContainerSizeChanged(child, v.indirect, settings)) - v = unknown; + v = ValueFlow::Value::unknown(); } else if (v.valueType != ValueFlow::Value::ValueType::UNINIT) { if (isVariableChanged(child, v.indirect, settings, true)) - v = unknown; + v = ValueFlow::Value::unknown(); } } return ChildrenToVisit::op1_and_op2; @@ -1456,7 +1455,7 @@ struct Executor { return result; } - return unknown; + return ValueFlow::Value::unknown(); } static const ValueFlow::Value* getImpossibleValue(const Token* tok) { diff --git a/lib/vfvalue.cpp b/lib/vfvalue.cpp index c99a76dd3..b07a2c573 100644 --- a/lib/vfvalue.cpp +++ b/lib/vfvalue.cpp @@ -190,10 +190,4 @@ namespace ValueFlow { } return ""; } - - Value Value::unknown() { - Value v; - v.valueType = ValueType::UNINIT; - return v; - } } diff --git a/lib/vfvalue.h b/lib/vfvalue.h index 7f7089845..b3a7598cb 100644 --- a/lib/vfvalue.h +++ b/lib/vfvalue.h @@ -51,7 +51,11 @@ namespace ValueFlow {} Value(const Token* c, long long val, Bound b = Bound::Point); - static Value unknown(); + static Value unknown() { + Value v; + v.valueType = ValueType::UNINIT; + return v; + } bool equalValue(const ValueFlow::Value& rhs) const { if (valueType != rhs.valueType)