aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorchriseth <chris@ethereum.org>2016-09-17 21:25:54 +0800
committerGitHub <noreply@github.com>2016-09-17 21:25:54 +0800
commitaf6afb0415761b53721f89c7f65064807f41cbd3 (patch)
tree006481ce07f5ed6f1690014921f8c559b71dc5b5
parent4fc6fc2ca59579fae2472df319c2d8d31fe5bde5 (diff)
parenta78e7794225da95d0f875c908025213d6a47cb59 (diff)
downloaddexon-solidity-af6afb0415761b53721f89c7f65064807f41cbd3.tar.gz
dexon-solidity-af6afb0415761b53721f89c7f65064807f41cbd3.tar.zst
dexon-solidity-af6afb0415761b53721f89c7f65064807f41cbd3.zip
Merge pull request #1107 from ethereum/develop
Version 0.4.2
-rw-r--r--.gitignore3
-rw-r--r--CMakeLists.txt2
-rw-r--r--Changelog.md13
-rw-r--r--cmake/scripts/buildinfo.cmake14
-rw-r--r--docs/conf.py4
-rw-r--r--docs/installing-solidity.rst26
-rw-r--r--libdevcore/Assertions.h14
-rw-r--r--libsolidity/analysis/TypeChecker.cpp2
-rw-r--r--libsolidity/codegen/ContractCompiler.cpp4
-rw-r--r--libsolidity/codegen/ExpressionCompiler.cpp17
-rw-r--r--libsolidity/formal/Why3Translator.cpp108
-rw-r--r--libsolidity/formal/Why3Translator.h5
-rwxr-xr-xscripts/build_emscripten.sh2
-rwxr-xr-xscripts/install_deps.sh47
-rwxr-xr-xscripts/release_ppa.sh4
-rwxr-xr-xscripts/travis-emscripten/publish_binary.sh7
-rw-r--r--test/libsolidity/SolidityEndToEndTest.cpp44
-rw-r--r--test/libsolidity/SolidityNameAndTypeResolution.cpp10
18 files changed, 276 insertions, 50 deletions
diff --git a/.gitignore b/.gitignore
index 1ad199c1..e3e12421 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,6 @@
+.commit_hash.txt
+.prerelease.txt
+
# Compiled Object files
*.slo
*.lo
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 6ad9c061..f190a507 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -8,7 +8,7 @@ include(EthPolicy)
eth_policy()
# project name and version should be set after cmake_policy CMP0048
-set(PROJECT_VERSION "0.4.1")
+set(PROJECT_VERSION "0.4.2")
project(solidity VERSION ${PROJECT_VERSION})
# Let's find our dependencies
diff --git a/Changelog.md b/Changelog.md
index 1ae18658..b5c0631d 100644
--- a/Changelog.md
+++ b/Changelog.md
@@ -1,3 +1,16 @@
+### 0.4.2 (2016-09-17)
+
+Bugfixes:
+
+ * Code Generator: Fix library functions being called from payable functions.
+ * Type Checker: Fixed a crash about invalid array types.
+ * Code Generator: Fixed a call gas bug that became visible after
+ version 0.4.0 for calls where the output is larger than the input.
+
+### 0.4.1 (2016-09-09)
+
+ * Build System: Fixes to allow library compilation.
+
### 0.4.0 (2016-09-08)
This release deliberately breaks backwards compatibility mostly to
diff --git a/cmake/scripts/buildinfo.cmake b/cmake/scripts/buildinfo.cmake
index e2f8cb3e..8e1615f6 100644
--- a/cmake/scripts/buildinfo.cmake
+++ b/cmake/scripts/buildinfo.cmake
@@ -26,6 +26,7 @@ if (EXISTS ${ETH_SOURCE_DIR}/prerelease.txt)
string(STRIP "${SOL_VERSION_PRERELEASE}" SOL_VERSION_PRERELEASE)
else()
string(TIMESTAMP SOL_VERSION_PRERELEASE "develop.%Y.%m.%d" UTC)
+ string(REPLACE .0 . SOL_VERSION_PRERELEASE "${SOL_VERSION_PRERELEASE}")
endif()
if (EXISTS ${ETH_SOURCE_DIR}/commit_hash.txt)
@@ -33,7 +34,7 @@ if (EXISTS ${ETH_SOURCE_DIR}/commit_hash.txt)
string(STRIP ${SOL_COMMIT_HASH} SOL_COMMIT_HASH)
else()
execute_process(
- COMMAND git --git-dir=${ETH_SOURCE_DIR}/.git --work-tree=${ETH_SOURCE_DIR} rev-parse HEAD
+ COMMAND git --git-dir=${ETH_SOURCE_DIR}/.git --work-tree=${ETH_SOURCE_DIR} rev-parse --short=8 HEAD
OUTPUT_VARIABLE SOL_COMMIT_HASH OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_QUIET
)
execute_process(
@@ -47,14 +48,17 @@ if (SOL_COMMIT_HASH)
string(SUBSTRING ${SOL_COMMIT_HASH} 0 8 SOL_COMMIT_HASH)
endif()
-if (SOL_COMMIT_HASH AND SOL_LOCAL_CHANGES)
- set(SOL_COMMIT_HASH "${SOL_COMMIT_HASH}.mod")
-endif()
-
if (NOT SOL_COMMIT_HASH)
message(FATAL_ERROR "Unable to determine commit hash. Either compile from within git repository or "
"supply a file called commit_hash.txt")
endif()
+if (NOT SOL_COMMIT_HASH MATCHES [a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9])
+ message(FATAL_ERROR "Malformed commit hash \"${SOL_COMMIT_HASH}\". It has to consist of exactly 8 hex digits.")
+endif()
+
+if (SOL_COMMIT_HASH AND SOL_LOCAL_CHANGES)
+ set(SOL_COMMIT_HASH "${SOL_COMMIT_HASH}.mod")
+endif()
set(SOL_VERSION_BUILDINFO "commit.${SOL_COMMIT_HASH}.${ETH_BUILD_PLATFORM}")
diff --git a/docs/conf.py b/docs/conf.py
index d0e26362..485184f2 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -56,9 +56,9 @@ copyright = '2016, Ethereum'
# built documents.
#
# The short X.Y version.
-version = '0.2.0'
+version = '0.4.1'
# The full version, including alpha/beta/rc tags.
-release = '0.2.0'
+release = '0.4.1-develop'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
diff --git a/docs/installing-solidity.rst b/docs/installing-solidity.rst
index ad27e528..ebb7537b 100644
--- a/docs/installing-solidity.rst
+++ b/docs/installing-solidity.rst
@@ -6,6 +6,15 @@
Installing Solidity
###################
+Versioning
+==========
+
+Solidity versions follow `semantic versioning <https://semver.org>` and in addition to
+releases, **nightly development builds** are also made available. The nightly builds
+are not guaranteed to be working and despite best efforts they might contain undocumented
+and/or broken changes. We recommend to use the latest release. Package installers below
+will use the latest release.
+
Browser-Solidity
================
@@ -186,3 +195,20 @@ Alternatively, you can build for Windows on the command-line, like so:
.. code:: bash
cmake --build . --config RelWithDebInfo
+
+Important information about versioning
+======================================
+
+After a release is made, the patch version level is bumped, because we assume that only
+patch level changes follow. When changes are merged, the version should be bumped according
+to semver and the severity of the change. Finally, a release is always made with the version
+of the current nightly build, but without the ``prerelease`` specifier.
+
+Example:
+- 0) the 0.4.0 release is made
+- 1) nightly build has a version of 0.4.1 from now on
+- 2) non-breaking changes are introduced - no change in version
+- 3) a breaking change is introduced - version is bumped to 0.5.0
+- 4) the 0.5.0 release is made
+
+This behaviour works well with the version pragma.
diff --git a/libdevcore/Assertions.h b/libdevcore/Assertions.h
index 7b4a4a76..05e0b0e5 100644
--- a/libdevcore/Assertions.h
+++ b/libdevcore/Assertions.h
@@ -73,7 +73,7 @@ inline bool assertEqualAux(A const& _a, B const& _b, char const* _aStr, char con
/// Use it as assertThrow(1 == 1, ExceptionType, "Mathematics is wrong.");
/// Do NOT supply an exception object as the second parameter.
#define assertThrow(_condition, _ExceptionType, _description) \
- ::dev::assertThrowAux<_ExceptionType>(_condition, _description, __LINE__, __FILE__, ETH_FUNC)
+ ::dev::assertThrowAux<_ExceptionType>(!!(_condition), _description, __LINE__, __FILE__, ETH_FUNC)
using errinfo_comment = boost::error_info<struct tag_comment, std::string>;
@@ -96,16 +96,4 @@ inline void assertThrowAux(
);
}
-template <class _ExceptionType>
-inline void assertThrowAux(
- void const* _pointer,
- ::std::string const& _errorDescription,
- unsigned _line,
- char const* _file,
- char const* _function
-)
-{
- assertThrowAux<_ExceptionType>(_pointer != nullptr, _errorDescription, _line, _file, _function);
-}
-
}
diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp
index d9c54f75..ae7c13c8 100644
--- a/libsolidity/analysis/TypeChecker.cpp
+++ b/libsolidity/analysis/TypeChecker.cpp
@@ -1438,7 +1438,7 @@ bool TypeChecker::visit(IndexAccess const& _access)
length->literalValue(nullptr)
));
else
- typeError(index->location(), "Integer constant expected.");
+ fatalTypeError(index->location(), "Integer constant expected.");
}
break;
}
diff --git a/libsolidity/codegen/ContractCompiler.cpp b/libsolidity/codegen/ContractCompiler.cpp
index 33571bc0..18b42fce 100644
--- a/libsolidity/codegen/ContractCompiler.cpp
+++ b/libsolidity/codegen/ContractCompiler.cpp
@@ -263,7 +263,9 @@ void ContractCompiler::appendFunctionSelector(ContractDefinition const& _contrac
CompilerContext::LocationSetter locationSetter(m_context, functionType->declaration());
m_context << callDataUnpackerEntryPoints.at(it.first);
- if (!functionType->isPayable())
+ // We have to allow this for libraries, because value of the previous
+ // call is still visible in the delegatecall.
+ if (!functionType->isPayable() && !_contract.isLibrary())
{
// Throw if function is not payable but call contained ether.
m_context << Instruction::CALLVALUE;
diff --git a/libsolidity/codegen/ExpressionCompiler.cpp b/libsolidity/codegen/ExpressionCompiler.cpp
index 96ca4296..26acd8a4 100644
--- a/libsolidity/codegen/ExpressionCompiler.cpp
+++ b/libsolidity/codegen/ExpressionCompiler.cpp
@@ -1476,6 +1476,18 @@ void ExpressionCompiler::appendExternalFunctionCall(
utils().storeFreeMemoryPointer();
}
+ // Touch the end of the output area so that we do not pay for memory resize during the call
+ // (which we would have to subtract from the gas left)
+ // We could also just use MLOAD; POP right before the gas calculation, but the optimizer
+ // would remove that, so we use MSTORE here.
+ if (!_functionType.gasSet() && retSize > 0)
+ {
+ m_context << u256(0);
+ utils().fetchFreeMemoryPointer();
+ // This touches too much, but that way we save some rounding arithmetics
+ m_context << u256(retSize) << Instruction::ADD << Instruction::MSTORE;
+ }
+
// Copy function identifier to memory.
utils().fetchFreeMemoryPointer();
if (!_functionType.isBareCall() || manualFunctionId)
@@ -1551,10 +1563,7 @@ void ExpressionCompiler::appendExternalFunctionCall(
gasNeededByCaller += eth::GasCosts::callValueTransferGas;
if (!isCallCode && !isDelegateCall && !existenceChecked)
gasNeededByCaller += eth::GasCosts::callNewAccountGas; // we never know
- m_context <<
- gasNeededByCaller <<
- Instruction::GAS <<
- Instruction::SUB;
+ m_context << gasNeededByCaller << Instruction::GAS << Instruction::SUB;
}
if (isDelegateCall)
m_context << Instruction::DELEGATECALL;
diff --git a/libsolidity/formal/Why3Translator.cpp b/libsolidity/formal/Why3Translator.cpp
index 834024fa..f3831b40 100644
--- a/libsolidity/formal/Why3Translator.cpp
+++ b/libsolidity/formal/Why3Translator.cpp
@@ -36,6 +36,10 @@ bool Why3Translator::process(SourceUnit const& _source)
appendPreface();
_source.accept(*this);
}
+ catch (NoFormalType&)
+ {
+ solAssert(false, "There is a call to toFormalType() that does not catch NoFormalType exceptions.");
+ }
catch (FatalError& /*_e*/)
{
solAssert(m_errorOccured, "");
@@ -77,14 +81,30 @@ string Why3Translator::toFormalType(Type const& _type) const
return "uint256";
}
else if (auto type = dynamic_cast<ArrayType const*>(&_type))
+ {
if (!type->isByteArray() && type->isDynamicallySized() && type->dataStoredIn(DataLocation::Memory))
{
+ // Not catching NoFormalType exception. Let the caller deal with it.
string base = toFormalType(*type->baseType());
- if (!base.empty())
- return "array " + base;
+ return "array " + base;
}
+ }
+ else if (auto mappingType = dynamic_cast<MappingType const*>(&_type))
+ {
+ solAssert(mappingType->keyType(), "A mappingType misses a keyType.");
+ if (dynamic_cast<IntegerType const*>(&*mappingType->keyType()))
+ {
+ //@TODO Use the information from the key type and specify the length of the array as an invariant.
+ // Also the constructor need to specify the length of the array.
+ solAssert(mappingType->valueType(), "A mappingType misses a valueType.");
+ // Not catching NoFormalType exception. Let the caller deal with it.
+ string valueTypeFormal = toFormalType(*mappingType->valueType());
+ return "array " + valueTypeFormal;
+ }
+ }
- return "";
+ BOOST_THROW_EXCEPTION(NoFormalType()
+ << errinfo_noFormalTypeFrom(_type.toString(true)));
}
void Why3Translator::addLine(string const& _line)
@@ -142,9 +162,17 @@ bool Why3Translator::visit(ContractDefinition const& _contract)
m_currentContract.stateVariables = _contract.stateVariables();
for (VariableDeclaration const* variable: m_currentContract.stateVariables)
{
- string varType = toFormalType(*variable->annotation().type);
- if (varType.empty())
- fatalError(*variable, "Type not supported for state variable.");
+ string varType;
+ try
+ {
+ varType = toFormalType(*variable->annotation().type);
+ }
+ catch (NoFormalType &err)
+ {
+ string const* typeNamePtr = boost::get_error_info<errinfo_noFormalTypeFrom>(err);
+ string typeName = typeNamePtr ? " \"" + *typeNamePtr + "\"" : "";
+ fatalError(*variable, "Type" + typeName + " not supported for state variable.");
+ }
addLine("mutable _" + variable->name() + ": " + varType);
}
unindent();
@@ -218,9 +246,16 @@ bool Why3Translator::visit(FunctionDefinition const& _function)
add(" (this: account)");
for (auto const& param: _function.parameters())
{
- string paramType = toFormalType(*param->annotation().type);
- if (paramType.empty())
- error(*param, "Parameter type not supported.");
+ string paramType;
+ try
+ {
+ paramType = toFormalType(*param->annotation().type);
+ }
+ catch (NoFormalType &err)
+ {
+ string const* typeName = boost::get_error_info<errinfo_noFormalTypeFrom>(err);
+ error(*param, "Parameter type \"" + (typeName ? *typeName : "") + "\" not supported.");
+ }
if (param->name().empty())
error(*param, "Anonymous function parameters not supported.");
add(" (arg_" + param->name() + ": " + paramType + ")");
@@ -232,9 +267,16 @@ bool Why3Translator::visit(FunctionDefinition const& _function)
string retString = "(";
for (auto const& retParam: _function.returnParameters())
{
- string paramType = toFormalType(*retParam->annotation().type);
- if (paramType.empty())
- error(*retParam, "Parameter type not supported.");
+ string paramType;
+ try
+ {
+ paramType = toFormalType(*retParam->annotation().type);
+ }
+ catch (NoFormalType &err)
+ {
+ string const* typeName = boost::get_error_info<errinfo_noFormalTypeFrom>(err);
+ error(*retParam, "Parameter type " + (typeName ? *typeName : "") + " not supported.");
+ }
if (retString.size() != 1)
retString += ", ";
retString += paramType;
@@ -264,14 +306,32 @@ bool Why3Translator::visit(FunctionDefinition const& _function)
{
if (variable->name().empty())
error(*variable, "Unnamed return variables not yet supported.");
- string varType = toFormalType(*variable->annotation().type);
+ string varType;
+ try
+ {
+ varType = toFormalType(*variable->annotation().type);
+ }
+ catch (NoFormalType &err)
+ {
+ string const* typeNamePtr = boost::get_error_info<errinfo_noFormalTypeFrom>(err);
+ error(*variable, "Type " + (typeNamePtr ? *typeNamePtr : "") + "in return parameter not yet supported.");
+ }
addLine("let _" + variable->name() + ": ref " + varType + " = ref (of_int 0) in");
}
for (VariableDeclaration const* variable: _function.localVariables())
{
if (variable->name().empty())
error(*variable, "Unnamed variables not yet supported.");
- string varType = toFormalType(*variable->annotation().type);
+ string varType;
+ try
+ {
+ varType = toFormalType(*variable->annotation().type);
+ }
+ catch (NoFormalType &err)
+ {
+ string const* typeNamePtr = boost::get_error_info<errinfo_noFormalTypeFrom>(err);
+ error(*variable, "Type " + (typeNamePtr ? *typeNamePtr : "") + "in variable declaration not yet supported.");
+ }
addLine("let _" + variable->name() + ": ref " + varType + " = ref (of_int 0) in");
}
addLine("try");
@@ -434,8 +494,15 @@ bool Why3Translator::visit(TupleExpression const& _node)
bool Why3Translator::visit(UnaryOperation const& _unaryOperation)
{
- if (toFormalType(*_unaryOperation.annotation().type).empty())
- error(_unaryOperation, "Type not supported in unary operation.");
+ try
+ {
+ toFormalType(*_unaryOperation.annotation().type);
+ }
+ catch (NoFormalType &err)
+ {
+ string const* typeNamePtr = boost::get_error_info<errinfo_noFormalTypeFrom>(err);
+ error(_unaryOperation, "Type \"" + (typeNamePtr ? *typeNamePtr : "") + "\" supported in unary operation.");
+ }
switch (_unaryOperation.getOperator())
{
@@ -798,5 +865,14 @@ module UInt256
type t = uint256,
constant max = max_uint256
end
+
+module Address
+ use import mach.int.Unsigned
+ type address
+ constant max_address: int = 0xffffffffffffffffffffffffffffffffffffffff (* 160 bit = 40 f's *)
+ clone export mach.int.Unsigned with
+ type t = address,
+ constant max = max_address
+end
)", 0});
}
diff --git a/libsolidity/formal/Why3Translator.h b/libsolidity/formal/Why3Translator.h
index 1b80ed61..22bfff89 100644
--- a/libsolidity/formal/Why3Translator.h
+++ b/libsolidity/formal/Why3Translator.h
@@ -60,9 +60,10 @@ private:
/// Appends imports and constants use throughout the formal code.
void appendPreface();
- /// @returns a string representation of the corresponding formal type or the empty string
- /// if the type is not supported.
+ /// @returns a string representation of the corresponding formal type or throws NoFormalType exception.
std::string toFormalType(Type const& _type) const;
+ using errinfo_noFormalTypeFrom = boost::error_info<struct tag_noFormalTypeFrom, std::string /* name of the type that cannot be translated */ >;
+ struct NoFormalType: virtual Exception {};
void indent() { newLine(); m_lines.back().indentation++; }
void unindent();
diff --git a/scripts/build_emscripten.sh b/scripts/build_emscripten.sh
index da2c7df3..fe7ea11d 100755
--- a/scripts/build_emscripten.sh
+++ b/scripts/build_emscripten.sh
@@ -29,7 +29,7 @@
set -e
if [[ "$OSTYPE" != "darwin"* ]]; then
- date -u +"nightly.%Y.%m.%d" > prerelease.txt
+ date -u +"nightly.%Y.%-m.%-d" > prerelease.txt
./scripts/travis-emscripten/install_deps.sh
docker run -v $(pwd):/src trzeci/emscripten:sdk-tag-1.35.4-64bit ./scripts/travis-emscripten/build_emscripten.sh
fi
diff --git a/scripts/install_deps.sh b/scripts/install_deps.sh
index 7c8523a8..334c62d4 100755
--- a/scripts/install_deps.sh
+++ b/scripts/install_deps.sh
@@ -56,6 +56,8 @@ detect_linux_distro() {
elif [ -f /etc/os-release ]; then
# extract 'foo' from NAME=foo, only on the line with NAME=foo
DISTRO=$(sed -n -e 's/^NAME="\(.*\)\"/\1/p' /etc/os-release)
+ elif [ -f /etc/centos-release ]; then
+ DISTRO=CentOS
else
DISTRO=''
fi
@@ -329,6 +331,51 @@ case $(uname -s) in
sudo apt-get -y install eth
;;
+
+#------------------------------------------------------------------------------
+# CentOS
+# CentOS needs some more testing. This is the general idea of packages
+# needed, but some tweaking/improvements can definitely happen
+#------------------------------------------------------------------------------
+ CentOS)
+ read -p "This script will heavily modify your system in order to allow for compilation of Solidity. Are you sure? [Y/N]" -n 1 -r
+ if [[ $REPLY =~ ^[Yy]$ ]]; then
+ # Make Sure we have the EPEL repos
+ sudo yum -y install epel-release
+ # Get g++ 4.8
+ sudo rpm --import http://ftp.scientificlinux.org/linux/scientific/5x/x86_64/RPM-GPG-KEYs/RPM-GPG-KEY-cern
+ wget -O /etc/yum.repos.d/slc6-devtoolset.repo http://linuxsoft.cern.ch/cern/devtoolset/slc6-devtoolset.repo
+ sudo yum -y install devtoolset-2-gcc devtoolset-2-gcc-c++ devtoolset-2-binutils
+
+ # Enable the devtoolset2 usage so global gcc/g++ become the 4.8 one.
+ # As per https://gist.github.com/stephenturner/e3bc5cfacc2dc67eca8b, what you should do afterwards is
+ # to add this line:
+ # source /opt/rh/devtoolset-2/enable
+ # to your bashrc so that this happens automatically at login
+ scl enable devtoolset-2 bash
+
+ # Get cmake
+ sudo yum -y remove cmake
+ sudo yum -y install cmake3
+ sudo ln -s /usr/bin/cmake3 /usr/bin/cmake
+
+ # Get latest boost thanks to this guy: http://vicendominguez.blogspot.de/2014/04/boost-c-library-rpm-packages-for-centos.html
+ sudo yum -y remove boost-devel
+ sudo wget http://repo.enetres.net/enetres.repo -O /etc/yum.repos.d/enetres.repo
+ sudo yum install boost-devel
+
+ # And finally jsoncpp
+ sudo yum -y install jsoncpp-devel
+ else
+ echo "Aborted CentOS Solidity Dependency Installation";
+ exit 1
+ fi
+
+ ;;
+
+
+
+
*)
#------------------------------------------------------------------------------
diff --git a/scripts/release_ppa.sh b/scripts/release_ppa.sh
index 8e9dc282..6a30faf5 100755
--- a/scripts/release_ppa.sh
+++ b/scripts/release_ppa.sh
@@ -52,9 +52,9 @@ mv solidity solc
# Determine version
cd solc
version=`grep -oP "PROJECT_VERSION \"?\K[0-9.]+(?=\")"? CMakeLists.txt`
-commithash=`git rev-parse --short HEAD`
+commithash=`git rev-parse --short=8 HEAD`
committimestamp=`git show --format=%ci HEAD | head -n 1`
-commitdate=`git show --format=%ci HEAD | head -n 1 | cut - -b1-10`
+commitdate=`git show --format=%ci HEAD | head -n 1 | cut - -b1-10 | sed -e 's/-0?/./' | sed -e 's/-0?/./'`
echo "$commithash" > commit_hash.txt
if [ $branch = develop ]
diff --git a/scripts/travis-emscripten/publish_binary.sh b/scripts/travis-emscripten/publish_binary.sh
index e89e3ce3..d372995c 100755
--- a/scripts/travis-emscripten/publish_binary.sh
+++ b/scripts/travis-emscripten/publish_binary.sh
@@ -33,8 +33,11 @@ set -e
VER=$(cat CMakeLists.txt | grep 'set(PROJECT_VERSION' | sed -e 's/.*set(PROJECT_VERSION "\(.*\)".*/\1/')
test -n "$VER"
VER="v$VER"
-COMMIT=$(git rev-parse --short HEAD)
-DATE=$(date --date="$(git log -1 --date=iso --format=%ad HEAD)" --utc +%Y.%m.%d)
+COMMIT=$(git rev-parse --short=8 HEAD)
+DATE=$(date --date="$(git log -1 --date=iso --format=%ad HEAD)" --utc +%Y.%-m.%-d)
+
+# remove leading zeros in components - they are not semver-compatible
+COMMIT=$(echo "$COMMIT" | sed -e 's/^0*//')
ENCRYPTED_KEY_VAR="encrypted_${ENCRYPTION_LABEL}_key"
ENCRYPTED_IV_VAR="encrypted_${ENCRYPTION_LABEL}_iv"
diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp
index 7ee5700c..23bd2abc 100644
--- a/test/libsolidity/SolidityEndToEndTest.cpp
+++ b/test/libsolidity/SolidityEndToEndTest.cpp
@@ -7144,6 +7144,23 @@ BOOST_AUTO_TEST_CASE(payable_function)
BOOST_CHECK_EQUAL(balanceAt(m_contractAddress), 27 + 27);
}
+BOOST_AUTO_TEST_CASE(payable_function_calls_library)
+{
+ char const* sourceCode = R"(
+ library L {
+ function f() returns (uint) { return 7; }
+ }
+ contract C {
+ function f() payable returns (uint) {
+ return L.f();
+ }
+ }
+ )";
+ compileAndRun(sourceCode, 0, "L");
+ compileAndRun(sourceCode, 0, "C", bytes(), map<string, Address>{{"L", m_contractAddress}});
+ BOOST_CHECK(callContractFunctionWithValue("f()", 27) == encodeArgs(u256(7)));
+}
+
BOOST_AUTO_TEST_CASE(non_payable_throw)
{
char const* sourceCode = R"(
@@ -7186,6 +7203,33 @@ BOOST_AUTO_TEST_CASE(no_nonpayable_circumvention_by_modifier)
BOOST_CHECK_EQUAL(balanceAt(m_contractAddress), 0);
}
+BOOST_AUTO_TEST_CASE(mem_resize_is_not_paid_at_call)
+{
+ // This tests that memory resize for return values is not paid during the call, which would
+ // make the gas calculation overly complex. We access the end of the output area before
+ // the call is made.
+ // Tests that this also survives the optimizer.
+ char const* sourceCode = R"(
+ contract C {
+ function f() returns (uint[200]) {}
+ }
+ contract D {
+ function f(C c) returns (uint) { c.f(); return 7; }
+ }
+ )";
+
+ compileAndRun(sourceCode, 0, "C");
+ u160 cAddr = m_contractAddress;
+ compileAndRun(sourceCode, 0, "D");
+ BOOST_CHECK(callContractFunction("f(address)", cAddr) == encodeArgs(u256(7)));
+
+ m_optimize = true;
+
+ compileAndRun(sourceCode, 0, "C");
+ u160 cAddrOpt = m_contractAddress;
+ compileAndRun(sourceCode, 0, "D");
+ BOOST_CHECK(callContractFunction("f(address)", cAddrOpt) == encodeArgs(u256(7)));
+}
BOOST_AUTO_TEST_SUITE_END()
diff --git a/test/libsolidity/SolidityNameAndTypeResolution.cpp b/test/libsolidity/SolidityNameAndTypeResolution.cpp
index 58736025..b8c64336 100644
--- a/test/libsolidity/SolidityNameAndTypeResolution.cpp
+++ b/test/libsolidity/SolidityNameAndTypeResolution.cpp
@@ -4009,6 +4009,16 @@ BOOST_AUTO_TEST_CASE(external_constructor)
BOOST_CHECK(expectError(text, false) == Error::Type::TypeError);
}
+BOOST_AUTO_TEST_CASE(invalid_array_as_statement)
+{
+ char const* text = R"(
+ contract test {
+ struct S { uint x; }
+ function test(uint k) { S[k]; }
+ }
+ )";
+ BOOST_CHECK(expectError(text, false) == Error::Type::TypeError);
+}
BOOST_AUTO_TEST_SUITE_END()