diff options
author | Christian <c@ethdev.com> | 2015-01-20 02:18:34 +0800 |
---|---|---|
committer | Christian <c@ethdev.com> | 2015-01-20 06:35:04 +0800 |
commit | 6e111d5d1da2a0ae397fa2bd846d13132cdd6dd9 (patch) | |
tree | 0cedcacb974cd0d7f15734bccde634e76c47a565 | |
parent | 4d833bc86bf10a685a8b5d72e90c49a24a33f8b3 (diff) | |
download | dexon-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.cpp | 5 | ||||
-rwxr-xr-x | AST.h | 19 | ||||
-rw-r--r-- | ExpressionCompiler.cpp | 34 | ||||
-rw-r--r-- | NameAndTypeResolver.cpp | 16 | ||||
-rw-r--r-- | NameAndTypeResolver.h | 7 | ||||
-rw-r--r-- | Types.cpp | 23 | ||||
-rw-r--r-- | Types.h | 8 |
7 files changed, 87 insertions, 25 deletions
@@ -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); @@ -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; }; @@ -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) { @@ -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; }; |