Better dynamic constant support in repo mode
A constant defined in a function/method should be treated as dynamic. A class constant with a dynamic initializer should evaluate to the value of its initializer at the time the constant was first seen; so the optimization should be all or nothing - either turn the class constant into a scalar, or leave it in its original form.
Esse commit está contido em:
@@ -144,6 +144,19 @@ ExpressionPtr ClassConstantExpression::preOptimize(AnalysisResultConstPtr ar) {
|
||||
ExpressionPtr value = dynamic_pointer_cast<Expression>(decl);
|
||||
BlockScope::s_constMutex.unlock();
|
||||
|
||||
if (!value->isScalar() &&
|
||||
(value->is(KindOfClassConstantExpression) ||
|
||||
value->is(KindOfConstantExpression))) {
|
||||
std::set<ExpressionPtr> seen;
|
||||
do {
|
||||
if (!seen.insert(value).second) return ExpressionPtr();
|
||||
value = value->preOptimize(ar);
|
||||
if (!value) return ExpressionPtr();
|
||||
} while (!value->isScalar() &&
|
||||
(value->is(KindOfClassConstantExpression) ||
|
||||
value->is(KindOfConstantExpression)));
|
||||
}
|
||||
|
||||
ExpressionPtr rep = Clone(value, getScope());
|
||||
bool annotate = Option::FlAnnotate;
|
||||
Option::FlAnnotate = false; // avoid nested comments on getText
|
||||
|
||||
@@ -332,7 +332,8 @@ void SimpleFunctionCall::analyzeProgram(AnalysisResultPtr ar) {
|
||||
|
||||
// check for dynamic constant and volatile function/class
|
||||
if (!m_class && m_className.empty() &&
|
||||
(m_type == DefinedFunction ||
|
||||
(m_type == DefineFunction ||
|
||||
m_type == DefinedFunction ||
|
||||
m_type == FunctionExistsFunction ||
|
||||
m_type == FBCallUserFuncSafeFunction ||
|
||||
m_type == ClassExistsFunction ||
|
||||
@@ -345,6 +346,28 @@ void SimpleFunctionCall::analyzeProgram(AnalysisResultPtr ar) {
|
||||
if (name && name->isLiteralString()) {
|
||||
string symbol = name->getLiteralString();
|
||||
switch (m_type) {
|
||||
case DefineFunction: {
|
||||
ConstantTableConstPtr constants = ar->getConstants();
|
||||
// system constant
|
||||
if (constants->isPresent(symbol)) {
|
||||
break;
|
||||
}
|
||||
// user constant
|
||||
BlockScopeConstPtr block = ar->findConstantDeclarer(symbol);
|
||||
// not found (i.e., undefined)
|
||||
if (!block) break;
|
||||
constants = block->getConstants();
|
||||
const Symbol *sym = constants->getSymbol(symbol);
|
||||
always_assert(sym);
|
||||
if (!sym->isDynamic()) {
|
||||
if (FunctionScopeRawPtr fsc = getFunctionScope()) {
|
||||
if (!fsc->inPseudoMain()) {
|
||||
const_cast<Symbol*>(sym)->setDynamic();
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DefinedFunction: {
|
||||
ConstantTablePtr constants = ar->getConstants();
|
||||
if (!constants->isPresent(symbol)) {
|
||||
|
||||
Referência em uma Nova Issue
Bloquear um usuário