Browse Source

Fix standload function call bug (#757)

Lucas Steuernagel 3 năm trước cách đây
mục cha
commit
2088ce7431

+ 1 - 2
src/bin/languageserver/mod.rs

@@ -757,12 +757,11 @@ impl SolangServer {
                 }
             }
             ast::Expression::ExternalFunctionCallRaw {
-                loc: _,
-                ty: _,
                 address,
                 args,
                 value,
                 gas,
+                ..
             } => {
                 SolangServer::construct_expr(args, lookup_tbl, symtab, fnc_map, ns);
                 SolangServer::construct_expr(address, lookup_tbl, symtab, fnc_map, ns);

+ 4 - 3
src/codegen/expression.rs

@@ -421,7 +421,6 @@ pub fn expression(
         | ast::Expression::ExternalFunctionCallRaw { .. }
         | ast::Expression::Builtin(_, _, ast::Builtin::AbiDecode, _) => {
             let mut returns = emit_function_call(expr, contract_no, cfg, func, ns, vartab, opt);
-            assert_eq!(returns.len(), 1);
 
             returns.remove(0)
         }
@@ -2144,6 +2143,7 @@ pub fn emit_function_call(
             args,
             value,
             gas,
+            returns,
             ..
         } => {
             if let ast::Expression::ExternalFunction {
@@ -2234,7 +2234,8 @@ pub fn emit_function_call(
                     },
                 );
 
-                if !ftype.returns.is_empty() {
+                // If the first element of returns is Void, we can discard the returns
+                if !ftype.returns.is_empty() && returns[0] != Type::Void {
                     let mut returns = Vec::new();
                     let mut res = Vec::new();
 
@@ -2319,7 +2320,7 @@ pub fn emit_function_call(
                     },
                 );
 
-                if !func_returns.is_empty() {
+                if !func_returns.is_empty() && returns[0] != Type::Void {
                     let mut returns = Vec::new();
                     let mut res = Vec::new();
                     let mut tys = Vec::new();

+ 1 - 1
src/sema/dotgraphviz.rs

@@ -808,7 +808,7 @@ impl Dot {
             Expression::UnaryMinus(loc, ty, expr) => {
                 let node = self.add_node(
                     Node::new(
-                        "unary minus",
+                        "unary_minus",
                         vec![
                             format!("unary minus {}", ty.to_string(ns)),
                             ns.loc_to_string(loc),

+ 99 - 42
src/sema/expression.rs

@@ -1464,7 +1464,7 @@ pub fn compatible_mutability(left: &Mutability, right: &Mutability) -> bool {
 }
 
 /// When resolving an expression, what type are we looking for
-#[derive(PartialEq, Clone, Copy)]
+#[derive(PartialEq, Clone, Copy, Debug)]
 pub enum ResolveTo<'a> {
     Unknown,        // We don't know what we're looking for, best effort
     Discard,        // We won't be using the result. For example, an expression as a statement/
@@ -1793,9 +1793,17 @@ pub fn expression(
 
             assign_expr(loc, var, expr, e, context, ns, symtable, diagnostics)
         }
-        pt::Expression::NamedFunctionCall(loc, ty, args) => {
-            named_call_expr(loc, ty, args, false, context, ns, symtable, diagnostics)
-        }
+        pt::Expression::NamedFunctionCall(loc, ty, args) => named_call_expr(
+            loc,
+            ty,
+            args,
+            false,
+            context,
+            ns,
+            symtable,
+            diagnostics,
+            resolve_to,
+        ),
         pt::Expression::New(loc, call) => {
             if context.constant {
                 diagnostics.push(Diagnostic::error(
@@ -1869,20 +1877,24 @@ pub fn expression(
         }
         pt::Expression::Or(loc, left, right) => {
             let boolty = Type::Bool;
-            let l = expression(left, context, ns, symtable, diagnostics, resolve_to)?.cast(
-                loc,
-                &boolty,
-                true,
+            let l = expression(
+                left,
+                context,
                 ns,
+                symtable,
                 diagnostics,
-            )?;
-            let r = expression(right, context, ns, symtable, diagnostics, resolve_to)?.cast(
-                loc,
-                &boolty,
-                true,
+                ResolveTo::Type(&boolty),
+            )?
+            .cast(loc, &boolty, true, ns, diagnostics)?;
+            let r = expression(
+                right,
+                context,
                 ns,
+                symtable,
                 diagnostics,
-            )?;
+                ResolveTo::Type(&boolty),
+            )?
+            .cast(loc, &boolty, true, ns, diagnostics)?;
 
             check_var_usage_expression(ns, &l, &r, symtable);
 
@@ -1890,20 +1902,24 @@ pub fn expression(
         }
         pt::Expression::And(loc, left, right) => {
             let boolty = Type::Bool;
-            let l = expression(left, context, ns, symtable, diagnostics, resolve_to)?.cast(
-                loc,
-                &boolty,
-                true,
+            let l = expression(
+                left,
+                context,
                 ns,
+                symtable,
                 diagnostics,
-            )?;
-            let r = expression(right, context, ns, symtable, diagnostics, resolve_to)?.cast(
-                loc,
-                &boolty,
-                true,
+                ResolveTo::Type(&boolty),
+            )?
+            .cast(loc, &boolty, true, ns, diagnostics)?;
+            let r = expression(
+                right,
+                context,
                 ns,
+                symtable,
                 diagnostics,
-            )?;
+                ResolveTo::Type(&boolty),
+            )?
+            .cast(loc, &boolty, true, ns, diagnostics)?;
             check_var_usage_expression(ns, &l, &r, symtable);
 
             Ok(Expression::And(*loc, Box::new(l), Box::new(r)))
@@ -3570,6 +3586,18 @@ fn addition(
         diagnostics,
     )?;
 
+    if ty.is_rational() {
+        let expr = Expression::Add(*loc, ty, false, Box::new(left), Box::new(right));
+
+        return match eval_const_rational(&expr, ns) {
+            Ok(_) => Ok(expr),
+            Err(diag) => {
+                diagnostics.push(diag);
+                Err(())
+            }
+        };
+    }
+
     // If we don't know what type the result is going to be
     if resolve_to == ResolveTo::Unknown {
         let bits = std::cmp::min(256, ty.bits(ns) * 2);
@@ -4214,7 +4242,7 @@ fn member_access(
 
                     expr = Ok(Expression::InternalFunction {
                         loc: e.loc(),
-                        ty: function_type(func, false),
+                        ty: function_type(func, false, resolve_to),
                         function_no: *function_no,
                         signature: None,
                     })
@@ -4806,6 +4834,7 @@ fn call_function_type(
     ns: &mut Namespace,
     symtable: &mut Symtable,
     diagnostics: &mut Vec<Diagnostic>,
+    resolve_to: ResolveTo,
 ) -> Result<Expression, ()> {
     let mut function = expression(expr, context, ns, symtable, diagnostics, ResolveTo::Unknown)?;
 
@@ -4860,7 +4889,7 @@ fn call_function_type(
 
         Ok(Expression::InternalFunctionCall {
             loc: *loc,
-            returns: if returns.is_empty() {
+            returns: if returns.is_empty() || resolve_to == ResolveTo::Discard {
                 vec![Type::Void]
             } else {
                 returns
@@ -4923,7 +4952,7 @@ fn call_function_type(
 
         Ok(Expression::ExternalFunctionCall {
             loc: *loc,
-            returns: if returns.is_empty() {
+            returns: if returns.is_empty() || resolve_to == ResolveTo::Discard {
                 vec![Type::Void]
             } else {
                 returns
@@ -5015,6 +5044,7 @@ pub fn call_position_args(
     virtual_call: bool,
     context: &ExprContext,
     ns: &mut Namespace,
+    resolve_to: ResolveTo,
     symtable: &mut Symtable,
     diagnostics: &mut Vec<Diagnostic>,
 ) -> Result<Expression, ()> {
@@ -5094,8 +5124,8 @@ pub fn call_position_args(
             continue;
         }
 
-        let returns = function_returns(func);
-        let ty = function_type(func, false);
+        let returns = function_returns(func, resolve_to);
+        let ty = function_type(func, false, resolve_to);
 
         return Ok(Expression::InternalFunctionCall {
             loc: *loc,
@@ -5148,6 +5178,7 @@ fn function_call_with_named_args(
     function_nos: Vec<usize>,
     virtual_call: bool,
     context: &ExprContext,
+    resolve_to: ResolveTo,
     ns: &mut Namespace,
     symtable: &mut Symtable,
     diagnostics: &mut Vec<Diagnostic>,
@@ -5259,8 +5290,8 @@ fn function_call_with_named_args(
             continue;
         }
 
-        let returns = function_returns(func);
-        let ty = function_type(func, false);
+        let returns = function_returns(func, resolve_to);
+        let ty = function_type(func, false, resolve_to);
 
         return Ok(Expression::InternalFunctionCall {
             loc: *loc,
@@ -5425,6 +5456,7 @@ fn method_call_pos_args(
                     false,
                     context,
                     ns,
+                    resolve_to,
                     symtable,
                     diagnostics,
                 );
@@ -5463,6 +5495,7 @@ fn method_call_pos_args(
                     true,
                     context,
                     ns,
+                    resolve_to,
                     symtable,
                     diagnostics,
                 );
@@ -5494,6 +5527,7 @@ fn method_call_pos_args(
                         false,
                         context,
                         ns,
+                        resolve_to,
                         symtable,
                         diagnostics,
                     );
@@ -5974,8 +6008,8 @@ fn method_call_pos_args(
                 };
 
                 let func = &ns.functions[*function_no];
-                let returns = function_returns(func);
-                let ty = function_type(func, true);
+                let returns = function_returns(func, resolve_to);
+                let ty = function_type(func, true, resolve_to);
 
                 return Ok(Expression::ExternalFunctionCall {
                     loc: *loc,
@@ -6012,6 +6046,7 @@ fn method_call_pos_args(
             symtable,
             diagnostics,
             ns,
+            resolve_to,
         ) {
             Ok(Some(expr)) => {
                 diagnostics.truncate(marker);
@@ -6177,6 +6212,7 @@ fn method_call_pos_args(
             symtable,
             diagnostics,
             ns,
+            resolve_to,
         ) {
             Ok(Some(expr)) => {
                 return Ok(expr);
@@ -6206,6 +6242,7 @@ fn resolve_using(
     symtable: &mut Symtable,
     diagnostics: &mut Vec<Diagnostic>,
     ns: &mut Namespace,
+    resolve_to: ResolveTo,
 ) -> Result<Option<Expression>, ()> {
     // first collect all possible libraries that match the using directive type
     // Use HashSet for deduplication.
@@ -6304,8 +6341,8 @@ fn resolve_using(
                 continue;
             }
 
-            let returns = function_returns(libfunc);
-            let ty = function_type(libfunc, false);
+            let returns = function_returns(libfunc, resolve_to);
+            let ty = function_type(libfunc, false, resolve_to);
 
             return Ok(Some(Expression::InternalFunctionCall {
                 loc: *loc,
@@ -6349,6 +6386,7 @@ fn method_call_named_args(
     ns: &mut Namespace,
     symtable: &mut Symtable,
     diagnostics: &mut Vec<Diagnostic>,
+    resolve_to: ResolveTo,
 ) -> Result<Expression, ()> {
     if let pt::Expression::Variable(namespace) = var {
         // is it a call to super
@@ -6369,6 +6407,7 @@ fn method_call_named_args(
                     available_super_functions(&func_name.name, cur_contract_no, ns),
                     false,
                     context,
+                    resolve_to,
                     ns,
                     symtable,
                     diagnostics,
@@ -6406,6 +6445,7 @@ fn method_call_named_args(
                     ),
                     true,
                     context,
+                    resolve_to,
                     ns,
                     symtable,
                     diagnostics,
@@ -6436,6 +6476,7 @@ fn method_call_named_args(
                         ),
                         false,
                         context,
+                        resolve_to,
                         ns,
                         symtable,
                         diagnostics,
@@ -6567,8 +6608,8 @@ fn method_call_named_args(
                 };
 
                 let func = &ns.functions[*function_no];
-                let returns = function_returns(func);
-                let ty = function_type(func, true);
+                let returns = function_returns(func, resolve_to);
+                let ty = function_type(func, true, resolve_to);
 
                 return Ok(Expression::ExternalFunctionCall {
                     loc: *loc,
@@ -7021,6 +7062,7 @@ pub fn named_call_expr(
     ns: &mut Namespace,
     symtable: &mut Symtable,
     diagnostics: &mut Vec<Diagnostic>,
+    resolve_to: ResolveTo,
 ) -> Result<Expression, ()> {
     let mut nullsink = Vec::new();
 
@@ -7054,7 +7096,16 @@ pub fn named_call_expr(
         return Err(());
     }
 
-    let expr = named_function_call_expr(loc, ty, args, context, ns, symtable, diagnostics)?;
+    let expr = named_function_call_expr(
+        loc,
+        ty,
+        args,
+        context,
+        ns,
+        symtable,
+        diagnostics,
+        resolve_to,
+    )?;
 
     check_function_call(ns, &expr, symtable);
     if expr.tys().len() > 1 && !is_destructible {
@@ -7234,6 +7285,7 @@ pub fn function_call_expr(
                     ns,
                     symtable,
                     diagnostics,
+                    resolve_to,
                 )
             } else {
                 if let Some(loc) = call_args_loc {
@@ -7253,6 +7305,7 @@ pub fn function_call_expr(
                     true,
                     context,
                     ns,
+                    resolve_to,
                     symtable,
                     diagnostics,
                 )
@@ -7268,6 +7321,7 @@ pub fn function_call_expr(
             ns,
             symtable,
             diagnostics,
+            resolve_to,
         ),
     }
 }
@@ -7281,6 +7335,7 @@ pub fn named_function_call_expr(
     ns: &mut Namespace,
     symtable: &mut Symtable,
     diagnostics: &mut Vec<Diagnostic>,
+    resolve_to: ResolveTo,
 ) -> Result<Expression, ()> {
     let (ty, call_args, call_args_loc) = collect_call_args(ty, diagnostics)?;
 
@@ -7296,6 +7351,7 @@ pub fn named_function_call_expr(
             ns,
             symtable,
             diagnostics,
+            resolve_to,
         ),
         pt::Expression::Variable(id) => {
             if let Some(loc) = call_args_loc {
@@ -7313,6 +7369,7 @@ pub fn named_function_call_expr(
                 available_functions(&id.name, true, context.file_no, context.contract_no, ns),
                 true,
                 context,
+                resolve_to,
                 ns,
                 symtable,
                 diagnostics,
@@ -7336,8 +7393,8 @@ pub fn named_function_call_expr(
 }
 
 /// Get the return values for a function call
-fn function_returns(ftype: &Function) -> Vec<Type> {
-    if !ftype.returns.is_empty() {
+fn function_returns(ftype: &Function, resolve_to: ResolveTo) -> Vec<Type> {
+    if !ftype.returns.is_empty() && !matches!(resolve_to, ResolveTo::Discard) {
         ftype.returns.iter().map(|p| p.ty.clone()).collect()
     } else {
         vec![Type::Void]
@@ -7345,10 +7402,10 @@ fn function_returns(ftype: &Function) -> Vec<Type> {
 }
 
 /// Get the function type for an internal.external function call
-fn function_type(func: &Function, external: bool) -> Type {
+fn function_type(func: &Function, external: bool, resolve_to: ResolveTo) -> Type {
     let params = func.params.iter().map(|p| p.ty.clone()).collect();
     let mutability = func.mutability.clone();
-    let returns = function_returns(func);
+    let returns = function_returns(func, resolve_to);
 
     if external {
         Type::ExternalFunction {

+ 100 - 51
src/sema/statements.rs

@@ -183,6 +183,7 @@ pub fn resolve_function_body(
                     true,
                     &context,
                     ns,
+                    ResolveTo::Unknown,
                     &mut symtable,
                     &mut diagnostics,
                 ) {
@@ -705,39 +706,37 @@ fn statement(
             Ok(false)
         }
         pt::Statement::Expression(loc, expr) => {
-            // delete statement
-            if let pt::Expression::Delete(_, expr) = expr {
-                let expr =
-                    expression(expr, context, ns, symtable, diagnostics, ResolveTo::Unknown)?;
-                used_variable(ns, &expr, symtable);
-                return if let Type::StorageRef(_, ty) = expr.ty() {
-                    if expr.ty().is_mapping() {
+            let expr = match expr {
+                // delete statement
+                pt::Expression::Delete(_, expr) => {
+                    let expr =
+                        expression(expr, context, ns, symtable, diagnostics, ResolveTo::Unknown)?;
+                    used_variable(ns, &expr, symtable);
+                    return if let Type::StorageRef(_, ty) = expr.ty() {
+                        if expr.ty().is_mapping() {
+                            ns.diagnostics.push(Diagnostic::error(
+                                *loc,
+                                "‘delete’ cannot be applied to mapping type".to_string(),
+                            ));
+                            return Err(());
+                        }
+
+                        res.push(Statement::Delete(*loc, ty.as_ref().clone(), expr));
+
+                        Ok(true)
+                    } else {
                         ns.diagnostics.push(Diagnostic::error(
                             *loc,
-                            "‘delete’ cannot be applied to mapping type".to_string(),
+                            "argument to ‘delete’ should be storage reference".to_string(),
                         ));
-                        return Err(());
-                    }
-
-                    res.push(Statement::Delete(*loc, ty.as_ref().clone(), expr));
-
-                    Ok(true)
-                } else {
-                    ns.diagnostics.push(Diagnostic::error(
-                        *loc,
-                        "argument to ‘delete’ should be storage reference".to_string(),
-                    ));
-
-                    Err(())
-                };
-            }
 
-            // is it an underscore modifier statement
-            if let pt::Expression::Variable(id) = expr {
-                if id.name == "_" {
+                        Err(())
+                    };
+                }
+                // is it an underscore modifier statement
+                pt::Expression::Variable(id) if id.name == "_" => {
                     return if ns.functions[function_no].ty == pt::FunctionTy::Modifier {
                         res.push(Statement::Underscore(*loc));
-
                         Ok(true)
                     } else {
                         ns.diagnostics.push(Diagnostic::error(
@@ -747,30 +746,52 @@ fn statement(
                         Err(())
                     };
                 }
-            }
-
-            // is it a destructure statement
-            if let pt::Expression::Assign(_, var, expr) = expr {
-                if let pt::Expression::List(_, var) = var.as_ref() {
-                    res.push(destructure(
-                        loc,
-                        var,
-                        expr,
-                        context,
-                        symtable,
-                        ns,
-                        diagnostics,
-                    )?);
+                pt::Expression::FunctionCall(loc, ty, args) => call_expr(
+                    loc,
+                    ty,
+                    args,
+                    true,
+                    context,
+                    ns,
+                    symtable,
+                    diagnostics,
+                    ResolveTo::Discard,
+                )?,
+                pt::Expression::NamedFunctionCall(loc, ty, args) => named_call_expr(
+                    loc,
+                    ty,
+                    args,
+                    true,
+                    context,
+                    ns,
+                    symtable,
+                    diagnostics,
+                    ResolveTo::Discard,
+                )?,
+                _ => {
+                    // is it a destructure statement
+                    if let pt::Expression::Assign(_, var, expr) = expr {
+                        if let pt::Expression::List(_, var) = var.as_ref() {
+                            res.push(destructure(
+                                loc,
+                                var,
+                                expr,
+                                context,
+                                symtable,
+                                ns,
+                                diagnostics,
+                            )?);
 
-                    // if a noreturn function was called, then the destructure would not resolve
-                    return Ok(true);
+                            // if a noreturn function was called, then the destructure would not resolve
+                            return Ok(true);
+                        }
+                    }
+                    // the rest. We don't care about the result
+                    expression(expr, context, ns, symtable, diagnostics, ResolveTo::Unknown)?
                 }
-            }
-
-            // the rest. We don't care about the result
-            let expr = expression(expr, context, ns, symtable, diagnostics, ResolveTo::Discard)?;
+            };
 
-            let reachable = expr.ty() != Type::Unreachable;
+            let reachable = expr.tys() != vec![Type::Unreachable];
 
             res.push(Statement::Expression(*loc, reachable, expr));
 
@@ -1292,7 +1313,16 @@ fn destructure_values(
             res
         }
         pt::Expression::NamedFunctionCall(loc, ty, args) => {
-            let res = named_function_call_expr(loc, ty, args, context, ns, symtable, diagnostics)?;
+            let res = named_function_call_expr(
+                loc,
+                ty,
+                args,
+                context,
+                ns,
+                symtable,
+                diagnostics,
+                ResolveTo::Unknown,
+            )?;
             check_function_call(ns, &res, symtable);
             res
         }
@@ -1504,7 +1534,17 @@ fn return_with_values(
             expr
         }
         pt::Expression::NamedFunctionCall(loc, ty, args) => {
-            let expr = named_call_expr(loc, ty, args, true, context, ns, symtable, diagnostics)?;
+            let expr = named_call_expr(
+                loc,
+                ty,
+                args,
+                true,
+                context,
+                ns,
+                symtable,
+                diagnostics,
+                ResolveTo::Unknown,
+            )?;
             used_variable(ns, &expr, symtable);
             expr
         }
@@ -1759,7 +1799,16 @@ fn try_catch(
             res
         }
         pt::Expression::NamedFunctionCall(loc, ty, args) => {
-            let res = named_function_call_expr(loc, ty, args, context, ns, symtable, diagnostics)?;
+            let res = named_function_call_expr(
+                loc,
+                ty,
+                args,
+                context,
+                ns,
+                symtable,
+                diagnostics,
+                ResolveTo::Unknown,
+            )?;
 
             check_function_call(ns, &res, symtable);
 

+ 15 - 0
tests/codegen_testcases/unused_returns.sol

@@ -0,0 +1,15 @@
+// RUN: --target substrate --emit cfg
+contract C {
+        function foo() public returns (int, int) { return (1, 2); }
+
+        // BEGIN-CHECK: C::function::bar
+        function bar() public { 
+            // NOT-CHECK: abidecode
+            this.foo(); 
+
+            function () external returns (int, int) fPtr = this.foo;
+
+            // NOT-CHECK: abidecode
+            fPtr();
+        }
+}

+ 284 - 0
tests/contract_testcases/ewasm/standalone_call.dot

@@ -0,0 +1,284 @@
+strict digraph "tests/contract_testcases/ewasm/standalone_call.sol" {
+	tts [label="name:tts\ncontract: BABYLINK\ntests/contract_testcases/ewasm/standalone_call.sol:8:12-15\nfield name:a ty:int256\nfield name:b ty:int256"]
+	contract [label="contract foo\ntests/contract_testcases/ewasm/standalone_call.sol:1:1-14"]
+	bar [label="function bar\ncontract: foo\ntests/contract_testcases/ewasm/standalone_call.sol:2:5-50\nsignature bar()\nvisibility public\nmutability pure"]
+	returns [label="returns\nint256 \nint256 "]
+	return [label="return\ntests/contract_testcases/ewasm/standalone_call.sol:3:9-22"]
+	list [label="list\ntests/contract_testcases/ewasm/standalone_call.sol:3:9-22"]
+	number_literal [label="int256 literal: 1\ntests/contract_testcases/ewasm/standalone_call.sol:3:17-18"]
+	number_literal_9 [label="int256 literal: 2\ntests/contract_testcases/ewasm/standalone_call.sol:3:20-21"]
+	contract_10 [label="contract BABYLINK\ntests/contract_testcases/ewasm/standalone_call.sol:6:1-7:19"]
+	multipleRetuns [label="function multipleRetuns\ncontract: BABYLINK\ntests/contract_testcases/ewasm/standalone_call.sol:13:5-71\nsignature multipleRetuns(int256)\nvisibility public\nmutability pure"]
+	parameters [label="parameters\nint256 c"]
+	returns_13 [label="returns\nint256 \nint256 \nint256 "]
+	return_14 [label="return\ntests/contract_testcases/ewasm/standalone_call.sol:14:9-29"]
+	list_15 [label="list\ntests/contract_testcases/ewasm/standalone_call.sol:14:9-29"]
+	number_literal_16 [label="int256 literal: 1\ntests/contract_testcases/ewasm/standalone_call.sol:14:17-18"]
+	add [label="add\nint256\ntests/contract_testcases/ewasm/standalone_call.sol:14:22-23"]
+	variable [label="variable: c\nint256\ntests/contract_testcases/ewasm/standalone_call.sol:14:20-21"]
+	number_literal_19 [label="int256 literal: 2\ntests/contract_testcases/ewasm/standalone_call.sol:14:24-25"]
+	number_literal_20 [label="int256 literal: 3\ntests/contract_testcases/ewasm/standalone_call.sol:14:27-28"]
+	singleReturn [label="function singleReturn\ncontract: BABYLINK\ntests/contract_testcases/ewasm/standalone_call.sol:17:5-55\nsignature singleReturn()\nvisibility private\nmutability pure"]
+	returns_22 [label="returns\nint256 "]
+	return_23 [label="return\ntests/contract_testcases/ewasm/standalone_call.sol:18:9-17"]
+	number_literal_24 [label="int256 literal: 3\ntests/contract_testcases/ewasm/standalone_call.sol:18:16-17"]
+	returnBool [label="function returnBool\ncontract: BABYLINK\ntests/contract_testcases/ewasm/standalone_call.sol:21:5-54\nsignature returnBool()\nvisibility private\nmutability pure"]
+	returns_26 [label="returns\nbool "]
+	return_27 [label="return\ntests/contract_testcases/ewasm/standalone_call.sol:22:9-20"]
+	bool_literal [label="bool literal: true\ntests/contract_testcases/ewasm/standalone_call.sol:22:16-20"]
+	testing [label="function testing\ncontract: BABYLINK\ntests/contract_testcases/ewasm/standalone_call.sol:25:5-44\nsignature testing()\nvisibility public\nmutability nonpayable"]
+	returns_30 [label="returns\nint256 "]
+	expr [label="expression\ntests/contract_testcases/ewasm/standalone_call.sol:26:9-26"]
+	call_internal_function [label="call internal function\ntests/contract_testcases/ewasm/standalone_call.sol:26:9-26"]
+	internal_function [label="function(int256) internal pure returns (void)\nBABYLINK.multipleRetuns\ntests/contract_testcases/ewasm/standalone_call.sol:26:9-26"]
+	number_literal_34 [label="int256 literal: 3\ntests/contract_testcases/ewasm/standalone_call.sol:26:24-25"]
+	var_decl [label="variable decl int256 b\ntests/contract_testcases/ewasm/standalone_call.sol:27:9-18"]
+	number_literal_36 [label="int256 literal: 5\ntests/contract_testcases/ewasm/standalone_call.sol:27:17-18"]
+	expr_37 [label="expression\ntests/contract_testcases/ewasm/standalone_call.sol:28:9-31"]
+	call_internal_function_38 [label="call internal function\ntests/contract_testcases/ewasm/standalone_call.sol:28:9-31"]
+	internal_function_39 [label="function(int256) internal pure returns (void)\nBABYLINK.multipleRetuns\ntests/contract_testcases/ewasm/standalone_call.sol:28:9-31"]
+	number_literal_40 [label="int256 literal: 9\ntests/contract_testcases/ewasm/standalone_call.sol:28:28-29"]
+	expr_41 [label="expression\ntests/contract_testcases/ewasm/standalone_call.sol:29:9-27"]
+	add_42 [label="add\nint256\ntests/contract_testcases/ewasm/standalone_call.sol:29:11-12"]
+	number_literal_43 [label="int256 literal: 1\ntests/contract_testcases/ewasm/standalone_call.sol:29:9-10"]
+	call_internal_function_44 [label="call internal function\ntests/contract_testcases/ewasm/standalone_call.sol:29:13-27"]
+	internal_function_45 [label="function() internal pure returns (int256)\nBABYLINK.singleReturn\ntests/contract_testcases/ewasm/standalone_call.sol:29:13-27"]
+	expr_46 [label="expression\ntests/contract_testcases/ewasm/standalone_call.sol:30:9-27"]
+	subtract [label="subtract\nint256\ntests/contract_testcases/ewasm/standalone_call.sol:30:11-12"]
+	number_literal_48 [label="int256 literal: 1\ntests/contract_testcases/ewasm/standalone_call.sol:30:9-10"]
+	call_internal_function_49 [label="call internal function\ntests/contract_testcases/ewasm/standalone_call.sol:30:13-27"]
+	internal_function_50 [label="function() internal pure returns (int256)\nBABYLINK.singleReturn\ntests/contract_testcases/ewasm/standalone_call.sol:30:13-27"]
+	expr_51 [label="expression\ntests/contract_testcases/ewasm/standalone_call.sol:31:9-27"]
+	multiply [label="multiply\nint256\ntests/contract_testcases/ewasm/standalone_call.sol:31:11-12"]
+	number_literal_53 [label="int256 literal: 1\ntests/contract_testcases/ewasm/standalone_call.sol:31:9-10"]
+	call_internal_function_54 [label="call internal function\ntests/contract_testcases/ewasm/standalone_call.sol:31:13-27"]
+	internal_function_55 [label="function() internal pure returns (int256)\nBABYLINK.singleReturn\ntests/contract_testcases/ewasm/standalone_call.sol:31:13-27"]
+	expr_56 [label="expression\ntests/contract_testcases/ewasm/standalone_call.sol:32:9-27"]
+	divide [label="divide\nint256\ntests/contract_testcases/ewasm/standalone_call.sol:32:11-12"]
+	number_literal_58 [label="int256 literal: 1\ntests/contract_testcases/ewasm/standalone_call.sol:32:9-10"]
+	call_internal_function_59 [label="call internal function\ntests/contract_testcases/ewasm/standalone_call.sol:32:13-27"]
+	internal_function_60 [label="function() internal pure returns (int256)\nBABYLINK.singleReturn\ntests/contract_testcases/ewasm/standalone_call.sol:32:13-27"]
+	expr_61 [label="expression\ntests/contract_testcases/ewasm/standalone_call.sol:33:9-27"]
+	bitwise_or [label="bitwise or\nint256\ntests/contract_testcases/ewasm/standalone_call.sol:33:11-12"]
+	number_literal_63 [label="int256 literal: 1\ntests/contract_testcases/ewasm/standalone_call.sol:33:9-10"]
+	call_internal_function_64 [label="call internal function\ntests/contract_testcases/ewasm/standalone_call.sol:33:13-27"]
+	internal_function_65 [label="function() internal pure returns (int256)\nBABYLINK.singleReturn\ntests/contract_testcases/ewasm/standalone_call.sol:33:13-27"]
+	expr_66 [label="expression\ntests/contract_testcases/ewasm/standalone_call.sol:34:9-27"]
+	bitwise_and [label="bitwise and\nint256\ntests/contract_testcases/ewasm/standalone_call.sol:34:11-12"]
+	number_literal_68 [label="int256 literal: 1\ntests/contract_testcases/ewasm/standalone_call.sol:34:9-10"]
+	call_internal_function_69 [label="call internal function\ntests/contract_testcases/ewasm/standalone_call.sol:34:13-27"]
+	internal_function_70 [label="function() internal pure returns (int256)\nBABYLINK.singleReturn\ntests/contract_testcases/ewasm/standalone_call.sol:34:13-27"]
+	expr_71 [label="expression\ntests/contract_testcases/ewasm/standalone_call.sol:35:9-28"]
+	shift_left [label="shift left\nuint8\ntests/contract_testcases/ewasm/standalone_call.sol:35:11-13"]
+	number_literal_73 [label="uint8 literal: 1\ntests/contract_testcases/ewasm/standalone_call.sol:35:9-10"]
+	trunc [label="truncate uint8\ntests/contract_testcases/ewasm/standalone_call.sol:35:11-13"]
+	call_internal_function_75 [label="call internal function\ntests/contract_testcases/ewasm/standalone_call.sol:35:14-28"]
+	internal_function_76 [label="function() internal pure returns (int256)\nBABYLINK.singleReturn\ntests/contract_testcases/ewasm/standalone_call.sol:35:14-28"]
+	expr_77 [label="expression\ntests/contract_testcases/ewasm/standalone_call.sol:36:9-28"]
+	shift_right [label="shift right\nuint8\ntests/contract_testcases/ewasm/standalone_call.sol:36:11-13"]
+	number_literal_79 [label="uint8 literal: 1\ntests/contract_testcases/ewasm/standalone_call.sol:36:9-10"]
+	trunc_80 [label="truncate uint8\ntests/contract_testcases/ewasm/standalone_call.sol:36:11-13"]
+	call_internal_function_81 [label="call internal function\ntests/contract_testcases/ewasm/standalone_call.sol:36:14-28"]
+	internal_function_82 [label="function() internal pure returns (int256)\nBABYLINK.singleReturn\ntests/contract_testcases/ewasm/standalone_call.sol:36:14-28"]
+	expr_83 [label="expression\ntests/contract_testcases/ewasm/standalone_call.sol:37:9-22"]
+	not [label="not\ntests/contract_testcases/ewasm/standalone_call.sol:37:9-10"]
+	call_internal_function_85 [label="call internal function\ntests/contract_testcases/ewasm/standalone_call.sol:37:10-22"]
+	internal_function_86 [label="function() internal pure returns (bool)\nBABYLINK.returnBool\ntests/contract_testcases/ewasm/standalone_call.sol:37:10-22"]
+	expr_87 [label="expression\ntests/contract_testcases/ewasm/standalone_call.sol:38:9-24"]
+	complement [label="complement int256\ntests/contract_testcases/ewasm/standalone_call.sol:38:9-10"]
+	call_internal_function_89 [label="call internal function\ntests/contract_testcases/ewasm/standalone_call.sol:38:10-24"]
+	internal_function_90 [label="function() internal pure returns (int256)\nBABYLINK.singleReturn\ntests/contract_testcases/ewasm/standalone_call.sol:38:10-24"]
+	expr_91 [label="expression\ntests/contract_testcases/ewasm/standalone_call.sol:39:9-24"]
+	call_internal_function_92 [label="call internal function\ntests/contract_testcases/ewasm/standalone_call.sol:39:10-24"]
+	internal_function_93 [label="function() internal pure returns (int256)\nBABYLINK.singleReturn\ntests/contract_testcases/ewasm/standalone_call.sol:39:10-24"]
+	expr_94 [label="expression\ntests/contract_testcases/ewasm/standalone_call.sol:40:9-24"]
+	unary_minus [label="unary minus int256\ntests/contract_testcases/ewasm/standalone_call.sol:40:9-10"]
+	call_internal_function_96 [label="call internal function\ntests/contract_testcases/ewasm/standalone_call.sol:40:10-24"]
+	internal_function_97 [label="function() internal pure returns (int256)\nBABYLINK.singleReturn\ntests/contract_testcases/ewasm/standalone_call.sol:40:10-24"]
+	var_decl_98 [label="variable decl contract foo r\ntests/contract_testcases/ewasm/standalone_call.sol:41:9-26"]
+	constructor [label="constructor contract foo\ntests/contract_testcases/ewasm/standalone_call.sol:41:17-26"]
+	expr_100 [label="expression\ntests/contract_testcases/ewasm/standalone_call.sol:42:9-16"]
+	call_external_function [label="call external function\ntests/contract_testcases/ewasm/standalone_call.sol:42:9-16"]
+	external_function [label="function() external pure returns (void)\nfoo.bar\ntests/contract_testcases/ewasm/standalone_call.sol:42:9-16"]
+	variable_103 [label="variable: r\ncontract foo\ntests/contract_testcases/ewasm/standalone_call.sol:42:9-10"]
+	expr_104 [label="expression\ntests/contract_testcases/ewasm/standalone_call.sol:44:9-24"]
+	add_105 [label="add\nrational\ntests/contract_testcases/ewasm/standalone_call.sol:44:11-12"]
+	number_literal_106 [label="uint8 literal: 1\ntests/contract_testcases/ewasm/standalone_call.sol:44:9-10"]
+	add_107 [label="add\nrational\ntests/contract_testcases/ewasm/standalone_call.sol:44:18-19"]
+	rational_literal [label="rational rational literal: 13/10\ntests/contract_testcases/ewasm/standalone_call.sol:44:14-17"]
+	rational_literal_109 [label="rational rational literal: 9/5\ntests/contract_testcases/ewasm/standalone_call.sol:44:20-23"]
+	var_decl_110 [label="variable decl function(int256) external returns (int256,int256,int256) fptr\ntests/contract_testcases/ewasm/standalone_call.sol:46:9-83"]
+	cast [label="cast function(int256) external returns (int256,int256,int256)\ntests/contract_testcases/ewasm/standalone_call.sol:46:69-83"]
+	external_function_112 [label="function(int256) external pure returns (int256,int256,int256)\nBABYLINK.multipleRetuns\ntests/contract_testcases/ewasm/standalone_call.sol:46:69-83"]
+	builtins [label="builtin GetAddress\ntests/contract_testcases/ewasm/standalone_call.sol:46:64-68"]
+	var_decl_114 [label="variable decl function(int256) internal returns (int256,int256,int256) fptr2\ntests/contract_testcases/ewasm/standalone_call.sol:47:9-79"]
+	cast_115 [label="cast function(int256) internal returns (int256,int256,int256)\ntests/contract_testcases/ewasm/standalone_call.sol:47:65-79"]
+	internal_function_116 [label="function(int256) internal pure returns (int256,int256,int256)\nBABYLINK.multipleRetuns\ntests/contract_testcases/ewasm/standalone_call.sol:47:65-79"]
+	expr_117 [label="expression\ntests/contract_testcases/ewasm/standalone_call.sol:49:9-16"]
+	call_external_function_118 [label="call external function\ntests/contract_testcases/ewasm/standalone_call.sol:49:9-16"]
+	variable_119 [label="variable: fptr\nfunction(int256) external returns (int256,int256,int256)\ntests/contract_testcases/ewasm/standalone_call.sol:49:9-13"]
+	number_literal_120 [label="int256 literal: 3\ntests/contract_testcases/ewasm/standalone_call.sol:49:14-15"]
+	expr_121 [label="expression\ntests/contract_testcases/ewasm/standalone_call.sol:50:9-17"]
+	call_internal_function_122 [label="call internal function\ntests/contract_testcases/ewasm/standalone_call.sol:50:9-17"]
+	variable_123 [label="variable: fptr2\nfunction(int256) internal returns (int256,int256,int256)\ntests/contract_testcases/ewasm/standalone_call.sol:50:9-14"]
+	number_literal_124 [label="int256 literal: 3\ntests/contract_testcases/ewasm/standalone_call.sol:50:15-16"]
+	expr_125 [label="expression\ntests/contract_testcases/ewasm/standalone_call.sol:52:9-45"]
+	call_external_function_126 [label="call external function\ntests/contract_testcases/ewasm/standalone_call.sol:52:9-45"]
+	cast_127 [label="cast address\ntests/contract_testcases/ewasm/standalone_call.sol:52:9-22"]
+	builtins_128 [label="builtin GetAddress\ntests/contract_testcases/ewasm/standalone_call.sol:52:17-21"]
+	alloc_array [label="alloc array bytes\ninitializer: 6d756c7469706c65526574756e73\ntests/contract_testcases/ewasm/standalone_call.sol:52:28-44"]
+	number_literal_130 [label="uint32 literal: 14\ntests/contract_testcases/ewasm/standalone_call.sol:52:28-44"]
+	expr_131 [label="expression\ntests/contract_testcases/ewasm/standalone_call.sol:53:9-18"]
+	struct_literal [label="struct literal: struct BABYLINK.tts\ntests/contract_testcases/ewasm/standalone_call.sol:53:9-18"]
+	number_literal_133 [label="int256 literal: 1\ntests/contract_testcases/ewasm/standalone_call.sol:53:13-14"]
+	number_literal_134 [label="int256 literal: 2\ntests/contract_testcases/ewasm/standalone_call.sol:53:16-17"]
+	expr_135 [label="expression\ntests/contract_testcases/ewasm/standalone_call.sol:54:9-25"]
+	struct_literal_136 [label="struct literal: struct BABYLINK.tts\ntests/contract_testcases/ewasm/standalone_call.sol:54:9-25"]
+	number_literal_137 [label="int256 literal: 1\ntests/contract_testcases/ewasm/standalone_call.sol:54:17-18"]
+	number_literal_138 [label="int256 literal: 2\ntests/contract_testcases/ewasm/standalone_call.sol:54:22-23"]
+	return_139 [label="return\ntests/contract_testcases/ewasm/standalone_call.sol:56:9-17"]
+	variable_140 [label="variable: b\nint256\ntests/contract_testcases/ewasm/standalone_call.sol:56:16-17"]
+	diagnostic [label="found contract ‘foo’\nlevel Debug\ntests/contract_testcases/ewasm/standalone_call.sol:1:1-14"]
+	diagnostic_143 [label="found contract ‘BABYLINK’\nlevel Debug\ntests/contract_testcases/ewasm/standalone_call.sol:6:1-7:19"]
+	structs -> tts
+	contracts -> contract
+	contract -> bar [label="function"]
+	bar -> returns [label="returns"]
+	bar -> return [label="body"]
+	return -> list [label="expr"]
+	list -> number_literal [label="entry #0"]
+	list -> number_literal_9 [label="entry #1"]
+	contracts -> contract_10
+	contract_10 -> multipleRetuns [label="function"]
+	multipleRetuns -> parameters [label="parameters"]
+	multipleRetuns -> returns_13 [label="returns"]
+	multipleRetuns -> return_14 [label="body"]
+	return_14 -> list_15 [label="expr"]
+	list_15 -> number_literal_16 [label="entry #0"]
+	list_15 -> add [label="entry #1"]
+	add -> variable [label="left"]
+	add -> number_literal_19 [label="right"]
+	list_15 -> number_literal_20 [label="entry #2"]
+	contract_10 -> singleReturn [label="function"]
+	singleReturn -> returns_22 [label="returns"]
+	singleReturn -> return_23 [label="body"]
+	return_23 -> number_literal_24 [label="expr"]
+	contract_10 -> returnBool [label="function"]
+	returnBool -> returns_26 [label="returns"]
+	returnBool -> return_27 [label="body"]
+	return_27 -> bool_literal [label="expr"]
+	contract_10 -> testing [label="function"]
+	testing -> returns_30 [label="returns"]
+	testing -> expr [label="body"]
+	expr -> call_internal_function [label="expr"]
+	call_internal_function -> internal_function [label="function"]
+	call_internal_function -> number_literal_34 [label="arg #0"]
+	expr -> var_decl [label="next"]
+	var_decl -> number_literal_36 [label="init"]
+	var_decl -> expr_37 [label="next"]
+	expr_37 -> call_internal_function_38 [label="expr"]
+	call_internal_function_38 -> internal_function_39 [label="function"]
+	call_internal_function_38 -> number_literal_40 [label="arg #0"]
+	expr_37 -> expr_41 [label="next"]
+	expr_41 -> add_42 [label="expr"]
+	add_42 -> number_literal_43 [label="left"]
+	add_42 -> call_internal_function_44 [label="right"]
+	call_internal_function_44 -> internal_function_45 [label="function"]
+	expr_41 -> expr_46 [label="next"]
+	expr_46 -> subtract [label="expr"]
+	subtract -> number_literal_48 [label="left"]
+	subtract -> call_internal_function_49 [label="right"]
+	call_internal_function_49 -> internal_function_50 [label="function"]
+	expr_46 -> expr_51 [label="next"]
+	expr_51 -> multiply [label="expr"]
+	multiply -> number_literal_53 [label="left"]
+	multiply -> call_internal_function_54 [label="right"]
+	call_internal_function_54 -> internal_function_55 [label="function"]
+	expr_51 -> expr_56 [label="next"]
+	expr_56 -> divide [label="expr"]
+	divide -> number_literal_58 [label="left"]
+	divide -> call_internal_function_59 [label="right"]
+	call_internal_function_59 -> internal_function_60 [label="function"]
+	expr_56 -> expr_61 [label="next"]
+	expr_61 -> bitwise_or [label="expr"]
+	bitwise_or -> number_literal_63 [label="left"]
+	bitwise_or -> call_internal_function_64 [label="right"]
+	call_internal_function_64 -> internal_function_65 [label="function"]
+	expr_61 -> expr_66 [label="next"]
+	expr_66 -> bitwise_and [label="expr"]
+	bitwise_and -> number_literal_68 [label="left"]
+	bitwise_and -> call_internal_function_69 [label="right"]
+	call_internal_function_69 -> internal_function_70 [label="function"]
+	expr_66 -> expr_71 [label="next"]
+	expr_71 -> shift_left [label="expr"]
+	shift_left -> number_literal_73 [label="left"]
+	shift_left -> trunc [label="right"]
+	trunc -> call_internal_function_75 [label="expr"]
+	call_internal_function_75 -> internal_function_76 [label="function"]
+	expr_71 -> expr_77 [label="next"]
+	expr_77 -> shift_right [label="expr"]
+	shift_right -> number_literal_79 [label="left"]
+	shift_right -> trunc_80 [label="right"]
+	trunc_80 -> call_internal_function_81 [label="expr"]
+	call_internal_function_81 -> internal_function_82 [label="function"]
+	expr_77 -> expr_83 [label="next"]
+	expr_83 -> not [label="expr"]
+	not -> call_internal_function_85 [label="expr"]
+	call_internal_function_85 -> internal_function_86 [label="function"]
+	expr_83 -> expr_87 [label="next"]
+	expr_87 -> complement [label="expr"]
+	complement -> call_internal_function_89 [label="expr"]
+	call_internal_function_89 -> internal_function_90 [label="function"]
+	expr_87 -> expr_91 [label="next"]
+	expr_91 -> call_internal_function_92 [label="expr"]
+	call_internal_function_92 -> internal_function_93 [label="function"]
+	expr_91 -> expr_94 [label="next"]
+	expr_94 -> unary_minus [label="expr"]
+	unary_minus -> call_internal_function_96 [label="expr"]
+	call_internal_function_96 -> internal_function_97 [label="function"]
+	expr_94 -> var_decl_98 [label="next"]
+	var_decl_98 -> constructor [label="init"]
+	var_decl_98 -> expr_100 [label="next"]
+	expr_100 -> call_external_function [label="expr"]
+	call_external_function -> external_function [label="function"]
+	external_function -> variable_103 [label="address"]
+	expr_100 -> expr_104 [label="next"]
+	expr_104 -> add_105 [label="expr"]
+	add_105 -> number_literal_106 [label="left"]
+	add_105 -> add_107 [label="right"]
+	add_107 -> rational_literal [label="left"]
+	add_107 -> rational_literal_109 [label="right"]
+	expr_104 -> var_decl_110 [label="next"]
+	var_decl_110 -> cast [label="init"]
+	cast -> external_function_112 [label="expr"]
+	external_function_112 -> builtins [label="address"]
+	var_decl_110 -> var_decl_114 [label="next"]
+	var_decl_114 -> cast_115 [label="init"]
+	cast_115 -> internal_function_116 [label="expr"]
+	var_decl_114 -> expr_117 [label="next"]
+	expr_117 -> call_external_function_118 [label="expr"]
+	call_external_function_118 -> variable_119 [label="function"]
+	call_external_function_118 -> number_literal_120 [label="arg #0"]
+	expr_117 -> expr_121 [label="next"]
+	expr_121 -> call_internal_function_122 [label="expr"]
+	call_internal_function_122 -> variable_123 [label="function"]
+	call_internal_function_122 -> number_literal_124 [label="arg #0"]
+	expr_121 -> expr_125 [label="next"]
+	expr_125 -> call_external_function_126 [label="expr"]
+	call_external_function_126 -> cast_127 [label="address"]
+	cast_127 -> builtins_128 [label="expr"]
+	call_external_function_126 -> alloc_array [label="args"]
+	alloc_array -> number_literal_130 [label="length"]
+	expr_125 -> expr_131 [label="next"]
+	expr_131 -> struct_literal [label="expr"]
+	struct_literal -> number_literal_133 [label="arg #0"]
+	struct_literal -> number_literal_134 [label="arg #1"]
+	expr_131 -> expr_135 [label="next"]
+	expr_135 -> struct_literal_136 [label="expr"]
+	struct_literal_136 -> number_literal_137 [label="arg #0"]
+	struct_literal_136 -> number_literal_138 [label="arg #1"]
+	expr_135 -> return_139 [label="next"]
+	return_139 -> variable_140 [label="expr"]
+	diagnostics -> diagnostic [label="Debug"]
+	diagnostics -> diagnostic_143 [label="Debug"]
+}

+ 58 - 0
tests/contract_testcases/ewasm/standalone_call.sol

@@ -0,0 +1,58 @@
+contract foo {
+    function bar() public pure returns (int, int) {
+        return (1, 2);
+    }
+}
+
+contract BABYLINK { 
+    struct tts{
+        int a;
+        int b;
+    }
+
+    function multipleRetuns(int c) public pure returns (int, int, int) {
+        return (1, c + 2, 3);
+    }
+
+    function singleReturn() private pure returns (int) {
+        return 3;
+    }
+
+    function returnBool() private pure returns (bool) {
+        return true;
+    }
+    
+    function testing() public returns (int) {
+        multipleRetuns(3); 
+        int b = 5;
+        multipleRetuns({c: 9});
+        1 + singleReturn();
+        1 - singleReturn();
+        1 * singleReturn();
+        1 / singleReturn();
+        1 | singleReturn();
+        1 & singleReturn();
+        1 << singleReturn();
+        1 >> singleReturn();
+        !returnBool();
+        ~singleReturn();
+        +singleReturn();
+        -singleReturn();
+        foo r = new foo();
+        r.bar();
+
+        1 + (1.3 + 1.8);
+
+        function (int) external returns (int, int, int) fptr = this.multipleRetuns;
+        function (int) internal returns (int, int, int) fptr2 = multipleRetuns;
+
+        fptr(3);
+        fptr2(3);
+
+        address(this).call("multipleRetuns");
+        tts(1, 2);
+        tts({a: 1, b:2});
+
+        return b;
+    }
+}

+ 1 - 1
tests/ewasm.rs

@@ -2284,7 +2284,7 @@ fn selfdestruct() {
             }
 
             function step2() public {
-                o.goaway(payable(address(this)));
+                bool foo = o.goaway(payable(address(this)));
             }
         }"##,
     );