aboutsummaryrefslogtreecommitdiffstats
path: root/Compiler.cpp
diff options
context:
space:
mode:
authorChristian <c@ethdev.com>2015-01-23 09:46:31 +0800
committerChristian <c@ethdev.com>2015-01-26 17:23:39 +0800
commitfd5899d03806d82e228da12f8cbe151f079ea41f (patch)
treef839426ef2d921062ac8206ced3089acd318496a /Compiler.cpp
parent7ded95c776717cf96e96dffb7425c86b47ad8b0e (diff)
downloaddexon-solidity-fd5899d03806d82e228da12f8cbe151f079ea41f.tar.gz
dexon-solidity-fd5899d03806d82e228da12f8cbe151f079ea41f.tar.zst
dexon-solidity-fd5899d03806d82e228da12f8cbe151f079ea41f.zip
Modifier overrides and callgraph analysis.
Diffstat (limited to 'Compiler.cpp')
-rw-r--r--Compiler.cpp52
1 files changed, 32 insertions, 20 deletions
diff --git a/Compiler.cpp b/Compiler.cpp
index fa8eb775..99a429bc 100644
--- a/Compiler.cpp
+++ b/Compiler.cpp
@@ -42,9 +42,13 @@ void Compiler::compileContract(ContractDefinition const& _contract,
initializeContext(_contract, _contracts);
for (ContractDefinition const* contract: _contract.getLinearizedBaseContracts())
+ {
for (ASTPointer<FunctionDefinition> const& function: contract->getDefinedFunctions())
if (!function->isConstructor())
m_context.addFunction(*function);
+ for (ASTPointer<ModifierDefinition> const& modifier: contract->getFunctionModifiers())
+ m_context.addModifier(*modifier);
+ }
appendFunctionSelector(_contract);
for (ContractDefinition const* contract: _contract.getLinearizedBaseContracts())
@@ -67,6 +71,13 @@ void Compiler::initializeContext(ContractDefinition const& _contract,
void Compiler::packIntoContractCreator(ContractDefinition const& _contract, CompilerContext const& _runtimeContext)
{
+ std::vector<ContractDefinition const*> const& bases = _contract.getLinearizedBaseContracts();
+
+ // Make all modifiers known to the context.
+ for (ContractDefinition const* contract: bases)
+ for (ASTPointer<ModifierDefinition> const& modifier: contract->getFunctionModifiers())
+ m_context.addModifier(*modifier);
+
// arguments for base constructors, filled in derived-to-base order
map<ContractDefinition const*, vector<ASTPointer<Expression>> const*> baseArguments;
set<FunctionDefinition const*> neededFunctions;
@@ -74,10 +85,8 @@ void Compiler::packIntoContractCreator(ContractDefinition const& _contract, Comp
// Determine the arguments that are used for the base constructors and also which functions
// are needed at compile time.
- std::vector<ContractDefinition const*> const& bases = _contract.getLinearizedBaseContracts();
for (ContractDefinition const* contract: bases)
{
- //TODO include modifiers
if (FunctionDefinition const* constructor = contract->getConstructor())
nodesUsedInConstructors.insert(constructor);
for (ASTPointer<InheritanceSpecifier> const& base: contract->getBaseContracts())
@@ -94,7 +103,7 @@ void Compiler::packIntoContractCreator(ContractDefinition const& _contract, Comp
}
}
- auto overrideResolver = [&](string const& _name) -> FunctionDefinition const*
+ auto functionOverrideResolver = [&](string const& _name) -> FunctionDefinition const*
{
for (ContractDefinition const* contract: bases)
for (ASTPointer<FunctionDefinition> const& function: contract->getDefinedFunctions())
@@ -102,21 +111,26 @@ void Compiler::packIntoContractCreator(ContractDefinition const& _contract, Comp
return function.get();
return nullptr;
};
+ auto modifierOverrideResolver = [&](string const& _name) -> ModifierDefinition const*
+ {
+ return &m_context.getFunctionModifier(_name);
+ };
- neededFunctions = getFunctionsCalled(nodesUsedInConstructors, overrideResolver);
+ neededFunctions = getFunctionsCalled(nodesUsedInConstructors, functionOverrideResolver,
+ modifierOverrideResolver);
// First add all overrides (or the functions themselves if there is no override)
for (FunctionDefinition const* fun: neededFunctions)
{
FunctionDefinition const* override = nullptr;
if (!fun->isConstructor())
- override = overrideResolver(fun->getName());
+ override = functionOverrideResolver(fun->getName());
if (!!override && neededFunctions.count(override))
m_context.addFunction(*override);
}
// now add the rest
for (FunctionDefinition const* fun: neededFunctions)
- if (fun->isConstructor() || overrideResolver(fun->getName()) != fun)
+ if (fun->isConstructor() || functionOverrideResolver(fun->getName()) != fun)
m_context.addFunction(*fun);
// Call constructors in base-to-derived order.
@@ -176,9 +190,10 @@ void Compiler::appendConstructorCall(FunctionDefinition const& _constructor)
}
set<FunctionDefinition const*> Compiler::getFunctionsCalled(set<ASTNode const*> const& _nodes,
- function<FunctionDefinition const*(string const&)> const& _resolveOverrides)
+ function<FunctionDefinition const*(string const&)> const& _resolveFunctionOverrides,
+ function<ModifierDefinition const*(string const&)> const& _resolveModifierOverrides)
{
- CallGraph callgraph(_resolveOverrides);
+ CallGraph callgraph(_resolveFunctionOverrides, _resolveModifierOverrides);
for (ASTNode const* node: _nodes)
callgraph.addNode(*node);
return callgraph.getCalls();
@@ -471,25 +486,22 @@ void Compiler::appendModifierOrFunctionCode()
{
ASTPointer<ModifierInvocation> const& modifierInvocation = m_currentFunction->getModifiers()[m_modifierDepth];
- // TODO get the most derived override of the modifier
- ModifierDefinition const* modifier = dynamic_cast<ModifierDefinition const*>(
- modifierInvocation->getName()->getReferencedDeclaration());
- solAssert(!!modifier, "Modifier not found.");
- solAssert(modifier->getParameters().size() == modifierInvocation->getArguments().size(), "");
- for (unsigned i = 0; i < modifier->getParameters().size(); ++i)
+ ModifierDefinition const& modifier = m_context.getFunctionModifier(modifierInvocation->getName()->getName());
+ solAssert(modifier.getParameters().size() == modifierInvocation->getArguments().size(), "");
+ for (unsigned i = 0; i < modifier.getParameters().size(); ++i)
{
- m_context.addVariable(*modifier->getParameters()[i]);
+ m_context.addVariable(*modifier.getParameters()[i]);
compileExpression(*modifierInvocation->getArguments()[i],
- modifier->getParameters()[i]->getType());
+ modifier.getParameters()[i]->getType());
}
- for (VariableDeclaration const* localVariable: modifier->getLocalVariables())
+ for (VariableDeclaration const* localVariable: modifier.getLocalVariables())
m_context.addAndInitializeVariable(*localVariable);
- unsigned const c_stackSurplus = CompilerUtils::getSizeOnStack(modifier->getParameters()) +
- CompilerUtils::getSizeOnStack(modifier->getLocalVariables());
+ unsigned const c_stackSurplus = CompilerUtils::getSizeOnStack(modifier.getParameters()) +
+ CompilerUtils::getSizeOnStack(modifier.getLocalVariables());
m_stackCleanupForReturn += c_stackSurplus;
- modifier->getBody().accept(*this);
+ modifier.getBody().accept(*this);
for (unsigned i = 0; i < c_stackSurplus; ++i)
m_context << eth::Instruction::POP;