diff --git a/Changelog.md b/Changelog.md index 967e548814ef..3794ec666a71 100644 --- a/Changelog.md +++ b/Changelog.md @@ -4,6 +4,7 @@ Language Features: Compiler Features: +* Constant Evaluator: Support for constants referenced by member access expressions. Bugfixes: diff --git a/libsolidity/analysis/ConstantEvaluator.cpp b/libsolidity/analysis/ConstantEvaluator.cpp index 0d953be93ff4..bd6bb4e59561 100644 --- a/libsolidity/analysis/ConstantEvaluator.cpp +++ b/libsolidity/analysis/ConstantEvaluator.cpp @@ -27,6 +27,8 @@ #include #include +#include + #include using namespace solidity; @@ -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(&_memberAccess.expression())) + { + if (auto const* contract = dynamic_cast(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); + } + } +} diff --git a/libsolidity/analysis/ConstantEvaluator.h b/libsolidity/analysis/ConstantEvaluator.h index 297d5f6e80c9..78a9a30f9fa2 100644 --- a/libsolidity/analysis/ConstantEvaluator.h +++ b/libsolidity/analysis/ConstantEvaluator.h @@ -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. diff --git a/test/libsolidity/syntaxTests/array/length/constant_member_access.sol b/test/libsolidity/syntaxTests/array/length/constant_member_access.sol new file mode 100644 index 000000000000..d6343b8c07b1 --- /dev/null +++ b/test/libsolidity/syntaxTests/array/length/constant_member_access.sol @@ -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; +} +// ---- diff --git a/test/libsolidity/syntaxTests/constantEvaluator/member_access.sol b/test/libsolidity/syntaxTests/constantEvaluator/member_access.sol new file mode 100644 index 000000000000..e75ea651569b --- /dev/null +++ b/test/libsolidity/syntaxTests/constantEvaluator/member_access.sol @@ -0,0 +1,8 @@ +contract A { + uint constant INHERITED = 1; +} +contract C is A { + uint constant CONST = 2 + A.INHERITED; + uint[CONST] array; +} +// ---- diff --git a/test/libsolidity/syntaxTests/constants/constant_variables_as_static_array_length.sol b/test/libsolidity/syntaxTests/constants/constant_variables_as_static_array_length.sol index 19e8bfee2108..5eb9ac7ce402 100644 --- a/test/libsolidity/syntaxTests/constants/constant_variables_as_static_array_length.sol +++ b/test/libsolidity/syntaxTests/constants/constant_variables_as_static_array_length.sol @@ -7,15 +7,15 @@ 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 { @@ -23,7 +23,4 @@ library L2 { } // ---- -// 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. diff --git a/test/libsolidity/syntaxTests/constants/constant_with_dependencies_as_array_sizes.sol b/test/libsolidity/syntaxTests/constants/constant_with_dependencies_as_array_sizes.sol index a2a1ce20ee15..c17df7842579 100644 --- a/test/libsolidity/syntaxTests/constants/constant_with_dependencies_as_array_sizes.sol +++ b/test/libsolidity/syntaxTests/constants/constant_with_dependencies_as_array_sizes.sol @@ -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 { @@ -20,8 +22,8 @@ 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 { @@ -29,7 +31,5 @@ library L2 { } // ---- -// 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.