Changes deprecation and adjusts tests.

This commit is contained in:
bitshift 2018-03-07 10:48:10 +01:00 committed by Alex Beregszaszi
parent bddfa47e77
commit 2c56e53046
5 changed files with 76 additions and 59 deletions

View File

@ -142,6 +142,7 @@ bool StaticAnalyzer::visit(MemberAccess const& _memberAccess)
bool const v050 = m_currentContract->sourceUnit().annotation().experimentalFeatures.count(ExperimentalFeature::V050); bool const v050 = m_currentContract->sourceUnit().annotation().experimentalFeatures.count(ExperimentalFeature::V050);
if (MagicType const* type = dynamic_cast<MagicType const*>(_memberAccess.expression().annotation().type.get())) if (MagicType const* type = dynamic_cast<MagicType const*>(_memberAccess.expression().annotation().type.get()))
{
if (type->kind() == MagicType::Kind::Message && _memberAccess.memberName() == "gas") if (type->kind() == MagicType::Kind::Message && _memberAccess.memberName() == "gas")
{ {
if (v050) if (v050)
@ -155,6 +156,20 @@ bool StaticAnalyzer::visit(MemberAccess const& _memberAccess)
"\"msg.gas\" has been deprecated in favor of \"gasleft()\"" "\"msg.gas\" has been deprecated in favor of \"gasleft()\""
); );
} }
if (type->kind() == MagicType::Kind::Block && _memberAccess.memberName() == "blockhash")
{
if (v050)
m_errorReporter.typeError(
_memberAccess.location(),
"\"block.blockhash()\" has been deprecated in favor of \"blockhash()\""
);
else
m_errorReporter.warning(
_memberAccess.location(),
"\"block.blockhash()\" has been deprecated in favor of \"blockhash()\""
);
}
}
if (m_nonPayablePublic && !m_library) if (m_nonPayablePublic && !m_library)
if (MagicType const* type = dynamic_cast<MagicType const*>(_memberAccess.expression().annotation().type.get())) if (MagicType const* type = dynamic_cast<MagicType const*>(_memberAccess.expression().annotation().type.get()))

View File

@ -3002,30 +3002,19 @@ bool MagicType::operator==(Type const& _other) const
return other.m_kind == m_kind; return other.m_kind == m_kind;
} }
MemberList::MemberMap MagicType::nativeMembers(ContractDefinition const* _contract) const MemberList::MemberMap MagicType::nativeMembers(ContractDefinition const*) const
{ {
const bool v050 = _contract->sourceUnit().annotation().experimentalFeatures.count(ExperimentalFeature::V050);
switch (m_kind) switch (m_kind)
{ {
case Kind::Block: case Kind::Block:
{ return MemberList::MemberMap({
std::vector<MemberList::Member> members = { {"coinbase", make_shared<IntegerType>(160, IntegerType::Modifier::Address)},
{"coinbase", make_shared<IntegerType>(160, IntegerType::Modifier::Address)}, {"timestamp", make_shared<IntegerType>(256)},
{"timestamp", make_shared<IntegerType>(256)}, {"blockhash", make_shared<FunctionType>(strings{"uint"}, strings{"bytes32"}, FunctionType::Kind::BlockHash, false, StateMutability::View)},
{"difficulty", make_shared<IntegerType>(256)}, {"difficulty", make_shared<IntegerType>(256)},
{"number", make_shared<IntegerType>(256)}, {"number", make_shared<IntegerType>(256)},
{"gaslimit", make_shared<IntegerType>(256)} {"gaslimit", make_shared<IntegerType>(256)}
}; });
if (!v050)
{
auto blockhashFun = make_shared<FunctionType>(strings{"uint256"}, strings{"bytes32"},
FunctionType::Kind::BlockHash, false, StateMutability::View);
members.emplace_back("blockhash", blockhashFun);
}
return MemberList::MemberMap(members);
}
case Kind::Message: case Kind::Message:
return MemberList::MemberMap({ return MemberList::MemberMap({
{"sender", make_shared<IntegerType>(160, IntegerType::Modifier::Address)}, {"sender", make_shared<IntegerType>(160, IntegerType::Modifier::Address)},

View File

@ -1805,33 +1805,16 @@ BOOST_AUTO_TEST_CASE(uncalled_blockhash)
BOOST_CHECK(result[0] != 0 || result[1] != 0 || result[2] != 0); BOOST_CHECK(result[0] != 0 || result[1] != 0 || result[2] != 0);
} }
BOOST_AUTO_TEST_CASE(blockhash_global_level) BOOST_AUTO_TEST_CASE(blockhash_shadow_resolution)
{ {
char const* sourceCode = R"( char const* code = R"(
contract Test { contract C {
function a() public returns (bytes32) { function blockhash(uint256 blockNumber) public returns(bytes32) { bytes32 x; return x; }
return blockhash(0); function f() public returns(bytes32) { return blockhash(3); }
}
} }
)"; )";
compileAndRun(sourceCode); compileAndRun(code, 0, "C");
BOOST_CHECK(!callContractFunction("a()").empty()); ABI_CHECK(callContractFunction("f()"), encodeArgs(0));
}
BOOST_AUTO_TEST_CASE(blockhash_shadow)
{
char const* sourceCode = R"(
contract Test {
function blockhash(uint256 blockNumber) public returns (bytes32) {
return "abc";
}
function f() returns (bytes32) {
return blockhash(3);
}
}
)";
compileAndRun(sourceCode);
BOOST_REQUIRE(callContractFunction("f()") != encodeArgs("abc"));
} }
BOOST_AUTO_TEST_CASE(log0) BOOST_AUTO_TEST_CASE(log0)

View File

@ -8555,16 +8555,31 @@ BOOST_AUTO_TEST_CASE(require_visibility_specifiers)
CHECK_ERROR(text, SyntaxError, "No visibility specified."); CHECK_ERROR(text, SyntaxError, "No visibility specified.");
} }
BOOST_AUTO_TEST_CASE(blockhash_not_available_in_block) BOOST_AUTO_TEST_CASE(blockhash)
{ {
char const* text = R"( char const* code = R"(
contract Test { contract C {
function a() public returns (bytes32) { function f() public view returns (bytes32) {
return block.blockhash(0); return block.blockhash(3);
} }
} }
)"; )";
CHECK_ERROR(text, TypeError, "Member \"blockhash\" not found or not visible after argument-dependent lookup in block"); CHECK_WARNING(code, "\"block.blockhash()\" has been deprecated in favor of \"blockhash()\"");
code = R"(
contract C {
function f() public view returns (bytes32) { return blockhash(3); }
}
)";
CHECK_SUCCESS_NO_WARNINGS(code);
code = R"(
pragma experimental "v0.5.0";
contract C {
function f() public returns (bytes32) { return block.blockhash(3); }
}
)";
CHECK_ERROR(code, TypeError, "\"block.blockhash()\" has been deprecated in favor of \"blockhash()\"");
} }
BOOST_AUTO_TEST_SUITE_END() BOOST_AUTO_TEST_SUITE_END()

View File

@ -25,6 +25,7 @@
#include <boost/test/unit_test.hpp> #include <boost/test/unit_test.hpp>
#include <string> #include <string>
#include <tuple>
using namespace std; using namespace std;
@ -107,9 +108,11 @@ BOOST_AUTO_TEST_CASE(environment_access)
vector<string> view{ vector<string> view{
"block.coinbase", "block.coinbase",
"block.timestamp", "block.timestamp",
"block.blockhash(7)",
"block.difficulty", "block.difficulty",
"block.number", "block.number",
"block.gaslimit", "block.gaslimit",
"blockhash(7)",
"gasleft()", "gasleft()",
"msg.gas", "msg.gas",
"msg.value", "msg.value",
@ -117,35 +120,47 @@ BOOST_AUTO_TEST_CASE(environment_access)
"tx.origin", "tx.origin",
"tx.gasprice", "tx.gasprice",
"this", "this",
"blockhash(7)",
"address(1).balance" "address(1).balance"
}; };
// ``block.blockhash`` and ``blockhash`` are tested seperately below because their usage will
// produce warnings that can't be handled in a generic way.
vector<string> pure{ vector<string> pure{
"msg.data", "msg.data",
"msg.data[0]", "msg.data[0]",
"msg.sig", "msg.sig",
"msg", "msg",
"block", "block",
"blockhash", // Not evaluating the function
"tx" "tx"
}; };
for (string const& x: view) for (string const& x: view)
{ {
CHECK_ERROR( CHECK_ERROR(
"contract C { function f() pure public { var x = " + x + "; x; } }", "contract C { function f() pure public { " + x + "; } }",
TypeError, TypeError,
"Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires \"view\"" "Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires \"view\""
); );
} }
for (string const& x: pure) for (string const& x: pure)
{ {
CHECK_WARNING_ALLOW_MULTI( CHECK_WARNING(
"contract C { function f() view public { var x = " + x + "; x; } }", "contract C { function f() view public { " + x + "; } }",
(std::vector<std::string>{ "Function state mutability can be restricted to pure"
"Function state mutability can be restricted to pure", );
"Use of the \"var\" keyword is deprecated."
}));
} }
CHECK_WARNING_ALLOW_MULTI(
"contract C { function f() view public { blockhash; } }",
(std::vector<std::string>{
"Function state mutability can be restricted to pure",
"Statement has no effect."
}));
CHECK_WARNING_ALLOW_MULTI(
"contract C { function f() view public { block.blockhash; } }",
(std::vector<std::string>{
"Function state mutability can be restricted to pure",
"\"block.blockhash()\" has been deprecated in favor of \"blockhash()\""
}));
} }
BOOST_AUTO_TEST_CASE(view_error_for_050) BOOST_AUTO_TEST_CASE(view_error_for_050)