From f271dfa2e26ba5bf3656e1b98110a3ac074750f8 Mon Sep 17 00:00:00 2001 From: chriseth Date: Thu, 16 Apr 2020 13:42:58 +0200 Subject: [PATCH] Yul codegen for `.selector`. --- .../codegen/ir/IRGeneratorForStatements.cpp | 25 ++++++++++++++++--- .../builtinFunctions/function_types_sig.sol | 2 ++ .../function_selector_via_contract_name.sol | 2 ++ 3 files changed, 25 insertions(+), 4 deletions(-) diff --git a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp index 2a9c6a9ea..0100056cd 100644 --- a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp +++ b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp @@ -842,11 +842,18 @@ void IRGeneratorForStatements::endVisit(MemberAccess const& _memberAccess) case Type::Category::Function: if (member == "selector") { - solUnimplementedAssert( - dynamic_cast(*_memberAccess.expression().annotation().type).kind() == - FunctionType::Kind::External, "" + FunctionType const& functionType = dynamic_cast( + *_memberAccess.expression().annotation().type ); - define(IRVariable{_memberAccess}, IRVariable(_memberAccess.expression()).part("functionIdentifier")); + if (functionType.kind() == FunctionType::Kind::External) + define(IRVariable{_memberAccess}, IRVariable(_memberAccess.expression()).part("functionIdentifier")); + else if (functionType.kind() == FunctionType::Kind::Declaration) + { + solAssert(functionType.hasDeclaration(), ""); + define(IRVariable{_memberAccess}) << formatNumber(functionType.externalIdentifier() << 224) << "\n"; + } + else + solAssert(false, "Invalid use of .selector"); } else if (member == "address") { @@ -973,6 +980,16 @@ void IRGeneratorForStatements::endVisit(MemberAccess const& _memberAccess) solAssert(false, "Illegal fixed bytes member."); break; } + case Type::Category::TypeType: + { + TypeType const& type = dynamic_cast(*_memberAccess.expression().annotation().type); + solUnimplementedAssert(type.actualType()->category() == Type::Category::Contract, ""); + FunctionType const* funType = dynamic_cast(_memberAccess.annotation().type); + solUnimplementedAssert(funType, ""); + solUnimplementedAssert(funType->kind() == FunctionType::Kind::Declaration, ""); + // Nothing to do for declaration. + break; + } default: solAssert(false, "Member access to unknown type."); } diff --git a/test/libsolidity/semanticTests/builtinFunctions/function_types_sig.sol b/test/libsolidity/semanticTests/builtinFunctions/function_types_sig.sol index 2e771032b..e753cbbe9 100644 --- a/test/libsolidity/semanticTests/builtinFunctions/function_types_sig.sol +++ b/test/libsolidity/semanticTests/builtinFunctions/function_types_sig.sol @@ -19,6 +19,8 @@ contract C { return this.x.selector; } } +// ==== +// compileViaYul: also // ---- // f() -> 0x26121ff000000000000000000000000000000000000000000000000000000000 // g() -> 0x26121ff000000000000000000000000000000000000000000000000000000000 diff --git a/test/libsolidity/semanticTests/functionSelector/function_selector_via_contract_name.sol b/test/libsolidity/semanticTests/functionSelector/function_selector_via_contract_name.sol index 0a9e6d3ff..b6a666d5b 100644 --- a/test/libsolidity/semanticTests/functionSelector/function_selector_via_contract_name.sol +++ b/test/libsolidity/semanticTests/functionSelector/function_selector_via_contract_name.sol @@ -15,6 +15,8 @@ contract C { return (a.f.selector, a.g.selector, b.f.selector, b.g.selector); } } +// ==== +// compileViaYul: also // ---- // test1() -> left(0x26121ff0), left(0xe420264a), left(0x26121ff0), left(0xe420264a) // test2() -> left(0x26121ff0), left(0xe420264a), left(0x26121ff0), left(0xe420264a)