From bf7daf0814ac17fece679a9d1aa187a8bdcf901b Mon Sep 17 00:00:00 2001 From: Lu Guanqun Date: Mon, 11 Jan 2016 15:08:28 +0800 Subject: [cond-expr] don't allow conditional as left value for the first stage --- libsolidity/analysis/TypeChecker.cpp | 68 ++++++++-------------- test/libsolidity/SolidityEndToEndTest.cpp | 16 ----- test/libsolidity/SolidityNameAndTypeResolution.cpp | 6 +- 3 files changed, 29 insertions(+), 61 deletions(-) diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index f3840675..8f1b2b9d 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -748,55 +748,37 @@ bool TypeChecker::visit(Conditional const& _conditional) { expectType(_conditional.condition(), BoolType()); - if (_conditional.annotation().lValueRequested) - { - requireLValue(_conditional.trueExpression()); - requireLValue(_conditional.falseExpression()); - - TypePointer const& trueType = type(_conditional.trueExpression()); - TypePointer const& falseType = type(_conditional.falseExpression()); + _conditional.trueExpression().accept(*this); + _conditional.falseExpression().accept(*this); - // as a left value, we require exact match to prevent subtle conversion issues. - if (*trueType != *falseType) - typeError( - _conditional.location(), - "True expression's type " + - trueType->toString() + - " doesn't match false expression's type " + - falseType->toString() + - "." - ); + TypePointer const& trueType = type(_conditional.trueExpression()); + TypePointer const& falseType = type(_conditional.falseExpression()); - _conditional.annotation().type = trueType; - _conditional.annotation().isLValue = true; - } - else + // we fake it as an equal operator, but any other comparison operator can work. + TypePointer commonType = trueType->binaryOperatorResult(Token::Equal, falseType); + if (!commonType) { - _conditional.trueExpression().accept(*this); - _conditional.falseExpression().accept(*this); + typeError( + _conditional.location(), + "True expression's type " + + trueType->toString() + + " doesn't match false expression's type " + + falseType->toString() + + "." + ); + // even we can't find a common type, we have to set a type here, + // otherwise the upper statement will not be able to check the type. + commonType = trueType; + } - TypePointer const& trueType = type(_conditional.trueExpression()); - TypePointer const& falseType = type(_conditional.falseExpression()); + _conditional.annotation().type = commonType; - // we fake it as an equal operator, but any other comparison operator can work. - TypePointer commonType = trueType->binaryOperatorResult(Token::Equal, falseType); - if (!commonType) - { - typeError( - _conditional.location(), - "True expression's type " + - trueType->toString() + - " doesn't match false expression's type " + - falseType->toString() + - "." - ); - // even we can't find a common type, we have to set a type here, - // otherwise the upper statement will not be able to check the type. - commonType = trueType; - } + if (_conditional.annotation().lValueRequested) + typeError( + _conditional.location(), + "Conditional expression as left value is not supported yet." + ); - _conditional.annotation().type = commonType; - } return false; } diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp index 3b9b8449..be291735 100644 --- a/test/libsolidity/SolidityEndToEndTest.cpp +++ b/test/libsolidity/SolidityEndToEndTest.cpp @@ -128,22 +128,6 @@ BOOST_AUTO_TEST_CASE(conditional_expression_multiple) BOOST_CHECK(callContractFunction("f(uint256)", u256(40)) == toBigEndian(u256(10))); } -BOOST_AUTO_TEST_CASE(conditional_expression_as_left_value) -{ - char const* sourceCode = R"( - contract test { - function f(uint x) returns(uint d) { - uint y = 1; - uint z = 1; - (x > 10 ? y : z) = 3; - return y ** z; - } - })"; - compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("f(uint256)", u256(20)) == toBigEndian(u256(3))); - BOOST_CHECK(callContractFunction("f(uint256)", u256(5)) == toBigEndian(u256(1))); -} - BOOST_AUTO_TEST_CASE(conditional_expression_with_return_values) { char const* sourceCode = R"( diff --git a/test/libsolidity/SolidityNameAndTypeResolution.cpp b/test/libsolidity/SolidityNameAndTypeResolution.cpp index 73f6a6c8..7cd92c9c 100644 --- a/test/libsolidity/SolidityNameAndTypeResolution.cpp +++ b/test/libsolidity/SolidityNameAndTypeResolution.cpp @@ -2972,12 +2972,14 @@ BOOST_AUTO_TEST_CASE(invalid_different_types_for_conditional_expression) BOOST_CHECK(expectError(text) == Error::Type::TypeError); } -BOOST_AUTO_TEST_CASE(invalid_left_value_in_conditional_expression) +BOOST_AUTO_TEST_CASE(left_value_in_conditional_expression_not_supported_yet) { char const* text = R"( contract C { function f() { - (true ? 3 : 5) = 1; + uint x; + uint y; + (true ? x : y) = 1; } } )"; -- cgit