diff --git a/Changelog.md b/Changelog.md index aac8ab8b2895..efca354e724b 100644 --- a/Changelog.md +++ b/Changelog.md @@ -19,6 +19,7 @@ Bugfixes: * Commandline Interface: It is no longer possible to specify both ``--optimize-yul`` and ``--no-optimize-yul`` at the same time. * SMTChecker: Fix encoding of side-effects inside ``if`` and ``ternary conditional``statements in the BMC engine. * SMTChecker: Fix false negative when a verification target can be violated only by trusted external call from another public function. + * Standard JSON Interface: Fix an incomplete AST being returned when analysis is interrupted by certain kinds of fatal errors. * Yul Optimizer: Ensure that the assignment of memory slots for variables moved to memory does not depend on AST IDs that may depend on whether additional files are included during compilation. * Yul Optimizer: Fix optimized IR being unnecessarily passed through the Yul optimizer again before bytecode generation. diff --git a/libsolidity/interface/StandardCompiler.cpp b/libsolidity/interface/StandardCompiler.cpp index f18c618e9c6f..9d1ac1f1f3c2 100644 --- a/libsolidity/interface/StandardCompiler.cpp +++ b/libsolidity/interface/StandardCompiler.cpp @@ -1305,15 +1305,21 @@ Json::Value StandardCompiler::compileSolidity(StandardCompiler::InputsAndSetting )); } + bool parsingSuccess = compilerStack.state() >= CompilerStack::State::Parsed; bool analysisPerformed = compilerStack.state() >= CompilerStack::State::AnalysisPerformed; - bool const compilationSuccess = compilerStack.state() == CompilerStack::State::CompilationSuccessful; + bool compilationSuccess = compilerStack.state() == CompilerStack::State::CompilationSuccessful; if (compilerStack.hasError() && !_inputsAndSettings.parserErrorRecovery) analysisPerformed = false; + // If analysis fails, the artifacts inside CompilerStack are potentially incomplete and must not be returned. + // Note that not completing analysis due to stopAfter does not count as a failure. It's neither failure nor success. + bool analysisFailed = !analysisPerformed && _inputsAndSettings.stopAfter >= CompilerStack::State::AnalysisPerformed; + bool compilationFailed = !compilationSuccess && binariesRequested; + /// Inconsistent state - stop here to receive error reports from users if ( - ((binariesRequested && !compilationSuccess) || !analysisPerformed) && + (compilationFailed || !analysisPerformed) && (errors.empty() && _inputsAndSettings.stopAfter >= CompilerStack::State::AnalysisPerformed) ) return formatFatalError(Error::Type::InternalCompilerError, "No error reported, but compilation failed."); @@ -1331,7 +1337,7 @@ Json::Value StandardCompiler::compileSolidity(StandardCompiler::InputsAndSetting output["sources"] = Json::objectValue; unsigned sourceIndex = 0; - if (compilerStack.state() >= CompilerStack::State::Parsed && (!compilerStack.hasError() || _inputsAndSettings.parserErrorRecovery)) + if (parsingSuccess && !analysisFailed && (!compilerStack.hasError() || _inputsAndSettings.parserErrorRecovery)) for (string const& sourceName: compilerStack.sourceNames()) { Json::Value sourceResult = Json::objectValue; diff --git a/test/cmdlineTests/standard_empty_file_name/output.json b/test/cmdlineTests/standard_empty_file_name/output.json index e419d0a5eec0..4e4d84c41c75 100644 --- a/test/cmdlineTests/standard_empty_file_name/output.json +++ b/test/cmdlineTests/standard_empty_file_name/output.json @@ -18,11 +18,5 @@ "type": "DeclarationError" } ], - "sources": - { - "": - { - "id": 0 - } - } + "sources": {} } diff --git a/test/cmdlineTests/standard_outputs_on_analysis_error_fatal_after_current_step/output.json b/test/cmdlineTests/standard_outputs_on_analysis_error_fatal_after_current_step/output.json index 29f3228a7ddd..d47ded5d4018 100644 --- a/test/cmdlineTests/standard_outputs_on_analysis_error_fatal_after_current_step/output.json +++ b/test/cmdlineTests/standard_outputs_on_analysis_error_fatal_after_current_step/output.json @@ -22,106 +22,5 @@ "type": "DeclarationError" } ], - "sources": - { - "C": - { - "ast": - { - "absolutePath": "C", - "exportedSymbols": - { - "f": - [ - 7 - ] - }, - "id": 8, - "license": "GPL-3.0", - "nodeType": "SourceUnit", - "nodes": - [ - { - "id": 1, - "literals": - [ - "solidity", - "*" - ], - "nodeType": "PragmaDirective", - "src": "36:18:0" - }, - { - "body": - { - "id": 6, - "nodeType": "Block", - "src": "261:2:0", - "statements": [] - }, - "id": 7, - "implemented": true, - "kind": "freeFunction", - "modifiers": [], - "name": "f", - "nameLocation": "241:1:0", - "nodeType": "FunctionDefinition", - "parameters": - { - "id": 4, - "nodeType": "ParameterList", - "parameters": - [ - { - "constant": false, - "id": 3, - "mutability": "immutable", - "name": "x", - "nameLocation": "258:1:0", - "nodeType": "VariableDeclaration", - "scope": 7, - "src": "243:16:0", - "stateVariable": false, - "storageLocation": "default", - "typeDescriptions": - { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - }, - "typeName": - { - "id": 2, - "name": "uint", - "nodeType": "ElementaryTypeName", - "src": "243:4:0", - "typeDescriptions": - { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "visibility": "internal" - } - ], - "src": "242:18:0" - }, - "returnParameters": - { - "id": 5, - "nodeType": "ParameterList", - "parameters": [], - "src": "261:0:0" - }, - "scope": 8, - "src": "232:31:0", - "stateMutability": "nonpayable", - "virtual": false, - "visibility": "internal" - } - ], - "src": "36:228:0" - }, - "id": 0 - } - } + "sources": {} }