|
23 | 23 | #include <libsolidity/analysis/PostTypeContractLevelChecker.h>
|
24 | 24 |
|
25 | 25 | #include <fmt/format.h>
|
| 26 | +#include <libsolidity/analysis/ConstantEvaluator.h> |
26 | 27 | #include <libsolidity/ast/AST.h>
|
27 | 28 | #include <libsolidity/ast/ASTUtils.h>
|
28 | 29 | #include <libsolidity/ast/TypeProvider.h>
|
@@ -101,29 +102,53 @@ void PostTypeContractLevelChecker::checkStorageLayoutSpecifier(ContractDefinitio
|
101 | 102 | }
|
102 | 103 |
|
103 | 104 | auto const* baseSlotExpressionType = type(baseSlotExpression);
|
104 |
| - auto const* rationalType = dynamic_cast<RationalNumberType const*>(baseSlotExpressionType); |
105 |
| - if (!rationalType) |
| 105 | + if ( |
| 106 | + !dynamic_cast<IntegerType const*>(baseSlotExpressionType) && |
| 107 | + !dynamic_cast<RationalNumberType const*>(baseSlotExpressionType) |
| 108 | + ) |
106 | 109 | {
|
107 | 110 | m_errorReporter.typeError(
|
108 | 111 | 6396_error,
|
109 | 112 | baseSlotExpression.location(),
|
110 |
| - "The base slot of the storage layout must evaluate to a rational number." |
| 113 | + "The base slot of the storage layout must evaluate to an integer number." |
111 | 114 | );
|
112 | 115 | return;
|
113 | 116 | }
|
114 | 117 |
|
115 |
| - if (rationalType->isFractional()) |
| 118 | + rational baseSlotRationalValue; |
| 119 | + if (auto const integerType = dynamic_cast<IntegerType const*>(baseSlotExpressionType)) |
116 | 120 | {
|
117 |
| - m_errorReporter.typeError( |
118 |
| - 1763_error, |
119 |
| - baseSlotExpression.location(), |
120 |
| - "The base slot of the storage layout must evaluate to an integer." |
121 |
| - ); |
122 |
| - return; |
| 121 | + std::optional<ConstantEvaluator::TypedRational> typedRational = ConstantEvaluator::evaluate(m_errorReporter, baseSlotExpression); |
| 122 | + if (!typedRational) |
| 123 | + { |
| 124 | + m_errorReporter.typeError( |
| 125 | + 1505_error, |
| 126 | + baseSlotExpression.location(), |
| 127 | + "The base slot expression contains elements that are not yet supported " |
| 128 | + "by the internal constant evaluator and therefore cannot be evaluated at compilation time." |
| 129 | + ); |
| 130 | + return; |
| 131 | + } |
| 132 | + baseSlotRationalValue = typedRational->value; |
| 133 | + } |
| 134 | + else |
| 135 | + { |
| 136 | + auto const* rationalType = dynamic_cast<RationalNumberType const*>(baseSlotExpressionType); |
| 137 | + solAssert(rationalType); |
| 138 | + if (rationalType->isFractional()) |
| 139 | + { |
| 140 | + m_errorReporter.typeError( |
| 141 | + 1763_error, |
| 142 | + baseSlotExpression.location(), |
| 143 | + "The base slot of the storage layout must evaluate to an integer." |
| 144 | + ); |
| 145 | + return; |
| 146 | + } |
| 147 | + baseSlotRationalValue = rationalType->value(); |
123 | 148 | }
|
124 |
| - solAssert(rationalType->value().denominator() == 1); |
125 | 149 |
|
126 |
| - bigint baseSlot = rationalType->value().numerator(); |
| 150 | + solAssert(baseSlotRationalValue.denominator() == 1); |
| 151 | + bigint baseSlot = baseSlotRationalValue.numerator(); |
127 | 152 | if (!(0 <= baseSlot && baseSlot <= std::numeric_limits<u256>::max()))
|
128 | 153 | {
|
129 | 154 | m_errorReporter.typeError(
|
|
0 commit comments