mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Check availability of data objects already in analysis phase.
This commit is contained in:
parent
f3bdc79187
commit
2a5280faa0
@ -18,6 +18,7 @@ Compiler Features:
|
|||||||
|
|
||||||
Bugfixes:
|
Bugfixes:
|
||||||
* View/Pure Checker: Properly detect state variable access through base class.
|
* View/Pure Checker: Properly detect state variable access through base class.
|
||||||
|
* Yul analyzer: Check availability of data objects already in analysis phase.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -383,11 +383,19 @@ bool AsmAnalyzer::operator()(FunctionCall const& _funCall)
|
|||||||
{
|
{
|
||||||
if (!expectExpression(arg))
|
if (!expectExpression(arg))
|
||||||
success = false;
|
success = false;
|
||||||
else if (needsLiteralArguments && arg.type() != typeid(Literal))
|
else if (needsLiteralArguments)
|
||||||
m_errorReporter.typeError(
|
{
|
||||||
_funCall.functionName.location,
|
if (arg.type() != typeid(Literal))
|
||||||
"Function expects direct literals as arguments."
|
m_errorReporter.typeError(
|
||||||
);
|
_funCall.functionName.location,
|
||||||
|
"Function expects direct literals as arguments."
|
||||||
|
);
|
||||||
|
else if (!m_dataNames.count(boost::get<Literal>(arg).value))
|
||||||
|
m_errorReporter.typeError(
|
||||||
|
_funCall.functionName.location,
|
||||||
|
"Unknown data object \"" + boost::get<Literal>(arg).value.str() + "\"."
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// Use argument size instead of parameter count to avoid misleading errors.
|
// Use argument size instead of parameter count to avoid misleading errors.
|
||||||
m_stackHeight += int(returns) - int(_funCall.arguments.size());
|
m_stackHeight += int(returns) - int(_funCall.arguments.size());
|
||||||
|
@ -61,13 +61,15 @@ public:
|
|||||||
langutil::ErrorReporter& _errorReporter,
|
langutil::ErrorReporter& _errorReporter,
|
||||||
boost::optional<langutil::Error::Type> _errorTypeForLoose,
|
boost::optional<langutil::Error::Type> _errorTypeForLoose,
|
||||||
Dialect const& _dialect,
|
Dialect const& _dialect,
|
||||||
ExternalIdentifierAccess::Resolver const& _resolver = ExternalIdentifierAccess::Resolver()
|
ExternalIdentifierAccess::Resolver const& _resolver = ExternalIdentifierAccess::Resolver(),
|
||||||
|
std::set<YulString> const& _dataNames = {}
|
||||||
):
|
):
|
||||||
m_resolver(_resolver),
|
m_resolver(_resolver),
|
||||||
m_info(_analysisInfo),
|
m_info(_analysisInfo),
|
||||||
m_errorReporter(_errorReporter),
|
m_errorReporter(_errorReporter),
|
||||||
m_dialect(_dialect),
|
m_dialect(_dialect),
|
||||||
m_errorTypeForLoose(_errorTypeForLoose)
|
m_errorTypeForLoose(_errorTypeForLoose),
|
||||||
|
m_dataNames(_dataNames)
|
||||||
{
|
{
|
||||||
if (EVMDialect const* evmDialect = dynamic_cast<EVMDialect const*>(&m_dialect))
|
if (EVMDialect const* evmDialect = dynamic_cast<EVMDialect const*>(&m_dialect))
|
||||||
m_evmVersion = evmDialect->evmVersion();
|
m_evmVersion = evmDialect->evmVersion();
|
||||||
@ -124,6 +126,8 @@ private:
|
|||||||
langutil::EVMVersion m_evmVersion;
|
langutil::EVMVersion m_evmVersion;
|
||||||
Dialect const& m_dialect;
|
Dialect const& m_dialect;
|
||||||
boost::optional<langutil::Error::Type> m_errorTypeForLoose;
|
boost::optional<langutil::Error::Type> m_errorTypeForLoose;
|
||||||
|
/// Names of data objects to be referenced by builtin functions with literal arguments.
|
||||||
|
std::set<YulString> m_dataNames;
|
||||||
ForLoop const* m_currentForLoop = nullptr;
|
ForLoop const* m_currentForLoop = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -113,7 +113,20 @@ bool AssemblyStack::analyzeParsed(Object& _object)
|
|||||||
{
|
{
|
||||||
solAssert(_object.code, "");
|
solAssert(_object.code, "");
|
||||||
_object.analysisInfo = make_shared<AsmAnalysisInfo>();
|
_object.analysisInfo = make_shared<AsmAnalysisInfo>();
|
||||||
AsmAnalyzer analyzer(*_object.analysisInfo, m_errorReporter, boost::none, languageToDialect(m_language, m_evmVersion));
|
|
||||||
|
set<YulString> objectNames;
|
||||||
|
objectNames.insert(_object.name);
|
||||||
|
for (auto const& subObject: _object.subIndexByName)
|
||||||
|
objectNames.insert(subObject.first);
|
||||||
|
|
||||||
|
AsmAnalyzer analyzer(
|
||||||
|
*_object.analysisInfo,
|
||||||
|
m_errorReporter,
|
||||||
|
boost::none,
|
||||||
|
languageToDialect(m_language, m_evmVersion),
|
||||||
|
{},
|
||||||
|
objectNames
|
||||||
|
);
|
||||||
bool success = analyzer.analyze(*_object.code);
|
bool success = analyzer.analyze(*_object.code);
|
||||||
for (auto& subNode: _object.subObjects)
|
for (auto& subNode: _object.subObjects)
|
||||||
if (auto subObject = dynamic_cast<Object*>(subNode.get()))
|
if (auto subObject = dynamic_cast<Object*>(subNode.get()))
|
||||||
|
@ -278,6 +278,19 @@ BOOST_AUTO_TEST_CASE(args_to_datacopy_are_arbitrary)
|
|||||||
BOOST_CHECK(successParse(code));
|
BOOST_CHECK(successParse(code));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(non_existing_objects)
|
||||||
|
{
|
||||||
|
BOOST_CHECK(successParse(
|
||||||
|
"object \"main\" { code { pop(datasize(\"main\")) } }"
|
||||||
|
));
|
||||||
|
CHECK_ERROR(
|
||||||
|
"object \"main\" { code { pop(datasize(\"abc\")) } }",
|
||||||
|
TypeError,
|
||||||
|
"Unknown data object"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_SUITE_END()
|
BOOST_AUTO_TEST_SUITE_END()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,15 +1,18 @@
|
|||||||
{
|
object "main" {
|
||||||
// Arguments to ``datasize`` and ``dataoffset`` need to be
|
code {
|
||||||
// literals. We cannot simplify their arguments, but we can
|
// Arguments to ``datasize`` and ``dataoffset`` need to be
|
||||||
// simplify them as a full expression.
|
// literals. We cannot simplify their arguments, but we can
|
||||||
// ``datacopy`` does not have this restriction.
|
// simplify them as a full expression.
|
||||||
let r := "abc"
|
// ``datacopy`` does not have this restriction.
|
||||||
let a := datasize("abc")
|
let r := "abc"
|
||||||
let x := dataoffset("abc")
|
let a := datasize("abc")
|
||||||
// should be replaced by a
|
let x := dataoffset("abc")
|
||||||
let y := datasize("abc")
|
// should be replaced by a
|
||||||
datacopy("abc", x, y)
|
let y := datasize("abc")
|
||||||
mstore(a, x)
|
datacopy("abc", x, y)
|
||||||
|
mstore(a, x)
|
||||||
|
}
|
||||||
|
data "abc" "Hello, World!"
|
||||||
}
|
}
|
||||||
// ====
|
// ====
|
||||||
// step: commonSubexpressionEliminator
|
// step: commonSubexpressionEliminator
|
||||||
|
@ -1,10 +1,13 @@
|
|||||||
{
|
object "main" {
|
||||||
// We should never split arguments to ``dataoffset``
|
code {
|
||||||
// or ``datasize`` because they need to be literals
|
// We should never split arguments to ``dataoffset``
|
||||||
let x := dataoffset("abc")
|
// or ``datasize`` because they need to be literals
|
||||||
let y := datasize("abc")
|
let x := dataoffset("abc")
|
||||||
// datacopy is fine, though
|
let y := datasize("abc")
|
||||||
datacopy(mload(0), mload(1), mload(2))
|
// datacopy is fine, though
|
||||||
|
datacopy(mload(0), mload(1), mload(2))
|
||||||
|
}
|
||||||
|
data "abc" "Hello, World!"
|
||||||
}
|
}
|
||||||
// ====
|
// ====
|
||||||
// step: expressionSplitter
|
// step: expressionSplitter
|
||||||
|
Loading…
Reference in New Issue
Block a user