Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Validate selected compiler outputs on the CLI #12071

Merged
merged 1 commit into from
Oct 11, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ Compiler Features:

Bugfixes:
* Commandline Interface: Fix extra newline character being appended to sources passed through standard input, affecting their hashes.
* Commandline Interface: Report output selection options unsupported by the selected input mode instead of ignoring them.
* SMTChecker: Fix internal error in magic type access (``block``, ``msg``, ``tx``).
* TypeChecker: Fix internal error when using user defined value types in public library functions.

Expand Down
53 changes: 51 additions & 2 deletions solc/CommandLineParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,14 @@ static set<string> const g_metadataHashArgs
g_strNone
};

static map<InputMode, string> const g_inputModeName = {
{InputMode::Compiler, "compiler"},
{InputMode::CompilerWithASTImport, "compiler (AST import)"},
{InputMode::Assembler, "assembler"},
{InputMode::StandardJson, "standard JSON"},
{InputMode::Linker, "linker"},
};

void CommandLineParser::printVersionAndExit()
{
sout() <<
Expand Down Expand Up @@ -460,6 +468,47 @@ bool CommandLineParser::parseLibraryOption(string const& _input)
return true;
}

bool CommandLineParser::parseOutputSelection()
{
static auto outputSupported = [](InputMode _mode, string_view _outputName)
{
static set<string> const compilerModeOutputs =
CompilerOutputs::componentMap() |
ranges::views::keys |
ranges::to<set>();

switch (_mode)
{
case InputMode::Compiler:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, I thought we need explicit [[fallthrough]]; but if this works, great!

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We only need that if there's anything between the labels.

case InputMode::CompilerWithASTImport:
return contains(compilerModeOutputs, _outputName);
case InputMode::Assembler:
case InputMode::StandardJson:
case InputMode::Linker:
return false;
}

solAssert(false, "");
};

for (auto&& [optionName, outputComponent]: CompilerOutputs::componentMap())
m_options.compiler.outputs.*outputComponent = (m_args.count(optionName) > 0);

vector<string> unsupportedOutputs;
for (auto&& [optionName, outputComponent]: CompilerOutputs::componentMap())
if (m_options.compiler.outputs.*outputComponent && !outputSupported(m_options.input.mode, optionName))
unsupportedOutputs.push_back(optionName);

if (!unsupportedOutputs.empty())
{
serr() << "The following outputs are not supported in " << g_inputModeName.at(m_options.input.mode) << " mode: ";
serr() << joinOptionNames(unsupportedOutputs) << ".";
return false;
}

return true;
}

po::options_description CommandLineParser::optionsDescription()
{
// Declare the supported options.
Expand Down Expand Up @@ -930,8 +979,8 @@ bool CommandLineParser::processArgs()
m_options.formatting.json.indent = m_args[g_strJsonIndent].as<uint32_t>();
}

for (auto&& [optionName, outputComponent]: CompilerOutputs::componentMap())
m_options.compiler.outputs.*outputComponent = (m_args.count(optionName) > 0);
if (!parseOutputSelection())
return false;

m_options.compiler.estimateGas = (m_args.count(g_strGas) > 0);

Expand Down
2 changes: 2 additions & 0 deletions solc/CommandLineParser.h
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,8 @@ class CommandLineParser
/// @return false if there are any validation errors, true otherwise.
bool parseLibraryOption(std::string const& _input);

bool parseOutputSelection();

bool checkMutuallyExclusive(std::vector<std::string> const& _optionNames);
[[noreturn]] void printVersionAndExit();
[[noreturn]] void printLicenseAndExit();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
--link --asm --asm-json --opcodes --bin --bin-runtime --abi --ir --ir-optimized --ewasm --hashes --userdoc --devdoc --metadata --storage-layout
1 change: 1 addition & 0 deletions test/cmdlineTests/linker_mode_output_selection_invalid/err
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
The following outputs are not supported in linker mode: --abi, --asm, --asm-json, --bin, --bin-runtime, --devdoc, --ewasm, --hashes, --ir, --ir-optimized, --metadata, --opcodes, --storage-layout, --userdoc.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
1
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
--ast-compact-json --asm --asm-json --opcodes --bin --bin-runtime --abi --ir --ir-optimized --ewasm --hashes --userdoc --devdoc --metadata --storage-layout
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
The following outputs are not supported in standard JSON mode: --abi, --asm, --asm-json, --ast-compact-json, --bin, --bin-runtime, --devdoc, --ewasm, --hashes, --ir, --ir-optimized, --metadata, --opcodes, --storage-layout, --userdoc.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
1
Empty file.
1 change: 1 addition & 0 deletions test/cmdlineTests/strict_asm_output_selection_invalid/args
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
--strict-assembly --asm --asm-json --opcodes --bin --bin-runtime --abi --ir --ir-optimized --ewasm --hashes --userdoc --devdoc --metadata --storage-layout
1 change: 1 addition & 0 deletions test/cmdlineTests/strict_asm_output_selection_invalid/err
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
The following outputs are not supported in assembler mode: --abi, --asm, --asm-json, --bin, --bin-runtime, --devdoc, --ewasm, --hashes, --ir, --ir-optimized, --metadata, --opcodes, --storage-layout, --userdoc.
1 change: 1 addition & 0 deletions test/cmdlineTests/strict_asm_output_selection_invalid/exit
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
1
Empty file.
2 changes: 1 addition & 1 deletion test/cmdlineTests/yul_optimize_runs/args
Original file line number Diff line number Diff line change
@@ -1 +1 @@
--yul --yul-dialect evm --optimize --ir-optimized --optimize-runs 10000
--yul --yul-dialect evm --optimize --optimize-runs 10000
18 changes: 0 additions & 18 deletions test/solc/CommandLineParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -289,10 +289,6 @@ BOOST_AUTO_TEST_CASE(assembly_mode_options)
"underflow,"
"divByZero",
"--model-checker-timeout=5", // Ignored in assembly mode

// Accepted but has no effect in assembly mode
"--ast-compact-json", "--asm", "--asm-json", "--opcodes", "--bin", "--bin-runtime", "--abi",
"--ir", "--ir-optimized", "--ewasm", "--hashes", "--userdoc", "--devdoc", "--metadata", "--storage-layout",
};
commandLine += assemblyOptions;
if (expectedLanguage == AssemblyStack::Language::StrictAssembly || expectedLanguage == AssemblyStack::Language::Ewasm)
Expand Down Expand Up @@ -328,11 +324,6 @@ BOOST_AUTO_TEST_CASE(assembly_mode_options)
};
expectedOptions.formatting.coloredOutput = false;
expectedOptions.formatting.withErrorIds = true;
expectedOptions.compiler.outputs = {
true, true, true, true, true,
true, true, true, true, true,
true, true, true, true, true,
};
if (expectedLanguage == AssemblyStack::Language::StrictAssembly || expectedLanguage == AssemblyStack::Language::Ewasm)
{
expectedOptions.optimizer.enabled = true;
Expand Down Expand Up @@ -388,10 +379,6 @@ BOOST_AUTO_TEST_CASE(standard_json_mode_options)
"underflow,"
"divByZero",
"--model-checker-timeout=5", // Ignored in Standard JSON mode

// Accepted but has no effect in Standard JSON mode
"--ast-compact-json", "--asm", "--asm-json", "--opcodes", "--bin", "--bin-runtime", "--abi",
"--ir", "--ir-optimized", "--ewasm", "--hashes", "--userdoc", "--devdoc", "--metadata", "--storage-layout",
};

CommandLineOptions expectedOptions;
Expand All @@ -408,11 +395,6 @@ BOOST_AUTO_TEST_CASE(standard_json_mode_options)
expectedOptions.formatting.json = JsonFormat {JsonFormat::Pretty, 1};
expectedOptions.formatting.coloredOutput = false;
expectedOptions.formatting.withErrorIds = true;
expectedOptions.compiler.outputs = {
true, true, true, true, true,
true, true, true, true, true,
true, true, true, true, true,
};
expectedOptions.compiler.estimateGas = true;
expectedOptions.compiler.combinedJsonRequests = CombinedJsonRequests{};
expectedOptions.compiler.combinedJsonRequests->abi = true;
Expand Down