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,39 @@ 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+ 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 cannot be evaluated during compilation."
128+ );
129+ return ;
130+ }
131+ baseSlotRationalValue = typedRational->value ;
132+ }
133+ else
134+ {
135+ auto const * rationalType = dynamic_cast <RationalNumberType const *>(baseSlotExpressionType);
136+ solAssert (rationalType);
137+ if (rationalType->isFractional ())
138+ {
139+ m_errorReporter.typeError (
140+ 1763_error,
141+ baseSlotExpression.location (),
142+ " The base slot of the storage layout must evaluate to an integer."
143+ );
144+ return ;
145+ }
146+ baseSlotRationalValue = rationalType->value ();
123147 }
124- solAssert (rationalType->value ().denominator () == 1 );
125148
126- bigint baseSlot = rationalType->value ().numerator ();
149+ solAssert (baseSlotRationalValue.denominator () == 1 );
150+ bigint baseSlot = baseSlotRationalValue.numerator ();
127151 if (!(0 <= baseSlot && baseSlot <= std::numeric_limits<u256>::max ()))
128152 {
129153 m_errorReporter.typeError (
0 commit comments