diff options
author | LianaHus <liana@ethdev.com> | 2015-10-27 00:31:35 +0800 |
---|---|---|
committer | LianaHus <liana@ethdev.com> | 2015-11-07 01:45:06 +0800 |
commit | 1a27bf8a39309a1d777276e8a7c3514d80c01a5f (patch) | |
tree | 8f9cc3cce2044f5f6ee94b5770f3dd3e825467fb /libsolidity/analysis | |
parent | 48ffa087837e19fd1cfa006ccb0737f07e735f0b (diff) | |
download | dexon-solidity-1a27bf8a39309a1d777276e8a7c3514d80c01a5f.tar.gz dexon-solidity-1a27bf8a39309a1d777276e8a7c3514d80c01a5f.tar.zst dexon-solidity-1a27bf8a39309a1d777276e8a7c3514d80c01a5f.zip |
added errors tu ReferencesResolver
Diffstat (limited to 'libsolidity/analysis')
-rw-r--r-- | libsolidity/analysis/NameAndTypeResolver.cpp | 45 | ||||
-rw-r--r-- | libsolidity/analysis/ReferencesResolver.cpp | 64 | ||||
-rw-r--r-- | libsolidity/analysis/ReferencesResolver.h | 24 |
3 files changed, 78 insertions, 55 deletions
diff --git a/libsolidity/analysis/NameAndTypeResolver.cpp b/libsolidity/analysis/NameAndTypeResolver.cpp index ffd01137..ca4e5e0f 100644 --- a/libsolidity/analysis/NameAndTypeResolver.cpp +++ b/libsolidity/analysis/NameAndTypeResolver.cpp @@ -64,44 +64,52 @@ bool NameAndTypeResolver::resolveNamesAndTypes(ContractDefinition& _contract) { m_currentScope = &m_scopes[nullptr]; + ReferencesResolver resolver(m_errors, *this, &_contract, nullptr); + bool result = true; for (ASTPointer<InheritanceSpecifier> const& baseContract: _contract.baseContracts()) - ReferencesResolver resolver(*baseContract, *this, &_contract, nullptr); + result = resolver.resolve(*baseContract); m_currentScope = &m_scopes[&_contract]; - linearizeBaseContracts(_contract); - std::vector<ContractDefinition const*> properBases( - ++_contract.annotation().linearizedBaseContracts.begin(), - _contract.annotation().linearizedBaseContracts.end() - ); + if (result) + { + + linearizeBaseContracts(_contract); + std::vector<ContractDefinition const*> properBases( + ++_contract.annotation().linearizedBaseContracts.begin(), + _contract.annotation().linearizedBaseContracts.end() + ); + + for (ContractDefinition const* base: properBases) + importInheritedScope(*base); + } - for (ContractDefinition const* base: properBases) - importInheritedScope(*base); for (ASTPointer<StructDefinition> const& structDef: _contract.definedStructs()) - ReferencesResolver resolver(*structDef, *this, &_contract, nullptr); + result = result && resolver.resolve(*structDef); for (ASTPointer<EnumDefinition> const& enumDef: _contract.definedEnums()) - ReferencesResolver resolver(*enumDef, *this, &_contract, nullptr); + result = result && resolver.resolve(*enumDef); for (ASTPointer<VariableDeclaration> const& variable: _contract.stateVariables()) - ReferencesResolver resolver(*variable, *this, &_contract, nullptr); + result = result && resolver.resolve(*variable); for (ASTPointer<EventDefinition> const& event: _contract.events()) - ReferencesResolver resolver(*event, *this, &_contract, nullptr); - + result = result && resolver.resolve(*event); // these can contain code, only resolve parameters for now for (ASTPointer<ModifierDefinition> const& modifier: _contract.functionModifiers()) { m_currentScope = &m_scopes[modifier.get()]; - ReferencesResolver resolver(*modifier, *this, &_contract, nullptr); + ReferencesResolver resolver(m_errors); + result = result && resolver.resolve(*modifier); } for (ASTPointer<FunctionDefinition> const& function: _contract.definedFunctions()) { m_currentScope = &m_scopes[function.get()]; ReferencesResolver referencesResolver( - *function, + m_errors; *this, &_contract, function->returnParameterList().get() ); + result = result && resolver.resolve(*function); } m_currentScope = &m_scopes[&_contract]; @@ -110,19 +118,22 @@ bool NameAndTypeResolver::resolveNamesAndTypes(ContractDefinition& _contract) for (ASTPointer<ModifierDefinition> const& modifier: _contract.functionModifiers()) { m_currentScope = &m_scopes[modifier.get()]; - ReferencesResolver resolver(*modifier, *this, &_contract, nullptr, true); + ReferencesResolver resolver(m_errors, *this, &_contract, nullptr, true); + result = result && resolver.resolve(*modifier); } for (ASTPointer<FunctionDefinition> const& function: _contract.definedFunctions()) { m_currentScope = &m_scopes[function.get()]; ReferencesResolver referencesResolver( - *function, *this, &_contract, function->returnParameterList().get(), true ); + result = result && resolver.resolve(*function); } + if (!result) + return false; } catch (FatalError const& _e) { diff --git a/libsolidity/analysis/ReferencesResolver.cpp b/libsolidity/analysis/ReferencesResolver.cpp index fb7cdb3e..6ac6c923 100644 --- a/libsolidity/analysis/ReferencesResolver.cpp +++ b/libsolidity/analysis/ReferencesResolver.cpp @@ -31,21 +31,6 @@ using namespace dev; using namespace dev::solidity; -ReferencesResolver::ReferencesResolver( - ASTNode& _root, - NameAndTypeResolver& _resolver, - ContractDefinition const* _currentContract, - ParameterList const* _returnParameters, - bool _resolveInsideCode -): - m_resolver(_resolver), - m_currentContract(_currentContract), - m_returnParameters(_returnParameters), - m_resolveInsideCode(_resolveInsideCode) -{ - _root.accept(*this); -} - bool ReferencesResolver::visit(Return const& _return) { _return.annotation().functionReturnParameters = m_returnParameters; @@ -108,19 +93,19 @@ void ReferencesResolver::endVisit(VariableDeclaration const& _variable) if (contract.isLibrary()) { if (loc == Location::Memory) - BOOST_THROW_EXCEPTION(_variable.createTypeError( + fatalTypeError( "Location has to be calldata or storage for external " "library functions (remove the \"memory\" keyword)." - )); + ); } else { // force location of external function parameters (not return) to calldata if (loc != Location::Default) - BOOST_THROW_EXCEPTION(_variable.createTypeError( + fatalTypeError( "Location has to be calldata for external functions " "(remove the \"memory\" or \"storage\" keyword)." - )); + ); } if (loc == Location::Default) type = ref->copyForLocation(DataLocation::CallData, true); @@ -130,10 +115,10 @@ void ReferencesResolver::endVisit(VariableDeclaration const& _variable) auto const& contract = dynamic_cast<ContractDefinition const&>(*_variable.scope()->scope()); // force locations of public or external function (return) parameters to memory if (loc == Location::Storage && !contract.isLibrary()) - BOOST_THROW_EXCEPTION(_variable.createTypeError( + fatalTypeError( "Location has to be memory for publicly visible functions " "(remove the \"storage\" keyword)." - )); + ); if (loc == Location::Default || !contract.isLibrary()) type = ref->copyForLocation(DataLocation::Memory, true); } @@ -142,9 +127,7 @@ void ReferencesResolver::endVisit(VariableDeclaration const& _variable) if (_variable.isConstant()) { if (loc != Location::Default && loc != Location::Memory) - BOOST_THROW_EXCEPTION(_variable.createTypeError( - "Storage location has to be \"memory\" (or unspecified) for constants." - )); + fatalTypeError("Storage location has to be \"memory\" (or unspecified) for constants."); loc = Location::Memory; } if (loc == Location::Default) @@ -159,16 +142,14 @@ void ReferencesResolver::endVisit(VariableDeclaration const& _variable) } } else if (loc != Location::Default && !ref) - BOOST_THROW_EXCEPTION(_variable.createTypeError( - "Storage location can only be given for array or struct types." - )); + fatalTypeError("Storage location can only be given for array or struct types."); if (!type) - BOOST_THROW_EXCEPTION(_variable.typeName()->createTypeError("Invalid type name.")); + fatalTypeError("Invalid type name."); } else if (!_variable.canHaveAutoType()) - BOOST_THROW_EXCEPTION(_variable.createTypeError("Explicit type needed.")); + fatalTypeError("Explicit type needed."); // otherwise we have a "var"-declaration whose type is resolved by the first assignment _variable.annotation().type = type; @@ -194,9 +175,7 @@ TypePointer ReferencesResolver::typeFor(TypeName const& _typeName) else if (ContractDefinition const* contract = dynamic_cast<ContractDefinition const*>(declaration)) type = make_shared<ContractType>(*contract); else - BOOST_THROW_EXCEPTION(typeName->createTypeError( - "Name has to refer to a struct, enum or contract." - )); + fatalTypeError("Name has to refer to a struct, enum or contract."); } else if (auto mapping = dynamic_cast<Mapping const*>(&_typeName)) { @@ -212,9 +191,7 @@ TypePointer ReferencesResolver::typeFor(TypeName const& _typeName) { TypePointer baseType = typeFor(arrayType->baseType()); if (baseType->storageBytes() == 0) - BOOST_THROW_EXCEPTION(arrayType->baseType().createTypeError( - "Illegal base type of storage size zero for array." - )); + fatalTypeError("Illegal base type of storage size zero for array."); if (Expression const* length = arrayType->length()) { if (!length->annotation().type) @@ -222,7 +199,7 @@ TypePointer ReferencesResolver::typeFor(TypeName const& _typeName) auto const* lengthType = dynamic_cast<IntegerConstantType const*>(length->annotation().type.get()); if (!lengthType) - BOOST_THROW_EXCEPTION(length->createTypeError("Invalid array length.")); + fatalTypeError("Invalid array length."); type = make_shared<ArrayType>(DataLocation::Storage, baseType, lengthType->literalValue(nullptr)); } else @@ -232,3 +209,18 @@ TypePointer ReferencesResolver::typeFor(TypeName const& _typeName) return _typeName.annotation().type = move(type); } +void ReferencesResolver::typeError(string const& _description) +{ + auto err = make_shared<Error>(Error::Type::TypeError); + *err << errinfo_comment(_description); + + m_errors.push_back(err); +} + +void ReferencesResolver::fatalTypeError(string const& _description) +{ + typeError(_description); + BOOST_THROW_EXCEPTION(FatalError()); +} + + diff --git a/libsolidity/analysis/ReferencesResolver.h b/libsolidity/analysis/ReferencesResolver.h index 4276adaa..13d5a47a 100644 --- a/libsolidity/analysis/ReferencesResolver.h +++ b/libsolidity/analysis/ReferencesResolver.h @@ -43,12 +43,25 @@ class ReferencesResolver: private ASTConstVisitor { public: ReferencesResolver( - ASTNode& _root, + ErrorList& _errors, NameAndTypeResolver& _resolver, ContractDefinition const* _currentContract, ParameterList const* _returnParameters, bool _resolveInsideCode = false - ); + ): + m_errors(_errors), + m_resolver(_resolver), + m_currentContract(_currentContract), + m_returnParameters(_returnParameters), + m_resolveInsideCode(_resolveInsideCode) + {} + + /// @returns true if no errors during resolving + bool resolve(ASTNode& _root) + { + _root.accept(*this); + return m_errors.empty(); + } private: virtual bool visit(Block const&) override { return m_resolveInsideCode; } @@ -59,6 +72,13 @@ private: TypePointer typeFor(TypeName const& _typeName); + /// Adds a new error to the list of errors. + void typeError(std::string const& _description); + + /// Adds a new error to the list of errors and throws to abort type checking. + void fatalTypeError(std::string const& _description); + + ErrorList& m_errors; NameAndTypeResolver& m_resolver; ContractDefinition const* m_currentContract; ParameterList const* m_returnParameters; |