From 093b9ced97729c84d17eb549f0c63e2736c987f9 Mon Sep 17 00:00:00 2001 From: Mathias Baumann Date: Tue, 12 Feb 2019 16:09:16 +0100 Subject: [PATCH] Make sure "value" error hint is only displayed in the right context Before, the hint would be shown for any "value" member, even a user-specified one. --- libsolidity/analysis/TypeChecker.cpp | 28 +++++++++++-------- .../SolidityNameAndTypeResolution.cpp | 2 +- .../call_value_on_non_constructor.sol | 7 +++++ ...all_value_on_non_payable_function_type.sol | 2 +- ...97_library_functions_do_not_have_value.sol | 2 +- .../362_calling_nonpayable.sol | 2 +- .../363_non_payable_constructor.sol | 2 +- .../502_builtin_keccak256_reject_value.sol | 2 +- .../503_builtin_sha256_reject_value.sol | 2 +- .../504_builtin_ripemd160_reject_value.sol | 2 +- .../505_builtin_ecrecover_reject_value.sol | 2 +- 11 files changed, 32 insertions(+), 21 deletions(-) create mode 100644 test/libsolidity/syntaxTests/functionTypes/call_value_on_non_constructor.sol diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index ce1910129..8c89f249d 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -2046,20 +2046,24 @@ bool TypeChecker::visit(MemberAccess const& _memberAccess) } string errorMsg = "Member \"" + memberName + "\" not found or not visible " "after argument-dependent lookup in " + exprType->toString() + "."; - if (memberName == "value") - { - errorMsg.pop_back(); - errorMsg += " - did you forget the \"payable\" modifier?"; - } - else if (auto const& funType = dynamic_pointer_cast(exprType)) + + if (auto const& funType = dynamic_pointer_cast(exprType)) { auto const& t = funType->returnParameterTypes(); - if (t.size() == 1) - if ( - t.front()->category() == Type::Category::Contract || - t.front()->category() == Type::Category::Struct - ) - errorMsg += " Did you intend to call the function?"; + + if (memberName == "value") + { + if (funType->kind() == FunctionType::Kind::Creation) + errorMsg = "Constructor for " + t.front()->toString() + " must be payable for member \"value\" to be available."; + else + errorMsg = "Member \"value\" is only available for payable functions."; + } + else if ( + t.size() == 1 && + (t.front()->category() == Type::Category::Struct || + t.front()->category() == Type::Category::Contract) + ) + errorMsg += " Did you intend to call the function?"; } else if (exprType->category() == Type::Category::Contract) { diff --git a/test/libsolidity/SolidityNameAndTypeResolution.cpp b/test/libsolidity/SolidityNameAndTypeResolution.cpp index 0470cf4c1..9bda24442 100644 --- a/test/libsolidity/SolidityNameAndTypeResolution.cpp +++ b/test/libsolidity/SolidityNameAndTypeResolution.cpp @@ -471,7 +471,7 @@ BOOST_AUTO_TEST_CASE(address_staticcall_value) } } )"; - CHECK_ERROR(sourceCode, TypeError, "Member \"value\" not found or not visible after argument-dependent lookup"); + CHECK_ERROR(sourceCode, TypeError, "Member \"value\" is only available for payable functions."); } } diff --git a/test/libsolidity/syntaxTests/functionTypes/call_value_on_non_constructor.sol b/test/libsolidity/syntaxTests/functionTypes/call_value_on_non_constructor.sol new file mode 100644 index 000000000..f289354f5 --- /dev/null +++ b/test/libsolidity/syntaxTests/functionTypes/call_value_on_non_constructor.sol @@ -0,0 +1,7 @@ +contract C { + // Tests that we don't get a wrong error about constructors + function f() public view returns (C) { return this; } + function g() public { this.f.value(); } +} +// ---- +// TypeError: (155-167): Member "value" is only available for payable functions. diff --git a/test/libsolidity/syntaxTests/functionTypes/call_value_on_non_payable_function_type.sol b/test/libsolidity/syntaxTests/functionTypes/call_value_on_non_payable_function_type.sol index 87c3b05b1..5efdf2407 100644 --- a/test/libsolidity/syntaxTests/functionTypes/call_value_on_non_payable_function_type.sol +++ b/test/libsolidity/syntaxTests/functionTypes/call_value_on_non_payable_function_type.sol @@ -5,4 +5,4 @@ contract C { } } // ---- -// TypeError: (94-101): Member "value" not found or not visible after argument-dependent lookup in function (uint256) external returns (uint256) - did you forget the "payable" modifier? +// TypeError: (94-101): Member "value" is only available for payable functions. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/297_library_functions_do_not_have_value.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/297_library_functions_do_not_have_value.sol index 918544cc0..dfb706417 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/297_library_functions_do_not_have_value.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/297_library_functions_do_not_have_value.sol @@ -5,4 +5,4 @@ contract test { } } // ---- -// TypeError: (87-96): Member "value" not found or not visible after argument-dependent lookup in function () - did you forget the "payable" modifier? +// TypeError: (87-96): Member "value" is only available for payable functions. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/362_calling_nonpayable.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/362_calling_nonpayable.sol index d47ea2bd5..1c04be755 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/362_calling_nonpayable.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/362_calling_nonpayable.sol @@ -3,4 +3,4 @@ contract test { function f() public { (new receiver()).nopay.value(10)(); } } // ---- -// TypeError: (91-119): Member "value" not found or not visible after argument-dependent lookup in function () external - did you forget the "payable" modifier? +// TypeError: (91-119): Member "value" is only available for payable functions. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/363_non_payable_constructor.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/363_non_payable_constructor.sol index 273819047..944bda0d9 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/363_non_payable_constructor.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/363_non_payable_constructor.sol @@ -8,4 +8,4 @@ contract D { } } // ---- -// TypeError: (106-119): Member "value" not found or not visible after argument-dependent lookup in function () returns (contract C) - did you forget the "payable" modifier? +// TypeError: (106-119): Constructor for contract C must be payable for member "value" to be available. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/502_builtin_keccak256_reject_value.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/502_builtin_keccak256_reject_value.sol index 61e51eff6..0b214822e 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/502_builtin_keccak256_reject_value.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/502_builtin_keccak256_reject_value.sol @@ -4,4 +4,4 @@ contract C { } } // ---- -// TypeError: (47-62): Member "value" not found or not visible after argument-dependent lookup in function (bytes memory) pure returns (bytes32) - did you forget the "payable" modifier? +// TypeError: (47-62): Member "value" is only available for payable functions. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/503_builtin_sha256_reject_value.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/503_builtin_sha256_reject_value.sol index 11141a9b9..5d8e0aecd 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/503_builtin_sha256_reject_value.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/503_builtin_sha256_reject_value.sol @@ -4,4 +4,4 @@ contract C { } } // ---- -// TypeError: (47-59): Member "value" not found or not visible after argument-dependent lookup in function (bytes memory) pure returns (bytes32) - did you forget the "payable" modifier? +// TypeError: (47-59): Member "value" is only available for payable functions. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/504_builtin_ripemd160_reject_value.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/504_builtin_ripemd160_reject_value.sol index d120f3ddd..d03e55b1b 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/504_builtin_ripemd160_reject_value.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/504_builtin_ripemd160_reject_value.sol @@ -4,4 +4,4 @@ contract C { } } // ---- -// TypeError: (47-62): Member "value" not found or not visible after argument-dependent lookup in function (bytes memory) pure returns (bytes20) - did you forget the "payable" modifier? +// TypeError: (47-62): Member "value" is only available for payable functions. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/505_builtin_ecrecover_reject_value.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/505_builtin_ecrecover_reject_value.sol index e0215901a..2a31934f3 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/505_builtin_ecrecover_reject_value.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/505_builtin_ecrecover_reject_value.sol @@ -4,4 +4,4 @@ contract C { } } // ---- -// TypeError: (47-62): Member "value" not found or not visible after argument-dependent lookup in function (bytes32,uint8,bytes32,bytes32) pure returns (address) - did you forget the "payable" modifier? +// TypeError: (47-62): Member "value" is only available for payable functions.