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();
|
||||
m_type = type.getMemberType(*m_memberName);
|
||||
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
|
||||
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);
|
||||
if (contractDef)
|
||||
{
|
||||
m_type = make_shared<TypeType>(make_shared<ContractType>(*contractDef));
|
||||
m_type = make_shared<TypeType>(make_shared<ContractType>(*contractDef), m_currentContract);
|
||||
return;
|
||||
}
|
||||
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 checkTypeRequirements() override;
|
||||
|
||||
void setFunctionReturnParameters(ParameterList& _parameters) { m_returnParameters = &_parameters; }
|
||||
void setFunctionReturnParameters(ParameterList const& _parameters) { m_returnParameters = &_parameters; }
|
||||
ParameterList const& getFunctionReturnParameters() const
|
||||
{
|
||||
solAssert(m_returnParameters, "");
|
||||
@ -607,7 +607,7 @@ private:
|
||||
ASTPointer<Expression> m_expression; ///< value to return, optional
|
||||
|
||||
/// 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:
|
||||
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(ASTConstVisitor& _visitor) const override;
|
||||
virtual void checkTypeRequirements() override;
|
||||
|
||||
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; }
|
||||
ContractDefinition const* getCurrentContract() const { return m_currentContract; }
|
||||
|
||||
private:
|
||||
ASTPointer<ASTString> m_name;
|
||||
|
||||
/// 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);
|
||||
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:
|
||||
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"
|
||||
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();
|
||||
return;
|
||||
}
|
||||
if (dynamic_cast<VariableDeclaration const*>(declaration))
|
||||
else if (dynamic_cast<VariableDeclaration const*>(declaration))
|
||||
{
|
||||
m_currentLValue.fromIdentifier(_identifier, *declaration);
|
||||
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)
|
||||
|
@ -49,7 +49,7 @@ void NameAndTypeResolver::resolveNamesAndTypes(ContractDefinition& _contract)
|
||||
m_currentScope = &m_scopes[nullptr];
|
||||
|
||||
for (ASTPointer<Identifier> const& baseContract: _contract.getBaseContracts())
|
||||
ReferencesResolver resolver(*baseContract, *this, nullptr);
|
||||
ReferencesResolver resolver(*baseContract, *this, &_contract, nullptr);
|
||||
|
||||
m_currentScope = &m_scopes[&_contract];
|
||||
|
||||
@ -58,13 +58,13 @@ void NameAndTypeResolver::resolveNamesAndTypes(ContractDefinition& _contract)
|
||||
importInheritedScope(*base);
|
||||
|
||||
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())
|
||||
ReferencesResolver resolver(*variable, *this, nullptr);
|
||||
ReferencesResolver resolver(*variable, *this, &_contract, nullptr);
|
||||
for (ASTPointer<FunctionDefinition> const& function: _contract.getDefinedFunctions())
|
||||
{
|
||||
m_currentScope = &m_scopes[function.get()];
|
||||
ReferencesResolver referencesResolver(*function, *this,
|
||||
ReferencesResolver referencesResolver(*function, *this, &_contract,
|
||||
function->getReturnParameterList().get());
|
||||
}
|
||||
}
|
||||
@ -267,8 +267,10 @@ void DeclarationRegistrationHelper::registerDeclaration(Declaration& _declaratio
|
||||
}
|
||||
|
||||
ReferencesResolver::ReferencesResolver(ASTNode& _root, NameAndTypeResolver& _resolver,
|
||||
ParameterList* _returnParameters, bool _allowLazyTypes):
|
||||
m_resolver(_resolver), m_returnParameters(_returnParameters), m_allowLazyTypes(_allowLazyTypes)
|
||||
ContractDefinition const* _currentContract,
|
||||
ParameterList const* _returnParameters, bool _allowLazyTypes):
|
||||
m_resolver(_resolver), m_currentContract(_currentContract),
|
||||
m_returnParameters(_returnParameters), m_allowLazyTypes(_allowLazyTypes)
|
||||
{
|
||||
_root.accept(*this);
|
||||
}
|
||||
@ -316,7 +318,7 @@ bool ReferencesResolver::visit(Identifier& _identifier)
|
||||
if (!declaration)
|
||||
BOOST_THROW_EXCEPTION(DeclarationError() << errinfo_sourceLocation(_identifier.getLocation())
|
||||
<< errinfo_comment("Undeclared identifier."));
|
||||
_identifier.setReferencedDeclaration(*declaration);
|
||||
_identifier.setReferencedDeclaration(*declaration, m_currentContract);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -120,7 +120,9 @@ class ReferencesResolver: private ASTVisitor
|
||||
{
|
||||
public:
|
||||
ReferencesResolver(ASTNode& _root, NameAndTypeResolver& _resolver,
|
||||
ParameterList* _returnParameters, bool _allowLazyTypes = true);
|
||||
ContractDefinition const* _currentContract,
|
||||
ParameterList const* _returnParameters,
|
||||
bool _allowLazyTypes = true);
|
||||
|
||||
private:
|
||||
virtual void endVisit(VariableDeclaration& _variable) override;
|
||||
@ -130,7 +132,8 @@ private:
|
||||
virtual bool visit(Return& _return) override;
|
||||
|
||||
NameAndTypeResolver& m_resolver;
|
||||
ParameterList* m_returnParameters;
|
||||
ContractDefinition const* m_currentContract;
|
||||
ParameterList const* m_returnParameters;
|
||||
bool m_allowLazyTypes;
|
||||
};
|
||||
|
||||
|
23
Types.cpp
23
Types.cpp
@ -695,6 +695,29 @@ bool TypeType::operator==(Type const& _other) const
|
||||
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):
|
||||
m_kind(_kind)
|
||||
{
|
||||
|
8
Types.h
8
Types.h
@ -442,7 +442,8 @@ class TypeType: public Type
|
||||
{
|
||||
public:
|
||||
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; }
|
||||
|
||||
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 bool canLiveOutsideStorage() const override { return false; }
|
||||
virtual std::string toString() const override { return "type(" + m_actualType->toString() + ")"; }
|
||||
virtual MemberList const& getMembers() const override;
|
||||
|
||||
private:
|
||||
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