2014-10-07 16:25:04 +00:00
|
|
|
/*
|
2019-02-13 15:56:46 +00:00
|
|
|
This file is part of solidity.
|
2014-10-07 16:25:04 +00:00
|
|
|
|
2019-02-13 15:56:46 +00:00
|
|
|
solidity is free software: you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU General Public License as published by
|
|
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
|
|
(at your option) any later version.
|
2014-10-07 16:25:04 +00:00
|
|
|
|
2019-02-13 15:56:46 +00:00
|
|
|
solidity is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License for more details.
|
2014-10-07 16:25:04 +00:00
|
|
|
|
2019-02-13 15:56:46 +00:00
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with solidity. If not, see <http://www.gnu.org/licenses/>.
|
2014-10-07 16:25:04 +00:00
|
|
|
*/
|
|
|
|
/**
|
|
|
|
* @author Christian <c@ethdev.com>
|
|
|
|
* @date 2014
|
|
|
|
* Solidity abstract syntax tree.
|
|
|
|
*/
|
|
|
|
|
2015-10-20 22:21:52 +00:00
|
|
|
#include <libsolidity/ast/AST.h>
|
2018-12-17 14:33:15 +00:00
|
|
|
|
2015-10-20 22:21:52 +00:00
|
|
|
#include <libsolidity/ast/ASTVisitor.h>
|
|
|
|
#include <libsolidity/ast/AST_accept.h>
|
2019-04-15 13:33:39 +00:00
|
|
|
#include <libsolidity/ast/TypeProvider.h>
|
2018-10-18 11:35:20 +00:00
|
|
|
#include <libdevcore/Keccak256.h>
|
2015-01-07 15:39:21 +00:00
|
|
|
|
2017-01-24 16:38:06 +00:00
|
|
|
#include <boost/algorithm/string.hpp>
|
|
|
|
#include <algorithm>
|
|
|
|
#include <functional>
|
|
|
|
|
2014-10-24 17:06:30 +00:00
|
|
|
using namespace std;
|
2015-09-16 14:56:30 +00:00
|
|
|
using namespace dev;
|
|
|
|
using namespace dev::solidity;
|
2014-10-24 17:06:30 +00:00
|
|
|
|
2017-01-20 10:47:20 +00:00
|
|
|
class IDDispenser
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
static size_t next() { return ++instance(); }
|
|
|
|
static void reset() { instance() = 0; }
|
|
|
|
private:
|
|
|
|
static size_t& instance()
|
|
|
|
{
|
|
|
|
static IDDispenser dispenser;
|
|
|
|
return dispenser.id;
|
|
|
|
}
|
|
|
|
size_t id = 0;
|
|
|
|
};
|
|
|
|
|
2015-09-16 14:56:30 +00:00
|
|
|
ASTNode::ASTNode(SourceLocation const& _location):
|
2017-01-20 10:47:20 +00:00
|
|
|
m_id(IDDispenser::next()),
|
2015-09-16 14:56:30 +00:00
|
|
|
m_location(_location)
|
2014-10-16 12:08:54 +00:00
|
|
|
{
|
2014-10-23 17:22:30 +00:00
|
|
|
}
|
|
|
|
|
2015-09-16 14:56:30 +00:00
|
|
|
ASTNode::~ASTNode()
|
2015-01-22 00:02:38 +00:00
|
|
|
{
|
2015-09-21 16:55:58 +00:00
|
|
|
delete m_annotation;
|
|
|
|
}
|
|
|
|
|
2017-01-20 10:47:20 +00:00
|
|
|
void ASTNode::resetID()
|
|
|
|
{
|
|
|
|
IDDispenser::reset();
|
|
|
|
}
|
|
|
|
|
2015-09-21 16:55:58 +00:00
|
|
|
ASTAnnotation& ASTNode::annotation() const
|
|
|
|
{
|
|
|
|
if (!m_annotation)
|
|
|
|
m_annotation = new ASTAnnotation();
|
|
|
|
return *m_annotation;
|
2015-01-22 00:02:38 +00:00
|
|
|
}
|
|
|
|
|
2015-12-15 14:46:03 +00:00
|
|
|
SourceUnitAnnotation& SourceUnit::annotation() const
|
|
|
|
{
|
|
|
|
if (!m_annotation)
|
|
|
|
m_annotation = new SourceUnitAnnotation();
|
2017-03-06 13:00:46 +00:00
|
|
|
return dynamic_cast<SourceUnitAnnotation&>(*m_annotation);
|
2015-12-15 14:46:03 +00:00
|
|
|
}
|
|
|
|
|
2017-07-13 00:07:23 +00:00
|
|
|
set<SourceUnit const*> SourceUnit::referencedSourceUnits(bool _recurse, set<SourceUnit const*> _skipList) const
|
2017-07-12 23:08:28 +00:00
|
|
|
{
|
2017-07-12 23:17:25 +00:00
|
|
|
set<SourceUnit const*> sourceUnits;
|
2017-07-12 23:08:28 +00:00
|
|
|
for (ImportDirective const* importDirective: filteredNodes<ImportDirective>(nodes()))
|
|
|
|
{
|
2017-07-13 00:07:23 +00:00
|
|
|
auto const& sourceUnit = importDirective->annotation().sourceUnit;
|
|
|
|
if (!_skipList.count(sourceUnit))
|
2017-07-12 23:17:25 +00:00
|
|
|
{
|
2017-07-13 00:07:23 +00:00
|
|
|
_skipList.insert(sourceUnit);
|
|
|
|
sourceUnits.insert(sourceUnit);
|
|
|
|
if (_recurse)
|
2017-07-13 23:17:52 +00:00
|
|
|
sourceUnits += sourceUnit->referencedSourceUnits(true, _skipList);
|
2017-07-12 23:17:25 +00:00
|
|
|
}
|
2017-07-12 23:08:28 +00:00
|
|
|
}
|
|
|
|
return sourceUnits;
|
|
|
|
}
|
|
|
|
|
2015-12-09 16:35:20 +00:00
|
|
|
ImportAnnotation& ImportDirective::annotation() const
|
|
|
|
{
|
|
|
|
if (!m_annotation)
|
|
|
|
m_annotation = new ImportAnnotation();
|
2017-03-06 13:00:46 +00:00
|
|
|
return dynamic_cast<ImportAnnotation&>(*m_annotation);
|
2015-12-09 16:35:20 +00:00
|
|
|
}
|
|
|
|
|
2015-12-15 14:46:03 +00:00
|
|
|
TypePointer ImportDirective::type() const
|
|
|
|
{
|
|
|
|
solAssert(!!annotation().sourceUnit, "");
|
2019-04-17 11:40:50 +00:00
|
|
|
return TypeProvider::module(*annotation().sourceUnit);
|
2015-12-15 14:46:03 +00:00
|
|
|
}
|
|
|
|
|
2019-08-02 16:36:26 +00:00
|
|
|
vector<VariableDeclaration const*> ContractDefinition::stateVariablesIncludingInherited() const
|
|
|
|
{
|
|
|
|
vector<VariableDeclaration const*> stateVars;
|
|
|
|
for (auto const& contract: annotation().linearizedBaseContracts)
|
|
|
|
for (auto var: contract->stateVariables())
|
|
|
|
if (*contract == *this || var->isVisibleInDerivedContracts())
|
|
|
|
stateVars.push_back(var);
|
|
|
|
return stateVars;
|
|
|
|
}
|
|
|
|
|
2015-08-31 16:44:29 +00:00
|
|
|
map<FixedHash<4>, FunctionTypePointer> ContractDefinition::interfaceFunctions() const
|
2014-11-11 16:41:48 +00:00
|
|
|
{
|
2015-08-31 16:44:29 +00:00
|
|
|
auto exportedFunctionList = interfaceFunctionList();
|
2015-01-23 15:37:06 +00:00
|
|
|
|
2015-01-29 15:48:39 +00:00
|
|
|
map<FixedHash<4>, FunctionTypePointer> exportedFunctions;
|
2015-01-23 15:37:06 +00:00
|
|
|
for (auto const& it: exportedFunctionList)
|
2015-01-29 15:39:30 +00:00
|
|
|
exportedFunctions.insert(it);
|
2015-01-22 16:40:22 +00:00
|
|
|
|
2015-09-10 08:17:17 +00:00
|
|
|
solAssert(
|
|
|
|
exportedFunctionList.size() == exportedFunctions.size(),
|
2015-09-08 12:30:21 +00:00
|
|
|
"Hash collision at Function Definition Hash calculation"
|
|
|
|
);
|
2014-11-11 16:41:48 +00:00
|
|
|
|
|
|
|
return exportedFunctions;
|
|
|
|
}
|
|
|
|
|
2015-08-31 16:44:29 +00:00
|
|
|
FunctionDefinition const* ContractDefinition::constructor() const
|
2014-12-12 15:49:26 +00:00
|
|
|
{
|
2015-11-23 22:57:17 +00:00
|
|
|
for (FunctionDefinition const* f: definedFunctions())
|
2015-01-20 14:58:04 +00:00
|
|
|
if (f->isConstructor())
|
2015-11-23 22:57:17 +00:00
|
|
|
return f;
|
2014-12-12 15:49:26 +00:00
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2017-03-06 13:12:20 +00:00
|
|
|
bool ContractDefinition::constructorIsPublic() const
|
|
|
|
{
|
|
|
|
FunctionDefinition const* f = constructor();
|
|
|
|
return !f || f->isPublic();
|
|
|
|
}
|
|
|
|
|
2019-01-17 19:08:17 +00:00
|
|
|
bool ContractDefinition::canBeDeployed() const
|
|
|
|
{
|
|
|
|
return constructorIsPublic() && annotation().unimplementedFunctions.empty();
|
|
|
|
}
|
|
|
|
|
2015-08-31 16:44:29 +00:00
|
|
|
FunctionDefinition const* ContractDefinition::fallbackFunction() const
|
2015-01-29 21:50:20 +00:00
|
|
|
{
|
2015-09-16 14:56:30 +00:00
|
|
|
for (ContractDefinition const* contract: annotation().linearizedBaseContracts)
|
2015-11-23 22:57:17 +00:00
|
|
|
for (FunctionDefinition const* f: contract->definedFunctions())
|
2017-07-27 19:55:55 +00:00
|
|
|
if (f->isFallback())
|
2015-11-23 22:57:17 +00:00
|
|
|
return f;
|
2015-01-29 21:50:20 +00:00
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2015-11-23 22:57:17 +00:00
|
|
|
vector<EventDefinition const*> const& ContractDefinition::interfaceEvents() const
|
2015-01-31 13:41:11 +00:00
|
|
|
{
|
|
|
|
if (!m_interfaceEvents)
|
|
|
|
{
|
|
|
|
set<string> eventsSeen;
|
2015-11-23 22:57:17 +00:00
|
|
|
m_interfaceEvents.reset(new vector<EventDefinition const*>());
|
2015-09-16 14:56:30 +00:00
|
|
|
for (ContractDefinition const* contract: annotation().linearizedBaseContracts)
|
2015-11-23 22:57:17 +00:00
|
|
|
for (EventDefinition const* e: contract->events())
|
2017-08-25 09:41:48 +00:00
|
|
|
{
|
|
|
|
/// NOTE: this requires the "internal" version of an Event,
|
|
|
|
/// though here internal strictly refers to visibility,
|
|
|
|
/// and not to function encoding (jump vs. call)
|
|
|
|
auto const& function = e->functionType(true);
|
|
|
|
solAssert(function, "");
|
|
|
|
string eventSignature = function->externalSignature();
|
|
|
|
if (eventsSeen.count(eventSignature) == 0)
|
2015-01-31 13:41:11 +00:00
|
|
|
{
|
2017-08-25 09:41:48 +00:00
|
|
|
eventsSeen.insert(eventSignature);
|
2015-01-31 13:41:11 +00:00
|
|
|
m_interfaceEvents->push_back(e);
|
|
|
|
}
|
2017-08-25 09:41:48 +00:00
|
|
|
}
|
2015-01-31 13:41:11 +00:00
|
|
|
}
|
|
|
|
return *m_interfaceEvents;
|
|
|
|
}
|
|
|
|
|
2015-08-31 16:44:29 +00:00
|
|
|
vector<pair<FixedHash<4>, FunctionTypePointer>> const& ContractDefinition::interfaceFunctionList() const
|
2015-01-16 16:50:10 +00:00
|
|
|
{
|
|
|
|
if (!m_interfaceFunctionList)
|
|
|
|
{
|
2015-03-01 03:34:39 +00:00
|
|
|
set<string> signaturesSeen;
|
2015-01-29 16:28:14 +00:00
|
|
|
m_interfaceFunctionList.reset(new vector<pair<FixedHash<4>, FunctionTypePointer>>());
|
2015-09-16 14:56:30 +00:00
|
|
|
for (ContractDefinition const* contract: annotation().linearizedBaseContracts)
|
2015-01-22 16:40:22 +00:00
|
|
|
{
|
2015-10-16 11:11:16 +00:00
|
|
|
vector<FunctionTypePointer> functions;
|
2015-11-23 22:57:17 +00:00
|
|
|
for (FunctionDefinition const* f: contract->definedFunctions())
|
2015-10-16 11:11:16 +00:00
|
|
|
if (f->isPartOfExternalInterface())
|
2019-04-17 11:40:50 +00:00
|
|
|
functions.push_back(TypeProvider::function(*f, false));
|
2015-11-23 22:57:17 +00:00
|
|
|
for (VariableDeclaration const* v: contract->stateVariables())
|
2015-10-16 11:11:16 +00:00
|
|
|
if (v->isPartOfExternalInterface())
|
2019-04-17 11:40:50 +00:00
|
|
|
functions.push_back(TypeProvider::function(*v));
|
2015-10-16 11:11:16 +00:00
|
|
|
for (FunctionTypePointer const& fun: functions)
|
2015-03-01 03:34:39 +00:00
|
|
|
{
|
2015-10-16 11:11:16 +00:00
|
|
|
if (!fun->interfaceFunctionType())
|
|
|
|
// Fails hopefully because we already registered the error
|
2015-06-26 14:52:30 +00:00
|
|
|
continue;
|
2015-10-16 11:11:16 +00:00
|
|
|
string functionSignature = fun->externalSignature();
|
2015-06-26 14:52:30 +00:00
|
|
|
if (signaturesSeen.count(functionSignature) == 0)
|
2015-01-16 16:50:10 +00:00
|
|
|
{
|
2015-03-01 03:34:39 +00:00
|
|
|
signaturesSeen.insert(functionSignature);
|
2016-10-05 10:30:28 +00:00
|
|
|
FixedHash<4> hash(dev::keccak256(functionSignature));
|
2018-12-10 18:02:39 +00:00
|
|
|
m_interfaceFunctionList->emplace_back(hash, fun);
|
2015-01-16 16:50:10 +00:00
|
|
|
}
|
2015-03-01 03:34:39 +00:00
|
|
|
}
|
2015-01-22 16:40:22 +00:00
|
|
|
}
|
2015-01-16 16:50:10 +00:00
|
|
|
}
|
|
|
|
return *m_interfaceFunctionList;
|
2015-01-14 09:16:58 +00:00
|
|
|
}
|
|
|
|
|
2015-08-31 16:44:29 +00:00
|
|
|
vector<Declaration const*> const& ContractDefinition::inheritableMembers() const
|
2015-02-25 19:35:55 +00:00
|
|
|
{
|
|
|
|
if (!m_inheritableMembers)
|
|
|
|
{
|
2015-03-02 11:08:32 +00:00
|
|
|
m_inheritableMembers.reset(new vector<Declaration const*>());
|
|
|
|
auto addInheritableMember = [&](Declaration const* _decl)
|
2015-02-25 19:35:55 +00:00
|
|
|
{
|
2016-10-21 10:14:24 +00:00
|
|
|
solAssert(_decl, "addInheritableMember got a nullpointer.");
|
2019-04-24 11:18:13 +00:00
|
|
|
if (_decl->isVisibleInDerivedContracts())
|
2015-02-28 17:30:33 +00:00
|
|
|
m_inheritableMembers->push_back(_decl);
|
|
|
|
};
|
2015-02-27 10:35:25 +00:00
|
|
|
|
2015-11-23 22:57:17 +00:00
|
|
|
for (FunctionDefinition const* f: definedFunctions())
|
|
|
|
addInheritableMember(f);
|
2015-02-25 19:35:55 +00:00
|
|
|
|
2015-11-23 22:57:17 +00:00
|
|
|
for (VariableDeclaration const* v: stateVariables())
|
|
|
|
addInheritableMember(v);
|
2015-02-26 11:11:54 +00:00
|
|
|
|
2015-11-23 22:57:17 +00:00
|
|
|
for (StructDefinition const* s: definedStructs())
|
|
|
|
addInheritableMember(s);
|
2016-10-18 11:01:22 +00:00
|
|
|
|
|
|
|
for (EnumDefinition const* e: definedEnums())
|
|
|
|
addInheritableMember(e);
|
2016-10-26 11:08:00 +00:00
|
|
|
|
|
|
|
for (EventDefinition const* e: events())
|
|
|
|
addInheritableMember(e);
|
2015-02-25 19:35:55 +00:00
|
|
|
}
|
|
|
|
return *m_inheritableMembers;
|
|
|
|
}
|
|
|
|
|
2015-11-19 17:02:04 +00:00
|
|
|
TypePointer ContractDefinition::type() const
|
2015-02-10 12:40:21 +00:00
|
|
|
{
|
2019-04-17 11:40:50 +00:00
|
|
|
return TypeProvider::typeType(TypeProvider::contract(*this));
|
2015-01-19 20:05:47 +00:00
|
|
|
}
|
|
|
|
|
2015-09-21 16:55:58 +00:00
|
|
|
ContractDefinitionAnnotation& ContractDefinition::annotation() const
|
|
|
|
{
|
|
|
|
if (!m_annotation)
|
|
|
|
m_annotation = new ContractDefinitionAnnotation();
|
2017-03-06 13:00:46 +00:00
|
|
|
return dynamic_cast<ContractDefinitionAnnotation&>(*m_annotation);
|
2015-09-21 16:55:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
TypeNameAnnotation& TypeName::annotation() const
|
|
|
|
{
|
|
|
|
if (!m_annotation)
|
|
|
|
m_annotation = new TypeNameAnnotation();
|
2017-03-06 13:00:46 +00:00
|
|
|
return dynamic_cast<TypeNameAnnotation&>(*m_annotation);
|
2015-09-21 16:55:58 +00:00
|
|
|
}
|
|
|
|
|
2015-11-19 17:02:04 +00:00
|
|
|
TypePointer StructDefinition::type() const
|
2015-01-22 00:02:38 +00:00
|
|
|
{
|
2019-04-15 15:28:32 +00:00
|
|
|
return TypeProvider::typeType(TypeProvider::structType(*this, DataLocation::Storage));
|
2015-01-22 00:02:38 +00:00
|
|
|
}
|
|
|
|
|
2015-10-05 15:19:23 +00:00
|
|
|
TypeDeclarationAnnotation& StructDefinition::annotation() const
|
|
|
|
{
|
|
|
|
if (!m_annotation)
|
|
|
|
m_annotation = new TypeDeclarationAnnotation();
|
2017-03-06 13:00:46 +00:00
|
|
|
return dynamic_cast<TypeDeclarationAnnotation&>(*m_annotation);
|
2015-10-05 15:19:23 +00:00
|
|
|
}
|
|
|
|
|
2015-11-19 17:02:04 +00:00
|
|
|
TypePointer EnumValue::type() const
|
2014-12-03 06:46:55 +00:00
|
|
|
{
|
2015-09-16 14:56:30 +00:00
|
|
|
auto parentDef = dynamic_cast<EnumDefinition const*>(scope());
|
|
|
|
solAssert(parentDef, "Enclosing Scope of EnumValue was not set");
|
2019-04-15 13:33:39 +00:00
|
|
|
return TypeProvider::enumType(*parentDef);
|
2014-12-03 06:46:55 +00:00
|
|
|
}
|
|
|
|
|
2015-11-19 17:02:04 +00:00
|
|
|
TypePointer EnumDefinition::type() const
|
2015-02-09 17:08:56 +00:00
|
|
|
{
|
2019-04-15 13:33:39 +00:00
|
|
|
return TypeProvider::typeType(TypeProvider::enumType(*this));
|
2015-02-09 17:08:56 +00:00
|
|
|
}
|
|
|
|
|
2015-10-05 15:19:23 +00:00
|
|
|
TypeDeclarationAnnotation& EnumDefinition::annotation() const
|
|
|
|
{
|
|
|
|
if (!m_annotation)
|
|
|
|
m_annotation = new TypeDeclarationAnnotation();
|
2017-03-06 13:00:46 +00:00
|
|
|
return dynamic_cast<TypeDeclarationAnnotation&>(*m_annotation);
|
2015-10-05 15:19:23 +00:00
|
|
|
}
|
|
|
|
|
2018-03-14 15:56:06 +00:00
|
|
|
ContractDefinition::ContractKind FunctionDefinition::inContractKind() const
|
|
|
|
{
|
|
|
|
auto contractDef = dynamic_cast<ContractDefinition const*>(scope());
|
|
|
|
solAssert(contractDef, "Enclosing Scope of FunctionDefinition was not set.");
|
|
|
|
return contractDef->contractKind();
|
|
|
|
}
|
|
|
|
|
2017-12-30 12:44:09 +00:00
|
|
|
FunctionTypePointer FunctionDefinition::functionType(bool _internal) const
|
2017-01-10 15:26:13 +00:00
|
|
|
{
|
|
|
|
if (_internal)
|
|
|
|
{
|
|
|
|
switch (visibility())
|
|
|
|
{
|
|
|
|
case Declaration::Visibility::Default:
|
|
|
|
solAssert(false, "visibility() should not return Default");
|
|
|
|
case Declaration::Visibility::Private:
|
|
|
|
case Declaration::Visibility::Internal:
|
|
|
|
case Declaration::Visibility::Public:
|
2019-04-17 11:40:50 +00:00
|
|
|
return TypeProvider::function(*this, _internal);
|
2017-01-10 15:26:13 +00:00
|
|
|
case Declaration::Visibility::External:
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
switch (visibility())
|
|
|
|
{
|
|
|
|
case Declaration::Visibility::Default:
|
|
|
|
solAssert(false, "visibility() should not return Default");
|
|
|
|
case Declaration::Visibility::Private:
|
|
|
|
case Declaration::Visibility::Internal:
|
|
|
|
return {};
|
|
|
|
case Declaration::Visibility::Public:
|
|
|
|
case Declaration::Visibility::External:
|
2019-04-17 11:40:50 +00:00
|
|
|
return TypeProvider::function(*this, _internal);
|
2017-01-10 15:26:13 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// To make the compiler happy
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
|
2015-11-19 17:02:04 +00:00
|
|
|
TypePointer FunctionDefinition::type() const
|
2015-01-22 00:02:38 +00:00
|
|
|
{
|
2017-12-30 12:44:09 +00:00
|
|
|
solAssert(visibility() != Declaration::Visibility::External, "");
|
2019-04-17 11:40:50 +00:00
|
|
|
return TypeProvider::function(*this);
|
2015-01-22 00:02:38 +00:00
|
|
|
}
|
|
|
|
|
2015-03-27 12:28:32 +00:00
|
|
|
string FunctionDefinition::externalSignature() const
|
2015-01-06 16:42:38 +00:00
|
|
|
{
|
2019-04-17 11:40:50 +00:00
|
|
|
return TypeProvider::function(*this)->externalSignature();
|
2015-01-06 16:42:38 +00:00
|
|
|
}
|
|
|
|
|
2015-10-26 14:13:36 +00:00
|
|
|
FunctionDefinitionAnnotation& FunctionDefinition::annotation() const
|
|
|
|
{
|
|
|
|
if (!m_annotation)
|
|
|
|
m_annotation = new FunctionDefinitionAnnotation();
|
2017-03-06 13:00:46 +00:00
|
|
|
return dynamic_cast<FunctionDefinitionAnnotation&>(*m_annotation);
|
2015-10-26 14:13:36 +00:00
|
|
|
}
|
|
|
|
|
2015-11-19 17:02:04 +00:00
|
|
|
TypePointer ModifierDefinition::type() const
|
2015-01-22 00:02:38 +00:00
|
|
|
{
|
2019-04-17 11:40:50 +00:00
|
|
|
return TypeProvider::modifier(*this);
|
2015-02-14 00:22:44 +00:00
|
|
|
}
|
|
|
|
|
2015-10-26 14:13:36 +00:00
|
|
|
ModifierDefinitionAnnotation& ModifierDefinition::annotation() const
|
|
|
|
{
|
|
|
|
if (!m_annotation)
|
|
|
|
m_annotation = new ModifierDefinitionAnnotation();
|
2017-03-06 13:00:46 +00:00
|
|
|
return dynamic_cast<ModifierDefinitionAnnotation&>(*m_annotation);
|
2015-10-26 14:13:36 +00:00
|
|
|
}
|
|
|
|
|
2015-11-19 17:02:04 +00:00
|
|
|
TypePointer EventDefinition::type() const
|
2015-02-17 15:21:38 +00:00
|
|
|
{
|
2019-04-17 11:40:50 +00:00
|
|
|
return TypeProvider::function(*this);
|
2015-09-16 14:56:30 +00:00
|
|
|
}
|
2015-03-08 22:26:36 +00:00
|
|
|
|
2017-12-30 12:44:09 +00:00
|
|
|
FunctionTypePointer EventDefinition::functionType(bool _internal) const
|
2017-01-10 17:55:36 +00:00
|
|
|
{
|
|
|
|
if (_internal)
|
2019-04-17 11:40:50 +00:00
|
|
|
return TypeProvider::function(*this);
|
2017-01-10 17:55:36 +00:00
|
|
|
else
|
2019-04-15 13:33:39 +00:00
|
|
|
return nullptr;
|
2017-01-10 17:55:36 +00:00
|
|
|
}
|
|
|
|
|
2015-10-26 14:13:36 +00:00
|
|
|
EventDefinitionAnnotation& EventDefinition::annotation() const
|
|
|
|
{
|
|
|
|
if (!m_annotation)
|
|
|
|
m_annotation = new EventDefinitionAnnotation();
|
2017-03-06 13:00:46 +00:00
|
|
|
return dynamic_cast<EventDefinitionAnnotation&>(*m_annotation);
|
2015-10-26 14:13:36 +00:00
|
|
|
}
|
|
|
|
|
2015-09-21 16:55:58 +00:00
|
|
|
UserDefinedTypeNameAnnotation& UserDefinedTypeName::annotation() const
|
|
|
|
{
|
|
|
|
if (!m_annotation)
|
|
|
|
m_annotation = new UserDefinedTypeNameAnnotation();
|
2017-03-06 13:00:46 +00:00
|
|
|
return dynamic_cast<UserDefinedTypeNameAnnotation&>(*m_annotation);
|
2015-09-21 16:55:58 +00:00
|
|
|
}
|
|
|
|
|
2018-02-14 00:48:40 +00:00
|
|
|
SourceUnit const& Scopable::sourceUnit() const
|
|
|
|
{
|
|
|
|
ASTNode const* s = scope();
|
|
|
|
solAssert(s, "");
|
2018-08-16 05:42:46 +00:00
|
|
|
// will not always be a declaration
|
2018-02-14 00:48:40 +00:00
|
|
|
while (dynamic_cast<Scopable const*>(s) && dynamic_cast<Scopable const*>(s)->scope())
|
|
|
|
s = dynamic_cast<Scopable const*>(s)->scope();
|
|
|
|
return dynamic_cast<SourceUnit const&>(*s);
|
|
|
|
}
|
|
|
|
|
2019-05-07 09:51:32 +00:00
|
|
|
CallableDeclaration const* Scopable::functionOrModifierDefinition() const
|
|
|
|
{
|
|
|
|
ASTNode const* s = scope();
|
|
|
|
solAssert(s, "");
|
|
|
|
while (dynamic_cast<Scopable const*>(s))
|
|
|
|
{
|
|
|
|
if (auto funDef = dynamic_cast<FunctionDefinition const*>(s))
|
|
|
|
return funDef;
|
|
|
|
if (auto modDef = dynamic_cast<ModifierDefinition const*>(s))
|
|
|
|
return modDef;
|
|
|
|
s = dynamic_cast<Scopable const*>(s)->scope();
|
|
|
|
}
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2018-02-14 00:48:40 +00:00
|
|
|
string Scopable::sourceUnitName() const
|
|
|
|
{
|
|
|
|
return sourceUnit().annotation().path;
|
|
|
|
}
|
|
|
|
|
2015-09-16 14:56:30 +00:00
|
|
|
bool VariableDeclaration::isLValue() const
|
|
|
|
{
|
2019-08-12 15:06:10 +00:00
|
|
|
// Constant declared variables are Read-Only
|
|
|
|
if (m_isConstant)
|
|
|
|
return false;
|
|
|
|
// External function arguments of reference type are Read-Only
|
|
|
|
if (isExternalCallableParameter() && dynamic_cast<ReferenceType const*>(type()))
|
|
|
|
return false;
|
|
|
|
return true;
|
2015-02-17 15:21:38 +00:00
|
|
|
}
|
|
|
|
|
2018-02-09 15:53:52 +00:00
|
|
|
bool VariableDeclaration::isLocalVariable() const
|
|
|
|
{
|
|
|
|
auto s = scope();
|
|
|
|
return
|
2018-08-07 13:58:34 +00:00
|
|
|
dynamic_cast<FunctionTypeName const*>(s) ||
|
2018-02-09 15:53:52 +00:00
|
|
|
dynamic_cast<CallableDeclaration const*>(s) ||
|
|
|
|
dynamic_cast<Block const*>(s) ||
|
2019-09-02 14:17:02 +00:00
|
|
|
dynamic_cast<TryCatchClause const*>(s) ||
|
2018-02-09 15:53:52 +00:00
|
|
|
dynamic_cast<ForStatement const*>(s);
|
|
|
|
}
|
|
|
|
|
2019-09-05 18:02:34 +00:00
|
|
|
bool VariableDeclaration::isCallableOrCatchParameter() const
|
2015-06-05 09:07:50 +00:00
|
|
|
{
|
2019-09-05 18:02:34 +00:00
|
|
|
if (isReturnParameter() || isTryCatchParameter())
|
2018-08-07 13:58:34 +00:00
|
|
|
return true;
|
|
|
|
|
|
|
|
vector<ASTPointer<VariableDeclaration>> const* parameters = nullptr;
|
|
|
|
|
|
|
|
if (auto const* funTypeName = dynamic_cast<FunctionTypeName const*>(scope()))
|
|
|
|
parameters = &funTypeName->parameterTypes();
|
|
|
|
else if (auto const* callable = dynamic_cast<CallableDeclaration const*>(scope()))
|
|
|
|
parameters = &callable->parameters();
|
|
|
|
|
|
|
|
if (parameters)
|
|
|
|
for (auto const& variable: *parameters)
|
2015-06-09 12:26:08 +00:00
|
|
|
if (variable.get() == this)
|
|
|
|
return true;
|
2015-06-05 09:07:50 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2017-07-06 09:05:05 +00:00
|
|
|
bool VariableDeclaration::isLocalOrReturn() const
|
|
|
|
{
|
2019-09-05 18:02:34 +00:00
|
|
|
return isReturnParameter() || (isLocalVariable() && !isCallableOrCatchParameter());
|
2017-07-06 09:05:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool VariableDeclaration::isReturnParameter() const
|
|
|
|
{
|
2018-08-07 13:58:34 +00:00
|
|
|
vector<ASTPointer<VariableDeclaration>> const* returnParameters = nullptr;
|
|
|
|
|
|
|
|
if (auto const* funTypeName = dynamic_cast<FunctionTypeName const*>(scope()))
|
|
|
|
returnParameters = &funTypeName->returnParameterTypes();
|
|
|
|
else if (auto const* callable = dynamic_cast<CallableDeclaration const*>(scope()))
|
|
|
|
if (callable->returnParameterList())
|
|
|
|
returnParameters = &callable->returnParameterList()->parameters();
|
|
|
|
|
|
|
|
if (returnParameters)
|
|
|
|
for (auto const& variable: *returnParameters)
|
2017-07-06 09:05:05 +00:00
|
|
|
if (variable.get() == this)
|
|
|
|
return true;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2019-09-05 18:02:34 +00:00
|
|
|
bool VariableDeclaration::isTryCatchParameter() const
|
|
|
|
{
|
|
|
|
return dynamic_cast<TryCatchClause const*>(scope());
|
|
|
|
}
|
|
|
|
|
2015-06-09 12:26:08 +00:00
|
|
|
bool VariableDeclaration::isExternalCallableParameter() const
|
2015-02-14 00:22:44 +00:00
|
|
|
{
|
2019-09-05 18:02:34 +00:00
|
|
|
if (!isCallableOrCatchParameter())
|
2015-02-14 00:22:44 +00:00
|
|
|
return false;
|
2018-08-07 13:58:34 +00:00
|
|
|
|
|
|
|
if (auto const* callable = dynamic_cast<CallableDeclaration const*>(scope()))
|
|
|
|
if (callable->visibility() == Declaration::Visibility::External)
|
|
|
|
return !isReturnParameter();
|
|
|
|
|
2015-02-14 00:22:44 +00:00
|
|
|
return false;
|
2015-01-22 00:02:38 +00:00
|
|
|
}
|
|
|
|
|
2018-08-07 13:58:34 +00:00
|
|
|
bool VariableDeclaration::isInternalCallableParameter() const
|
|
|
|
{
|
2019-09-05 18:02:34 +00:00
|
|
|
if (!isCallableOrCatchParameter())
|
2018-08-07 13:58:34 +00:00
|
|
|
return false;
|
|
|
|
|
|
|
|
if (auto const* funTypeName = dynamic_cast<FunctionTypeName const*>(scope()))
|
|
|
|
return funTypeName->visibility() == Declaration::Visibility::Internal;
|
|
|
|
else if (auto const* callable = dynamic_cast<CallableDeclaration const*>(scope()))
|
|
|
|
return callable->visibility() <= Declaration::Visibility::Internal;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool VariableDeclaration::isLibraryFunctionParameter() const
|
|
|
|
{
|
2019-09-05 18:02:34 +00:00
|
|
|
if (!isCallableOrCatchParameter())
|
2018-08-07 13:58:34 +00:00
|
|
|
return false;
|
|
|
|
if (auto const* funDef = dynamic_cast<FunctionDefinition const*>(scope()))
|
|
|
|
return dynamic_cast<ContractDefinition const&>(*funDef->scope()).isLibrary();
|
|
|
|
else
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool VariableDeclaration::isEventParameter() const
|
|
|
|
{
|
|
|
|
return dynamic_cast<EventDefinition const*>(scope()) != nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool VariableDeclaration::hasReferenceOrMappingType() const
|
|
|
|
{
|
|
|
|
solAssert(typeName(), "");
|
|
|
|
solAssert(typeName()->annotation().type, "Can only be called after reference resolution");
|
2019-04-15 13:33:39 +00:00
|
|
|
Type const* type = typeName()->annotation().type;
|
|
|
|
return type->category() == Type::Category::Mapping || dynamic_cast<ReferenceType const*>(type);
|
2018-08-07 13:58:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
set<VariableDeclaration::Location> VariableDeclaration::allowedDataLocations() const
|
|
|
|
{
|
|
|
|
using Location = VariableDeclaration::Location;
|
|
|
|
|
|
|
|
if (!hasReferenceOrMappingType() || isStateVariable() || isEventParameter())
|
2018-08-17 23:09:31 +00:00
|
|
|
return set<Location>{ Location::Unspecified };
|
2018-08-07 13:58:34 +00:00
|
|
|
else if (isStateVariable() && isConstant())
|
|
|
|
return set<Location>{ Location::Memory };
|
|
|
|
else if (isExternalCallableParameter())
|
|
|
|
{
|
|
|
|
set<Location> locations{ Location::CallData };
|
|
|
|
if (isLibraryFunctionParameter())
|
|
|
|
locations.insert(Location::Storage);
|
|
|
|
return locations;
|
|
|
|
}
|
2019-09-05 18:02:34 +00:00
|
|
|
else if (isCallableOrCatchParameter())
|
2018-08-07 13:58:34 +00:00
|
|
|
{
|
|
|
|
set<Location> locations{ Location::Memory };
|
2019-09-05 18:02:34 +00:00
|
|
|
if (isInternalCallableParameter() || isLibraryFunctionParameter() || isTryCatchParameter())
|
2018-08-07 13:58:34 +00:00
|
|
|
locations.insert(Location::Storage);
|
|
|
|
return locations;
|
|
|
|
}
|
|
|
|
else if (isLocalVariable())
|
|
|
|
{
|
|
|
|
solAssert(typeName(), "");
|
|
|
|
solAssert(typeName()->annotation().type, "Can only be called after reference resolution");
|
|
|
|
if (typeName()->annotation().type->category() == Type::Category::Mapping)
|
|
|
|
return set<Location>{ Location::Storage };
|
|
|
|
else
|
|
|
|
// TODO: add Location::Calldata once implemented for local variables.
|
|
|
|
return set<Location>{ Location::Memory, Location::Storage };
|
|
|
|
}
|
|
|
|
else
|
|
|
|
// Struct members etc.
|
2018-08-17 23:09:31 +00:00
|
|
|
return set<Location>{ Location::Unspecified };
|
2018-08-07 13:58:34 +00:00
|
|
|
}
|
|
|
|
|
2015-11-19 17:02:04 +00:00
|
|
|
TypePointer VariableDeclaration::type() const
|
2014-10-13 16:22:15 +00:00
|
|
|
{
|
2015-09-16 14:56:30 +00:00
|
|
|
return annotation().type;
|
2014-10-16 12:08:54 +00:00
|
|
|
}
|
2015-09-21 16:55:58 +00:00
|
|
|
|
2017-12-30 12:44:09 +00:00
|
|
|
FunctionTypePointer VariableDeclaration::functionType(bool _internal) const
|
2017-01-10 15:26:13 +00:00
|
|
|
{
|
|
|
|
if (_internal)
|
2019-04-15 13:33:39 +00:00
|
|
|
return nullptr;
|
2017-01-10 15:26:13 +00:00
|
|
|
switch (visibility())
|
|
|
|
{
|
|
|
|
case Declaration::Visibility::Default:
|
|
|
|
solAssert(false, "visibility() should not return Default");
|
|
|
|
case Declaration::Visibility::Private:
|
|
|
|
case Declaration::Visibility::Internal:
|
2019-04-15 13:33:39 +00:00
|
|
|
return nullptr;
|
2017-01-10 15:26:13 +00:00
|
|
|
case Declaration::Visibility::Public:
|
|
|
|
case Declaration::Visibility::External:
|
2019-04-17 11:40:50 +00:00
|
|
|
return TypeProvider::function(*this);
|
2017-01-10 15:26:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// To make the compiler happy
|
2019-04-15 13:33:39 +00:00
|
|
|
return nullptr;
|
2017-01-10 15:26:13 +00:00
|
|
|
}
|
|
|
|
|
2015-09-21 16:55:58 +00:00
|
|
|
VariableDeclarationAnnotation& VariableDeclaration::annotation() const
|
|
|
|
{
|
|
|
|
if (!m_annotation)
|
|
|
|
m_annotation = new VariableDeclarationAnnotation();
|
2017-03-06 13:00:46 +00:00
|
|
|
return dynamic_cast<VariableDeclarationAnnotation&>(*m_annotation);
|
2015-09-21 16:55:58 +00:00
|
|
|
}
|
|
|
|
|
2015-10-26 16:20:29 +00:00
|
|
|
StatementAnnotation& Statement::annotation() const
|
|
|
|
{
|
|
|
|
if (!m_annotation)
|
|
|
|
m_annotation = new StatementAnnotation();
|
2017-03-06 13:00:46 +00:00
|
|
|
return dynamic_cast<StatementAnnotation&>(*m_annotation);
|
2015-10-26 16:20:29 +00:00
|
|
|
}
|
|
|
|
|
2016-03-01 21:56:39 +00:00
|
|
|
InlineAssemblyAnnotation& InlineAssembly::annotation() const
|
|
|
|
{
|
|
|
|
if (!m_annotation)
|
|
|
|
m_annotation = new InlineAssemblyAnnotation();
|
2017-03-06 13:00:46 +00:00
|
|
|
return dynamic_cast<InlineAssemblyAnnotation&>(*m_annotation);
|
2016-03-01 21:56:39 +00:00
|
|
|
}
|
|
|
|
|
2015-09-21 16:55:58 +00:00
|
|
|
ReturnAnnotation& Return::annotation() const
|
|
|
|
{
|
|
|
|
if (!m_annotation)
|
|
|
|
m_annotation = new ReturnAnnotation();
|
2017-03-06 13:00:46 +00:00
|
|
|
return dynamic_cast<ReturnAnnotation&>(*m_annotation);
|
2015-09-21 16:55:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
ExpressionAnnotation& Expression::annotation() const
|
|
|
|
{
|
|
|
|
if (!m_annotation)
|
|
|
|
m_annotation = new ExpressionAnnotation();
|
2017-03-06 13:00:46 +00:00
|
|
|
return dynamic_cast<ExpressionAnnotation&>(*m_annotation);
|
2015-09-21 16:55:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
MemberAccessAnnotation& MemberAccess::annotation() const
|
|
|
|
{
|
|
|
|
if (!m_annotation)
|
|
|
|
m_annotation = new MemberAccessAnnotation();
|
2017-03-06 13:00:46 +00:00
|
|
|
return dynamic_cast<MemberAccessAnnotation&>(*m_annotation);
|
2015-09-21 16:55:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
BinaryOperationAnnotation& BinaryOperation::annotation() const
|
|
|
|
{
|
|
|
|
if (!m_annotation)
|
|
|
|
m_annotation = new BinaryOperationAnnotation();
|
2017-03-06 13:00:46 +00:00
|
|
|
return dynamic_cast<BinaryOperationAnnotation&>(*m_annotation);
|
2015-09-21 16:55:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
FunctionCallAnnotation& FunctionCall::annotation() const
|
|
|
|
{
|
|
|
|
if (!m_annotation)
|
|
|
|
m_annotation = new FunctionCallAnnotation();
|
2017-03-06 13:00:46 +00:00
|
|
|
return dynamic_cast<FunctionCallAnnotation&>(*m_annotation);
|
2015-09-21 16:55:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
IdentifierAnnotation& Identifier::annotation() const
|
|
|
|
{
|
|
|
|
if (!m_annotation)
|
|
|
|
m_annotation = new IdentifierAnnotation();
|
2017-03-06 13:00:46 +00:00
|
|
|
return dynamic_cast<IdentifierAnnotation&>(*m_annotation);
|
2015-09-21 16:55:58 +00:00
|
|
|
}
|
2017-01-24 16:38:06 +00:00
|
|
|
|
2018-10-01 12:36:57 +00:00
|
|
|
ASTString Literal::valueWithoutUnderscores() const
|
|
|
|
{
|
|
|
|
return boost::erase_all_copy(value(), "_");
|
|
|
|
}
|
|
|
|
|
2017-06-28 15:59:34 +00:00
|
|
|
bool Literal::isHexNumber() const
|
2017-06-26 11:49:05 +00:00
|
|
|
{
|
|
|
|
if (token() != Token::Number)
|
|
|
|
return false;
|
2017-06-28 16:00:14 +00:00
|
|
|
return boost::starts_with(value(), "0x");
|
2017-06-26 11:49:05 +00:00
|
|
|
}
|
|
|
|
|
2017-01-24 16:38:06 +00:00
|
|
|
bool Literal::looksLikeAddress() const
|
|
|
|
{
|
|
|
|
if (subDenomination() != SubDenomination::None)
|
|
|
|
return false;
|
2017-06-26 11:49:05 +00:00
|
|
|
|
2017-06-28 15:59:34 +00:00
|
|
|
if (!isHexNumber())
|
2017-06-22 14:39:42 +00:00
|
|
|
return false;
|
2017-01-24 16:38:06 +00:00
|
|
|
|
2018-10-01 12:36:57 +00:00
|
|
|
return abs(int(valueWithoutUnderscores().length()) - 42) <= 1;
|
2017-01-24 16:38:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool Literal::passesAddressChecksum() const
|
|
|
|
{
|
2017-06-28 15:59:34 +00:00
|
|
|
solAssert(isHexNumber(), "Expected hex number");
|
2018-10-01 12:36:57 +00:00
|
|
|
return dev::passesAddressChecksum(valueWithoutUnderscores(), true);
|
2017-01-24 16:38:06 +00:00
|
|
|
}
|
2017-10-05 13:28:25 +00:00
|
|
|
|
2018-08-07 13:58:34 +00:00
|
|
|
string Literal::getChecksummedAddress() const
|
2017-10-05 13:28:25 +00:00
|
|
|
{
|
|
|
|
solAssert(isHexNumber(), "Expected hex number");
|
2017-10-24 10:01:56 +00:00
|
|
|
/// Pad literal to be a proper hex address.
|
2018-10-01 12:36:57 +00:00
|
|
|
string address = valueWithoutUnderscores().substr(2);
|
2017-10-24 10:01:56 +00:00
|
|
|
if (address.length() > 40)
|
2017-10-24 09:54:51 +00:00
|
|
|
return string();
|
2017-10-24 10:01:56 +00:00
|
|
|
address.insert(address.begin(), 40 - address.size(), '0');
|
|
|
|
return dev::getChecksummedAddress(address);
|
2017-10-05 13:28:25 +00:00
|
|
|
}
|