mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Disallow visibility for constructors.
This commit is contained in:
parent
312403f7fb
commit
da36400576
@ -301,7 +301,13 @@ bool SyntaxChecker::visit(ContractDefinition const& _contract)
|
|||||||
|
|
||||||
bool SyntaxChecker::visit(FunctionDefinition const& _function)
|
bool SyntaxChecker::visit(FunctionDefinition const& _function)
|
||||||
{
|
{
|
||||||
if (_function.noVisibilitySpecified())
|
if (_function.isConstructor() && !_function.noVisibilitySpecified())
|
||||||
|
m_errorReporter.syntaxError(
|
||||||
|
2462_error,
|
||||||
|
_function.location(),
|
||||||
|
"Visibility specified for constructor. If you want the contract to be non-deployable, make it \"abstract\"."
|
||||||
|
);
|
||||||
|
else if (!_function.isConstructor() && _function.noVisibilitySpecified())
|
||||||
{
|
{
|
||||||
string suggestedVisibility = _function.isFallback() || _function.isReceive() || m_isInterface ? "external" : "public";
|
string suggestedVisibility = _function.isFallback() || _function.isReceive() || m_isInterface ? "external" : "public";
|
||||||
m_errorReporter.syntaxError(
|
m_errorReporter.syntaxError(
|
||||||
|
@ -323,11 +323,13 @@ bool TypeChecker::visit(FunctionDefinition const& _function)
|
|||||||
{
|
{
|
||||||
if (_function.markedVirtual())
|
if (_function.markedVirtual())
|
||||||
{
|
{
|
||||||
if (_function.annotation().contract->isInterface())
|
if (_function.isConstructor())
|
||||||
|
m_errorReporter.typeError(7001_error, _function.location(), "Constructors cannot be virtual.");
|
||||||
|
else if (_function.annotation().contract->isInterface())
|
||||||
m_errorReporter.warning(5815_error, _function.location(), "Interface functions are implicitly \"virtual\"");
|
m_errorReporter.warning(5815_error, _function.location(), "Interface functions are implicitly \"virtual\"");
|
||||||
if (_function.visibility() == Visibility::Private)
|
else if (_function.visibility() == Visibility::Private)
|
||||||
m_errorReporter.typeError(3942_error, _function.location(), "\"virtual\" and \"private\" cannot be used together.");
|
m_errorReporter.typeError(3942_error, _function.location(), "\"virtual\" and \"private\" cannot be used together.");
|
||||||
if (_function.libraryFunction())
|
else if (_function.libraryFunction())
|
||||||
m_errorReporter.typeError(7801_error, _function.location(), "Library functions cannot be \"virtual\".");
|
m_errorReporter.typeError(7801_error, _function.location(), "Library functions cannot be \"virtual\".");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -403,11 +405,10 @@ bool TypeChecker::visit(FunctionDefinition const& _function)
|
|||||||
if (_function.isImplemented())
|
if (_function.isImplemented())
|
||||||
m_errorReporter.typeError(4726_error, _function.location(), "Functions in interfaces cannot have an implementation.");
|
m_errorReporter.typeError(4726_error, _function.location(), "Functions in interfaces cannot have an implementation.");
|
||||||
|
|
||||||
if (_function.visibility() != Visibility::External)
|
|
||||||
m_errorReporter.typeError(1560_error, _function.location(), "Functions in interfaces must be declared external.");
|
|
||||||
|
|
||||||
if (_function.isConstructor())
|
if (_function.isConstructor())
|
||||||
m_errorReporter.typeError(6482_error, _function.location(), "Constructor cannot be defined in interfaces.");
|
m_errorReporter.typeError(6482_error, _function.location(), "Constructor cannot be defined in interfaces.");
|
||||||
|
else if (_function.visibility() != Visibility::External)
|
||||||
|
m_errorReporter.typeError(1560_error, _function.location(), "Functions in interfaces must be declared external.");
|
||||||
}
|
}
|
||||||
else if (m_currentContract->contractKind() == ContractKind::Library)
|
else if (m_currentContract->contractKind() == ContractKind::Library)
|
||||||
if (_function.isConstructor())
|
if (_function.isConstructor())
|
||||||
@ -1881,8 +1882,6 @@ void TypeChecker::typeCheckReceiveFunction(FunctionDefinition const& _function)
|
|||||||
void TypeChecker::typeCheckConstructor(FunctionDefinition const& _function)
|
void TypeChecker::typeCheckConstructor(FunctionDefinition const& _function)
|
||||||
{
|
{
|
||||||
solAssert(_function.isConstructor(), "");
|
solAssert(_function.isConstructor(), "");
|
||||||
if (_function.markedVirtual())
|
|
||||||
m_errorReporter.typeError(7001_error, _function.location(), "Constructors cannot be virtual.");
|
|
||||||
if (_function.overrides())
|
if (_function.overrides())
|
||||||
m_errorReporter.typeError(1209_error, _function.location(), "Constructors cannot override.");
|
m_errorReporter.typeError(1209_error, _function.location(), "Constructors cannot override.");
|
||||||
if (!_function.returnParameters().empty())
|
if (!_function.returnParameters().empty())
|
||||||
@ -1895,8 +1894,6 @@ void TypeChecker::typeCheckConstructor(FunctionDefinition const& _function)
|
|||||||
stateMutabilityToString(_function.stateMutability()) +
|
stateMutabilityToString(_function.stateMutability()) +
|
||||||
"\"."
|
"\"."
|
||||||
);
|
);
|
||||||
if (_function.visibility() != Visibility::Public && _function.visibility() != Visibility::Internal)
|
|
||||||
m_errorReporter.typeError(9239_error, _function.location(), "Constructor must be public or internal.");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TypeChecker::typeCheckABIEncodeFunctions(
|
void TypeChecker::typeCheckABIEncodeFunctions(
|
||||||
@ -2495,8 +2492,6 @@ void TypeChecker::endVisit(NewExpression const& _newExpression)
|
|||||||
m_errorReporter.fatalTypeError(5540_error, _newExpression.location(), "Identifier is not a contract.");
|
m_errorReporter.fatalTypeError(5540_error, _newExpression.location(), "Identifier is not a contract.");
|
||||||
if (contract->isInterface())
|
if (contract->isInterface())
|
||||||
m_errorReporter.fatalTypeError(2971_error, _newExpression.location(), "Cannot instantiate an interface.");
|
m_errorReporter.fatalTypeError(2971_error, _newExpression.location(), "Cannot instantiate an interface.");
|
||||||
if (!contract->constructorIsPublic())
|
|
||||||
m_errorReporter.typeError(9054_error, _newExpression.location(), "Contract with internal constructor cannot be created directly.");
|
|
||||||
if (contract->abstract())
|
if (contract->abstract())
|
||||||
m_errorReporter.typeError(4614_error, _newExpression.location(), "Cannot instantiate an abstract contract.");
|
m_errorReporter.typeError(4614_error, _newExpression.location(), "Cannot instantiate an abstract contract.");
|
||||||
|
|
||||||
|
@ -122,15 +122,9 @@ FunctionDefinition const* ContractDefinition::constructor() const
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ContractDefinition::constructorIsPublic() const
|
|
||||||
{
|
|
||||||
FunctionDefinition const* f = constructor();
|
|
||||||
return !f || f->isPublic();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ContractDefinition::canBeDeployed() const
|
bool ContractDefinition::canBeDeployed() const
|
||||||
{
|
{
|
||||||
return constructorIsPublic() && !abstract() && !isInterface();
|
return !abstract() && !isInterface();
|
||||||
}
|
}
|
||||||
|
|
||||||
FunctionDefinition const* ContractDefinition::fallbackFunction() const
|
FunctionDefinition const* ContractDefinition::fallbackFunction() const
|
||||||
|
@ -505,8 +505,6 @@ public:
|
|||||||
|
|
||||||
/// Returns the constructor or nullptr if no constructor was specified.
|
/// Returns the constructor or nullptr if no constructor was specified.
|
||||||
FunctionDefinition const* constructor() const;
|
FunctionDefinition const* constructor() const;
|
||||||
/// @returns true iff the constructor of this contract is public (or non-existing).
|
|
||||||
bool constructorIsPublic() const;
|
|
||||||
/// @returns true iff the contract can be deployed, i.e. is not abstract and has a
|
/// @returns true iff the contract can be deployed, i.e. is not abstract and has a
|
||||||
/// public constructor.
|
/// public constructor.
|
||||||
/// Should only be called after the type checker has run.
|
/// Should only be called after the type checker has run.
|
||||||
@ -814,7 +812,7 @@ public:
|
|||||||
}
|
}
|
||||||
bool isVisibleViaContractTypeAccess() const override
|
bool isVisibleViaContractTypeAccess() const override
|
||||||
{
|
{
|
||||||
return visibility() >= Visibility::Public;
|
return isOrdinary() && visibility() >= Visibility::Public;
|
||||||
}
|
}
|
||||||
bool isPartOfExternalInterface() const override { return isPublic() && isOrdinary(); }
|
bool isPartOfExternalInterface() const override { return isPublic() && isOrdinary(); }
|
||||||
|
|
||||||
|
@ -350,12 +350,18 @@ bool ASTJsonConverter::visit(OverrideSpecifier const& _node)
|
|||||||
|
|
||||||
bool ASTJsonConverter::visit(FunctionDefinition const& _node)
|
bool ASTJsonConverter::visit(FunctionDefinition const& _node)
|
||||||
{
|
{
|
||||||
|
Visibility visibility;
|
||||||
|
if (_node.isConstructor())
|
||||||
|
visibility = _node.annotation().contract->abstract() ? Visibility::Internal : Visibility::Public;
|
||||||
|
else
|
||||||
|
visibility = _node.visibility();
|
||||||
|
|
||||||
std::vector<pair<string, Json::Value>> attributes = {
|
std::vector<pair<string, Json::Value>> attributes = {
|
||||||
make_pair("name", _node.name()),
|
make_pair("name", _node.name()),
|
||||||
make_pair("documentation", _node.documentation() ? toJson(*_node.documentation()) : Json::nullValue),
|
make_pair("documentation", _node.documentation() ? toJson(*_node.documentation()) : Json::nullValue),
|
||||||
make_pair("kind", TokenTraits::toString(_node.kind())),
|
make_pair("kind", TokenTraits::toString(_node.kind())),
|
||||||
make_pair("stateMutability", stateMutabilityToString(_node.stateMutability())),
|
make_pair("stateMutability", stateMutabilityToString(_node.stateMutability())),
|
||||||
make_pair("visibility", Declaration::visibilityToString(_node.visibility())),
|
make_pair("visibility", Declaration::visibilityToString(visibility)),
|
||||||
make_pair("virtual", _node.markedVirtual()),
|
make_pair("virtual", _node.markedVirtual()),
|
||||||
make_pair("overrides", _node.overrides() ? toJson(*_node.overrides()) : Json::nullValue),
|
make_pair("overrides", _node.overrides() ? toJson(*_node.overrides()) : Json::nullValue),
|
||||||
make_pair("parameters", toJson(_node.parameterList())),
|
make_pair("parameters", toJson(_node.parameterList())),
|
||||||
@ -365,6 +371,7 @@ bool ASTJsonConverter::visit(FunctionDefinition const& _node)
|
|||||||
make_pair("implemented", _node.isImplemented()),
|
make_pair("implemented", _node.isImplemented()),
|
||||||
make_pair("scope", idOrNull(_node.scope()))
|
make_pair("scope", idOrNull(_node.scope()))
|
||||||
};
|
};
|
||||||
|
|
||||||
if (_node.isPartOfExternalInterface())
|
if (_node.isPartOfExternalInterface())
|
||||||
attributes.emplace_back("functionSelector", _node.externalIdentifierHex());
|
attributes.emplace_back("functionSelector", _node.externalIdentifierHex());
|
||||||
if (!_node.annotation().baseFunctions.empty())
|
if (!_node.annotation().baseFunctions.empty())
|
||||||
|
@ -399,7 +399,7 @@ ASTPointer<FunctionDefinition> ASTJsonImporter::createFunctionDefinition(Json::V
|
|||||||
return createASTNode<FunctionDefinition>(
|
return createASTNode<FunctionDefinition>(
|
||||||
_node,
|
_node,
|
||||||
memberAsASTString(_node, "name"),
|
memberAsASTString(_node, "name"),
|
||||||
visibility(_node),
|
kind == Token::Constructor ? Visibility::Default : visibility(_node),
|
||||||
stateMutability(_node),
|
stateMutability(_node),
|
||||||
kind,
|
kind,
|
||||||
memberAsBool(_node, "virtual"),
|
memberAsBool(_node, "virtual"),
|
||||||
|
@ -74,7 +74,7 @@ Json::Value ABI::generate(ContractDefinition const& _contractDef)
|
|||||||
abi.emplace(std::move(method));
|
abi.emplace(std::move(method));
|
||||||
}
|
}
|
||||||
FunctionDefinition const* constructor = _contractDef.constructor();
|
FunctionDefinition const* constructor = _contractDef.constructor();
|
||||||
if (constructor && constructor->visibility() >= Visibility::Public)
|
if (constructor && !_contractDef.abstract())
|
||||||
{
|
{
|
||||||
FunctionType constrType(*constructor);
|
FunctionType constrType(*constructor);
|
||||||
FunctionType const* externalFunctionType = constrType.interfaceFunctionType();
|
FunctionType const* externalFunctionType = constrType.interfaceFunctionType();
|
||||||
|
Loading…
Reference in New Issue
Block a user