aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian <c@ethdev.com>2015-01-20 02:18:34 +0800
committerChristian <c@ethdev.com>2015-01-20 06:35:04 +0800
commit6e111d5d1da2a0ae397fa2bd846d13132cdd6dd9 (patch)
tree0cedcacb974cd0d7f15734bccde634e76c47a565
parent4d833bc86bf10a685a8b5d72e90c49a24a33f8b3 (diff)
downloaddexon-solidity-6e111d5d1da2a0ae397fa2bd846d13132cdd6dd9.tar
dexon-solidity-6e111d5d1da2a0ae397fa2bd846d13132cdd6dd9.tar.gz
dexon-solidity-6e111d5d1da2a0ae397fa2bd846d13132cdd6dd9.tar.bz2
dexon-solidity-6e111d5d1da2a0ae397fa2bd846d13132cdd6dd9.tar.lz
dexon-solidity-6e111d5d1da2a0ae397fa2bd846d13132cdd6dd9.tar.xz
dexon-solidity-6e111d5d1da2a0ae397fa2bd846d13132cdd6dd9.tar.zst
dexon-solidity-6e111d5d1da2a0ae397fa2bd846d13132cdd6dd9.zip
Explicit calls to base class function.
-rw-r--r--AST.cpp5
-rwxr-xr-xAST.h19
-rw-r--r--ExpressionCompiler.cpp34
-rw-r--r--NameAndTypeResolver.cpp16
-rw-r--r--NameAndTypeResolver.h7
-rw-r--r--Types.cpp23
-rw-r--r--Types.h8
7 files changed, 87 insertions, 25 deletions
diff --git a/AST.cpp b/AST.cpp
index a529d6df..e0ee5c09 100644
--- a/AST.cpp
+++ b/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);
diff --git a/AST.h b/AST.h
index e8bc7f6a..76bdaebc 100755
--- a/AST.h
+++ b/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;
};
/**
diff --git a/ExpressionCompiler.cpp b/ExpressionCompiler.cpp
index 5a45bfd6..60c5c4de 100644
--- a/ExpressionCompiler.cpp
+++ b/ExpressionCompiler.cpp
@@ -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)
diff --git a/NameAndTypeResolver.cpp b/NameAndTypeResolver.cpp
index 0b6afdd5..f208dc78 100644
--- a/NameAndTypeResolver.cpp
+++ b/NameAndTypeResolver.cpp
@@ -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;
}
diff --git a/NameAndTypeResolver.h b/NameAndTypeResolver.h
index 4fb67da3..f97c7ae5 100644
--- a/NameAndTypeResolver.h
+++ b/NameAndTypeResolver.h
@@ -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;
};
diff --git a/Types.cpp b/Types.cpp
index a99e4853..94fd5750 100644
--- a/Types.cpp
+++ b/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)
{
diff --git a/Types.h b/Types.h
index cb8a8db0..e6c99fe3 100644
--- a/Types.h
+++ b/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;
};