mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Add and use mapTuple helper.
This commit is contained in:
parent
91cdb606a5
commit
f34d7120a2
@ -265,6 +265,39 @@ decltype(auto) valueOrDefault(MapType&& _map, KeyType const& _key, ValueType&& _
|
|||||||
return (it == _map.end()) ? _defaultValue : it->second;
|
return (it == _map.end()) ? _defaultValue : it->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
template<typename Callable>
|
||||||
|
struct MapTuple
|
||||||
|
{
|
||||||
|
Callable callable;
|
||||||
|
template<typename TupleType>
|
||||||
|
decltype(auto) operator()(TupleType&& _tuple) {
|
||||||
|
using PlainTupleType = std::remove_cv_t<std::remove_reference_t<TupleType>>;
|
||||||
|
return operator()(
|
||||||
|
std::forward<TupleType>(_tuple),
|
||||||
|
std::make_index_sequence<std::tuple_size_v<PlainTupleType>>{}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
template<typename TupleType, size_t... I>
|
||||||
|
decltype(auto) operator()(TupleType&& _tuple, std::index_sequence<I...>)
|
||||||
|
{
|
||||||
|
return callable(std::get<I>(std::forward<TupleType>(_tuple))...);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Wraps @a _callable, which takes multiple arguments, into a callable that takes a single tuple of arguments.
|
||||||
|
/// Since structured binding in lambdas is not allowed, i.e. [](auto&& [key, value]) { ... } is invalid, this allows
|
||||||
|
/// to instead use mapTuple([](auto&& key, auto&& value) { ... }).
|
||||||
|
template<typename Callable>
|
||||||
|
decltype(auto) mapTuple(Callable&& _callable)
|
||||||
|
{
|
||||||
|
return detail::MapTuple<Callable>{std::forward<Callable>(_callable)};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// String conversion functions, mainly to/from hex/nibble/byte representations.
|
// String conversion functions, mainly to/from hex/nibble/byte representations.
|
||||||
|
|
||||||
enum class WhenError
|
enum class WhenError
|
||||||
|
@ -63,19 +63,19 @@ void DataFlowAnalyzer::operator()(ExpressionStatement& _statement)
|
|||||||
if (auto vars = isSimpleStore(StoreLoadLocation::Storage, _statement))
|
if (auto vars = isSimpleStore(StoreLoadLocation::Storage, _statement))
|
||||||
{
|
{
|
||||||
ASTModifier::operator()(_statement);
|
ASTModifier::operator()(_statement);
|
||||||
cxx20::erase_if(m_storage, [&](auto const& entry) {
|
cxx20::erase_if(m_storage, mapTuple([&](auto&& key, auto&& value) {
|
||||||
return
|
return
|
||||||
!m_knowledgeBase.knownToBeDifferent(vars->first, entry.first) &&
|
!m_knowledgeBase.knownToBeDifferent(vars->first, key) &&
|
||||||
!m_knowledgeBase.knownToBeEqual(vars->second, entry.second);
|
!m_knowledgeBase.knownToBeEqual(vars->second, value);
|
||||||
});
|
}));
|
||||||
m_storage[vars->first] = vars->second;
|
m_storage[vars->first] = vars->second;
|
||||||
}
|
}
|
||||||
else if (auto vars = isSimpleStore(StoreLoadLocation::Memory, _statement))
|
else if (auto vars = isSimpleStore(StoreLoadLocation::Memory, _statement))
|
||||||
{
|
{
|
||||||
ASTModifier::operator()(_statement);
|
ASTModifier::operator()(_statement);
|
||||||
cxx20::erase_if(m_memory, [&](auto const& entry) {
|
cxx20::erase_if(m_memory, mapTuple([&](auto&& key, auto&& /* value */) {
|
||||||
return !m_knowledgeBase.knownToBeDifferentByAtLeast32(vars->first, entry.first);
|
return !m_knowledgeBase.knownToBeDifferentByAtLeast32(vars->first, key);
|
||||||
});
|
}));
|
||||||
m_memory[vars->first] = vars->second;
|
m_memory[vars->first] = vars->second;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -261,11 +261,11 @@ void DataFlowAnalyzer::handleAssignment(set<YulString> const& _variables, Expres
|
|||||||
// assignment to slot denoted by "name"
|
// assignment to slot denoted by "name"
|
||||||
m_storage.erase(name);
|
m_storage.erase(name);
|
||||||
// assignment to slot contents denoted by "name"
|
// assignment to slot contents denoted by "name"
|
||||||
cxx20::erase_if(m_storage, [&](auto const& entry) { return entry.second == name; });
|
cxx20::erase_if(m_storage, mapTuple([&name](auto&& /* key */, auto&& value) { return value == name; }));
|
||||||
// assignment to slot denoted by "name"
|
// assignment to slot denoted by "name"
|
||||||
m_memory.erase(name);
|
m_memory.erase(name);
|
||||||
// assignment to slot contents denoted by "name"
|
// assignment to slot contents denoted by "name"
|
||||||
cxx20::erase_if(m_memory, [&](auto const& entry) { return entry.second == name; });
|
cxx20::erase_if(m_memory, mapTuple([&name](auto&& /* key */, auto&& value) { return value == name; }));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -318,9 +318,9 @@ void DataFlowAnalyzer::clearValues(set<YulString> _variables)
|
|||||||
// First clear storage knowledge, because we do not have to clear
|
// First clear storage knowledge, because we do not have to clear
|
||||||
// storage knowledge of variables whose expression has changed,
|
// storage knowledge of variables whose expression has changed,
|
||||||
// since the value is still unchanged.
|
// since the value is still unchanged.
|
||||||
auto eraseCondition = [&](auto const& entry) {
|
auto eraseCondition = mapTuple([&_variables](auto&& key, auto&& value) {
|
||||||
return _variables.count(entry.first) || _variables.count(entry.second);
|
return _variables.count(key) || _variables.count(value);
|
||||||
};
|
});
|
||||||
cxx20::erase_if(m_storage, eraseCondition);
|
cxx20::erase_if(m_storage, eraseCondition);
|
||||||
cxx20::erase_if(m_memory, eraseCondition);
|
cxx20::erase_if(m_memory, eraseCondition);
|
||||||
|
|
||||||
@ -379,10 +379,10 @@ void DataFlowAnalyzer::joinKnowledgeHelper(
|
|||||||
// This also works for memory because _older is an "older version"
|
// This also works for memory because _older is an "older version"
|
||||||
// of m_memory and thus any overlapping write would have cleared the keys
|
// of m_memory and thus any overlapping write would have cleared the keys
|
||||||
// that are not known to be different inside m_memory already.
|
// that are not known to be different inside m_memory already.
|
||||||
cxx20::erase_if(_this, [&](auto const& entry){
|
cxx20::erase_if(_this, mapTuple([&_older](auto&& key, auto&& currentValue){
|
||||||
YulString const* value = valueOrNullptr(_older, entry.first);
|
YulString const* oldValue = valueOrNullptr(_older, key);
|
||||||
return !value || *value != entry.second;
|
return !oldValue || *oldValue != currentValue;
|
||||||
});
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DataFlowAnalyzer::inScope(YulString _variableName) const
|
bool DataFlowAnalyzer::inScope(YulString _variableName) const
|
||||||
|
Loading…
Reference in New Issue
Block a user