mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge pull request #12016 from ethereum/external-fp-10358
Add ``.address`` and ``.selector`` in inside assembly for external function pointers
This commit is contained in:
@@ -219,13 +219,15 @@ void ReferencesResolver::operator()(yul::Identifier const& _identifier)
|
||||
{
|
||||
solAssert(nativeLocationOf(_identifier) == originLocationOf(_identifier), "");
|
||||
|
||||
static set<string> suffixes{"slot", "offset", "length"};
|
||||
static set<string> suffixes{"slot", "offset", "length", "address", "selector"};
|
||||
string suffix;
|
||||
for (string const& s: suffixes)
|
||||
if (boost::algorithm::ends_with(_identifier.name.str(), "." + s))
|
||||
suffix = s;
|
||||
|
||||
// Could also use `pathFromCurrentScope`, split by '.'
|
||||
// Could also use `pathFromCurrentScope`, split by '.'.
|
||||
// If we do that, suffix should only be set for when it has a special
|
||||
// meaning, not for normal identifierPaths.
|
||||
auto declarations = m_resolver.nameFromCurrentScope(_identifier.name.str());
|
||||
if (!suffix.empty())
|
||||
{
|
||||
|
||||
@@ -828,7 +828,7 @@ bool TypeChecker::visit(InlineAssembly const& _inlineAssembly)
|
||||
if (!identifierInfo.suffix.empty())
|
||||
{
|
||||
string const& suffix = identifierInfo.suffix;
|
||||
solAssert((set<string>{"offset", "slot", "length"}).count(suffix), "");
|
||||
solAssert((set<string>{"offset", "slot", "length", "selector", "address"}).count(suffix), "");
|
||||
if (!var->isConstant() && (var->isStateVariable() || var->type()->dataStoredIn(DataLocation::Storage)))
|
||||
{
|
||||
if (suffix != "slot" && suffix != "offset")
|
||||
@@ -861,6 +861,19 @@ bool TypeChecker::visit(InlineAssembly const& _inlineAssembly)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (auto const* fpType = dynamic_cast<FunctionTypePointer>(var->type()))
|
||||
{
|
||||
if (suffix != "selector" && suffix != "address")
|
||||
{
|
||||
m_errorReporter.typeError(9272_error, nativeLocationOf(_identifier), "Variables of type function pointer only support \".selector\" and \".address\".");
|
||||
return false;
|
||||
}
|
||||
if (fpType->kind() != FunctionType::Kind::External)
|
||||
{
|
||||
m_errorReporter.typeError(8533_error, nativeLocationOf(_identifier), "Only Variables of type external function pointer support \".selector\" and \".address\".");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_errorReporter.typeError(3622_error, nativeLocationOf(_identifier), "The suffix \"." + suffix + "\" is not supported by this variable or type.");
|
||||
|
||||
@@ -211,7 +211,7 @@ struct InlineAssemblyAnnotation: StatementAnnotation
|
||||
struct ExternalIdentifierInfo
|
||||
{
|
||||
Declaration const* declaration = nullptr;
|
||||
/// Suffix used, one of "slot", "offset", "length" or empty.
|
||||
/// Suffix used, one of "slot", "offset", "length", "address", "selector" or empty.
|
||||
std::string suffix;
|
||||
size_t valueSize = size_t(-1);
|
||||
};
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
|
||||
#include <libsolutil/JSON.h>
|
||||
#include <libsolutil/UTF8.h>
|
||||
#include <libsolutil/CommonData.h>
|
||||
|
||||
#include <boost/algorithm/string/join.hpp>
|
||||
|
||||
@@ -178,9 +179,12 @@ Json::Value ASTJsonConverter::inlineAssemblyIdentifierToJson(pair<yul::Identifie
|
||||
tuple["declaration"] = idOrNull(_info.second.declaration);
|
||||
tuple["isSlot"] = Json::Value(_info.second.suffix == "slot");
|
||||
tuple["isOffset"] = Json::Value(_info.second.suffix == "offset");
|
||||
|
||||
if (!_info.second.suffix.empty())
|
||||
tuple["suffix"] = Json::Value(_info.second.suffix);
|
||||
|
||||
tuple["valueSize"] = Json::Value(Json::LargestUInt(_info.second.valueSize));
|
||||
|
||||
return tuple;
|
||||
}
|
||||
|
||||
|
||||
@@ -823,6 +823,16 @@ bool ContractCompiler::visit(InlineAssembly const& _inlineAssembly)
|
||||
if (suffix == "length")
|
||||
stackDiff--;
|
||||
}
|
||||
else if (
|
||||
auto const* functionType = dynamic_cast<FunctionType const*>(variable->type());
|
||||
functionType && functionType->kind() == FunctionType::Kind::External
|
||||
)
|
||||
{
|
||||
solAssert(suffix == "selector" || suffix == "address", "");
|
||||
solAssert(variable->type()->sizeOnStack() == 2, "");
|
||||
if (suffix == "selector")
|
||||
stackDiff--;
|
||||
}
|
||||
else
|
||||
solAssert(false, "");
|
||||
}
|
||||
@@ -889,6 +899,16 @@ bool ContractCompiler::visit(InlineAssembly const& _inlineAssembly)
|
||||
solAssert(suffix.empty(), "");
|
||||
}
|
||||
}
|
||||
else if (
|
||||
auto const* functionType = dynamic_cast<FunctionType const*>(variable->type());
|
||||
functionType && functionType->kind() == FunctionType::Kind::External
|
||||
)
|
||||
{
|
||||
solAssert(suffix == "selector" || suffix == "address", "");
|
||||
solAssert(variable->type()->sizeOnStack() == 2, "");
|
||||
if (suffix == "selector")
|
||||
stackDiff--;
|
||||
}
|
||||
else
|
||||
solAssert(suffix.empty(), "");
|
||||
|
||||
|
||||
@@ -188,6 +188,18 @@ private:
|
||||
solAssert(suffix == "offset" || suffix == "length", "");
|
||||
value = IRVariable{*varDecl}.part(suffix).name();
|
||||
}
|
||||
else if (
|
||||
auto const* functionType = dynamic_cast<FunctionType const*>(varDecl->type());
|
||||
functionType && functionType->kind() == FunctionType::Kind::External
|
||||
)
|
||||
{
|
||||
solAssert(suffix == "selector" || suffix == "address", "");
|
||||
solAssert(varDecl->type()->sizeOnStack() == 2, "");
|
||||
if (suffix == "selector")
|
||||
value = IRVariable{*varDecl}.part("functionSelector").name();
|
||||
else
|
||||
value = IRVariable{*varDecl}.part("address").name();
|
||||
}
|
||||
else
|
||||
solAssert(false, "");
|
||||
|
||||
|
||||
Reference in New Issue
Block a user