aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--AST.cpp4
-rw-r--r--Types.cpp28
-rw-r--r--Types.h16
3 files changed, 31 insertions, 17 deletions
diff --git a/AST.cpp b/AST.cpp
index bcaae0e1..90b9962c 100644
--- a/AST.cpp
+++ b/AST.cpp
@@ -228,8 +228,8 @@ void UnaryOperation::checkTypeRequirements()
m_subExpression->checkTypeRequirements();
if (m_operator == Token::Value::INC || m_operator == Token::Value::DEC || m_operator == Token::Value::DELETE)
m_subExpression->requireLValue();
- m_type = m_subExpression->getType();
- if (!m_type->acceptsUnaryOperator(m_operator))
+ m_type = m_subExpression->getType()->unaryOperatorResult(m_operator);
+ if (!m_type)
BOOST_THROW_EXCEPTION(createTypeError("Unary operator not compatible with type."));
}
diff --git a/Types.cpp b/Types.cpp
index d1a3c7a7..ade196f2 100644
--- a/Types.cpp
+++ b/Types.cpp
@@ -156,18 +156,26 @@ bool IntegerType::isExplicitlyConvertibleTo(Type const& _convertTo) const
return _convertTo.getCategory() == getCategory() || _convertTo.getCategory() == Category::CONTRACT;
}
-bool IntegerType::acceptsUnaryOperator(Token::Value _operator) const
+TypePointer IntegerType::unaryOperatorResult(Token::Value _operator) const
{
+ // "delete" is ok for all integer types
if (_operator == Token::DELETE)
- return true;
- if (isAddress())
- return false;
- if (_operator == Token::BIT_NOT)
- return true;
- if (isHash())
- return false;
- return _operator == Token::ADD || _operator == Token::SUB ||
- _operator == Token::INC || _operator == Token::DEC;
+ return shared_from_this();
+ // no further unary operators for addresses
+ else if (isAddress())
+ return TypePointer();
+ // "~" is ok for all other types
+ else if (_operator == Token::BIT_NOT)
+ return shared_from_this();
+ // nothing else for hashes
+ else if (isHash())
+ return TypePointer();
+ // for non-hash integers, we allow +, -, ++ and --
+ else if (_operator == Token::ADD || _operator == Token::SUB ||
+ _operator == Token::INC || _operator == Token::DEC)
+ return shared_from_this();
+ else
+ return TypePointer();
}
bool IntegerType::operator==(Type const& _other) const
diff --git a/Types.h b/Types.h
index 3b416f40..36484451 100644
--- a/Types.h
+++ b/Types.h
@@ -99,7 +99,10 @@ public:
{
return isImplicitlyConvertibleTo(_convertTo);
}
- virtual bool acceptsUnaryOperator(Token::Value) const { return false; }
+ /// @returns the resulting type of applying the given unary operator or an empty pointer if
+ /// this is not possible.
+ /// The default implementation does not allow any unary operator.
+ virtual TypePointer unaryOperatorResult(Token::Value) const { return TypePointer(); }
/// @returns the resulting type of applying the given binary operator or an empty pointer if
/// this is not possible.
/// The default implementation allows comparison operators if a common type exists
@@ -163,7 +166,7 @@ public:
virtual bool isImplicitlyConvertibleTo(Type const& _convertTo) const override;
virtual bool isExplicitlyConvertibleTo(Type const& _convertTo) const override;
- virtual bool acceptsUnaryOperator(Token::Value _operator) const override;
+ virtual TypePointer unaryOperatorResult(Token::Value _operator) const override;
virtual TypePointer binaryOperatorResult(Token::Value _operator, TypePointer const& _other) const override;
virtual bool operator==(Type const& _other) const override;
@@ -225,9 +228,9 @@ public:
BoolType() {}
virtual Category getCategory() const { return Category::BOOL; }
virtual bool isExplicitlyConvertibleTo(Type const& _convertTo) const override;
- virtual bool acceptsUnaryOperator(Token::Value _operator) const override
+ virtual TypePointer unaryOperatorResult(Token::Value _operator) const override
{
- return _operator == Token::NOT || _operator == Token::DELETE;
+ return (_operator == Token::NOT || _operator == Token::DELETE) ? shared_from_this() : TypePointer();
}
virtual TypePointer binaryOperatorResult(Token::Value _operator, TypePointer const& _other) const override;
@@ -277,7 +280,10 @@ class StructType: public Type
public:
virtual Category getCategory() const override { return Category::STRUCT; }
StructType(StructDefinition const& _struct): m_struct(_struct) {}
- virtual bool acceptsUnaryOperator(Token::Value _operator) const override { return _operator == Token::DELETE; }
+ virtual TypePointer unaryOperatorResult(Token::Value _operator) const override
+ {
+ return _operator == Token::DELETE ? shared_from_this() : TypePointer();
+ }
virtual bool operator==(Type const& _other) const override;
virtual u256 getStorageSize() const override;