Browse Source

Some fixes for the ether units parser.

cl-refactor
Christian 10 years ago
parent
commit
a90ec7576c
  1. 11
      libsolidity/AST.cpp
  2. 3
      libsolidity/AST.h
  3. 16
      libsolidity/Parser.cpp
  4. 44
      libsolidity/Types.cpp
  5. 3
      libsolidity/Types.h
  6. 22
      test/SolidityNameAndTypeResolution.cpp
  7. 13
      test/SolidityParser.cpp

11
libsolidity/AST.cpp

@ -596,17 +596,6 @@ void ElementaryTypeNameExpression::checkTypeRequirements()
m_type = make_shared<TypeType>(Type::fromElementaryTypeName(m_typeToken)); m_type = make_shared<TypeType>(Type::fromElementaryTypeName(m_typeToken));
} }
Literal::Literal(Location const& _location, Token::Value _token,
ASTPointer<ASTString> const& _value,
Token::Value _sub):
PrimaryExpression(_location), m_token(_token), m_value(_value)
{
if (Token::isEtherSubdenomination(_sub))
m_subDenomination = static_cast<Literal::SubDenomination>(_sub);
else
m_subDenomination = Literal::SubDenomination::None;
}
void Literal::checkTypeRequirements() void Literal::checkTypeRequirements()
{ {
m_type = Type::forLiteral(*this); m_type = Type::forLiteral(*this);

3
libsolidity/AST.h

@ -1127,7 +1127,8 @@ public:
}; };
Literal(Location const& _location, Token::Value _token, Literal(Location const& _location, Token::Value _token,
ASTPointer<ASTString> const& _value, ASTPointer<ASTString> const& _value,
Token::Value _sub = Token::ILLEGAL); SubDenomination _sub = SubDenomination::None):
PrimaryExpression(_location), m_token(_token), m_value(_value), m_subDenomination(_sub) {}
virtual void accept(ASTVisitor& _visitor) override; virtual void accept(ASTVisitor& _visitor) override;
virtual void accept(ASTConstVisitor& _visitor) const override; virtual void accept(ASTConstVisitor& _visitor) const override;
virtual void checkTypeRequirements() override; virtual void checkTypeRequirements() override;

16
libsolidity/Parser.cpp

@ -684,7 +684,6 @@ ASTPointer<Expression> Parser::parsePrimaryExpression()
ASTNodeFactory nodeFactory(*this); ASTNodeFactory nodeFactory(*this);
Token::Value token = m_scanner->getCurrentToken(); Token::Value token = m_scanner->getCurrentToken();
ASTPointer<Expression> expression; ASTPointer<Expression> expression;
Token::Value nextToken = Token::ILLEGAL;
switch (token) switch (token)
{ {
case Token::TRUE_LITERAL: case Token::TRUE_LITERAL:
@ -692,12 +691,19 @@ ASTPointer<Expression> Parser::parsePrimaryExpression()
expression = nodeFactory.createNode<Literal>(token, getLiteralAndAdvance()); expression = nodeFactory.createNode<Literal>(token, getLiteralAndAdvance());
break; break;
case Token::NUMBER: case Token::NUMBER:
nextToken = m_scanner->peekNextToken(); if (Token::isEtherSubdenomination(m_scanner->peekNextToken()))
case Token::STRING_LITERAL: {
ASTPointer<ASTString> literal = getLiteralAndAdvance();
nodeFactory.markEndPosition(); nodeFactory.markEndPosition();
expression = nodeFactory.createNode<Literal>(token, getLiteralAndAdvance(), nextToken); Literal::SubDenomination subdenomination = static_cast<Literal::SubDenomination>(m_scanner->getCurrentToken());
if (Token::isEtherSubdenomination(nextToken))
m_scanner->next(); m_scanner->next();
expression = nodeFactory.createNode<Literal>(token, literal, subdenomination);
break;
}
// fall-through
case Token::STRING_LITERAL:
nodeFactory.markEndPosition();
expression = nodeFactory.createNode<Literal>(token, getLiteralAndAdvance());
break; break;
case Token::IDENTIFIER: case Token::IDENTIFIER:
nodeFactory.markEndPosition(); nodeFactory.markEndPosition();

44
libsolidity/Types.cpp

@ -91,7 +91,7 @@ shared_ptr<Type const> Type::forLiteral(Literal const& _literal)
case Token::FALSE_LITERAL: case Token::FALSE_LITERAL:
return make_shared<BoolType>(); return make_shared<BoolType>();
case Token::NUMBER: case Token::NUMBER:
return IntegerConstantType::fromLiteral(_literal.getValue()); return make_shared<IntegerConstantType>(_literal);
case Token::STRING_LITERAL: case Token::STRING_LITERAL:
//@todo put larger strings into dynamic strings //@todo put larger strings into dynamic strings
return StaticStringType::smallestTypeForLiteral(_literal.getValue()); return StaticStringType::smallestTypeForLiteral(_literal.getValue());
@ -216,9 +216,25 @@ const MemberList IntegerType::AddressMemberList =
strings{}, FunctionType::Location::BARE)}, strings{}, FunctionType::Location::BARE)},
{"send", make_shared<FunctionType>(strings{"uint"}, strings{}, FunctionType::Location::SEND)}}); {"send", make_shared<FunctionType>(strings{"uint"}, strings{}, FunctionType::Location::SEND)}});
shared_ptr<IntegerConstantType const> IntegerConstantType::fromLiteral(string const& _literal) IntegerConstantType::IntegerConstantType(Literal const& _literal)
{ {
return make_shared<IntegerConstantType>(bigint(_literal)); m_value = bigint(_literal.getValue());
switch (_literal.getSubDenomination())
{
case Literal::SubDenomination::Wei:
case Literal::SubDenomination::None:
break;
case Literal::SubDenomination::Szabo:
m_value *= bigint("1000000000000");
break;
case Literal::SubDenomination::Finney:
m_value *= bigint("1000000000000000");
break;
case Literal::SubDenomination::Ether:
m_value *= bigint("1000000000000000000");
break;
}
} }
bool IntegerConstantType::isImplicitlyConvertibleTo(Type const& _convertTo) const bool IntegerConstantType::isImplicitlyConvertibleTo(Type const& _convertTo) const
@ -326,7 +342,7 @@ string IntegerConstantType::toString() const
return "int_const " + m_value.str(); return "int_const " + m_value.str();
} }
u256 IntegerConstantType::literalValue(Literal const* _literal) const u256 IntegerConstantType::literalValue(Literal const*) const
{ {
u256 value; u256 value;
// we ignore the literal and hope that the type was correctly determined // we ignore the literal and hope that the type was correctly determined
@ -338,26 +354,6 @@ u256 IntegerConstantType::literalValue(Literal const* _literal) const
else else
value = s2u(s256(m_value)); value = s2u(s256(m_value));
if (_literal)
{
Literal::SubDenomination sub =_literal->getSubDenomination();
switch(sub)
{
case Literal::SubDenomination::Wei:
case Literal::SubDenomination::None:
break;
case Literal::SubDenomination::Szabo:
value *= u256(1000000000000);
break;
case Literal::SubDenomination::Finney:
value *= u256(1000000000000000);
break;
case Literal::SubDenomination::Ether:
value *= u256(1000000000000000000);
break;
}
}
return value; return value;
} }

3
libsolidity/Types.h

@ -197,8 +197,7 @@ class IntegerConstantType: public Type
public: public:
virtual Category getCategory() const override { return Category::INTEGER_CONSTANT; } virtual Category getCategory() const override { return Category::INTEGER_CONSTANT; }
static std::shared_ptr<IntegerConstantType const> fromLiteral(std::string const& _literal); explicit IntegerConstantType(Literal const& _literal);
explicit IntegerConstantType(bigint _value): m_value(_value) {} explicit IntegerConstantType(bigint _value): m_value(_value) {}
virtual bool isImplicitlyConvertibleTo(Type const& _convertTo) const override; virtual bool isImplicitlyConvertibleTo(Type const& _convertTo) const override;

22
test/SolidityNameAndTypeResolution.cpp

@ -910,6 +910,28 @@ BOOST_AUTO_TEST_CASE(disallow_declaration_of_void_type)
BOOST_CHECK_THROW(parseTextAndResolveNames(sourceCode), TypeError); BOOST_CHECK_THROW(parseTextAndResolveNames(sourceCode), TypeError);
} }
BOOST_AUTO_TEST_CASE(overflow_caused_by_ether_units)
{
char const* sourceCodeFine = R"(
contract c {
function c ()
{
a = 115792089237316195423570985008687907853269984665640564039458;
}
uint256 a;
})";
BOOST_CHECK_NO_THROW(parseTextAndResolveNames(sourceCodeFine));
char const* sourceCode = R"(
contract c {
function c ()
{
a = 115792089237316195423570985008687907853269984665640564039458 ether;
}
uint256 a;
})";
BOOST_CHECK_THROW(parseTextAndResolveNames(sourceCode), TypeError);
}
BOOST_AUTO_TEST_SUITE_END() BOOST_AUTO_TEST_SUITE_END()
} }

13
test/SolidityParser.cpp

@ -679,6 +679,19 @@ BOOST_AUTO_TEST_CASE(literal_constants_with_ether_subdenominations)
BOOST_CHECK_NO_THROW(parseTextExplainError(text)); BOOST_CHECK_NO_THROW(parseTextExplainError(text));
} }
BOOST_AUTO_TEST_CASE(literal_constants_with_ether_subdenominations_in_expressions)
{
char const* text = R"(
contract c {
function c ()
{
a = 1 wei * 100 wei + 7 szabo - 3;
}
uint256 a;
})";
BOOST_CHECK_NO_THROW(parseTextExplainError(text));
}
BOOST_AUTO_TEST_SUITE_END() BOOST_AUTO_TEST_SUITE_END()
} }

Loading…
Cancel
Save