aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLefteris Karapetsas <lefteris@refu.co>2015-01-09 00:43:38 +0800
committerLefteris Karapetsas <lefteris@refu.co>2015-01-09 00:43:38 +0800
commita7b661d3be53b4c6a05401782ab8f90202a4f776 (patch)
treea2fdb25e88821def4962e1eacf303ec8f89cdfc3
parent184ddca5a108c5f3d026aa372a2af2f63b2694f9 (diff)
parentd18fa27b6a48540298e835ad324152566586c65c (diff)
downloaddexon-solidity-a7b661d3be53b4c6a05401782ab8f90202a4f776.tar
dexon-solidity-a7b661d3be53b4c6a05401782ab8f90202a4f776.tar.gz
dexon-solidity-a7b661d3be53b4c6a05401782ab8f90202a4f776.tar.bz2
dexon-solidity-a7b661d3be53b4c6a05401782ab8f90202a4f776.tar.lz
dexon-solidity-a7b661d3be53b4c6a05401782ab8f90202a4f776.tar.xz
dexon-solidity-a7b661d3be53b4c6a05401782ab8f90202a4f776.tar.zst
dexon-solidity-a7b661d3be53b4c6a05401782ab8f90202a4f776.zip
merging develop
-rw-r--r--AST.cpp35
-rw-r--r--Compiler.h2
-rw-r--r--CompilerStack.h2
-rw-r--r--ExpressionCompiler.cpp2
-rw-r--r--ExpressionCompiler.h6
-rw-r--r--GlobalContext.h2
-rw-r--r--NameAndTypeResolver.h2
-rw-r--r--Types.cpp52
-rw-r--r--Types.h62
9 files changed, 116 insertions, 49 deletions
diff --git a/AST.cpp b/AST.cpp
index 300303ac..fb71e900 100644
--- a/AST.cpp
+++ b/AST.cpp
@@ -185,12 +185,18 @@ void Assignment::checkTypeRequirements()
//@todo later, assignments to structs might be possible, but not to mappings
if (!m_leftHandSide->getType()->isValueType() && !m_leftHandSide->isLocalLValue())
BOOST_THROW_EXCEPTION(createTypeError("Assignment to non-local non-value lvalue."));
- m_rightHandSide->expectType(*m_leftHandSide->getType());
m_type = m_leftHandSide->getType();
- if (m_assigmentOperator != Token::ASSIGN)
+ if (m_assigmentOperator == Token::ASSIGN)
+ m_rightHandSide->expectType(*m_type);
+ else
+ {
// compound assignment
- if (!m_type->acceptsBinaryOperator(Token::AssignmentToBinaryOp(m_assigmentOperator)))
+ m_rightHandSide->checkTypeRequirements();
+ TypePointer resultType = Type::binaryOperatorResult(Token::AssignmentToBinaryOp(m_assigmentOperator),
+ m_type, m_rightHandSide->getType());
+ if (!resultType || *resultType != *m_type)
BOOST_THROW_EXCEPTION(createTypeError("Operator not compatible with type."));
+ }
}
void ExpressionStatement::checkTypeRequirements()
@@ -230,24 +236,13 @@ void BinaryOperation::checkTypeRequirements()
{
m_left->checkTypeRequirements();
m_right->checkTypeRequirements();
- if (m_right->getType()->isImplicitlyConvertibleTo(*m_left->getType()))
- m_commonType = m_left->getType();
- else if (m_left->getType()->isImplicitlyConvertibleTo(*m_right->getType()))
- m_commonType = m_right->getType();
- else
- BOOST_THROW_EXCEPTION(createTypeError("No common type found in binary operation: " +
- m_left->getType()->toString() + " vs. " +
+ m_commonType = Type::binaryOperatorResult(m_operator, m_left->getType(), m_right->getType());
+ if (!m_commonType)
+ BOOST_THROW_EXCEPTION(createTypeError("Operator " + string(Token::toString(m_operator)) +
+ " not compatible with types " +
+ m_left->getType()->toString() + " and " +
m_right->getType()->toString()));
- if (Token::isCompareOp(m_operator))
- m_type = make_shared<BoolType>();
- else
- {
- m_type = m_commonType;
- if (!m_commonType->acceptsBinaryOperator(m_operator))
- BOOST_THROW_EXCEPTION(createTypeError("Operator " + string(Token::toString(m_operator)) +
- " not compatible with type " +
- m_commonType->toString()));
- }
+ m_type = Token::isCompareOp(m_operator) ? make_shared<BoolType>() : m_commonType;
}
void FunctionCall::checkTypeRequirements()
diff --git a/Compiler.h b/Compiler.h
index 8471fae2..e83d1ed3 100644
--- a/Compiler.h
+++ b/Compiler.h
@@ -30,7 +30,7 @@ namespace solidity {
class Compiler: private ASTConstVisitor
{
public:
- explicit Compiler(bool _optimize = false): m_optimize(_optimize), m_returnTag(m_context.newTag()) {}
+ explicit Compiler(bool _optimize = false): m_optimize(_optimize), m_context(), m_returnTag(m_context.newTag()) {}
void compileContract(ContractDefinition const& _contract, std::vector<MagicVariableDeclaration const*> const& _magicGlobals,
std::map<ContractDefinition const*, bytes const*> const& _contracts);
diff --git a/CompilerStack.h b/CompilerStack.h
index 358c8fb7..e7143b7b 100644
--- a/CompilerStack.h
+++ b/CompilerStack.h
@@ -113,7 +113,7 @@ private:
struct Contract
{
- ContractDefinition const* contract;
+ ContractDefinition const* contract = nullptr;
std::shared_ptr<Compiler> compiler;
bytes bytecode;
std::shared_ptr<InterfaceHandler> interfaceHandler;
diff --git a/ExpressionCompiler.cpp b/ExpressionCompiler.cpp
index 5fefd528..1b10c854 100644
--- a/ExpressionCompiler.cpp
+++ b/ExpressionCompiler.cpp
@@ -217,7 +217,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
unsigned returnParametersSize = CompilerUtils::getSizeOnStack(function.getReturnParameterTypes());
// callee adds return parameters, but removes arguments and return label
- m_context.adjustStackOffset(returnParametersSize - CompilerUtils::getSizeOnStack(arguments) - 1);
+ m_context.adjustStackOffset(returnParametersSize - CompilerUtils::getSizeOnStack(function.getParameterTypes()) - 1);
// @todo for now, the return value of a function is its first return value, so remove
// all others
diff --git a/ExpressionCompiler.h b/ExpressionCompiler.h
index 67b16aac..c0ee4ab4 100644
--- a/ExpressionCompiler.h
+++ b/ExpressionCompiler.h
@@ -146,12 +146,12 @@ private:
private:
CompilerContext* m_context;
- LValueType m_type;
+ LValueType m_type = NONE;
/// If m_type is STACK, this is base stack offset (@see
/// CompilerContext::getBaseStackOffsetOfVariable) of a local variable.
- unsigned m_baseStackOffset;
+ unsigned m_baseStackOffset = 0;
/// Size of the value of this lvalue on the stack.
- unsigned m_stackSize;
+ unsigned m_stackSize = 0;
};
bool m_optimize;
diff --git a/GlobalContext.h b/GlobalContext.h
index 50a21f70..c6e35f50 100644
--- a/GlobalContext.h
+++ b/GlobalContext.h
@@ -56,7 +56,7 @@ public:
private:
std::vector<std::shared_ptr<MagicVariableDeclaration const>> m_magicVariables;
- ContractDefinition const* m_currentContract;
+ ContractDefinition const* m_currentContract = nullptr;
std::map<ContractDefinition const*, std::shared_ptr<MagicVariableDeclaration const>> mutable m_thisPointer;
};
diff --git a/NameAndTypeResolver.h b/NameAndTypeResolver.h
index 23ac5fe7..1032a87c 100644
--- a/NameAndTypeResolver.h
+++ b/NameAndTypeResolver.h
@@ -69,7 +69,7 @@ private:
/// not contain code.
std::map<ASTNode const*, DeclarationContainer> m_scopes;
- DeclarationContainer* m_currentScope;
+ DeclarationContainer* m_currentScope = nullptr;
};
/**
diff --git a/Types.cpp b/Types.cpp
index e5bfa30f..494bbd26 100644
--- a/Types.cpp
+++ b/Types.cpp
@@ -100,6 +100,16 @@ shared_ptr<Type const> Type::forLiteral(Literal const& _literal)
}
}
+TypePointer Type::commonType(TypePointer const& _a, TypePointer const& _b)
+{
+ if (_b->isImplicitlyConvertibleTo(*_a))
+ return _a;
+ else if (_a->isImplicitlyConvertibleTo(*_b))
+ return _b;
+ else
+ return TypePointer();
+}
+
const MemberList Type::EmptyMemberList = MemberList();
shared_ptr<IntegerType const> IntegerType::smallestTypeForLiteral(string const& _literal)
@@ -146,16 +156,6 @@ bool IntegerType::isExplicitlyConvertibleTo(Type const& _convertTo) const
return _convertTo.getCategory() == getCategory() || _convertTo.getCategory() == Category::CONTRACT;
}
-bool IntegerType::acceptsBinaryOperator(Token::Value _operator) const
-{
- if (isAddress())
- return Token::isCompareOp(_operator);
- else if (isHash())
- return Token::isCompareOp(_operator) || Token::isBitOp(_operator);
- else
- return true;
-}
-
bool IntegerType::acceptsUnaryOperator(Token::Value _operator) const
{
if (_operator == Token::DELETE)
@@ -192,6 +192,28 @@ u256 IntegerType::literalValue(Literal const& _literal) const
return u256(value);
}
+TypePointer IntegerType::binaryOperatorResultImpl(Token::Value _operator, TypePointer const& _this, TypePointer const& _other) const
+{
+ if (getCategory() != _other->getCategory())
+ return TypePointer();
+ auto commonType = dynamic_pointer_cast<IntegerType const>(Type::commonType(_this, _other));
+
+ if (!commonType)
+ return TypePointer();
+
+ // All integer types can be compared
+ if (Token::isCompareOp(_operator))
+ return commonType;
+
+ // Nothing else can be done with addresses, but hashes can receive bit operators
+ if (commonType->isAddress())
+ return TypePointer();
+ else if (commonType->isHash() && !Token::isBitOp(_operator))
+ return TypePointer();
+ else
+ return commonType;
+}
+
const MemberList IntegerType::AddressMemberList =
MemberList({{"balance",
make_shared<IntegerType const>(256)},
@@ -266,6 +288,16 @@ u256 BoolType::literalValue(Literal const& _literal) const
BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Bool type constructed from non-boolean literal."));
}
+TypePointer BoolType::binaryOperatorResultImpl(Token::Value _operator, TypePointer const& _this, TypePointer const& _other) const
+{
+ if (getCategory() != _other->getCategory())
+ return TypePointer();
+ if (Token::isCompareOp(_operator) || _operator == Token::AND || _operator == Token::OR)
+ return _this;
+ else
+ return TypePointer();
+}
+
bool ContractType::isExplicitlyConvertibleTo(Type const& _convertTo) const
{
if (isImplicitlyConvertibleTo(_convertTo))
diff --git a/Types.h b/Types.h
index 9d34e19a..0823f25d 100644
--- a/Types.h
+++ b/Types.h
@@ -81,15 +81,23 @@ public:
///@{
///@name Factory functions
/// Factory functions that convert an AST @ref TypeName to a Type.
- static std::shared_ptr<Type const> fromElementaryTypeName(Token::Value _typeToken);
- static std::shared_ptr<Type const> fromUserDefinedTypeName(UserDefinedTypeName const& _typeName);
- static std::shared_ptr<Type const> fromMapping(Mapping const& _typeName);
- static std::shared_ptr<Type const> fromFunction(FunctionDefinition const& _function);
+ static TypePointer fromElementaryTypeName(Token::Value _typeToken);
+ static TypePointer fromUserDefinedTypeName(UserDefinedTypeName const& _typeName);
+ static TypePointer fromMapping(Mapping const& _typeName);
+ static TypePointer fromFunction(FunctionDefinition const& _function);
/// @}
/// Auto-detect the proper type for a literal. @returns an empty pointer if the literal does
/// not fit any type.
- static std::shared_ptr<Type const> forLiteral(Literal const& _literal);
+ static TypePointer forLiteral(Literal const& _literal);
+ /// @returns a pointer to _a or _b if the other is implicitly convertible to it or nullptr otherwise
+ static TypePointer commonType(TypePointer const& _a, TypePointer const& _b);
+ /// @returns the resulting type of applying the given operator or an empty pointer if this is not possible.
+ /// The default implementation allows comparison operators if a common type exists
+ static TypePointer binaryOperatorResult(Token::Value _operator, TypePointer const& _a, TypePointer const& _b)
+ {
+ return _a->binaryOperatorResultImpl(_operator, _a, _b);
+ }
virtual Category getCategory() const = 0;
virtual bool isImplicitlyConvertibleTo(Type const& _other) const { return *this == _other; }
@@ -97,7 +105,6 @@ public:
{
return isImplicitlyConvertibleTo(_convertTo);
}
- virtual bool acceptsBinaryOperator(Token::Value) const { return false; }
virtual bool acceptsUnaryOperator(Token::Value) const { return false; }
virtual bool operator==(Type const& _other) const { return getCategory() == _other.getCategory(); }
@@ -131,6 +138,11 @@ public:
}
protected:
+ virtual TypePointer binaryOperatorResultImpl(Token::Value _operator, TypePointer const& _a, TypePointer const& _b) const
+ {
+ return Token::isCompareOp(_operator) ? commonType(_a, _b) : TypePointer();
+ }
+
/// Convenience object used when returning an empty member list.
static const MemberList EmptyMemberList;
};
@@ -155,7 +167,6 @@ public:
virtual bool isImplicitlyConvertibleTo(Type const& _convertTo) const override;
virtual bool isExplicitlyConvertibleTo(Type const& _convertTo) const override;
- virtual bool acceptsBinaryOperator(Token::Value _operator) const override;
virtual bool acceptsUnaryOperator(Token::Value _operator) const override;
virtual bool operator==(Type const& _other) const override;
@@ -173,6 +184,9 @@ public:
bool isAddress() const { return m_modifier == Modifier::ADDRESS; }
int isSigned() const { return m_modifier == Modifier::SIGNED; }
+protected:
+ virtual TypePointer binaryOperatorResultImpl(Token::Value _operator, TypePointer const& _this, TypePointer const& _other) const override;
+
private:
int m_bits;
Modifier m_modifier;
@@ -217,10 +231,6 @@ public:
BoolType() {}
virtual Category getCategory() const { return Category::BOOL; }
virtual bool isExplicitlyConvertibleTo(Type const& _convertTo) const override;
- virtual bool acceptsBinaryOperator(Token::Value _operator) const override
- {
- return _operator == Token::AND || _operator == Token::OR;
- }
virtual bool acceptsUnaryOperator(Token::Value _operator) const override
{
return _operator == Token::NOT || _operator == Token::DELETE;
@@ -231,6 +241,9 @@ public:
virtual std::string toString() const override { return "bool"; }
virtual u256 literalValue(Literal const& _literal) const override;
+
+protected:
+ virtual TypePointer binaryOperatorResultImpl(Token::Value _operator, TypePointer const& _this, TypePointer const& _other) const override;
};
/**
@@ -370,6 +383,15 @@ public:
virtual u256 getStorageSize() const override { BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Storage size of non-storable void type requested.")); }
virtual bool canLiveOutsideStorage() const override { return false; }
virtual unsigned getSizeOnStack() const override { return 0; }
+
+protected:
+ virtual TypePointer binaryOperatorResultImpl(Token::Value _operator, TypePointer const& _this, TypePointer const& _other) const override
+ {
+ (void)_operator;
+ (void)_this;
+ (void)_other;
+ return TypePointer();
+ }
};
/**
@@ -390,6 +412,15 @@ public:
virtual bool canLiveOutsideStorage() const override { return false; }
virtual std::string toString() const override { return "type(" + m_actualType->toString() + ")"; }
+protected:
+ virtual TypePointer binaryOperatorResultImpl(Token::Value _operator, TypePointer const& _this, TypePointer const& _other) const override
+ {
+ (void)_operator;
+ (void)_this;
+ (void)_other;
+ return TypePointer();
+ }
+
private:
TypePointer m_actualType;
};
@@ -414,6 +445,15 @@ public:
virtual std::string toString() const override;
+protected:
+ virtual TypePointer binaryOperatorResultImpl(Token::Value _operator, TypePointer const& _this, TypePointer const& _other) const override
+ {
+ (void)_operator;
+ (void)_this;
+ (void)_other;
+ return TypePointer();
+ }
+
private:
Kind m_kind;