mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge pull request #7554 from ethereum/develop
Merge develop into develop_060
This commit is contained in:
commit
7e01696030
@ -423,7 +423,7 @@ jobs:
|
|||||||
|
|
||||||
b_osx:
|
b_osx:
|
||||||
macos:
|
macos:
|
||||||
xcode: "10.0.0"
|
xcode: "11.0.0"
|
||||||
environment:
|
environment:
|
||||||
TERM: xterm
|
TERM: xterm
|
||||||
CMAKE_BUILD_TYPE: Debug
|
CMAKE_BUILD_TYPE: Debug
|
||||||
@ -445,7 +445,7 @@ jobs:
|
|||||||
|
|
||||||
t_osx_cli:
|
t_osx_cli:
|
||||||
macos:
|
macos:
|
||||||
xcode: "10.0.0"
|
xcode: "11.0.0"
|
||||||
environment:
|
environment:
|
||||||
TERM: xterm
|
TERM: xterm
|
||||||
steps:
|
steps:
|
||||||
|
@ -57,7 +57,7 @@ RUN git clone --recursive -b boost-1.69.0 https://github.com/boostorg/boost.git
|
|||||||
./bootstrap.sh --with-toolset=clang --prefix=/usr; \
|
./bootstrap.sh --with-toolset=clang --prefix=/usr; \
|
||||||
./b2 toolset=clang headers; \
|
./b2 toolset=clang headers; \
|
||||||
./b2 toolset=clang variant=release \
|
./b2 toolset=clang variant=release \
|
||||||
system regex filesystem unit_test_framework program_options \
|
system filesystem unit_test_framework program_options \
|
||||||
install -j $(($(nproc)/2)); \
|
install -j $(($(nproc)/2)); \
|
||||||
rm -rf /usr/src/boost
|
rm -rf /usr/src/boost
|
||||||
|
|
||||||
|
@ -34,7 +34,7 @@ RUN set -ex; \
|
|||||||
build-essential \
|
build-essential \
|
||||||
software-properties-common \
|
software-properties-common \
|
||||||
cmake ninja-build clang++-8 \
|
cmake ninja-build clang++-8 \
|
||||||
libboost-regex-dev libboost-filesystem-dev libboost-test-dev libboost-system-dev \
|
libboost-filesystem-dev libboost-test-dev libboost-system-dev \
|
||||||
libboost-program-options-dev \
|
libboost-program-options-dev \
|
||||||
libjsoncpp-dev \
|
libjsoncpp-dev \
|
||||||
llvm-8-dev libz3-static-dev \
|
llvm-8-dev libz3-static-dev \
|
||||||
|
@ -34,7 +34,7 @@ RUN set -ex; \
|
|||||||
build-essential \
|
build-essential \
|
||||||
software-properties-common \
|
software-properties-common \
|
||||||
cmake ninja-build clang++-8 libc++-8-dev libc++abi-8-dev \
|
cmake ninja-build clang++-8 libc++-8-dev libc++abi-8-dev \
|
||||||
libboost-regex-dev libboost-filesystem-dev libboost-test-dev libboost-system-dev \
|
libboost-filesystem-dev libboost-test-dev libboost-system-dev \
|
||||||
libboost-program-options-dev \
|
libboost-program-options-dev \
|
||||||
libjsoncpp-dev \
|
libjsoncpp-dev \
|
||||||
llvm-8-dev libcvc4-dev libz3-static-dev libleveldb1d \
|
llvm-8-dev libcvc4-dev libz3-static-dev libleveldb1d \
|
||||||
|
@ -23,6 +23,7 @@ Language Features:
|
|||||||
|
|
||||||
|
|
||||||
Compiler Features:
|
Compiler Features:
|
||||||
|
* Code Generator: Use SELFBALANCE for ``address(this).balance`` if using Istanbul EVM
|
||||||
|
|
||||||
|
|
||||||
Bugfixes:
|
Bugfixes:
|
||||||
|
@ -133,6 +133,8 @@ elseif (DEFINED MSVC)
|
|||||||
add_compile_options(-D_WIN32_WINNT=0x0600) # declare Windows Vista API requirement
|
add_compile_options(-D_WIN32_WINNT=0x0600) # declare Windows Vista API requirement
|
||||||
add_compile_options(-DNOMINMAX) # undefine windows.h MAX && MIN macros cause it cause conflicts with std::min && std::max functions
|
add_compile_options(-DNOMINMAX) # undefine windows.h MAX && MIN macros cause it cause conflicts with std::min && std::max functions
|
||||||
add_compile_options(/utf-8) # enable utf-8 encoding (solves warning 4819)
|
add_compile_options(/utf-8) # enable utf-8 encoding (solves warning 4819)
|
||||||
|
add_compile_options(-DBOOST_REGEX_NO_LIB) # disable automatic boost::regex library selection
|
||||||
|
add_compile_options(-D_REGEX_MAX_STACK_COUNT=200000L) # increase std::regex recursion depth limit
|
||||||
|
|
||||||
# disable empty object file warning
|
# disable empty object file warning
|
||||||
set(CMAKE_STATIC_LINKER_FLAGS "${CMAKE_STATIC_LINKER_FLAGS} /ignore:4221")
|
set(CMAKE_STATIC_LINKER_FLAGS "${CMAKE_STATIC_LINKER_FLAGS} /ignore:4221")
|
||||||
|
@ -26,7 +26,7 @@ set(ETH_SCRIPTS_DIR ${ETH_CMAKE_DIR}/scripts)
|
|||||||
set(Boost_USE_MULTITHREADED ON)
|
set(Boost_USE_MULTITHREADED ON)
|
||||||
option(Boost_USE_STATIC_LIBS "Link Boost statically" ON)
|
option(Boost_USE_STATIC_LIBS "Link Boost statically" ON)
|
||||||
|
|
||||||
set(BOOST_COMPONENTS "regex;filesystem;unit_test_framework;program_options;system")
|
set(BOOST_COMPONENTS "filesystem;unit_test_framework;program_options;system")
|
||||||
|
|
||||||
find_package(Boost 1.65.0 QUIET REQUIRED COMPONENTS ${BOOST_COMPONENTS})
|
find_package(Boost 1.65.0 QUIET REQUIRED COMPONENTS ${BOOST_COMPONENTS})
|
||||||
|
|
||||||
|
@ -292,7 +292,7 @@ In the grammar, opcodes are represented as pre-defined identifiers.
|
|||||||
| create2(v, p, n, s) | | C | create new contract with code mem[p...(p+n)) at address |
|
| create2(v, p, n, s) | | C | create new contract with code mem[p...(p+n)) at address |
|
||||||
| | | | keccak256(0xff . this . s . keccak256(mem[p...(p+n))) |
|
| | | | keccak256(0xff . this . s . keccak256(mem[p...(p+n))) |
|
||||||
| | | | and send v wei and return the new address, where ``0xff`` is a |
|
| | | | and send v wei and return the new address, where ``0xff`` is a |
|
||||||
| | | | 8 byte value, ``this`` is the current contract's address |
|
| | | | 1 byte value, ``this`` is the current contract's address |
|
||||||
| | | | as a 20 byte value and ``s`` is a big-endian 256-bit value |
|
| | | | as a 20 byte value and ``s`` is a big-endian 256-bit value |
|
||||||
+-------------------------+-----+---+-----------------------------------------------------------------+
|
+-------------------------+-----+---+-----------------------------------------------------------------+
|
||||||
| call(g, a, v, in, | | F | call contract at address a with input mem[in...(in+insize)) |
|
| call(g, a, v, in, | | F | call contract at address a with input mem[in...(in+insize)) |
|
||||||
|
@ -34,7 +34,7 @@ set(sources
|
|||||||
)
|
)
|
||||||
|
|
||||||
add_library(devcore ${sources})
|
add_library(devcore ${sources})
|
||||||
target_link_libraries(devcore PUBLIC jsoncpp Boost::boost Boost::filesystem Boost::regex Boost::system)
|
target_link_libraries(devcore PUBLIC jsoncpp Boost::boost Boost::filesystem Boost::system)
|
||||||
target_include_directories(devcore PUBLIC "${CMAKE_SOURCE_DIR}")
|
target_include_directories(devcore PUBLIC "${CMAKE_SOURCE_DIR}")
|
||||||
add_dependencies(devcore solidity_BuildInfo.h)
|
add_dependencies(devcore solidity_BuildInfo.h)
|
||||||
|
|
||||||
|
@ -25,7 +25,7 @@
|
|||||||
|
|
||||||
#include <libdevcore/Assertions.h>
|
#include <libdevcore/Assertions.h>
|
||||||
|
|
||||||
#include <boost/regex.hpp>
|
#include <regex>
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace dev;
|
using namespace dev;
|
||||||
@ -72,9 +72,9 @@ string Whiskers::render() const
|
|||||||
|
|
||||||
void Whiskers::checkParameterValid(string const& _parameter) const
|
void Whiskers::checkParameterValid(string const& _parameter) const
|
||||||
{
|
{
|
||||||
static boost::regex validParam("^" + paramRegex() + "$");
|
static regex validParam("^" + paramRegex() + "$");
|
||||||
assertThrow(
|
assertThrow(
|
||||||
boost::regex_match(_parameter, validParam),
|
regex_match(_parameter, validParam),
|
||||||
WhiskersError,
|
WhiskersError,
|
||||||
"Parameter" + _parameter + " contains invalid characters."
|
"Parameter" + _parameter + " contains invalid characters."
|
||||||
);
|
);
|
||||||
@ -99,6 +99,32 @@ void Whiskers::checkParameterUnknown(string const& _parameter) const
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
template<class ReplaceCallback>
|
||||||
|
string regex_replace(
|
||||||
|
string const& _source,
|
||||||
|
regex const& _pattern,
|
||||||
|
ReplaceCallback _replace,
|
||||||
|
regex_constants::match_flag_type _flags = regex_constants::match_default
|
||||||
|
)
|
||||||
|
{
|
||||||
|
sregex_iterator curMatch(_source.begin(), _source.end(), _pattern, _flags);
|
||||||
|
sregex_iterator matchEnd;
|
||||||
|
string::const_iterator lastMatchedPos(_source.cbegin());
|
||||||
|
string result;
|
||||||
|
while (curMatch != matchEnd)
|
||||||
|
{
|
||||||
|
result.append(curMatch->prefix().first, curMatch->prefix().second);
|
||||||
|
result.append(_replace(*curMatch));
|
||||||
|
lastMatchedPos = (*curMatch)[0].second;
|
||||||
|
++curMatch;
|
||||||
|
}
|
||||||
|
result.append(lastMatchedPos, _source.cend());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
string Whiskers::replace(
|
string Whiskers::replace(
|
||||||
string const& _template,
|
string const& _template,
|
||||||
StringMap const& _parameters,
|
StringMap const& _parameters,
|
||||||
@ -106,8 +132,7 @@ string Whiskers::replace(
|
|||||||
map<string, vector<StringMap>> const& _listParameters
|
map<string, vector<StringMap>> const& _listParameters
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
using namespace boost;
|
static regex listOrTag("<(" + paramRegex() + ")>|<#(" + paramRegex() + ")>((?:.|\\r|\\n)*?)</\\2>|<\\?(" + paramRegex() + ")>((?:.|\\r|\\n)*?)(<!\\4>((?:.|\\r|\\n)*?))?</\\4>");
|
||||||
static regex listOrTag("<(" + paramRegex() + ")>|<#(" + paramRegex() + ")>(.*?)</\\2>|<\\?(" + paramRegex() + ")>(.*?)(<!\\4>(.*?))?</\\4>");
|
|
||||||
return regex_replace(_template, listOrTag, [&](match_results<string::const_iterator> _match) -> string
|
return regex_replace(_template, listOrTag, [&](match_results<string::const_iterator> _match) -> string
|
||||||
{
|
{
|
||||||
string tagName(_match[1]);
|
string tagName(_match[1]);
|
||||||
|
@ -1271,6 +1271,28 @@ bool ExpressionCompiler::visit(MemberAccess const& _memberAccess)
|
|||||||
utils().leftShiftNumberOnStack(224);
|
utils().leftShiftNumberOnStack(224);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
// Another special case for `address(this).balance`. Post-Istanbul, we can use the selfbalance
|
||||||
|
// opcode.
|
||||||
|
if (
|
||||||
|
m_context.evmVersion().hasSelfBalance() &&
|
||||||
|
member == "balance" &&
|
||||||
|
_memberAccess.expression().annotation().type->category() == Type::Category::Address
|
||||||
|
)
|
||||||
|
if (FunctionCall const* funCall = dynamic_cast<FunctionCall const*>(&_memberAccess.expression()))
|
||||||
|
if (auto const* addr = dynamic_cast<ElementaryTypeNameExpression const*>(&funCall->expression()))
|
||||||
|
if (
|
||||||
|
addr->typeName().token() == Token::Address &&
|
||||||
|
funCall->arguments().size() == 1
|
||||||
|
)
|
||||||
|
if (auto arg = dynamic_cast<Identifier const*>( funCall->arguments().front().get()))
|
||||||
|
if (
|
||||||
|
arg->name() == "this" &&
|
||||||
|
dynamic_cast<MagicVariableDeclaration const*>(arg->annotation().referencedDeclaration)
|
||||||
|
)
|
||||||
|
{
|
||||||
|
m_context << Instruction::SELFBALANCE;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
_memberAccess.expression().accept(*this);
|
_memberAccess.expression().accept(*this);
|
||||||
switch (_memberAccess.expression().annotation().type->category())
|
switch (_memberAccess.expression().annotation().type->category())
|
||||||
|
@ -45,6 +45,7 @@
|
|||||||
#include <libyul/optimiser/SSATransform.h>
|
#include <libyul/optimiser/SSATransform.h>
|
||||||
#include <libyul/optimiser/StackCompressor.h>
|
#include <libyul/optimiser/StackCompressor.h>
|
||||||
#include <libyul/optimiser/StructuralSimplifier.h>
|
#include <libyul/optimiser/StructuralSimplifier.h>
|
||||||
|
#include <libyul/optimiser/SyntacticalEquality.h>
|
||||||
#include <libyul/optimiser/RedundantAssignEliminator.h>
|
#include <libyul/optimiser/RedundantAssignEliminator.h>
|
||||||
#include <libyul/optimiser/VarNameCleaner.h>
|
#include <libyul/optimiser/VarNameCleaner.h>
|
||||||
#include <libyul/optimiser/LoadResolver.h>
|
#include <libyul/optimiser/LoadResolver.h>
|
||||||
@ -343,10 +344,25 @@ map<string, unique_ptr<OptimiserStep>> const& OptimiserSuite::allSteps()
|
|||||||
|
|
||||||
void OptimiserSuite::runSequence(std::vector<string> const& _steps, Block& _ast)
|
void OptimiserSuite::runSequence(std::vector<string> const& _steps, Block& _ast)
|
||||||
{
|
{
|
||||||
|
unique_ptr<Block> copy;
|
||||||
|
if (m_debug == Debug::PrintChanges)
|
||||||
|
copy = make_unique<Block>(boost::get<Block>(ASTCopier{}(_ast)));
|
||||||
for (string const& step: _steps)
|
for (string const& step: _steps)
|
||||||
{
|
{
|
||||||
if (m_debug == Debug::PrintStep)
|
if (m_debug == Debug::PrintStep)
|
||||||
cout << "Running " << step << endl;
|
cout << "Running " << step << endl;
|
||||||
allSteps().at(step)->run(m_context, _ast);
|
allSteps().at(step)->run(m_context, _ast);
|
||||||
|
if (m_debug == Debug::PrintChanges)
|
||||||
|
{
|
||||||
|
// TODO should add switch to also compare variable names!
|
||||||
|
if (SyntacticallyEqual{}.statementEqual(_ast, *copy))
|
||||||
|
cout << "== Running " << step << " did not cause changes." << endl;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cout << "== Running " << step << " changed the AST." << endl;
|
||||||
|
cout << AsmPrinter{}(_ast) << endl;
|
||||||
|
copy = make_unique<Block>(boost::get<Block>(ASTCopier{}(_ast)));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -48,7 +48,8 @@ public:
|
|||||||
enum class Debug
|
enum class Debug
|
||||||
{
|
{
|
||||||
None,
|
None,
|
||||||
PrintStep
|
PrintStep,
|
||||||
|
PrintChanges
|
||||||
};
|
};
|
||||||
static void run(
|
static void run(
|
||||||
Dialect const& _dialect,
|
Dialect const& _dialect,
|
||||||
|
@ -67,7 +67,7 @@ echo -en 'travis_fold:start:compiling_boost\\r'
|
|||||||
test -e "$WORKSPACE"/boost_1_70_0_install/include/boost/version.hpp || (
|
test -e "$WORKSPACE"/boost_1_70_0_install/include/boost/version.hpp || (
|
||||||
cd "$WORKSPACE"/boost_1_70_0
|
cd "$WORKSPACE"/boost_1_70_0
|
||||||
./b2 toolset=emscripten link=static variant=release threading=single runtime-link=static \
|
./b2 toolset=emscripten link=static variant=release threading=single runtime-link=static \
|
||||||
--with-system --with-regex --with-filesystem --with-test --with-program_options cxxflags="-Wno-unused-local-typedef -Wno-variadic-macros -Wno-c99-extensions -Wno-all" \
|
--with-system --with-filesystem --with-test --with-program_options cxxflags="-Wno-unused-local-typedef -Wno-variadic-macros -Wno-c99-extensions -Wno-all" \
|
||||||
--prefix="$WORKSPACE"/boost_1_70_0_install install
|
--prefix="$WORKSPACE"/boost_1_70_0_install install
|
||||||
)
|
)
|
||||||
ln -sf "$WORKSPACE"/boost_1_70_0_install/lib/* /emsdk_portable/sdk/system/lib
|
ln -sf "$WORKSPACE"/boost_1_70_0_install/lib/* /emsdk_portable/sdk/system/lib
|
||||||
|
@ -617,6 +617,25 @@ BOOST_AUTO_TEST_CASE(gas_left)
|
|||||||
BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end());
|
BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(selfbalance)
|
||||||
|
{
|
||||||
|
char const* sourceCode = R"(
|
||||||
|
contract test {
|
||||||
|
function f() returns (uint) {
|
||||||
|
return address(this).balance;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)";
|
||||||
|
|
||||||
|
bytes code = compileFirstExpression(sourceCode, {}, {});
|
||||||
|
|
||||||
|
if (dev::test::Options::get().evmVersion() == EVMVersion::istanbul())
|
||||||
|
{
|
||||||
|
bytes expectation({uint8_t(Instruction::SELFBALANCE)});
|
||||||
|
BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_SUITE_END()
|
BOOST_AUTO_TEST_SUITE_END()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -263,7 +263,7 @@ string BytesUtils::formatBytes(
|
|||||||
os << formatHexString(_bytes);
|
os << formatHexString(_bytes);
|
||||||
break;
|
break;
|
||||||
case ABIType::String:
|
case ABIType::String:
|
||||||
os << formatString(_bytes);
|
os << formatString(_bytes, _bytes.size() - countRightPaddedZeros(_bytes));
|
||||||
break;
|
break;
|
||||||
case ABIType::Failure:
|
case ABIType::Failure:
|
||||||
break;
|
break;
|
||||||
@ -311,3 +311,12 @@ string BytesUtils::formatBytesRange(
|
|||||||
return os.str();
|
return os.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t BytesUtils::countRightPaddedZeros(bytes const& _bytes)
|
||||||
|
{
|
||||||
|
return find_if(
|
||||||
|
_bytes.rbegin(),
|
||||||
|
_bytes.rend(),
|
||||||
|
[](uint8_t b) { return b != '\0'; }
|
||||||
|
) - _bytes.rbegin();
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -122,6 +122,10 @@ public:
|
|||||||
ParameterList const& _parameters,
|
ParameterList const& _parameters,
|
||||||
bool _highlight
|
bool _highlight
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/// Count the number of zeros between the last non-zero byte and the end of
|
||||||
|
/// \param _bytes.
|
||||||
|
static size_t countRightPaddedZeros(bytes const& _bytes);
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -50,7 +50,7 @@ public:
|
|||||||
TestFunctionCall(FunctionCall _call): m_call(std::move(_call)) {}
|
TestFunctionCall(FunctionCall _call): m_call(std::move(_call)) {}
|
||||||
|
|
||||||
/// Formats this function call test and applies the format that was detected during parsing.
|
/// Formats this function call test and applies the format that was detected during parsing.
|
||||||
/// If _renderResult is false, the expected result of the call will is used, if it's false
|
/// If _renderResult is false, the expected result of the call will be used, if it's true
|
||||||
/// the actual result is used.
|
/// the actual result is used.
|
||||||
/// If _highlight is false, it's formatted without colorized highlighting. If it's true, AnsiColorized is
|
/// If _highlight is false, it's formatted without colorized highlighting. If it's true, AnsiColorized is
|
||||||
/// used to apply a colorized highlighting.
|
/// used to apply a colorized highlighting.
|
||||||
|
Loading…
Reference in New Issue
Block a user