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:
parent
86495dfc57
commit
b47d593252
@ -84,35 +84,11 @@ bool NameAndTypeResolver::resolveNamesAndTypes(ContractDefinition& _contract)
|
|||||||
importInheritedScope(*base);
|
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
|
// 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()];
|
m_currentScope = &m_scopes[m_scopes.count(node.get()) ? node.get() : &_contract];
|
||||||
ReferencesResolver resolver(m_errors, *this, nullptr);
|
if (!resolver.resolve(*node))
|
||||||
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))
|
|
||||||
success = false;
|
success = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -122,17 +98,17 @@ bool NameAndTypeResolver::resolveNamesAndTypes(ContractDefinition& _contract)
|
|||||||
m_currentScope = &m_scopes[&_contract];
|
m_currentScope = &m_scopes[&_contract];
|
||||||
|
|
||||||
// now resolve references inside the code
|
// 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);
|
ReferencesResolver resolver(m_errors, *this, nullptr, true);
|
||||||
if (!resolver.resolve(*modifier))
|
if (!resolver.resolve(*modifier))
|
||||||
success = false;
|
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(
|
if (!ReferencesResolver(
|
||||||
m_errors,
|
m_errors,
|
||||||
*this,
|
*this,
|
||||||
|
@ -53,7 +53,7 @@ bool ReferencesResolver::visit(UserDefinedTypeName const& _typeName)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ReferencesResolver::resolve(ASTNode& _root)
|
bool ReferencesResolver::resolve(ASTNode const& _root)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -55,7 +55,7 @@ public:
|
|||||||
{}
|
{}
|
||||||
|
|
||||||
/// @returns true if no errors during resolving
|
/// @returns true if no errors during resolving
|
||||||
bool resolve(ASTNode& _root);
|
bool resolve(ASTNode const& _root);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual bool visit(Block const&) override { return m_resolveInsideCode; }
|
virtual bool visit(Block const&) override { return m_resolveInsideCode; }
|
||||||
|
@ -63,6 +63,7 @@ bool TypeChecker::visit(ContractDefinition const& _contract)
|
|||||||
m_scope = &_contract;
|
m_scope = &_contract;
|
||||||
|
|
||||||
// We force our own visiting order here.
|
// 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.definedStructs(), *this);
|
||||||
ASTNode::listAccept(_contract.baseContracts(), *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.");
|
typeError(function->returnParameterList()->location(), "Non-empty \"returns\" directive for constructor.");
|
||||||
|
|
||||||
FunctionDefinition const* fallbackFunction = nullptr;
|
FunctionDefinition const* fallbackFunction = nullptr;
|
||||||
for (ASTPointer<FunctionDefinition> const& function: _contract.definedFunctions())
|
for (FunctionDefinition const* function: _contract.definedFunctions())
|
||||||
{
|
{
|
||||||
if (function->name().empty())
|
if (function->name().empty())
|
||||||
{
|
{
|
||||||
@ -88,7 +89,7 @@ bool TypeChecker::visit(ContractDefinition const& _contract)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
fallbackFunction = function.get();
|
fallbackFunction = function;
|
||||||
if (!fallbackFunction->parameters().empty())
|
if (!fallbackFunction->parameters().empty())
|
||||||
typeError(fallbackFunction->parameterList().location(), "Fallback function cannot take parameters.");
|
typeError(fallbackFunction->parameterList().location(), "Fallback function cannot take parameters.");
|
||||||
}
|
}
|
||||||
@ -97,10 +98,7 @@ bool TypeChecker::visit(ContractDefinition const& _contract)
|
|||||||
_contract.annotation().isFullyImplemented = false;
|
_contract.annotation().isFullyImplemented = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ASTNode::listAccept(_contract.stateVariables(), *this);
|
ASTNode::listAccept(_contract.subNodes(), *this);
|
||||||
ASTNode::listAccept(_contract.events(), *this);
|
|
||||||
ASTNode::listAccept(_contract.functionModifiers(), *this);
|
|
||||||
ASTNode::listAccept(_contract.definedFunctions(), *this);
|
|
||||||
|
|
||||||
checkContractExternalTypeClashes(_contract);
|
checkContractExternalTypeClashes(_contract);
|
||||||
// check for hash collisions in function signatures
|
// 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
|
/// Checks that two functions with the same name defined in this contract have different
|
||||||
/// argument types and that there is at most one constructor.
|
/// argument types and that there is at most one constructor.
|
||||||
map<string, vector<FunctionDefinition const*>> functions;
|
map<string, vector<FunctionDefinition const*>> functions;
|
||||||
for (ASTPointer<FunctionDefinition> const& function: _contract.definedFunctions())
|
for (FunctionDefinition const* function: _contract.definedFunctions())
|
||||||
functions[function->name()].push_back(function.get());
|
functions[function->name()].push_back(function);
|
||||||
|
|
||||||
// Constructor
|
// Constructor
|
||||||
if (functions[_contract.name()].size() > 1)
|
if (functions[_contract.name()].size() > 1)
|
||||||
@ -172,7 +170,7 @@ void TypeChecker::checkContractAbstractFunctions(ContractDefinition const& _cont
|
|||||||
|
|
||||||
// Search from base to derived
|
// Search from base to derived
|
||||||
for (ContractDefinition const* contract: boost::adaptors::reverse(_contract.annotation().linearizedBaseContracts))
|
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()];
|
auto& overloads = functions[function->name()];
|
||||||
FunctionTypePointer funType = make_shared<FunctionType>(*function);
|
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.
|
// We search from derived to base, so the stored item causes the error.
|
||||||
for (ContractDefinition const* contract: _contract.annotation().linearizedBaseContracts)
|
for (ContractDefinition const* contract: _contract.annotation().linearizedBaseContracts)
|
||||||
{
|
{
|
||||||
for (ASTPointer<FunctionDefinition> const& function: contract->definedFunctions())
|
for (FunctionDefinition const* function: contract->definedFunctions())
|
||||||
{
|
{
|
||||||
if (function->isConstructor())
|
if (function->isConstructor())
|
||||||
continue; // constructors can neither be overridden nor override anything
|
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.");
|
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();
|
string const& name = modifier->name();
|
||||||
ModifierDefinition const*& override = modifiers[name];
|
ModifierDefinition const*& override = modifiers[name];
|
||||||
if (!override)
|
if (!override)
|
||||||
override = modifier.get();
|
override = modifier;
|
||||||
else if (ModifierType(*override) != ModifierType(*modifier))
|
else if (ModifierType(*override) != ModifierType(*modifier))
|
||||||
typeError(override->location(), "Override changes modifier signature.");
|
typeError(override->location(), "Override changes modifier signature.");
|
||||||
if (!functions[name].empty())
|
if (!functions[name].empty())
|
||||||
@ -290,20 +288,20 @@ void TypeChecker::checkContractExternalTypeClashes(ContractDefinition const& _co
|
|||||||
map<string, vector<pair<Declaration const*, FunctionTypePointer>>> externalDeclarations;
|
map<string, vector<pair<Declaration const*, FunctionTypePointer>>> externalDeclarations;
|
||||||
for (ContractDefinition const* contract: _contract.annotation().linearizedBaseContracts)
|
for (ContractDefinition const* contract: _contract.annotation().linearizedBaseContracts)
|
||||||
{
|
{
|
||||||
for (ASTPointer<FunctionDefinition> const& f: contract->definedFunctions())
|
for (FunctionDefinition const* f: contract->definedFunctions())
|
||||||
if (f->isPartOfExternalInterface())
|
if (f->isPartOfExternalInterface())
|
||||||
{
|
{
|
||||||
auto functionType = make_shared<FunctionType>(*f);
|
auto functionType = make_shared<FunctionType>(*f);
|
||||||
externalDeclarations[functionType->externalSignature()].push_back(
|
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())
|
if (v->isPartOfExternalInterface())
|
||||||
{
|
{
|
||||||
auto functionType = make_shared<FunctionType>(*v);
|
auto functionType = make_shared<FunctionType>(*v);
|
||||||
externalDeclarations[functionType->externalSignature()].push_back(
|
externalDeclarations[functionType->externalSignature()].push_back(
|
||||||
make_pair(v.get(), functionType)
|
make_pair(v, functionType)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -74,29 +74,83 @@ map<FixedHash<4>, FunctionTypePointer> ContractDefinition::interfaceFunctions()
|
|||||||
|
|
||||||
FunctionDefinition const* ContractDefinition::constructor() const
|
FunctionDefinition const* ContractDefinition::constructor() const
|
||||||
{
|
{
|
||||||
for (ASTPointer<FunctionDefinition> const& f: m_definedFunctions)
|
for (FunctionDefinition const* f: definedFunctions())
|
||||||
if (f->isConstructor())
|
if (f->isConstructor())
|
||||||
return f.get();
|
return f;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
FunctionDefinition const* ContractDefinition::fallbackFunction() const
|
FunctionDefinition const* ContractDefinition::fallbackFunction() const
|
||||||
{
|
{
|
||||||
for (ContractDefinition const* contract: annotation().linearizedBaseContracts)
|
for (ContractDefinition const* contract: annotation().linearizedBaseContracts)
|
||||||
for (ASTPointer<FunctionDefinition> const& f: contract->definedFunctions())
|
for (FunctionDefinition const* f: contract->definedFunctions())
|
||||||
if (f->name().empty())
|
if (f->name().empty())
|
||||||
return f.get();
|
return f;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
vector<ASTPointer<EventDefinition>> const& ContractDefinition::interfaceEvents() const
|
vector<StructDefinition const*> ContractDefinition::definedStructs() const
|
||||||
|
{
|
||||||
|
vector<StructDefinition const*> ret;
|
||||||
|
for (auto const& node: m_subNodes)
|
||||||
|
if (auto v = dynamic_cast<StructDefinition const*>(node.get()))
|
||||||
|
ret.push_back(v);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
vector<EnumDefinition const*> ContractDefinition::definedEnums() const
|
||||||
|
{
|
||||||
|
vector<EnumDefinition const*> ret;
|
||||||
|
for (auto const& node: m_subNodes)
|
||||||
|
if (auto v = dynamic_cast<EnumDefinition const*>(node.get()))
|
||||||
|
ret.push_back(v);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
vector<VariableDeclaration const*> ContractDefinition::stateVariables() const
|
||||||
|
{
|
||||||
|
vector<VariableDeclaration const*> ret;
|
||||||
|
for (auto const& node: m_subNodes)
|
||||||
|
if (auto v = dynamic_cast<VariableDeclaration const*>(node.get()))
|
||||||
|
ret.push_back(v);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
vector<ModifierDefinition const*> ContractDefinition::functionModifiers() const
|
||||||
|
{
|
||||||
|
vector<ModifierDefinition const*> ret;
|
||||||
|
for (auto const& node: m_subNodes)
|
||||||
|
if (auto v = dynamic_cast<ModifierDefinition const*>(node.get()))
|
||||||
|
ret.push_back(v);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
vector<FunctionDefinition const*> ContractDefinition::definedFunctions() const
|
||||||
|
{
|
||||||
|
vector<FunctionDefinition const*> ret;
|
||||||
|
for (auto const& node: m_subNodes)
|
||||||
|
if (auto v = dynamic_cast<FunctionDefinition const*>(node.get()))
|
||||||
|
ret.push_back(v);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
vector<EventDefinition const*> ContractDefinition::events() const
|
||||||
|
{
|
||||||
|
vector<EventDefinition const*> ret;
|
||||||
|
for (auto const& node: m_subNodes)
|
||||||
|
if (auto v = dynamic_cast<EventDefinition const*>(node.get()))
|
||||||
|
ret.push_back(v);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
vector<EventDefinition const*> const& ContractDefinition::interfaceEvents() const
|
||||||
{
|
{
|
||||||
if (!m_interfaceEvents)
|
if (!m_interfaceEvents)
|
||||||
{
|
{
|
||||||
set<string> eventsSeen;
|
set<string> eventsSeen;
|
||||||
m_interfaceEvents.reset(new vector<ASTPointer<EventDefinition>>());
|
m_interfaceEvents.reset(new vector<EventDefinition const*>());
|
||||||
for (ContractDefinition const* contract: annotation().linearizedBaseContracts)
|
for (ContractDefinition const* contract: annotation().linearizedBaseContracts)
|
||||||
for (ASTPointer<EventDefinition> const& e: contract->events())
|
for (EventDefinition const* e: contract->events())
|
||||||
if (eventsSeen.count(e->name()) == 0)
|
if (eventsSeen.count(e->name()) == 0)
|
||||||
{
|
{
|
||||||
eventsSeen.insert(e->name());
|
eventsSeen.insert(e->name());
|
||||||
@ -116,10 +170,10 @@ vector<pair<FixedHash<4>, FunctionTypePointer>> const& ContractDefinition::inter
|
|||||||
for (ContractDefinition const* contract: annotation().linearizedBaseContracts)
|
for (ContractDefinition const* contract: annotation().linearizedBaseContracts)
|
||||||
{
|
{
|
||||||
vector<FunctionTypePointer> functions;
|
vector<FunctionTypePointer> functions;
|
||||||
for (ASTPointer<FunctionDefinition> const& f: contract->definedFunctions())
|
for (FunctionDefinition const* f: contract->definedFunctions())
|
||||||
if (f->isPartOfExternalInterface())
|
if (f->isPartOfExternalInterface())
|
||||||
functions.push_back(make_shared<FunctionType>(*f, false));
|
functions.push_back(make_shared<FunctionType>(*f, false));
|
||||||
for (ASTPointer<VariableDeclaration> const& v: contract->stateVariables())
|
for (VariableDeclaration const* v: contract->stateVariables())
|
||||||
if (v->isPartOfExternalInterface())
|
if (v->isPartOfExternalInterface())
|
||||||
functions.push_back(make_shared<FunctionType>(*v));
|
functions.push_back(make_shared<FunctionType>(*v));
|
||||||
for (FunctionTypePointer const& fun: functions)
|
for (FunctionTypePointer const& fun: functions)
|
||||||
@ -176,14 +230,14 @@ vector<Declaration const*> const& ContractDefinition::inheritableMembers() const
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
for (ASTPointer<FunctionDefinition> const& f: definedFunctions())
|
for (FunctionDefinition const* f: definedFunctions())
|
||||||
addInheritableMember(f.get());
|
addInheritableMember(f);
|
||||||
|
|
||||||
for (ASTPointer<VariableDeclaration> const& v: stateVariables())
|
for (VariableDeclaration const* v: stateVariables())
|
||||||
addInheritableMember(v.get());
|
addInheritableMember(v);
|
||||||
|
|
||||||
for (ASTPointer<StructDefinition> const& s: definedStructs())
|
for (StructDefinition const* s: definedStructs())
|
||||||
addInheritableMember(s.get());
|
addInheritableMember(s);
|
||||||
}
|
}
|
||||||
return *m_inheritableMembers;
|
return *m_inheritableMembers;
|
||||||
}
|
}
|
||||||
|
@ -58,15 +58,15 @@ public:
|
|||||||
virtual void accept(ASTVisitor& _visitor) = 0;
|
virtual void accept(ASTVisitor& _visitor) = 0;
|
||||||
virtual void accept(ASTConstVisitor& _visitor) const = 0;
|
virtual void accept(ASTConstVisitor& _visitor) const = 0;
|
||||||
template <class T>
|
template <class T>
|
||||||
static void listAccept(std::vector<ASTPointer<T>>& _list, ASTVisitor& _visitor)
|
static void listAccept(std::vector<T> const& _list, ASTVisitor& _visitor)
|
||||||
{
|
{
|
||||||
for (ASTPointer<T>& element: _list)
|
for (T const& element: _list)
|
||||||
element->accept(_visitor);
|
element->accept(_visitor);
|
||||||
}
|
}
|
||||||
template <class T>
|
template <class T>
|
||||||
static void listAccept(std::vector<ASTPointer<T>> const& _list, ASTConstVisitor& _visitor)
|
static void listAccept(std::vector<T> const& _list, ASTConstVisitor& _visitor)
|
||||||
{
|
{
|
||||||
for (ASTPointer<T> const& element: _list)
|
for (T const& element: _list)
|
||||||
element->accept(_visitor);
|
element->accept(_visitor);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -238,23 +238,13 @@ public:
|
|||||||
ASTPointer<ASTString> const& _name,
|
ASTPointer<ASTString> const& _name,
|
||||||
ASTPointer<ASTString> const& _documentation,
|
ASTPointer<ASTString> const& _documentation,
|
||||||
std::vector<ASTPointer<InheritanceSpecifier>> const& _baseContracts,
|
std::vector<ASTPointer<InheritanceSpecifier>> const& _baseContracts,
|
||||||
std::vector<ASTPointer<StructDefinition>> const& _definedStructs,
|
std::vector<ASTPointer<ASTNode>> const& _subNodes,
|
||||||
std::vector<ASTPointer<EnumDefinition>> const& _definedEnums,
|
|
||||||
std::vector<ASTPointer<VariableDeclaration>> const& _stateVariables,
|
|
||||||
std::vector<ASTPointer<FunctionDefinition>> const& _definedFunctions,
|
|
||||||
std::vector<ASTPointer<ModifierDefinition>> const& _functionModifiers,
|
|
||||||
std::vector<ASTPointer<EventDefinition>> const& _events,
|
|
||||||
bool _isLibrary
|
bool _isLibrary
|
||||||
):
|
):
|
||||||
Declaration(_location, _name),
|
Declaration(_location, _name),
|
||||||
Documented(_documentation),
|
Documented(_documentation),
|
||||||
m_baseContracts(_baseContracts),
|
m_baseContracts(_baseContracts),
|
||||||
m_definedStructs(_definedStructs),
|
m_subNodes(_subNodes),
|
||||||
m_definedEnums(_definedEnums),
|
|
||||||
m_stateVariables(_stateVariables),
|
|
||||||
m_definedFunctions(_definedFunctions),
|
|
||||||
m_functionModifiers(_functionModifiers),
|
|
||||||
m_events(_events),
|
|
||||||
m_isLibrary(_isLibrary)
|
m_isLibrary(_isLibrary)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
@ -262,13 +252,14 @@ public:
|
|||||||
virtual void accept(ASTConstVisitor& _visitor) const override;
|
virtual void accept(ASTConstVisitor& _visitor) const override;
|
||||||
|
|
||||||
std::vector<ASTPointer<InheritanceSpecifier>> const& baseContracts() const { return m_baseContracts; }
|
std::vector<ASTPointer<InheritanceSpecifier>> const& baseContracts() const { return m_baseContracts; }
|
||||||
std::vector<ASTPointer<StructDefinition>> const& definedStructs() const { return m_definedStructs; }
|
std::vector<ASTPointer<ASTNode>> const& subNodes() const { return m_subNodes; }
|
||||||
std::vector<ASTPointer<EnumDefinition>> const& definedEnums() const { return m_definedEnums; }
|
std::vector<StructDefinition const*> definedStructs() const;
|
||||||
std::vector<ASTPointer<VariableDeclaration>> const& stateVariables() const { return m_stateVariables; }
|
std::vector<EnumDefinition const*> definedEnums() const;
|
||||||
std::vector<ASTPointer<ModifierDefinition>> const& functionModifiers() const { return m_functionModifiers; }
|
std::vector<VariableDeclaration const*> stateVariables() const;
|
||||||
std::vector<ASTPointer<FunctionDefinition>> const& definedFunctions() const { return m_definedFunctions; }
|
std::vector<ModifierDefinition const*> functionModifiers() const;
|
||||||
std::vector<ASTPointer<EventDefinition>> const& events() const { return m_events; }
|
std::vector<FunctionDefinition const*> definedFunctions() const;
|
||||||
std::vector<ASTPointer<EventDefinition>> const& interfaceEvents() const;
|
std::vector<EventDefinition const*> events() const;
|
||||||
|
std::vector<EventDefinition const*> const& interfaceEvents() const;
|
||||||
bool isLibrary() const { return m_isLibrary; }
|
bool isLibrary() const { return m_isLibrary; }
|
||||||
|
|
||||||
/// @returns a map of canonical function signatures to FunctionDefinitions
|
/// @returns a map of canonical function signatures to FunctionDefinitions
|
||||||
@ -296,12 +287,7 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<ASTPointer<InheritanceSpecifier>> m_baseContracts;
|
std::vector<ASTPointer<InheritanceSpecifier>> m_baseContracts;
|
||||||
std::vector<ASTPointer<StructDefinition>> m_definedStructs;
|
std::vector<ASTPointer<ASTNode>> m_subNodes;
|
||||||
std::vector<ASTPointer<EnumDefinition>> m_definedEnums;
|
|
||||||
std::vector<ASTPointer<VariableDeclaration>> m_stateVariables;
|
|
||||||
std::vector<ASTPointer<FunctionDefinition>> m_definedFunctions;
|
|
||||||
std::vector<ASTPointer<ModifierDefinition>> m_functionModifiers;
|
|
||||||
std::vector<ASTPointer<EventDefinition>> m_events;
|
|
||||||
bool m_isLibrary;
|
bool m_isLibrary;
|
||||||
|
|
||||||
// parsed Natspec documentation of the contract.
|
// parsed Natspec documentation of the contract.
|
||||||
@ -310,7 +296,7 @@ private:
|
|||||||
|
|
||||||
std::vector<ContractDefinition const*> m_linearizedBaseContracts;
|
std::vector<ContractDefinition const*> m_linearizedBaseContracts;
|
||||||
mutable std::unique_ptr<std::vector<std::pair<FixedHash<4>, FunctionTypePointer>>> m_interfaceFunctionList;
|
mutable std::unique_ptr<std::vector<std::pair<FixedHash<4>, FunctionTypePointer>>> m_interfaceFunctionList;
|
||||||
mutable std::unique_ptr<std::vector<ASTPointer<EventDefinition>>> m_interfaceEvents;
|
mutable std::unique_ptr<std::vector<EventDefinition const*>> m_interfaceEvents;
|
||||||
mutable std::unique_ptr<std::vector<Declaration const*>> m_inheritableMembers;
|
mutable std::unique_ptr<std::vector<Declaration const*>> m_inheritableMembers;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -62,12 +62,7 @@ void ContractDefinition::accept(ASTVisitor& _visitor)
|
|||||||
if (_visitor.visit(*this))
|
if (_visitor.visit(*this))
|
||||||
{
|
{
|
||||||
listAccept(m_baseContracts, _visitor);
|
listAccept(m_baseContracts, _visitor);
|
||||||
listAccept(m_definedStructs, _visitor);
|
listAccept(m_subNodes, _visitor);
|
||||||
listAccept(m_definedEnums, _visitor);
|
|
||||||
listAccept(m_stateVariables, _visitor);
|
|
||||||
listAccept(m_events, _visitor);
|
|
||||||
listAccept(m_functionModifiers, _visitor);
|
|
||||||
listAccept(m_definedFunctions, _visitor);
|
|
||||||
}
|
}
|
||||||
_visitor.endVisit(*this);
|
_visitor.endVisit(*this);
|
||||||
}
|
}
|
||||||
@ -77,12 +72,7 @@ void ContractDefinition::accept(ASTConstVisitor& _visitor) const
|
|||||||
if (_visitor.visit(*this))
|
if (_visitor.visit(*this))
|
||||||
{
|
{
|
||||||
listAccept(m_baseContracts, _visitor);
|
listAccept(m_baseContracts, _visitor);
|
||||||
listAccept(m_definedStructs, _visitor);
|
listAccept(m_subNodes, _visitor);
|
||||||
listAccept(m_definedEnums, _visitor);
|
|
||||||
listAccept(m_stateVariables, _visitor);
|
|
||||||
listAccept(m_events, _visitor);
|
|
||||||
listAccept(m_functionModifiers, _visitor);
|
|
||||||
listAccept(m_definedFunctions, _visitor);
|
|
||||||
}
|
}
|
||||||
_visitor.endVisit(*this);
|
_visitor.endVisit(*this);
|
||||||
}
|
}
|
||||||
|
@ -970,7 +970,7 @@ MemberList const& ContractType::members(ContractDefinition const*) const
|
|||||||
{
|
{
|
||||||
// add the most derived of all functions which are visible in derived contracts
|
// add the most derived of all functions which are visible in derived contracts
|
||||||
for (ContractDefinition const* base: m_contract.annotation().linearizedBaseContracts)
|
for (ContractDefinition const* base: m_contract.annotation().linearizedBaseContracts)
|
||||||
for (ASTPointer<FunctionDefinition> const& function: base->definedFunctions())
|
for (FunctionDefinition const* function: base->definedFunctions())
|
||||||
{
|
{
|
||||||
if (!function->isVisibleInDerivedContracts())
|
if (!function->isVisibleInDerivedContracts())
|
||||||
continue;
|
continue;
|
||||||
@ -991,7 +991,7 @@ MemberList const& ContractType::members(ContractDefinition const*) const
|
|||||||
members.push_back(MemberList::Member(
|
members.push_back(MemberList::Member(
|
||||||
function->name(),
|
function->name(),
|
||||||
functionType,
|
functionType,
|
||||||
function.get()
|
function
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1024,9 +1024,9 @@ vector<tuple<VariableDeclaration const*, u256, unsigned>> ContractType::stateVar
|
|||||||
{
|
{
|
||||||
vector<VariableDeclaration const*> variables;
|
vector<VariableDeclaration const*> variables;
|
||||||
for (ContractDefinition const* contract: boost::adaptors::reverse(m_contract.annotation().linearizedBaseContracts))
|
for (ContractDefinition const* contract: boost::adaptors::reverse(m_contract.annotation().linearizedBaseContracts))
|
||||||
for (ASTPointer<VariableDeclaration> const& variable: contract->stateVariables())
|
for (VariableDeclaration const* variable: contract->stateVariables())
|
||||||
if (!variable->isConstant())
|
if (!variable->isConstant())
|
||||||
variables.push_back(variable.get());
|
variables.push_back(variable);
|
||||||
TypePointers types;
|
TypePointers types;
|
||||||
for (auto variable: variables)
|
for (auto variable: variables)
|
||||||
types.push_back(variable->annotation().type);
|
types.push_back(variable->annotation().type);
|
||||||
|
@ -385,7 +385,7 @@ void Compiler::registerStateVariables(ContractDefinition const& _contract)
|
|||||||
|
|
||||||
void Compiler::initializeStateVariables(ContractDefinition const& _contract)
|
void Compiler::initializeStateVariables(ContractDefinition const& _contract)
|
||||||
{
|
{
|
||||||
for (ASTPointer<VariableDeclaration> const& variable: _contract.stateVariables())
|
for (VariableDeclaration const* variable: _contract.stateVariables())
|
||||||
if (variable->value() && !variable->isConstant())
|
if (variable->value() && !variable->isConstant())
|
||||||
ExpressionCompiler(m_context, m_optimize).appendStateVariableInitialization(*variable);
|
ExpressionCompiler(m_context, m_optimize).appendStateVariableInitialization(*variable);
|
||||||
}
|
}
|
||||||
|
@ -133,9 +133,9 @@ ModifierDefinition const& CompilerContext::functionModifier(string const& _name)
|
|||||||
{
|
{
|
||||||
solAssert(!m_inheritanceHierarchy.empty(), "No inheritance hierarchy set.");
|
solAssert(!m_inheritanceHierarchy.empty(), "No inheritance hierarchy set.");
|
||||||
for (ContractDefinition const* contract: m_inheritanceHierarchy)
|
for (ContractDefinition const* contract: m_inheritanceHierarchy)
|
||||||
for (ASTPointer<ModifierDefinition> const& modifier: contract->functionModifiers())
|
for (ModifierDefinition const* modifier: contract->functionModifiers())
|
||||||
if (modifier->name() == _name)
|
if (modifier->name() == _name)
|
||||||
return *modifier.get();
|
return *modifier;
|
||||||
BOOST_THROW_EXCEPTION(InternalCompilerError()
|
BOOST_THROW_EXCEPTION(InternalCompilerError()
|
||||||
<< errinfo_comment("Function modifier " + _name + " not found."));
|
<< errinfo_comment("Function modifier " + _name + " not found."));
|
||||||
}
|
}
|
||||||
@ -195,7 +195,7 @@ eth::AssemblyItem CompilerContext::virtualFunctionEntryLabel(
|
|||||||
FunctionType functionType(_function);
|
FunctionType functionType(_function);
|
||||||
auto it = _searchStart;
|
auto it = _searchStart;
|
||||||
for (; it != m_inheritanceHierarchy.end(); ++it)
|
for (; it != m_inheritanceHierarchy.end(); ++it)
|
||||||
for (ASTPointer<FunctionDefinition> const& function: (*it)->definedFunctions())
|
for (FunctionDefinition const* function: (*it)->definedFunctions())
|
||||||
if (
|
if (
|
||||||
function->name() == name &&
|
function->name() == name &&
|
||||||
!function->isConstructor() &&
|
!function->isConstructor() &&
|
||||||
|
@ -145,8 +145,8 @@ bool Why3Translator::visit(ContractDefinition const& _contract)
|
|||||||
|
|
||||||
addLine("type state = {");
|
addLine("type state = {");
|
||||||
indent();
|
indent();
|
||||||
m_stateVariables = &_contract.stateVariables();
|
m_stateVariables = _contract.stateVariables();
|
||||||
for (auto const& variable: _contract.stateVariables())
|
for (VariableDeclaration const* variable: m_stateVariables)
|
||||||
{
|
{
|
||||||
string varType = toFormalType(*variable->annotation().type);
|
string varType = toFormalType(*variable->annotation().type);
|
||||||
if (varType.empty())
|
if (varType.empty())
|
||||||
@ -174,7 +174,7 @@ bool Why3Translator::visit(ContractDefinition const& _contract)
|
|||||||
|
|
||||||
void Why3Translator::endVisit(ContractDefinition const& _contract)
|
void Why3Translator::endVisit(ContractDefinition const& _contract)
|
||||||
{
|
{
|
||||||
m_stateVariables = nullptr;
|
m_stateVariables.clear();
|
||||||
addSourceFromDocStrings(_contract.annotation());
|
addSourceFromDocStrings(_contract.annotation());
|
||||||
unindent();
|
unindent();
|
||||||
addLine("end");
|
addLine("end");
|
||||||
@ -600,17 +600,12 @@ bool Why3Translator::visit(Literal const& _literal)
|
|||||||
|
|
||||||
bool Why3Translator::isStateVariable(VariableDeclaration const* _var) const
|
bool Why3Translator::isStateVariable(VariableDeclaration const* _var) const
|
||||||
{
|
{
|
||||||
solAssert(!!m_stateVariables, "");
|
return contains(m_stateVariables, _var);
|
||||||
for (auto const& var: *m_stateVariables)
|
|
||||||
if (var.get() == _var)
|
|
||||||
return true;
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Why3Translator::isStateVariable(string const& _name) const
|
bool Why3Translator::isStateVariable(string const& _name) const
|
||||||
{
|
{
|
||||||
solAssert(!!m_stateVariables, "");
|
for (auto const& var: m_stateVariables)
|
||||||
for (auto const& var: *m_stateVariables)
|
|
||||||
if (var->name() == _name)
|
if (var->name() == _name)
|
||||||
return true;
|
return true;
|
||||||
return false;
|
return false;
|
||||||
|
@ -117,7 +117,7 @@ private:
|
|||||||
bool m_seenContract = false;
|
bool m_seenContract = false;
|
||||||
bool m_errorOccured = false;
|
bool m_errorOccured = false;
|
||||||
|
|
||||||
std::vector<ASTPointer<VariableDeclaration>> const* m_stateVariables = nullptr;
|
std::vector<VariableDeclaration const*> m_stateVariables;
|
||||||
std::map<std::string, VariableDeclaration const*> m_localVariables;
|
std::map<std::string, VariableDeclaration const*> m_localVariables;
|
||||||
|
|
||||||
struct Line
|
struct Line
|
||||||
|
@ -132,12 +132,6 @@ ASTPointer<ContractDefinition> Parser::parseContractDefinition(bool _isLibrary)
|
|||||||
expectToken(_isLibrary ? Token::Library : Token::Contract);
|
expectToken(_isLibrary ? Token::Library : Token::Contract);
|
||||||
ASTPointer<ASTString> name = expectIdentifierToken();
|
ASTPointer<ASTString> name = expectIdentifierToken();
|
||||||
vector<ASTPointer<InheritanceSpecifier>> baseContracts;
|
vector<ASTPointer<InheritanceSpecifier>> baseContracts;
|
||||||
vector<ASTPointer<StructDefinition>> structs;
|
|
||||||
vector<ASTPointer<EnumDefinition>> enums;
|
|
||||||
vector<ASTPointer<VariableDeclaration>> stateVariables;
|
|
||||||
vector<ASTPointer<FunctionDefinition>> functions;
|
|
||||||
vector<ASTPointer<ModifierDefinition>> modifiers;
|
|
||||||
vector<ASTPointer<EventDefinition>> events;
|
|
||||||
if (m_scanner->currentToken() == Token::Is)
|
if (m_scanner->currentToken() == Token::Is)
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
@ -145,6 +139,7 @@ ASTPointer<ContractDefinition> Parser::parseContractDefinition(bool _isLibrary)
|
|||||||
baseContracts.push_back(parseInheritanceSpecifier());
|
baseContracts.push_back(parseInheritanceSpecifier());
|
||||||
}
|
}
|
||||||
while (m_scanner->currentToken() == Token::Comma);
|
while (m_scanner->currentToken() == Token::Comma);
|
||||||
|
vector<ASTPointer<ASTNode>> subNodes;
|
||||||
expectToken(Token::LBrace);
|
expectToken(Token::LBrace);
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
@ -152,11 +147,11 @@ ASTPointer<ContractDefinition> Parser::parseContractDefinition(bool _isLibrary)
|
|||||||
if (currentTokenValue == Token::RBrace)
|
if (currentTokenValue == Token::RBrace)
|
||||||
break;
|
break;
|
||||||
else if (currentTokenValue == Token::Function)
|
else if (currentTokenValue == Token::Function)
|
||||||
functions.push_back(parseFunctionDefinition(name.get()));
|
subNodes.push_back(parseFunctionDefinition(name.get()));
|
||||||
else if (currentTokenValue == Token::Struct)
|
else if (currentTokenValue == Token::Struct)
|
||||||
structs.push_back(parseStructDefinition());
|
subNodes.push_back(parseStructDefinition());
|
||||||
else if (currentTokenValue == Token::Enum)
|
else if (currentTokenValue == Token::Enum)
|
||||||
enums.push_back(parseEnumDefinition());
|
subNodes.push_back(parseEnumDefinition());
|
||||||
else if (
|
else if (
|
||||||
currentTokenValue == Token::Identifier ||
|
currentTokenValue == Token::Identifier ||
|
||||||
currentTokenValue == Token::Mapping ||
|
currentTokenValue == Token::Mapping ||
|
||||||
@ -166,13 +161,13 @@ ASTPointer<ContractDefinition> Parser::parseContractDefinition(bool _isLibrary)
|
|||||||
VarDeclParserOptions options;
|
VarDeclParserOptions options;
|
||||||
options.isStateVariable = true;
|
options.isStateVariable = true;
|
||||||
options.allowInitialValue = true;
|
options.allowInitialValue = true;
|
||||||
stateVariables.push_back(parseVariableDeclaration(options));
|
subNodes.push_back(parseVariableDeclaration(options));
|
||||||
expectToken(Token::Semicolon);
|
expectToken(Token::Semicolon);
|
||||||
}
|
}
|
||||||
else if (currentTokenValue == Token::Modifier)
|
else if (currentTokenValue == Token::Modifier)
|
||||||
modifiers.push_back(parseModifierDefinition());
|
subNodes.push_back(parseModifierDefinition());
|
||||||
else if (currentTokenValue == Token::Event)
|
else if (currentTokenValue == Token::Event)
|
||||||
events.push_back(parseEventDefinition());
|
subNodes.push_back(parseEventDefinition());
|
||||||
else
|
else
|
||||||
fatalParserError(std::string("Function, variable, struct or modifier declaration expected."));
|
fatalParserError(std::string("Function, variable, struct or modifier declaration expected."));
|
||||||
}
|
}
|
||||||
@ -182,12 +177,7 @@ ASTPointer<ContractDefinition> Parser::parseContractDefinition(bool _isLibrary)
|
|||||||
name,
|
name,
|
||||||
docString,
|
docString,
|
||||||
baseContracts,
|
baseContracts,
|
||||||
structs,
|
subNodes,
|
||||||
enums,
|
|
||||||
stateVariables,
|
|
||||||
functions,
|
|
||||||
modifiers,
|
|
||||||
events,
|
|
||||||
_isLibrary
|
_isLibrary
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -73,7 +73,7 @@ bool successParse(std::string const& _source)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void checkFunctionNatspec(
|
void checkFunctionNatspec(
|
||||||
ASTPointer<FunctionDefinition> _function,
|
FunctionDefinition const* _function,
|
||||||
std::string const& _expectedDoc
|
std::string const& _expectedDoc
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
@ -193,7 +193,7 @@ BOOST_AUTO_TEST_CASE(function_natspec_documentation)
|
|||||||
BOOST_CHECK(successParse(text));
|
BOOST_CHECK(successParse(text));
|
||||||
ErrorList e;
|
ErrorList e;
|
||||||
ASTPointer<ContractDefinition> contract = parseText(text, e);
|
ASTPointer<ContractDefinition> contract = parseText(text, e);
|
||||||
ASTPointer<FunctionDefinition> function;
|
FunctionDefinition const* function = nullptr;
|
||||||
|
|
||||||
ErrorList errors;
|
ErrorList errors;
|
||||||
auto functions = parseText(text, errors)->definedFunctions();
|
auto functions = parseText(text, errors)->definedFunctions();
|
||||||
@ -204,7 +204,7 @@ BOOST_AUTO_TEST_CASE(function_natspec_documentation)
|
|||||||
BOOST_AUTO_TEST_CASE(function_normal_comments)
|
BOOST_AUTO_TEST_CASE(function_normal_comments)
|
||||||
{
|
{
|
||||||
ASTPointer<ContractDefinition> contract;
|
ASTPointer<ContractDefinition> contract;
|
||||||
ASTPointer<FunctionDefinition> function;
|
FunctionDefinition const* function = nullptr;
|
||||||
char const* text = "contract test {\n"
|
char const* text = "contract test {\n"
|
||||||
" uint256 stateVar;\n"
|
" uint256 stateVar;\n"
|
||||||
" // We won't see this comment\n"
|
" // We won't see this comment\n"
|
||||||
@ -221,7 +221,7 @@ BOOST_AUTO_TEST_CASE(function_normal_comments)
|
|||||||
BOOST_AUTO_TEST_CASE(multiple_functions_natspec_documentation)
|
BOOST_AUTO_TEST_CASE(multiple_functions_natspec_documentation)
|
||||||
{
|
{
|
||||||
ASTPointer<ContractDefinition> contract;
|
ASTPointer<ContractDefinition> contract;
|
||||||
ASTPointer<FunctionDefinition> function;
|
FunctionDefinition const* function = nullptr;
|
||||||
char const* text = "contract test {\n"
|
char const* text = "contract test {\n"
|
||||||
" uint256 stateVar;\n"
|
" uint256 stateVar;\n"
|
||||||
" /// This is test function 1\n"
|
" /// This is test function 1\n"
|
||||||
@ -254,7 +254,7 @@ BOOST_AUTO_TEST_CASE(multiple_functions_natspec_documentation)
|
|||||||
BOOST_AUTO_TEST_CASE(multiline_function_documentation)
|
BOOST_AUTO_TEST_CASE(multiline_function_documentation)
|
||||||
{
|
{
|
||||||
ASTPointer<ContractDefinition> contract;
|
ASTPointer<ContractDefinition> contract;
|
||||||
ASTPointer<FunctionDefinition> function;
|
FunctionDefinition const* function = nullptr;
|
||||||
char const* text = "contract test {\n"
|
char const* text = "contract test {\n"
|
||||||
" uint256 stateVar;\n"
|
" uint256 stateVar;\n"
|
||||||
" /// This is a test function\n"
|
" /// This is a test function\n"
|
||||||
@ -272,7 +272,7 @@ BOOST_AUTO_TEST_CASE(multiline_function_documentation)
|
|||||||
BOOST_AUTO_TEST_CASE(natspec_comment_in_function_body)
|
BOOST_AUTO_TEST_CASE(natspec_comment_in_function_body)
|
||||||
{
|
{
|
||||||
ASTPointer<ContractDefinition> contract;
|
ASTPointer<ContractDefinition> contract;
|
||||||
ASTPointer<FunctionDefinition> function;
|
FunctionDefinition const* function = nullptr;
|
||||||
char const* text = "contract test {\n"
|
char const* text = "contract test {\n"
|
||||||
" /// fun1 description\n"
|
" /// fun1 description\n"
|
||||||
" function fun1(uint256 a) {\n"
|
" function fun1(uint256 a) {\n"
|
||||||
@ -301,7 +301,7 @@ BOOST_AUTO_TEST_CASE(natspec_comment_in_function_body)
|
|||||||
BOOST_AUTO_TEST_CASE(natspec_docstring_between_keyword_and_signature)
|
BOOST_AUTO_TEST_CASE(natspec_docstring_between_keyword_and_signature)
|
||||||
{
|
{
|
||||||
ASTPointer<ContractDefinition> contract;
|
ASTPointer<ContractDefinition> contract;
|
||||||
ASTPointer<FunctionDefinition> function;
|
FunctionDefinition const* function = nullptr;
|
||||||
char const* text = "contract test {\n"
|
char const* text = "contract test {\n"
|
||||||
" uint256 stateVar;\n"
|
" uint256 stateVar;\n"
|
||||||
" function ///I am in the wrong place \n"
|
" function ///I am in the wrong place \n"
|
||||||
@ -325,7 +325,7 @@ BOOST_AUTO_TEST_CASE(natspec_docstring_between_keyword_and_signature)
|
|||||||
BOOST_AUTO_TEST_CASE(natspec_docstring_after_signature)
|
BOOST_AUTO_TEST_CASE(natspec_docstring_after_signature)
|
||||||
{
|
{
|
||||||
ASTPointer<ContractDefinition> contract;
|
ASTPointer<ContractDefinition> contract;
|
||||||
ASTPointer<FunctionDefinition> function;
|
FunctionDefinition const* function = nullptr;
|
||||||
char const* text = "contract test {\n"
|
char const* text = "contract test {\n"
|
||||||
" uint256 stateVar;\n"
|
" uint256 stateVar;\n"
|
||||||
" function fun1(uint256 a) {\n"
|
" function fun1(uint256 a) {\n"
|
||||||
|
Loading…
Reference in New Issue
Block a user