diff options
-rw-r--r-- | libsolidity/interface/CompilerStack.cpp | 37 | ||||
-rw-r--r-- | libsolidity/interface/CompilerStack.h | 31 | ||||
-rw-r--r-- | solc/CommandLineInterface.cpp | 5 | ||||
-rw-r--r-- | test/libsolidity/AnalysisFramework.cpp | 2 | ||||
-rw-r--r-- | test/libsolidity/GasMeter.cpp | 14 | ||||
-rw-r--r-- | test/libsolidity/SolidityABIJSON.cpp | 2 | ||||
-rw-r--r-- | test/libsolidity/SolidityExecutionFramework.h | 2 | ||||
-rw-r--r-- | test/libsolidity/SolidityNatspecJSON.cpp | 4 |
8 files changed, 56 insertions, 41 deletions
diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index b99fe4ee..5713256a 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -747,22 +747,32 @@ void CompilerStack::compileContract( } } +string const CompilerStack::lastContractName() const +{ + if (m_contracts.empty()) + BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("No compiled contracts found.")); + // try to find some user-supplied contract + string contractName; + for (auto const& it: m_sources) + for (ASTPointer<ASTNode> const& node: it.second.ast->nodes()) + if (auto contract = dynamic_cast<ContractDefinition const*>(node.get())) + contractName = contract->fullyQualifiedName(); + return contractName; +} + CompilerStack::Contract const& CompilerStack::contract(string const& _contractName) const { if (m_contracts.empty()) BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("No compiled contracts found.")); - string contractName = _contractName; - if (_contractName.empty()) - // try to find some user-supplied contract - for (auto const& it: m_sources) - for (ASTPointer<ASTNode> const& node: it.second.ast->nodes()) - if (auto contract = dynamic_cast<ContractDefinition const*>(node.get())) - contractName = contract->fullyQualifiedName(); - auto it = m_contracts.find(contractName); + + auto it = m_contracts.find(_contractName); + if (it != m_contracts.end()) + return it->second; + // To provide a measure of backward-compatibility, if a contract is not located by its // fully-qualified name, a lookup will be attempted purely on the contract's name to see // if anything will satisfy. - if (it == m_contracts.end() && contractName.find(":") == string::npos) + if (_contractName.find(":") == string::npos) { for (auto const& contractEntry: m_contracts) { @@ -773,12 +783,13 @@ CompilerStack::Contract const& CompilerStack::contract(string const& _contractNa string foundName; getline(ss, source, ':'); getline(ss, foundName, ':'); - if (foundName == contractName) return contractEntry.second; + if (foundName == _contractName) + return contractEntry.second; } - // If we get here, both lookup methods failed. - BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Contract " + _contractName + " not found.")); } - return it->second; + + // If we get here, both lookup methods failed. + BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Contract \"" + _contractName + "\" not found.")); } CompilerStack::Source const& CompilerStack::source(string const& _sourceName) const diff --git a/libsolidity/interface/CompilerStack.h b/libsolidity/interface/CompilerStack.h index c567ac2c..b377b3aa 100644 --- a/libsolidity/interface/CompilerStack.h +++ b/libsolidity/interface/CompilerStack.h @@ -155,10 +155,10 @@ public: std::map<std::string, unsigned> sourceIndices() const; /// @returns the previously used scanner, useful for counting lines during error reporting. - Scanner const& scanner(std::string const& _sourceName = "") const; + Scanner const& scanner(std::string const& _sourceName) const; /// @returns the parsed source unit with the supplied name. - SourceUnit const& ast(std::string const& _sourceName = "") const; + SourceUnit const& ast(std::string const& _sourceName) const; /// Helper function for logs printing. Do only use in error cases, it's quite expensive. /// line and columns are numbered starting from 1 with following order: @@ -168,48 +168,51 @@ public: /// @returns a list of the contract names in the sources. std::vector<std::string> contractNames() const; + /// @returns the name of the last contract. + std::string const lastContractName() const; + /// @returns either the contract's name or a mixture of its name and source file, sanitized for filesystem use std::string const filesystemFriendlyName(std::string const& _contractName) const; /// @returns the assembled object for a contract. - eth::LinkerObject const& object(std::string const& _contractName = "") const; + eth::LinkerObject const& object(std::string const& _contractName) const; /// @returns the runtime object for the contract. - eth::LinkerObject const& runtimeObject(std::string const& _contractName = "") const; + eth::LinkerObject const& runtimeObject(std::string const& _contractName) const; /// @returns the bytecode of a contract that uses an already deployed contract via DELEGATECALL. /// The returned bytes will contain a sequence of 20 bytes of the format "XXX...XXX" which have to /// substituted by the actual address. Note that this sequence starts end ends in three X /// characters but can contain anything in between. - eth::LinkerObject const& cloneObject(std::string const& _contractName = "") const; + eth::LinkerObject const& cloneObject(std::string const& _contractName) const; /// @returns normal contract assembly items - eth::AssemblyItems const* assemblyItems(std::string const& _contractName = "") const; + eth::AssemblyItems const* assemblyItems(std::string const& _contractName) const; /// @returns runtime contract assembly items - eth::AssemblyItems const* runtimeAssemblyItems(std::string const& _contractName = "") const; + eth::AssemblyItems const* runtimeAssemblyItems(std::string const& _contractName) const; /// @returns the string that provides a mapping between bytecode and sourcecode or a nullptr /// if the contract does not (yet) have bytecode. - std::string const* sourceMapping(std::string const& _contractName = "") const; + std::string const* sourceMapping(std::string const& _contractName) const; /// @returns the string that provides a mapping between runtime bytecode and sourcecode. /// if the contract does not (yet) have bytecode. - std::string const* runtimeSourceMapping(std::string const& _contractName = "") const; + std::string const* runtimeSourceMapping(std::string const& _contractName) const; /// @return a verbose text representation of the assembly. /// @arg _sourceCodes is the map of input files to source code strings /// Prerequisite: Successful compilation. - std::string assemblyString(std::string const& _contractName = "", StringMap _sourceCodes = StringMap()) const; + std::string assemblyString(std::string const& _contractName, StringMap _sourceCodes = StringMap()) const; /// @returns a JSON representation of the assembly. /// @arg _sourceCodes is the map of input files to source code strings /// Prerequisite: Successful compilation. - Json::Value assemblyJSON(std::string const& _contractName = "", StringMap _sourceCodes = StringMap()) const; + Json::Value assemblyJSON(std::string const& _contractName, StringMap _sourceCodes = StringMap()) const; /// @returns a JSON representing the contract ABI. /// Prerequisite: Successful call to parse or compile. - Json::Value const& contractABI(std::string const& _contractName = "") const; + Json::Value const& contractABI(std::string const& _contractName) const; /// @returns a JSON representing the contract's user documentation. /// Prerequisite: Successful call to parse or compile. @@ -276,8 +279,8 @@ private: ); void link(); - Contract const& contract(std::string const& _contractName = "") const; - Source const& source(std::string const& _sourceName = "") const; + Contract const& contract(std::string const& _contractName) const; + Source const& source(std::string const& _sourceName) const; /// @returns the parsed contract with the supplied name. Throws an exception if the contract /// does not exist. diff --git a/solc/CommandLineInterface.cpp b/solc/CommandLineInterface.cpp index fe1461b4..9e2cb77a 100644 --- a/solc/CommandLineInterface.cpp +++ b/solc/CommandLineInterface.cpp @@ -938,9 +938,10 @@ void CommandLineInterface::handleAst(string const& _argStr) for (auto const& sourceCode: m_sourceCodes) asts.push_back(&m_compiler->ast(sourceCode.first)); map<ASTNode const*, eth::GasMeter::GasConsumption> gasCosts; - if (m_compiler->runtimeAssemblyItems()) + // FIXME: shouldn't this be done for every contract? + if (m_compiler->runtimeAssemblyItems(m_compiler->lastContractName())) gasCosts = GasEstimator::breakToStatementLevel( - GasEstimator::structuralEstimation(*m_compiler->runtimeAssemblyItems(), asts), + GasEstimator::structuralEstimation(*m_compiler->runtimeAssemblyItems(m_compiler->lastContractName()), asts), asts ); diff --git a/test/libsolidity/AnalysisFramework.cpp b/test/libsolidity/AnalysisFramework.cpp index 3bdc40a0..ea9703ea 100644 --- a/test/libsolidity/AnalysisFramework.cpp +++ b/test/libsolidity/AnalysisFramework.cpp @@ -81,7 +81,7 @@ AnalysisFramework::parseAnalyseAndReturnError( } } - return make_pair(&m_compiler.ast(), firstError); + return make_pair(&m_compiler.ast(""), firstError); } SourceUnit const* AnalysisFramework::parseAndAnalyse(string const& _source) diff --git a/test/libsolidity/GasMeter.cpp b/test/libsolidity/GasMeter.cpp index c2886f5b..86e8201b 100644 --- a/test/libsolidity/GasMeter.cpp +++ b/test/libsolidity/GasMeter.cpp @@ -51,8 +51,8 @@ public: m_compiler.setOptimiserSettings(dev::test::Options::get().optimize); BOOST_REQUIRE_MESSAGE(m_compiler.compile(), "Compiling contract failed"); - AssemblyItems const* items = m_compiler.runtimeAssemblyItems(""); - ASTNode const& sourceUnit = m_compiler.ast(); + AssemblyItems const* items = m_compiler.runtimeAssemblyItems(m_compiler.lastContractName()); + ASTNode const& sourceUnit = m_compiler.ast(""); BOOST_REQUIRE(items != nullptr); m_gasCosts = GasEstimator::breakToStatementLevel( GasEstimator::structuralEstimation(*items, vector<ASTNode const*>({&sourceUnit})), @@ -64,13 +64,13 @@ public: { compileAndRun(_sourceCode); auto state = make_shared<KnownState>(); - PathGasMeter meter(*m_compiler.assemblyItems()); + PathGasMeter meter(*m_compiler.assemblyItems(m_compiler.lastContractName())); GasMeter::GasConsumption gas = meter.estimateMax(0, state); - u256 bytecodeSize(m_compiler.runtimeObject().bytecode.size()); + u256 bytecodeSize(m_compiler.runtimeObject(m_compiler.lastContractName()).bytecode.size()); // costs for deployment gas += bytecodeSize * GasCosts::createDataGas; // costs for transaction - gas += gasForTransaction(m_compiler.object().bytecode, true); + gas += gasForTransaction(m_compiler.object(m_compiler.lastContractName()).bytecode, true); BOOST_REQUIRE(!gas.isInfinite); BOOST_CHECK(gas.value == m_gasUsed); @@ -91,7 +91,7 @@ public: } gas += GasEstimator::functionalEstimation( - *m_compiler.runtimeAssemblyItems(), + *m_compiler.runtimeAssemblyItems(m_compiler.lastContractName()), _sig ); BOOST_REQUIRE(!gas.isInfinite); @@ -135,7 +135,7 @@ BOOST_AUTO_TEST_CASE(non_overlapping_filtered_costs) if (first->first->location().intersects(second->first->location())) { BOOST_CHECK_MESSAGE(false, "Source locations should not overlap!"); - auto scannerFromSource = [&](string const&) -> Scanner const& { return m_compiler.scanner(); }; + auto scannerFromSource = [&](string const& _sourceName) -> Scanner const& { return m_compiler.scanner(_sourceName); }; SourceReferenceFormatter::printSourceLocation(cout, &first->first->location(), scannerFromSource); SourceReferenceFormatter::printSourceLocation(cout, &second->first->location(), scannerFromSource); } diff --git a/test/libsolidity/SolidityABIJSON.cpp b/test/libsolidity/SolidityABIJSON.cpp index 42f7525f..33962730 100644 --- a/test/libsolidity/SolidityABIJSON.cpp +++ b/test/libsolidity/SolidityABIJSON.cpp @@ -46,7 +46,7 @@ public: m_compilerStack.addSource("", "pragma solidity >=0.0;\n" + _code); BOOST_REQUIRE_MESSAGE(m_compilerStack.parseAndAnalyze(), "Parsing contract failed"); - Json::Value generatedInterface = m_compilerStack.contractABI(""); + Json::Value generatedInterface = m_compilerStack.contractABI(m_compilerStack.lastContractName()); Json::Value expectedInterface; BOOST_REQUIRE(m_reader.parse(_expectedInterfaceString, expectedInterface)); BOOST_CHECK_MESSAGE( diff --git a/test/libsolidity/SolidityExecutionFramework.h b/test/libsolidity/SolidityExecutionFramework.h index 342d0875..b0daaba9 100644 --- a/test/libsolidity/SolidityExecutionFramework.h +++ b/test/libsolidity/SolidityExecutionFramework.h @@ -69,7 +69,7 @@ public: ); BOOST_ERROR("Compiling contract failed"); } - eth::LinkerObject obj = m_compiler.object(_contractName); + eth::LinkerObject obj = m_compiler.object(_contractName.empty() ? m_compiler.lastContractName() : _contractName); BOOST_REQUIRE(obj.linkReferences.empty()); sendMessage(obj.bytecode + _arguments, true, _value); return m_output; diff --git a/test/libsolidity/SolidityNatspecJSON.cpp b/test/libsolidity/SolidityNatspecJSON.cpp index d83773bc..fb09451f 100644 --- a/test/libsolidity/SolidityNatspecJSON.cpp +++ b/test/libsolidity/SolidityNatspecJSON.cpp @@ -51,9 +51,9 @@ public: Json::Value generatedDocumentation; if (_userDocumentation) - generatedDocumentation = m_compilerStack.natspecUser(""); + generatedDocumentation = m_compilerStack.natspecUser(m_compilerStack.lastContractName()); else - generatedDocumentation = m_compilerStack.natspecDev(""); + generatedDocumentation = m_compilerStack.natspecDev(m_compilerStack.lastContractName()); Json::Value expectedDocumentation; m_reader.parse(_expectedDocumentationString, expectedDocumentation); BOOST_CHECK_MESSAGE( |