mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Do not store elements of a contract by AST node type.
This commit is contained in:
@@ -84,35 +84,11 @@ bool NameAndTypeResolver::resolveNamesAndTypes(ContractDefinition& _contract)
|
||||
importInheritedScope(*base);
|
||||
}
|
||||
|
||||
for (ASTPointer<StructDefinition> const& structDef: _contract.definedStructs())
|
||||
if (!resolver.resolve(*structDef))
|
||||
success = false;
|
||||
for (ASTPointer<EnumDefinition> const& enumDef: _contract.definedEnums())
|
||||
if (!resolver.resolve(*enumDef))
|
||||
success = false;
|
||||
for (ASTPointer<VariableDeclaration> const& variable: _contract.stateVariables())
|
||||
if (!resolver.resolve(*variable))
|
||||
success = false;
|
||||
for (ASTPointer<EventDefinition> const& event: _contract.events())
|
||||
if (!resolver.resolve(*event))
|
||||
success = false;
|
||||
// these can contain code, only resolve parameters for now
|
||||
for (ASTPointer<ModifierDefinition> const& modifier: _contract.functionModifiers())
|
||||
for (ASTPointer<ASTNode> const& node: _contract.subNodes())
|
||||
{
|
||||
m_currentScope = &m_scopes[modifier.get()];
|
||||
ReferencesResolver resolver(m_errors, *this, nullptr);
|
||||
if (!resolver.resolve(*modifier))
|
||||
success = false;
|
||||
}
|
||||
|
||||
for (ASTPointer<FunctionDefinition> const& function: _contract.definedFunctions())
|
||||
{
|
||||
m_currentScope = &m_scopes[function.get()];
|
||||
if (!ReferencesResolver(
|
||||
m_errors,
|
||||
*this,
|
||||
function->returnParameterList().get()
|
||||
).resolve(*function))
|
||||
m_currentScope = &m_scopes[m_scopes.count(node.get()) ? node.get() : &_contract];
|
||||
if (!resolver.resolve(*node))
|
||||
success = false;
|
||||
}
|
||||
|
||||
@@ -122,17 +98,17 @@ bool NameAndTypeResolver::resolveNamesAndTypes(ContractDefinition& _contract)
|
||||
m_currentScope = &m_scopes[&_contract];
|
||||
|
||||
// now resolve references inside the code
|
||||
for (ASTPointer<ModifierDefinition> const& modifier: _contract.functionModifiers())
|
||||
for (ModifierDefinition const* modifier: _contract.functionModifiers())
|
||||
{
|
||||
m_currentScope = &m_scopes[modifier.get()];
|
||||
m_currentScope = &m_scopes[modifier];
|
||||
ReferencesResolver resolver(m_errors, *this, nullptr, true);
|
||||
if (!resolver.resolve(*modifier))
|
||||
success = false;
|
||||
}
|
||||
|
||||
for (ASTPointer<FunctionDefinition> const& function: _contract.definedFunctions())
|
||||
for (FunctionDefinition const* function: _contract.definedFunctions())
|
||||
{
|
||||
m_currentScope = &m_scopes[function.get()];
|
||||
m_currentScope = &m_scopes[function];
|
||||
if (!ReferencesResolver(
|
||||
m_errors,
|
||||
*this,
|
||||
|
||||
@@ -53,7 +53,7 @@ bool ReferencesResolver::visit(UserDefinedTypeName const& _typeName)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ReferencesResolver::resolve(ASTNode& _root)
|
||||
bool ReferencesResolver::resolve(ASTNode const& _root)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
||||
@@ -55,7 +55,7 @@ public:
|
||||
{}
|
||||
|
||||
/// @returns true if no errors during resolving
|
||||
bool resolve(ASTNode& _root);
|
||||
bool resolve(ASTNode const& _root);
|
||||
|
||||
private:
|
||||
virtual bool visit(Block const&) override { return m_resolveInsideCode; }
|
||||
|
||||
@@ -63,6 +63,7 @@ bool TypeChecker::visit(ContractDefinition const& _contract)
|
||||
m_scope = &_contract;
|
||||
|
||||
// We force our own visiting order here.
|
||||
//@TODO structs will be visited again below, but it is probably fine.
|
||||
ASTNode::listAccept(_contract.definedStructs(), *this);
|
||||
ASTNode::listAccept(_contract.baseContracts(), *this);
|
||||
|
||||
@@ -76,7 +77,7 @@ bool TypeChecker::visit(ContractDefinition const& _contract)
|
||||
typeError(function->returnParameterList()->location(), "Non-empty \"returns\" directive for constructor.");
|
||||
|
||||
FunctionDefinition const* fallbackFunction = nullptr;
|
||||
for (ASTPointer<FunctionDefinition> const& function: _contract.definedFunctions())
|
||||
for (FunctionDefinition const* function: _contract.definedFunctions())
|
||||
{
|
||||
if (function->name().empty())
|
||||
{
|
||||
@@ -88,7 +89,7 @@ bool TypeChecker::visit(ContractDefinition const& _contract)
|
||||
}
|
||||
else
|
||||
{
|
||||
fallbackFunction = function.get();
|
||||
fallbackFunction = function;
|
||||
if (!fallbackFunction->parameters().empty())
|
||||
typeError(fallbackFunction->parameterList().location(), "Fallback function cannot take parameters.");
|
||||
}
|
||||
@@ -97,10 +98,7 @@ bool TypeChecker::visit(ContractDefinition const& _contract)
|
||||
_contract.annotation().isFullyImplemented = false;
|
||||
}
|
||||
|
||||
ASTNode::listAccept(_contract.stateVariables(), *this);
|
||||
ASTNode::listAccept(_contract.events(), *this);
|
||||
ASTNode::listAccept(_contract.functionModifiers(), *this);
|
||||
ASTNode::listAccept(_contract.definedFunctions(), *this);
|
||||
ASTNode::listAccept(_contract.subNodes(), *this);
|
||||
|
||||
checkContractExternalTypeClashes(_contract);
|
||||
// check for hash collisions in function signatures
|
||||
@@ -127,8 +125,8 @@ void TypeChecker::checkContractDuplicateFunctions(ContractDefinition const& _con
|
||||
/// Checks that two functions with the same name defined in this contract have different
|
||||
/// argument types and that there is at most one constructor.
|
||||
map<string, vector<FunctionDefinition const*>> functions;
|
||||
for (ASTPointer<FunctionDefinition> const& function: _contract.definedFunctions())
|
||||
functions[function->name()].push_back(function.get());
|
||||
for (FunctionDefinition const* function: _contract.definedFunctions())
|
||||
functions[function->name()].push_back(function);
|
||||
|
||||
// Constructor
|
||||
if (functions[_contract.name()].size() > 1)
|
||||
@@ -172,7 +170,7 @@ void TypeChecker::checkContractAbstractFunctions(ContractDefinition const& _cont
|
||||
|
||||
// Search from base to derived
|
||||
for (ContractDefinition const* contract: boost::adaptors::reverse(_contract.annotation().linearizedBaseContracts))
|
||||
for (ASTPointer<FunctionDefinition> const& function: contract->definedFunctions())
|
||||
for (FunctionDefinition const* function: contract->definedFunctions())
|
||||
{
|
||||
auto& overloads = functions[function->name()];
|
||||
FunctionTypePointer funType = make_shared<FunctionType>(*function);
|
||||
@@ -248,7 +246,7 @@ void TypeChecker::checkContractIllegalOverrides(ContractDefinition const& _contr
|
||||
// We search from derived to base, so the stored item causes the error.
|
||||
for (ContractDefinition const* contract: _contract.annotation().linearizedBaseContracts)
|
||||
{
|
||||
for (ASTPointer<FunctionDefinition> const& function: contract->definedFunctions())
|
||||
for (FunctionDefinition const* function: contract->definedFunctions())
|
||||
{
|
||||
if (function->isConstructor())
|
||||
continue; // constructors can neither be overridden nor override anything
|
||||
@@ -269,14 +267,14 @@ void TypeChecker::checkContractIllegalOverrides(ContractDefinition const& _contr
|
||||
)
|
||||
typeError(overriding->location(), "Override changes extended function signature.");
|
||||
}
|
||||
functions[name].push_back(function.get());
|
||||
functions[name].push_back(function);
|
||||
}
|
||||
for (ASTPointer<ModifierDefinition> const& modifier: contract->functionModifiers())
|
||||
for (ModifierDefinition const* modifier: contract->functionModifiers())
|
||||
{
|
||||
string const& name = modifier->name();
|
||||
ModifierDefinition const*& override = modifiers[name];
|
||||
if (!override)
|
||||
override = modifier.get();
|
||||
override = modifier;
|
||||
else if (ModifierType(*override) != ModifierType(*modifier))
|
||||
typeError(override->location(), "Override changes modifier signature.");
|
||||
if (!functions[name].empty())
|
||||
@@ -290,20 +288,20 @@ void TypeChecker::checkContractExternalTypeClashes(ContractDefinition const& _co
|
||||
map<string, vector<pair<Declaration const*, FunctionTypePointer>>> externalDeclarations;
|
||||
for (ContractDefinition const* contract: _contract.annotation().linearizedBaseContracts)
|
||||
{
|
||||
for (ASTPointer<FunctionDefinition> const& f: contract->definedFunctions())
|
||||
for (FunctionDefinition const* f: contract->definedFunctions())
|
||||
if (f->isPartOfExternalInterface())
|
||||
{
|
||||
auto functionType = make_shared<FunctionType>(*f);
|
||||
externalDeclarations[functionType->externalSignature()].push_back(
|
||||
make_pair(f.get(), functionType)
|
||||
make_pair(f, functionType)
|
||||
);
|
||||
}
|
||||
for (ASTPointer<VariableDeclaration> const& v: contract->stateVariables())
|
||||
for (VariableDeclaration const* v: contract->stateVariables())
|
||||
if (v->isPartOfExternalInterface())
|
||||
{
|
||||
auto functionType = make_shared<FunctionType>(*v);
|
||||
externalDeclarations[functionType->externalSignature()].push_back(
|
||||
make_pair(v.get(), functionType)
|
||||
make_pair(v, functionType)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user