diff options
Diffstat (limited to 'Types.cpp')
-rw-r--r-- | Types.cpp | 163 |
1 files changed, 87 insertions, 76 deletions
@@ -26,6 +26,8 @@ #include <libsolidity/Types.h> #include <libsolidity/AST.h> +#include <limits> + using namespace std; namespace dev @@ -37,24 +39,24 @@ shared_ptr<Type const> Type::fromElementaryTypeName(Token::Value _typeToken) { solAssert(Token::isElementaryTypeName(_typeToken), "Elementary type name expected."); - if (Token::INT <= _typeToken && _typeToken <= Token::HASH256) + if (Token::Int <= _typeToken && _typeToken <= Token::Hash256) { - int offset = _typeToken - Token::INT; + int offset = _typeToken - Token::Int; int bytes = offset % 33; if (bytes == 0) bytes = 32; int modifier = offset / 33; return make_shared<IntegerType>(bytes * 8, - modifier == 0 ? IntegerType::Modifier::SIGNED : - modifier == 1 ? IntegerType::Modifier::UNSIGNED : - IntegerType::Modifier::HASH); + modifier == 0 ? IntegerType::Modifier::Signed : + modifier == 1 ? IntegerType::Modifier::Unsigned : + IntegerType::Modifier::Hash); } - else if (_typeToken == Token::ADDRESS) - return make_shared<IntegerType>(0, IntegerType::Modifier::ADDRESS); - else if (_typeToken == Token::BOOL) + else if (_typeToken == Token::Address) + return make_shared<IntegerType>(0, IntegerType::Modifier::Address); + else if (_typeToken == Token::Bool) return make_shared<BoolType>(); - else if (Token::STRING0 <= _typeToken && _typeToken <= Token::STRING32) - return make_shared<StaticStringType>(int(_typeToken) - int(Token::STRING0)); + else if (Token::String0 <= _typeToken && _typeToken <= Token::String32) + return make_shared<StaticStringType>(int(_typeToken) - int(Token::String0)); else BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Unable to convert elementary typename " + std::string(Token::toString(_typeToken)) + " to type.")); @@ -87,12 +89,12 @@ shared_ptr<Type const> Type::forLiteral(Literal const& _literal) { switch (_literal.getToken()) { - case Token::TRUE_LITERAL: - case Token::FALSE_LITERAL: + case Token::TrueLiteral: + case Token::FalseLiteral: return make_shared<BoolType>(); - case Token::NUMBER: + case Token::Number: return make_shared<IntegerConstantType>(_literal); - case Token::STRING_LITERAL: + case Token::StringLiteral: //@todo put larger strings into dynamic strings return StaticStringType::smallestTypeForLiteral(_literal.getValue()); default: @@ -140,31 +142,31 @@ bool IntegerType::isImplicitlyConvertibleTo(Type const& _convertTo) const bool IntegerType::isExplicitlyConvertibleTo(Type const& _convertTo) const { - if (_convertTo.getCategory() == Category::STRING) + if (_convertTo.getCategory() == Category::String) { StaticStringType const& convertTo = dynamic_cast<StaticStringType const&>(_convertTo); return isHash() && (m_bits == convertTo.getNumBytes() * 8); } - return _convertTo.getCategory() == getCategory() || _convertTo.getCategory() == Category::CONTRACT; + return _convertTo.getCategory() == getCategory() || _convertTo.getCategory() == Category::Contract; } TypePointer IntegerType::unaryOperatorResult(Token::Value _operator) const { // "delete" is ok for all integer types - if (_operator == Token::DELETE) + if (_operator == Token::Delete) return make_shared<VoidType>(); // no further unary operators for addresses else if (isAddress()) return TypePointer(); // "~" is ok for all other types - else if (_operator == Token::BIT_NOT) + else if (_operator == Token::BitNot) 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) + else if (_operator == Token::Add || _operator == Token::Sub || + _operator == Token::Inc || _operator == Token::Dec) return shared_from_this(); else return TypePointer(); @@ -188,7 +190,7 @@ string IntegerType::toString() const TypePointer IntegerType::binaryOperatorResult(Token::Value _operator, TypePointer const& _other) const { - if (_other->getCategory() != Category::INTEGER_CONSTANT && _other->getCategory() != getCategory()) + if (_other->getCategory() != Category::IntegerConstant && _other->getCategory() != getCategory()) return TypePointer(); auto commonType = dynamic_pointer_cast<IntegerType const>(Type::commonType(shared_from_this(), _other)); @@ -210,11 +212,8 @@ TypePointer IntegerType::binaryOperatorResult(Token::Value _operator, TypePointe const MemberList IntegerType::AddressMemberList = MemberList({{"balance", make_shared<IntegerType >(256)}, - {"callstring32", make_shared<FunctionType>(strings{"string32"}, strings{}, - FunctionType::Location::BARE)}, - {"callstring32string32", make_shared<FunctionType>(strings{"string32", "string32"}, - strings{}, FunctionType::Location::BARE)}, - {"send", make_shared<FunctionType>(strings{"uint"}, strings{}, FunctionType::Location::SEND)}}); + {"call", make_shared<FunctionType>(strings(), strings(), FunctionType::Location::Bare, true)}, + {"send", make_shared<FunctionType>(strings{"uint"}, strings{}, FunctionType::Location::Send)}}); IntegerConstantType::IntegerConstantType(Literal const& _literal) { @@ -254,13 +253,13 @@ TypePointer IntegerConstantType::unaryOperatorResult(Token::Value _operator) con bigint value; switch (_operator) { - case Token::BIT_NOT: + case Token::BitNot: value = ~m_value; break; - case Token::ADD: + case Token::Add: value = m_value; break; - case Token::SUB: + case Token::Sub: value = -m_value; break; default: @@ -271,7 +270,7 @@ TypePointer IntegerConstantType::unaryOperatorResult(Token::Value _operator) con TypePointer IntegerConstantType::binaryOperatorResult(Token::Value _operator, TypePointer const& _other) const { - if (_other->getCategory() == Category::INTEGER) + if (_other->getCategory() == Category::Integer) { shared_ptr<IntegerType const> integerType = getIntegerType(); if (!integerType) @@ -295,34 +294,42 @@ TypePointer IntegerConstantType::binaryOperatorResult(Token::Value _operator, Ty bigint value; switch (_operator) { - case Token::BIT_OR: + case Token::BitOr: value = m_value | other.m_value; break; - case Token::BIT_XOR: + case Token::BitXor: value = m_value ^ other.m_value; break; - case Token::BIT_AND: + case Token::BitAnd: value = m_value & other.m_value; break; - case Token::ADD: + case Token::Add: value = m_value + other.m_value; break; - case Token::SUB: + case Token::Sub: value = m_value - other.m_value; break; - case Token::MUL: + case Token::Mul: value = m_value * other.m_value; break; - case Token::DIV: + case Token::Div: if (other.m_value == 0) return TypePointer(); value = m_value / other.m_value; break; - case Token::MOD: + case Token::Mod: if (other.m_value == 0) return TypePointer(); value = m_value % other.m_value; break; + case Token::Exp: + if (other.m_value < 0) + return TypePointer(); + else if (other.m_value > std::numeric_limits<unsigned int>::max()) + return TypePointer(); + else + value = boost::multiprecision::pow(m_value, other.m_value.convert_to<unsigned int>()); + break; default: return TypePointer(); } @@ -374,8 +381,8 @@ shared_ptr<IntegerType const> IntegerConstantType::getIntegerType() const return shared_ptr<IntegerType const>(); else return make_shared<IntegerType>(max(bytesRequired(value), 1u) * 8, - negative ? IntegerType::Modifier::SIGNED - : IntegerType::Modifier::UNSIGNED); + negative ? IntegerType::Modifier::Signed + : IntegerType::Modifier::Unsigned); } shared_ptr<StaticStringType> StaticStringType::smallestTypeForLiteral(string const& _literal) @@ -401,13 +408,16 @@ bool StaticStringType::isImplicitlyConvertibleTo(Type const& _convertTo) const bool StaticStringType::isExplicitlyConvertibleTo(Type const& _convertTo) const { - if (_convertTo.getCategory() == Category::INTEGER) + if (_convertTo.getCategory() == getCategory()) + return true; + if (_convertTo.getCategory() == Category::Integer) { IntegerType const& convertTo = dynamic_cast<IntegerType const&>(_convertTo); if (convertTo.isHash() && (m_bytes * 8 == convertTo.getNumBits())) return true; } - return isImplicitlyConvertibleTo(_convertTo); + + return false; } bool StaticStringType::operator==(Type const& _other) const @@ -443,9 +453,9 @@ bool BoolType::isExplicitlyConvertibleTo(Type const& _convertTo) const u256 BoolType::literalValue(Literal const* _literal) const { solAssert(_literal, ""); - if (_literal->getToken() == Token::TRUE_LITERAL) + if (_literal->getToken() == Token::TrueLiteral) return u256(1); - else if (_literal->getToken() == Token::FALSE_LITERAL) + else if (_literal->getToken() == Token::FalseLiteral) return u256(0); else BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Bool type constructed from non-boolean literal.")); @@ -453,16 +463,16 @@ u256 BoolType::literalValue(Literal const* _literal) const TypePointer BoolType::unaryOperatorResult(Token::Value _operator) const { - if (_operator == Token::DELETE) + if (_operator == Token::Delete) return make_shared<VoidType>(); - return (_operator == Token::NOT) ? shared_from_this() : TypePointer(); + return (_operator == Token::Not) ? shared_from_this() : TypePointer(); } TypePointer BoolType::binaryOperatorResult(Token::Value _operator, TypePointer const& _other) const { if (getCategory() != _other->getCategory()) return TypePointer(); - if (Token::isCompareOp(_operator) || _operator == Token::AND || _operator == Token::OR) + if (Token::isCompareOp(_operator) || _operator == Token::And || _operator == Token::Or) return _other; else return TypePointer(); @@ -472,9 +482,9 @@ bool ContractType::isImplicitlyConvertibleTo(Type const& _convertTo) const { if (*this == _convertTo) return true; - if (_convertTo.getCategory() == Category::INTEGER) + if (_convertTo.getCategory() == Category::Integer) return dynamic_cast<IntegerType const&>(_convertTo).isAddress(); - if (_convertTo.getCategory() == Category::CONTRACT) + if (_convertTo.getCategory() == Category::Contract) { auto const& bases = getContractDefinition().getLinearizedBaseContracts(); if (m_super && bases.size() <= 1) @@ -487,13 +497,13 @@ bool ContractType::isImplicitlyConvertibleTo(Type const& _convertTo) const bool ContractType::isExplicitlyConvertibleTo(Type const& _convertTo) const { - return isImplicitlyConvertibleTo(_convertTo) || _convertTo.getCategory() == Category::INTEGER || - _convertTo.getCategory() == Category::CONTRACT; + return isImplicitlyConvertibleTo(_convertTo) || _convertTo.getCategory() == Category::Integer || + _convertTo.getCategory() == Category::Contract; } TypePointer ContractType::unaryOperatorResult(Token::Value _operator) const { - return _operator == Token::DELETE ? make_shared<VoidType>() : TypePointer(); + return _operator == Token::Delete ? make_shared<VoidType>() : TypePointer(); } bool ContractType::operator==(Type const& _other) const @@ -557,7 +567,7 @@ u256 ContractType::getFunctionIdentifier(string const& _functionName) const TypePointer StructType::unaryOperatorResult(Token::Value _operator) const { - return _operator == Token::DELETE ? make_shared<VoidType>() : TypePointer(); + return _operator == Token::Delete ? make_shared<VoidType>() : TypePointer(); } bool StructType::operator==(Type const& _other) const @@ -616,7 +626,7 @@ u256 StructType::getStorageOffsetOfMember(string const& _name) const } FunctionType::FunctionType(FunctionDefinition const& _function, bool _isInternal): - m_location(_isInternal ? Location::INTERNAL : Location::EXTERNAL), + m_location(_isInternal ? Location::Internal : Location::External), m_isConstant(_function.isDeclaredConst()), m_declaration(&_function) { @@ -646,7 +656,7 @@ FunctionType::FunctionType(FunctionDefinition const& _function, bool _isInternal } FunctionType::FunctionType(VariableDeclaration const& _varDecl): - m_location(Location::EXTERNAL), m_isConstant(true), m_declaration(&_varDecl) + m_location(Location::External), m_isConstant(true), m_declaration(&_varDecl) { TypePointers params; vector<string> paramNames; @@ -683,7 +693,7 @@ FunctionType::FunctionType(VariableDeclaration const& _varDecl): } FunctionType::FunctionType(const EventDefinition& _event): - m_location(Location::EVENT), m_declaration(&_event) + m_location(Location::Event), m_declaration(&_event) { TypePointers params; vector<string> paramNames; @@ -740,9 +750,9 @@ string FunctionType::toString() const unsigned FunctionType::getSizeOnStack() const { unsigned size = 0; - if (m_location == Location::EXTERNAL) + if (m_location == Location::External) size = 2; - else if (m_location == Location::INTERNAL || m_location == Location::BARE) + else if (m_location == Location::Internal || m_location == Location::Bare) size = 1; if (m_gasSet) size++; @@ -755,22 +765,22 @@ MemberList const& FunctionType::getMembers() const { switch (m_location) { - case Location::EXTERNAL: - case Location::CREATION: - case Location::ECRECOVER: + case Location::External: + case Location::Creation: + case Location::ECRecover: case Location::SHA256: case Location::RIPEMD160: - case Location::BARE: + case Location::Bare: if (!m_members) { map<string, TypePointer> members{ {"gas", make_shared<FunctionType>(parseElementaryTypeVector({"uint"}), TypePointers{copyAndSetGasOrValue(true, false)}, - Location::SET_GAS, m_gasSet, m_valueSet)}, + Location::SetGas, false, m_gasSet, m_valueSet)}, {"value", make_shared<FunctionType>(parseElementaryTypeVector({"uint"}), TypePointers{copyAndSetGasOrValue(false, true)}, - Location::SET_VALUE, m_gasSet, m_valueSet)}}; - if (m_location == Location::CREATION) + Location::SetValue, false, m_gasSet, m_valueSet)}}; + if (m_location == Location::Creation) members.erase("gas"); m_members.reset(new MemberList(members)); } @@ -808,6 +818,7 @@ TypePointers FunctionType::parseElementaryTypeVector(strings const& _types) TypePointer FunctionType::copyAndSetGasOrValue(bool _setGas, bool _setValue) const { return make_shared<FunctionType>(m_parameterTypes, m_returnParameterTypes, m_location, + m_arbitraryParameters, m_gasSet || _setGas, m_valueSet || _setValue); } @@ -865,7 +876,7 @@ MemberList const& TypeType::getMembers() const if (!m_members) { map<string, TypePointer> members; - if (m_actualType->getCategory() == Category::CONTRACT && m_currentContract != nullptr) + if (m_actualType->getCategory() == Category::Contract && m_currentContract != nullptr) { ContractDefinition const& contract = dynamic_cast<ContractType const&>(*m_actualType).getContractDefinition(); vector<ContractDefinition const*> currentBases = m_currentContract->getLinearizedBaseContracts(); @@ -919,21 +930,21 @@ MagicType::MagicType(MagicType::Kind _kind): { switch (m_kind) { - case Kind::BLOCK: - m_members = MemberList({{"coinbase", make_shared<IntegerType>(0, IntegerType::Modifier::ADDRESS)}, + case Kind::Block: + m_members = MemberList({{"coinbase", make_shared<IntegerType>(0, IntegerType::Modifier::Address)}, {"timestamp", make_shared<IntegerType>(256)}, - {"blockhash", make_shared<FunctionType>(strings{"uint"}, strings{"hash"}, FunctionType::Location::BLOCKHASH)}, + {"blockhash", make_shared<FunctionType>(strings{"uint"}, strings{"hash"}, FunctionType::Location::BlockHash)}, {"difficulty", make_shared<IntegerType>(256)}, {"number", make_shared<IntegerType>(256)}, {"gaslimit", make_shared<IntegerType>(256)}}); break; - case Kind::MSG: - m_members = MemberList({{"sender", make_shared<IntegerType>(0, IntegerType::Modifier::ADDRESS)}, + case Kind::Message: + m_members = MemberList({{"sender", make_shared<IntegerType>(0, IntegerType::Modifier::Address)}, {"gas", make_shared<IntegerType>(256)}, {"value", make_shared<IntegerType>(256)}}); break; - case Kind::TX: - m_members = MemberList({{"origin", make_shared<IntegerType>(0, IntegerType::Modifier::ADDRESS)}, + case Kind::Transaction: + m_members = MemberList({{"origin", make_shared<IntegerType>(0, IntegerType::Modifier::Address)}, {"gasprice", make_shared<IntegerType>(256)}}); break; default: @@ -953,11 +964,11 @@ string MagicType::toString() const { switch (m_kind) { - case Kind::BLOCK: + case Kind::Block: return "block"; - case Kind::MSG: + case Kind::Message: return "msg"; - case Kind::TX: + case Kind::Transaction: return "tx"; default: BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Unknown kind of magic.")); |