From 742002b05ade24c7e5399b3f6d9e36e090385681 Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Fri, 20 Mar 2015 17:50:26 +0100 Subject: [PATCH 1/6] Parsing of not fully implemented functions - Adding the possibility of omitting a function body by simply ending a function definition with a semicolon - Such a function is marked as not fully implemented and any contract that contains such a function is considered a not fully implemented contract --- libsolidity/AST.cpp | 4 +- libsolidity/AST.h | 85 +++++++++++++++++--------- libsolidity/AST_accept.h | 6 +- libsolidity/Parser.cpp | 33 ++++++++-- test/SolidityNameAndTypeResolution.cpp | 15 +++++ test/SolidityParser.cpp | 8 +++ 6 files changed, 112 insertions(+), 39 deletions(-) diff --git a/libsolidity/AST.cpp b/libsolidity/AST.cpp index d05eaf83e..71af3286f 100644 --- a/libsolidity/AST.cpp +++ b/libsolidity/AST.cpp @@ -311,8 +311,8 @@ void FunctionDefinition::checkTypeRequirements() modifier->checkTypeRequirements(isConstructor() ? dynamic_cast(*getScope()).getBaseContracts() : vector>()); - - m_body->checkTypeRequirements(); + if (m_body) + m_body->checkTypeRequirements(); } string FunctionDefinition::getCanonicalSignature() const diff --git a/libsolidity/AST.h b/libsolidity/AST.h index 335b9a880..fa0172b10 100644 --- a/libsolidity/AST.h +++ b/libsolidity/AST.h @@ -196,6 +196,21 @@ protected: ASTPointer m_documentation; }; +/** + * Abstract class that is added to AST nodes that can be marked as not being fully implemented + */ +class ImplementationOptional +{ +public: + explicit ImplementationOptional(bool _implemented): m_implemented(_implemented) {} + + /// @return whether this node is fully implemented or not + bool isFullyImplemented() const { return m_implemented; } + +protected: + bool m_implemented; +}; + /// @} /** @@ -203,20 +218,25 @@ protected: * document order. It first visits all struct declarations, then all variable declarations and * finally all function declarations. */ -class ContractDefinition: public Declaration, public Documented +class ContractDefinition: public Declaration, public Documented, public ImplementationOptional { public: - ContractDefinition(SourceLocation const& _location, - ASTPointer const& _name, - ASTPointer const& _documentation, - std::vector> const& _baseContracts, - std::vector> const& _definedStructs, - std::vector> const& _definedEnums, - std::vector> const& _stateVariables, - std::vector> const& _definedFunctions, - std::vector> const& _functionModifiers, - std::vector> const& _events): - Declaration(_location, _name), Documented(_documentation), + ContractDefinition( + SourceLocation const& _location, + ASTPointer const& _name, + ASTPointer const& _documentation, + std::vector> const& _baseContracts, + std::vector> const& _definedStructs, + std::vector> const& _definedEnums, + std::vector> const& _stateVariables, + std::vector> const& _definedFunctions, + std::vector> const& _functionModifiers, + std::vector> const& _events, + bool _isFullyImplemented + ): + Declaration(_location, _name), + Documented(_documentation), + ImplementationOptional(_isFullyImplemented), m_baseContracts(_baseContracts), m_definedStructs(_definedStructs), m_definedEnums(_definedEnums), @@ -224,7 +244,7 @@ public: m_definedFunctions(_definedFunctions), m_functionModifiers(_functionModifiers), m_events(_events) - {} + {} virtual void accept(ASTVisitor& _visitor) override; virtual void accept(ASTConstVisitor& _visitor) const override; @@ -378,25 +398,30 @@ private: std::vector> m_parameters; }; -class FunctionDefinition: public Declaration, public VariableScope, public Documented +class FunctionDefinition: public Declaration, public VariableScope, public Documented, public ImplementationOptional { public: - FunctionDefinition(SourceLocation const& _location, ASTPointer const& _name, - Declaration::Visibility _visibility, bool _isConstructor, - ASTPointer const& _documentation, - ASTPointer const& _parameters, - bool _isDeclaredConst, - std::vector> const& _modifiers, - ASTPointer const& _returnParameters, - ASTPointer const& _body): - Declaration(_location, _name, _visibility), Documented(_documentation), - m_isConstructor(_isConstructor), - m_parameters(_parameters), - m_isDeclaredConst(_isDeclaredConst), - m_functionModifiers(_modifiers), - m_returnParameters(_returnParameters), - m_body(_body) - {} + FunctionDefinition( + SourceLocation const& _location, + ASTPointer const& _name, + Declaration::Visibility _visibility, bool _isConstructor, + ASTPointer const& _documentation, + ASTPointer const& _parameters, + bool _isDeclaredConst, + std::vector> const& _modifiers, + ASTPointer const& _returnParameters, + ASTPointer const& _body + ): + Declaration(_location, _name, _visibility), + Documented(_documentation), + ImplementationOptional(_body != nullptr), + m_isConstructor(_isConstructor), + m_parameters(_parameters), + m_isDeclaredConst(_isDeclaredConst), + m_functionModifiers(_modifiers), + m_returnParameters(_returnParameters), + m_body(_body) + {} virtual void accept(ASTVisitor& _visitor) override; virtual void accept(ASTConstVisitor& _visitor) const override; diff --git a/libsolidity/AST_accept.h b/libsolidity/AST_accept.h index 81ede8fc9..3557f8779 100644 --- a/libsolidity/AST_accept.h +++ b/libsolidity/AST_accept.h @@ -175,7 +175,8 @@ void FunctionDefinition::accept(ASTVisitor& _visitor) if (m_returnParameters) m_returnParameters->accept(_visitor); listAccept(m_functionModifiers, _visitor); - m_body->accept(_visitor); + if (m_body) + m_body->accept(_visitor); } _visitor.endVisit(*this); } @@ -188,7 +189,8 @@ void FunctionDefinition::accept(ASTConstVisitor& _visitor) const if (m_returnParameters) m_returnParameters->accept(_visitor); listAccept(m_functionModifiers, _visitor); - m_body->accept(_visitor); + if (m_body) + m_body->accept(_visitor); } _visitor.endVisit(*this); } diff --git a/libsolidity/Parser.cpp b/libsolidity/Parser.cpp index 393d2734e..3dfedf6d2 100644 --- a/libsolidity/Parser.cpp +++ b/libsolidity/Parser.cpp @@ -116,6 +116,7 @@ ASTPointer Parser::parseContractDefinition() { ASTNodeFactory nodeFactory(*this); ASTPointer docString; + bool contractFullyImplemented = true; if (m_scanner->getCurrentCommentLiteral() != "") docString = make_shared(m_scanner->getCurrentCommentLiteral()); expectToken(Token::Contract); @@ -141,7 +142,12 @@ ASTPointer Parser::parseContractDefinition() if (currentToken == Token::RBrace) break; else if (currentToken == Token::Function) - functions.push_back(parseFunctionDefinition(name.get())); + { + ASTPointer func = parseFunctionDefinition(name.get()); + functions.push_back(func); + if (!func->isFullyImplemented()) + contractFullyImplemented = false; + } else if (currentToken == Token::Struct) structs.push_back(parseStructDefinition()); else if (currentToken == Token::Enum) @@ -164,8 +170,18 @@ ASTPointer Parser::parseContractDefinition() } nodeFactory.markEndPosition(); expectToken(Token::RBrace); - return nodeFactory.createNode(name, docString, baseContracts, structs, enums, - stateVariables, functions, modifiers, events); + return nodeFactory.createNode( + name, + docString, + baseContracts, + structs, + enums, + stateVariables, + functions, + modifiers, + events, + contractFullyImplemented + ); } ASTPointer Parser::parseInheritanceSpecifier() @@ -247,8 +263,15 @@ ASTPointer Parser::parseFunctionDefinition(ASTString const* } else returnParameters = createEmptyParameterList(); - ASTPointer block = parseBlock(); - nodeFactory.setEndPositionFromNode(block); + ASTPointer block = ASTPointer(); + nodeFactory.markEndPosition(); + if (m_scanner->getCurrentToken() != Token::Semicolon) + { + block = parseBlock(); + nodeFactory.setEndPositionFromNode(block); + } + else + m_scanner->next(); // just consume the ';' bool const c_isConstructor = (_contractName && *name == *_contractName); return nodeFactory.createNode(name, visibility, c_isConstructor, docstring, parameters, isDeclaredConst, modifiers, diff --git a/test/SolidityNameAndTypeResolution.cpp b/test/SolidityNameAndTypeResolution.cpp index 591cf053a..3c088358c 100644 --- a/test/SolidityNameAndTypeResolution.cpp +++ b/test/SolidityNameAndTypeResolution.cpp @@ -346,6 +346,21 @@ BOOST_AUTO_TEST_CASE(comparison_bitop_precedence) ETH_TEST_CHECK_NO_THROW(parseTextAndResolveNames(text), "Parsing and Name Resolving Failed"); } +BOOST_AUTO_TEST_CASE(function_no_implementation) +{ + ASTPointer sourceUnit; + char const* text = "contract test {\n" + " function functionName(bytes32 input) returns (bytes32 out);\n" + "}\n"; + ETH_TEST_REQUIRE_NO_THROW(sourceUnit = parseTextAndResolveNames(text), "Parsing and name Resolving failed"); + ContractDefinition* contract; + for (ASTPointer const& node: sourceUnit->getNodes()) + contract = dynamic_cast(node.get()); + BOOST_CHECK(contract); + BOOST_CHECK(!contract->isFullyImplemented()); + BOOST_CHECK(!contract->getDefinedFunctions()[0]->isFullyImplemented()); +} + BOOST_AUTO_TEST_CASE(function_canonical_signature) { ASTPointer sourceUnit; diff --git a/test/SolidityParser.cpp b/test/SolidityParser.cpp index 392d9ac47..7640f91ad 100644 --- a/test/SolidityParser.cpp +++ b/test/SolidityParser.cpp @@ -108,6 +108,14 @@ BOOST_AUTO_TEST_CASE(single_function_param) ETH_TEST_CHECK_NO_THROW(parseText(text), "Parsing failed."); } +BOOST_AUTO_TEST_CASE(function_no_body) +{ + char const* text = "contract test {\n" + " function functionName(bytes32 input) returns (bytes32 out);\n" + "}\n"; + ETH_TEST_CHECK_NO_THROW(parseText(text), "Parsing failed."); +} + BOOST_AUTO_TEST_CASE(missing_parameter_name_in_named_args) { char const* text = "contract test {\n" From 4e234b30ed06bff60afda479eaf9190fe11bc27c Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Fri, 27 Mar 2015 11:53:17 +0100 Subject: [PATCH 2/6] Moving contract fullyImplemented check to TypeRequirements --- libsolidity/AST.cpp | 4 ++++ libsolidity/AST.h | 10 +++++----- libsolidity/Parser.cpp | 6 +----- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/libsolidity/AST.cpp b/libsolidity/AST.cpp index 71af3286f..52c58170d 100644 --- a/libsolidity/AST.cpp +++ b/libsolidity/AST.cpp @@ -60,6 +60,7 @@ void ContractDefinition::checkTypeRequirements() FunctionDefinition const* fallbackFunction = nullptr; for (ASTPointer const& function: getDefinedFunctions()) + { if (function->getName().empty()) { if (fallbackFunction) @@ -71,6 +72,9 @@ void ContractDefinition::checkTypeRequirements() BOOST_THROW_EXCEPTION(fallbackFunction->getParameterList().createTypeError("Fallback function cannot take parameters.")); } } + if (!function->isFullyImplemented()) + setFullyImplemented(false); + } for (ASTPointer const& modifier: getFunctionModifiers()) modifier->checkTypeRequirements(); diff --git a/libsolidity/AST.h b/libsolidity/AST.h index fa0172b10..c1da90cdb 100644 --- a/libsolidity/AST.h +++ b/libsolidity/AST.h @@ -206,6 +206,7 @@ public: /// @return whether this node is fully implemented or not bool isFullyImplemented() const { return m_implemented; } + void setFullyImplemented(bool _implemented) { m_implemented = _implemented; } protected: bool m_implemented; @@ -231,12 +232,11 @@ public: std::vector> const& _stateVariables, std::vector> const& _definedFunctions, std::vector> const& _functionModifiers, - std::vector> const& _events, - bool _isFullyImplemented + std::vector> const& _events ): Declaration(_location, _name), Documented(_documentation), - ImplementationOptional(_isFullyImplemented), + ImplementationOptional(true), m_baseContracts(_baseContracts), m_definedStructs(_definedStructs), m_definedEnums(_definedEnums), @@ -244,7 +244,7 @@ public: m_definedFunctions(_definedFunctions), m_functionModifiers(_functionModifiers), m_events(_events) - {} + {} virtual void accept(ASTVisitor& _visitor) override; virtual void accept(ASTConstVisitor& _visitor) const override; @@ -421,7 +421,7 @@ public: m_functionModifiers(_modifiers), m_returnParameters(_returnParameters), m_body(_body) - {} + {} virtual void accept(ASTVisitor& _visitor) override; virtual void accept(ASTConstVisitor& _visitor) const override; diff --git a/libsolidity/Parser.cpp b/libsolidity/Parser.cpp index 3dfedf6d2..0f1b34069 100644 --- a/libsolidity/Parser.cpp +++ b/libsolidity/Parser.cpp @@ -116,7 +116,6 @@ ASTPointer Parser::parseContractDefinition() { ASTNodeFactory nodeFactory(*this); ASTPointer docString; - bool contractFullyImplemented = true; if (m_scanner->getCurrentCommentLiteral() != "") docString = make_shared(m_scanner->getCurrentCommentLiteral()); expectToken(Token::Contract); @@ -145,8 +144,6 @@ ASTPointer Parser::parseContractDefinition() { ASTPointer func = parseFunctionDefinition(name.get()); functions.push_back(func); - if (!func->isFullyImplemented()) - contractFullyImplemented = false; } else if (currentToken == Token::Struct) structs.push_back(parseStructDefinition()); @@ -179,8 +176,7 @@ ASTPointer Parser::parseContractDefinition() stateVariables, functions, modifiers, - events, - contractFullyImplemented + events ); } From dfcaf8a414ed78f4d4a92aea67e181f2030a6f24 Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Fri, 27 Mar 2015 15:15:34 +0100 Subject: [PATCH 3/6] Abstract contract and inheritance - Checking the linearized base contracts for abstract functions and handle their existence appropriately - If a contract is abstract it can't be created with new - An abstract contract is not compiled (no backend code is generated) - Of course tests --- libsolidity/AST.cpp | 40 +++++++++++++++++++++ libsolidity/AST.h | 1 + libsolidity/CompilerStack.cpp | 2 ++ libsolidity/Parser.cpp | 5 +-- test/SolidityNameAndTypeResolution.cpp | 48 ++++++++++++++++++++++++-- 5 files changed, 89 insertions(+), 7 deletions(-) diff --git a/libsolidity/AST.cpp b/libsolidity/AST.cpp index 52c58170d..2ada73627 100644 --- a/libsolidity/AST.cpp +++ b/libsolidity/AST.cpp @@ -21,6 +21,7 @@ */ #include +#include #include #include #include @@ -52,6 +53,7 @@ void ContractDefinition::checkTypeRequirements() baseSpecifier->checkTypeRequirements(); checkIllegalOverrides(); + checkAbstractFunctions(); FunctionDefinition const* constructor = getConstructor(); if (constructor && !constructor->getReturnParameters().empty()) @@ -128,6 +130,42 @@ FunctionDefinition const* ContractDefinition::getFallbackFunction() const return nullptr; } +void ContractDefinition::checkAbstractFunctions() +{ + map functions; + + // Search from base to derived + for (ContractDefinition const* contract: boost::adaptors::reverse(getLinearizedBaseContracts())) + { + for (ASTPointer const& function: contract->getDefinedFunctions()) + { + string const& name = function->getName(); + if (!function->isFullyImplemented() && functions.count(name) && functions[name]) + BOOST_THROW_EXCEPTION(function->createTypeError("Redeclaring an already implemented function as abstract")); + // if (functions.count(name) && !functions[name] && function->isFullyImplemented()) + // functions.insert(make_pair(name, true); + + // if (functions.count(name) && !functions[name] && function->isFullyImplemented) + // functions.insert(make_pair(name, true)); + + // functions.insert(make_pair(name, function->isFullyImplemented())); + functions[name] = function->isFullyImplemented(); + + // if (function->isFullyImplemented()) + // full_functions.insert(make_pair(name, function.get())); + // else + // abs_functions.insert(make_pair(name, function.get())); + } + } + for (auto const& it: functions) + if (!it.second) + { + setFullyImplemented(false); + break; + } + +} + void ContractDefinition::checkIllegalOverrides() const { // TODO unify this at a later point. for this we need to put the constness and the access specifier @@ -643,6 +681,8 @@ void NewExpression::checkTypeRequirements() m_contract = dynamic_cast(m_contractName->getReferencedDeclaration()); if (!m_contract) BOOST_THROW_EXCEPTION(createTypeError("Identifier is not a contract.")); + if (!m_contract->isFullyImplemented()) + BOOST_THROW_EXCEPTION(m_contract->createTypeError("Trying to create an object of an abstract contract.")); shared_ptr contractType = make_shared(*m_contract); TypePointers const& parameterTypes = contractType->getConstructorType()->getParameterTypes(); m_type = make_shared(parameterTypes, TypePointers{contractType}, diff --git a/libsolidity/AST.h b/libsolidity/AST.h index c1da90cdb..8570e7bd9 100644 --- a/libsolidity/AST.h +++ b/libsolidity/AST.h @@ -283,6 +283,7 @@ public: private: void checkIllegalOverrides() const; + void checkAbstractFunctions(); std::vector, FunctionTypePointer>> const& getInterfaceFunctionList() const; diff --git a/libsolidity/CompilerStack.cpp b/libsolidity/CompilerStack.cpp index 55ec0cb59..1301bfa5d 100644 --- a/libsolidity/CompilerStack.cpp +++ b/libsolidity/CompilerStack.cpp @@ -138,6 +138,8 @@ void CompilerStack::compile(bool _optimize) for (ASTPointer const& node: source->ast->getNodes()) if (ContractDefinition* contract = dynamic_cast(node.get())) { + if (!contract->isFullyImplemented()) + continue; shared_ptr compiler = make_shared(_optimize); compiler->compileContract(*contract, contractBytecode); Contract& compiledContract = m_contracts[contract->getName()]; diff --git a/libsolidity/Parser.cpp b/libsolidity/Parser.cpp index 0f1b34069..5c7676df5 100644 --- a/libsolidity/Parser.cpp +++ b/libsolidity/Parser.cpp @@ -141,10 +141,7 @@ ASTPointer Parser::parseContractDefinition() if (currentToken == Token::RBrace) break; else if (currentToken == Token::Function) - { - ASTPointer func = parseFunctionDefinition(name.get()); - functions.push_back(func); - } + functions.push_back(parseFunctionDefinition(name.get())); else if (currentToken == Token::Struct) structs.push_back(parseStructDefinition()); else if (currentToken == Token::Enum) diff --git a/test/SolidityNameAndTypeResolution.cpp b/test/SolidityNameAndTypeResolution.cpp index 3c088358c..8eb83b117 100644 --- a/test/SolidityNameAndTypeResolution.cpp +++ b/test/SolidityNameAndTypeResolution.cpp @@ -353,14 +353,56 @@ BOOST_AUTO_TEST_CASE(function_no_implementation) " function functionName(bytes32 input) returns (bytes32 out);\n" "}\n"; ETH_TEST_REQUIRE_NO_THROW(sourceUnit = parseTextAndResolveNames(text), "Parsing and name Resolving failed"); - ContractDefinition* contract; - for (ASTPointer const& node: sourceUnit->getNodes()) - contract = dynamic_cast(node.get()); + std::vector> nodes = sourceUnit->getNodes(); + ContractDefinition* contract = dynamic_cast(nodes[0].get()); BOOST_CHECK(contract); BOOST_CHECK(!contract->isFullyImplemented()); BOOST_CHECK(!contract->getDefinedFunctions()[0]->isFullyImplemented()); } +BOOST_AUTO_TEST_CASE(abstract_contract) +{ + ASTPointer sourceUnit; + char const* text = R"( + contract base { function foo(); } + contract derived is base { function foo() {} } + )"; + ETH_TEST_REQUIRE_NO_THROW(sourceUnit = parseTextAndResolveNames(text), "Parsing and name Resolving failed"); + std::vector> nodes = sourceUnit->getNodes(); + ContractDefinition* base = dynamic_cast(nodes[0].get()); + ContractDefinition* derived = dynamic_cast(nodes[1].get()); + BOOST_CHECK(base); + BOOST_CHECK(!base->isFullyImplemented()); + BOOST_CHECK(!base->getDefinedFunctions()[0]->isFullyImplemented()); + BOOST_CHECK(derived); + BOOST_CHECK(derived->isFullyImplemented()); + BOOST_CHECK(derived->getDefinedFunctions()[0]->isFullyImplemented()); +} + +BOOST_AUTO_TEST_CASE(create_abstract_contract) +{ + ASTPointer sourceUnit; + char const* text = R"( + contract base { function foo(); } + contract derived { + base b; + function foo() { b = new base();} + } + )"; + BOOST_CHECK_THROW(parseTextAndResolveNames(text), TypeError); +} + +BOOST_AUTO_TEST_CASE(redeclare_implemented_abstract_function_as_abstract) +{ + ASTPointer sourceUnit; + char const* text = R"( + contract base { function foo(); } + contract derived is base { function foo() {} } + contract wrong is derived { function foo(); } + )"; + BOOST_CHECK_THROW(parseTextAndResolveNames(text), TypeError); +} + BOOST_AUTO_TEST_CASE(function_canonical_signature) { ASTPointer sourceUnit; From 04d0415e52de572b34cea5be19f85ce6e3b0e987 Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Mon, 30 Mar 2015 15:14:59 +0200 Subject: [PATCH 4/6] Detect if non-existant parameter is documented with natspec --- libsolidity/InterfaceHandler.cpp | 9 +++++++++ test/SolidityNatspecJSON.cpp | 13 ++++++++++++- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/libsolidity/InterfaceHandler.cpp b/libsolidity/InterfaceHandler.cpp index 2f35a96f6..aacbbfd72 100644 --- a/libsolidity/InterfaceHandler.cpp +++ b/libsolidity/InterfaceHandler.cpp @@ -175,8 +175,17 @@ std::unique_ptr InterfaceHandler::getDevDocumentation(ContractDefin method["author"] = m_author; Json::Value params(Json::objectValue); + std::vector paramNames = it.second->getParameterNames(); for (auto const& pair: m_params) + { + if (find(paramNames.begin(), paramNames.end(), pair.first) == paramNames.end()) + // LTODO: mismatching parameter name, throw some form of warning and not just an exception + BOOST_THROW_EXCEPTION( + DocstringParsingError() << + errinfo_comment("documented parameter \"" + pair.first + "\" not found found in the function") + ); params[pair.first] = pair.second; + } if (!m_params.empty()) method["params"] = params; diff --git a/test/SolidityNatspecJSON.cpp b/test/SolidityNatspecJSON.cpp index edfe89861..4e6c98556 100644 --- a/test/SolidityNatspecJSON.cpp +++ b/test/SolidityNatspecJSON.cpp @@ -176,7 +176,6 @@ BOOST_AUTO_TEST_CASE(dev_and_user_no_doc) "}\n"; char const* devNatspec = "{\"methods\":{}}"; - char const* userNatspec = "{\"methods\":{}}"; checkNatspec(sourceCode, devNatspec, false); @@ -230,6 +229,18 @@ BOOST_AUTO_TEST_CASE(dev_multiple_params) checkNatspec(sourceCode, natspec, false); } +BOOST_AUTO_TEST_CASE(dev_documenting_nonexistant_param) +{ + char const* sourceCode = "contract test {\n" + " /// @dev Multiplies a number by 7 and adds second parameter\n" + " /// @param a Documentation for the first parameter\n" + " /// @param not_existing Documentation for the second parameter\n" + " function mul(uint a, uint second) returns(uint d) { return a * 7 + second; }\n" + "}\n"; + + BOOST_CHECK_THROW(checkNatspec(sourceCode, natspec, false), DocstringParsingError); +} + BOOST_AUTO_TEST_CASE(dev_mutiline_param_description) { char const* sourceCode = "contract test {\n" From b0629cb2c56df1bc52f90d9221fda57fd145e3fa Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Mon, 30 Mar 2015 15:32:25 +0200 Subject: [PATCH 5/6] no need to have target json for failing tests --- test/SolidityNatspecJSON.cpp | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/test/SolidityNatspecJSON.cpp b/test/SolidityNatspecJSON.cpp index 4e6c98556..aeaad1966 100644 --- a/test/SolidityNatspecJSON.cpp +++ b/test/SolidityNatspecJSON.cpp @@ -238,7 +238,7 @@ BOOST_AUTO_TEST_CASE(dev_documenting_nonexistant_param) " function mul(uint a, uint second) returns(uint d) { return a * 7 + second; }\n" "}\n"; - BOOST_CHECK_THROW(checkNatspec(sourceCode, natspec, false), DocstringParsingError); + BOOST_CHECK_THROW(checkNatspec(sourceCode, "", false), DocstringParsingError); } BOOST_AUTO_TEST_CASE(dev_mutiline_param_description) @@ -498,17 +498,7 @@ BOOST_AUTO_TEST_CASE(dev_title_at_function_error) " function mul(uint a, uint second) returns(uint d) { return a * 7 + second; }\n" "}\n"; - char const* natspec = "{" - " \"author\": \"Lefteris\"," - " \"title\": \"Just a test contract\"," - " \"methods\":{" - " \"mul(uint256,uint256)\":{ \n" - " \"details\": \"Mul function\"\n" - " }\n" - " }\n" - "}"; - - BOOST_CHECK_THROW(checkNatspec(sourceCode, natspec, false), DocstringParsingError); + BOOST_CHECK_THROW(checkNatspec(sourceCode, "", false), DocstringParsingError); } BOOST_AUTO_TEST_CASE(natspec_notice_without_tag) From 29669c16a2dfcac6dd01f8ea5cde95dadd82b3e9 Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Mon, 30 Mar 2015 17:18:38 +0200 Subject: [PATCH 6/6] Fix some styling issues and remove comments --- libsolidity/AST.cpp | 18 ++---------------- test/SolidityNameAndTypeResolution.cpp | 6 +++--- 2 files changed, 5 insertions(+), 19 deletions(-) diff --git a/libsolidity/AST.cpp b/libsolidity/AST.cpp index 2ada73627..db72ea65a 100644 --- a/libsolidity/AST.cpp +++ b/libsolidity/AST.cpp @@ -136,34 +136,20 @@ void ContractDefinition::checkAbstractFunctions() // Search from base to derived for (ContractDefinition const* contract: boost::adaptors::reverse(getLinearizedBaseContracts())) - { for (ASTPointer const& function: contract->getDefinedFunctions()) { string const& name = function->getName(); if (!function->isFullyImplemented() && functions.count(name) && functions[name]) BOOST_THROW_EXCEPTION(function->createTypeError("Redeclaring an already implemented function as abstract")); - // if (functions.count(name) && !functions[name] && function->isFullyImplemented()) - // functions.insert(make_pair(name, true); - - // if (functions.count(name) && !functions[name] && function->isFullyImplemented) - // functions.insert(make_pair(name, true)); - - // functions.insert(make_pair(name, function->isFullyImplemented())); functions[name] = function->isFullyImplemented(); - - // if (function->isFullyImplemented()) - // full_functions.insert(make_pair(name, function.get())); - // else - // abs_functions.insert(make_pair(name, function.get())); } - } + for (auto const& it: functions) if (!it.second) { setFullyImplemented(false); break; } - } void ContractDefinition::checkIllegalOverrides() const @@ -682,7 +668,7 @@ void NewExpression::checkTypeRequirements() if (!m_contract) BOOST_THROW_EXCEPTION(createTypeError("Identifier is not a contract.")); if (!m_contract->isFullyImplemented()) - BOOST_THROW_EXCEPTION(m_contract->createTypeError("Trying to create an object of an abstract contract.")); + BOOST_THROW_EXCEPTION(m_contract->createTypeError("Trying to create an instance of an abstract contract.")); shared_ptr contractType = make_shared(*m_contract); TypePointers const& parameterTypes = contractType->getConstructorType()->getParameterTypes(); m_type = make_shared(parameterTypes, TypePointers{contractType}, diff --git a/test/SolidityNameAndTypeResolution.cpp b/test/SolidityNameAndTypeResolution.cpp index 8eb83b117..a1f780134 100644 --- a/test/SolidityNameAndTypeResolution.cpp +++ b/test/SolidityNameAndTypeResolution.cpp @@ -384,10 +384,10 @@ BOOST_AUTO_TEST_CASE(create_abstract_contract) ASTPointer sourceUnit; char const* text = R"( contract base { function foo(); } - contract derived { + contract derived { base b; - function foo() { b = new base();} - } + function foo() { b = new base();} + } )"; BOOST_CHECK_THROW(parseTextAndResolveNames(text), TypeError); }