From c3491e446964f366101f28e3d51ab59dd9aaa5b2 Mon Sep 17 00:00:00 2001 From: LianaHus Date: Wed, 14 Oct 2015 20:37:41 +0200 Subject: errors instead of exceptions Conflicts: libsolidity/CompilerStack.cpp libsolidity/NameAndTypeResolver.cpp libsolidity/NameAndTypeResolver.h libsolidity/TypeChecker.cpp test/libsolidity/SolidityNameAndTypeResolution.cpp --- libsolidity/NameAndTypeResolver.cpp | 240 +++++++++++++++++++++++++----------- 1 file changed, 165 insertions(+), 75 deletions(-) (limited to 'libsolidity/NameAndTypeResolver.cpp') diff --git a/libsolidity/NameAndTypeResolver.cpp b/libsolidity/NameAndTypeResolver.cpp index 3591c07a..934be0e3 100644 --- a/libsolidity/NameAndTypeResolver.cpp +++ b/libsolidity/NameAndTypeResolver.cpp @@ -42,81 +42,105 @@ NameAndTypeResolver::NameAndTypeResolver( m_scopes[nullptr].registerDeclaration(*declaration); } -void NameAndTypeResolver::registerDeclarations(SourceUnit& _sourceUnit) +bool NameAndTypeResolver::registerDeclarations(SourceUnit& _sourceUnit) { // The helper registers all declarations in m_scopes as a side-effect of its construction. - DeclarationRegistrationHelper registrar(m_scopes, _sourceUnit); + try + { + DeclarationRegistrationHelper registrar(m_scopes, _sourceUnit, m_errors); + } + catch (fatalError) + { + return false; + } + return true; } -void NameAndTypeResolver::resolveNamesAndTypes(ContractDefinition& _contract) +bool NameAndTypeResolver::resolveNamesAndTypes(ContractDefinition& _contract) { - m_currentScope = &m_scopes[nullptr]; + try + { + m_currentScope = &m_scopes[nullptr]; - for (ASTPointer const& baseContract: _contract.baseContracts()) - ReferencesResolver resolver(*baseContract, *this, &_contract, nullptr); + for (ASTPointer const& baseContract: _contract.baseContracts()) + ReferencesResolver resolver(*baseContract, *this, &_contract, nullptr); - m_currentScope = &m_scopes[&_contract]; + m_currentScope = &m_scopes[&_contract]; - linearizeBaseContracts(_contract); - std::vector properBases( - ++_contract.annotation().linearizedBaseContracts.begin(), - _contract.annotation().linearizedBaseContracts.end() - ); + linearizeBaseContracts(_contract); + std::vector 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 const& structDef: _contract.definedStructs()) - ReferencesResolver resolver(*structDef, *this, &_contract, nullptr); - for (ASTPointer const& enumDef: _contract.definedEnums()) - ReferencesResolver resolver(*enumDef, *this, &_contract, nullptr); - for (ASTPointer const& variable: _contract.stateVariables()) - ReferencesResolver resolver(*variable, *this, &_contract, nullptr); - for (ASTPointer const& event: _contract.events()) - ReferencesResolver resolver(*event, *this, &_contract, nullptr); + for (ASTPointer const& structDef: _contract.definedStructs()) + ReferencesResolver resolver(*structDef, *this, &_contract, nullptr); + for (ASTPointer const& enumDef: _contract.definedEnums()) + ReferencesResolver resolver(*enumDef, *this, &_contract, nullptr); + for (ASTPointer const& variable: _contract.stateVariables()) + ReferencesResolver resolver(*variable, *this, &_contract, nullptr); + for (ASTPointer const& event: _contract.events()) + ReferencesResolver resolver(*event, *this, &_contract, nullptr); - // these can contain code, only resolve parameters for now - for (ASTPointer const& modifier: _contract.functionModifiers()) - { - m_currentScope = &m_scopes[modifier.get()]; - ReferencesResolver resolver(*modifier, *this, &_contract, nullptr); - } - for (ASTPointer const& function: _contract.definedFunctions()) - { - m_currentScope = &m_scopes[function.get()]; - ReferencesResolver referencesResolver( - *function, - *this, - &_contract, - function->returnParameterList().get() - ); - } + // these can contain code, only resolve parameters for now + for (ASTPointer const& modifier: _contract.functionModifiers()) + { + m_currentScope = &m_scopes[modifier.get()]; + ReferencesResolver resolver(*modifier, *this, &_contract, nullptr); + } + for (ASTPointer const& function: _contract.definedFunctions()) + { + m_currentScope = &m_scopes[function.get()]; + ReferencesResolver referencesResolver( + *function, + *this, + &_contract, + function->returnParameterList().get() + ); + } - m_currentScope = &m_scopes[&_contract]; + m_currentScope = &m_scopes[&_contract]; - // now resolve references inside the code - for (ASTPointer const& modifier: _contract.functionModifiers()) - { - m_currentScope = &m_scopes[modifier.get()]; - ReferencesResolver resolver(*modifier, *this, &_contract, nullptr, true); + // now resolve references inside the code + for (ASTPointer const& modifier: _contract.functionModifiers()) + { + m_currentScope = &m_scopes[modifier.get()]; + ReferencesResolver resolver(*modifier, *this, &_contract, nullptr, true); + } + for (ASTPointer const& function: _contract.definedFunctions()) + { + m_currentScope = &m_scopes[function.get()]; + ReferencesResolver referencesResolver( + *function, + *this, + &_contract, + function->returnParameterList().get(), + true + ); + } } - for (ASTPointer const& function: _contract.definedFunctions()) + catch (fatalError const& _e) { - m_currentScope = &m_scopes[function.get()]; - ReferencesResolver referencesResolver( - *function, - *this, - &_contract, - function->returnParameterList().get(), - true - ); + return false; } + return true; } -void NameAndTypeResolver::updateDeclaration(Declaration const& _declaration) +bool NameAndTypeResolver::updateDeclaration(Declaration const& _declaration) { - m_scopes[nullptr].registerDeclaration(_declaration, false, true); - solAssert(_declaration.scope() == nullptr, "Updated declaration outside global scope."); + try + { + m_scopes[nullptr].registerDeclaration(_declaration, false, true); + solAssert(_declaration.scope() == nullptr, "Updated declaration outside global scope."); + } + catch(fatalError _error) + { + return false; + } + return true; } vector NameAndTypeResolver::resolveName(ASTString const& _name, Declaration const* _scope) const @@ -164,11 +188,8 @@ vector NameAndTypeResolver::cleanedDeclarations( FunctionType functionType(functionDefinition); for (auto parameter: functionType.parameterTypes() + functionType.returnParameterTypes()) if (!parameter) - BOOST_THROW_EXCEPTION( - Error(Error::Type::DeclarationError) << - errinfo_sourceLocation(_identifier.location()) << - errinfo_comment("Function type can not be used in this context") - ); + reportFatalDeclarationError(_identifier.location(), "Function type can not be used in this context"); + if (uniqueFunctions.end() == find_if( uniqueFunctions.begin(), uniqueFunctions.end(), @@ -194,7 +215,7 @@ void NameAndTypeResolver::importInheritedScope(ContractDefinition const& _base) m_currentScope->registerDeclaration(*declaration); } -void NameAndTypeResolver::linearizeBaseContracts(ContractDefinition& _contract) const +void NameAndTypeResolver::linearizeBaseContracts(ContractDefinition& _contract) { // order in the lists is from derived to base // list of lists to linearize, the last element is the list of direct bases @@ -204,19 +225,19 @@ void NameAndTypeResolver::linearizeBaseContracts(ContractDefinition& _contract) Identifier const& baseName = baseSpecifier->name(); auto base = dynamic_cast(baseName.annotation().referencedDeclaration); if (!base) - BOOST_THROW_EXCEPTION(baseName.createTypeError("Contract expected.")); + reportFatalTypeError(baseName.createTypeError("Contract expected.")); // "push_front" has the effect that bases mentioned later can overwrite members of bases // mentioned earlier input.back().push_front(base); vector const& basesBases = base->annotation().linearizedBaseContracts; if (basesBases.empty()) - BOOST_THROW_EXCEPTION(baseName.createTypeError("Definition of base has to precede definition of derived contract")); + reportFatalTypeError(baseName.createTypeError("Definition of base has to precede definition of derived contract")); input.push_front(list(basesBases.begin(), basesBases.end())); } input.back().push_front(&_contract); vector result = cThreeMerge(input); if (result.empty()) - BOOST_THROW_EXCEPTION(_contract.createTypeError("Linearization of inheritance graph impossible")); + reportFatalTypeError(_contract.createTypeError("Linearization of inheritance graph impossible")); _contract.annotation().linearizedBaseContracts = result; _contract.annotation().contractDependencies.insert(result.begin() + 1, result.end()); } @@ -272,9 +293,53 @@ vector<_T const*> NameAndTypeResolver::cThreeMerge(list>& _toMer return result; } -DeclarationRegistrationHelper::DeclarationRegistrationHelper(map& _scopes, - ASTNode& _astRoot): - m_scopes(_scopes), m_currentScope(nullptr) +void NameAndTypeResolver::reportDeclarationError( + SourceLocation _sourceLoction, + string const& _description, + SourceLocation _secondarySourceLocation = SourceLocation(), + string const& _secondaryDescription = "" +) +{ + auto err = make_shared(Error::Type::DeclarationError); // todo remove Error? + *err << + errinfo_sourceLocation(_sourceLoction) << + errinfo_comment(_description) << + errinfo_secondarySourceLocation( + SecondarySourceLocation().append(_secondaryDescription, _secondarySourceLocation) + ); + + m_errors.push_back(err); +} + +void NameAndTypeResolver::reportFatalDeclarationError( + SourceLocation _sourceLoction, + string _description +) +{ + reportDeclarationError(_sourceLoction, _description); + BOOST_THROW_EXCEPTION(fatalError()); +} + +void NameAndTypeResolver::reportTypeError(Error _e) +{ + m_errors.push_back(make_shared(_e)); +} + +void NameAndTypeResolver::reportFatalTypeError(Error _e) +{ + reportTypeError(_e); + BOOST_THROW_EXCEPTION(fatalError()); +} + + +DeclarationRegistrationHelper::DeclarationRegistrationHelper( + map& _scopes, + ASTNode& _astRoot, + ErrorList& _errors +): + m_scopes(_scopes), + m_currentScope(nullptr), + m_errors(_errors) { _astRoot.accept(*this); } @@ -409,13 +474,11 @@ void DeclarationRegistrationHelper::registerDeclaration(Declaration& _declaratio secondDeclarationLocation = _declaration.location(); } - BOOST_THROW_EXCEPTION( - Error(Error::Type::DeclarationError) << - errinfo_sourceLocation(secondDeclarationLocation) << - errinfo_comment("Identifier already declared.") << - errinfo_secondarySourceLocation( - SecondarySourceLocation().append("The previous declaration is here:", firstDeclarationLocation) - ) + declarationError( + secondDeclarationLocation, + "Identifier already declared.", + firstDeclarationLocation, + "The previous declaration is here:" ); } @@ -440,5 +503,32 @@ string DeclarationRegistrationHelper::currentCanonicalName() const return ret; } +void DeclarationRegistrationHelper::declarationError( + SourceLocation _sourceLoction, + string const& _description, + SourceLocation _secondarySourceLocation = SourceLocation(), + string const& _secondaryDescription = "" +) +{ + auto err = make_shared(Error::Type::DeclarationError); + *err << + errinfo_sourceLocation(_sourceLoction) << + errinfo_comment(_description) << + errinfo_secondarySourceLocation( + SecondarySourceLocation().append(_secondaryDescription, _secondarySourceLocation) + ); + + m_errors.push_back(err); +} + +void DeclarationRegistrationHelper::fatalDeclarationError( + SourceLocation _sourceLoction, + string const& _description +) +{ + declarationError(_sourceLoction, _description); + BOOST_THROW_EXCEPTION(fatalError()); +} + } } -- cgit