mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Explicit calls to base class function.
This commit is contained in:
parent
4d833bc86b
commit
6e111d5d1d
5
AST.cpp
5
AST.cpp
@ -373,7 +373,8 @@ void MemberAccess::checkTypeRequirements()
|
|||||||
Type const& type = *m_expression->getType();
|
Type const& type = *m_expression->getType();
|
||||||
m_type = type.getMemberType(*m_memberName);
|
m_type = type.getMemberType(*m_memberName);
|
||||||
if (!m_type)
|
if (!m_type)
|
||||||
BOOST_THROW_EXCEPTION(createTypeError("Member \"" + *m_memberName + "\" not found in " + type.toString()));
|
BOOST_THROW_EXCEPTION(createTypeError("Member \"" + *m_memberName + "\" not found or not "
|
||||||
|
"visible in " + type.toString()));
|
||||||
//@todo later, this will not always be STORAGE
|
//@todo later, this will not always be STORAGE
|
||||||
m_lvalue = type.getCategory() == Type::Category::STRUCT ? LValueType::STORAGE : LValueType::NONE;
|
m_lvalue = type.getCategory() == Type::Category::STRUCT ? LValueType::STORAGE : LValueType::NONE;
|
||||||
}
|
}
|
||||||
@ -423,7 +424,7 @@ void Identifier::checkTypeRequirements()
|
|||||||
ContractDefinition const* contractDef = dynamic_cast<ContractDefinition const*>(m_referencedDeclaration);
|
ContractDefinition const* contractDef = dynamic_cast<ContractDefinition const*>(m_referencedDeclaration);
|
||||||
if (contractDef)
|
if (contractDef)
|
||||||
{
|
{
|
||||||
m_type = make_shared<TypeType>(make_shared<ContractType>(*contractDef));
|
m_type = make_shared<TypeType>(make_shared<ContractType>(*contractDef), m_currentContract);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
MagicVariableDeclaration const* magicVariable = dynamic_cast<MagicVariableDeclaration const*>(m_referencedDeclaration);
|
MagicVariableDeclaration const* magicVariable = dynamic_cast<MagicVariableDeclaration const*>(m_referencedDeclaration);
|
||||||
|
19
AST.h
19
AST.h
@ -595,7 +595,7 @@ public:
|
|||||||
virtual void accept(ASTConstVisitor& _visitor) const override;
|
virtual void accept(ASTConstVisitor& _visitor) const override;
|
||||||
virtual void checkTypeRequirements() override;
|
virtual void checkTypeRequirements() override;
|
||||||
|
|
||||||
void setFunctionReturnParameters(ParameterList& _parameters) { m_returnParameters = &_parameters; }
|
void setFunctionReturnParameters(ParameterList const& _parameters) { m_returnParameters = &_parameters; }
|
||||||
ParameterList const& getFunctionReturnParameters() const
|
ParameterList const& getFunctionReturnParameters() const
|
||||||
{
|
{
|
||||||
solAssert(m_returnParameters, "");
|
solAssert(m_returnParameters, "");
|
||||||
@ -607,7 +607,7 @@ private:
|
|||||||
ASTPointer<Expression> m_expression; ///< value to return, optional
|
ASTPointer<Expression> m_expression; ///< value to return, optional
|
||||||
|
|
||||||
/// Pointer to the parameter list of the function, filled by the @ref NameAndTypeResolver.
|
/// Pointer to the parameter list of the function, filled by the @ref NameAndTypeResolver.
|
||||||
ParameterList* m_returnParameters;
|
ParameterList const* m_returnParameters;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -884,21 +884,30 @@ class Identifier: public PrimaryExpression
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Identifier(Location const& _location, ASTPointer<ASTString> const& _name):
|
Identifier(Location const& _location, ASTPointer<ASTString> const& _name):
|
||||||
PrimaryExpression(_location), m_name(_name), m_referencedDeclaration(nullptr) {}
|
PrimaryExpression(_location), m_name(_name) {}
|
||||||
virtual void accept(ASTVisitor& _visitor) override;
|
virtual void accept(ASTVisitor& _visitor) override;
|
||||||
virtual void accept(ASTConstVisitor& _visitor) const override;
|
virtual void accept(ASTConstVisitor& _visitor) const override;
|
||||||
virtual void checkTypeRequirements() override;
|
virtual void checkTypeRequirements() override;
|
||||||
|
|
||||||
ASTString const& getName() const { return *m_name; }
|
ASTString const& getName() const { return *m_name; }
|
||||||
|
|
||||||
void setReferencedDeclaration(Declaration const& _referencedDeclaration) { m_referencedDeclaration = &_referencedDeclaration; }
|
void setReferencedDeclaration(Declaration const& _referencedDeclaration,
|
||||||
|
ContractDefinition const* _currentContract = nullptr)
|
||||||
|
{
|
||||||
|
m_referencedDeclaration = &_referencedDeclaration;
|
||||||
|
m_currentContract = _currentContract;
|
||||||
|
}
|
||||||
Declaration const* getReferencedDeclaration() const { return m_referencedDeclaration; }
|
Declaration const* getReferencedDeclaration() const { return m_referencedDeclaration; }
|
||||||
|
ContractDefinition const* getCurrentContract() const { return m_currentContract; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ASTPointer<ASTString> m_name;
|
ASTPointer<ASTString> m_name;
|
||||||
|
|
||||||
/// Declaration the name refers to.
|
/// Declaration the name refers to.
|
||||||
Declaration const* m_referencedDeclaration;
|
Declaration const* m_referencedDeclaration = nullptr;
|
||||||
|
/// Stores a reference to the current contract. This is needed because types of base contracts
|
||||||
|
/// change depending on the context.
|
||||||
|
ContractDefinition const* m_currentContract = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -419,6 +419,22 @@ void ExpressionCompiler::endVisit(MemberAccess const& _memberAccess)
|
|||||||
m_currentLValue.retrieveValueIfLValueNotRequested(_memberAccess);
|
m_currentLValue.retrieveValueIfLValueNotRequested(_memberAccess);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case Type::Category::TYPE:
|
||||||
|
{
|
||||||
|
TypeType const& type = dynamic_cast<TypeType const&>(*_memberAccess.getExpression().getType());
|
||||||
|
if (type.getMembers().getMemberType(member))
|
||||||
|
{
|
||||||
|
ContractDefinition const& contract = dynamic_cast<ContractType const&>(*type.getActualType())
|
||||||
|
.getContractDefinition();
|
||||||
|
for (ASTPointer<FunctionDefinition> const& function: contract.getDefinedFunctions())
|
||||||
|
if (function->getName() == member)
|
||||||
|
{
|
||||||
|
m_context << m_context.getFunctionEntryLabel(*function).pushTag();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Invalid member access to " + type.toString()));
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Member access to unknown type."));
|
BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Member access to unknown type."));
|
||||||
}
|
}
|
||||||
@ -449,20 +465,22 @@ void ExpressionCompiler::endVisit(Identifier const& _identifier)
|
|||||||
{
|
{
|
||||||
if (magicVar->getType()->getCategory() == Type::Category::CONTRACT) // must be "this"
|
if (magicVar->getType()->getCategory() == Type::Category::CONTRACT) // must be "this"
|
||||||
m_context << eth::Instruction::ADDRESS;
|
m_context << eth::Instruction::ADDRESS;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
if (FunctionDefinition const* functionDef = dynamic_cast<FunctionDefinition const*>(declaration))
|
else if (FunctionDefinition const* functionDef = dynamic_cast<FunctionDefinition const*>(declaration))
|
||||||
{
|
|
||||||
m_context << m_context.getVirtualFunctionEntryLabel(*functionDef).pushTag();
|
m_context << m_context.getVirtualFunctionEntryLabel(*functionDef).pushTag();
|
||||||
return;
|
else if (dynamic_cast<VariableDeclaration const*>(declaration))
|
||||||
}
|
|
||||||
if (dynamic_cast<VariableDeclaration const*>(declaration))
|
|
||||||
{
|
{
|
||||||
m_currentLValue.fromIdentifier(_identifier, *declaration);
|
m_currentLValue.fromIdentifier(_identifier, *declaration);
|
||||||
m_currentLValue.retrieveValueIfLValueNotRequested(_identifier);
|
m_currentLValue.retrieveValueIfLValueNotRequested(_identifier);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Identifier type not expected in expression context."));
|
else if (dynamic_cast<ContractDefinition const*>(declaration))
|
||||||
|
{
|
||||||
|
// no-op
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Identifier type not expected in expression context."));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExpressionCompiler::endVisit(Literal const& _literal)
|
void ExpressionCompiler::endVisit(Literal const& _literal)
|
||||||
|
@ -49,7 +49,7 @@ void NameAndTypeResolver::resolveNamesAndTypes(ContractDefinition& _contract)
|
|||||||
m_currentScope = &m_scopes[nullptr];
|
m_currentScope = &m_scopes[nullptr];
|
||||||
|
|
||||||
for (ASTPointer<Identifier> const& baseContract: _contract.getBaseContracts())
|
for (ASTPointer<Identifier> const& baseContract: _contract.getBaseContracts())
|
||||||
ReferencesResolver resolver(*baseContract, *this, nullptr);
|
ReferencesResolver resolver(*baseContract, *this, &_contract, nullptr);
|
||||||
|
|
||||||
m_currentScope = &m_scopes[&_contract];
|
m_currentScope = &m_scopes[&_contract];
|
||||||
|
|
||||||
@ -58,13 +58,13 @@ void NameAndTypeResolver::resolveNamesAndTypes(ContractDefinition& _contract)
|
|||||||
importInheritedScope(*base);
|
importInheritedScope(*base);
|
||||||
|
|
||||||
for (ASTPointer<StructDefinition> const& structDef: _contract.getDefinedStructs())
|
for (ASTPointer<StructDefinition> const& structDef: _contract.getDefinedStructs())
|
||||||
ReferencesResolver resolver(*structDef, *this, nullptr);
|
ReferencesResolver resolver(*structDef, *this, &_contract, nullptr);
|
||||||
for (ASTPointer<VariableDeclaration> const& variable: _contract.getStateVariables())
|
for (ASTPointer<VariableDeclaration> const& variable: _contract.getStateVariables())
|
||||||
ReferencesResolver resolver(*variable, *this, nullptr);
|
ReferencesResolver resolver(*variable, *this, &_contract, nullptr);
|
||||||
for (ASTPointer<FunctionDefinition> const& function: _contract.getDefinedFunctions())
|
for (ASTPointer<FunctionDefinition> const& function: _contract.getDefinedFunctions())
|
||||||
{
|
{
|
||||||
m_currentScope = &m_scopes[function.get()];
|
m_currentScope = &m_scopes[function.get()];
|
||||||
ReferencesResolver referencesResolver(*function, *this,
|
ReferencesResolver referencesResolver(*function, *this, &_contract,
|
||||||
function->getReturnParameterList().get());
|
function->getReturnParameterList().get());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -267,8 +267,10 @@ void DeclarationRegistrationHelper::registerDeclaration(Declaration& _declaratio
|
|||||||
}
|
}
|
||||||
|
|
||||||
ReferencesResolver::ReferencesResolver(ASTNode& _root, NameAndTypeResolver& _resolver,
|
ReferencesResolver::ReferencesResolver(ASTNode& _root, NameAndTypeResolver& _resolver,
|
||||||
ParameterList* _returnParameters, bool _allowLazyTypes):
|
ContractDefinition const* _currentContract,
|
||||||
m_resolver(_resolver), m_returnParameters(_returnParameters), m_allowLazyTypes(_allowLazyTypes)
|
ParameterList const* _returnParameters, bool _allowLazyTypes):
|
||||||
|
m_resolver(_resolver), m_currentContract(_currentContract),
|
||||||
|
m_returnParameters(_returnParameters), m_allowLazyTypes(_allowLazyTypes)
|
||||||
{
|
{
|
||||||
_root.accept(*this);
|
_root.accept(*this);
|
||||||
}
|
}
|
||||||
@ -316,7 +318,7 @@ bool ReferencesResolver::visit(Identifier& _identifier)
|
|||||||
if (!declaration)
|
if (!declaration)
|
||||||
BOOST_THROW_EXCEPTION(DeclarationError() << errinfo_sourceLocation(_identifier.getLocation())
|
BOOST_THROW_EXCEPTION(DeclarationError() << errinfo_sourceLocation(_identifier.getLocation())
|
||||||
<< errinfo_comment("Undeclared identifier."));
|
<< errinfo_comment("Undeclared identifier."));
|
||||||
_identifier.setReferencedDeclaration(*declaration);
|
_identifier.setReferencedDeclaration(*declaration, m_currentContract);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -120,7 +120,9 @@ class ReferencesResolver: private ASTVisitor
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ReferencesResolver(ASTNode& _root, NameAndTypeResolver& _resolver,
|
ReferencesResolver(ASTNode& _root, NameAndTypeResolver& _resolver,
|
||||||
ParameterList* _returnParameters, bool _allowLazyTypes = true);
|
ContractDefinition const* _currentContract,
|
||||||
|
ParameterList const* _returnParameters,
|
||||||
|
bool _allowLazyTypes = true);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual void endVisit(VariableDeclaration& _variable) override;
|
virtual void endVisit(VariableDeclaration& _variable) override;
|
||||||
@ -130,7 +132,8 @@ private:
|
|||||||
virtual bool visit(Return& _return) override;
|
virtual bool visit(Return& _return) override;
|
||||||
|
|
||||||
NameAndTypeResolver& m_resolver;
|
NameAndTypeResolver& m_resolver;
|
||||||
ParameterList* m_returnParameters;
|
ContractDefinition const* m_currentContract;
|
||||||
|
ParameterList const* m_returnParameters;
|
||||||
bool m_allowLazyTypes;
|
bool m_allowLazyTypes;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
23
Types.cpp
23
Types.cpp
@ -695,6 +695,29 @@ bool TypeType::operator==(Type const& _other) const
|
|||||||
return *getActualType() == *other.getActualType();
|
return *getActualType() == *other.getActualType();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MemberList const& TypeType::getMembers() const
|
||||||
|
{
|
||||||
|
// We need to lazy-initialize it because of recursive references.
|
||||||
|
if (!m_members)
|
||||||
|
{
|
||||||
|
map<string, TypePointer> members;
|
||||||
|
if (m_actualType->getCategory() == Category::CONTRACT && m_currentContract != nullptr)
|
||||||
|
{
|
||||||
|
ContractDefinition const& contract = dynamic_cast<ContractType const&>(*m_actualType).getContractDefinition();
|
||||||
|
vector<ContractDefinition const*> currentBases = m_currentContract->getLinearizedBaseContracts();
|
||||||
|
if (find(currentBases.begin(), currentBases.end(), &contract) != currentBases.end())
|
||||||
|
// We are accessing the type of a base contract, so add all public and private
|
||||||
|
// functions. Note that this does not add inherited functions on purpose.
|
||||||
|
for (ASTPointer<FunctionDefinition> const& f: contract.getDefinedFunctions())
|
||||||
|
if (f->getName() != contract.getName())
|
||||||
|
members[f->getName()] = make_shared<FunctionType>(*f);
|
||||||
|
}
|
||||||
|
m_members.reset(new MemberList(members));
|
||||||
|
}
|
||||||
|
return *m_members;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
MagicType::MagicType(MagicType::Kind _kind):
|
MagicType::MagicType(MagicType::Kind _kind):
|
||||||
m_kind(_kind)
|
m_kind(_kind)
|
||||||
{
|
{
|
||||||
|
8
Types.h
8
Types.h
@ -442,7 +442,8 @@ class TypeType: public Type
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual Category getCategory() const override { return Category::TYPE; }
|
virtual Category getCategory() const override { return Category::TYPE; }
|
||||||
TypeType(TypePointer const& _actualType): m_actualType(_actualType) {}
|
TypeType(TypePointer const& _actualType, ContractDefinition const* _currentContract = nullptr):
|
||||||
|
m_actualType(_actualType), m_currentContract(_currentContract) {}
|
||||||
TypePointer const& getActualType() const { return m_actualType; }
|
TypePointer const& getActualType() const { return m_actualType; }
|
||||||
|
|
||||||
virtual TypePointer binaryOperatorResult(Token::Value, TypePointer const&) const override { return TypePointer(); }
|
virtual TypePointer binaryOperatorResult(Token::Value, TypePointer const&) const override { return TypePointer(); }
|
||||||
@ -451,9 +452,14 @@ public:
|
|||||||
virtual u256 getStorageSize() const override { BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Storage size of non-storable type type requested.")); }
|
virtual u256 getStorageSize() const override { BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Storage size of non-storable type type requested.")); }
|
||||||
virtual bool canLiveOutsideStorage() const override { return false; }
|
virtual bool canLiveOutsideStorage() const override { return false; }
|
||||||
virtual std::string toString() const override { return "type(" + m_actualType->toString() + ")"; }
|
virtual std::string toString() const override { return "type(" + m_actualType->toString() + ")"; }
|
||||||
|
virtual MemberList const& getMembers() const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
TypePointer m_actualType;
|
TypePointer m_actualType;
|
||||||
|
/// Context in which this type is used (influences visibility etc.), can be nullptr.
|
||||||
|
ContractDefinition const* m_currentContract;
|
||||||
|
/// List of member types, will be lazy-initialized because of recursive references.
|
||||||
|
mutable std::unique_ptr<MemberList> m_members;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user