Make visibility optional, but it has to be consistent.

This commit is contained in:
chriseth 2020-06-30 12:04:58 +02:00
parent 479d7a059f
commit 5959d442cb
13 changed files with 78 additions and 15 deletions

View File

@ -2,6 +2,7 @@
Breaking changes:
* Type Checker: Disallow virtual for library functions.
* Constructors should not have visibility.
* Deprecated dot syntax for `value` and `gas`.
* Deprecated the identifier `now`.
* JSON AST: Removes members with ``null`` value from JSON output.

View File

@ -301,13 +301,7 @@ bool SyntaxChecker::visit(ContractDefinition const& _contract)
bool SyntaxChecker::visit(FunctionDefinition const& _function)
{
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())
if (!_function.isConstructor() && _function.noVisibilitySpecified())
{
string suggestedVisibility = _function.isFallback() || _function.isReceive() || m_isInterface ? "external" : "public";
m_errorReporter.syntaxError(

View File

@ -1922,6 +1922,30 @@ void TypeChecker::typeCheckConstructor(FunctionDefinition const& _function)
stateMutabilityToString(_function.stateMutability()) +
"\"."
);
if (!_function.noVisibilitySpecified())
{
auto const& contract = dynamic_cast<ContractDefinition const&>(*_function.scope());
if (_function.visibility() != Visibility::Public && _function.visibility() != Visibility::Internal)
m_errorReporter.typeError(9239_error, _function.location(), "Constructor cannot have visibility.");
else if (_function.isPublic() && contract.abstract())
m_errorReporter.declarationError(
8295_error,
_function.location(),
"Abstract contracts cannot have public constructors. Remove the \"public\" keyword to fix this."
);
else if (!_function.isPublic() && !contract.abstract())
m_errorReporter.declarationError(
1845_error,
_function.location(),
"Non-abstract contracts cannot have internal constructors. Remove the \"internal\" keyword and make the contract abstract to fix this."
);
else
m_errorReporter.warning(
2462_error,
_function.location(),
"Visibility for constructor is ignored. If you want the contract to be non-deployable, making it \"abstract\" is sufficient."
);
}
}
void TypeChecker::typeCheckABIEncodeFunctions(

View File

@ -0,0 +1,6 @@
abstract contract C {
constructor() {}
}
contract D is C {
constructor() { }
}

View File

@ -1,6 +1,8 @@
abstract contract C {
constructor() {}
constructor() internal {}
}
contract D is C {
constructor() { }
}
// ----
// Warning 2462: (23-48): Visibility for constructor is ignored. If you want the contract to be non-deployable, making it "abstract" is sufficient.

View File

@ -2,4 +2,4 @@ contract test {
constructor() external {}
}
// ----
// SyntaxError 2462: (17-42): Visibility specified for constructor. If you want the contract to be non-deployable, make it "abstract".
// TypeError 9239: (17-42): Constructor cannot have visibility.

View File

@ -0,0 +1,8 @@
abstract contract C {
constructor() {}
}
contract D {
function f() public { C c = new C(); c; }
}
// ----
// TypeError 4614: (84-89): Cannot instantiate an abstract contract.

View File

@ -0,0 +1,13 @@
// Previously, the type information for A was not yet available at the point of
// "new A".
contract B {
A a;
constructor() {
a = new A(address(this));
}
}
abstract contract A {
constructor(address) {}
}
// ----
// TypeError 4614: (134-139): Cannot instantiate an abstract contract.

View File

@ -1,8 +1,8 @@
abstract contract C {
constructor() {}
contract C {
constructor() internal {}
}
contract D {
function f() public { C c = new C(); c; }
}
// ----
// TypeError 4614: (84-89): Cannot instantiate an abstract contract.
// DeclarationError 1845: (14-39): Non-abstract contracts cannot have internal constructors. Remove the "internal" keyword and make the contract abstract to fix this.

View File

@ -6,8 +6,8 @@ contract B {
a = new A(address(this));
}
}
abstract contract A {
constructor(address) {}
contract A {
constructor(address) internal {}
}
// ----
// TypeError 4614: (134-139): Cannot instantiate an abstract contract.
// DeclarationError 1845: (175-207): Non-abstract contracts cannot have internal constructors. Remove the "internal" keyword and make the contract abstract to fix this.

View File

@ -0,0 +1,5 @@
contract C {
constructor() internal {}
}
// ----
// DeclarationError 1845: (14-39): Non-abstract contracts cannot have internal constructors. Remove the "internal" keyword and make the contract abstract to fix this.

View File

@ -0,0 +1,5 @@
abstract contract C {
constructor() public {}
}
// ----
// DeclarationError 8295: (23-46): Abstract contracts cannot have public constructors. Remove the "public" keyword to fix this.

View File

@ -0,0 +1,5 @@
contract C {
constructor() public {}
}
// ----
// Warning 2462: (14-37): Visibility for constructor is ignored. If you want the contract to be non-deployable, making it "abstract" is sufficient.