diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index de3cdc847..39fd694b6 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -1467,24 +1467,25 @@ bool TypeChecker::visit(Conditional const& _conditional) _conditional.trueExpression().accept(*this); _conditional.falseExpression().accept(*this); - Type const* trueType = type(_conditional.trueExpression())->mobileType(); - Type const* falseType = type(_conditional.falseExpression())->mobileType(); - + Type const* trueType = type(_conditional.trueExpression()); + Type const* falseType = type(_conditional.falseExpression()); + Type const* trueMobileType = trueType->mobileType(); + Type const* falseMobileType = falseType->mobileType(); Type const* commonType = nullptr; - if (!trueType) - m_errorReporter.typeError(9717_error, _conditional.trueExpression().location(), "Invalid mobile type in true expression."); - else + if (trueMobileType) commonType = trueType; - - if (!falseType) - m_errorReporter.typeError(3703_error, _conditional.falseExpression().location(), "Invalid mobile type in false expression."); else - commonType = falseType; + m_errorReporter.typeError(9717_error, _conditional.trueExpression().location(), "Invalid mobile type in true expression."); - if (!trueType && !falseType) + if (falseMobileType) + commonType = falseType; + else + m_errorReporter.typeError(3703_error, _conditional.falseExpression().location(), "Invalid mobile type in false expression."); + + if (!trueMobileType && !falseMobileType) BOOST_THROW_EXCEPTION(FatalError()); - else if (trueType && falseType) + else if (trueMobileType && falseMobileType) { commonType = Type::commonType(trueType, falseType); @@ -1494,14 +1495,14 @@ bool TypeChecker::visit(Conditional const& _conditional) 1080_error, _conditional.location(), "True expression's type " + - trueType->humanReadableName() + + trueMobileType->humanReadableName() + " does not match false expression's type " + - falseType->humanReadableName() + + falseMobileType->humanReadableName() + "." ); // 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; + commonType = trueMobileType; } } diff --git a/test/libsolidity/semanticTests/literals/ternary_operator_with_rationals.sol b/test/libsolidity/semanticTests/literals/ternary_operator_with_rationals.sol new file mode 100644 index 000000000..79c2fe956 --- /dev/null +++ b/test/libsolidity/semanticTests/literals/ternary_operator_with_rationals.sol @@ -0,0 +1,22 @@ +contract C { + function f(int a, int b) public returns (int) { + return a < b ? -1 : 1; + } + + function g(int a) public returns (int) { + int8 b = -1; + return a < 0 ? b : 1; + } + + function h(int a) public returns (int) { + int8 b = -1; + return a < 0 ? 1 : b; + } +} +// ---- +// f(int256,int256): 0, 2 -> -1 +// f(int256,int256): 2, 0 -> 1 +// g(int256): -2 -> -1 +// g(int256): 2 -> 1 +// h(int256): -2 -> 1 +// h(int256): 2 -> -1 diff --git a/test/libsolidity/syntaxTests/literals/ternary_operator_with_address_arguments.sol b/test/libsolidity/syntaxTests/literals/ternary_operator_with_address_arguments.sol new file mode 100644 index 000000000..a4a096360 --- /dev/null +++ b/test/libsolidity/syntaxTests/literals/ternary_operator_with_address_arguments.sol @@ -0,0 +1,14 @@ +contract C { + function f(bool cond) public { + // OK + address a1 = cond ? 0xdCad3a6d3569DF655070DEd06cb7A1b2Ccd1D3AF : payable(0x1234567890123456789012345678901234567890); + address a2 = cond ? address(0xdCad3a6d3569DF655070DEd06cb7A1b2Ccd1D3AF) : 0x1234567890123456789012345678901234567890; + + // Errors + address payable a3 = cond ? 0xdCad3a6d3569DF655070DEd06cb7A1b2Ccd1D3AF : payable(0x1234567890123456789012345678901234567890); + cond ? 0xdCad3a6d3569DF655070DEd06cb7A1b2Ccd1D3AF : 1; + } +} +// ---- +// TypeError 9574: (346-470): Type address is not implicitly convertible to expected type address payable. +// TypeError 1080: (481-534): True expression's type address does not match false expression's type uint8. diff --git a/test/libsolidity/syntaxTests/literals/ternary_operator_with_byte_and_string_arguments.sol b/test/libsolidity/syntaxTests/literals/ternary_operator_with_byte_and_string_arguments.sol new file mode 100644 index 000000000..d5f7d0c47 --- /dev/null +++ b/test/libsolidity/syntaxTests/literals/ternary_operator_with_byte_and_string_arguments.sol @@ -0,0 +1,16 @@ +contract C { + function f(bool cond) public { + // OK + string memory v1 = cond ? "foo" : string("bar"); + bytes1 v2 = cond ? bytes1("a") : "a"; + bytes2 v3 = cond ? bytes2("a") : "a"; + bytes2 v4 = cond ? bytes1("a") : bytes2("ab"); + + // Errors + cond ? bytes1("a") : string("b"); + cond ? 1 : bytes1("a"); + } +} +// ---- +// TypeError 1080: (300-332): True expression's type bytes1 does not match false expression's type string memory. +// TypeError 1080: (343-365): True expression's type uint8 does not match false expression's type bytes1. diff --git a/test/libsolidity/syntaxTests/literals/ternary_operator_with_new.sol b/test/libsolidity/syntaxTests/literals/ternary_operator_with_new.sol new file mode 100644 index 000000000..8b7ee1d54 --- /dev/null +++ b/test/libsolidity/syntaxTests/literals/ternary_operator_with_new.sol @@ -0,0 +1,27 @@ +contract C { + function f(bool cond, bytes calldata cbytes) public view { + bytes1[2] memory marray; + bytes1[2] storage sarray; + uint8[2] memory uint8Array; + int16[2] memory int16Array; + bytes memory mbytes; + + // OK + bytes1[2] memory marray1 = cond ? sarray : marray; + bytes1[2] memory marray2 = cond ? marray : sarray; + bytes memory mbytes1 = cond ? cbytes[1:2] : mbytes; + bytes memory mbytes2 = cond ? mbytes : cbytes[1:2]; + + // Errors + bytes1[2] storage sarray1 = cond ? sarray : marray; + bytes1[2] storage sarray2 = cond ? marray : sarray; + + cond ? uint8Array : int16Array; + cond ? [1, 2] : [-1, -3]; + } +} +// ---- +// TypeError 9574: (517-567): Type bytes1[2] memory is not implicitly convertible to expected type bytes1[2] storage pointer. +// TypeError 9574: (577-627): Type bytes1[2] memory is not implicitly convertible to expected type bytes1[2] storage pointer. +// TypeError 1080: (638-668): True expression's type uint8[2] memory does not match false expression's type int16[2] memory. +// TypeError 1080: (678-702): True expression's type uint8[2] memory does not match false expression's type int8[2] memory. diff --git a/test/libsolidity/syntaxTests/literals/ternary_operator_with_rational_arguments.sol b/test/libsolidity/syntaxTests/literals/ternary_operator_with_rational_arguments.sol new file mode 100644 index 000000000..deb39da32 --- /dev/null +++ b/test/libsolidity/syntaxTests/literals/ternary_operator_with_rational_arguments.sol @@ -0,0 +1,30 @@ +contract C { + function f(bool cond) public { + // OK + int8 v1 = cond ? -1 : 1; + int16 v2 = cond ? -32768 : 1; + int16 v3 = cond ? -32768 : -1; + int16 v4 = cond ? -32768 : int8(1); + int16 v5 = cond ? int16(1) : 1; + uint16 v6 = cond ? uint16(1) : 1; + ufixed8x1 v7 = cond ? 1.0 : 1.1; + ufixed8x1 v8 = cond ? 0 : 1.1; + fixed8x1 v9 = cond ? -1.0 : -1.1; + fixed8x1 v10 = cond ? -1.1 : 1; + + // Errors + cond ? 32768 : -1; + cond ? int16(-1) : uint8(1); + cond ? int8(-1) : uint8(1); + cond ? -1 : 1.1; + cond ? -1.0 : 1.1; + cond ? true : 1; + } +} +// ---- +// TypeError 1080: (500-517): True expression's type uint16 does not match false expression's type int8. +// TypeError 1080: (528-555): True expression's type int16 does not match false expression's type uint8. +// TypeError 1080: (566-592): True expression's type int8 does not match false expression's type uint8. +// TypeError 1080: (603-618): True expression's type int8 does not match false expression's type ufixed8x1. +// TypeError 1080: (629-646): True expression's type int8 does not match false expression's type ufixed8x1. +// TypeError 1080: (657-672): True expression's type bool does not match false expression's type uint8. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/invalidTypes/conditional_expression.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/invalidTypes/conditional_expression.sol index e7abd890d..278975c45 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/invalidTypes/conditional_expression.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/invalidTypes/conditional_expression.sol @@ -9,8 +9,8 @@ contract C { } // ---- // TypeError 9717: (94-100): Invalid mobile type in true expression. -// TypeError 9553: (87-105): Invalid type for argument in function call. Invalid implicit conversion from uint8 to bytes1 requested. +// TypeError 9553: (87-105): Invalid type for argument in function call. Invalid implicit conversion from int_const 99 to bytes1 requested. // TypeError 3703: (130-136): Invalid mobile type in false expression. -// TypeError 9553: (118-136): Invalid type for argument in function call. Invalid implicit conversion from uint8 to bytes1 requested. +// TypeError 9553: (118-136): Invalid type for argument in function call. Invalid implicit conversion from int_const 99 to bytes1 requested. // TypeError 9717: (157-163): Invalid mobile type in true expression. // TypeError 3703: (166-172): Invalid mobile type in false expression.