Browse Source

Merge remote-tracking branch 'ethereum/develop' into sol_optimizer

cl-refactor
Christian 10 years ago
parent
commit
a3eeb47820
  1. 20
      libsolidity/AST.cpp
  2. 4
      libsolidity/AST.h
  3. 6
      libsolidity/Compiler.cpp
  4. 49
      test/solidityEndToEndTest.cpp

20
libsolidity/AST.cpp

@ -283,14 +283,6 @@ void WhileStatement::checkTypeRequirements()
m_body->checkTypeRequirements(); m_body->checkTypeRequirements();
} }
void Continue::checkTypeRequirements()
{
}
void Break::checkTypeRequirements()
{
}
void Return::checkTypeRequirements() void Return::checkTypeRequirements()
{ {
if (!m_expression) if (!m_expression)
@ -326,8 +318,6 @@ void VariableDefinition::checkTypeRequirements()
void Assignment::checkTypeRequirements() void Assignment::checkTypeRequirements()
{ {
//@todo lefthandside actually has to be assignable
// add a feature to the type system to check that
m_leftHandSide->checkTypeRequirements(); m_leftHandSide->checkTypeRequirements();
if (!m_leftHandSide->isLvalue()) if (!m_leftHandSide->isLvalue())
BOOST_THROW_EXCEPTION(createTypeError("Expression has to be an lvalue.")); BOOST_THROW_EXCEPTION(createTypeError("Expression has to be an lvalue."));
@ -366,8 +356,8 @@ void UnaryOperation::checkTypeRequirements()
void BinaryOperation::checkTypeRequirements() void BinaryOperation::checkTypeRequirements()
{ {
m_right->checkTypeRequirements();
m_left->checkTypeRequirements(); m_left->checkTypeRequirements();
m_right->checkTypeRequirements();
if (m_right->getType()->isImplicitlyConvertibleTo(*m_left->getType())) if (m_right->getType()->isImplicitlyConvertibleTo(*m_left->getType()))
m_commonType = m_left->getType(); m_commonType = m_left->getType();
else if (m_left->getType()->isImplicitlyConvertibleTo(*m_right->getType())) else if (m_left->getType()->isImplicitlyConvertibleTo(*m_right->getType()))
@ -446,14 +436,6 @@ void Identifier::checkTypeRequirements()
if (asserts(m_referencedDeclaration)) if (asserts(m_referencedDeclaration))
BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Identifier not resolved.")); BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Identifier not resolved."));
//@todo these dynamic casts here are not really nice...
// is i useful to have an AST visitor here?
// or can this already be done in NameAndTypeResolver?
// the only problem we get there is that in
// var x;
// x = 2;
// var y = x;
// the type of x is not yet determined.
VariableDeclaration* variable = dynamic_cast<VariableDeclaration*>(m_referencedDeclaration); VariableDeclaration* variable = dynamic_cast<VariableDeclaration*>(m_referencedDeclaration);
if (variable) if (variable)
{ {

4
libsolidity/AST.h

@ -390,7 +390,7 @@ class Continue: public Statement
public: public:
Continue(Location const& _location): Statement(_location) {} Continue(Location const& _location): Statement(_location) {}
virtual void accept(ASTVisitor& _visitor) override; virtual void accept(ASTVisitor& _visitor) override;
virtual void checkTypeRequirements() override; virtual void checkTypeRequirements() override {}
}; };
class Break: public Statement class Break: public Statement
@ -398,7 +398,7 @@ class Break: public Statement
public: public:
Break(Location const& _location): Statement(_location) {} Break(Location const& _location): Statement(_location) {}
virtual void accept(ASTVisitor& _visitor) override; virtual void accept(ASTVisitor& _visitor) override;
virtual void checkTypeRequirements() override; virtual void checkTypeRequirements() override {}
}; };
class Return: public Statement class Return: public Statement

6
libsolidity/Compiler.cpp

@ -252,16 +252,14 @@ bool Compiler::visit(WhileStatement& _whileStatement)
bool Compiler::visit(Continue&) bool Compiler::visit(Continue&)
{ {
if (asserts(!m_continueTags.empty())) if (!m_continueTags.empty())
BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Jump tag not available for \"continue\"."));
m_context.appendJumpTo(m_continueTags.back()); m_context.appendJumpTo(m_continueTags.back());
return false; return false;
} }
bool Compiler::visit(Break&) bool Compiler::visit(Break&)
{ {
if (asserts(!m_breakTags.empty())) if (!m_breakTags.empty())
BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Jump tag not available for \"break\"."));
m_context.appendJumpTo(m_breakTags.back()); m_context.appendJumpTo(m_breakTags.back());
return false; return false;
} }

49
test/solidityEndToEndTest.cpp

@ -151,6 +151,55 @@ BOOST_AUTO_TEST_CASE(while_loop)
BOOST_CHECK(framework.callFunction(0, u256(4)) == toBigEndian(u256(24))); BOOST_CHECK(framework.callFunction(0, u256(4)) == toBigEndian(u256(24)));
} }
BOOST_AUTO_TEST_CASE(break_outside_loop)
{
// break and continue outside loops should be simply ignored
char const* sourceCode = "contract test {\n"
" function f(uint x) returns(uint y) {\n"
" break; continue; return 2;\n"
" }\n"
"}\n";
ExecutionFramework framework;
framework.compileAndRun(sourceCode);
BOOST_CHECK(framework.callFunction(0, u256(0)) == toBigEndian(u256(2)));
}
BOOST_AUTO_TEST_CASE(nested_loops)
{
// tests that break and continue statements in nested loops jump to the correct place
char const* sourceCode = "contract test {\n"
" function f(uint x) returns(uint y) {\n"
" while (x > 1) {\n"
" if (x == 10) break;\n"
" while (x > 5) {\n"
" if (x == 8) break;\n"
" x--;\n"
" if (x == 6) continue;\n"
" return x;\n"
" }\n"
" x--;\n"
" if (x == 3) continue;\n"
" break;\n"
" }\n"
" return x;\n"
" }\n"
"}\n";
ExecutionFramework framework;
framework.compileAndRun(sourceCode);
BOOST_CHECK(framework.callFunction(0, u256(0)) == toBigEndian(u256(0)));
BOOST_CHECK(framework.callFunction(0, u256(1)) == toBigEndian(u256(1)));
BOOST_CHECK(framework.callFunction(0, u256(2)) == toBigEndian(u256(1)));
BOOST_CHECK(framework.callFunction(0, u256(3)) == toBigEndian(u256(2)));
BOOST_CHECK(framework.callFunction(0, u256(4)) == toBigEndian(u256(2)));
BOOST_CHECK(framework.callFunction(0, u256(5)) == toBigEndian(u256(4)));
BOOST_CHECK(framework.callFunction(0, u256(6)) == toBigEndian(u256(5)));
BOOST_CHECK(framework.callFunction(0, u256(7)) == toBigEndian(u256(5)));
BOOST_CHECK(framework.callFunction(0, u256(8)) == toBigEndian(u256(7)));
BOOST_CHECK(framework.callFunction(0, u256(9)) == toBigEndian(u256(8)));
BOOST_CHECK(framework.callFunction(0, u256(10)) == toBigEndian(u256(10)));
BOOST_CHECK(framework.callFunction(0, u256(11)) == toBigEndian(u256(10)));
}
BOOST_AUTO_TEST_CASE(calling_other_functions) BOOST_AUTO_TEST_CASE(calling_other_functions)
{ {
// note that the index of a function is its index in the sorted sequence of functions // note that the index of a function is its index in the sorted sequence of functions

Loading…
Cancel
Save