mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
[SMTChecker] Fix super and virtual
This commit is contained in:
@@ -30,6 +30,8 @@
|
||||
#include <libsmtutil/SMTPortfolio.h>
|
||||
#include <libsmtutil/Helpers.h>
|
||||
|
||||
#include <range/v3/view.hpp>
|
||||
|
||||
#include <boost/range/adaptors.hpp>
|
||||
#include <boost/range/adaptor/reversed.hpp>
|
||||
|
||||
@@ -112,7 +114,7 @@ bool SMTEncoder::visit(ContractDefinition const& _contract)
|
||||
// the constructor.
|
||||
// Constructors are visited as part of the constructor
|
||||
// hierarchy inlining.
|
||||
for (auto const* function: contractFunctions(_contract))
|
||||
for (auto const* function: contractFunctionsWithoutVirtual(_contract))
|
||||
if (!function->isConstructor())
|
||||
function->accept(*this);
|
||||
|
||||
@@ -776,6 +778,7 @@ void SMTEncoder::initFunction(FunctionDefinition const& _function)
|
||||
createLocalVariables(_function);
|
||||
m_arrayAssignmentHappened = false;
|
||||
clearIndices(m_currentContract, &_function);
|
||||
m_variableUsage.setCurrentFunction(_function);
|
||||
m_checked = true;
|
||||
}
|
||||
|
||||
@@ -2534,6 +2537,14 @@ bool SMTEncoder::visitedFunction(FunctionDefinition const* _funDef)
|
||||
return false;
|
||||
}
|
||||
|
||||
ContractDefinition const* SMTEncoder::currentScopeContract()
|
||||
{
|
||||
for (auto&& f: m_callStack | ranges::views::reverse | ranges::views::keys)
|
||||
if (auto fun = dynamic_cast<FunctionDefinition const*>(f))
|
||||
return fun->annotation().contract;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
SMTEncoder::VariableIndices SMTEncoder::copyVariableIndices()
|
||||
{
|
||||
VariableIndices indices;
|
||||
@@ -2678,7 +2689,11 @@ string SMTEncoder::extraComment()
|
||||
return extra;
|
||||
}
|
||||
|
||||
pair<FunctionDefinition const*, ContractDefinition const*> SMTEncoder::functionCallToDefinition(FunctionCall const& _funCall, ContractDefinition const* _contract)
|
||||
FunctionDefinition const* SMTEncoder::functionCallToDefinition(
|
||||
FunctionCall const& _funCall,
|
||||
ContractDefinition const* _scopeContract,
|
||||
ContractDefinition const* _contextContract
|
||||
)
|
||||
{
|
||||
if (*_funCall.annotation().kind != FunctionCallKind::FunctionCall)
|
||||
return {};
|
||||
@@ -2690,32 +2705,27 @@ pair<FunctionDefinition const*, ContractDefinition const*> SMTEncoder::functionC
|
||||
calledExpr = innermostTuple(*calledExpr);
|
||||
}
|
||||
|
||||
auto resolveVirtual = [&](auto const* _ref) -> pair<FunctionDefinition const*, ContractDefinition const*> {
|
||||
auto resolveVirtual = [&](auto const* _ref) -> FunctionDefinition const* {
|
||||
VirtualLookup lookup = *_ref->annotation().requiredLookup;
|
||||
solAssert(_contract || lookup == VirtualLookup::Static, "No contract context provided for function lookup resolution!");
|
||||
solAssert(_contextContract || lookup == VirtualLookup::Static, "No contract context provided for function lookup resolution!");
|
||||
auto funDef = dynamic_cast<FunctionDefinition const*>(_ref->annotation().referencedDeclaration);
|
||||
if (!funDef)
|
||||
return {funDef, _contract};
|
||||
ContractDefinition const* contextContract = nullptr;
|
||||
return funDef;
|
||||
switch (lookup)
|
||||
{
|
||||
case VirtualLookup::Virtual:
|
||||
funDef = &funDef->resolveVirtual(*_contract);
|
||||
contextContract = _contract;
|
||||
break;
|
||||
return &(funDef->resolveVirtual(*_contextContract));
|
||||
case VirtualLookup::Super:
|
||||
{
|
||||
auto super = _contract->superContract(*_contract);
|
||||
solAssert(_scopeContract, "");
|
||||
auto super = _scopeContract->superContract(*_contextContract);
|
||||
solAssert(super, "Super contract not available.");
|
||||
funDef = &funDef->resolveVirtual(*_contract, super);
|
||||
contextContract = super;
|
||||
break;
|
||||
return &funDef->resolveVirtual(*_contextContract, super);
|
||||
}
|
||||
case VirtualLookup::Static:
|
||||
contextContract = funDef->annotation().contract;
|
||||
break;
|
||||
return funDef;
|
||||
}
|
||||
return {funDef, contextContract};
|
||||
solAssert(false, "");
|
||||
};
|
||||
|
||||
if (Identifier const* fun = dynamic_cast<Identifier const*>(calledExpr))
|
||||
@@ -2810,11 +2820,12 @@ ModifierDefinition const* SMTEncoder::resolveModifierInvocation(ModifierInvocati
|
||||
return modifier;
|
||||
}
|
||||
|
||||
vector<FunctionDefinition const*> const& SMTEncoder::contractFunctions(ContractDefinition const& _contract)
|
||||
set<FunctionDefinition const*, ASTNode::CompareByID> const& SMTEncoder::contractFunctions(ContractDefinition const& _contract)
|
||||
{
|
||||
if (!m_contractFunctions.count(&_contract))
|
||||
{
|
||||
vector<FunctionDefinition const *> resolvedFunctions = _contract.definedFunctions();
|
||||
auto const& functions = _contract.definedFunctions();
|
||||
set<FunctionDefinition const*, ASTNode::CompareByID> resolvedFunctions(begin(functions), end(functions));
|
||||
for (auto const* base: _contract.annotation().linearizedBaseContracts)
|
||||
{
|
||||
if (base == &_contract)
|
||||
@@ -2836,7 +2847,7 @@ vector<FunctionDefinition const*> const& SMTEncoder::contractFunctions(ContractD
|
||||
break;
|
||||
}
|
||||
if (!overridden)
|
||||
resolvedFunctions.push_back(baseFunction);
|
||||
resolvedFunctions.insert(baseFunction);
|
||||
}
|
||||
}
|
||||
m_contractFunctions.emplace(&_contract, move(resolvedFunctions));
|
||||
@@ -2844,6 +2855,22 @@ vector<FunctionDefinition const*> const& SMTEncoder::contractFunctions(ContractD
|
||||
return m_contractFunctions.at(&_contract);
|
||||
}
|
||||
|
||||
set<FunctionDefinition const*, ASTNode::CompareByID> const& SMTEncoder::contractFunctionsWithoutVirtual(ContractDefinition const& _contract)
|
||||
{
|
||||
if (!m_contractFunctionsWithoutVirtual.count(&_contract))
|
||||
{
|
||||
auto allFunctions = contractFunctions(_contract);
|
||||
for (auto const* base: _contract.annotation().linearizedBaseContracts)
|
||||
for (auto const* baseFun: base->definedFunctions())
|
||||
if (!baseFun->isConstructor())
|
||||
allFunctions.insert(baseFun);
|
||||
|
||||
m_contractFunctionsWithoutVirtual.emplace(&_contract, move(allFunctions));
|
||||
|
||||
}
|
||||
return m_contractFunctionsWithoutVirtual.at(&_contract);
|
||||
}
|
||||
|
||||
SourceUnit const* SMTEncoder::sourceUnitContaining(Scopable const& _scopable)
|
||||
{
|
||||
for (auto const* s = &_scopable; s; s = dynamic_cast<Scopable const*>(s->scope()))
|
||||
@@ -2926,9 +2953,9 @@ set<FunctionCall const*> SMTEncoder::collectABICalls(ASTNode const* _node)
|
||||
return ABIFunctions(_node).abiCalls;
|
||||
}
|
||||
|
||||
void SMTEncoder::createReturnedExpressions(FunctionCall const& _funCall, ContractDefinition const* _contract)
|
||||
void SMTEncoder::createReturnedExpressions(FunctionCall const& _funCall, ContractDefinition const* _contextContract)
|
||||
{
|
||||
auto [funDef, contextContract] = functionCallToDefinition(_funCall, _contract);
|
||||
auto funDef = functionCallToDefinition(_funCall, currentScopeContract(), _contextContract);
|
||||
if (!funDef)
|
||||
return;
|
||||
|
||||
@@ -2954,9 +2981,9 @@ void SMTEncoder::createReturnedExpressions(FunctionCall const& _funCall, Contrac
|
||||
defineExpr(_funCall, currentValue(*returnParams.front()));
|
||||
}
|
||||
|
||||
vector<smtutil::Expression> SMTEncoder::symbolicArguments(FunctionCall const& _funCall, ContractDefinition const* _contract)
|
||||
vector<smtutil::Expression> SMTEncoder::symbolicArguments(FunctionCall const& _funCall, ContractDefinition const* _contextContract)
|
||||
{
|
||||
auto [funDef, contextContract] = functionCallToDefinition(_funCall, _contract);
|
||||
auto funDef = functionCallToDefinition(_funCall, currentScopeContract(), _contextContract);
|
||||
solAssert(funDef, "");
|
||||
|
||||
vector<smtutil::Expression> args;
|
||||
|
||||
Reference in New Issue
Block a user