diff --git a/solc/CommandLineParser.cpp b/solc/CommandLineParser.cpp index c40840a07567..297a2f497686 100644 --- a/solc/CommandLineParser.cpp +++ b/solc/CommandLineParser.cpp @@ -159,6 +159,23 @@ void CommandLineParser::checkMutuallyExclusive(std::vector const& _ } } +std::vector const& CommandLineParser::experimentalOptionNames() +{ + static std::vector const names{ + g_strLSP, + g_strImportAst, + g_strImportEvmAssemblerJson, + "ir-ast-json", + "ir-optimized-ast-json", + "yul-cfg-json", + "ethdebug", + "ethdebug-runtime", + g_strEOFVersion, + g_strViaSSACFG, + }; + return names; +} + void CommandLineParser::checkExperimental(std::vector const& _optionNames) const { if (!m_args.contains(g_strExperimental) && countEnabledOptions(_optionNames) > 0) @@ -994,18 +1011,7 @@ void CommandLineParser::processArgs() g_strImportEvmAssemblerJson, }); - checkExperimental({ - g_strLSP, - g_strImportAst, - g_strImportEvmAssemblerJson, - "ir-ast-json", - "ir-optimized-ast-json", - "yul-cfg-json", - "ethdebug", - "ethdebug-runtime", - g_strEOFVersion, - g_strViaSSACFG, - }); + checkExperimental(experimentalOptionNames()); if (m_args.count(g_strHelp) > 0) m_options.input.mode = InputMode::Help; diff --git a/solc/CommandLineParser.h b/solc/CommandLineParser.h index 5f5527c619f2..bc13acf9cf1d 100644 --- a/solc/CommandLineParser.h +++ b/solc/CommandLineParser.h @@ -289,6 +289,9 @@ class CommandLineParser CommandLineOptions const& options() const { return m_options; } + /// yields CLI option names (without leading "--") that require --experimental. + static std::vector const& experimentalOptionNames(); + static void printHelp(std::ostream& _out) { _out << optionsDescription(); } private: diff --git a/test/solc/CommandLineParser.cpp b/test/solc/CommandLineParser.cpp index 1e5896604a41..2233d0df3ec6 100644 --- a/test/solc/CommandLineParser.cpp +++ b/test/solc/CommandLineParser.cpp @@ -31,6 +31,8 @@ #include #include +#include + #include #include #include @@ -429,20 +431,20 @@ BOOST_AUTO_TEST_CASE(invalid_options_input_modes_combinations) { std::map> invalidOptionInputModeCombinations = { // TODO: This should eventually contain all options. - {"--experimental-via-ir", {"--assemble", "--strict-assembly", "--standard-json", "--link"}}, - {"--via-ir", {"--assemble", "--strict-assembly", "--standard-json", "--link"}}, - {"--metadata-literal", {"--assemble", "--strict-assembly", "--standard-json", "--link"}}, - {"--metadata-hash=swarm", {"--assemble", "--strict-assembly", "--standard-json", "--link"}}, - {"--model-checker-show-proved-safe", {"--assemble", "--strict-assembly", "--standard-json", "--link"}}, - {"--model-checker-show-unproved", {"--assemble", "--strict-assembly", "--standard-json", "--link"}}, - {"--model-checker-show-unsupported", {"--assemble", "--strict-assembly", "--standard-json", "--link"}}, - {"--model-checker-div-mod-no-slacks", {"--assemble", "--strict-assembly", "--standard-json", "--link"}}, - {"--model-checker-engine=bmc", {"--assemble", "--strict-assembly", "--standard-json", "--link"}}, - {"--model-checker-invariants=contract,reentrancy", {"--assemble", "--strict-assembly", "--standard-json", "--link"}}, - {"--model-checker-solvers=z3,smtlib2", {"--assemble", "--strict-assembly", "--standard-json", "--link"}}, - {"--model-checker-timeout=5", {"--assemble", "--strict-assembly", "--standard-json", "--link"}}, - {"--model-checker-contracts=contract1.yul:A,contract2.yul:B", {"--assemble", "--strict-assembly", "--standard-json", "--link"}}, - {"--model-checker-targets=underflow,divByZero", {"--assemble", "--strict-assembly", "--standard-json", "--link"}}, + {"--experimental-via-ir", {"--assemble", "--strict-assembly", "--standard-json", "--link", "--import-asm-json"}}, + {"--via-ir", {"--assemble", "--strict-assembly", "--standard-json", "--link", "--import-asm-json"}}, + {"--metadata-literal", {"--assemble", "--strict-assembly", "--standard-json", "--link", "--import-asm-json"}}, + {"--metadata-hash=swarm", {"--assemble", "--strict-assembly", "--standard-json", "--link", "--import-asm-json"}}, + {"--model-checker-show-proved-safe", {"--assemble", "--strict-assembly", "--standard-json", "--link", "--import-asm-json"}}, + {"--model-checker-show-unproved", {"--assemble", "--strict-assembly", "--standard-json", "--link", "--import-asm-json"}}, + {"--model-checker-show-unsupported", {"--assemble", "--strict-assembly", "--standard-json", "--link", "--import-asm-json"}}, + {"--model-checker-div-mod-no-slacks", {"--assemble", "--strict-assembly", "--standard-json", "--link", "--import-asm-json"}}, + {"--model-checker-engine=bmc", {"--assemble", "--strict-assembly", "--standard-json", "--link", "--import-asm-json"}}, + {"--model-checker-invariants=contract,reentrancy", {"--assemble", "--strict-assembly", "--standard-json", "--link", "--import-asm-json"}}, + {"--model-checker-solvers=z3,smtlib2", {"--assemble", "--strict-assembly", "--standard-json", "--link", "--import-asm-json"}}, + {"--model-checker-timeout=5", {"--assemble", "--strict-assembly", "--standard-json", "--link", "--import-asm-json"}}, + {"--model-checker-contracts=contract1.yul:A,contract2.yul:B", {"--assemble", "--strict-assembly", "--standard-json", "--link", "--import-asm-json"}}, + {"--model-checker-targets=underflow,divByZero", {"--assemble", "--strict-assembly", "--standard-json", "--link", "--import-asm-json"}}, {"--via-ssa-cfg", {"--standard-json", "--link", "--import-asm-json"}} }; @@ -455,12 +457,14 @@ BOOST_AUTO_TEST_CASE(invalid_options_input_modes_combinations) soltestAssert(!optionNameWithoutValue.empty()); std::vector commandLine = {"solc", optionName, "file", inputMode}; - bool experimentalMode = false; - if (optionNameWithoutValue == "--via-ssa-cfg") - { - commandLine.push_back("--experimental"); - experimentalMode = true; - } + + static auto constexpr isExperimental = [](std::string_view const _cliFlag) -> bool { + auto const& experimentalOpts = CommandLineParser::experimentalOptionNames(); + return ranges::find(experimentalOpts, _cliFlag.substr(2)) != ranges::end(experimentalOpts); + }; + bool needsExperimentalMode = isExperimental(optionNameWithoutValue) || isExperimental(inputMode); + if (needsExperimentalMode) + commandLine.emplace_back("--experimental"); std::string expectedMessage = "The following options are not supported in the current input mode: " + optionNameWithoutValue; // When --experimental is combined with --standard-json, a different error fires first @@ -469,7 +473,7 @@ BOOST_AUTO_TEST_CASE(invalid_options_input_modes_combinations) { std::string const what = _exception.what(); return what == expectedMessage || ( - experimentalMode && + needsExperimentalMode && what.starts_with("Standard JSON input mode is incompatible with the --experimental flag.") ); };