aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--libsolidity/AST.h12
-rw-r--r--libsolidity/ASTForward.h1
-rw-r--r--libsolidity/ASTJsonConverter.cpp11
-rw-r--r--libsolidity/ASTJsonConverter.h2
-rw-r--r--libsolidity/ASTPrinter.cpp12
-rw-r--r--libsolidity/ASTPrinter.h2
-rw-r--r--libsolidity/ASTVisitor.h4
-rw-r--r--libsolidity/AST_accept.h12
-rw-r--r--libsolidity/Compiler.cpp7
-rw-r--r--libsolidity/Compiler.h1
-rw-r--r--libsolidity/Parser.cpp10
-rw-r--r--libsolidity/Token.h2
-rw-r--r--libsolidity/grammar.txt1
-rw-r--r--test/libsolidity/SolidityEndToEndTest.cpp18
14 files changed, 94 insertions, 1 deletions
diff --git a/libsolidity/AST.h b/libsolidity/AST.h
index da6a7d58..db83cf59 100644
--- a/libsolidity/AST.h
+++ b/libsolidity/AST.h
@@ -969,6 +969,18 @@ private:
};
/**
+ * @brief The Throw statement to throw that triggers a solidity exception(jump to ErrorTag)
+ */
+class Throw: public Statement
+{
+public:
+ Throw(SourceLocation const& _location): Statement(_location) {}
+ virtual void accept(ASTVisitor& _visitor) override;
+ virtual void accept(ASTConstVisitor& _visitor) const override;
+ virtual void checkTypeRequirements() override{};
+};
+
+/**
* Definition of a variable as a statement inside a function. It requires a type name (which can
* also be "var") but the actual assignment can be missing.
* Examples: var a = 2; uint256 a;
diff --git a/libsolidity/ASTForward.h b/libsolidity/ASTForward.h
index 0ba485a2..396cf50a 100644
--- a/libsolidity/ASTForward.h
+++ b/libsolidity/ASTForward.h
@@ -64,6 +64,7 @@ class ForStatement;
class Continue;
class Break;
class Return;
+class Throw;
class VariableDeclarationStatement;
class ExpressionStatement;
class Expression;
diff --git a/libsolidity/ASTJsonConverter.cpp b/libsolidity/ASTJsonConverter.cpp
index 3d119a4e..96e5cf2a 100644
--- a/libsolidity/ASTJsonConverter.cpp
+++ b/libsolidity/ASTJsonConverter.cpp
@@ -193,6 +193,12 @@ bool ASTJsonConverter::visit(Return const&)
return true;
}
+bool ASTJsonConverter::visit(Throw const&)
+{
+ addJsonNode("Throw", {}, true);;
+ return true;
+}
+
bool ASTJsonConverter::visit(VariableDeclarationStatement const&)
{
addJsonNode("VariableDefinition", {}, true);
@@ -364,6 +370,11 @@ void ASTJsonConverter::endVisit(Return const&)
goUp();
}
+void ASTJsonConverter::endVisit(Throw const&)
+{
+ goUp();
+}
+
void ASTJsonConverter::endVisit(VariableDeclarationStatement const&)
{
goUp();
diff --git a/libsolidity/ASTJsonConverter.h b/libsolidity/ASTJsonConverter.h
index 09217e97..77230d92 100644
--- a/libsolidity/ASTJsonConverter.h
+++ b/libsolidity/ASTJsonConverter.h
@@ -63,6 +63,7 @@ public:
bool visit(Continue const& _node) override;
bool visit(Break const& _node) override;
bool visit(Return const& _node) override;
+ bool visit(Throw const& _node) override;
bool visit(VariableDeclarationStatement const& _node) override;
bool visit(ExpressionStatement const& _node) override;
bool visit(Assignment const& _node) override;
@@ -93,6 +94,7 @@ public:
void endVisit(Continue const&) override;
void endVisit(Break const&) override;
void endVisit(Return const&) override;
+ void endVisit(Throw const&) override;
void endVisit(VariableDeclarationStatement const&) override;
void endVisit(ExpressionStatement const&) override;
void endVisit(Assignment const&) override;
diff --git a/libsolidity/ASTPrinter.cpp b/libsolidity/ASTPrinter.cpp
index a64e8490..8ed45d87 100644
--- a/libsolidity/ASTPrinter.cpp
+++ b/libsolidity/ASTPrinter.cpp
@@ -221,6 +221,13 @@ bool ASTPrinter::visit(Return const& _node)
return goDeeper();
}
+bool ASTPrinter::visit(Throw const& _node)
+{
+ writeLine("Throw");
+ printSourcePart(_node);
+ return goDeeper();
+}
+
bool ASTPrinter::visit(VariableDeclarationStatement const& _node)
{
writeLine("VariableDeclarationStatement");
@@ -444,6 +451,11 @@ void ASTPrinter::endVisit(Return const&)
m_indentation--;
}
+void ASTPrinter::endVisit(Throw const&)
+{
+ m_indentation--;
+}
+
void ASTPrinter::endVisit(VariableDeclarationStatement const&)
{
m_indentation--;
diff --git a/libsolidity/ASTPrinter.h b/libsolidity/ASTPrinter.h
index 8c8be112..a12ec0aa 100644
--- a/libsolidity/ASTPrinter.h
+++ b/libsolidity/ASTPrinter.h
@@ -72,6 +72,7 @@ public:
bool visit(Continue const& _node) override;
bool visit(Break const& _node) override;
bool visit(Return const& _node) override;
+ bool visit(Throw const& _node) override;
bool visit(VariableDeclarationStatement const& _node) override;
bool visit(ExpressionStatement const& _node) override;
bool visit(Assignment const& _node) override;
@@ -110,6 +111,7 @@ public:
void endVisit(Continue const&) override;
void endVisit(Break const&) override;
void endVisit(Return const&) override;
+ void endVisit(Throw const&) override;
void endVisit(VariableDeclarationStatement const&) override;
void endVisit(ExpressionStatement const&) override;
void endVisit(Assignment const&) override;
diff --git a/libsolidity/ASTVisitor.h b/libsolidity/ASTVisitor.h
index f7847220..e665396c 100644
--- a/libsolidity/ASTVisitor.h
+++ b/libsolidity/ASTVisitor.h
@@ -69,6 +69,7 @@ public:
virtual bool visit(Continue& _node) { return visitNode(_node); }
virtual bool visit(Break& _node) { return visitNode(_node); }
virtual bool visit(Return& _node) { return visitNode(_node); }
+ virtual bool visit(Throw& _node) { return visitNode(_node); }
virtual bool visit(VariableDeclarationStatement& _node) { return visitNode(_node); }
virtual bool visit(ExpressionStatement& _node) { return visitNode(_node); }
virtual bool visit(Assignment& _node) { return visitNode(_node); }
@@ -108,6 +109,7 @@ public:
virtual void endVisit(Continue& _node) { endVisitNode(_node); }
virtual void endVisit(Break& _node) { endVisitNode(_node); }
virtual void endVisit(Return& _node) { endVisitNode(_node); }
+ virtual void endVisit(Throw& _node) { endVisitNode(_node); }
virtual void endVisit(VariableDeclarationStatement& _node) { endVisitNode(_node); }
virtual void endVisit(ExpressionStatement& _node) { endVisitNode(_node); }
virtual void endVisit(Assignment& _node) { endVisitNode(_node); }
@@ -159,6 +161,7 @@ public:
virtual bool visit(Continue const& _node) { return visitNode(_node); }
virtual bool visit(Break const& _node) { return visitNode(_node); }
virtual bool visit(Return const& _node) { return visitNode(_node); }
+ virtual bool visit(Throw const& _node) { return visitNode(_node); }
virtual bool visit(VariableDeclarationStatement const& _node) { return visitNode(_node); }
virtual bool visit(ExpressionStatement const& _node) { return visitNode(_node); }
virtual bool visit(Assignment const& _node) { return visitNode(_node); }
@@ -198,6 +201,7 @@ public:
virtual void endVisit(Continue const& _node) { endVisitNode(_node); }
virtual void endVisit(Break const& _node) { endVisitNode(_node); }
virtual void endVisit(Return const& _node) { endVisitNode(_node); }
+ virtual void endVisit(Throw const& _node) { endVisitNode(_node); }
virtual void endVisit(VariableDeclarationStatement const& _node) { endVisitNode(_node); }
virtual void endVisit(ExpressionStatement const& _node) { endVisitNode(_node); }
virtual void endVisit(Assignment const& _node) { endVisitNode(_node); }
diff --git a/libsolidity/AST_accept.h b/libsolidity/AST_accept.h
index 3557f877..d07c2cd0 100644
--- a/libsolidity/AST_accept.h
+++ b/libsolidity/AST_accept.h
@@ -491,6 +491,18 @@ void Return::accept(ASTConstVisitor& _visitor) const
_visitor.endVisit(*this);
}
+void Throw::accept(ASTVisitor& _visitor)
+{
+ if (_visitor.visit(*this))
+ _visitor.endVisit(*this);
+}
+
+void Throw::accept(ASTConstVisitor& _visitor) const
+{
+ if (_visitor.visit(*this))
+ _visitor.endVisit(*this);
+}
+
void ExpressionStatement::accept(ASTVisitor& _visitor)
{
if (_visitor.visit(*this))
diff --git a/libsolidity/Compiler.cpp b/libsolidity/Compiler.cpp
index 9bdf45f8..d6582653 100644
--- a/libsolidity/Compiler.cpp
+++ b/libsolidity/Compiler.cpp
@@ -606,6 +606,13 @@ bool Compiler::visit(Return const& _return)
return false;
}
+bool Compiler::visit(Throw const& _throw)
+{
+ CompilerContext::LocationSetter locationSetter(m_context, _throw);
+ m_context.appendJumpTo(m_context.errorTag());
+ return false;
+}
+
bool Compiler::visit(VariableDeclarationStatement const& _variableDeclarationStatement)
{
StackHeightChecker checker(m_context);
diff --git a/libsolidity/Compiler.h b/libsolidity/Compiler.h
index 7e1d3222..c7dd7d90 100644
--- a/libsolidity/Compiler.h
+++ b/libsolidity/Compiler.h
@@ -112,6 +112,7 @@ private:
virtual bool visit(Continue const& _continue) override;
virtual bool visit(Break const& _break) override;
virtual bool visit(Return const& _return) override;
+ virtual bool visit(Throw const& _throw) override;
virtual bool visit(VariableDeclarationStatement const& _variableDeclarationStatement) override;
virtual bool visit(ExpressionStatement const& _expressionStatement) override;
virtual bool visit(PlaceholderStatement const&) override;
diff --git a/libsolidity/Parser.cpp b/libsolidity/Parser.cpp
index 24f7734c..ac9e04c8 100644
--- a/libsolidity/Parser.cpp
+++ b/libsolidity/Parser.cpp
@@ -622,6 +622,16 @@ ASTPointer<Statement> Parser::parseStatement()
statement = nodeFactory.createNode<Return>(expression);
break;
}
+ case Token::Throw:
+ {
+ ASTNodeFactory nodeFactory(*this);
+ ASTPointer<Expression> expression;
+ if (m_scanner->next() != Token::Semicolon)
+ BOOST_THROW_EXCEPTION(createParserError("Throw statement cannot have parameters."));
+
+ statement = nodeFactory.createNode<Throw>(/*expression*/);
+ break;
+ }
case Token::Identifier:
if (m_insideModifier && m_scanner->currentLiteral() == "_")
{
diff --git a/libsolidity/Token.h b/libsolidity/Token.h
index 1632a693..2ea7eb01 100644
--- a/libsolidity/Token.h
+++ b/libsolidity/Token.h
@@ -171,6 +171,7 @@ namespace solidity
K(Returns, "returns", 0) \
K(Storage, "storage", 0) \
K(Struct, "struct", 0) \
+ K(Throw, "throw", 0) \
K(Var, "var", 0) \
K(While, "while", 0) \
\
@@ -316,7 +317,6 @@ namespace solidity
K(Of, "of", 0) \
K(Relocatable, "relocatable", 0) \
K(Switch, "switch", 0) \
- K(Throw, "throw", 0) \
K(Try, "try", 0) \
K(Type, "type", 0) \
K(TypeOf, "typeof", 0) \
diff --git a/libsolidity/grammar.txt b/libsolidity/grammar.txt
index 467aebee..08a74f45 100644
--- a/libsolidity/grammar.txt
+++ b/libsolidity/grammar.txt
@@ -34,6 +34,7 @@ ForStatement = 'for' '(' (VardefOrExprStmt)? ';' (Expression)? ';' (ExpressionSt
Continue = 'continue' ';'
Break = 'break' ';'
Return = 'return' Expression? ';'
+Throw = 'throw' Expression? ';'
VariableDefinition = VariableDeclaration ( = Expression )? ';'
Expression = Assignment | UnaryOperation | BinaryOperation | FunctionCall | NewExpression | IndexAccess |
diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp
index 2ba6ab85..9c4d0c5b 100644
--- a/test/libsolidity/SolidityEndToEndTest.cpp
+++ b/test/libsolidity/SolidityEndToEndTest.cpp
@@ -5265,6 +5265,24 @@ BOOST_AUTO_TEST_CASE(library_stray_values)
BOOST_CHECK(callContractFunction("f(uint256)", u256(33)) == encodeArgs(u256(42)));
}
+BOOST_AUTO_TEST_CASE(simple_throw)
+{
+ char const* sourceCode = R"(
+ contract Test {
+ function f(uint x) returns (uint) {
+ if (x > 10)
+ return x + 10;
+ else
+ throw;
+ return 2;
+ }
+ }
+ )";
+ compileAndRun(sourceCode);
+ BOOST_CHECK(callContractFunction("f(uint256)", u256(11)) == encodeArgs(u256(21)));
+ BOOST_CHECK(callContractFunction("f(uint256)", u256(1)) == encodeArgs());
+}
+
BOOST_AUTO_TEST_SUITE_END()
}