diff --git a/Changelog.md b/Changelog.md index 30bb94742..567c13b1b 100644 --- a/Changelog.md +++ b/Changelog.md @@ -34,6 +34,7 @@ Bugfixes: * SMTChecker: Fix internal error when assigning to a 1-tuple. * State Mutability: Constant public state variables are considered ``pure`` functions. * Type Checker: Fixing deduction issues on function types when function call has named arguments. + * Immutables: Fix internal compiler error when immutables are not assigned. ### 0.6.12 (2020-07-22) diff --git a/libevmasm/Assembly.cpp b/libevmasm/Assembly.cpp index b1de71e3b..c729a4eb4 100644 --- a/libevmasm/Assembly.cpp +++ b/libevmasm/Assembly.cpp @@ -30,6 +30,8 @@ #include #include +#include + #include #include @@ -699,12 +701,10 @@ LinkerObject const& Assembly::assemble() const } } - assertThrow( - immutableReferencesBySub.empty(), - AssemblyException, - "Some immutables were read from but never assigned." - ); - + if (!immutableReferencesBySub.empty()) + throw + langutil::Error(1284_error, langutil::Error::Type::CodeGenerationError) << + util::errinfo_comment("Some immutables were read from but never assigned, possibly because of optimization."); if (!m_subs.empty() || !m_data.empty() || !m_auxiliaryData.empty()) // Append an INVALID here to help tests find miscompilation. diff --git a/liblangutil/Exceptions.cpp b/liblangutil/Exceptions.cpp index 2e9d22b41..0661d5ce5 100644 --- a/liblangutil/Exceptions.cpp +++ b/liblangutil/Exceptions.cpp @@ -33,6 +33,9 @@ Error::Error(ErrorId _errorId, Type _type, SourceLocation const& _location, stri { switch (m_type) { + case Type::CodeGenerationError: + m_typeName = "CodeGenerationError"; + break; case Type::DeclarationError: m_typeName = "DeclarationError"; break; diff --git a/liblangutil/Exceptions.h b/liblangutil/Exceptions.h index 69745a2fc..29acb7ee4 100644 --- a/liblangutil/Exceptions.h +++ b/liblangutil/Exceptions.h @@ -78,6 +78,7 @@ class Error: virtual public util::Exception public: enum class Type { + CodeGenerationError, DeclarationError, DocstringParsingError, ParserError, diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index 27a51552e..41a9040c4 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -516,7 +516,17 @@ bool CompilerStack::compile() if (auto contract = dynamic_cast(node.get())) if (isRequestedContract(*contract)) { - compileContract(*contract, otherCompilers); + try + { + compileContract(*contract, otherCompilers); + } + catch (Error const& _error) + { + if (_error.type() != Error::Type::CodeGenerationError) + throw; + m_errorReporter.error(_error.errorId(), _error.type(), SourceLocation(), _error.what()); + return false; + } if (m_generateIR || m_generateEwasm) generateIR(*contract); if (m_generateEwasm) diff --git a/test/libsolidity/SyntaxTest.cpp b/test/libsolidity/SyntaxTest.cpp index c554366e9..92b246b34 100644 --- a/test/libsolidity/SyntaxTest.cpp +++ b/test/libsolidity/SyntaxTest.cpp @@ -74,7 +74,19 @@ void SyntaxTest::parseAndAnalyze() try { if (!compiler().compile()) - BOOST_THROW_EXCEPTION(runtime_error("Compilation failed even though analysis was successful.")); + { + ErrorList const& errors = compiler().errors(); + auto codeGeneretionErrorCount = count_if(errors.cbegin(), errors.cend(), [](auto const& error) { + return error->type() == Error::Type::CodeGenerationError; + }); + auto errorCount = count_if(errors.cbegin(), errors.cend(), [](auto const& error) { + return error->type() != Error::Type::Warning; + }); + // failing compilation after successful analysis is a rare case, + // it assumes that errors contain exactly one error, and the error is of type Error::Type::CodeGenerationError + if (codeGeneretionErrorCount != 1 || errorCount != 1) + BOOST_THROW_EXCEPTION(runtime_error("Compilation failed even though analysis was successful.")); + } } catch (UnimplementedFeatureError const& _e) { diff --git a/test/libsolidity/syntaxTests/immutable/no_assignments.sol b/test/libsolidity/syntaxTests/immutable/no_assignments.sol new file mode 100644 index 000000000..7357d174a --- /dev/null +++ b/test/libsolidity/syntaxTests/immutable/no_assignments.sol @@ -0,0 +1,13 @@ +contract C { + uint immutable x; + constructor() { + x = 0; + while (true) + {} + } + function f() external view returns(uint) { return x; } +} +// ==== +// optimize-yul: true +// ---- +// CodeGenerationError 1284: Some immutables were read from but never assigned, possibly because of optimization.