Skip to content

Commit 00ee32e

Browse files
Allow constants in custom storage layout expression
1 parent 22ae336 commit 00ee32e

File tree

1 file changed

+44
-11
lines changed

1 file changed

+44
-11
lines changed

libsolidity/analysis/PostTypeContractLevelChecker.cpp

+44-11
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
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

Comments
 (0)