diff --git a/docs/using-the-compiler.rst b/docs/using-the-compiler.rst index ba07d9e54..d37934cca 100644 --- a/docs/using-the-compiler.rst +++ b/docs/using-the-compiler.rst @@ -566,33 +566,36 @@ the latest version of the compiler. Available upgrade modules ~~~~~~~~~~~~~~~~~~~~~~~~~ -+-----------------+---------+--------------------------------------------------+ -| Module | Version | Description | -+=================+=========+==================================================+ -| ``constructor`` | 0.5.0 | Constructors must now be defined using the | -| | | ``constructor`` keyword. | -+-----------------+---------+--------------------------------------------------+ -| ``visibility`` | 0.5.0 | Explicit function visibility is now mandatory, | -| | | defaults to ``public``. | -+-----------------+---------+--------------------------------------------------+ -| ``abstract`` | 0.6.0 | The keyword ``abstract`` has to be used if a | -| | | contract does not implement all its functions. | -+-----------------+---------+--------------------------------------------------+ -| ``virtual`` | 0.6.0 | Functions without implementation outside an | -| | | interface have to be marked ``virtual``. | -+-----------------+---------+--------------------------------------------------+ -| ``override`` | 0.6.0 | When overriding a function or modifier, the new | -| | | keyword ``override`` must be used. | -+-----------------+---------+--------------------------------------------------+ -| ``dotsyntax`` | 0.7.0 | The following syntax is deprecated: | -| | | ``f.gas(...)()``, ``f.value(...)()`` and | -| | | ``(new C).value(...)()``. Replace these calls by | -| | | ``f{gas: ..., value: ...}()`` and | -| | | ``(new C){value: ...}()``. | -+-----------------+---------+--------------------------------------------------+ -| ``now`` | 0.7.0 | The ``now`` keyword is deprecated. Use | -| | | ``block.timestamp`` instead. | -+-----------------+---------+--------------------------------------------------+ ++----------------------------+---------+--------------------------------------------------+ +| Module | Version | Description | ++============================+=========+==================================================+ +| ``constructor`` | 0.5.0 | Constructors must now be defined using the | +| | | ``constructor`` keyword. | ++----------------------------+---------+--------------------------------------------------+ +| ``visibility`` | 0.5.0 | Explicit function visibility is now mandatory, | +| | | defaults to ``public``. | ++----------------------------+---------+--------------------------------------------------+ +| ``abstract`` | 0.6.0 | The keyword ``abstract`` has to be used if a | +| | | contract does not implement all its functions. | ++----------------------------+---------+--------------------------------------------------+ +| ``virtual`` | 0.6.0 | Functions without implementation outside an | +| | | interface have to be marked ``virtual``. | ++----------------------------+---------+--------------------------------------------------+ +| ``override`` | 0.6.0 | When overriding a function or modifier, the new | +| | | keyword ``override`` must be used. | ++----------------------------+---------+--------------------------------------------------+ +| ``dotsyntax`` | 0.7.0 | The following syntax is deprecated: | +| | | ``f.gas(...)()``, ``f.value(...)()`` and | +| | | ``(new C).value(...)()``. Replace these calls by | +| | | ``f{gas: ..., value: ...}()`` and | +| | | ``(new C){value: ...}()``. | ++----------------------------+---------+--------------------------------------------------+ +| ``now`` | 0.7.0 | The ``now`` keyword is deprecated. Use | +| | | ``block.timestamp`` instead. | ++----------------------------+---------+--------------------------------------------------+ +| ``constructor-visibility`` | 0.7.0 | Removes visibility of constructors. | +| | | | ++----------------------------+---------+--------------------------------------------------+ Please read :doc:`0.5.0 release notes <050-breaking-changes>`, :doc:`0.6.0 release notes <060-breaking-changes>` and diff --git a/tools/solidityUpgrade/SourceTransform.h b/tools/solidityUpgrade/SourceTransform.h index 5da2fc799..1b56f73a7 100644 --- a/tools/solidityUpgrade/SourceTransform.h +++ b/tools/solidityUpgrade/SourceTransform.h @@ -132,7 +132,8 @@ public: return regex_replace( _location.text(), _regex, - _expression + " " + _keyword + _expression + " " + _keyword, + std::regex_constants::format_first_only ); else solAssert( @@ -274,6 +275,14 @@ public: { return regex_replace(_location.text(), std::regex{"now"}, "block.timestamp"); } + + static std::string removeVisibility(langutil::SourceLocation const& _location) + { + std::string replacement = _location.text(); + for (auto const& replace: {"public ", "public", "internal ", "internal", "external ", "external"}) + replacement = regex_replace(replacement, std::regex{replace}, ""); + return replacement; + } }; } diff --git a/tools/solidityUpgrade/SourceUpgrade.cpp b/tools/solidityUpgrade/SourceUpgrade.cpp index 72d9ba19d..a7d691688 100644 --- a/tools/solidityUpgrade/SourceUpgrade.cpp +++ b/tools/solidityUpgrade/SourceUpgrade.cpp @@ -198,6 +198,8 @@ Allowed options)", m_suite.activateModule(Module::DotSyntax); else if (module == "now") m_suite.activateModule(Module::NowKeyword); + else if (module == "constructor-visibility") + m_suite.activateModule(Module::ConstrutorVisibility); else { error() << "Unknown upgrade module \"" + module + "\"" << endl; diff --git a/tools/solidityUpgrade/SourceUpgrade.h b/tools/solidityUpgrade/SourceUpgrade.h index 8b82b310e..0f2124bdd 100644 --- a/tools/solidityUpgrade/SourceUpgrade.h +++ b/tools/solidityUpgrade/SourceUpgrade.h @@ -59,7 +59,8 @@ private: OverridingFunction, VirtualFunction, DotSyntax, - NowKeyword + NowKeyword, + ConstrutorVisibility }; /// Upgrade suite that hosts all available modules. @@ -87,6 +88,8 @@ private: DotSyntax{m_changes}.analyze(_sourceUnit); if (isActivated(Module::NowKeyword)) NowKeyword{m_changes}.analyze(_sourceUnit); + if (isActivated(Module::ConstrutorVisibility)) + ConstructorVisibility{m_changes}.analyze(_sourceUnit); } void activateModule(Module _module) { m_modules.insert(_module); } @@ -107,7 +110,8 @@ private: Module::OverridingFunction, Module::VirtualFunction, Module::DotSyntax, - Module::NowKeyword + Module::NowKeyword, + Module::ConstrutorVisibility }; }; diff --git a/tools/solidityUpgrade/Upgrade070.cpp b/tools/solidityUpgrade/Upgrade070.cpp index d71f3685d..a5ee50c01 100644 --- a/tools/solidityUpgrade/Upgrade070.cpp +++ b/tools/solidityUpgrade/Upgrade070.cpp @@ -59,3 +59,27 @@ void NowKeyword::endVisit(Identifier const& _identifier) ); } } + +void ConstructorVisibility::endVisit(ContractDefinition const& _contract) +{ + if (!_contract.abstract()) + for (FunctionDefinition const* function: _contract.definedFunctions()) + if ( + function->isConstructor() && + !function->noVisibilitySpecified() && + function->visibility() == Visibility::Internal + ) + m_changes.emplace_back( + UpgradeChange::Level::Safe, + _contract.location(), + SourceTransform::insertBeforeKeyword(_contract.location(), "contract", "abstract") + ); + + for (FunctionDefinition const* function: _contract.definedFunctions()) + if (function->isConstructor() && !function->noVisibilitySpecified()) + m_changes.emplace_back( + UpgradeChange::Level::Safe, + function->location(), + SourceTransform::removeVisibility(function->location()) + ); +} diff --git a/tools/solidityUpgrade/Upgrade070.h b/tools/solidityUpgrade/Upgrade070.h index bfa07ce51..b99f9d306 100644 --- a/tools/solidityUpgrade/Upgrade070.h +++ b/tools/solidityUpgrade/Upgrade070.h @@ -41,4 +41,13 @@ private: void endVisit(frontend::Identifier const& _expression) override; }; +class ConstructorVisibility: public AnalysisUpgrade +{ +public: + using AnalysisUpgrade::AnalysisUpgrade; + void analyze(frontend::SourceUnit const& _sourceUnit) { _sourceUnit.accept(*this); } +private: + void endVisit(frontend::ContractDefinition const& _contract) override; +}; + }