From 93c1fe68789ae23c610570c70685d0c6a9aa8a12 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Mon, 11 Oct 2021 13:03:51 +0200 Subject: [PATCH 1/3] Treat --help, --license and --version as separate input modes --- solc/CommandLineInterface.cpp | 66 ++++++++++++++++++++++++---- solc/CommandLineInterface.h | 2 + solc/CommandLineParser.cpp | 69 +++++++++++------------------- solc/CommandLineParser.h | 28 ++++-------- test/solc/CommandLineInterface.cpp | 39 ++++++++++++++++- test/solc/CommandLineParser.cpp | 62 +++++++++++++-------------- 6 files changed, 160 insertions(+), 106 deletions(-) diff --git a/solc/CommandLineInterface.cpp b/solc/CommandLineInterface.cpp index 6c24b7742..e86381bf3 100644 --- a/solc/CommandLineInterface.cpp +++ b/solc/CommandLineInterface.cpp @@ -23,6 +23,7 @@ */ #include +#include "license.h" #include "solidity/BuildInfo.h" #include @@ -405,6 +406,13 @@ bool CommandLineInterface::readInputFiles() { solAssert(!m_standardJsonInput.has_value(), ""); + if ( + m_options.input.mode == InputMode::Help || + m_options.input.mode == InputMode::License || + m_options.input.mode == InputMode::Version + ) + return true; + m_fileReader.setBasePath(m_options.input.basePath); if (m_fileReader.basePath() != "") @@ -573,8 +581,18 @@ void CommandLineInterface::createJson(string const& _fileName, string const& _js bool CommandLineInterface::parseArguments(int _argc, char const* const* _argv) { - CommandLineParser parser(sout(/* _markAsUsed */ false), serr(/* _markAsUsed */ false)); - bool success = parser.parse(_argc, _argv, isatty(fileno(stdin))); + CommandLineParser parser(serr(/* _markAsUsed */ false)); + + if (isatty(fileno(stdin)) && _argc == 1) + { + // If the terminal is taking input from the user, provide more user-friendly output. + CommandLineParser::printHelp(sout()); + + // In this case we want to exit with an error but not display any error message. + return false; + } + + bool success = parser.parse(_argc, _argv); if (!success) return false; m_hasOutput = m_hasOutput || parser.hasOutput(); @@ -587,6 +605,15 @@ bool CommandLineInterface::processInput() { switch (m_options.input.mode) { + case InputMode::Help: + CommandLineParser::printHelp(sout()); + return false; + case InputMode::License: + printLicense(); + return true; + case InputMode::Version: + printVersion(); + return true; case InputMode::StandardJson: { solAssert(m_standardJsonInput.has_value(), ""); @@ -611,6 +638,19 @@ bool CommandLineInterface::processInput() return false; } +void CommandLineInterface::printVersion() +{ + sout() << "solc, the solidity compiler commandline interface" << endl; + sout() << "Version: " << solidity::frontend::VersionString << endl; +} + +void CommandLineInterface::printLicense() +{ + sout() << otherLicenses << endl; + // This is a static variable generated by cmake from LICENSE.txt + sout() << licenseText << endl; +} + bool CommandLineInterface::compile() { solAssert(m_options.input.mode == InputMode::Compiler || m_options.input.mode == InputMode::CompilerWithASTImport, ""); @@ -845,16 +885,24 @@ void CommandLineInterface::handleAst() bool CommandLineInterface::actOnInput() { - if (m_options.input.mode == InputMode::StandardJson || m_options.input.mode == InputMode::Assembler) - // Already done in "processInput" phase. - return true; - else if (m_options.input.mode == InputMode::Linker) - writeLinkedFiles(); - else + switch (m_options.input.mode) { - solAssert(m_options.input.mode == InputMode::Compiler || m_options.input.mode == InputMode::CompilerWithASTImport, ""); + case InputMode::Help: + case InputMode::License: + case InputMode::Version: + case InputMode::StandardJson: + case InputMode::Assembler: + // Already done in "processInput" phase. + break; + case InputMode::Linker: + writeLinkedFiles(); + break; + case InputMode::Compiler: + case InputMode::CompilerWithASTImport: outputCompilationResults(); + break; } + return !m_outputFailed; } diff --git a/solc/CommandLineInterface.h b/solc/CommandLineInterface.h index 1ca40568c..e99ed1c07 100644 --- a/solc/CommandLineInterface.h +++ b/solc/CommandLineInterface.h @@ -66,6 +66,8 @@ public: std::optional const& standardJsonInput() const { return m_standardJsonInput; } private: + void printVersion(); + void printLicense(); bool compile(); bool link(); void writeLinkedFiles(); diff --git a/solc/CommandLineParser.cpp b/solc/CommandLineParser.cpp index 22d92d463..c3448ff8f 100644 --- a/solc/CommandLineParser.cpp +++ b/solc/CommandLineParser.cpp @@ -16,8 +16,6 @@ */ // SPDX-License-Identifier: GPL-3.0 -#include "license.h" - #include #include #include @@ -36,19 +34,12 @@ namespace po = boost::program_options; namespace solidity::frontend { -ostream& CommandLineParser::sout() -{ - m_hasOutput = true; - return m_sout; -} - ostream& CommandLineParser::serr() { m_hasOutput = true; return m_serr; } -#define cout #define cerr static string const g_strAllowPaths = "allow-paths"; @@ -147,26 +138,6 @@ static map const g_inputModeName = { {InputMode::Linker, "linker"}, }; -void CommandLineParser::printVersionAndExit() -{ - sout() << - "solc, the solidity compiler commandline interface" << - endl << - "Version: " << - solidity::frontend::VersionString << - endl; - exit(EXIT_SUCCESS); -} - -void CommandLineParser::printLicenseAndExit() -{ - sout() << otherLicenses << endl; - // This is a static variable generated by cmake from LICENSE.txt - sout() << licenseText << endl; - exit(EXIT_SUCCESS); -} - - bool CommandLineParser::checkMutuallyExclusive(vector const& _optionNames) { if (countEnabledOptions(_optionNames) > 1) @@ -297,11 +268,11 @@ OptimiserSettings CommandLineOptions::optimiserSettings() const return settings; } -bool CommandLineParser::parse(int _argc, char const* const* _argv, bool _interactiveTerminal) +bool CommandLineParser::parse(int _argc, char const* const* _argv) { m_hasOutput = false; - if (!parseArgs(_argc, _argv, _interactiveTerminal)) + if (!parseArgs(_argc, _argv)) return false; return processArgs(); @@ -482,6 +453,10 @@ bool CommandLineParser::parseOutputSelection() switch (_mode) { + case InputMode::Help: + case InputMode::License: + case InputMode::Version: + solAssert(false); case InputMode::Compiler: case InputMode::CompilerWithASTImport: return contains(compilerModeOutputs, _outputName); @@ -847,7 +822,7 @@ po::positional_options_description CommandLineParser::positionalOptionsDescripti return filesPositions; } -bool CommandLineParser::parseArgs(int _argc, char const* const* _argv, bool _interactiveTerminal) +bool CommandLineParser::parseArgs(int _argc, char const* const* _argv) { po::options_description allOptions = optionsDescription(); po::positional_options_description filesPositions = positionalOptionsDescription(); @@ -866,18 +841,6 @@ bool CommandLineParser::parseArgs(int _argc, char const* const* _argv, bool _int return false; } - if (m_args.count(g_strHelp) || (_interactiveTerminal && _argc == 1)) - { - sout() << allOptions; - return false; - } - - if (m_args.count(g_strVersion)) - printVersionAndExit(); - - if (m_args.count(g_strLicense)) - printLicenseAndExit(); - po::notify(m_args); return true; @@ -886,6 +849,9 @@ bool CommandLineParser::parseArgs(int _argc, char const* const* _argv, bool _int bool CommandLineParser::processArgs() { if (!checkMutuallyExclusive({ + g_strHelp, + g_strLicense, + g_strVersion, g_strStandardJSON, g_strLink, g_strAssemble, @@ -895,7 +861,13 @@ bool CommandLineParser::processArgs() })) return false; - if (m_args.count(g_strStandardJSON) > 0) + if (m_args.count(g_strHelp) > 0) + m_options.input.mode = InputMode::Help; + else if (m_args.count(g_strLicense) > 0) + m_options.input.mode = InputMode::License; + else if (m_args.count(g_strVersion) > 0) + m_options.input.mode = InputMode::Version; + else if (m_args.count(g_strStandardJSON) > 0) m_options.input.mode = InputMode::StandardJson; else if (m_args.count(g_strAssemble) > 0 || m_args.count(g_strStrictAssembly) > 0 || m_args.count(g_strYul) > 0) m_options.input.mode = InputMode::Assembler; @@ -906,6 +878,13 @@ bool CommandLineParser::processArgs() else m_options.input.mode = InputMode::Compiler; + if ( + m_options.input.mode == InputMode::Help || + m_options.input.mode == InputMode::License || + m_options.input.mode == InputMode::Version + ) + return true; + map> validOptionInputModeCombinations = { // TODO: This should eventually contain all options. {g_strErrorRecovery, {InputMode::Compiler, InputMode::CompilerWithASTImport}}, diff --git a/solc/CommandLineParser.h b/solc/CommandLineParser.h index ad525ea3b..27a64c7b9 100644 --- a/solc/CommandLineParser.h +++ b/solc/CommandLineParser.h @@ -48,6 +48,9 @@ namespace solidity::frontend enum class InputMode { + Help, + License, + Version, Compiler, CompilerWithASTImport, StandardJson, @@ -230,34 +233,28 @@ struct CommandLineOptions /// Parses the command-line arguments and produces a filled-out CommandLineOptions structure. /// Validates provided values and prints error messages in case of errors. -/// -/// The class is also responsible for handling options that only result in printing informational -/// text, without the need to invoke the compiler - printing usage banner, version or license. class CommandLineParser { public: - explicit CommandLineParser(std::ostream& _sout, std::ostream& _serr): - m_sout(_sout), + explicit CommandLineParser(std::ostream& _serr): m_serr(_serr) {} /// Parses the command-line arguments and fills out the internal CommandLineOptions structure. - /// Performs validation and prints error messages. If requested, prints usage banner, version - /// or license. - /// @param interactiveTerminal specifies whether the terminal is taking input from the user. - /// This is used to determine whether to provide more user-friendly output in some situations. - /// E.g. whether to print help text when no arguments are provided. + /// Performs validation and prints error messages. /// @return true if there were no validation errors when parsing options and the /// CommandLineOptions structure has been fully initialized. false if there were errors - in /// this case CommandLineOptions may be only partially filled out. May also return false if /// there is not further processing necessary and the program should just exit. - bool parse(int _argc, char const* const* _argv, bool _interactiveTerminal); + bool parse(int _argc, char const* const* _argv); CommandLineOptions const& options() const { return m_options; } /// Returns true if the parser has written anything to any of its output streams. bool hasOutput() const { return m_hasOutput; } + static void printHelp(std::ostream& _out) { _out << optionsDescription(); } + private: /// @returns a specification of all named command-line options accepted by the compiler. /// The object can be used to parse command-line arguments or to generate the help screen. @@ -270,7 +267,7 @@ private: /// Uses boost::program_options to parse the command-line arguments and leaves the result in @a m_args. /// Also handles the arguments that result in information being printed followed by immediate exit. /// @returns false if parsing fails due to syntactical errors or the arguments not matching the description. - bool parseArgs(int _argc, char const* const* _argv, bool _interactiveTerminal); + bool parseArgs(int _argc, char const* const* _argv); /// Validates parsed arguments stored in @a m_args and fills out the internal CommandLineOptions /// structure. @@ -294,20 +291,13 @@ private: bool parseOutputSelection(); bool checkMutuallyExclusive(std::vector const& _optionNames); - [[noreturn]] void printVersionAndExit(); - [[noreturn]] void printLicenseAndExit(); size_t countEnabledOptions(std::vector const& _optionNames) const; static std::string joinOptionNames(std::vector const& _optionNames, std::string _separator = ", "); - /// Returns the stream that should receive normal output. Sets m_hasOutput to true if the - /// stream has ever been used. - std::ostream& sout(); - /// Returns the stream that should receive error output. Sets m_hasOutput to true if the /// stream has ever been used. std::ostream& serr(); - std::ostream& m_sout; std::ostream& m_serr; bool m_hasOutput = false; diff --git a/test/solc/CommandLineInterface.cpp b/test/solc/CommandLineInterface.cpp index 3d1fce7d2..739213e8f 100644 --- a/test/solc/CommandLineInterface.cpp +++ b/test/solc/CommandLineInterface.cpp @@ -29,6 +29,8 @@ #include +#include + #include #include @@ -110,9 +112,42 @@ namespace solidity::frontend::test BOOST_AUTO_TEST_SUITE(CommandLineInterfaceTest) +BOOST_AUTO_TEST_CASE(help) +{ + OptionsReaderAndMessages result = parseCommandLineAndReadInputFiles({"solc", "--help"}, "", /* _processInput */ true); + + BOOST_TEST(!result.success); + BOOST_TEST(boost::starts_with(result.stdoutContent, "solc, the Solidity commandline compiler.")); + BOOST_TEST(result.stderrContent == ""); + BOOST_TEST(result.options.input.mode == InputMode::Help); +} + +BOOST_AUTO_TEST_CASE(license) +{ + OptionsReaderAndMessages result = parseCommandLineAndReadInputFiles({"solc", "--license"}, "", /* _processInput */ true); + + BOOST_TEST(result.success); + BOOST_TEST(boost::starts_with(result.stdoutContent, "Most of the code is licensed under GPLv3")); + BOOST_TEST(result.stderrContent == ""); + BOOST_TEST(result.options.input.mode == InputMode::License); +} + +BOOST_AUTO_TEST_CASE(version) +{ + OptionsReaderAndMessages result = parseCommandLineAndReadInputFiles({"solc", "--version"}, "", /* _processInput */ true); + + BOOST_TEST(result.success); + BOOST_TEST(boost::ends_with(result.stdoutContent, "Version: " + solidity::frontend::VersionString + "\n")); + BOOST_TEST(result.stderrContent == ""); + BOOST_TEST(result.options.input.mode == InputMode::Version); +} + BOOST_AUTO_TEST_CASE(multiple_input_modes) { - array inputModeOptions = { + array inputModeOptions = { + "--help", + "--license", + "--version", "--standard-json", "--link", "--assemble", @@ -122,7 +157,7 @@ BOOST_AUTO_TEST_CASE(multiple_input_modes) }; string expectedMessage = "The following options are mutually exclusive: " - "--standard-json, --link, --assemble, --strict-assembly, --yul, --import-ast. " + "--help, --license, --version, --standard-json, --link, --assemble, --strict-assembly, --yul, --import-ast. " "Select at most one.\n"; for (string const& mode1: inputModeOptions) diff --git a/test/solc/CommandLineParser.cpp b/test/solc/CommandLineParser.cpp index 663bf022c..a9ba08d81 100644 --- a/test/solc/CommandLineParser.cpp +++ b/test/solc/CommandLineParser.cpp @@ -30,8 +30,6 @@ #include #include -#include - #include #include #include @@ -48,16 +46,12 @@ using namespace solidity::yul; namespace { -optional parseCommandLine(vector const& _commandLine, ostream& _stdout, ostream& _stderr) +optional parseCommandLine(vector const& _commandLine, ostream& _stderr) { vector argv = test::makeArgv(_commandLine); - CommandLineParser cliParser(_stdout, _stderr); - bool success = cliParser.parse( - static_cast(_commandLine.size()), - argv.data(), - false // interactiveTerminal - ); + CommandLineParser cliParser(_stderr); + bool success = cliParser.parse(static_cast(_commandLine.size()), argv.data()); if (!success) return nullopt; @@ -81,24 +75,34 @@ BOOST_AUTO_TEST_CASE(no_options) expectedOptions.modelChecker.initialize = true; expectedOptions.modelChecker.settings = {}; - stringstream sout, serr; - optional parsedOptions = parseCommandLine(commandLine, sout, serr); + stringstream serr; + optional parsedOptions = parseCommandLine(commandLine, serr); - BOOST_TEST(sout.str() == ""); BOOST_TEST(serr.str() == ""); BOOST_REQUIRE(parsedOptions.has_value()); BOOST_TEST(parsedOptions.value() == expectedOptions); } -BOOST_AUTO_TEST_CASE(help) +BOOST_AUTO_TEST_CASE(help_license_version) { - stringstream sout, serr; - optional parsedOptions = parseCommandLine({"solc", "--help"}, sout, serr); + map expectedModePerOption = { + {"--help", InputMode::Help}, + {"--license", InputMode::License}, + {"--version", InputMode::Version}, + }; - BOOST_TEST(serr.str() == ""); - BOOST_TEST(boost::starts_with(sout.str(), "solc, the Solidity commandline compiler.")); - BOOST_TEST(sout.str().find("Usage: solc [options] [input_file...]") != string::npos); - BOOST_TEST(!parsedOptions.has_value()); + for (auto const& [option, expectedMode]: expectedModePerOption) + { + stringstream serr; + optional parsedOptions = parseCommandLine({"solc", option}, serr); + + CommandLineOptions expectedOptions; + expectedOptions.input.mode = expectedMode; + + BOOST_TEST(serr.str() == ""); + BOOST_REQUIRE(parsedOptions.has_value()); + BOOST_TEST(parsedOptions.value() == expectedOptions); + } } BOOST_AUTO_TEST_CASE(cli_mode_options) @@ -220,10 +224,9 @@ BOOST_AUTO_TEST_CASE(cli_mode_options) 5, }; - stringstream sout, serr; - optional parsedOptions = parseCommandLine(commandLine, sout, serr); + stringstream serr; + optional parsedOptions = parseCommandLine(commandLine, serr); - BOOST_TEST(sout.str() == ""); BOOST_TEST(serr.str() == ""); BOOST_REQUIRE(parsedOptions.has_value()); BOOST_TEST(parsedOptions.value() == expectedOptions); @@ -337,10 +340,9 @@ BOOST_AUTO_TEST_CASE(assembly_mode_options) expectedOptions.optimizer.expectedExecutionsPerDeployment = 1000; } - stringstream sout, serr; - optional parsedOptions = parseCommandLine(commandLine, sout, serr); + stringstream serr; + optional parsedOptions = parseCommandLine(commandLine, serr); - BOOST_TEST(sout.str() == ""); BOOST_TEST(serr.str() == "Warning: Yul is still experimental. Please use the output with care.\n"); BOOST_REQUIRE(parsedOptions.has_value()); BOOST_TEST(parsedOptions.value() == expectedOptions); @@ -406,10 +408,9 @@ BOOST_AUTO_TEST_CASE(standard_json_mode_options) expectedOptions.compiler.combinedJsonRequests->abi = true; expectedOptions.compiler.combinedJsonRequests->binary = true; - stringstream sout, serr; - optional parsedOptions = parseCommandLine(commandLine, sout, serr); + stringstream serr; + optional parsedOptions = parseCommandLine(commandLine, serr); - BOOST_TEST(sout.str() == ""); BOOST_TEST(serr.str() == ""); BOOST_REQUIRE(parsedOptions.has_value()); BOOST_TEST(parsedOptions.value() == expectedOptions); @@ -426,11 +427,10 @@ BOOST_AUTO_TEST_CASE(invalid_options_input_modes_combinations) for (auto const& [optionName, inputModes]: invalidOptionInputModeCombinations) for (string const& inputMode: inputModes) { - stringstream sout, serr; + stringstream serr; vector commandLine = {"solc", optionName, "file", inputMode}; - optional parsedOptions = parseCommandLine(commandLine, sout, serr); + optional parsedOptions = parseCommandLine(commandLine, serr); - BOOST_TEST(sout.str() == ""); BOOST_TEST(serr.str() == "The following options are not supported in the current input mode: " + optionName + "\n"); BOOST_REQUIRE(!parsedOptions.has_value()); } From a1c9c1e2b5bbe87e70a7179353b305c80fba34eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Mon, 11 Oct 2021 13:17:01 +0200 Subject: [PATCH 2/3] CommandLineInterface: Merge processInput() and actOnInput() - The distinction between them is not as clear-cut as it should be. For example processInput() prints output in assembly mode. --- solc/CommandLineInterface.cpp | 47 +++++++++++------------------------ solc/CommandLineInterface.h | 5 +--- solc/main.cpp | 3 +-- test/solc/Common.cpp | 6 ++++- 4 files changed, 21 insertions(+), 40 deletions(-) diff --git a/solc/CommandLineInterface.cpp b/solc/CommandLineInterface.cpp index e86381bf3..1358dd484 100644 --- a/solc/CommandLineInterface.cpp +++ b/solc/CommandLineInterface.cpp @@ -610,10 +610,10 @@ bool CommandLineInterface::processInput() return false; case InputMode::License: printLicense(); - return true; + break; case InputMode::Version: printVersion(); - return true; + break; case InputMode::StandardJson: { solAssert(m_standardJsonInput.has_value(), ""); @@ -621,21 +621,25 @@ bool CommandLineInterface::processInput() StandardCompiler compiler(m_fileReader.reader(), m_options.formatting.json); sout() << compiler.compile(move(m_standardJsonInput.value())) << endl; m_standardJsonInput.reset(); - return true; + break; } case InputMode::Assembler: - { - return assemble(m_options.assembly.inputLanguage, m_options.assembly.targetMachine); - } + if (!assemble(m_options.assembly.inputLanguage, m_options.assembly.targetMachine)) + return false; + break; case InputMode::Linker: - return link(); + if (!link()) + return false; + writeLinkedFiles(); + break; case InputMode::Compiler: case InputMode::CompilerWithASTImport: - return compile(); + if (!compile()) + return false; + outputCompilationResults(); } - solAssert(false, ""); - return false; + return !m_outputFailed; } void CommandLineInterface::printVersion() @@ -883,29 +887,6 @@ void CommandLineInterface::handleAst() } } -bool CommandLineInterface::actOnInput() -{ - switch (m_options.input.mode) - { - case InputMode::Help: - case InputMode::License: - case InputMode::Version: - case InputMode::StandardJson: - case InputMode::Assembler: - // Already done in "processInput" phase. - break; - case InputMode::Linker: - writeLinkedFiles(); - break; - case InputMode::Compiler: - case InputMode::CompilerWithASTImport: - outputCompilationResults(); - break; - } - - return !m_outputFailed; -} - bool CommandLineInterface::link() { solAssert(m_options.input.mode == InputMode::Linker, ""); diff --git a/solc/CommandLineInterface.h b/solc/CommandLineInterface.h index e99ed1c07..ee5057468 100644 --- a/solc/CommandLineInterface.h +++ b/solc/CommandLineInterface.h @@ -55,11 +55,8 @@ public: bool parseArguments(int _argc, char const* const* _argv); /// Read the content of all input files and initialize the file reader. bool readInputFiles(); - /// Parse the files and create source code objects + /// Parse the files, create source code objects, print the output. bool processInput(); - /// Perform actions on the input depending on provided compiler arguments - /// @returns true on success. - bool actOnInput(); CommandLineOptions const& options() const { return m_options; } FileReader const& fileReader() const { return m_fileReader; } diff --git a/solc/main.cpp b/solc/main.cpp index 1299e2564..874ee13ca 100644 --- a/solc/main.cpp +++ b/solc/main.cpp @@ -65,8 +65,7 @@ int main(int argc, char** argv) bool success = cli.parseArguments(argc, argv) && cli.readInputFiles() && - cli.processInput() && - cli.actOnInput(); + cli.processInput(); return success ? 0 : 1; } diff --git a/test/solc/Common.cpp b/test/solc/Common.cpp index 28263e21e..8e40c1af6 100644 --- a/test/solc/Common.cpp +++ b/test/solc/Common.cpp @@ -70,6 +70,10 @@ string test::stripPreReleaseWarning(string const& _stderrContent) R"(Warning( \(3805\))?: This is a pre-release compiler version, please do not use it in production\.\n)" R"((\n)?)" }; + static regex const noOutputRegex{ + R"(Compiler run successful, no output requested\.\n)" + }; - return regex_replace(_stderrContent, preReleaseWarningRegex, ""); + string output = regex_replace(_stderrContent, preReleaseWarningRegex, ""); + return regex_replace(move(output), noOutputRegex, ""); } From 0417db0f6a8474468a74515edddcf6d27c5ba977 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Mon, 11 Oct 2021 13:30:08 +0200 Subject: [PATCH 3/3] Don't return an error from --help --- solc/CommandLineInterface.cpp | 2 +- test/solc/CommandLineInterface.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/solc/CommandLineInterface.cpp b/solc/CommandLineInterface.cpp index 1358dd484..9d2279910 100644 --- a/solc/CommandLineInterface.cpp +++ b/solc/CommandLineInterface.cpp @@ -607,7 +607,7 @@ bool CommandLineInterface::processInput() { case InputMode::Help: CommandLineParser::printHelp(sout()); - return false; + break; case InputMode::License: printLicense(); break; diff --git a/test/solc/CommandLineInterface.cpp b/test/solc/CommandLineInterface.cpp index 739213e8f..0269ec462 100644 --- a/test/solc/CommandLineInterface.cpp +++ b/test/solc/CommandLineInterface.cpp @@ -116,7 +116,7 @@ BOOST_AUTO_TEST_CASE(help) { OptionsReaderAndMessages result = parseCommandLineAndReadInputFiles({"solc", "--help"}, "", /* _processInput */ true); - BOOST_TEST(!result.success); + BOOST_TEST(result.success); BOOST_TEST(boost::starts_with(result.stdoutContent, "solc, the Solidity commandline compiler.")); BOOST_TEST(result.stderrContent == ""); BOOST_TEST(result.options.input.mode == InputMode::Help);