diff options
38 files changed, 452 insertions, 493 deletions
diff --git a/Changelog.md b/Changelog.md index 0050f9a6..61a6c693 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,33 +1,34 @@ ### 0.5.0 (unreleased) -Language Features: - * General: Support ``pop()`` for storage arrays. - Breaking Changes: - * Disallow conversions between bytesX and uintY of different size. + * ABI Encoder: Properly pad data from calldata (``msg.data`` and external function parameters). Use ``abi.encodePacked`` for unpadded encoding. + * Code Generator: Signed right shift uses proper arithmetic shift, i.e. rounding towards negative infinity. Warning: this may silently change the semantics of existing code! + * Commandline interface: Remove obsolete ``--formal`` option. * Commandline interface: Require ``-`` if standard input is used as source. - * General: New keywords: ``calldata`` * General: ``continue`` in a ``do...while`` loop jumps to the condition (it used to jump to the loop body). Warning: this may silently change the semantics of existing code. - * Introduce ``emit`` as a keyword instead of parsing it as identifier. - * Type Checker: Disallow arithmetic operations for Boolean variables. - * Disallow trailing dots that are not followed by a number. - * Remove assembly instructions ``sha3`` and ``suicide`` + * General: Disallow ``sha3`` and ``suicide`` aliases. + * General: Introduce ``emit`` as a keyword instead of parsing it as identifier. + * General: New keywords: ``calldata`` + * General: New reserved keywords: ``alias``, ``apply``, ``auto``, ``copyof``, ``define``, ``immutable``, + ``implements``, ``macro``, ``mutable``, ``override``, ``partial``, ``promise``, ``reference``, ``sealed``, + ``sizeof``, ``supports``, ``typedef`` and ``unchecked``. + * General: Remove assembly instruction aliases ``sha3`` and ``suicide`` + * Parser: Disallow trailing dots that are not followed by a number. + * Type Checker: Disallow arithmetic operations for boolean variables. + * Type Checker: Disallow conversions between ``bytesX`` and ``uintY`` of different size. + * Remove obsolete ``std`` directory from the Solidity repository. This means accessing ``https://github.com/ethereum/soldity/blob/develop/std/*.sol`` (or ``https://github.com/ethereum/solidity/std/*.sol`` in Remix) will not be possible. Language Features: * General: Allow appending ``calldata`` keyword to types, to explicitly specify data location for arguments of external functions. + * General: Support ``pop()`` for storage arrays. -Bugfixes: - - - -Features: +Compiler Features: * Type Checker: Show named argument in case of error. Bugfixes: ### 0.4.24 (2018-05-16) - Language Features: * Code Generator: Use native shift instructions on target Constantinople. * General: Allow multiple variables to be declared as part of a tuple assignment, e.g. ``(uint a, uint b) = ...``. diff --git a/docs/contributing.rst b/docs/contributing.rst index 6717a8b9..b95cff1a 100644 --- a/docs/contributing.rst +++ b/docs/contributing.rst @@ -111,7 +111,7 @@ Example: ``./test/libsolidity/syntaxTests/double_stateVariable_declaration.sol`` A syntax test must contain at least the contract under test itself, followed by the seperator ``----``. The additional comments above are used to describe the expected compiler errors or warnings. This section can be empty in case that the contract should compile without any errors or warnings. -In the above example, the state variable ``variable`` was declared twice, which is not allowed. This will result in a ``DeclarationError`` stating that the identifer was already declared. +In the above example, the state variable ``variable`` was declared twice, which is not allowed. This will result in a ``DeclarationError`` stating that the identifier was already declared. The tool that is being used for those tests is called ``isoltest`` and can be found under ``./test/tools/``. It is an interactive tool which allows editing of failing contracts using your prefered text editor. Let's try to break this test by removing the second declaration of ``variable``: diff --git a/docs/index.rst b/docs/index.rst index 80b0d6e7..a57b93e4 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -169,7 +169,7 @@ Contents using-the-compiler.rst metadata.rst abi-spec.rst - julia.rst + yul.rst style-guide.rst common-patterns.rst bugs.rst diff --git a/docs/miscellaneous.rst b/docs/miscellaneous.rst index c7c32528..108d4c96 100644 --- a/docs/miscellaneous.rst +++ b/docs/miscellaneous.rst @@ -190,7 +190,7 @@ important for static analysis tools that operate on bytecode level and for displaying the current position in the source code inside a debugger or for breakpoint handling. -Both kinds of source mappings use integer indentifiers to refer to source files. +Both kinds of source mappings use integer identifiers to refer to source files. These are regular array indices into a list of source files usually called ``"sourceList"``, which is part of the combined-json and the output of the json / npm compiler. @@ -409,8 +409,11 @@ Reserved Keywords These keywords are reserved in Solidity. They might become part of the syntax in the future: -``abstract``, ``after``, ``case``, ``catch``, ``default``, ``final``, ``in``, ``inline``, ``let``, ``match``, ``null``, -``of``, ``relocatable``, ``static``, ``switch``, ``try``, ``type``, ``typeof``. +``abstract``, ``after``, ``alias``, ``apply``, ``auto``, ``case``, ``catch``, ``copyof``, ``default``, +``define``, ``final``, ``immutable``, ``implements``, ``in``, ``inline``, ``let``, ``macro``, ``match``, +``mutable``, ``null``, ``of``, ``override``, ``partial``, ``promise``, ``reference``, ``relocatable``, +``sealed``, ``sizeof``, ``static``, ``supports``, ``switch``, ``try``, ``type``, ``typedef``, ``typeof``, +``unchecked``. Language Grammar ================ diff --git a/docs/types.rst b/docs/types.rst index 08b74241..009896d5 100644 --- a/docs/types.rst +++ b/docs/types.rst @@ -60,15 +60,14 @@ operators are :ref:`literals<rational_literals>` (or literal expressions). Division by zero and modulus with zero throws a runtime exception. The result of a shift operation is the type of the left operand. The -expression ``x << y`` is equivalent to ``x * 2**y``, and ``x >> y`` is -equivalent to ``x / 2**y``. This means that shifting negative numbers -sign extends. Shifting by a negative amount throws a runtime exception. +expression ``x << y`` is equivalent to ``x * 2**y``, and, for positive integers, +``x >> y`` is equivalent to ``x / 2**y``. For negative ``x``, ``x >> y`` +is equivalent to dividing by a power of ``2`` while rounding down (towards negative infinity). +Shifting by a negative amount throws a runtime exception. .. warning:: - The results produced by shift right of negative values of signed integer types is different from those produced - by other programming languages. In Solidity, shift right maps to division so the shifted negative values - are going to be rounded towards zero (truncated). In other programming languages the shift right of negative values - works like division with rounding down (towards negative infinity). + Before version ``0.5.0`` a right shift ``x >> y`` for negative ``x`` was equivalent to ``x / 2**y``, + i.e. right shifts used rounding towards zero instead of rounding towards negative infinity. .. index:: ! ufixed, ! fixed, ! fixed point number diff --git a/docs/julia.rst b/docs/yul.rst index 91b91df2..4f5ef98f 100644 --- a/docs/julia.rst +++ b/docs/yul.rst @@ -1,18 +1,19 @@ -################################################# -Joyfully Universal Language for (Inline) Assembly -################################################# +### +Yul +### -.. _julia: +.. _yul: -.. index:: ! assembly, ! asm, ! evmasm, ! julia +.. index:: ! assembly, ! asm, ! evmasm, ! yul, julia, iulia -JULIA is an intermediate language that can compile to various different backends +Yul (previously also called JULIA or IULIA) is an intermediate language that can +compile to various different backends (EVM 1.0, EVM 1.5 and eWASM are planned). Because of that, it is designed to be a usable common denominator of all three platforms. It can already be used for "inline assembly" inside Solidity and -future versions of the Solidity compiler will even use JULIA as intermediate -language. It should also be easy to build high-level optimizer stages for JULIA. +future versions of the Solidity compiler will even use Yul as intermediate +language. It should also be easy to build high-level optimizer stages for Yul. .. note:: @@ -21,14 +22,14 @@ language. It should also be easy to build high-level optimizer stages for JULIA. to the EVM opcodes. Please resort to the inline assembly documentation for details. -The core components of JULIA are functions, blocks, variables, literals, +The core components of Yul are functions, blocks, variables, literals, for-loops, if-statements, switch-statements, expressions and assignments to variables. -JULIA is typed, both variables and literals must specify the type with postfix +Yul is typed, both variables and literals must specify the type with postfix notation. The supported types are ``bool``, ``u8``, ``s8``, ``u32``, ``s32``, ``u64``, ``s64``, ``u128``, ``s128``, ``u256`` and ``s256``. -JULIA in itself does not even provide operators. If the EVM is targeted, +Yul in itself does not even provide operators. If the EVM is targeted, opcodes will be available as built-in functions, but they can be reimplemented if the backend changes. For a list of mandatory built-in functions, see the section below. @@ -69,10 +70,10 @@ and ``add`` to be available. } } -Specification of JULIA -====================== +Specification of Yul +==================== -JULIA code is described in this chapter. JULIA code is usually placed into a JULIA object, which is described in the following chapter. +This chapter describes Yul code. It is usually placed inside a Yul object, which is described in the following chapter. Grammar:: @@ -156,7 +157,7 @@ Literals cannot be larger than the their type. The largest type defined is 256-b Scoping Rules ------------- -Scopes in JULIA are tied to Blocks (exceptions are functions and the for loop +Scopes in Yul are tied to Blocks (exceptions are functions and the for loop as explained below) and all declarations (``FunctionDefinition``, ``VariableDeclaration``) introduce new identifiers into these scopes. @@ -186,7 +187,7 @@ outside of that function. Formal Specification -------------------- -We formally specify JULIA by providing an evaluation function E overloaded +We formally specify Yul by providing an evaluation function E overloaded on the various nodes of the AST. Any functions can have side effects, so E takes two state objects and the AST node and returns two new state objects and a variable number of other values. @@ -303,7 +304,7 @@ We will use a destructuring notation for the AST nodes. Type Conversion Functions ------------------------- -JULIA has no support for implicit type conversion and therefore functions exist to provide explicit conversion. +Yul has no support for implicit type conversion and therefore functions exist to provide explicit conversion. When converting a larger type to a shorter type a runtime exception can occur in case of an overflow. Truncating conversions are supported between the following types: @@ -507,7 +508,7 @@ The following functions must be available: Backends -------- -Backends or targets are the translators from JULIA to a specific bytecode. Each of the backends can expose functions +Backends or targets are the translators from Yul to a specific bytecode. Each of the backends can expose functions prefixed with the name of the backend. We reserve ``evm_`` and ``ewasm_`` prefixes for the two proposed backends. Backend: EVM @@ -525,8 +526,8 @@ Backend: eWASM TBD -Specification of JULIA Object -============================= +Specification of Yul Object +=========================== Grammar:: @@ -537,9 +538,9 @@ Grammar:: HexLiteral = 'hex' ('"' ([0-9a-fA-F]{2})* '"' | '\'' ([0-9a-fA-F]{2})* '\'') StringLiteral = '"' ([^"\r\n\\] | '\\' .)* '"' -Above, ``Block`` refers to ``Block`` in the JULIA code grammar explained in the previous chapter. +Above, ``Block`` refers to ``Block`` in the Yul code grammar explained in the previous chapter. -An example JULIA Object is shown below: +An example Yul Object is shown below: .. code:: diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index 521e8bd9..671e4030 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -1708,18 +1708,10 @@ bool TypeChecker::visit(FunctionCall const& _functionCall) if (auto functionName = dynamic_cast<Identifier const*>(&_functionCall.expression())) { - string msg; if (functionName->name() == "sha3" && functionType->kind() == FunctionType::Kind::SHA3) - msg = "\"sha3\" has been deprecated in favour of \"keccak256\""; + m_errorReporter.typeError(_functionCall.location(), "\"sha3\" has been deprecated in favour of \"keccak256\""); else if (functionName->name() == "suicide" && functionType->kind() == FunctionType::Kind::Selfdestruct) - msg = "\"suicide\" has been deprecated in favour of \"selfdestruct\""; - if (!msg.empty()) - { - if (v050) - m_errorReporter.typeError(_functionCall.location(), msg); - else - m_errorReporter.warning(_functionCall.location(), msg); - } + m_errorReporter.typeError(_functionCall.location(), "\"suicide\" has been deprecated in favour of \"selfdestruct\""); } if (!m_insideEmitStatement && functionType->kind() == FunctionType::Kind::Event) { diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp index 1e0565c0..c4d97c64 100644 --- a/libsolidity/ast/Types.cpp +++ b/libsolidity/ast/Types.cpp @@ -1084,9 +1084,21 @@ TypePointer RationalNumberType::binaryOperatorResult(Token::Value _operator, Typ { uint32_t exponent = other.m_value.numerator().convert_to<uint32_t>(); if (exponent > mostSignificantBit(boost::multiprecision::abs(m_value.numerator()))) - value = 0; + value = m_value.numerator() < 0 ? -1 : 0; else - value = rational(m_value.numerator() / boost::multiprecision::pow(bigint(2), exponent), 1); + { + if (m_value.numerator() < 0) + // Add 1 to the negative value before dividing to get a result that is strictly too large, + // then subtract 1 afterwards to round towards negative infinity. + // This is the same algorithm as used in ExpressionCompiler::appendShiftOperatorCode(...). + // To see this note that for negative x, xor(x,all_ones) = (-x-1) and + // therefore xor(div(xor(x,all_ones), exp(2, shift_amount)), all_ones) is + // -(-x - 1) / 2^shift_amount - 1, which is the same as + // (x + 1) / 2^shift_amount - 1. + value = rational((m_value.numerator() + 1) / boost::multiprecision::pow(bigint(2), exponent) - bigint(1), 1); + else + value = rational(m_value.numerator() / boost::multiprecision::pow(bigint(2), exponent), 1); + } } break; } diff --git a/libsolidity/codegen/ArrayUtils.cpp b/libsolidity/codegen/ArrayUtils.cpp index 14c887c3..2b77db8f 100644 --- a/libsolidity/codegen/ArrayUtils.cpp +++ b/libsolidity/codegen/ArrayUtils.cpp @@ -303,12 +303,17 @@ void ArrayUtils::copyArrayToMemory(ArrayType const& _sourceType, bool _padToWord m_context << _sourceType.length(); if (baseSize > 1) m_context << u256(baseSize) << Instruction::MUL; - // stack: target source_offset source_len - m_context << Instruction::DUP1 << Instruction::DUP3 << Instruction::DUP5; - // stack: target source_offset source_len source_len source_offset target - m_context << Instruction::CALLDATACOPY; - m_context << Instruction::DUP3 << Instruction::ADD; - m_context << Instruction::SWAP2 << Instruction::POP << Instruction::POP; + + string routine = "calldatacopy(target, source, len)\n"; + if (_padToWordBoundaries) + routine += R"( + // Set padding suffix to zero + mstore(add(target, len), 0) + len := and(add(len, 0x1f), not(0x1f)) + )"; + routine += "target := add(target, len)\n"; + m_context.appendInlineAssembly("{" + routine + "}", {"target", "source", "len"}); + m_context << Instruction::POP << Instruction::POP; } else if (_sourceType.location() == DataLocation::Memory) { diff --git a/libsolidity/codegen/ExpressionCompiler.cpp b/libsolidity/codegen/ExpressionCompiler.cpp index 93d440c8..0470c3ec 100644 --- a/libsolidity/codegen/ExpressionCompiler.cpp +++ b/libsolidity/codegen/ExpressionCompiler.cpp @@ -1737,11 +1737,36 @@ void ExpressionCompiler::appendShiftOperatorCode(Token::Value _operator, Type co m_context << u256(2) << Instruction::EXP << Instruction::MUL; break; case Token::SAR: - // NOTE: SAR rounds differently than SDIV - if (m_context.evmVersion().hasBitwiseShifting() && !c_valueSigned) - m_context << Instruction::SHR; + if (m_context.evmVersion().hasBitwiseShifting()) + m_context << (c_valueSigned ? Instruction::SAR : Instruction::SHR); else - m_context << u256(2) << Instruction::EXP << Instruction::SWAP1 << (c_valueSigned ? Instruction::SDIV : Instruction::DIV); + { + if (c_valueSigned) + // In the following assembly snippet, xor_mask will be zero, if value_to_shift is positive. + // Therefor xor'ing with xor_mask is the identity and the computation reduces to + // div(value_to_shift, exp(2, shift_amount)), which is correct, since for positive values + // arithmetic right shift is dividing by a power of two (which, as a bitwise operation, results + // in discarding bits on the right and filling with zeros from the left). + // For negative values arithmetic right shift, viewed as a bitwise operation, discards bits to the + // right and fills in ones from the left. This is achieved as follows: + // If value_to_shift is negative, then xor_mask will have all bits set, so xor'ing with xor_mask + // will flip all bits. First all bits in value_to_shift are flipped. As for the positive case, + // dividing by a power of two using integer arithmetic results in discarding bits to the right + // and filling with zeros from the left. Flipping all bits in the result again, turns all zeros + // on the left to ones and restores the non-discarded, shifted bits to their original value (they + // have now been flipped twice). In summary we now have discarded bits to the right and filled with + // ones from the left, i.e. we have performed an arithmetic right shift. + m_context.appendInlineAssembly(R"({ + let xor_mask := sub(0, slt(value_to_shift, 0)) + value_to_shift := xor(div(xor(value_to_shift, xor_mask), exp(2, shift_amount)), xor_mask) + })", {"value_to_shift", "shift_amount"}); + else + m_context.appendInlineAssembly(R"({ + value_to_shift := div(value_to_shift, exp(2, shift_amount)) + })", {"value_to_shift", "shift_amount"}); + m_context << Instruction::POP; + + } break; case Token::SHR: default: diff --git a/libsolidity/formal/SMTChecker.cpp b/libsolidity/formal/SMTChecker.cpp index 8639317b..a4d9500b 100644 --- a/libsolidity/formal/SMTChecker.cpp +++ b/libsolidity/formal/SMTChecker.cpp @@ -68,7 +68,7 @@ bool SMTChecker::visit(ContractDefinition const& _contract) void SMTChecker::endVisit(ContractDefinition const&) { - m_stateVariables.clear(); + m_variables.clear(); } void SMTChecker::endVisit(VariableDeclaration const& _varDecl) @@ -86,12 +86,10 @@ bool SMTChecker::visit(FunctionDefinition const& _function) ); m_currentFunction = &_function; m_interface->reset(); - m_variables.clear(); - m_variables.insert(m_stateVariables.begin(), m_stateVariables.end()); m_pathConditions.clear(); m_loopExecutionHappened = false; - initializeLocalVariables(_function); resetStateVariables(); + initializeLocalVariables(_function); return true; } @@ -100,6 +98,7 @@ void SMTChecker::endVisit(FunctionDefinition const&) // TOOD we could check for "reachability", i.e. satisfiability here. // We only handle local variables, so we clear at the beginning of the function. // If we add storage variables, those should be cleared differently. + removeLocalVariables(); m_currentFunction = nullptr; } @@ -110,7 +109,7 @@ bool SMTChecker::visit(IfStatement const& _node) checkBooleanNotConstant(_node.condition(), "Condition is always $VALUE."); auto countersEndTrue = visitBranch(_node.trueStatement(), expr(_node.condition())); - vector<Declaration const*> touchedVariables = m_variableUsage->touchedVariables(_node.trueStatement()); + vector<VariableDeclaration const*> touchedVariables = m_variableUsage->touchedVariables(_node.trueStatement()); decltype(countersEndTrue) countersEndFalse; if (_node.falseStatement()) { @@ -230,10 +229,10 @@ void SMTChecker::endVisit(Assignment const& _assignment) ); else if (Identifier const* identifier = dynamic_cast<Identifier const*>(&_assignment.leftHandSide())) { - Declaration const* decl = identifier->annotation().referencedDeclaration; - if (knownVariable(*decl)) + VariableDeclaration const& decl = dynamic_cast<VariableDeclaration const&>(*identifier->annotation().referencedDeclaration); + if (knownVariable(decl)) { - assignment(*decl, _assignment.rightHandSide(), _assignment.location()); + assignment(decl, _assignment.rightHandSide(), _assignment.location()); defineExpr(_assignment, expr(_assignment.rightHandSide())); } else @@ -296,12 +295,12 @@ void SMTChecker::endVisit(UnaryOperation const& _op) solAssert(_op.subExpression().annotation().lValueRequested, ""); if (Identifier const* identifier = dynamic_cast<Identifier const*>(&_op.subExpression())) { - Declaration const* decl = identifier->annotation().referencedDeclaration; - if (knownVariable(*decl)) + VariableDeclaration const& decl = dynamic_cast<VariableDeclaration const&>(*identifier->annotation().referencedDeclaration); + if (knownVariable(decl)) { - auto innerValue = currentValue(*decl); + auto innerValue = currentValue(decl); auto newValue = _op.getOperator() == Token::Inc ? innerValue + 1 : innerValue - 1; - assignment(*decl, newValue, _op.location()); + assignment(decl, newValue, _op.location()); defineExpr(_op, _op.isPrefixOperation() ? newValue : innerValue); } else @@ -383,14 +382,15 @@ void SMTChecker::endVisit(FunctionCall const& _funCall) void SMTChecker::endVisit(Identifier const& _identifier) { - Declaration const* decl = _identifier.annotation().referencedDeclaration; - solAssert(decl, ""); if (_identifier.annotation().lValueRequested) { // Will be translated as part of the node that requested the lvalue. } else if (SSAVariable::isSupportedType(_identifier.annotation().type->category())) - defineExpr(_identifier, currentValue(*decl)); + { + VariableDeclaration const& decl = dynamic_cast<VariableDeclaration const&>(*(_identifier.annotation().referencedDeclaration)); + defineExpr(_identifier, currentValue(decl)); + } else if (FunctionType const* fun = dynamic_cast<FunctionType const*>(_identifier.annotation().type.get())) { if (fun->kind() == FunctionType::Kind::Assert || fun->kind() == FunctionType::Kind::Require) @@ -530,12 +530,12 @@ smt::Expression SMTChecker::division(smt::Expression _left, smt::Expression _rig return _left / _right; } -void SMTChecker::assignment(Declaration const& _variable, Expression const& _value, SourceLocation const& _location) +void SMTChecker::assignment(VariableDeclaration const& _variable, Expression const& _value, SourceLocation const& _location) { assignment(_variable, expr(_value), _location); } -void SMTChecker::assignment(Declaration const& _variable, smt::Expression const& _value, SourceLocation const& _location) +void SMTChecker::assignment(VariableDeclaration const& _variable, smt::Expression const& _value, SourceLocation const& _location) { TypePointer type = _variable.type(); if (auto const* intType = dynamic_cast<IntegerType const*>(type.get())) @@ -583,19 +583,7 @@ void SMTChecker::checkCondition( expressionsToEvaluate.emplace_back(*_additionalValue); expressionNames.push_back(_additionalValueName); } - for (auto const& param: m_currentFunction->parameters()) - if (knownVariable(*param)) - { - expressionsToEvaluate.emplace_back(currentValue(*param)); - expressionNames.push_back(param->name()); - } - for (auto const& var: m_currentFunction->localVariables()) - if (knownVariable(*var)) - { - expressionsToEvaluate.emplace_back(currentValue(*var)); - expressionNames.push_back(var->name()); - } - for (auto const& var: m_stateVariables) + for (auto const& var: m_variables) if (knownVariable(*var.first)) { expressionsToEvaluate.emplace_back(currentValue(*var.first)); @@ -740,14 +728,17 @@ void SMTChecker::initializeLocalVariables(FunctionDefinition const& _function) void SMTChecker::resetStateVariables() { - for (auto const& variable: m_stateVariables) + for (auto const& variable: m_variables) { - newValue(*variable.first); - setUnknownValue(*variable.first); + if (variable.first->isStateVariable()) + { + newValue(*variable.first); + setUnknownValue(*variable.first); + } } } -void SMTChecker::resetVariables(vector<Declaration const*> _variables) +void SMTChecker::resetVariables(vector<VariableDeclaration const*> _variables) { for (auto const* decl: _variables) { @@ -756,9 +747,9 @@ void SMTChecker::resetVariables(vector<Declaration const*> _variables) } } -void SMTChecker::mergeVariables(vector<Declaration const*> const& _variables, smt::Expression const& _condition, VariableSequenceCounters const& _countersEndTrue, VariableSequenceCounters const& _countersEndFalse) +void SMTChecker::mergeVariables(vector<VariableDeclaration const*> const& _variables, smt::Expression const& _condition, VariableSequenceCounters const& _countersEndTrue, VariableSequenceCounters const& _countersEndFalse) { - set<Declaration const*> uniqueVars(_variables.begin(), _variables.end()); + set<VariableDeclaration const*> uniqueVars(_variables.begin(), _variables.end()); for (auto const* decl: uniqueVars) { int trueCounter = _countersEndTrue.at(decl).index(); @@ -777,14 +768,7 @@ bool SMTChecker::createVariable(VariableDeclaration const& _varDecl) if (SSAVariable::isSupportedType(_varDecl.type()->category())) { solAssert(m_variables.count(&_varDecl) == 0, ""); - solAssert(m_stateVariables.count(&_varDecl) == 0, ""); - if (_varDecl.isLocalVariable()) - m_variables.emplace(&_varDecl, SSAVariable(_varDecl, *m_interface)); - else - { - solAssert(_varDecl.isStateVariable(), ""); - m_stateVariables.emplace(&_varDecl, SSAVariable(_varDecl, *m_interface)); - } + m_variables.emplace(&_varDecl, SSAVariable(_varDecl, *m_interface)); return true; } else @@ -802,37 +786,37 @@ string SMTChecker::uniqueSymbol(Expression const& _expr) return "expr_" + to_string(_expr.id()); } -bool SMTChecker::knownVariable(Declaration const& _decl) +bool SMTChecker::knownVariable(VariableDeclaration const& _decl) { return m_variables.count(&_decl); } -smt::Expression SMTChecker::currentValue(Declaration const& _decl) +smt::Expression SMTChecker::currentValue(VariableDeclaration const& _decl) { solAssert(knownVariable(_decl), ""); return m_variables.at(&_decl)(); } -smt::Expression SMTChecker::valueAtSequence(Declaration const& _decl, int _sequence) +smt::Expression SMTChecker::valueAtSequence(VariableDeclaration const& _decl, int _sequence) { solAssert(knownVariable(_decl), ""); return m_variables.at(&_decl)(_sequence); } -smt::Expression SMTChecker::newValue(Declaration const& _decl) +smt::Expression SMTChecker::newValue(VariableDeclaration const& _decl) { solAssert(knownVariable(_decl), ""); ++m_variables.at(&_decl); return m_variables.at(&_decl)(); } -void SMTChecker::setZeroValue(Declaration const& _decl) +void SMTChecker::setZeroValue(VariableDeclaration const& _decl) { solAssert(knownVariable(_decl), ""); m_variables.at(&_decl).setZeroValue(); } -void SMTChecker::setUnknownValue(Declaration const& _decl) +void SMTChecker::setUnknownValue(VariableDeclaration const& _decl) { solAssert(knownVariable(_decl), ""); m_variables.at(&_decl).setUnknownValue(); @@ -909,3 +893,14 @@ void SMTChecker::addPathImpliedExpression(smt::Expression const& _e) { m_interface->addAssertion(smt::Expression::implies(currentPathConditions(), _e)); } + +void SMTChecker::removeLocalVariables() +{ + for (auto it = m_variables.begin(); it != m_variables.end(); ) + { + if (it->first->isLocalVariable()) + it = m_variables.erase(it); + else + ++it; + } +} diff --git a/libsolidity/formal/SMTChecker.h b/libsolidity/formal/SMTChecker.h index 50d40ab9..6cf4e48a 100644 --- a/libsolidity/formal/SMTChecker.h +++ b/libsolidity/formal/SMTChecker.h @@ -76,11 +76,11 @@ private: /// of rounding for signed division. smt::Expression division(smt::Expression _left, smt::Expression _right, IntegerType const& _type); - void assignment(Declaration const& _variable, Expression const& _value, SourceLocation const& _location); - void assignment(Declaration const& _variable, smt::Expression const& _value, SourceLocation const& _location); + void assignment(VariableDeclaration const& _variable, Expression const& _value, SourceLocation const& _location); + void assignment(VariableDeclaration const& _variable, smt::Expression const& _value, SourceLocation const& _location); /// Maps a variable to an SSA index. - using VariableSequenceCounters = std::map<Declaration const*, SSAVariable>; + using VariableSequenceCounters = std::map<VariableDeclaration const*, SSAVariable>; /// Visits the branch given by the statement, pushes and pops the current path conditions. /// @param _condition if present, asserts that this condition is true within the branch. @@ -114,11 +114,11 @@ private: void initializeLocalVariables(FunctionDefinition const& _function); void resetStateVariables(); - void resetVariables(std::vector<Declaration const*> _variables); + void resetVariables(std::vector<VariableDeclaration const*> _variables); /// Given two different branches and the touched variables, /// merge the touched variables into after-branch ite variables /// using the branch condition as guard. - void mergeVariables(std::vector<Declaration const*> const& _variables, smt::Expression const& _condition, VariableSequenceCounters const& _countersEndTrue, VariableSequenceCounters const& _countersEndFalse); + void mergeVariables(std::vector<VariableDeclaration const*> const& _variables, smt::Expression const& _condition, VariableSequenceCounters const& _countersEndTrue, VariableSequenceCounters const& _countersEndFalse); /// Tries to create an uninitialized variable and returns true on success. /// This fails if the type is not supported. bool createVariable(VariableDeclaration const& _varDecl); @@ -127,21 +127,21 @@ private: /// @returns true if _delc is a variable that is known at the current point, i.e. /// has a valid sequence number - bool knownVariable(Declaration const& _decl); + bool knownVariable(VariableDeclaration const& _decl); /// @returns an expression denoting the value of the variable declared in @a _decl /// at the current point. - smt::Expression currentValue(Declaration const& _decl); + smt::Expression currentValue(VariableDeclaration const& _decl); /// @returns an expression denoting the value of the variable declared in @a _decl /// at the given sequence point. Does not ensure that this sequence point exists. - smt::Expression valueAtSequence(Declaration const& _decl, int _sequence); + smt::Expression valueAtSequence(VariableDeclaration const& _decl, int _sequence); /// Allocates a new sequence number for the declaration, updates the current /// sequence number to this value and returns the expression. - smt::Expression newValue(Declaration const& _decl); + smt::Expression newValue(VariableDeclaration const& _decl); /// Sets the value of the declaration to zero. - void setZeroValue(Declaration const& _decl); + void setZeroValue(VariableDeclaration const& _decl); /// Resets the variable to an unknown value (in its range). - void setUnknownValue(Declaration const& decl); + void setUnknownValue(VariableDeclaration const& decl); /// Returns the expression corresponding to the AST node. Throws if the expression does not exist. smt::Expression expr(Expression const& _e); @@ -161,12 +161,14 @@ private: /// Add to the solver: the given expression implied by the current path conditions void addPathImpliedExpression(smt::Expression const& _e); + /// Removes the local variables of a function. + void removeLocalVariables(); + std::shared_ptr<smt::SolverInterface> m_interface; std::shared_ptr<VariableUsage> m_variableUsage; bool m_loopExecutionHappened = false; std::map<Expression const*, smt::Expression> m_expressions; - std::map<Declaration const*, SSAVariable> m_variables; - std::map<Declaration const*, SSAVariable> m_stateVariables; + std::map<VariableDeclaration const*, SSAVariable> m_variables; std::vector<smt::Expression> m_pathConditions; ErrorReporter& m_errorReporter; diff --git a/libsolidity/formal/VariableUsage.cpp b/libsolidity/formal/VariableUsage.cpp index c2dea844..9282a560 100644 --- a/libsolidity/formal/VariableUsage.cpp +++ b/libsolidity/formal/VariableUsage.cpp @@ -50,12 +50,12 @@ VariableUsage::VariableUsage(ASTNode const& _node) _node.accept(reducer); } -vector<Declaration const*> VariableUsage::touchedVariables(ASTNode const& _node) const +vector<VariableDeclaration const*> VariableUsage::touchedVariables(ASTNode const& _node) const { if (!m_children.count(&_node) && !m_touchedVariable.count(&_node)) return {}; - set<Declaration const*> touched; + set<VariableDeclaration const*> touched; vector<ASTNode const*> toVisit; toVisit.push_back(&_node); diff --git a/libsolidity/formal/VariableUsage.h b/libsolidity/formal/VariableUsage.h index 62561cce..dda13de2 100644 --- a/libsolidity/formal/VariableUsage.h +++ b/libsolidity/formal/VariableUsage.h @@ -27,7 +27,7 @@ namespace solidity { class ASTNode; -class Declaration; +class VariableDeclaration; /** * This class collects information about which local variables of value type @@ -38,11 +38,11 @@ class VariableUsage public: explicit VariableUsage(ASTNode const& _node); - std::vector<Declaration const*> touchedVariables(ASTNode const& _node) const; + std::vector<VariableDeclaration const*> touchedVariables(ASTNode const& _node) const; private: // Variable touched by a specific AST node. - std::map<ASTNode const*, Declaration const*> m_touchedVariable; + std::map<ASTNode const*, VariableDeclaration const*> m_touchedVariable; std::map<ASTNode const*, std::vector<ASTNode const*>> m_children; }; diff --git a/libsolidity/parsing/Token.h b/libsolidity/parsing/Token.h index 845a97bc..cb855cbe 100644 --- a/libsolidity/parsing/Token.h +++ b/libsolidity/parsing/Token.h @@ -223,22 +223,41 @@ namespace solidity /* Keywords reserved for future use. */ \ K(Abstract, "abstract", 0) \ K(After, "after", 0) \ + K(Alias, "alias", 0) \ + K(Apply, "apply", 0) \ + K(Auto, "auto", 0) \ K(Case, "case", 0) \ K(Catch, "catch", 0) \ + K(CopyOf, "copyof", 0) \ K(Default, "default", 0) \ + K(Define, "define", 0) \ K(Final, "final", 0) \ + K(Immutable, "immutable", 0) \ + K(Implements, "implements", 0) \ K(In, "in", 0) \ K(Inline, "inline", 0) \ K(Let, "let", 0) \ + K(Macro, "macro", 0) \ K(Match, "match", 0) \ + K(Mutable, "mutable", 0) \ K(NullLiteral, "null", 0) \ K(Of, "of", 0) \ + K(Override, "override", 0) \ + K(Partial, "partial", 0) \ + K(Promise, "promise", 0) \ + K(Reference, "reference", 0) \ K(Relocatable, "relocatable", 0) \ + K(Sealed, "sealed", 0) \ + K(Sizeof, "sizeof", 0) \ K(Static, "static", 0) \ + K(Supports, "supports", 0) \ K(Switch, "switch", 0) \ K(Try, "try", 0) \ K(Type, "type", 0) \ + K(Typedef, "typedef", 0) \ K(TypeOf, "typeof", 0) \ + K(Unchecked, "unchecked", 0) \ + \ /* Illegal token - not able to scan. */ \ T(Illegal, "ILLEGAL", 0) \ \ @@ -295,7 +314,7 @@ public: static bool isStateMutabilitySpecifier(Value op) { return op == Pure || op == Constant || op == View || op == Payable; } static bool isEtherSubdenomination(Value op) { return op == SubWei || op == SubSzabo || op == SubFinney || op == SubEther; } static bool isTimeSubdenomination(Value op) { return op == SubSecond || op == SubMinute || op == SubHour || op == SubDay || op == SubWeek || op == SubYear; } - static bool isReservedKeyword(Value op) { return (Abstract <= op && op <= TypeOf); } + static bool isReservedKeyword(Value op) { return (Abstract <= op && op <= Unchecked); } // @returns a string corresponding to the JS token string // (.e., "<" for the token LT) or NULL if the token doesn't diff --git a/scripts/release.bat b/scripts/release.bat index be95b35e..6415a040 100644 --- a/scripts/release.bat +++ b/scripts/release.bat @@ -32,11 +32,10 @@ set VERSION=%2 IF "%VERSION%"=="2015" ( set "DLLS=C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\redist\x86\Microsoft.VC140.CRT\msvc*.dll" ) ELSE ( - - IF EXIST "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Redist\MSVC\14.13.26020\x86\Microsoft.VC141.CRT\" ( - set "DLLS=C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Redist\MSVC\14.13.26020\x86\Microsoft.VC141.CRT\msvc*.dll" + IF EXIST "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Redist\MSVC\14.14.26405\x86\Microsoft.VC141.CRT\" ( + set "DLLS=C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Redist\MSVC\14.14.26405\x86\Microsoft.VC141.CRT\msvc*.dll" ) ELSE ( - set "DLLS=C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\VC\Redist\MSVC\14.13.26020\x86\Microsoft.VC141.CRT\msvc*.dll" + set "DLLS=C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\VC\Redist\MSVC\14.14.26405\x86\Microsoft.VC141.CRT\msvc*.dll" ) ) diff --git a/solc/CommandLineInterface.cpp b/solc/CommandLineInterface.cpp index 89ac8806..2e4b70e6 100644 --- a/solc/CommandLineInterface.cpp +++ b/solc/CommandLineInterface.cpp @@ -88,7 +88,6 @@ static string const g_strEVM = "evm"; static string const g_strEVM15 = "evm15"; static string const g_strEVMVersion = "evm-version"; static string const g_streWasm = "ewasm"; -static string const g_strFormal = "formal"; static string const g_strGas = "gas"; static string const g_strHelp = "help"; static string const g_strInputFile = "input-file"; @@ -132,7 +131,6 @@ static string const g_argBinaryRuntime = g_strBinaryRuntime; static string const g_argCloneBinary = g_strCloneBinary; static string const g_argCombinedJson = g_strCombinedJson; static string const g_argCompactJSON = g_strCompactJSON; -static string const g_argFormal = g_strFormal; static string const g_argGas = g_strGas; static string const g_argHelp = g_strHelp; static string const g_argInputFile = g_strInputFile; @@ -216,7 +214,6 @@ static bool needsHumanTargetedStdout(po::variables_map const& _args) g_argBinary, g_argBinaryRuntime, g_argCloneBinary, - g_argFormal, g_argMetadata, g_argNatspecUser, g_argNatspecDev, @@ -639,8 +636,7 @@ Allowed options)", (g_argSignatureHashes.c_str(), "Function signature hashes of the contracts.") (g_argNatspecUser.c_str(), "Natspec user documentation of all contracts.") (g_argNatspecDev.c_str(), "Natspec developer documentation of all contracts.") - (g_argMetadata.c_str(), "Combined Metadata JSON whose Swarm hash is stored on-chain.") - (g_argFormal.c_str(), "Translated source suitable for formal analysis. (Deprecated)"); + (g_argMetadata.c_str(), "Combined Metadata JSON whose Swarm hash is stored on-chain."); desc.add(outputComponents); po::options_description allOptions = desc; @@ -1236,9 +1232,6 @@ void CommandLineInterface::outputCompilationResults() handleNatspec(true, contract); handleNatspec(false, contract); } // end of contracts iteration - - if (m_args.count(g_argFormal)) - cerr << "Support for the Why3 output was removed." << endl; } } diff --git a/std/StandardToken.sol b/std/StandardToken.sol deleted file mode 100644 index c2fc3a66..00000000 --- a/std/StandardToken.sol +++ /dev/null @@ -1,59 +0,0 @@ -pragma solidity ^0.4.22; - -import "./Token.sol"; - -contract StandardToken is Token { - uint256 supply; - mapping (address => uint256) balance; - mapping (address => - mapping (address => uint256)) m_allowance; - - constructor(address _initialOwner, uint256 _supply) public { - supply = _supply; - balance[_initialOwner] = _supply; - } - - function balanceOf(address _account) view public returns (uint) { - return balance[_account]; - } - - function totalSupply() view public returns (uint) { - return supply; - } - - function transfer(address _to, uint256 _value) public returns (bool success) { - return doTransfer(msg.sender, _to, _value); - } - - function transferFrom(address _from, address _to, uint256 _value) public returns (bool) { - if (m_allowance[_from][msg.sender] >= _value) { - if (doTransfer(_from, _to, _value)) { - m_allowance[_from][msg.sender] -= _value; - } - return true; - } else { - return false; - } - } - - function doTransfer(address _from, address _to, uint _value) internal returns (bool success) { - if (balance[_from] >= _value && balance[_to] + _value >= balance[_to]) { - balance[_from] -= _value; - balance[_to] += _value; - emit Transfer(_from, _to, _value); - return true; - } else { - return false; - } - } - - function approve(address _spender, uint256 _value) public returns (bool success) { - m_allowance[msg.sender][_spender] = _value; - emit Approval(msg.sender, _spender, _value); - return true; - } - - function allowance(address _owner, address _spender) view public returns (uint256) { - return m_allowance[_owner][_spender]; - } -} diff --git a/std/Token.sol b/std/Token.sol deleted file mode 100644 index 7348a8f5..00000000 --- a/std/Token.sol +++ /dev/null @@ -1,13 +0,0 @@ -pragma solidity ^0.4.0; - -contract Token { - event Transfer(address indexed _from, address indexed _to, uint256 _value); - event Approval(address indexed _owner, address indexed _spender, uint256 _value); - - function totalSupply() view public returns (uint256 supply); - function balanceOf(address _owner) view public returns (uint256 balance); - function transfer(address _to, uint256 _value) public returns (bool success); - function transferFrom(address _from, address _to, uint256 _value) public returns (bool success); - function approve(address _spender, uint256 _value) public returns (bool success); - function allowance(address _owner, address _spender) view public returns (uint256 remaining); -} diff --git a/std/mortal.sol b/std/mortal.sol deleted file mode 100644 index c43f1e4f..00000000 --- a/std/mortal.sol +++ /dev/null @@ -1,10 +0,0 @@ -pragma solidity ^0.4.0; - -import "./owned.sol"; - -contract mortal is owned { - function kill() public { - if (msg.sender == owner) - selfdestruct(owner); - } -} diff --git a/std/owned.sol b/std/owned.sol deleted file mode 100644 index 75007f3e..00000000 --- a/std/owned.sol +++ /dev/null @@ -1,15 +0,0 @@ -pragma solidity ^0.4.22; - -contract owned { - address owner; - - modifier onlyowner() { - if (msg.sender == owner) { - _; - } - } - - constructor() public { - owner = msg.sender; - } -} diff --git a/std/std.sol b/std/std.sol deleted file mode 100644 index 4d65bef2..00000000 --- a/std/std.sol +++ /dev/null @@ -1,6 +0,0 @@ -pragma solidity ^0.4.0; - -import "./owned.sol"; -import "./mortal.sol"; -import "./Token.sol"; -import "./StandardToken.sol"; diff --git a/test/cmdlineTests.sh b/test/cmdlineTests.sh index 74b6a5a7..e8ff69de 100755 --- a/test/cmdlineTests.sh +++ b/test/cmdlineTests.sh @@ -37,10 +37,6 @@ FULLARGS="--optimize --ignore-missing --combined-json abi,asm,ast,bin,bin-runtim echo "Checking that the bug list is up to date..." "$REPO_ROOT"/scripts/update_bugs_by_version.py -echo "Checking that StandardToken.sol, owned.sol and mortal.sol produce bytecode..." -output=$("$REPO_ROOT"/build/solc/solc --bin "$REPO_ROOT"/std/*.sol 2>/dev/null | grep "ffff" | wc -l) -test "${output//[[:blank:]]/}" = "3" - function printTask() { echo "$(tput bold)$(tput setaf 2)$1$(tput sgr0)"; } function printError() { echo "$(tput setaf 1)$1$(tput sgr0)"; } @@ -113,14 +109,6 @@ do done ) -printTask "Compiling all files in std and examples..." - -for f in "$REPO_ROOT"/std/*.sol -do - echo "$f" - compileWithoutWarning "$f" -done - printTask "Compiling all examples from the documentation..." TMPDIR=$(mktemp -d) ( diff --git a/test/compilationTests/corion/moduleHandler.sol b/test/compilationTests/corion/moduleHandler.sol index 682f81dd..3aefce30 100644 --- a/test/compilationTests/corion/moduleHandler.sol +++ b/test/compilationTests/corion/moduleHandler.sol @@ -54,11 +54,11 @@ contract moduleHandler is multiOwner, announcementTypes { require( owners[msg.sender] ); require( modules.length == 0 ); foundationAddress = foundation; - addModule( modules_s(Token, sha3('Token'), false, false), ! forReplace); - addModule( modules_s(Premium, sha3('Premium'), false, false), ! forReplace); - addModule( modules_s(Publisher, sha3('Publisher'), false, true), ! forReplace); - addModule( modules_s(Schelling, sha3('Schelling'), false, true), ! forReplace); - addModule( modules_s(Provider, sha3('Provider'), true, true), ! forReplace); + addModule( modules_s(Token, keccak256('Token'), false, false), ! forReplace); + addModule( modules_s(Premium, keccak256('Premium'), false, false), ! forReplace); + addModule( modules_s(Publisher, keccak256('Publisher'), false, true), ! forReplace); + addModule( modules_s(Schelling, keccak256('Schelling'), false, true), ! forReplace); + addModule( modules_s(Provider, keccak256('Provider'), true, true), ! forReplace); } function addModule(modules_s input, bool call) internal { /* @@ -117,7 +117,7 @@ contract moduleHandler is multiOwner, announcementTypes { @id Index of module. @found Was there any result or not. */ - bytes32 _name = sha3(name); + bytes32 _name = keccak256(name); for ( uint256 a=0 ; a<modules.length ; a++ ) { if ( modules[a].name == _name ) { return (true, true, a); @@ -151,9 +151,9 @@ contract moduleHandler is multiOwner, announcementTypes { */ var (_success, _found, _id) = getModuleIDByAddress(msg.sender); require( _success ); - if ( ! ( _found && modules[_id].name == sha3('Publisher') )) { + if ( ! ( _found && modules[_id].name == keccak256('Publisher') )) { require( block.number < debugModeUntil ); - if ( ! insertAndCheckDo(calcDoHash("replaceModule", sha3(name, addr, callCallback))) ) { + if ( ! insertAndCheckDo(calcDoHash("replaceModule", keccak256(name, addr, callCallback))) ) { return true; } } @@ -169,7 +169,7 @@ contract moduleHandler is multiOwner, announcementTypes { function callReplaceCallback(string moduleName, address newModule) external returns (bool success) { require( block.number < debugModeUntil ); - if ( ! insertAndCheckDo(calcDoHash("callReplaceCallback", sha3(moduleName, newModule))) ) { + if ( ! insertAndCheckDo(calcDoHash("callReplaceCallback", keccak256(moduleName, newModule))) ) { return true; } var (_success, _found, _id) = getModuleIDByName(moduleName); @@ -190,13 +190,13 @@ contract moduleHandler is multiOwner, announcementTypes { */ var (_success, _found, _id) = getModuleIDByAddress(msg.sender); require( _success ); - if ( ! ( _found && modules[_id].name == sha3('Publisher') )) { + if ( ! ( _found && modules[_id].name == keccak256('Publisher') )) { require( block.number < debugModeUntil ); - if ( ! insertAndCheckDo(calcDoHash("newModule", sha3(name, addr, schellingEvent, transferEvent))) ) { + if ( ! insertAndCheckDo(calcDoHash("newModule", keccak256(name, addr, schellingEvent, transferEvent))) ) { return true; } } - addModule( modules_s(addr, sha3(name), schellingEvent, transferEvent), true); + addModule( modules_s(addr, keccak256(name), schellingEvent, transferEvent), true); return true; } function dropModule(string name, bool callCallback) external returns (bool success) { @@ -209,9 +209,9 @@ contract moduleHandler is multiOwner, announcementTypes { */ var (_success, _found, _id) = getModuleIDByAddress(msg.sender); require( _success ); - if ( ! ( _found && modules[_id].name == sha3('Publisher') )) { + if ( ! ( _found && modules[_id].name == keccak256('Publisher') )) { require( block.number < debugModeUntil ); - if ( ! insertAndCheckDo(calcDoHash("replaceModule", sha3(name, callCallback))) ) { + if ( ! insertAndCheckDo(calcDoHash("replaceModule", keccak256(name, callCallback))) ) { return true; } } @@ -226,7 +226,7 @@ contract moduleHandler is multiOwner, announcementTypes { function callDisableCallback(string moduleName) external returns (bool success) { require( block.number < debugModeUntil ); - if ( ! insertAndCheckDo(calcDoHash("callDisableCallback", sha3(moduleName))) ) { + if ( ! insertAndCheckDo(calcDoHash("callDisableCallback", keccak256(moduleName))) ) { return true; } var (_success, _found, _id) = getModuleIDByName(moduleName); @@ -248,7 +248,7 @@ contract moduleHandler is multiOwner, announcementTypes { @bool Was the function successfull? */ var (_success, _found, _id) = getModuleIDByAddress(msg.sender); - require( _success && _found && modules[_id].name == sha3('Token') ); + require( _success && _found && modules[_id].name == keccak256('Token') ); for ( uint256 a=0 ; a<modules.length ; a++ ) { if ( modules[a].transferEvent && abstractModule(modules[a].addr).isActive() ) { require( abstractModule(modules[a].addr).transferEvent(from, to, value) ); @@ -267,7 +267,7 @@ contract moduleHandler is multiOwner, announcementTypes { @bool Was the function successfull? */ var (_success, _found, _id) = getModuleIDByAddress(msg.sender); - require( _success && _found && modules[_id].name == sha3('Schelling') ); + require( _success && _found && modules[_id].name == keccak256('Schelling') ); for ( uint256 a=0 ; a<modules.length ; a++ ) { if ( modules[a].schellingEvent && abstractModule(modules[a].addr).isActive() ) { require( abstractModule(modules[a].addr).newSchellingRoundEvent(roundID, reward) ); @@ -287,9 +287,9 @@ contract moduleHandler is multiOwner, announcementTypes { */ var (_success, _found, _id) = getModuleIDByAddress(msg.sender); require( _success ); - if ( ! ( _found && modules[_id].name == sha3('Publisher') )) { + if ( ! ( _found && modules[_id].name == keccak256('Publisher') )) { require( block.number < debugModeUntil ); - if ( ! insertAndCheckDo(calcDoHash("replaceModuleHandler", sha3(newHandler))) ) { + if ( ! insertAndCheckDo(calcDoHash("replaceModuleHandler", keccak256(newHandler))) ) { return true; } } @@ -353,7 +353,7 @@ contract moduleHandler is multiOwner, announcementTypes { @success Was the function successfull? */ var (_success, _found, _id) = getModuleIDByAddress(msg.sender); - require( _success && _found && modules[_id].name == sha3('Provider') ); + require( _success && _found && modules[_id].name == keccak256('Provider') ); (_success, _found, _id) = getModuleIDByName('Token'); require( _success && _found ); require( token(modules[_id].addr).mint(to, value) ); @@ -385,7 +385,7 @@ contract moduleHandler is multiOwner, announcementTypes { @success Was the function successfull? */ var (_success, _found, _id) = getModuleIDByAddress(msg.sender); - require( _success && _found && modules[_id].name == sha3('Provider') ); + require( _success && _found && modules[_id].name == keccak256('Provider') ); (_success, _found, _id) = getModuleIDByName('Token'); require( _success && _found ); require( token(modules[_id].addr).processTransactionFee(from, value) ); @@ -400,7 +400,7 @@ contract moduleHandler is multiOwner, announcementTypes { @success Was the function successfull? */ var (_success, _found, _id) = getModuleIDByAddress(msg.sender); - require( _success && _found && modules[_id].name == sha3('Schelling') ); + require( _success && _found && modules[_id].name == keccak256('Schelling') ); (_success, _found, _id) = getModuleIDByName('Token'); require( _success && _found ); require( token(modules[_id].addr).burn(from, value) ); @@ -417,9 +417,9 @@ contract moduleHandler is multiOwner, announcementTypes { */ var (_success, _found, _id) = getModuleIDByAddress(msg.sender); require( _success ); - if ( ! ( _found && modules[_id].name == sha3('Publisher') )) { + if ( ! ( _found && modules[_id].name == keccak256('Publisher') )) { require( block.number < debugModeUntil ); - if ( ! insertAndCheckDo(calcDoHash("configureModule", sha3(moduleName, aType, value))) ) { + if ( ! insertAndCheckDo(calcDoHash("configureModule", keccak256(moduleName, aType, value))) ) { return true; } } @@ -437,7 +437,7 @@ contract moduleHandler is multiOwner, announcementTypes { */ require( owners[msg.sender] ); if ( forever ) { - if ( ! insertAndCheckDo(calcDoHash("freezing", sha3(forever))) ) { + if ( ! insertAndCheckDo(calcDoHash("freezing", keccak256(forever))) ) { return; } } diff --git a/test/compilationTests/corion/multiOwner.sol b/test/compilationTests/corion/multiOwner.sol index 9aae0ebd..b8436c8b 100644 --- a/test/compilationTests/corion/multiOwner.sol +++ b/test/compilationTests/corion/multiOwner.sol @@ -21,12 +21,12 @@ contract multiOwner is safeMath { Externals */ function insertOwner(address addr) external { - if ( insertAndCheckDo(calcDoHash("insertOwner", sha3(addr))) ) { + if ( insertAndCheckDo(calcDoHash("insertOwner", keccak256(addr))) ) { _addOwner(addr); } } function dropOwner(address addr) external { - if ( insertAndCheckDo(calcDoHash("dropOwner", sha3(addr))) ) { + if ( insertAndCheckDo(calcDoHash("dropOwner", keccak256(addr))) ) { _delOwner(addr); } } @@ -42,7 +42,7 @@ contract multiOwner is safeMath { return ownerCount * 75 / 100; } function calcDoHash(string job, bytes32 data) public constant returns (bytes32 hash) { - return sha3(job, data); + return keccak256(job, data); } function validDoHash(bytes32 doHash) public constant returns (bool valid) { return doDB[doHash].length > 0; diff --git a/test/compilationTests/corion/schelling.sol b/test/compilationTests/corion/schelling.sol index 8c8e093c..b74cfb46 100644 --- a/test/compilationTests/corion/schelling.sol +++ b/test/compilationTests/corion/schelling.sol @@ -335,7 +335,7 @@ contract schelling is module, announcementTypes, schellingVars { require( voter.status == voterStatus.afterPrepareVote ); require( voter.roundID < currentRound ); - if ( sha3(vote) == voter.hash ) { + if ( keccak256(vote) == voter.hash ) { delete voter.hash; if (round.blockHeight+roundBlockDelay/2 >= block.number) { if ( bytes(vote)[0] == aboveChar ) { diff --git a/test/compilationTests/milestonetracker/MilestoneTracker.sol b/test/compilationTests/milestonetracker/MilestoneTracker.sol index 318330df..2f0d58cb 100644 --- a/test/compilationTests/milestonetracker/MilestoneTracker.sol +++ b/test/compilationTests/milestonetracker/MilestoneTracker.sol @@ -196,7 +196,7 @@ contract MilestoneTracker { } /// @notice `onlyDonor` Approves the proposed milestone list - /// @param _hashProposals The sha3() of the proposed milestone list's + /// @param _hashProposals The keccak256() of the proposed milestone list's /// bytecode; this confirms that the `donor` knows the set of milestones /// they are approving function acceptProposedMilestones(bytes32 _hashProposals @@ -205,7 +205,7 @@ contract MilestoneTracker { uint i; if (!changingMilestones) throw; - if (sha3(proposedMilestones) != _hashProposals) throw; + if (keccak256(proposedMilestones) != _hashProposals) throw; // Cancel all the unfinished milestones for (i=0; i<milestones.length; i++) { diff --git a/test/externalTests.sh b/test/externalTests.sh index 1565d04f..3599e069 100755 --- a/test/externalTests.sh +++ b/test/externalTests.sh @@ -40,14 +40,24 @@ function test_truffle { name="$1" repo="$2" + branch="$3" echo "Running $name tests..." DIR=$(mktemp -d) ( - git clone --depth 1 "$repo" "$DIR" + if [ -n "$branch" ] + then + echo "Cloning $branch of $repo..." + git clone --depth 1 "$repo" -b "$branch" "$DIR" + else + echo "Cloning $repo..." + git clone --depth 1 "$repo" "$DIR" + fi cd "$DIR" + echo "Current commit hash: `git rev-parse HEAD`" npm install find . -name soljson.js -exec cp "$SOLJSON" {} \; if [ "$name" == "Gnosis" ]; then + echo "Replaced fixed-version pragmas..." # Replace fixed-version pragmas in Gnosis (part of Consensys best practice) find contracts test -name '*.sol' -type f -print0 | xargs -0 sed -i -e 's/pragma solidity 0/pragma solidity ^0/' fi @@ -57,5 +67,5 @@ function test_truffle } # Using our temporary fork here. Hopefully to be merged into upstream after the 0.5.0 release. -test_truffle Gnosis https://github.com/axic/pm-contracts.git -b solidity-050 -test_truffle Zeppelin https://github.com/axic/openzeppelin-solidity.git -b solidity-050 +test_truffle Zeppelin https://github.com/axic/openzeppelin-solidity.git solidity-050 +test_truffle Gnosis https://github.com/axic/pm-contracts.git solidity-050 diff --git a/test/libsolidity/ABIEncoderTests.cpp b/test/libsolidity/ABIEncoderTests.cpp index 49db9ce1..5f15b28f 100644 --- a/test/libsolidity/ABIEncoderTests.cpp +++ b/test/libsolidity/ABIEncoderTests.cpp @@ -374,15 +374,12 @@ BOOST_AUTO_TEST_CASE(calldata) )"; string s("abcdef"); string t("abcdefgggggggggggggggggggggggggggggggggggggggghhheeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeggg"); - bool newEncoder = false; BOTH_ENCODERS( compileAndRun(sourceCode); callContractFunction("f(bytes)", 0x20, s.size(), s); - // The old encoder did not pad to multiples of 32 bytes - REQUIRE_LOG_DATA(encodeArgs(0x20, s.size()) + (newEncoder ? encodeArgs(s) : asBytes(s))); + REQUIRE_LOG_DATA(encodeArgs(0x20, s.size(), s)); callContractFunction("f(bytes)", 0x20, t.size(), t); - REQUIRE_LOG_DATA(encodeArgs(0x20, t.size()) + (newEncoder ? encodeArgs(t) : asBytes(t))); - newEncoder = true; + REQUIRE_LOG_DATA(encodeArgs(0x20, t.size(), t)); ) } diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp index b53a9294..236d83ef 100644 --- a/test/libsolidity/SolidityEndToEndTest.cpp +++ b/test/libsolidity/SolidityEndToEndTest.cpp @@ -1971,25 +1971,6 @@ BOOST_AUTO_TEST_CASE(log_in_constructor) BOOST_CHECK_EQUAL(m_logs[0].topics[0], h256(u256(2))); } -BOOST_AUTO_TEST_CASE(suicide) -{ - char const* sourceCode = R"( - contract test { - function test() payable {} - function a(address receiver) returns (uint ret) { - suicide(receiver); - return 10; - } - } - )"; - u256 amount(130); - compileAndRun(sourceCode, amount); - u160 address(23); - ABI_CHECK(callContractFunction("a(address)", address), bytes()); - BOOST_CHECK(!addressHasCode(m_contractAddress)); - BOOST_CHECK_EQUAL(balanceAt(address), amount); -} - BOOST_AUTO_TEST_CASE(selfdestruct) { char const* sourceCode = R"( @@ -2028,23 +2009,6 @@ BOOST_AUTO_TEST_CASE(keccak256) testContractAgainstCpp("a(bytes32)", f, u256(-1)); } -BOOST_AUTO_TEST_CASE(sha3) -{ - char const* sourceCode = R"( - contract test { - // to confuse the optimiser - function b(bytes32 input) returns (bytes32) { - return sha3(input); - } - function a(bytes32 input) returns (bool) { - return keccak256(input) == b(input); - } - } - )"; - compileAndRun(sourceCode); - BOOST_REQUIRE(callContractFunction("a(bytes32)", u256(42)) == encodeArgs(true)); -} - BOOST_AUTO_TEST_CASE(sha256) { char const* sourceCode = R"( @@ -3493,7 +3457,7 @@ BOOST_AUTO_TEST_CASE(event_really_lots_of_data) callContractFunction("deposit()"); BOOST_REQUIRE_EQUAL(m_logs.size(), 1); BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress); - BOOST_CHECK_EQUAL(toHex(m_logs[0].data), toHex(encodeArgs(10, 0x60, 15, 4) + FixedHash<4>(dev::keccak256("deposit()")).asBytes())); + BOOST_CHECK_EQUAL(toHex(m_logs[0].data), toHex(encodeArgs(10, 0x60, 15, 4, asString(FixedHash<4>(dev::keccak256("deposit()")).asBytes())))); BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 1); BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("Deposit(uint256,bytes,uint256)"))); } @@ -3760,27 +3724,6 @@ BOOST_AUTO_TEST_CASE(iterated_keccak256_with_bytes) )); } -BOOST_AUTO_TEST_CASE(sha3_multiple_arguments) -{ - char const* sourceCode = R"( - contract c { - function foo(uint a, uint b, uint c) returns (bytes32 d) - { - d = sha3(a, b, c); - } - } - )"; - compileAndRun(sourceCode); - - ABI_CHECK(callContractFunction("foo(uint256,uint256,uint256)", 10, 12, 13), encodeArgs( - dev::keccak256( - toBigEndian(u256(10)) + - toBigEndian(u256(12)) + - toBigEndian(u256(13)) - ) - )); -} - BOOST_AUTO_TEST_CASE(generic_call) { char const* sourceCode = R"**( @@ -4021,7 +3964,8 @@ BOOST_AUTO_TEST_CASE(call_forward_bytes_length) compileAndRun(sourceCode, 0, "sender"); // No additional data, just function selector - ABI_CHECK(callContractFunction("viaCalldata()"), encodeArgs(4)); + ABI_CHECK(callContractFunction("viaCalldata()"), encodeArgs(0x20)); + // Should be this with 0.5.0: encodeArgs(4)); ABI_CHECK(callContractFunction("viaMemory()"), encodeArgs(0x20)); // Should be this with 0.5.0: encodeArgs(4)); ABI_CHECK(callContractFunction("viaStorage()"), encodeArgs(0x20)); @@ -4029,7 +3973,8 @@ BOOST_AUTO_TEST_CASE(call_forward_bytes_length) // Some additional unpadded data bytes unpadded = asBytes(string("abc")); - ABI_CHECK(callContractFunctionNoEncoding("viaCalldata()", unpadded), encodeArgs(7)); + ABI_CHECK(callContractFunctionNoEncoding("viaCalldata()", unpadded), encodeArgs(0x20)); + // Should be this with 0.5.0: encodeArgs(7)); ABI_CHECK(callContractFunctionNoEncoding("viaMemory()", unpadded), encodeArgs(0x20)); // Should be this with 0.5.0: encodeArgs(7)); ABI_CHECK(callContractFunctionNoEncoding("viaStorage()", unpadded), encodeArgs(0x20)); @@ -10487,6 +10432,7 @@ BOOST_AUTO_TEST_CASE(shift_right) ABI_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(8)), encodeArgs(u256(0x42))); ABI_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(16)), encodeArgs(u256(0))); ABI_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(17)), encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("f(uint256,uint256)", u256(1)<<255, u256(5)), encodeArgs(u256(1)<<250)); } BOOST_AUTO_TEST_CASE(shift_right_garbled) @@ -10507,6 +10453,39 @@ BOOST_AUTO_TEST_CASE(shift_right_garbled) ABI_CHECK(callContractFunction("f(uint8,uint8)", u256(0x0), u256(0x1004)), encodeArgs(u256(0xf))); } +BOOST_AUTO_TEST_CASE(shift_right_garbled_signed) +{ + char const* sourceCode = R"( + contract C { + function f(int8 a, uint8 b) returns (int) { + assembly { + a := 0xfffffff0 + } + // Higher bits should be signextended before the shift + return a >> b; + } + function g(int8 a, uint8 b) returns (int) { + assembly { + a := 0xf0 + } + // Higher bits should be signextended before the shift + return a >> b; + } + } + )"; + compileAndRun(sourceCode, 0, "C"); + ABI_CHECK(callContractFunction("f(int8,uint8)", u256(0x0), u256(3)), encodeArgs(u256(-2))); + ABI_CHECK(callContractFunction("f(int8,uint8)", u256(0x0), u256(4)), encodeArgs(u256(-1))); + ABI_CHECK(callContractFunction("f(int8,uint8)", u256(0x0), u256(0xFF)), encodeArgs(u256(-1))); + ABI_CHECK(callContractFunction("f(int8,uint8)", u256(0x0), u256(0x1003)), encodeArgs(u256(-2))); + ABI_CHECK(callContractFunction("f(int8,uint8)", u256(0x0), u256(0x1004)), encodeArgs(u256(-1))); + ABI_CHECK(callContractFunction("g(int8,uint8)", u256(0x0), u256(3)), encodeArgs(u256(-2))); + ABI_CHECK(callContractFunction("g(int8,uint8)", u256(0x0), u256(4)), encodeArgs(u256(-1))); + ABI_CHECK(callContractFunction("g(int8,uint8)", u256(0x0), u256(0xFF)), encodeArgs(u256(-1))); + ABI_CHECK(callContractFunction("g(int8,uint8)", u256(0x0), u256(0x1003)), encodeArgs(u256(-2))); + ABI_CHECK(callContractFunction("g(int8,uint8)", u256(0x0), u256(0x1004)), encodeArgs(u256(-1))); +} + BOOST_AUTO_TEST_CASE(shift_right_uint32) { char const* sourceCode = R"( @@ -10583,16 +10562,73 @@ BOOST_AUTO_TEST_CASE(shift_right_negative_lvalue) compileAndRun(sourceCode, 0, "C"); ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4266), u256(0)), encodeArgs(u256(-4266))); ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4266), u256(1)), encodeArgs(u256(-2133))); - ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4266), u256(4)), encodeArgs(u256(-266))); - ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4266), u256(8)), encodeArgs(u256(-16))); - ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4266), u256(16)), encodeArgs(u256(0))); - ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4266), u256(17)), encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4266), u256(4)), encodeArgs(u256(-267))); + ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4266), u256(8)), encodeArgs(u256(-17))); + ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4266), u256(16)), encodeArgs(u256(-1))); + ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4266), u256(17)), encodeArgs(u256(-1))); ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4267), u256(0)), encodeArgs(u256(-4267))); - ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4267), u256(1)), encodeArgs(u256(-2133))); - ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4267), u256(4)), encodeArgs(u256(-266))); - ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4267), u256(8)), encodeArgs(u256(-16))); - ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4267), u256(16)), encodeArgs(u256(0))); - ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4267), u256(17)), encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4267), u256(1)), encodeArgs(u256(-2134))); + ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4267), u256(4)), encodeArgs(u256(-267))); + ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4267), u256(8)), encodeArgs(u256(-17))); + ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4267), u256(16)), encodeArgs(u256(-1))); + ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4267), u256(17)), encodeArgs(u256(-1))); +} + +BOOST_AUTO_TEST_CASE(shift_right_negative_literal) +{ + char const* sourceCode = R"( + contract C { + function f1() pure returns (bool) { + return (-4266 >> 0) == -4266; + } + function f2() pure returns (bool) { + return (-4266 >> 1) == -2133; + } + function f3() pure returns (bool) { + return (-4266 >> 4) == -267; + } + function f4() pure returns (bool) { + return (-4266 >> 8) == -17; + } + function f5() pure returns (bool) { + return (-4266 >> 16) == -1; + } + function f6() pure returns (bool) { + return (-4266 >> 17) == -1; + } + function g1() pure returns (bool) { + return (-4267 >> 0) == -4267; + } + function g2() pure returns (bool) { + return (-4267 >> 1) == -2134; + } + function g3() pure returns (bool) { + return (-4267 >> 4) == -267; + } + function g4() pure returns (bool) { + return (-4267 >> 8) == -17; + } + function g5() pure returns (bool) { + return (-4267 >> 16) == -1; + } + function g6() pure returns (bool) { + return (-4267 >> 17) == -1; + } + } + )"; + compileAndRun(sourceCode, 0, "C"); + ABI_CHECK(callContractFunction("f1()"), encodeArgs(true)); + ABI_CHECK(callContractFunction("f2()"), encodeArgs(true)); + ABI_CHECK(callContractFunction("f3()"), encodeArgs(true)); + ABI_CHECK(callContractFunction("f4()"), encodeArgs(true)); + ABI_CHECK(callContractFunction("f5()"), encodeArgs(true)); + ABI_CHECK(callContractFunction("f6()"), encodeArgs(true)); + ABI_CHECK(callContractFunction("g1()"), encodeArgs(true)); + ABI_CHECK(callContractFunction("g2()"), encodeArgs(true)); + ABI_CHECK(callContractFunction("g3()"), encodeArgs(true)); + ABI_CHECK(callContractFunction("g4()"), encodeArgs(true)); + ABI_CHECK(callContractFunction("g5()"), encodeArgs(true)); + ABI_CHECK(callContractFunction("g6()"), encodeArgs(true)); } BOOST_AUTO_TEST_CASE(shift_right_negative_lvalue_int8) @@ -10607,16 +10643,16 @@ BOOST_AUTO_TEST_CASE(shift_right_negative_lvalue_int8) compileAndRun(sourceCode, 0, "C"); ABI_CHECK(callContractFunction("f(int8,int8)", u256(-66), u256(0)), encodeArgs(u256(-66))); ABI_CHECK(callContractFunction("f(int8,int8)", u256(-66), u256(1)), encodeArgs(u256(-33))); - ABI_CHECK(callContractFunction("f(int8,int8)", u256(-66), u256(4)), encodeArgs(u256(-4))); - ABI_CHECK(callContractFunction("f(int8,int8)", u256(-66), u256(8)), encodeArgs(u256(0))); - ABI_CHECK(callContractFunction("f(int8,int8)", u256(-66), u256(16)), encodeArgs(u256(0))); - ABI_CHECK(callContractFunction("f(int8,int8)", u256(-66), u256(17)), encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("f(int8,int8)", u256(-66), u256(4)), encodeArgs(u256(-5))); + ABI_CHECK(callContractFunction("f(int8,int8)", u256(-66), u256(8)), encodeArgs(u256(-1))); + ABI_CHECK(callContractFunction("f(int8,int8)", u256(-66), u256(16)), encodeArgs(u256(-1))); + ABI_CHECK(callContractFunction("f(int8,int8)", u256(-66), u256(17)), encodeArgs(u256(-1))); ABI_CHECK(callContractFunction("f(int8,int8)", u256(-67), u256(0)), encodeArgs(u256(-67))); - ABI_CHECK(callContractFunction("f(int8,int8)", u256(-67), u256(1)), encodeArgs(u256(-33))); - ABI_CHECK(callContractFunction("f(int8,int8)", u256(-67), u256(4)), encodeArgs(u256(-4))); - ABI_CHECK(callContractFunction("f(int8,int8)", u256(-67), u256(8)), encodeArgs(u256(0))); - ABI_CHECK(callContractFunction("f(int8,int8)", u256(-67), u256(16)), encodeArgs(u256(0))); - ABI_CHECK(callContractFunction("f(int8,int8)", u256(-67), u256(17)), encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("f(int8,int8)", u256(-67), u256(1)), encodeArgs(u256(-34))); + ABI_CHECK(callContractFunction("f(int8,int8)", u256(-67), u256(4)), encodeArgs(u256(-5))); + ABI_CHECK(callContractFunction("f(int8,int8)", u256(-67), u256(8)), encodeArgs(u256(-1))); + ABI_CHECK(callContractFunction("f(int8,int8)", u256(-67), u256(16)), encodeArgs(u256(-1))); + ABI_CHECK(callContractFunction("f(int8,int8)", u256(-67), u256(17)), encodeArgs(u256(-1))); } BOOST_AUTO_TEST_CASE(shift_right_negative_lvalue_signextend_int8) @@ -10630,10 +10666,10 @@ BOOST_AUTO_TEST_CASE(shift_right_negative_lvalue_signextend_int8) )"; compileAndRun(sourceCode, 0, "C"); ABI_CHECK(callContractFunction("f(int8,int8)", u256(0x99u), u256(0)), encodeArgs(u256(-103))); - ABI_CHECK(callContractFunction("f(int8,int8)", u256(0x99u), u256(1)), encodeArgs(u256(-51))); - ABI_CHECK(callContractFunction("f(int8,int8)", u256(0x99u), u256(2)), encodeArgs(u256(-25))); - ABI_CHECK(callContractFunction("f(int8,int8)", u256(0x99u), u256(4)), encodeArgs(u256(-6))); - ABI_CHECK(callContractFunction("f(int8,int8)", u256(0x99u), u256(8)), encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("f(int8,int8)", u256(0x99u), u256(1)), encodeArgs(u256(-52))); + ABI_CHECK(callContractFunction("f(int8,int8)", u256(0x99u), u256(2)), encodeArgs(u256(-26))); + ABI_CHECK(callContractFunction("f(int8,int8)", u256(0x99u), u256(4)), encodeArgs(u256(-7))); + ABI_CHECK(callContractFunction("f(int8,int8)", u256(0x99u), u256(8)), encodeArgs(u256(-1))); } BOOST_AUTO_TEST_CASE(shift_right_negative_lvalue_signextend_int16) @@ -10647,10 +10683,10 @@ BOOST_AUTO_TEST_CASE(shift_right_negative_lvalue_signextend_int16) )"; compileAndRun(sourceCode, 0, "C"); ABI_CHECK(callContractFunction("f(int16,int16)", u256(0xFF99u), u256(0)), encodeArgs(u256(-103))); - ABI_CHECK(callContractFunction("f(int16,int16)", u256(0xFF99u), u256(1)), encodeArgs(u256(-51))); - ABI_CHECK(callContractFunction("f(int16,int16)", u256(0xFF99u), u256(2)), encodeArgs(u256(-25))); - ABI_CHECK(callContractFunction("f(int16,int16)", u256(0xFF99u), u256(4)), encodeArgs(u256(-6))); - ABI_CHECK(callContractFunction("f(int16,int16)", u256(0xFF99u), u256(8)), encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("f(int16,int16)", u256(0xFF99u), u256(1)), encodeArgs(u256(-52))); + ABI_CHECK(callContractFunction("f(int16,int16)", u256(0xFF99u), u256(2)), encodeArgs(u256(-26))); + ABI_CHECK(callContractFunction("f(int16,int16)", u256(0xFF99u), u256(4)), encodeArgs(u256(-7))); + ABI_CHECK(callContractFunction("f(int16,int16)", u256(0xFF99u), u256(8)), encodeArgs(u256(-1))); } BOOST_AUTO_TEST_CASE(shift_right_negative_lvalue_signextend_int32) @@ -10664,10 +10700,10 @@ BOOST_AUTO_TEST_CASE(shift_right_negative_lvalue_signextend_int32) )"; compileAndRun(sourceCode, 0, "C"); ABI_CHECK(callContractFunction("f(int32,int32)", u256(0xFFFFFF99u), u256(0)), encodeArgs(u256(-103))); - ABI_CHECK(callContractFunction("f(int32,int32)", u256(0xFFFFFF99u), u256(1)), encodeArgs(u256(-51))); - ABI_CHECK(callContractFunction("f(int32,int32)", u256(0xFFFFFF99u), u256(2)), encodeArgs(u256(-25))); - ABI_CHECK(callContractFunction("f(int32,int32)", u256(0xFFFFFF99u), u256(4)), encodeArgs(u256(-6))); - ABI_CHECK(callContractFunction("f(int32,int32)", u256(0xFFFFFF99u), u256(8)), encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("f(int32,int32)", u256(0xFFFFFF99u), u256(1)), encodeArgs(u256(-52))); + ABI_CHECK(callContractFunction("f(int32,int32)", u256(0xFFFFFF99u), u256(2)), encodeArgs(u256(-26))); + ABI_CHECK(callContractFunction("f(int32,int32)", u256(0xFFFFFF99u), u256(4)), encodeArgs(u256(-7))); + ABI_CHECK(callContractFunction("f(int32,int32)", u256(0xFFFFFF99u), u256(8)), encodeArgs(u256(-1))); } @@ -10683,16 +10719,16 @@ BOOST_AUTO_TEST_CASE(shift_right_negative_lvalue_int16) compileAndRun(sourceCode, 0, "C"); ABI_CHECK(callContractFunction("f(int16,int16)", u256(-4266), u256(0)), encodeArgs(u256(-4266))); ABI_CHECK(callContractFunction("f(int16,int16)", u256(-4266), u256(1)), encodeArgs(u256(-2133))); - ABI_CHECK(callContractFunction("f(int16,int16)", u256(-4266), u256(4)), encodeArgs(u256(-266))); - ABI_CHECK(callContractFunction("f(int16,int16)", u256(-4266), u256(8)), encodeArgs(u256(-16))); - ABI_CHECK(callContractFunction("f(int16,int16)", u256(-4266), u256(16)), encodeArgs(u256(0))); - ABI_CHECK(callContractFunction("f(int16,int16)", u256(-4266), u256(17)), encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("f(int16,int16)", u256(-4266), u256(4)), encodeArgs(u256(-267))); + ABI_CHECK(callContractFunction("f(int16,int16)", u256(-4266), u256(8)), encodeArgs(u256(-17))); + ABI_CHECK(callContractFunction("f(int16,int16)", u256(-4266), u256(16)), encodeArgs(u256(-1))); + ABI_CHECK(callContractFunction("f(int16,int16)", u256(-4266), u256(17)), encodeArgs(u256(-1))); ABI_CHECK(callContractFunction("f(int16,int16)", u256(-4267), u256(0)), encodeArgs(u256(-4267))); - ABI_CHECK(callContractFunction("f(int16,int16)", u256(-4267), u256(1)), encodeArgs(u256(-2133))); - ABI_CHECK(callContractFunction("f(int16,int16)", u256(-4267), u256(4)), encodeArgs(u256(-266))); - ABI_CHECK(callContractFunction("f(int16,int16)", u256(-4267), u256(8)), encodeArgs(u256(-16))); - ABI_CHECK(callContractFunction("f(int16,int16)", u256(-4267), u256(16)), encodeArgs(u256(0))); - ABI_CHECK(callContractFunction("f(int16,int16)", u256(-4267), u256(17)), encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("f(int16,int16)", u256(-4267), u256(1)), encodeArgs(u256(-2134))); + ABI_CHECK(callContractFunction("f(int16,int16)", u256(-4267), u256(4)), encodeArgs(u256(-267))); + ABI_CHECK(callContractFunction("f(int16,int16)", u256(-4267), u256(8)), encodeArgs(u256(-17))); + ABI_CHECK(callContractFunction("f(int16,int16)", u256(-4267), u256(16)), encodeArgs(u256(-1))); + ABI_CHECK(callContractFunction("f(int16,int16)", u256(-4267), u256(17)), encodeArgs(u256(-1))); } BOOST_AUTO_TEST_CASE(shift_right_negative_lvalue_int32) @@ -10707,16 +10743,16 @@ BOOST_AUTO_TEST_CASE(shift_right_negative_lvalue_int32) compileAndRun(sourceCode, 0, "C"); ABI_CHECK(callContractFunction("f(int32,int32)", u256(-4266), u256(0)), encodeArgs(u256(-4266))); ABI_CHECK(callContractFunction("f(int32,int32)", u256(-4266), u256(1)), encodeArgs(u256(-2133))); - ABI_CHECK(callContractFunction("f(int32,int32)", u256(-4266), u256(4)), encodeArgs(u256(-266))); - ABI_CHECK(callContractFunction("f(int32,int32)", u256(-4266), u256(8)), encodeArgs(u256(-16))); - ABI_CHECK(callContractFunction("f(int32,int32)", u256(-4266), u256(16)), encodeArgs(u256(0))); - ABI_CHECK(callContractFunction("f(int32,int32)", u256(-4266), u256(17)), encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("f(int32,int32)", u256(-4266), u256(4)), encodeArgs(u256(-267))); + ABI_CHECK(callContractFunction("f(int32,int32)", u256(-4266), u256(8)), encodeArgs(u256(-17))); + ABI_CHECK(callContractFunction("f(int32,int32)", u256(-4266), u256(16)), encodeArgs(u256(-1))); + ABI_CHECK(callContractFunction("f(int32,int32)", u256(-4266), u256(17)), encodeArgs(u256(-1))); ABI_CHECK(callContractFunction("f(int32,int32)", u256(-4267), u256(0)), encodeArgs(u256(-4267))); - ABI_CHECK(callContractFunction("f(int32,int32)", u256(-4267), u256(1)), encodeArgs(u256(-2133))); - ABI_CHECK(callContractFunction("f(int32,int32)", u256(-4267), u256(4)), encodeArgs(u256(-266))); - ABI_CHECK(callContractFunction("f(int32,int32)", u256(-4267), u256(8)), encodeArgs(u256(-16))); - ABI_CHECK(callContractFunction("f(int32,int32)", u256(-4267), u256(16)), encodeArgs(u256(0))); - ABI_CHECK(callContractFunction("f(int32,int32)", u256(-4267), u256(17)), encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("f(int32,int32)", u256(-4267), u256(1)), encodeArgs(u256(-2134))); + ABI_CHECK(callContractFunction("f(int32,int32)", u256(-4267), u256(4)), encodeArgs(u256(-267))); + ABI_CHECK(callContractFunction("f(int32,int32)", u256(-4267), u256(8)), encodeArgs(u256(-17))); + ABI_CHECK(callContractFunction("f(int32,int32)", u256(-4267), u256(16)), encodeArgs(u256(-1))); + ABI_CHECK(callContractFunction("f(int32,int32)", u256(-4267), u256(17)), encodeArgs(u256(-1))); } BOOST_AUTO_TEST_CASE(shift_right_negative_lvalue_assignment) @@ -10732,16 +10768,16 @@ BOOST_AUTO_TEST_CASE(shift_right_negative_lvalue_assignment) compileAndRun(sourceCode, 0, "C"); ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4266), u256(0)), encodeArgs(u256(-4266))); ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4266), u256(1)), encodeArgs(u256(-2133))); - ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4266), u256(4)), encodeArgs(u256(-266))); - ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4266), u256(8)), encodeArgs(u256(-16))); - ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4266), u256(16)), encodeArgs(u256(0))); - ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4266), u256(17)), encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4266), u256(4)), encodeArgs(u256(-267))); + ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4266), u256(8)), encodeArgs(u256(-17))); + ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4266), u256(16)), encodeArgs(u256(-1))); + ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4266), u256(17)), encodeArgs(u256(-1))); ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4267), u256(0)), encodeArgs(u256(-4267))); - ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4267), u256(1)), encodeArgs(u256(-2133))); - ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4267), u256(4)), encodeArgs(u256(-266))); - ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4267), u256(8)), encodeArgs(u256(-16))); - ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4267), u256(16)), encodeArgs(u256(0))); - ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4267), u256(17)), encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4267), u256(1)), encodeArgs(u256(-2134))); + ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4267), u256(4)), encodeArgs(u256(-267))); + ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4267), u256(8)), encodeArgs(u256(-17))); + ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4267), u256(16)), encodeArgs(u256(-1))); + ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4267), u256(17)), encodeArgs(u256(-1))); } BOOST_AUTO_TEST_CASE(shift_negative_rvalue) @@ -11551,13 +11587,13 @@ BOOST_AUTO_TEST_CASE(delegatecall_return_value) return value; } function get_delegated() external returns (bool) { - return this.delegatecall(bytes4(sha3("get()"))); + return this.delegatecall(bytes4(keccak256("get()"))); } function assert0() external view { assert(value == 0); } function assert0_delegated() external returns (bool) { - return this.delegatecall(bytes4(sha3("assert0()"))); + return this.delegatecall(bytes4(keccak256("assert0()"))); } } )DELIMITER"; diff --git a/test/libsolidity/SolidityParser.cpp b/test/libsolidity/SolidityParser.cpp index 0797b53b..1ffbd771 100644 --- a/test/libsolidity/SolidityParser.cpp +++ b/test/libsolidity/SolidityParser.cpp @@ -491,28 +491,46 @@ BOOST_AUTO_TEST_CASE(keyword_is_reserved) auto keywords = { "abstract", "after", + "alias", + "apply", + "auto", "case", "catch", + "copyof", "default", + "define", "final", + "immutable", + "implements", "in", "inline", "let", + "macro", "match", + "mutable", "null", "of", + "override", + "partial", + "promise", + "reference", "relocatable", + "sealed", + "sizeof", "static", + "supports", "switch", "try", "type", - "typeof" + "typedef", + "typeof", + "unchecked" }; for (const auto& keyword: keywords) { auto text = std::string("contract ") + keyword + " {}"; - CHECK_PARSE_ERROR(text.c_str(), "Expected identifier but got reserved keyword"); + CHECK_PARSE_ERROR(text.c_str(), string("Expected identifier but got reserved keyword '") + keyword + "'"); } } diff --git a/test/libsolidity/SyntaxTest.cpp b/test/libsolidity/SyntaxTest.cpp index 1c2355d5..430073a0 100644 --- a/test/libsolidity/SyntaxTest.cpp +++ b/test/libsolidity/SyntaxTest.cpp @@ -268,9 +268,16 @@ int SyntaxTest::registerTests( [fullpath] { BOOST_REQUIRE_NO_THROW({ - stringstream errorStream; - if (!SyntaxTest(fullpath.string()).run(errorStream)) - BOOST_ERROR("Test expectation mismatch.\n" + errorStream.str()); + try + { + stringstream errorStream; + if (!SyntaxTest(fullpath.string()).run(errorStream)) + BOOST_ERROR("Test expectation mismatch.\n" + errorStream.str()); + } + catch (boost::exception const& _e) + { + BOOST_ERROR("Exception during syntax test: " << boost::diagnostic_information(_e)); + } }); }, _path.stem().string(), diff --git a/test/libsolidity/syntaxTests/deprecated_functions.sol b/test/libsolidity/syntaxTests/deprecated_functions.sol index 9df2b43c..ff3af7d2 100644 --- a/test/libsolidity/syntaxTests/deprecated_functions.sol +++ b/test/libsolidity/syntaxTests/deprecated_functions.sol @@ -8,5 +8,5 @@ contract test { } } // ---- -// Warning: (58-64): "sha3" has been deprecated in favour of "keccak256" -// Warning: (99-109): "suicide" has been deprecated in favour of "selfdestruct" +// TypeError: (58-64): "sha3" has been deprecated in favour of "keccak256" +// TypeError: (99-109): "suicide" has been deprecated in favour of "selfdestruct" diff --git a/test/libsolidity/syntaxTests/deprecated_functions_050.sol b/test/libsolidity/syntaxTests/deprecated_functions_050.sol deleted file mode 100644 index b28e5abb..00000000 --- a/test/libsolidity/syntaxTests/deprecated_functions_050.sol +++ /dev/null @@ -1,15 +0,0 @@ -pragma experimental "v0.5.0"; -contract test { - function f() pure public { - bytes32 x = sha3(uint8(1)); - x; - } - function g() public { - suicide(1); - } -} -// ---- -// TypeError: (88-102): "sha3" has been deprecated in favour of "keccak256" -// TypeError: (88-102): This function only accepts a single "bytes" argument. Please use "abi.encodePacked(...)" or a similar function to encode the data. -// TypeError: (88-102): The provided argument of type uint8 is not implicitly convertible to expected type bytes memory. -// TypeError: (137-147): "suicide" has been deprecated in favour of "selfdestruct" diff --git a/test/libsolidity/syntaxTests/tight_packing_literals.sol b/test/libsolidity/syntaxTests/tight_packing_literals.sol index a190adc3..d6c7f0ba 100644 --- a/test/libsolidity/syntaxTests/tight_packing_literals.sol +++ b/test/libsolidity/syntaxTests/tight_packing_literals.sol @@ -2,9 +2,6 @@ contract C { function f() pure public returns (bytes32) { return keccak256(1); } - function g() pure public returns (bytes32) { - return sha3(1); - } function h() pure public returns (bytes32) { return sha256(1); } @@ -20,14 +17,10 @@ contract C { // Warning: (87-88): The type of "int_const 1" was inferred as uint8. This is probably not desired. Use an explicit type to silence this warning. // Warning: (77-89): This function only accepts a single "bytes" argument. Please use "abi.encodePacked(...)" or a similar function to encode the data. // Warning: (77-89): The provided argument of type int_const 1 is not implicitly convertible to expected type bytes memory. -// Warning: (161-168): "sha3" has been deprecated in favour of "keccak256" -// Warning: (166-167): The type of "int_const 1" was inferred as uint8. This is probably not desired. Use an explicit type to silence this warning. -// Warning: (161-168): This function only accepts a single "bytes" argument. Please use "abi.encodePacked(...)" or a similar function to encode the data. -// Warning: (161-168): The provided argument of type int_const 1 is not implicitly convertible to expected type bytes memory. -// Warning: (247-248): The type of "int_const 1" was inferred as uint8. This is probably not desired. Use an explicit type to silence this warning. -// Warning: (240-249): This function only accepts a single "bytes" argument. Please use "abi.encodePacked(...)" or a similar function to encode the data. -// Warning: (240-249): The provided argument of type int_const 1 is not implicitly convertible to expected type bytes memory. -// Warning: (331-332): The type of "int_const 1" was inferred as uint8. This is probably not desired. Use an explicit type to silence this warning. -// Warning: (321-333): This function only accepts a single "bytes" argument. Please use "abi.encodePacked(...)" or a similar function to encode the data. -// Warning: (321-333): The provided argument of type int_const 1 is not implicitly convertible to expected type bytes memory. -// Warning: (420-421): The type of "int_const 1" was inferred as uint8. This is probably not desired. Use an explicit type to silence this warning. +// Warning: (168-169): The type of "int_const 1" was inferred as uint8. This is probably not desired. Use an explicit type to silence this warning. +// Warning: (161-170): This function only accepts a single "bytes" argument. Please use "abi.encodePacked(...)" or a similar function to encode the data. +// Warning: (161-170): The provided argument of type int_const 1 is not implicitly convertible to expected type bytes memory. +// Warning: (252-253): The type of "int_const 1" was inferred as uint8. This is probably not desired. Use an explicit type to silence this warning. +// Warning: (242-254): This function only accepts a single "bytes" argument. Please use "abi.encodePacked(...)" or a similar function to encode the data. +// Warning: (242-254): The provided argument of type int_const 1 is not implicitly convertible to expected type bytes memory. +// Warning: (341-342): The type of "int_const 1" was inferred as uint8. This is probably not desired. Use an explicit type to silence this warning. diff --git a/test/libsolidity/syntaxTests/tight_packing_literals_fine.sol b/test/libsolidity/syntaxTests/tight_packing_literals_fine.sol index 2b9b688a..27665b52 100644 --- a/test/libsolidity/syntaxTests/tight_packing_literals_fine.sol +++ b/test/libsolidity/syntaxTests/tight_packing_literals_fine.sol @@ -2,9 +2,6 @@ contract C { function f() pure public returns (bytes32) { return keccak256(uint8(1)); } - function g() pure public returns (bytes32) { - return sha3(uint8(1)); - } function h() pure public returns (bytes32) { return sha256(uint8(1)); } @@ -21,10 +18,7 @@ contract C { // ---- // Warning: (77-96): This function only accepts a single "bytes" argument. Please use "abi.encodePacked(...)" or a similar function to encode the data. // Warning: (77-96): The provided argument of type uint8 is not implicitly convertible to expected type bytes memory. -// Warning: (168-182): "sha3" has been deprecated in favour of "keccak256" -// Warning: (168-182): This function only accepts a single "bytes" argument. Please use "abi.encodePacked(...)" or a similar function to encode the data. -// Warning: (168-182): The provided argument of type uint8 is not implicitly convertible to expected type bytes memory. -// Warning: (254-270): This function only accepts a single "bytes" argument. Please use "abi.encodePacked(...)" or a similar function to encode the data. -// Warning: (254-270): The provided argument of type uint8 is not implicitly convertible to expected type bytes memory. -// Warning: (342-361): This function only accepts a single "bytes" argument. Please use "abi.encodePacked(...)" or a similar function to encode the data. -// Warning: (342-361): The provided argument of type uint8 is not implicitly convertible to expected type bytes memory. +// Warning: (168-184): This function only accepts a single "bytes" argument. Please use "abi.encodePacked(...)" or a similar function to encode the data. +// Warning: (168-184): The provided argument of type uint8 is not implicitly convertible to expected type bytes memory. +// Warning: (256-275): This function only accepts a single "bytes" argument. Please use "abi.encodePacked(...)" or a similar function to encode the data. +// Warning: (256-275): The provided argument of type uint8 is not implicitly convertible to expected type bytes memory. diff --git a/test/solcjsTests.sh b/test/solcjsTests.sh index 27797cb4..e0bbc5df 100755 --- a/test/solcjsTests.sh +++ b/test/solcjsTests.sh @@ -53,6 +53,11 @@ DIR=$(mktemp -d) rm -f soljson.js cp "$SOLJSON" soljson.js + # ensure to use always 0.5.0 sources + # FIXME: should be removed once the version bump in this repo is done + rm -rf test/DAO040 + cp -R test/DAO test/DAO040 + # Update version (needed for some tests) echo "Updating package.json to version $VERSION" npm version --no-git-tag-version $VERSION diff --git a/test/tools/isoltest.cpp b/test/tools/isoltest.cpp index 100fcbf0..d4b99e9d 100644 --- a/test/tools/isoltest.cpp +++ b/test/tools/isoltest.cpp @@ -150,39 +150,22 @@ SyntaxTestTool::Result SyntaxTestTool::process() m_test = unique_ptr<SyntaxTest>(new SyntaxTest(m_path.string())); success = m_test->run(outputMessages, " ", m_formatted); } - catch(CompilerError const& _e) + catch(boost::exception const& _e) { FormattedScope(cout, m_formatted, {BOLD, RED}) << - "Exception: " << SyntaxTest::errorMessage(_e) << endl; - return Result::Exception; - } - catch(InternalCompilerError const& _e) - { - FormattedScope(cout, m_formatted, {BOLD, RED}) << - "InternalCompilerError: " << SyntaxTest::errorMessage(_e) << endl; - return Result::Exception; - } - catch(FatalError const& _e) - { - FormattedScope(cout, m_formatted, {BOLD, RED}) << - "FatalError: " << SyntaxTest::errorMessage(_e) << endl; - return Result::Exception; - } - catch(UnimplementedFeatureError const& _e) - { - FormattedScope(cout, m_formatted, {BOLD, RED}) << - "UnimplementedFeatureError: " << SyntaxTest::errorMessage(_e) << endl; + "Exception during syntax test: " << boost::diagnostic_information(_e) << endl; return Result::Exception; } catch (std::exception const& _e) { - FormattedScope(cout, m_formatted, {BOLD, RED}) << "Exception: " << _e.what() << endl; + FormattedScope(cout, m_formatted, {BOLD, RED}) << + "Exception during syntax test: " << _e.what() << endl; return Result::Exception; } catch(...) { FormattedScope(cout, m_formatted, {BOLD, RED}) << - "Unknown Exception" << endl; + "Unknown exception during syntax test." << endl; return Result::Exception; } |