Properly cope with constructor headers.

This commit is contained in:
chriseth 2018-04-11 17:44:44 +02:00
parent 52f68d3b63
commit b5a696ad48
3 changed files with 21 additions and 3 deletions

View File

@ -365,9 +365,10 @@ Parser::FunctionHeaderParserResult Parser::parseFunctionHeader(
Token::Value token = m_scanner->currentToken(); Token::Value token = m_scanner->currentToken();
if (_allowModifiers && token == Token::Identifier) if (_allowModifiers && token == Token::Identifier)
{ {
// If the name is empty, then this can either be a modifier (fallback function declaration) // If the name is empty (and this is not a constructor),
// then this can either be a modifier (fallback function declaration)
// or the name of the state variable (function type name plus variable). // or the name of the state variable (function type name plus variable).
if (result.name->empty() && ( if ((result.name->empty() && !result.isConstructor) && (
m_scanner->peekNextToken() == Token::Semicolon || m_scanner->peekNextToken() == Token::Semicolon ||
m_scanner->peekNextToken() == Token::Assign m_scanner->peekNextToken() == Token::Assign
)) ))
@ -385,7 +386,7 @@ Parser::FunctionHeaderParserResult Parser::parseFunctionHeader(
if ( if (
(result.visibility == Declaration::Visibility::External || result.visibility == Declaration::Visibility::Internal) && (result.visibility == Declaration::Visibility::External || result.visibility == Declaration::Visibility::Internal) &&
result.modifiers.empty() && result.modifiers.empty() &&
result.name->empty() (result.name->empty() && !result.isConstructor)
) )
break; break;
parserError(string( parserError(string(
@ -437,6 +438,7 @@ ASTPointer<ASTNode> Parser::parseFunctionDefinitionOrFunctionTypeStateVariable(A
FunctionHeaderParserResult header = parseFunctionHeader(false, true, _contractName); FunctionHeaderParserResult header = parseFunctionHeader(false, true, _contractName);
if ( if (
header.isConstructor ||
!header.modifiers.empty() || !header.modifiers.empty() ||
!header.name->empty() || !header.name->empty() ||
m_scanner->currentToken() == Token::Semicolon || m_scanner->currentToken() == Token::Semicolon ||
@ -802,6 +804,7 @@ ASTPointer<FunctionTypeName> Parser::parseFunctionType()
RecursionGuard recursionGuard(*this); RecursionGuard recursionGuard(*this);
ASTNodeFactory nodeFactory(*this); ASTNodeFactory nodeFactory(*this);
FunctionHeaderParserResult header = parseFunctionHeader(true, false); FunctionHeaderParserResult header = parseFunctionHeader(true, false);
solAssert(!header.isConstructor, "Tried to parse type as constructor.");
return nodeFactory.createNode<FunctionTypeName>( return nodeFactory.createNode<FunctionTypeName>(
header.parameters, header.parameters,
header.returnParameters, header.returnParameters,

View File

@ -0,0 +1,7 @@
contract C {
// Fool parser into parsing a constructor as a function type.
constructor() x;
}
// ----
// Warning: (83-99): Modifiers of functions without implementation are ignored.
// DeclarationError: (97-98): Undeclared identifier.

View File

@ -0,0 +1,8 @@
contract C {
// Fool parser into parsing a constructor as a function type.
function f() {
constructor() x;
}
}
// ----
// ParserError: (118-118): Expected token Semicolon got 'Identifier'