mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Visibility specifiers.
This commit is contained in:
parent
adce36ff58
commit
e157364fe8
2
AST.cpp
2
AST.cpp
@ -133,7 +133,7 @@ void ContractDefinition::checkIllegalOverrides() const
|
|||||||
FunctionDefinition const*& override = functions[name];
|
FunctionDefinition const*& override = functions[name];
|
||||||
if (!override)
|
if (!override)
|
||||||
override = function.get();
|
override = function.get();
|
||||||
else if (override->isPublic() != function->isPublic() ||
|
else if (override->getVisibility() != function->getVisibility() ||
|
||||||
override->isDeclaredConst() != function->isDeclaredConst() ||
|
override->isDeclaredConst() != function->isDeclaredConst() ||
|
||||||
FunctionType(*override) != FunctionType(*function))
|
FunctionType(*override) != FunctionType(*function))
|
||||||
BOOST_THROW_EXCEPTION(override->createTypeError("Override changes extended function signature."));
|
BOOST_THROW_EXCEPTION(override->createTypeError("Override changes extended function signature."));
|
||||||
|
35
AST.h
35
AST.h
@ -133,12 +133,17 @@ class Declaration: public ASTNode
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
enum class LValueType { NONE, LOCAL, STORAGE };
|
enum class LValueType { NONE, LOCAL, STORAGE };
|
||||||
|
enum class Visibility { DEFAULT, PUBLIC, PROTECTED, PRIVATE };
|
||||||
|
|
||||||
Declaration(Location const& _location, ASTPointer<ASTString> const& _name):
|
Declaration(Location const& _location, ASTPointer<ASTString> const& _name,
|
||||||
ASTNode(_location), m_name(_name), m_scope(nullptr) {}
|
Visibility _visibility = Visibility::DEFAULT):
|
||||||
|
ASTNode(_location), m_name(_name), m_visibility(_visibility), m_scope(nullptr) {}
|
||||||
|
|
||||||
/// @returns the declared name.
|
/// @returns the declared name.
|
||||||
ASTString const& getName() const { return *m_name; }
|
ASTString const& getName() const { return *m_name; }
|
||||||
|
Visibility getVisibility() const { return m_visibility == Visibility::DEFAULT ? getDefaultVisibility() : m_visibility; }
|
||||||
|
bool isPublic() const { return getVisibility() == Visibility::PUBLIC; }
|
||||||
|
|
||||||
/// @returns the scope this declaration resides in. Can be nullptr if it is the global scope.
|
/// @returns the scope this declaration resides in. Can be nullptr if it is the global scope.
|
||||||
/// Available only after name and type resolution step.
|
/// Available only after name and type resolution step.
|
||||||
Declaration const* getScope() const { return m_scope; }
|
Declaration const* getScope() const { return m_scope; }
|
||||||
@ -151,8 +156,12 @@ public:
|
|||||||
/// @returns the lvalue type of expressions referencing this declaration
|
/// @returns the lvalue type of expressions referencing this declaration
|
||||||
virtual LValueType getLValueType() const { return LValueType::NONE; }
|
virtual LValueType getLValueType() const { return LValueType::NONE; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual Visibility getDefaultVisibility() const { return Visibility::PUBLIC; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ASTPointer<ASTString> m_name;
|
ASTPointer<ASTString> m_name;
|
||||||
|
Visibility m_visibility;
|
||||||
Declaration const* m_scope;
|
Declaration const* m_scope;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -330,16 +339,15 @@ class FunctionDefinition: public Declaration, public VariableScope, public Docum
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
FunctionDefinition(Location const& _location, ASTPointer<ASTString> const& _name,
|
FunctionDefinition(Location const& _location, ASTPointer<ASTString> const& _name,
|
||||||
bool _isPublic,
|
Declaration::Visibility _visibility, bool _isConstructor,
|
||||||
bool _isConstructor,
|
|
||||||
ASTPointer<ASTString> const& _documentation,
|
ASTPointer<ASTString> const& _documentation,
|
||||||
ASTPointer<ParameterList> const& _parameters,
|
ASTPointer<ParameterList> const& _parameters,
|
||||||
bool _isDeclaredConst,
|
bool _isDeclaredConst,
|
||||||
std::vector<ASTPointer<ModifierInvocation>> const& _modifiers,
|
std::vector<ASTPointer<ModifierInvocation>> const& _modifiers,
|
||||||
ASTPointer<ParameterList> const& _returnParameters,
|
ASTPointer<ParameterList> const& _returnParameters,
|
||||||
ASTPointer<Block> const& _body):
|
ASTPointer<Block> const& _body):
|
||||||
Declaration(_location, _name), Documented(_documentation),
|
Declaration(_location, _name, _visibility), Documented(_documentation),
|
||||||
m_isPublic(_isPublic), m_isConstructor(_isConstructor),
|
m_isConstructor(_isConstructor),
|
||||||
m_parameters(_parameters),
|
m_parameters(_parameters),
|
||||||
m_isDeclaredConst(_isDeclaredConst),
|
m_isDeclaredConst(_isDeclaredConst),
|
||||||
m_functionModifiers(_modifiers),
|
m_functionModifiers(_modifiers),
|
||||||
@ -350,7 +358,6 @@ public:
|
|||||||
virtual void accept(ASTVisitor& _visitor) override;
|
virtual void accept(ASTVisitor& _visitor) override;
|
||||||
virtual void accept(ASTConstVisitor& _visitor) const override;
|
virtual void accept(ASTConstVisitor& _visitor) const override;
|
||||||
|
|
||||||
bool isPublic() const { return m_isPublic; }
|
|
||||||
bool isConstructor() const { return m_isConstructor; }
|
bool isConstructor() const { return m_isConstructor; }
|
||||||
bool isDeclaredConst() const { return m_isDeclaredConst; }
|
bool isDeclaredConst() const { return m_isDeclaredConst; }
|
||||||
std::vector<ASTPointer<ModifierInvocation>> const& getModifiers() const { return m_functionModifiers; }
|
std::vector<ASTPointer<ModifierInvocation>> const& getModifiers() const { return m_functionModifiers; }
|
||||||
@ -371,7 +378,6 @@ public:
|
|||||||
std::string getCanonicalSignature() const;
|
std::string getCanonicalSignature() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool m_isPublic;
|
|
||||||
bool m_isConstructor;
|
bool m_isConstructor;
|
||||||
ASTPointer<ParameterList> m_parameters;
|
ASTPointer<ParameterList> m_parameters;
|
||||||
bool m_isDeclaredConst;
|
bool m_isDeclaredConst;
|
||||||
@ -388,10 +394,10 @@ class VariableDeclaration: public Declaration
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
VariableDeclaration(Location const& _location, ASTPointer<TypeName> const& _type,
|
VariableDeclaration(Location const& _location, ASTPointer<TypeName> const& _type,
|
||||||
ASTPointer<ASTString> const& _name, bool _isPublic, bool _isStateVar = false,
|
ASTPointer<ASTString> const& _name, Visibility _visibility,
|
||||||
bool _isIndexed = false):
|
bool _isStateVar = false, bool _isIndexed = false):
|
||||||
Declaration(_location, _name), m_typeName(_type),
|
Declaration(_location, _name, _visibility), m_typeName(_type),
|
||||||
m_isPublic(_isPublic), m_isStateVariable(_isStateVar), m_isIndexed(_isIndexed) {}
|
m_isStateVariable(_isStateVar), m_isIndexed(_isIndexed) {}
|
||||||
virtual void accept(ASTVisitor& _visitor) override;
|
virtual void accept(ASTVisitor& _visitor) override;
|
||||||
virtual void accept(ASTConstVisitor& _visitor) const override;
|
virtual void accept(ASTConstVisitor& _visitor) const override;
|
||||||
|
|
||||||
@ -404,13 +410,14 @@ public:
|
|||||||
|
|
||||||
virtual LValueType getLValueType() const override;
|
virtual LValueType getLValueType() const override;
|
||||||
bool isLocalVariable() const { return !!dynamic_cast<FunctionDefinition const*>(getScope()); }
|
bool isLocalVariable() const { return !!dynamic_cast<FunctionDefinition const*>(getScope()); }
|
||||||
bool isPublic() const { return m_isPublic; }
|
|
||||||
bool isStateVariable() const { return m_isStateVariable; }
|
bool isStateVariable() const { return m_isStateVariable; }
|
||||||
bool isIndexed() const { return m_isIndexed; }
|
bool isIndexed() const { return m_isIndexed; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
Visibility getDefaultVisibility() const override { return Visibility::PROTECTED; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ASTPointer<TypeName> m_typeName; ///< can be empty ("var")
|
ASTPointer<TypeName> m_typeName; ///< can be empty ("var")
|
||||||
bool m_isPublic; ///< Whether there is an accessor for it or not
|
|
||||||
bool m_isStateVariable; ///< Whether or not this is a contract state variable
|
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_isIndexed; ///< Whether this is an indexed variable (used by events).
|
||||||
|
|
||||||
|
49
Parser.cpp
49
Parser.cpp
@ -131,27 +131,19 @@ ASTPointer<ContractDefinition> Parser::parseContractDefinition()
|
|||||||
}
|
}
|
||||||
while (m_scanner->getCurrentToken() == Token::COMMA);
|
while (m_scanner->getCurrentToken() == Token::COMMA);
|
||||||
expectToken(Token::LBRACE);
|
expectToken(Token::LBRACE);
|
||||||
bool visibilityIsPublic = true;
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
Token::Value currentToken = m_scanner->getCurrentToken();
|
Token::Value currentToken = m_scanner->getCurrentToken();
|
||||||
if (currentToken == Token::RBRACE)
|
if (currentToken == Token::RBRACE)
|
||||||
break;
|
break;
|
||||||
else if (currentToken == Token::PUBLIC || currentToken == Token::PRIVATE)
|
|
||||||
{
|
|
||||||
visibilityIsPublic = (m_scanner->getCurrentToken() == Token::PUBLIC);
|
|
||||||
m_scanner->next();
|
|
||||||
expectToken(Token::COLON);
|
|
||||||
}
|
|
||||||
else if (currentToken == Token::FUNCTION)
|
else if (currentToken == Token::FUNCTION)
|
||||||
functions.push_back(parseFunctionDefinition(visibilityIsPublic, name.get()));
|
functions.push_back(parseFunctionDefinition(name.get()));
|
||||||
else if (currentToken == Token::STRUCT)
|
else if (currentToken == Token::STRUCT)
|
||||||
structs.push_back(parseStructDefinition());
|
structs.push_back(parseStructDefinition());
|
||||||
else if (currentToken == Token::IDENTIFIER || currentToken == Token::MAPPING ||
|
else if (currentToken == Token::IDENTIFIER || currentToken == Token::MAPPING ||
|
||||||
Token::isElementaryTypeName(currentToken))
|
Token::isElementaryTypeName(currentToken))
|
||||||
{
|
{
|
||||||
VarDeclParserOptions options;
|
VarDeclParserOptions options;
|
||||||
options.isPublic = visibilityIsPublic;
|
|
||||||
options.isStateVariable = true;
|
options.isStateVariable = true;
|
||||||
stateVariables.push_back(parseVariableDeclaration(options));
|
stateVariables.push_back(parseVariableDeclaration(options));
|
||||||
expectToken(Token::SEMICOLON);
|
expectToken(Token::SEMICOLON);
|
||||||
@ -186,7 +178,22 @@ ASTPointer<InheritanceSpecifier> Parser::parseInheritanceSpecifier()
|
|||||||
return nodeFactory.createNode<InheritanceSpecifier>(name, arguments);
|
return nodeFactory.createNode<InheritanceSpecifier>(name, arguments);
|
||||||
}
|
}
|
||||||
|
|
||||||
ASTPointer<FunctionDefinition> Parser::parseFunctionDefinition(bool _isPublic, ASTString const* _contractName)
|
Declaration::Visibility Parser::parseVisibilitySpecifier(Token::Value _token)
|
||||||
|
{
|
||||||
|
Declaration::Visibility visibility;
|
||||||
|
if (_token == Token::PUBLIC)
|
||||||
|
visibility = Declaration::Visibility::PUBLIC;
|
||||||
|
else if (_token == Token::PROTECTED)
|
||||||
|
visibility = Declaration::Visibility::PROTECTED;
|
||||||
|
else if (_token == Token::PRIVATE)
|
||||||
|
visibility = Declaration::Visibility::PRIVATE;
|
||||||
|
else
|
||||||
|
solAssert(false, "Invalid visibility specifier.");
|
||||||
|
m_scanner->next();
|
||||||
|
return visibility;
|
||||||
|
}
|
||||||
|
|
||||||
|
ASTPointer<FunctionDefinition> Parser::parseFunctionDefinition(ASTString const* _contractName)
|
||||||
{
|
{
|
||||||
ASTNodeFactory nodeFactory(*this);
|
ASTNodeFactory nodeFactory(*this);
|
||||||
ASTPointer<ASTString> docstring;
|
ASTPointer<ASTString> docstring;
|
||||||
@ -201,16 +208,24 @@ ASTPointer<FunctionDefinition> Parser::parseFunctionDefinition(bool _isPublic, A
|
|||||||
name = expectIdentifierToken();
|
name = expectIdentifierToken();
|
||||||
ASTPointer<ParameterList> parameters(parseParameterList());
|
ASTPointer<ParameterList> parameters(parseParameterList());
|
||||||
bool isDeclaredConst = false;
|
bool isDeclaredConst = false;
|
||||||
|
Declaration::Visibility visibility(Declaration::Visibility::DEFAULT);
|
||||||
vector<ASTPointer<ModifierInvocation>> modifiers;
|
vector<ASTPointer<ModifierInvocation>> modifiers;
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
if (m_scanner->getCurrentToken() == Token::CONST)
|
Token::Value token = m_scanner->getCurrentToken();
|
||||||
|
if (token == Token::CONST)
|
||||||
{
|
{
|
||||||
isDeclaredConst = true;
|
isDeclaredConst = true;
|
||||||
m_scanner->next();
|
m_scanner->next();
|
||||||
}
|
}
|
||||||
else if (m_scanner->getCurrentToken() == Token::IDENTIFIER)
|
else if (token == Token::IDENTIFIER)
|
||||||
modifiers.push_back(parseModifierInvocation());
|
modifiers.push_back(parseModifierInvocation());
|
||||||
|
else if (Token::isVisibilitySpecifier(token))
|
||||||
|
{
|
||||||
|
if (visibility != Declaration::Visibility::DEFAULT)
|
||||||
|
BOOST_THROW_EXCEPTION(createParserError("Multiple visibility specifiers."));
|
||||||
|
visibility = parseVisibilitySpecifier(token);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -226,7 +241,7 @@ ASTPointer<FunctionDefinition> Parser::parseFunctionDefinition(bool _isPublic, A
|
|||||||
ASTPointer<Block> block = parseBlock();
|
ASTPointer<Block> block = parseBlock();
|
||||||
nodeFactory.setEndPositionFromNode(block);
|
nodeFactory.setEndPositionFromNode(block);
|
||||||
bool const c_isConstructor = (_contractName && *name == *_contractName);
|
bool const c_isConstructor = (_contractName && *name == *_contractName);
|
||||||
return nodeFactory.createNode<FunctionDefinition>(name, _isPublic, c_isConstructor, docstring,
|
return nodeFactory.createNode<FunctionDefinition>(name, visibility, c_isConstructor, docstring,
|
||||||
parameters, isDeclaredConst, modifiers,
|
parameters, isDeclaredConst, modifiers,
|
||||||
returnParameters, block);
|
returnParameters, block);
|
||||||
}
|
}
|
||||||
@ -253,14 +268,18 @@ ASTPointer<VariableDeclaration> Parser::parseVariableDeclaration(VarDeclParserOp
|
|||||||
ASTNodeFactory nodeFactory(*this);
|
ASTNodeFactory nodeFactory(*this);
|
||||||
ASTPointer<TypeName> type = parseTypeName(_options.allowVar);
|
ASTPointer<TypeName> type = parseTypeName(_options.allowVar);
|
||||||
bool isIndexed = false;
|
bool isIndexed = false;
|
||||||
if (_options.allowIndexed && m_scanner->getCurrentToken() == Token::INDEXED)
|
Token::Value token = m_scanner->getCurrentToken();
|
||||||
|
if (_options.allowIndexed && token == Token::INDEXED)
|
||||||
{
|
{
|
||||||
isIndexed = true;
|
isIndexed = true;
|
||||||
m_scanner->next();
|
m_scanner->next();
|
||||||
}
|
}
|
||||||
|
Declaration::Visibility visibility(Declaration::Visibility::DEFAULT);
|
||||||
|
if (_options.isStateVariable && Token::isVisibilitySpecifier(token))
|
||||||
|
visibility = parseVisibilitySpecifier(token);
|
||||||
nodeFactory.markEndPosition();
|
nodeFactory.markEndPosition();
|
||||||
return nodeFactory.createNode<VariableDeclaration>(type, expectIdentifierToken(),
|
return nodeFactory.createNode<VariableDeclaration>(type, expectIdentifierToken(),
|
||||||
_options.isPublic, _options.isStateVariable,
|
visibility, _options.isStateVariable,
|
||||||
isIndexed);
|
isIndexed);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
4
Parser.h
4
Parser.h
@ -48,7 +48,6 @@ private:
|
|||||||
struct VarDeclParserOptions {
|
struct VarDeclParserOptions {
|
||||||
VarDeclParserOptions() {}
|
VarDeclParserOptions() {}
|
||||||
bool allowVar = false;
|
bool allowVar = false;
|
||||||
bool isPublic = false;
|
|
||||||
bool isStateVariable = false;
|
bool isStateVariable = false;
|
||||||
bool allowIndexed = false;
|
bool allowIndexed = false;
|
||||||
};
|
};
|
||||||
@ -58,7 +57,8 @@ private:
|
|||||||
ASTPointer<ImportDirective> parseImportDirective();
|
ASTPointer<ImportDirective> parseImportDirective();
|
||||||
ASTPointer<ContractDefinition> parseContractDefinition();
|
ASTPointer<ContractDefinition> parseContractDefinition();
|
||||||
ASTPointer<InheritanceSpecifier> parseInheritanceSpecifier();
|
ASTPointer<InheritanceSpecifier> parseInheritanceSpecifier();
|
||||||
ASTPointer<FunctionDefinition> parseFunctionDefinition(bool _isPublic, ASTString const* _contractName);
|
Declaration::Visibility parseVisibilitySpecifier(Token::Value _token);
|
||||||
|
ASTPointer<FunctionDefinition> parseFunctionDefinition(ASTString const* _contractName);
|
||||||
ASTPointer<StructDefinition> parseStructDefinition();
|
ASTPointer<StructDefinition> parseStructDefinition();
|
||||||
ASTPointer<VariableDeclaration> parseVariableDeclaration(VarDeclParserOptions const& _options = VarDeclParserOptions());
|
ASTPointer<VariableDeclaration> parseVariableDeclaration(VarDeclParserOptions const& _options = VarDeclParserOptions());
|
||||||
ASTPointer<ModifierDefinition> parseModifierDefinition();
|
ASTPointer<ModifierDefinition> parseModifierDefinition();
|
||||||
|
2
Token.h
2
Token.h
@ -165,6 +165,7 @@ namespace solidity
|
|||||||
K(NEW, "new", 0) \
|
K(NEW, "new", 0) \
|
||||||
K(PUBLIC, "public", 0) \
|
K(PUBLIC, "public", 0) \
|
||||||
K(PRIVATE, "private", 0) \
|
K(PRIVATE, "private", 0) \
|
||||||
|
K(PROTECTED, "protected", 0) \
|
||||||
K(RETURN, "return", 0) \
|
K(RETURN, "return", 0) \
|
||||||
K(RETURNS, "returns", 0) \
|
K(RETURNS, "returns", 0) \
|
||||||
K(STRUCT, "struct", 0) \
|
K(STRUCT, "struct", 0) \
|
||||||
@ -376,6 +377,7 @@ public:
|
|||||||
static bool isUnaryOp(Value op) { return (NOT <= op && op <= DELETE) || op == ADD || op == SUB; }
|
static bool isUnaryOp(Value op) { return (NOT <= op && op <= DELETE) || op == ADD || op == SUB; }
|
||||||
static bool isCountOp(Value op) { return op == INC || op == DEC; }
|
static bool isCountOp(Value op) { return op == INC || op == DEC; }
|
||||||
static bool isShiftOp(Value op) { return (SHL <= op) && (op <= SHR); }
|
static bool isShiftOp(Value op) { return (SHL <= op) && (op <= SHR); }
|
||||||
|
static bool isVisibilitySpecifier(Value op) { return op == PUBLIC || op == PRIVATE || op == PROTECTED; }
|
||||||
|
|
||||||
// Returns a string corresponding to the JS token string
|
// Returns a string corresponding to the JS token string
|
||||||
// (.e., "<" for the token LT) or NULL if the token doesn't
|
// (.e., "<" for the token LT) or NULL if the token doesn't
|
||||||
|
@ -1,14 +1,15 @@
|
|||||||
ContractDefinition = 'contract' Identifier
|
ContractDefinition = 'contract' Identifier
|
||||||
( 'is' InheritanceSpecifier (',' InheritanceSpecifier )* )?
|
( 'is' InheritanceSpecifier (',' InheritanceSpecifier )* )?
|
||||||
'{' ContractPart* '}'
|
'{' ContractPart* '}'
|
||||||
ContractPart = VariableDeclaration ';' | StructDefinition | ModifierDefinition |
|
ContractPart = StateVariableDeclaration | StructDefinition | ModifierDefinition | FunctionDefinition
|
||||||
FunctionDefinition | 'public:' | 'private:'
|
|
||||||
|
|
||||||
InheritanceSpecifier = Identifier ( '(' Expression ( ',' Expression )* ')' )?
|
InheritanceSpecifier = Identifier ( '(' Expression ( ',' Expression )* ')' )?
|
||||||
StructDefinition = 'struct' Identifier '{'
|
StructDefinition = 'struct' Identifier '{'
|
||||||
( VariableDeclaration (';' VariableDeclaration)* )? '}
|
( VariableDeclaration (';' VariableDeclaration)* )? '}
|
||||||
|
StateVariableDeclaration = TypeName ( 'public' | 'protected' | 'private' )? Identifier ';'
|
||||||
ModifierDefinition = 'modifier' Identifier ParameterList? Block
|
ModifierDefinition = 'modifier' Identifier ParameterList? Block
|
||||||
FunctionDefinition = 'function' Identifier ParameterList ( Identifier | 'constant' )*
|
FunctionDefinition = 'function' Identifier ParameterList
|
||||||
|
( Identifier | 'constant' | 'public' | 'protected' | 'private' )*
|
||||||
( 'returns' ParameterList )? Block
|
( 'returns' ParameterList )? Block
|
||||||
ParameterList = '(' ( VariableDeclaration (',' VariableDeclaration)* )? ')'
|
ParameterList = '(' ( VariableDeclaration (',' VariableDeclaration)* )? ')'
|
||||||
// semantic restriction: mappings and structs (recursively) containing mappings
|
// semantic restriction: mappings and structs (recursively) containing mappings
|
||||||
|
Loading…
Reference in New Issue
Block a user