mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
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
This commit is contained in:
parent
8f8e407306
commit
9d6d7ccab8
4
AST.cpp
4
AST.cpp
@ -311,8 +311,8 @@ void FunctionDefinition::checkTypeRequirements()
|
||||
modifier->checkTypeRequirements(isConstructor() ?
|
||||
dynamic_cast<ContractDefinition const&>(*getScope()).getBaseContracts() :
|
||||
vector<ASTPointer<InheritanceSpecifier>>());
|
||||
|
||||
m_body->checkTypeRequirements();
|
||||
if (m_body)
|
||||
m_body->checkTypeRequirements();
|
||||
}
|
||||
|
||||
string FunctionDefinition::getCanonicalSignature() const
|
||||
|
85
AST.h
85
AST.h
@ -196,6 +196,21 @@ protected:
|
||||
ASTPointer<ASTString> 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<ASTString> const& _name,
|
||||
ASTPointer<ASTString> const& _documentation,
|
||||
std::vector<ASTPointer<InheritanceSpecifier>> const& _baseContracts,
|
||||
std::vector<ASTPointer<StructDefinition>> const& _definedStructs,
|
||||
std::vector<ASTPointer<EnumDefinition>> const& _definedEnums,
|
||||
std::vector<ASTPointer<VariableDeclaration>> const& _stateVariables,
|
||||
std::vector<ASTPointer<FunctionDefinition>> const& _definedFunctions,
|
||||
std::vector<ASTPointer<ModifierDefinition>> const& _functionModifiers,
|
||||
std::vector<ASTPointer<EventDefinition>> const& _events):
|
||||
Declaration(_location, _name), Documented(_documentation),
|
||||
ContractDefinition(
|
||||
SourceLocation const& _location,
|
||||
ASTPointer<ASTString> const& _name,
|
||||
ASTPointer<ASTString> const& _documentation,
|
||||
std::vector<ASTPointer<InheritanceSpecifier>> const& _baseContracts,
|
||||
std::vector<ASTPointer<StructDefinition>> const& _definedStructs,
|
||||
std::vector<ASTPointer<EnumDefinition>> const& _definedEnums,
|
||||
std::vector<ASTPointer<VariableDeclaration>> const& _stateVariables,
|
||||
std::vector<ASTPointer<FunctionDefinition>> const& _definedFunctions,
|
||||
std::vector<ASTPointer<ModifierDefinition>> const& _functionModifiers,
|
||||
std::vector<ASTPointer<EventDefinition>> 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<ASTPointer<VariableDeclaration>> 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<ASTString> const& _name,
|
||||
Declaration::Visibility _visibility, bool _isConstructor,
|
||||
ASTPointer<ASTString> const& _documentation,
|
||||
ASTPointer<ParameterList> const& _parameters,
|
||||
bool _isDeclaredConst,
|
||||
std::vector<ASTPointer<ModifierInvocation>> const& _modifiers,
|
||||
ASTPointer<ParameterList> const& _returnParameters,
|
||||
ASTPointer<Block> 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<ASTString> const& _name,
|
||||
Declaration::Visibility _visibility, bool _isConstructor,
|
||||
ASTPointer<ASTString> const& _documentation,
|
||||
ASTPointer<ParameterList> const& _parameters,
|
||||
bool _isDeclaredConst,
|
||||
std::vector<ASTPointer<ModifierInvocation>> const& _modifiers,
|
||||
ASTPointer<ParameterList> const& _returnParameters,
|
||||
ASTPointer<Block> 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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
33
Parser.cpp
33
Parser.cpp
@ -116,6 +116,7 @@ ASTPointer<ContractDefinition> Parser::parseContractDefinition()
|
||||
{
|
||||
ASTNodeFactory nodeFactory(*this);
|
||||
ASTPointer<ASTString> docString;
|
||||
bool contractFullyImplemented = true;
|
||||
if (m_scanner->getCurrentCommentLiteral() != "")
|
||||
docString = make_shared<ASTString>(m_scanner->getCurrentCommentLiteral());
|
||||
expectToken(Token::Contract);
|
||||
@ -141,7 +142,12 @@ ASTPointer<ContractDefinition> Parser::parseContractDefinition()
|
||||
if (currentToken == Token::RBrace)
|
||||
break;
|
||||
else if (currentToken == Token::Function)
|
||||
functions.push_back(parseFunctionDefinition(name.get()));
|
||||
{
|
||||
ASTPointer<FunctionDefinition> 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<ContractDefinition> Parser::parseContractDefinition()
|
||||
}
|
||||
nodeFactory.markEndPosition();
|
||||
expectToken(Token::RBrace);
|
||||
return nodeFactory.createNode<ContractDefinition>(name, docString, baseContracts, structs, enums,
|
||||
stateVariables, functions, modifiers, events);
|
||||
return nodeFactory.createNode<ContractDefinition>(
|
||||
name,
|
||||
docString,
|
||||
baseContracts,
|
||||
structs,
|
||||
enums,
|
||||
stateVariables,
|
||||
functions,
|
||||
modifiers,
|
||||
events,
|
||||
contractFullyImplemented
|
||||
);
|
||||
}
|
||||
|
||||
ASTPointer<InheritanceSpecifier> Parser::parseInheritanceSpecifier()
|
||||
@ -247,8 +263,15 @@ ASTPointer<FunctionDefinition> Parser::parseFunctionDefinition(ASTString const*
|
||||
}
|
||||
else
|
||||
returnParameters = createEmptyParameterList();
|
||||
ASTPointer<Block> block = parseBlock();
|
||||
nodeFactory.setEndPositionFromNode(block);
|
||||
ASTPointer<Block> block = ASTPointer<Block>();
|
||||
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<FunctionDefinition>(name, visibility, c_isConstructor, docstring,
|
||||
parameters, isDeclaredConst, modifiers,
|
||||
|
Loading…
Reference in New Issue
Block a user