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,8 +102,10 @@ 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,
@@ -112,18 +115,48 @@ void PostTypeContractLevelChecker::checkStorageLayoutSpecifier(ContractDefinitio
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
+ if (integerType->isSigned ())
122
+ {
123
+ m_errorReporter.typeError (
124
+ 1481_error,
125
+ baseSlotExpression.location (),
126
+ " The base slot expression must have an unsigned integer type."
127
+ );
128
+ return ;
129
+ }
130
+ std::optional<ConstantEvaluator::TypedRational> typedRational = ConstantEvaluator::evaluate (m_errorReporter, baseSlotExpression);
131
+ if (!typedRational)
132
+ {
133
+ m_errorReporter.typeError (
134
+ 1505_error,
135
+ baseSlotExpression.location (),
136
+ " The base slot expression cannot be evaluated during compilation."
137
+ );
138
+ return ;
139
+ }
140
+ baseSlotRationalValue = typedRational->value ;
141
+ }
142
+ else
143
+ {
144
+ auto const * rationalType = dynamic_cast <RationalNumberType const *>(baseSlotExpressionType);
145
+ solAssert (rationalType);
146
+ if (rationalType->isFractional ())
147
+ {
148
+ m_errorReporter.typeError (
149
+ 1763_error,
150
+ baseSlotExpression.location (),
151
+ " The base slot of the storage layout must evaluate to an integer."
152
+ );
153
+ return ;
154
+ }
155
+ baseSlotRationalValue = rationalType->value ();
123
156
}
124
- solAssert (rationalType->value ().denominator () == 1 );
125
157
126
- bigint baseSlot = rationalType->value ().numerator ();
158
+ solAssert (baseSlotRationalValue.denominator () == 1 );
159
+ bigint baseSlot = baseSlotRationalValue.numerator ();
127
160
if (!(0 <= baseSlot && baseSlot <= std::numeric_limits<u256>::max ()))
128
161
{
129
162
m_errorReporter.typeError (
0 commit comments