Merge remote-tracking branch 'origin/develop' into merge_develop_060

This commit is contained in:
Leonardo Alt
2019-11-20 12:27:40 +01:00
104 changed files with 621 additions and 653 deletions
+3 -3
View File
@@ -32,13 +32,13 @@ namespace test
#ifdef _WIN32
static constexpr auto evmoneFilename = "evmone.dll";
static constexpr auto evmoneDownloadLink = "https://github.com/ethereum/evmone/releases/download/v0.1.0/evmone-0.1.0-windows-amd64.zip";
static constexpr auto evmoneDownloadLink = "https://github.com/ethereum/evmone/releases/download/v0.3.0/evmone-0.3.0-windows-amd64.zip";
#elif defined(__APPLE__)
static constexpr auto evmoneFilename = "libevmone.dylib";
static constexpr auto evmoneDownloadLink = "https://github.com/ethereum/evmone/releases/download/v0.1.0/evmone-0.1.0-darwin-x86_64.tar.gz";
static constexpr auto evmoneDownloadLink = "https://github.com/ethereum/evmone/releases/download/v0.3.0/evmone-0.3.0-darwin-x86_64.tar.gz";
#else
static constexpr auto evmoneFilename = "libevmone.so";
static constexpr auto evmoneDownloadLink = "https://github.com/ethereum/evmone/releases/download/v0.1.0/evmone-0.1.0-linux-x86_64.tar.gz";
static constexpr auto evmoneDownloadLink = "https://github.com/ethereum/evmone/releases/download/v0.3.0/evmone-0.3.0-linux-x86_64.tar.gz";
#endif
+11 -10
View File
@@ -64,7 +64,8 @@ evmc::VM* EVMHost::getVM(string const& _path)
}
EVMHost::EVMHost(langutil::EVMVersion _evmVersion, evmc::VM* _vm):
m_vm(_vm)
m_vm(_vm),
m_evmVersion(_evmVersion)
{
if (!m_vm)
{
@@ -73,21 +74,21 @@ EVMHost::EVMHost(langutil::EVMVersion _evmVersion, evmc::VM* _vm):
}
if (_evmVersion == langutil::EVMVersion::homestead())
m_evmVersion = EVMC_HOMESTEAD;
m_evmRevision = EVMC_HOMESTEAD;
else if (_evmVersion == langutil::EVMVersion::tangerineWhistle())
m_evmVersion = EVMC_TANGERINE_WHISTLE;
m_evmRevision = EVMC_TANGERINE_WHISTLE;
else if (_evmVersion == langutil::EVMVersion::spuriousDragon())
m_evmVersion = EVMC_SPURIOUS_DRAGON;
m_evmRevision = EVMC_SPURIOUS_DRAGON;
else if (_evmVersion == langutil::EVMVersion::byzantium())
m_evmVersion = EVMC_BYZANTIUM;
m_evmRevision = EVMC_BYZANTIUM;
else if (_evmVersion == langutil::EVMVersion::constantinople())
m_evmVersion = EVMC_CONSTANTINOPLE;
m_evmRevision = EVMC_CONSTANTINOPLE;
else if (_evmVersion == langutil::EVMVersion::istanbul())
m_evmVersion = EVMC_ISTANBUL;
m_evmRevision = EVMC_ISTANBUL;
else if (_evmVersion == langutil::EVMVersion::berlin())
assertThrow(false, Exception, "Berlin is not supported yet.");
else //if (_evmVersion == langutil::EVMVersion::petersburg())
m_evmVersion = EVMC_PETERSBURG;
m_evmRevision = EVMC_PETERSBURG;
}
evmc_storage_status EVMHost::set_storage(const evmc::address& _addr, const evmc::bytes32& _key, const evmc::bytes32& _value) noexcept
@@ -146,7 +147,7 @@ evmc::result EVMHost::call(evmc_message const& _message) noexcept
{
message.gas -= message.kind == EVMC_CREATE ? eth::GasCosts::txCreateGas : eth::GasCosts::txGas;
for (size_t i = 0; i < message.input_size; ++i)
message.gas -= message.input_data[i] == 0 ? eth::GasCosts::txDataZeroGas : eth::GasCosts::txDataNonZeroGas;
message.gas -= message.input_data[i] == 0 ? eth::GasCosts::txDataZeroGas : eth::GasCosts::txDataNonZeroGas(m_evmVersion);
if (message.gas < 0)
{
evmc::result result({});
@@ -191,7 +192,7 @@ evmc::result EVMHost::call(evmc_message const& _message) noexcept
evmc::address currentAddress = m_currentAddress;
m_currentAddress = message.destination;
evmc::result result = m_vm->execute(*this, m_evmVersion, message, code.data(), code.size());
evmc::result result = m_vm->execute(*this, m_evmRevision, message, code.data(), code.size());
m_currentAddress = currentAddress;
if (message.kind == EVMC_CREATE)
+4 -1
View File
@@ -180,7 +180,10 @@ private:
static evmc::result resultWithGas(evmc_message const& _message, bytes const& _data) noexcept;
evmc::VM* m_vm = nullptr;
evmc_revision m_evmVersion;
// EVM version requested by the testing tool
langutil::EVMVersion m_evmVersion;
// EVM version requested from EVMC (matches the above)
evmc_revision m_evmRevision;
};
-1
View File
@@ -16,7 +16,6 @@ target_sources(evmc INTERFACE
${PROJECT_SOURCE_DIR}/test/evmc/evmc.h
${PROJECT_SOURCE_DIR}/test/evmc/evmc.hpp
${PROJECT_SOURCE_DIR}/test/evmc/helpers.h
${PROJECT_SOURCE_DIR}/test/evmc/helpers.hpp
${PROJECT_SOURCE_DIR}/test/evmc/utils.h
)
target_include_directories(evmc INTERFACE ${PROJECT_SOURCE_DIR}/test/)
+3
View File
@@ -0,0 +1,3 @@
# EVMC
This is an import of [EVMC](https://github.com/ethereum/evmc) version [7.0.0](https://github.com/ethereum/evmc/releases/tag/v7.0.0).
+116 -120
View File
@@ -334,118 +334,6 @@ public:
}
};
class Host;
/// @copybrief evmc_vm
///
/// This is a RAII wrapper for evmc_vm and objects of this type
/// automatically destroys the VM instance.
class VM
{
public:
VM() noexcept = default;
/// Converting constructor from evmc_vm.
explicit VM(evmc_vm* vm) noexcept : m_instance{vm} {}
/// Destructor responsible for automatically destroying the VM instance.
~VM() noexcept
{
if (m_instance)
m_instance->destroy(m_instance);
}
VM(const VM&) = delete;
VM& operator=(const VM&) = delete;
/// Move constructor.
VM(VM&& other) noexcept : m_instance{other.m_instance} { other.m_instance = nullptr; }
/// Move assignment operator.
VM& operator=(VM&& other) noexcept
{
this->~VM();
m_instance = other.m_instance;
other.m_instance = nullptr;
return *this;
}
/// The constructor that captures a VM instance and configures the instance
/// with the provided list of options.
inline VM(evmc_vm* vm,
std::initializer_list<std::pair<const char*, const char*>> options) noexcept;
/// Checks if contains a valid pointer to the VM instance.
explicit operator bool() const noexcept { return m_instance != nullptr; }
/// Checks whenever the VM instance is ABI compatible with the current EVMC API.
bool is_abi_compatible() const noexcept { return m_instance->abi_version == EVMC_ABI_VERSION; }
/// @copydoc evmc_vm::name
char const* name() const noexcept { return m_instance->name; }
/// @copydoc evmc_vm::version
char const* version() const noexcept { return m_instance->version; }
/// @copydoc evmc::vm::get_capabilities
evmc_capabilities_flagset get_capabilities() const noexcept
{
return m_instance->get_capabilities(m_instance);
}
/// @copydoc evmc_set_option()
evmc_set_option_result set_option(const char name[], const char value[]) noexcept
{
return evmc_set_option(m_instance, name, value);
}
/// @copydoc evmc_execute()
result execute(const evmc_host_interface& host,
evmc_host_context* ctx,
evmc_revision rev,
const evmc_message& msg,
const uint8_t* code,
size_t code_size) noexcept
{
return result{m_instance->execute(m_instance, &host, ctx, rev, &msg, code, code_size)};
}
/// Convenient variant of the VM::execute() that takes reference to evmc::Host class.
inline result execute(Host& host,
evmc_revision rev,
const evmc_message& msg,
const uint8_t* code,
size_t code_size) noexcept;
/// Executes code without the Host context.
///
/// The same as
/// execute(const evmc_host_interface&, evmc_host_context*, evmc_revision,
/// const evmc_message&, const uint8_t*, size_t),
/// but without providing the Host context and interface.
/// This method is for experimental precompiles support where execution is
/// guaranteed not to require any Host access.
result execute(evmc_revision rev,
const evmc_message& msg,
const uint8_t* code,
size_t code_size) noexcept
{
return result{
m_instance->execute(m_instance, nullptr, nullptr, rev, &msg, code, code_size)};
}
private:
evmc_vm* m_instance = nullptr;
};
inline VM::VM(evmc_vm* vm,
std::initializer_list<std::pair<const char*, const char*>> options) noexcept
: m_instance{vm}
{
for (const auto& option : options)
set_option(option.first, option.second);
}
/// The EVMC Host interface
class HostInterface
@@ -514,8 +402,10 @@ public:
HostContext() = default;
/// Constructor from the EVMC Host primitives.
HostContext(const evmc_host_interface* interface, evmc_host_context* ctx) noexcept
: host{interface}, context{ctx}
/// @param interface The reference to the Host interface.
/// @param ctx The pointer to the Host context object. This parameter MAY be null.
HostContext(const evmc_host_interface& interface, evmc_host_context* ctx) noexcept
: host{&interface}, context{ctx}
{}
bool account_exists(const address& address) noexcept final
@@ -596,6 +486,7 @@ public:
}
};
/// Abstract class to be used by Host implementations.
///
/// When implementing EVMC Host, you can directly inherit from the evmc::Host class.
@@ -628,13 +519,118 @@ public:
};
inline result VM::execute(Host& host,
evmc_revision rev,
const evmc_message& msg,
const uint8_t* code,
size_t code_size) noexcept
/// @copybrief evmc_vm
///
/// This is a RAII wrapper for evmc_vm, and object of this type
/// automatically destroys the VM instance.
class VM
{
return execute(Host::get_interface(), host.to_context(), rev, msg, code, code_size);
public:
VM() noexcept = default;
/// Converting constructor from evmc_vm.
explicit VM(evmc_vm* vm) noexcept : m_instance{vm} {}
/// Destructor responsible for automatically destroying the VM instance.
~VM() noexcept
{
if (m_instance)
m_instance->destroy(m_instance);
}
VM(const VM&) = delete;
VM& operator=(const VM&) = delete;
/// Move constructor.
VM(VM&& other) noexcept : m_instance{other.m_instance} { other.m_instance = nullptr; }
/// Move assignment operator.
VM& operator=(VM&& other) noexcept
{
this->~VM();
m_instance = other.m_instance;
other.m_instance = nullptr;
return *this;
}
/// The constructor that captures a VM instance and configures the instance
/// with the provided list of options.
inline VM(evmc_vm* vm,
std::initializer_list<std::pair<const char*, const char*>> options) noexcept;
/// Checks if contains a valid pointer to the VM instance.
explicit operator bool() const noexcept { return m_instance != nullptr; }
/// Checks whenever the VM instance is ABI compatible with the current EVMC API.
bool is_abi_compatible() const noexcept { return m_instance->abi_version == EVMC_ABI_VERSION; }
/// @copydoc evmc_vm::name
char const* name() const noexcept { return m_instance->name; }
/// @copydoc evmc_vm::version
char const* version() const noexcept { return m_instance->version; }
/// @copydoc evmc::vm::get_capabilities
evmc_capabilities_flagset get_capabilities() const noexcept
{
return m_instance->get_capabilities(m_instance);
}
/// @copydoc evmc_set_option()
evmc_set_option_result set_option(const char name[], const char value[]) noexcept
{
return evmc_set_option(m_instance, name, value);
}
/// @copydoc evmc_execute()
result execute(const evmc_host_interface& host,
evmc_host_context* ctx,
evmc_revision rev,
const evmc_message& msg,
const uint8_t* code,
size_t code_size) noexcept
{
return result{m_instance->execute(m_instance, &host, ctx, rev, &msg, code, code_size)};
}
/// Convenient variant of the VM::execute() that takes reference to evmc::Host class.
result execute(Host& host,
evmc_revision rev,
const evmc_message& msg,
const uint8_t* code,
size_t code_size) noexcept
{
return execute(Host::get_interface(), host.to_context(), rev, msg, code, code_size);
}
/// Executes code without the Host context.
///
/// The same as
/// execute(const evmc_host_interface&, evmc_host_context*, evmc_revision,
/// const evmc_message&, const uint8_t*, size_t),
/// but without providing the Host context and interface.
/// This method is for experimental precompiles support where execution is
/// guaranteed not to require any Host access.
result execute(evmc_revision rev,
const evmc_message& msg,
const uint8_t* code,
size_t code_size) noexcept
{
return result{
m_instance->execute(m_instance, nullptr, nullptr, rev, &msg, code, code_size)};
}
private:
evmc_vm* m_instance = nullptr;
};
inline VM::VM(evmc_vm* vm,
std::initializer_list<std::pair<const char*, const char*>> options) noexcept
: m_instance{vm}
{
// This constructor is implemented outside of the class definition to workaround a doxygen bug.
for (const auto& option : options)
set_option(option.first, option.second);
}
-116
View File
@@ -1,116 +0,0 @@
/* EVMC: Ethereum Client-VM Connector API.
* Copyright 2018-2019 The EVMC Authors.
* Licensed under the Apache License, Version 2.0.
*/
/**
* @file
* A collection of helpers (overloaded operators) for using EVMC types effectively in C++.
*
* @addtogroup helpers
* @{
*/
#pragma once
#include <evmc/evmc.hpp>
#include <cstring>
#include <functional>
using evmc::is_zero;
/// The comparator for std::map<evmc_address, ...>.
EVMC_DEPRECATED
inline bool operator<(const evmc_address& a, const evmc_address& b)
{
return std::memcmp(a.bytes, b.bytes, sizeof(a.bytes)) < 0;
}
/// The comparator for std::map<evmc_bytes32, ...>.
EVMC_DEPRECATED
inline bool operator<(const evmc_bytes32& a, const evmc_bytes32& b)
{
return std::memcmp(a.bytes, b.bytes, sizeof(a.bytes)) < 0;
}
/// The comparator for equality.
EVMC_DEPRECATED
inline bool operator==(const evmc_address& a, const evmc_address& b)
{
return std::memcmp(a.bytes, b.bytes, sizeof(a.bytes)) == 0;
}
/// The comparator for equality.
EVMC_DEPRECATED
inline bool operator==(const evmc_bytes32& a, const evmc_bytes32& b)
{
return std::memcmp(a.bytes, b.bytes, sizeof(a.bytes)) == 0;
}
/// Parameters for the fnv1a hash function, specialized by the hash result size (size_t).
///
/// The values for the matching size are taken from
/// https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function#FNV_hash_parameters.
///
/// @tparam size The size of the hash result (size_t).
template <size_t size>
struct fnv1_params
{
};
/// Parameters for the fnv1a hash function, specialized for the hash result of 4 bytes.
template <>
struct fnv1_params<4>
{
static constexpr auto prime = 0x1000193; ///< The FNV prime.
static constexpr auto offset_basis = 0x811c9dc5; ///< The FNV offset basis.
};
/// Parameters for the fnv1a hash function, specialized for the hash result of 8 bytes.
template <>
struct fnv1_params<8>
{
static constexpr auto prime = 0x100000001b3; ///< The FNV prime.
static constexpr auto offset_basis = 0xcbf29ce484222325; ///< The FNV offset basis.
};
/// FNV1a hash function.
inline size_t fnv1a(const uint8_t* ptr, size_t len) noexcept
{
using params = fnv1_params<sizeof(size_t)>;
auto ret = size_t{params::offset_basis};
for (size_t i = 0; i < len; i++)
{
ret ^= ptr[i];
ret *= params::prime;
}
return ret;
}
namespace std
{
/// Hash operator template specialization for evmc_address needed for unordered containers.
template <>
struct EVMC_DEPRECATED hash<evmc_address>
{
/// Hash operator using FNV1a.
size_t operator()(const evmc_address& s) const noexcept
{
return fnv1a(s.bytes, sizeof(s.bytes));
}
};
/// Hash operator template needed for std::unordered_set and others using hashes.
template <>
struct EVMC_DEPRECATED hash<evmc_bytes32>
{
/// Hash operator using FNV1a.
size_t operator()(const evmc_bytes32& s) const noexcept
{
return fnv1a(s.bytes, sizeof(s.bytes));
}
};
} // namespace std
/** @} */
+1 -1
View File
@@ -246,7 +246,7 @@ function truffle_run_test
for optimize in "${optimizer_settings[@]}"
do
clean
force_solc_settings "$CONFIG" "$optimize" "petersburg"
force_solc_settings "$CONFIG" "$optimize" "istanbul"
# Force ABIEncoderV2 in the last step. Has to be the last because code is modified.
if [ "$FORCE_ABIv2" = true ]; then
[[ "$optimize" =~ yul ]] && force_abi_v2
+39 -11
View File
@@ -19,6 +19,7 @@
*/
#include <test/libsolidity/SolidityExecutionFramework.h>
#include <liblangutil/EVMVersion.h>
#include <libdevcore/IpfsHash.h>
#include <libevmasm/GasMeter.h>
@@ -37,7 +38,7 @@ namespace solidity
namespace test
{
#define CHECK_DEPLOY_GAS(_gasNoOpt, _gasOpt) \
#define CHECK_DEPLOY_GAS(_gasNoOpt, _gasOpt, _evmVersion) \
do \
{ \
u256 ipfsCost = GasMeter::dataGas(dev::ipfsHash(m_compiler.metadata(m_compiler.lastContractName())), true); \
@@ -95,34 +96,61 @@ BOOST_AUTO_TEST_CASE(string_storage)
m_compiler.overwriteReleaseFlag(true);
compileAndRun(sourceCode);
if (Options::get().evmVersion() <= EVMVersion::byzantium())
CHECK_DEPLOY_GAS(134145, 130831);
auto evmVersion = dev::test::Options::get().evmVersion();
if (evmVersion <= EVMVersion::byzantium())
CHECK_DEPLOY_GAS(134071, 130763, evmVersion);
// This is only correct on >=Constantinople.
else if (Options::get().useABIEncoderV2)
{
if (Options::get().optimizeYul)
CHECK_DEPLOY_GAS(127785, 127721);
{
// Costs with 0 are cases which cannot be triggered in tests.
if (evmVersion < EVMVersion::istanbul())
CHECK_DEPLOY_GAS(0, 127653, evmVersion);
else
CHECK_DEPLOY_GAS(0, 113821, evmVersion);
}
else
CHECK_DEPLOY_GAS(151587, 135371);
{
if (evmVersion < EVMVersion::istanbul())
CHECK_DEPLOY_GAS(0, 135371, evmVersion);
else
CHECK_DEPLOY_GAS(0, 120083, evmVersion);
}
}
else if (evmVersion < EVMVersion::istanbul())
CHECK_DEPLOY_GAS(126861, 119591, evmVersion);
else
CHECK_DEPLOY_GAS(126929, 119659);
CHECK_DEPLOY_GAS(114173, 107163, evmVersion);
if (Options::get().evmVersion() >= EVMVersion::byzantium())
if (evmVersion >= EVMVersion::byzantium())
{
callContractFunction("f()");
if (Options::get().evmVersion() == EVMVersion::byzantium())
if (evmVersion == EVMVersion::byzantium())
CHECK_GAS(21551, 21526, 20);
// This is only correct on >=Constantinople.
else if (Options::get().useABIEncoderV2)
{
if (Options::get().optimizeYul)
CHECK_GAS(21713, 21567, 20);
{
if (evmVersion < EVMVersion::istanbul())
CHECK_GAS(0, 21567, 20);
else
CHECK_GAS(0, 21351, 20);
}
else
CHECK_GAS(21713, 21635, 20);
{
if (evmVersion < EVMVersion::istanbul())
CHECK_GAS(0, 21635, 20);
else
CHECK_GAS(0, 21431, 20);
}
}
else
else if (evmVersion < EVMVersion::istanbul())
CHECK_GAS(21546, 21526, 20);
else
CHECK_GAS(21332, 21322, 20);
}
}
+2 -1
View File
@@ -114,9 +114,10 @@ public:
static GasMeter::GasConsumption gasForTransaction(bytes const& _data, bool _isCreation)
{
auto evmVersion = dev::test::Options::get().evmVersion();
GasMeter::GasConsumption gas = _isCreation ? GasCosts::txCreateGas : GasCosts::txGas;
for (auto i: _data)
gas += i != 0 ? GasCosts::txDataNonZeroGas : GasCosts::txDataZeroGas;
gas += i != 0 ? GasCosts::txDataNonZeroGas(evmVersion) : GasCosts::txDataZeroGas;
return gas;
}
@@ -0,0 +1,12 @@
contract C {
function f() public returns (uint id) {
assembly {
id := chainid()
}
}
}
// ====
// compileViaYul: also
// EVMVersion: >=istanbul
// ----
// f() -> 1
@@ -0,0 +1,12 @@
contract C {
function f() public payable returns (uint ret) {
assembly {
ret := selfbalance()
}
}
}
// ====
// EVMVersion: >=istanbul
// compileViaYul: also
// ----
// f(), 254 ether -> 254
@@ -0,0 +1,15 @@
contract S
{
int o;
function foo() public returns (int) { return o = 3; }
}
contract B is S
{
function fii() public
{
o = S(super).foo();
}
}
// ----
// TypeError: (129-137): Explicit type conversion not allowed from "contract super B" to "contract S".
+3 -1
View File
@@ -37,6 +37,8 @@
#include <boost/test/unit_test.hpp>
#include <variant>
using namespace std;
using namespace langutil;
using namespace yul;
@@ -75,7 +77,7 @@ pair<shared_ptr<Block>, shared_ptr<yul::AsmAnalysisInfo>> yul::test::parse(strin
yul::Block yul::test::disambiguate(string const& _source, bool _yul)
{
auto result = parse(_source, _yul);
return boost::get<Block>(Disambiguator(defaultDialect(_yul), *result.second, {})(*result.first));
return std::get<Block>(Disambiguator(defaultDialect(_yul), *result.second, {})(*result.first));
}
string yul::test::format(string const& _source, bool _yul)
+2 -1
View File
@@ -74,6 +74,7 @@
#include <boost/algorithm/string.hpp>
#include <fstream>
#include <variant>
using namespace dev;
using namespace langutil;
@@ -415,7 +416,7 @@ bool YulOptimizerTest::parse(ostream& _stream, string const& _linePrefix, bool c
void YulOptimizerTest::disambiguate()
{
*m_ast = boost::get<Block>(Disambiguator(*m_dialect, *m_analysisInfo)(*m_ast));
*m_ast = std::get<Block>(Disambiguator(*m_dialect, *m_analysisInfo)(*m_ast));
m_analysisInfo.reset();
updateContext();
}
+2 -1
View File
@@ -34,7 +34,8 @@ static vector<string> s_evmVersions = {
"spuriousDragon",
"byzantium",
"constantinople",
"petersburg"
"petersburg",
"istanbul"
};
void FuzzerUtil::runCompiler(string const& _input, bool _quiet)
+3 -2
View File
@@ -35,6 +35,7 @@
#include <boost/algorithm/cxx11/all_of.hpp>
#include <ostream>
#include <variant>
using namespace std;
using namespace dev;
@@ -174,9 +175,9 @@ void Interpreter::operator()(Block const& _block)
openScope();
// Register functions.
for (auto const& statement: _block.statements)
if (statement.type() == typeid(FunctionDefinition))
if (holds_alternative<FunctionDefinition>(statement))
{
FunctionDefinition const& funDef = boost::get<FunctionDefinition>(statement);
FunctionDefinition const& funDef = std::get<FunctionDefinition>(statement);
solAssert(!m_scopes.back().count(funDef.name), "");
m_scopes.back().emplace(funDef.name, &funDef);
}
+2 -1
View File
@@ -72,6 +72,7 @@
#include <string>
#include <sstream>
#include <iostream>
#include <variant>
using namespace std;
using namespace dev;
@@ -130,7 +131,7 @@ public:
set<YulString> reservedIdentifiers;
if (!disambiguated)
{
*m_ast = boost::get<yul::Block>(Disambiguator(m_dialect, *m_analysisInfo)(*m_ast));
*m_ast = std::get<yul::Block>(Disambiguator(m_dialect, *m_analysisInfo)(*m_ast));
m_analysisInfo.reset();
m_nameDispenser = make_shared<NameDispenser>(m_dialect, *m_ast, reservedIdentifiers);
disambiguated = true;