Enforce view with error for experimental 0.5.0.

This commit is contained in:
chriseth 2017-09-14 17:53:43 +02:00
parent 1c85ba10e1
commit 24fd67b7db
4 changed files with 35 additions and 11 deletions

View File

@ -9,6 +9,7 @@ Features:
* Type Checker: Greatly reduce the number of duplicate errors shown for duplicate constructors and functions. * Type Checker: Greatly reduce the number of duplicate errors shown for duplicate constructors and functions.
* Type Checker: Warn on using literals as tight packing parameters in ``keccak256``, ``sha3``, ``sha256`` and ``ripemd160``. * Type Checker: Warn on using literals as tight packing parameters in ``keccak256``, ``sha3``, ``sha256`` and ``ripemd160``.
* Type Checker: Enforce ``view`` and ``pure``. * Type Checker: Enforce ``view`` and ``pure``.
* Type Checker: Enforce ``view`` / ``constant`` with error as experimental 0.5.0 feature.
Bugfixes: Bugfixes:
* ABI JSON: Include all overloaded events. * ABI JSON: Include all overloaded events.

View File

@ -20,6 +20,7 @@
#include <libevmasm/SemanticInformation.h> #include <libevmasm/SemanticInformation.h>
#include <libsolidity/inlineasm/AsmData.h> #include <libsolidity/inlineasm/AsmData.h>
#include <libsolidity/ast/ExperimentalFeatures.h>
#include <functional> #include <functional>
@ -102,22 +103,31 @@ private:
bool ViewPureChecker::check() bool ViewPureChecker::check()
{ {
vector<ContractDefinition const*> contracts; // The bool means "enforce view with errors".
map<ContractDefinition const*, bool> contracts;
for (auto const& node: m_ast) for (auto const& node: m_ast)
{ {
SourceUnit const* source = dynamic_cast<SourceUnit const*>(node.get()); SourceUnit const* source = dynamic_cast<SourceUnit const*>(node.get());
solAssert(source, ""); solAssert(source, "");
contracts += source->filteredNodes<ContractDefinition>(source->nodes()); bool enforceView = source->annotation().experimentalFeatures.count(ExperimentalFeature::V050);
for (ContractDefinition const* c: source->filteredNodes<ContractDefinition>(source->nodes()))
contracts[c] = enforceView;
} }
// Check modifiers first to infer their state mutability. // Check modifiers first to infer their state mutability.
for (auto const* contract: contracts) for (auto const& contract: contracts)
for (ModifierDefinition const* mod: contract->functionModifiers()) {
m_enforceViewWithError = contract.second;
for (ModifierDefinition const* mod: contract.first->functionModifiers())
mod->accept(*this); mod->accept(*this);
}
for (auto const* contract: contracts) for (auto const& contract: contracts)
contract->accept(*this); {
m_enforceViewWithError = contract.second;
contract.first->accept(*this);
}
return !m_errors; return !m_errors;
} }
@ -223,16 +233,18 @@ void ViewPureChecker::reportMutability(StateMutability _mutability, SourceLocati
else else
solAssert(false, ""); solAssert(false, "");
if (m_currentFunction->stateMutability() == StateMutability::View) solAssert(
// TODO Change this to error with 0.5.0 m_currentFunction->stateMutability() == StateMutability::View ||
m_currentFunction->stateMutability() == StateMutability::Pure,
""
);
if (!m_enforceViewWithError && m_currentFunction->stateMutability() == StateMutability::View)
m_errorReporter.warning(_location, text); m_errorReporter.warning(_location, text);
else if (m_currentFunction->stateMutability() == StateMutability::Pure) else
{ {
m_errors = true; m_errors = true;
m_errorReporter.typeError(_location, text); m_errorReporter.typeError(_location, text);
} }
else
solAssert(false, "");
} }
if (_mutability > m_currentBestMutability) if (_mutability > m_currentBestMutability)
m_currentBestMutability = _mutability; m_currentBestMutability = _mutability;

View File

@ -70,6 +70,7 @@ private:
ErrorReporter& m_errorReporter; ErrorReporter& m_errorReporter;
bool m_errors = false; bool m_errors = false;
bool m_enforceViewWithError = false;
StateMutability m_currentBestMutability = StateMutability::Payable; StateMutability m_currentBestMutability = StateMutability::Payable;
FunctionDefinition const* m_currentFunction = nullptr; FunctionDefinition const* m_currentFunction = nullptr;
std::map<ModifierDefinition const*, StateMutability> m_inferredMutability; std::map<ModifierDefinition const*, StateMutability> m_inferredMutability;

View File

@ -143,6 +143,16 @@ BOOST_AUTO_TEST_CASE(environment_access)
} }
} }
BOOST_AUTO_TEST_CASE(view_error_for_050)
{
CHECK_ERROR(
"pragma experimental \"v0.5.0\"; contract C { uint x; function f() view { x = 2; } }",
TypeError,
"Function declared as view, but this expression (potentially) modifies the state and thus requires non-payable (the default) or payable."
);
}
BOOST_AUTO_TEST_CASE(modifiers) BOOST_AUTO_TEST_CASE(modifiers)
{ {
string text = R"( string text = R"(