aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Changelog.md1
-rw-r--r--libsolidity/codegen/ExpressionCompiler.cpp6
-rw-r--r--test/libsolidity/SolidityEndToEndTest.cpp20
-rw-r--r--test/libsolidity/syntaxTests/memberLookup/internal_function_type.sol7
4 files changed, 31 insertions, 3 deletions
diff --git a/Changelog.md b/Changelog.md
index 2835a14e..1c3fcde4 100644
--- a/Changelog.md
+++ b/Changelog.md
@@ -18,6 +18,7 @@ Bugfixes:
* Assembly output: Do not mix in/out jump annotations with arguments.
* Commandline interface: Fix crash when using ``--ast`` on empty runtime code.
* Code Generator: Annotate jump from calldata decoder to function as "jump in".
+ * Code Generator: Fix internal error related to state variables of function type access via base contract name.
* Optimizer: Fix nondeterminism bug related to the boost version and constants representation. The bug only resulted in less optimal but still correct code because the generated routine is always verified to be correct.
* Type Checker: Properly detect different return types when overriding an external interface function with a public contract function.
* Type Checker: Disallow struct return types for getters of public state variables unless the new ABI encoder is active.
diff --git a/libsolidity/codegen/ExpressionCompiler.cpp b/libsolidity/codegen/ExpressionCompiler.cpp
index 87eecd2e..121585d9 100644
--- a/libsolidity/codegen/ExpressionCompiler.cpp
+++ b/libsolidity/codegen/ExpressionCompiler.cpp
@@ -1153,7 +1153,9 @@ bool ExpressionCompiler::visit(MemberAccess const& _memberAccess)
if (dynamic_cast<ContractType const*>(type->actualType().get()))
{
solAssert(_memberAccess.annotation().type, "_memberAccess has no type");
- if (auto funType = dynamic_cast<FunctionType const*>(_memberAccess.annotation().type.get()))
+ if (auto variable = dynamic_cast<VariableDeclaration const*>(_memberAccess.annotation().referencedDeclaration))
+ appendVariable(*variable, static_cast<Expression const&>(_memberAccess));
+ else if (auto funType = dynamic_cast<FunctionType const*>(_memberAccess.annotation().type.get()))
{
switch (funType->kind())
{
@@ -1199,8 +1201,6 @@ bool ExpressionCompiler::visit(MemberAccess const& _memberAccess)
{
// no-op
}
- else if (auto variable = dynamic_cast<VariableDeclaration const*>(_memberAccess.annotation().referencedDeclaration))
- appendVariable(*variable, static_cast<Expression const&>(_memberAccess));
else
_memberAccess.expression().accept(*this);
}
diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp
index 05bb7446..c6135a72 100644
--- a/test/libsolidity/SolidityEndToEndTest.cpp
+++ b/test/libsolidity/SolidityEndToEndTest.cpp
@@ -14213,6 +14213,26 @@ BOOST_AUTO_TEST_CASE(external_public_override)
ABI_CHECK(callContractFunction("f()"), encodeArgs(2));
ABI_CHECK(callContractFunction("g()"), encodeArgs(2));
}
+
+BOOST_AUTO_TEST_CASE(base_access_to_function_type_variables)
+{
+ char const* sourceCode = R"(
+ contract C {
+ function () internal returns (uint) x;
+ function set() public {
+ C.x = g;
+ }
+ function g() public pure returns (uint) { return 2; }
+ function h() public returns (uint) { return C.x(); }
+ }
+ )";
+ compileAndRun(sourceCode);
+ ABI_CHECK(callContractFunction("g()"), encodeArgs(2));
+ ABI_CHECK(callContractFunction("h()"), encodeArgs());
+ ABI_CHECK(callContractFunction("set()"), encodeArgs());
+ ABI_CHECK(callContractFunction("h()"), encodeArgs(2));
+}
+
BOOST_AUTO_TEST_SUITE_END()
}
diff --git a/test/libsolidity/syntaxTests/memberLookup/internal_function_type.sol b/test/libsolidity/syntaxTests/memberLookup/internal_function_type.sol
new file mode 100644
index 00000000..560a6c2a
--- /dev/null
+++ b/test/libsolidity/syntaxTests/memberLookup/internal_function_type.sol
@@ -0,0 +1,7 @@
+contract C {
+ function () internal returns (uint) x;
+ constructor() public {
+ C.x = g;
+ }
+ function g() public pure returns (uint) {}
+}