Skip to content

Constant evaluator support for member constants #16056

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ Language Features:


Compiler Features:
* Constant Evaluator: Support for constants referenced by member access expressions.


Bugfixes:
Expand Down
23 changes: 23 additions & 0 deletions libsolidity/analysis/ConstantEvaluator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@
#include <libsolidity/ast/TypeProvider.h>
#include <liblangutil/ErrorReporter.h>

#include <range/v3/algorithm/find_if.hpp>

#include <limits>

using namespace solidity;
Expand Down Expand Up @@ -407,3 +409,24 @@ void ConstantEvaluator::endVisit(TupleExpression const& _tuple)
if (!_tuple.isInlineArray() && _tuple.components().size() == 1)
m_values[&_tuple] = evaluate(*_tuple.components().front());
}

void ConstantEvaluator::endVisit(MemberAccess const& _memberAccess)
{
if (auto const* parentIdentifier = dynamic_cast<Identifier const*>(&_memberAccess.expression()))
{
if (auto const* contract = dynamic_cast<ContractDefinition const*>(parentIdentifier->annotation().referencedDeclaration))
{
auto contractVariables = contract->stateVariables();
auto variable = ranges::find_if(
contractVariables,
[&](VariableDeclaration const* _variable) { return _variable->name() == _memberAccess.memberName(); }
);

if (
variable != ranges::end(contractVariables) &&
(*variable)->isConstant()
)
m_values[&_memberAccess] = evaluate(**variable);
}
}
}
1 change: 1 addition & 0 deletions libsolidity/analysis/ConstantEvaluator.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ class ConstantEvaluator: private ASTConstVisitor
void endVisit(Literal const& _literal) override;
void endVisit(Identifier const& _identifier) override;
void endVisit(TupleExpression const& _tuple) override;
void endVisit(MemberAccess const& _memberAcess) override;

langutil::ErrorReporter& m_errorReporter;
/// Current recursion depth.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
contract A {
uint constant INHERITED = 42;
}

contract C is A {
uint constant CONST = 64;
uint[A.INHERITED] x;
uint[C.CONST] y;
}
// ----
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
contract A {
uint constant INHERITED = 1;
}
contract C is A {
uint constant CONST = 2 + A.INHERITED;
uint[CONST] array;
}
// ----
Original file line number Diff line number Diff line change
Expand Up @@ -7,23 +7,20 @@ library L1 {
contract C1 {
uint256 internal constant CONST1 = L1.INT;

uint256[L1.INT] internal arr1; // error, backward reference
uint256[L1.INT] internal arr1;
uint256[L2.INT] internal arr2; // error, forward reference
}

contract C2 is C1 {
uint256 internal constant CONST2 = CONST1;

uint256[CONST1] internal arr3; // error, inherited constants
uint256[CONST2] internal arr4; // error, same contract constant
uint256[CONST1] internal arr3;
uint256[CONST2] internal arr4;
}

library L2 {
uint256 internal constant INT = 100;
}

// ----
// TypeError 5462: (158-164): Invalid array length, expected integer literal or constant expression.
// TypeError 5462: (222-228): Invalid array length, expected integer literal or constant expression.
// TypeError 5462: (356-362): Invalid array length, expected integer literal or constant expression.
// TypeError 5462: (421-427): Invalid array length, expected integer literal or constant expression.
// TypeError 5462: (193-199): Invalid array length, expected integer literal or constant expression.
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,14 @@ library L1 {
}

contract C1 {
uint256 internal constant CONST = 20 + L2.INT; // forward reference
uint256 internal constant CONST = 30 + L1.INT; // backward reference
uint256 internal constant CONST2 = 30 + L2.INT; // forward reference
uint256 internal constant LIMIT = MAX * L1.INT; // same file & external library constant
uint256 internal constant NESTED = LIMIT + CONST; // nested & same contract constant

uint256[L1.INT] internal arr1; // error, backward reference
uint256[L1.INT] internal arr1; // ok, backward reference
uint256[L2.INT] internal arr2; // error, forward reference
uint256[CONST2] internal arr3; // error, computed with forward reference
}

contract C2 is C1 {
Expand All @@ -20,16 +22,14 @@ contract C2 is C1 {
contract C3 is C2 {
uint256 internal constant NESTED_INHERITED = INHERITED + NESTED + CONST * LIMIT; // nest-inherited constants

uint256[CONST] internal arr3; // error, nest-inherited constants
uint256[NESTED_INHERITED] internal arr4; // error, same contract constant
uint256[CONST] internal arr4; // nest-inherited constants
uint256[NESTED_INHERITED] internal arr5; // same contract constant
}

library L2 {
uint256 internal constant INT = 100;
}

// ----
// TypeError 5462: (366-372): Invalid array length, expected integer literal or constant expression.
// TypeError 5462: (430-436): Invalid array length, expected integer literal or constant expression.
// TypeError 5462: (742-747): Invalid array length, expected integer literal or constant expression.
// TypeError 5462: (822-838): Invalid array length, expected integer literal or constant expression.
// TypeError 5462: (501-507): Invalid array length, expected integer literal or constant expression.
// TypeError 5462: (564-570): Invalid array length, expected integer literal or constant expression.