Skip to content

Commit

Permalink
Parse override keyword
Browse files Browse the repository at this point in the history
  • Loading branch information
Marenz committed Aug 19, 2019
1 parent d3ea86b commit 6f83344
Show file tree
Hide file tree
Showing 64 changed files with 1,109 additions and 7 deletions.
2 changes: 1 addition & 1 deletion liblangutil/Token.h
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,7 @@ namespace langutil
K(Memory, "memory", 0) \
K(Modifier, "modifier", 0) \
K(New, "new", 0) \
K(Override, "override", 0) \
K(Payable, "payable", 0) \
K(Public, "public", 0) \
K(Pragma, "pragma", 0) \
Expand Down Expand Up @@ -248,7 +249,6 @@ namespace langutil
K(Mutable, "mutable", 0) \
K(NullLiteral, "null", 0) \
K(Of, "of", 0) \
K(Override, "override", 0) \
K(Partial, "partial", 0) \
K(Promise, "promise", 0) \
K(Reference, "reference", 0) \
Expand Down
34 changes: 34 additions & 0 deletions libsolidity/ast/AST.h
Original file line number Diff line number Diff line change
Expand Up @@ -604,6 +604,32 @@ class CallableDeclaration: public Declaration, public VariableScope
ASTPointer<ParameterList> m_returnParameters;
};

/**
* Function override specifier. Consists of a single override keyword or a list of
* overrides
*/
class OverrideSpecifier: public ASTNode
{
public:
OverrideSpecifier(
SourceLocation const& _location,
std::vector<ASTPointer<UserDefinedTypeName>> const& _overrides
):
ASTNode(_location),
m_overrides(_overrides)
{
}

void accept(ASTVisitor& _visitor) override;
void accept(ASTConstVisitor& _visitor) const override;

/// @returns the list of specific overrides, if any
std::vector<ASTPointer<UserDefinedTypeName>> const& overrides() const { return m_overrides; }

protected:
std::vector<ASTPointer<UserDefinedTypeName>> m_overrides;
};

class FunctionDefinition: public CallableDeclaration, public Documented, public ImplementationOptional
{
public:
Expand All @@ -613,6 +639,7 @@ class FunctionDefinition: public CallableDeclaration, public Documented, public
Declaration::Visibility _visibility,
StateMutability _stateMutability,
bool _isConstructor,
ASTPointer<OverrideSpecifier> const& _overrides,
ASTPointer<ASTString> const& _documentation,
ASTPointer<ParameterList> const& _parameters,
std::vector<ASTPointer<ModifierInvocation>> const& _modifiers,
Expand All @@ -624,6 +651,7 @@ class FunctionDefinition: public CallableDeclaration, public Documented, public
ImplementationOptional(_body != nullptr),
m_stateMutability(_stateMutability),
m_isConstructor(_isConstructor),
m_overrides(_overrides),
m_functionModifiers(_modifiers),
m_body(_body)
{}
Expand All @@ -633,6 +661,7 @@ class FunctionDefinition: public CallableDeclaration, public Documented, public

StateMutability stateMutability() const { return m_stateMutability; }
bool isConstructor() const { return m_isConstructor; }
ASTPointer<OverrideSpecifier> const& overrides() const { return m_overrides; }
bool isFallback() const { return !m_isConstructor && name().empty(); }
bool isPayable() const { return m_stateMutability == StateMutability::Payable; }
std::vector<ASTPointer<ModifierInvocation>> const& modifiers() const { return m_functionModifiers; }
Expand Down Expand Up @@ -661,6 +690,7 @@ class FunctionDefinition: public CallableDeclaration, public Documented, public
private:
StateMutability m_stateMutability;
bool m_isConstructor;
ASTPointer<OverrideSpecifier> m_overrides;
std::vector<ASTPointer<ModifierInvocation>> m_functionModifiers;
ASTPointer<Block> m_body;
};
Expand All @@ -683,6 +713,7 @@ class VariableDeclaration: public Declaration
bool _isStateVar = false,
bool _isIndexed = false,
bool _isConstant = false,
ASTPointer<OverrideSpecifier> const& _overrides = nullptr,
Location _referenceLocation = Location::Unspecified
):
Declaration(_sourceLocation, _name, _visibility),
Expand All @@ -691,6 +722,7 @@ class VariableDeclaration: public Declaration
m_isStateVariable(_isStateVar),
m_isIndexed(_isIndexed),
m_isConstant(_isConstant),
m_overrides(_overrides),
m_location(_referenceLocation) {}

void accept(ASTVisitor& _visitor) override;
Expand Down Expand Up @@ -730,6 +762,7 @@ class VariableDeclaration: public Declaration
bool isStateVariable() const { return m_isStateVariable; }
bool isIndexed() const { return m_isIndexed; }
bool isConstant() const { return m_isConstant; }
ASTPointer<OverrideSpecifier> const& overrides() const { return m_overrides; }
Location referenceLocation() const { return m_location; }
/// @returns a set of allowed storage locations for the variable.
std::set<Location> allowedDataLocations() const;
Expand All @@ -753,6 +786,7 @@ class VariableDeclaration: public Declaration
bool m_isStateVariable; ///< Whether or not this is a contract state variable
bool m_isIndexed; ///< Whether this is an indexed variable (used by events).
bool m_isConstant; ///< Whether the variable is a compile-time constant.
ASTPointer<OverrideSpecifier> m_overrides; ///< Contains the override specifier node
Location m_location; ///< Location of the variable if it is of reference type.
};

Expand Down
2 changes: 2 additions & 0 deletions libsolidity/ast/ASTJsonConverter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,7 @@ bool ASTJsonConverter::visit(FunctionDefinition const& _node)
make_pair("stateMutability", stateMutabilityToString(_node.stateMutability())),
make_pair("superFunction", idOrNull(_node.annotation().superFunction)),
make_pair("visibility", Declaration::visibilityToString(_node.visibility())),
make_pair("overrides", _node.overrides() ? toJson(_node.overrides()->overrides()) : Json::nullValue),
make_pair("parameters", toJson(_node.parameterList())),
make_pair("returnParameters", toJson(*_node.returnParameterList())),
make_pair("modifiers", toJson(_node.modifiers())),
Expand All @@ -352,6 +353,7 @@ bool ASTJsonConverter::visit(VariableDeclaration const& _node)
make_pair("constant", _node.isConstant()),
make_pair("stateVariable", _node.isStateVariable()),
make_pair("storageLocation", location(_node.referenceLocation())),
make_pair("overrides", _node.overrides() ? toJson(_node.overrides()->overrides()) : Json::nullValue),
make_pair("visibility", Declaration::visibilityToString(_node.visibility())),
make_pair("value", _node.value() ? toJson(*_node.value()) : Json::nullValue),
make_pair("scope", idOrNull(_node.scope())),
Expand Down
12 changes: 12 additions & 0 deletions libsolidity/ast/ASTPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,13 @@ bool ASTPrinter::visit(ParameterList const& _node)
return goDeeper();
}

bool ASTPrinter::visit(OverrideSpecifier const& _node)
{
writeLine("OverrideSpecifier");
printSourcePart(_node);
return goDeeper();
}

bool ASTPrinter::visit(FunctionDefinition const& _node)
{
writeLine(
Expand Down Expand Up @@ -432,6 +439,11 @@ void ASTPrinter::endVisit(ParameterList const&)
m_indentation--;
}

void ASTPrinter::endVisit(OverrideSpecifier const&)
{
m_indentation--;
}

void ASTPrinter::endVisit(FunctionDefinition const&)
{
m_indentation--;
Expand Down
2 changes: 2 additions & 0 deletions libsolidity/ast/ASTPrinter.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ class ASTPrinter: public ASTConstVisitor
bool visit(EnumDefinition const& _node) override;
bool visit(EnumValue const& _node) override;
bool visit(ParameterList const& _node) override;
bool visit(OverrideSpecifier const& _node) override;
bool visit(FunctionDefinition const& _node) override;
bool visit(VariableDeclaration const& _node) override;
bool visit(ModifierDefinition const& _node) override;
Expand Down Expand Up @@ -101,6 +102,7 @@ class ASTPrinter: public ASTConstVisitor
void endVisit(EnumDefinition const&) override;
void endVisit(EnumValue const&) override;
void endVisit(ParameterList const&) override;
void endVisit(OverrideSpecifier const&) override;
void endVisit(FunctionDefinition const&) override;
void endVisit(VariableDeclaration const&) override;
void endVisit(ModifierDefinition const&) override;
Expand Down
4 changes: 4 additions & 0 deletions libsolidity/ast/ASTVisitor.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ class ASTVisitor
virtual bool visit(EnumDefinition& _node) { return visitNode(_node); }
virtual bool visit(EnumValue& _node) { return visitNode(_node); }
virtual bool visit(ParameterList& _node) { return visitNode(_node); }
virtual bool visit(OverrideSpecifier& _node) { return visitNode(_node); }
virtual bool visit(FunctionDefinition& _node) { return visitNode(_node); }
virtual bool visit(VariableDeclaration& _node) { return visitNode(_node); }
virtual bool visit(ModifierDefinition& _node) { return visitNode(_node); }
Expand Down Expand Up @@ -100,6 +101,7 @@ class ASTVisitor
virtual void endVisit(EnumDefinition& _node) { endVisitNode(_node); }
virtual void endVisit(EnumValue& _node) { endVisitNode(_node); }
virtual void endVisit(ParameterList& _node) { endVisitNode(_node); }
virtual void endVisit(OverrideSpecifier& _node) { endVisitNode(_node); }
virtual void endVisit(FunctionDefinition& _node) { endVisitNode(_node); }
virtual void endVisit(VariableDeclaration& _node) { endVisitNode(_node); }
virtual void endVisit(ModifierDefinition& _node) { endVisitNode(_node); }
Expand Down Expand Up @@ -159,6 +161,7 @@ class ASTConstVisitor
virtual bool visit(EnumDefinition const& _node) { return visitNode(_node); }
virtual bool visit(EnumValue const& _node) { return visitNode(_node); }
virtual bool visit(ParameterList const& _node) { return visitNode(_node); }
virtual bool visit(OverrideSpecifier const& _node) { return visitNode(_node); }
virtual bool visit(FunctionDefinition const& _node) { return visitNode(_node); }
virtual bool visit(VariableDeclaration const& _node) { return visitNode(_node); }
virtual bool visit(ModifierDefinition const& _node) { return visitNode(_node); }
Expand Down Expand Up @@ -205,6 +208,7 @@ class ASTConstVisitor
virtual void endVisit(EnumDefinition const& _node) { endVisitNode(_node); }
virtual void endVisit(EnumValue const& _node) { endVisitNode(_node); }
virtual void endVisit(ParameterList const& _node) { endVisitNode(_node); }
virtual void endVisit(OverrideSpecifier const& _node) { endVisitNode(_node); }
virtual void endVisit(FunctionDefinition const& _node) { endVisitNode(_node); }
virtual void endVisit(VariableDeclaration const& _node) { endVisitNode(_node); }
virtual void endVisit(ModifierDefinition const& _node) { endVisitNode(_node); }
Expand Down
14 changes: 14 additions & 0 deletions libsolidity/ast/AST_accept.h
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,20 @@ void ParameterList::accept(ASTConstVisitor& _visitor) const
_visitor.endVisit(*this);
}

void OverrideSpecifier::accept(ASTVisitor& _visitor)
{
if (_visitor.visit(*this))
listAccept(m_overrides, _visitor);
_visitor.endVisit(*this);
}

void OverrideSpecifier::accept(ASTConstVisitor& _visitor) const
{
if (_visitor.visit(*this))
listAccept(m_overrides, _visitor);
_visitor.endVisit(*this);
}

void FunctionDefinition::accept(ASTVisitor& _visitor)
{
if (_visitor.visit(*this))
Expand Down
52 changes: 49 additions & 3 deletions libsolidity/parsing/Parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -382,6 +382,34 @@ Declaration::Visibility Parser::parseVisibilitySpecifier()
return visibility;
}

ASTPointer<OverrideSpecifier> Parser::parseOverrideSpecifier()
{
solAssert(m_scanner->currentToken() == Token::Override, "");
ASTNodeFactory nodeFactory(*this);

m_scanner->next();

std::vector<ASTPointer<UserDefinedTypeName>> overrides;

if (m_scanner->currentToken() == Token::LParen)
{
m_scanner->next();
while (true)
{
overrides.push_back(parseUserDefinedTypeName());

if (m_scanner->currentToken() == Token::RParen)
break;

expectToken(Token::Comma);
}

expectToken(Token::RParen);
}

return nodeFactory.createNode<OverrideSpecifier>(move(overrides));
}

StateMutability Parser::parseStateMutability()
{
StateMutability stateMutability(StateMutability::NonPayable);
Expand Down Expand Up @@ -411,12 +439,13 @@ StateMutability Parser::parseStateMutability()
return stateMutability;
}

Parser::FunctionHeaderParserResult Parser::parseFunctionHeader(bool _forceEmptyName, bool _allowModifiers)
Parser::FunctionHeaderParserResult Parser::parseFunctionHeader(bool _onlyFuncType, bool _allowFuncDef)
{
RecursionGuard recursionGuard(*this);
FunctionHeaderParserResult result;

result.isConstructor = false;
result.overrides = nullptr;

if (m_scanner->currentToken() == Token::Constructor)
result.isConstructor = true;
Expand All @@ -426,7 +455,7 @@ Parser::FunctionHeaderParserResult Parser::parseFunctionHeader(bool _forceEmptyN

if (result.isConstructor)
result.name = make_shared<ASTString>();
else if (_forceEmptyName || m_scanner->currentToken() == Token::LParen)
else if (_onlyFuncType || m_scanner->currentToken() == Token::LParen)
result.name = make_shared<ASTString>();
else if (m_scanner->currentToken() == Token::Constructor)
fatalParserError(string(
Expand All @@ -443,7 +472,7 @@ Parser::FunctionHeaderParserResult Parser::parseFunctionHeader(bool _forceEmptyN
while (true)
{
Token token = m_scanner->currentToken();
if (_allowModifiers && token == Token::Identifier)
if (_allowFuncDef && token == Token::Identifier)
{
// If the name is empty (and this is not a constructor),
// then this can either be a modifier (fallback function declaration)
Expand Down Expand Up @@ -493,6 +522,13 @@ Parser::FunctionHeaderParserResult Parser::parseFunctionHeader(bool _forceEmptyN
else
result.stateMutability = parseStateMutability();
}
else if (_allowFuncDef && token == Token::Override)
{
if (result.overrides)
parserError("Override already specified.");

result.overrides = parseOverrideSpecifier();
}
else
break;
}
Expand Down Expand Up @@ -540,6 +576,7 @@ ASTPointer<ASTNode> Parser::parseFunctionDefinitionOrFunctionTypeStateVariable()
header.visibility,
header.stateMutability,
header.isConstructor,
header.overrides,
docstring,
header.parameters,
header.modifiers,
Expand Down Expand Up @@ -637,6 +674,7 @@ ASTPointer<VariableDeclaration> Parser::parseVariableDeclaration(
}
bool isIndexed = false;
bool isDeclaredConst = false;
ASTPointer<OverrideSpecifier> overrides = nullptr;
Declaration::Visibility visibility(Declaration::Visibility::Default);
VariableDeclaration::Location location = VariableDeclaration::Location::Unspecified;
ASTPointer<ASTString> identifier;
Expand All @@ -659,6 +697,13 @@ ASTPointer<VariableDeclaration> Parser::parseVariableDeclaration(
else
visibility = parseVisibilitySpecifier();
}
else if (_options.isStateVariable && token == Token::Override)
{
if (overrides)
parserError("Override already specified.");

overrides = parseOverrideSpecifier();
}
else
{
if (_options.allowIndexed && token == Token::Indexed)
Expand Down Expand Up @@ -724,6 +769,7 @@ ASTPointer<VariableDeclaration> Parser::parseVariableDeclaration(
_options.isStateVariable,
isIndexed,
isDeclaredConst,
overrides,
location
);
}
Expand Down
4 changes: 3 additions & 1 deletion libsolidity/parsing/Parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ class Parser: public langutil::ParserBase
struct FunctionHeaderParserResult
{
bool isConstructor;
ASTPointer<OverrideSpecifier> overrides;
ASTPointer<ASTString> name;
ASTPointer<ParameterList> parameters;
ASTPointer<ParameterList> returnParameters;
Expand All @@ -88,8 +89,9 @@ class Parser: public langutil::ParserBase
ASTPointer<ContractDefinition> parseContractDefinition();
ASTPointer<InheritanceSpecifier> parseInheritanceSpecifier();
Declaration::Visibility parseVisibilitySpecifier();
ASTPointer<OverrideSpecifier> parseOverrideSpecifier();
StateMutability parseStateMutability();
FunctionHeaderParserResult parseFunctionHeader(bool _forceEmptyName, bool _allowModifiers);
FunctionHeaderParserResult parseFunctionHeader(bool _onlyFuncType, bool _allowFuncDef);
ASTPointer<ASTNode> parseFunctionDefinitionOrFunctionTypeStateVariable();
ASTPointer<FunctionDefinition> parseFunctionDefinition(ASTString const* _contractName);
ASTPointer<StructDefinition> parseStructDefinition();
Expand Down
2 changes: 1 addition & 1 deletion test/cmdlineTests/standard_only_ast_requested/output.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"sources":{"A":{"ast":{"absolutePath":"A","exportedSymbols":{"C":[6]},"id":7,"nodeType":"SourceUnit","nodes":[{"id":1,"literals":["solidity",">=","0.0"],"nodeType":"PragmaDirective","src":"0:22:0"},{"baseContracts":[],"contractDependencies":[],"contractKind":"contract","documentation":null,"fullyImplemented":true,"id":6,"linearizedBaseContracts":[6],"name":"C","nodeType":"ContractDefinition","nodes":[{"body":{"id":4,"nodeType":"Block","src":"61:2:0","statements":[]},"documentation":null,"id":5,"implemented":true,"kind":"function","modifiers":[],"name":"f","nodeType":"FunctionDefinition","parameters":{"id":2,"nodeType":"ParameterList","parameters":[],"src":"46:2:0"},"returnParameters":{"id":3,"nodeType":"ParameterList","parameters":[],"src":"61:0:0"},"scope":6,"src":"36:27:0","stateMutability":"pure","superFunction":null,"visibility":"public"}],"scope":7,"src":"23:42:0"}],"src":"0:65:0"},"id":0}}}
{"sources":{"A":{"ast":{"absolutePath":"A","exportedSymbols":{"C":[6]},"id":7,"nodeType":"SourceUnit","nodes":[{"id":1,"literals":["solidity",">=","0.0"],"nodeType":"PragmaDirective","src":"0:22:0"},{"baseContracts":[],"contractDependencies":[],"contractKind":"contract","documentation":null,"fullyImplemented":true,"id":6,"linearizedBaseContracts":[6],"name":"C","nodeType":"ContractDefinition","nodes":[{"body":{"id":4,"nodeType":"Block","src":"61:2:0","statements":[]},"documentation":null,"id":5,"implemented":true,"kind":"function","modifiers":[],"name":"f","nodeType":"FunctionDefinition","overrides":null,"parameters":{"id":2,"nodeType":"ParameterList","parameters":[],"src":"46:2:0"},"returnParameters":{"id":3,"nodeType":"ParameterList","parameters":[],"src":"61:0:0"},"scope":6,"src":"36:27:0","stateMutability":"pure","superFunction":null,"visibility":"public"}],"scope":7,"src":"23:42:0"}],"src":"0:65:0"},"id":0}}}
Loading

0 comments on commit 6f83344

Please sign in to comment.