From fa338eba3b0e546ea2351c080e34252f0bf134a7 Mon Sep 17 00:00:00 2001 From: Sean Young Date: Mon, 10 Feb 2025 17:12:42 +0000 Subject: [PATCH] abi.decode("", ()) has no returns (#1732) This should be compiled as: function returning void Fixes: https://github.com/hyperledger-solang/solang/issues/1727 Signed-off-by: Sean Young --- src/codegen/expression.rs | 7 +++- src/sema/builtin.rs | 32 +++++++++++-------- .../evm/builtins/abi_decode_unit_1.sol | 7 ++++ .../evm/builtins/abi_decode_unit_2.sol | 8 +++++ 4 files changed, 40 insertions(+), 14 deletions(-) create mode 100644 tests/contract_testcases/evm/builtins/abi_decode_unit_1.sol create mode 100644 tests/contract_testcases/evm/builtins/abi_decode_unit_2.sol diff --git a/src/codegen/expression.rs b/src/codegen/expression.rs index 5913fcfe0..e6aee2094 100644 --- a/src/codegen/expression.rs +++ b/src/codegen/expression.rs @@ -3198,7 +3198,12 @@ pub fn emit_function_call( args, } => { let data = expression(&args[0], cfg, caller_contract_no, func, ns, vartab, opt); - abi_decode(loc, &data, tys, ns, vartab, cfg, None) + + if tys.len() == 1 && tys[0] == Type::Void { + vec![Expression::Poison] + } else { + abi_decode(loc, &data, tys, ns, vartab, cfg, None) + } } _ => unreachable!(), } diff --git a/src/sema/builtin.rs b/src/sema/builtin.rs index cc3ee66ee..6cefddfb1 100644 --- a/src/sema/builtin.rs +++ b/src/sema/builtin.rs @@ -1135,24 +1135,30 @@ pub(super) fn resolve_namespace_call( let mut tys = Vec::new(); let mut broken = false; - for arg in parameter_list_to_expr_list(&args[1], diagnostics)? { - let ty = ns.resolve_type( - context.file_no, - context.contract_no, - ResolveTypeContext::None, - arg.strip_parentheses(), - diagnostics, - )?; + let ty_exprs = parameter_list_to_expr_list(&args[1], diagnostics)?; - if ty.is_mapping() || ty.is_recursive(ns) { - diagnostics.push(Diagnostic::error( + if ty_exprs.is_empty() { + tys.push(Type::Void); + } else { + for arg in ty_exprs { + let ty = ns.resolve_type( + context.file_no, + context.contract_no, + ResolveTypeContext::None, + arg.strip_parentheses(), + diagnostics, + )?; + + if ty.is_mapping() || ty.is_recursive(ns) { + diagnostics.push(Diagnostic::error( *loc, format!("Invalid type '{}': mappings and recursive types cannot be abi decoded or encoded", ty.to_string(ns)) )); - broken = true; - } + broken = true; + } - tys.push(ty); + tys.push(ty); + } } return if broken { diff --git a/tests/contract_testcases/evm/builtins/abi_decode_unit_1.sol b/tests/contract_testcases/evm/builtins/abi_decode_unit_1.sol new file mode 100644 index 000000000..58d0fa5f3 --- /dev/null +++ b/tests/contract_testcases/evm/builtins/abi_decode_unit_1.sol @@ -0,0 +1,7 @@ +contract C { + function g() public pure { + abi.decode("abc", ()); + } +} + +// ---- Expect: diagnostics ---- diff --git a/tests/contract_testcases/evm/builtins/abi_decode_unit_2.sol b/tests/contract_testcases/evm/builtins/abi_decode_unit_2.sol new file mode 100644 index 000000000..b864aabff --- /dev/null +++ b/tests/contract_testcases/evm/builtins/abi_decode_unit_2.sol @@ -0,0 +1,8 @@ +contract C { + function f() public pure { + int a =abi.decode("abc", ()); + } +} + +// ---- Expect: diagnostics ---- +// error: 3:16-37: function or method does not return a value