Ver código fonte

Give nice diagnostics when old style call arguments are used (#1107)

Give nice diagnostics when old stlye call arguments are used

	C c = (new C).value(1).gas(2)(1, 2, 3);

Fixes https://github.com/xermicus/fuzzy-sol/issues/141

Signed-off-by: Sean Young <sean@mess.org>
Co-authored-by: Cyrill Leutwiler <bigcyrill@hotmail.com>
Co-authored-by: Lucas Steuernagel <38472950+LucasSte@users.noreply.github.com>
Sean Young 2 anos atrás
pai
commit
4588c7f6f4

+ 59 - 11
src/sema/expression.rs

@@ -2217,7 +2217,20 @@ pub fn expression(
 
                     res
                 }
-                _ => unreachable!(),
+                pt::Expression::Variable(id) => {
+                    diagnostics.push(Diagnostic::error(
+                        *loc,
+                        format!("missing constructor arguments to {}", id.name),
+                    ));
+                    Err(())
+                }
+                expr => {
+                    diagnostics.push(Diagnostic::error(
+                        expr.loc(),
+                        "type with arguments expected".into(),
+                    ));
+                    Err(())
+                }
             }
         }
         pt::Expression::Delete(loc, _) => {
@@ -7861,16 +7874,20 @@ pub fn call_expr(
         {
             new(loc, ty, args, context, ns, symtable, diagnostics)?
         }
-        _ => function_call_expr(
-            loc,
-            ty,
-            args,
-            context,
-            ns,
-            symtable,
-            diagnostics,
-            resolve_to,
-        )?,
+        _ => {
+            deprecated_constructor_arguments(ty, diagnostics)?;
+
+            function_call_expr(
+                loc,
+                ty,
+                args,
+                context,
+                ns,
+                symtable,
+                diagnostics,
+                resolve_to,
+            )?
+        }
     };
 
     check_function_call(ns, &expr, symtable);
@@ -7885,6 +7902,37 @@ pub fn call_expr(
     Ok(expr)
 }
 
+/// Is it an (new C).value(1).gas(2)(1, 2, 3) style constructor (not supported)?
+fn deprecated_constructor_arguments(
+    expr: &pt::Expression,
+    diagnostics: &mut Diagnostics,
+) -> Result<(), ()> {
+    match expr.remove_parenthesis() {
+        pt::Expression::FunctionCall(func_loc, ty, _) => {
+            if let pt::Expression::MemberAccess(_, ty, call_arg) = ty.as_ref() {
+                if deprecated_constructor_arguments(ty, diagnostics).is_err() {
+                    // location should be the identifier and the arguments
+                    let mut loc = call_arg.loc;
+                    if let pt::Loc::File(_, _, end) = &mut loc {
+                        *end = func_loc.end();
+                    }
+                    diagnostics.push(Diagnostic::error(
+                        loc,
+                        format!("deprecated call argument syntax '.{}(...)' is not supported, use '{{{}: ...}}' instead", call_arg.name, call_arg.name)
+                    ));
+                    return Err(());
+                }
+            }
+        }
+        pt::Expression::New(..) => {
+            return Err(());
+        }
+        _ => (),
+    }
+
+    Ok(())
+}
+
 /// Resolve function call
 pub fn function_call_expr(
     loc: &pt::Loc,

+ 26 - 0
tests/contract_testcases/evm/old_style_call_args.dot

@@ -0,0 +1,26 @@
+strict digraph "tests/contract_testcases/evm/old_style_call_args.sol" {
+	contract [label="contract c\ntests/contract_testcases/evm/old_style_call_args.sol:1:1-13:2"]
+	foo [label="function foo\ncontract: c\ntests/contract_testcases/evm/old_style_call_args.sol:2:2-23\nsignature foo()\nvisibility public\nmutability nonpayable"]
+	bar [label="function bar\ncontract: c\ntests/contract_testcases/evm/old_style_call_args.sol:6:2-23\nsignature bar()\nvisibility public\nmutability nonpayable"]
+	baz [label="function baz\ncontract: c\ntests/contract_testcases/evm/old_style_call_args.sol:10:2-23\nsignature baz()\nvisibility public\nmutability nonpayable"]
+	contract_5 [label="contract d\ntests/contract_testcases/evm/old_style_call_args.sol:15:1-14"]
+	diagnostic [label="found contract 'c'\nlevel Debug\ntests/contract_testcases/evm/old_style_call_args.sol:1:1-13:2"]
+	diagnostic_8 [label="deprecated call argument syntax '.value(...)' is not supported, use '{value: ...}' instead\nlevel Error\ntests/contract_testcases/evm/old_style_call_args.sol:3:17-25"]
+	diagnostic_9 [label="deprecated call argument syntax '.gas(...)' is not supported, use '{gas: ...}' instead\nlevel Error\ntests/contract_testcases/evm/old_style_call_args.sol:3:26-32"]
+	diagnostic_10 [label="deprecated call argument syntax '.foo(...)' is not supported, use '{foo: ...}' instead\nlevel Error\ntests/contract_testcases/evm/old_style_call_args.sol:3:33-39"]
+	diagnostic_11 [label="type with arguments expected\nlevel Error\ntests/contract_testcases/evm/old_style_call_args.sol:7:13-14"]
+	diagnostic_12 [label="missing constructor arguments to d\nlevel Error\ntests/contract_testcases/evm/old_style_call_args.sol:11:9-14"]
+	diagnostic_13 [label="found contract 'd'\nlevel Debug\ntests/contract_testcases/evm/old_style_call_args.sol:15:1-14"]
+	contracts -> contract
+	contract -> foo [label="function"]
+	contract -> bar [label="function"]
+	contract -> baz [label="function"]
+	contracts -> contract_5
+	diagnostics -> diagnostic [label="Debug"]
+	diagnostics -> diagnostic_8 [label="Error"]
+	diagnostics -> diagnostic_9 [label="Error"]
+	diagnostics -> diagnostic_10 [label="Error"]
+	diagnostics -> diagnostic_11 [label="Error"]
+	diagnostics -> diagnostic_12 [label="Error"]
+	diagnostics -> diagnostic_13 [label="Debug"]
+}

+ 15 - 0
tests/contract_testcases/evm/old_style_call_args.sol

@@ -0,0 +1,15 @@
+contract c {
+	function foo() public {
+		d x = (new d).value(1).gas(2).foo(3)();
+	}
+
+	function bar() public {
+		d x = new 1;
+	}
+
+	function baz() public {
+		d x = new d;
+	}
+}
+
+contract d {}