2323#include < libsolidity/analysis/PostTypeContractLevelChecker.h>
2424
2525#include < fmt/format.h>
26+ #include < libsolidity/analysis/ConstantEvaluator.h>
2627#include < libsolidity/ast/AST.h>
2728#include < libsolidity/ast/ASTUtils.h>
2829#include < libsolidity/ast/TypeProvider.h>
@@ -101,8 +102,10 @@ void PostTypeContractLevelChecker::checkStorageLayoutSpecifier(ContractDefinitio
101102 }
102103
103104 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+ )
106109 {
107110 m_errorReporter.typeError (
108111 6396_error,
@@ -112,18 +115,48 @@ void PostTypeContractLevelChecker::checkStorageLayoutSpecifier(ContractDefinitio
112115 return ;
113116 }
114117
115- if (rationalType->isFractional ())
118+ rational baseSlotRationalValue;
119+ if (auto const integerType = dynamic_cast <IntegerType const *>(baseSlotExpressionType))
116120 {
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 ();
123156 }
124- solAssert (rationalType->value ().denominator () == 1 );
125157
126- bigint baseSlot = rationalType->value ().numerator ();
158+ solAssert (baseSlotRationalValue.denominator () == 1 );
159+ bigint baseSlot = baseSlotRationalValue.numerator ();
127160 if (!(0 <= baseSlot && baseSlot <= std::numeric_limits<u256>::max ()))
128161 {
129162 m_errorReporter.typeError (
0 commit comments