diff options
Diffstat (limited to 'libsolidity')
-rw-r--r-- | libsolidity/analysis/NameAndTypeResolver.cpp | 6 | ||||
-rw-r--r-- | libsolidity/codegen/ABIFunctions.cpp | 37 | ||||
-rw-r--r-- | libsolidity/codegen/ABIFunctions.h | 6 | ||||
-rw-r--r-- | libsolidity/codegen/ArrayUtils.cpp | 3 | ||||
-rw-r--r-- | libsolidity/codegen/ExpressionCompiler.cpp | 3 | ||||
-rw-r--r-- | libsolidity/interface/CompilerStack.cpp | 11 | ||||
-rw-r--r-- | libsolidity/interface/CompilerStack.h | 11 | ||||
-rw-r--r-- | libsolidity/interface/StandardCompiler.cpp | 19 |
8 files changed, 68 insertions, 28 deletions
diff --git a/libsolidity/analysis/NameAndTypeResolver.cpp b/libsolidity/analysis/NameAndTypeResolver.cpp index 523e7176..5d010693 100644 --- a/libsolidity/analysis/NameAndTypeResolver.cpp +++ b/libsolidity/analysis/NameAndTypeResolver.cpp @@ -647,10 +647,12 @@ void DeclarationRegistrationHelper::registerDeclaration(Declaration& _declaratio bool warnAboutShadowing = true; // Do not warn about shadowing for structs and enums because their members are - // not accessible without prefixes. + // not accessible without prefixes. Also do not warn about event parameters + // because they don't participate in any proper scope. if ( dynamic_cast<StructDefinition const*>(m_currentScope) || - dynamic_cast<EnumDefinition const*>(m_currentScope) + dynamic_cast<EnumDefinition const*>(m_currentScope) || + dynamic_cast<EventDefinition const*>(m_currentScope) ) warnAboutShadowing = false; // Do not warn about the constructor shadowing the contract. diff --git a/libsolidity/codegen/ABIFunctions.cpp b/libsolidity/codegen/ABIFunctions.cpp index 756148e7..080be359 100644 --- a/libsolidity/codegen/ABIFunctions.cpp +++ b/libsolidity/codegen/ABIFunctions.cpp @@ -87,7 +87,7 @@ string ABIFunctions::tupleEncoder( ); elementTempl("values", valueNames); elementTempl("pos", to_string(headPos)); - elementTempl("abiEncode", abiEncodingFunction(*_givenTypes[i], *_targetTypes[i], _encodeAsLibraryTypes, false)); + elementTempl("abiEncode", abiEncodingFunction(*_givenTypes[i], *_targetTypes[i], _encodeAsLibraryTypes, true)); encodeElements += elementTempl.render(); headPos += dynamic ? 0x20 : _targetTypes[i]->calldataEncodedSize(); } @@ -371,7 +371,7 @@ string ABIFunctions::abiEncodingFunction( Type const& _from, Type const& _to, bool _encodeAsLibraryTypes, - bool _compacted + bool _fromStack ) { solUnimplementedAssert( @@ -415,7 +415,7 @@ string ABIFunctions::abiEncodingFunction( dynamic_cast<FunctionType const&>(_from), to, _encodeAsLibraryTypes, - _compacted + _fromStack ); solAssert(_from.sizeOnStack() == 1, ""); @@ -542,7 +542,7 @@ string ABIFunctions::abiEncodingFunctionSimpleArray( mstore(pos, sub(tail, headStart)) tail := <encodeToMemoryFun>(<arrayElementAccess>, tail) srcPtr := <nextArrayElement>(srcPtr) - pos := add(pos, <elementEncodedSize>) + pos := add(pos, 0x20) } pos := tail <assignEnd> @@ -580,7 +580,7 @@ string ABIFunctions::abiEncodingFunctionSimpleArray( *_from.baseType(), *_to.baseType(), _encodeAsLibraryTypes, - true + false )); templ("arrayElementAccess", inMemory ? "mload(srcPtr)" : _from.baseType()->isValueType() ? "sload(srcPtr)" : "srcPtr" ); templ("nextArrayElement", nextArrayElementFunction(_from)); @@ -729,7 +729,7 @@ string ABIFunctions::abiEncodingFunctionCompactStorageArray( *_from.baseType(), *_to.baseType(), _encodeAsLibraryTypes, - true + false ); templ("encodeToMemoryFun", encodeToMemoryFun); std::vector<std::map<std::string, std::string>> items(itemsPerSlot); @@ -925,7 +925,7 @@ string ABIFunctions::abiEncodingFunctionFunctionType( FunctionType const& _from, Type const& _to, bool _encodeAsLibraryTypes, - bool _compacted + bool _fromStack ) { solAssert(_from.kind() == FunctionType::Kind::External, ""); @@ -936,35 +936,31 @@ string ABIFunctions::abiEncodingFunctionFunctionType( _from.identifier() + "_to_" + _to.identifier() + - (_compacted ? "_compacted" : "") + + (_fromStack ? "_fromStack" : "") + (_encodeAsLibraryTypes ? "_library" : ""); - if (_compacted) - { + if (_fromStack) return createFunction(functionName, [&]() { return Whiskers(R"( - function <functionName>(addr_and_function_id, pos) { - mstore(pos, <cleanExtFun>(addr_and_function_id)) + function <functionName>(addr, function_id, pos) { + mstore(pos, <combineExtFun>(addr, function_id)) } )") ("functionName", functionName) - ("cleanExtFun", cleanupCombinedExternalFunctionIdFunction()) + ("combineExtFun", combineExternalFunctionIdFunction()) .render(); }); - } else - { return createFunction(functionName, [&]() { return Whiskers(R"( - function <functionName>(addr, function_id, pos) { - mstore(pos, <combineExtFun>(addr, function_id)) + function <functionName>(addr_and_function_id, pos) { + mstore(pos, <cleanExtFun>(addr_and_function_id)) } )") ("functionName", functionName) - ("combineExtFun", combineExternalFunctionIdFunction()) + ("cleanExtFun", cleanupCombinedExternalFunctionIdFunction()) .render(); }); - } } string ABIFunctions::copyToMemoryFunction(bool _fromCalldata) @@ -1212,10 +1208,7 @@ size_t ABIFunctions::headSize(TypePointers const& _targetTypes) if (t->isDynamicallyEncoded()) headSize += 0x20; else - { - solAssert(t->calldataEncodedSize() > 0, ""); headSize += t->calldataEncodedSize(); - } } return headSize; diff --git a/libsolidity/codegen/ABIFunctions.h b/libsolidity/codegen/ABIFunctions.h index de2a140a..e61f68bc 100644 --- a/libsolidity/codegen/ABIFunctions.h +++ b/libsolidity/codegen/ABIFunctions.h @@ -89,13 +89,13 @@ private: /// @returns the name of the ABI encoding function with the given type /// and queues the generation of the function to the requested functions. - /// @param _compacted if true, the input value was just loaded from storage + /// @param _fromStack if false, the input value was just loaded from storage /// or memory and thus might be compacted into a single slot (depending on the type). std::string abiEncodingFunction( Type const& _givenType, Type const& _targetType, bool _encodeAsLibraryTypes, - bool _compacted + bool _fromStack ); /// Part of @a abiEncodingFunction for array target type and given calldata array. std::string abiEncodingFunctionCalldataArray( @@ -143,7 +143,7 @@ private: FunctionType const& _from, Type const& _to, bool _encodeAsLibraryTypes, - bool _compacted + bool _fromStack ); /// @returns a function that copies raw bytes of dynamic length from calldata diff --git a/libsolidity/codegen/ArrayUtils.cpp b/libsolidity/codegen/ArrayUtils.cpp index e17188c2..ce8cbb5f 100644 --- a/libsolidity/codegen/ArrayUtils.cpp +++ b/libsolidity/codegen/ArrayUtils.cpp @@ -291,8 +291,11 @@ void ArrayUtils::copyArrayToMemory(ArrayType const& _sourceType, bool _padToWord CompilerUtils utils(m_context); unsigned baseSize = 1; if (!_sourceType.isByteArray()) + { // We always pad the elements, regardless of _padToWordBoundaries. baseSize = _sourceType.baseType()->calldataEncodedSize(); + solAssert(baseSize >= 0x20, ""); + } if (_sourceType.location() == DataLocation::CallData) { diff --git a/libsolidity/codegen/ExpressionCompiler.cpp b/libsolidity/codegen/ExpressionCompiler.cpp index c2bf0f5c..fe37baac 100644 --- a/libsolidity/codegen/ExpressionCompiler.cpp +++ b/libsolidity/codegen/ExpressionCompiler.cpp @@ -1714,6 +1714,9 @@ void ExpressionCompiler::appendExternalFunctionCall( if (_functionType.gasSet()) m_context << dupInstruction(m_context.baseToCurrentStackOffset(gasStackPos)); + else if (m_context.experimentalFeatureActive(ExperimentalFeature::V050)) + // Send all gas (requires tangerine whistle EVM) + m_context << Instruction::GAS; else { // send all gas except the amount needed to execute "SUB" and "CALL" diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index 51544f8a..b99fe4ee 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -252,6 +252,14 @@ bool CompilerStack::parseAndAnalyze() return parse() && analyze(); } +bool CompilerStack::isRequestedContract(ContractDefinition const& _contract) const +{ + return + m_requestedContractNames.empty() || + m_requestedContractNames.count(_contract.fullyQualifiedName()) || + m_requestedContractNames.count(_contract.name()); +} + bool CompilerStack::compile() { if (m_stackState < AnalysisSuccessful) @@ -262,7 +270,8 @@ bool CompilerStack::compile() for (Source const* source: m_sourceOrder) for (ASTPointer<ASTNode> const& node: source->ast->nodes()) if (auto contract = dynamic_cast<ContractDefinition const*>(node.get())) - compileContract(*contract, compiledContracts); + if (isRequestedContract(*contract)) + compileContract(*contract, compiledContracts); this->link(); m_stackState = CompilationSuccessful; return true; diff --git a/libsolidity/interface/CompilerStack.h b/libsolidity/interface/CompilerStack.h index f1bbae47..c567ac2c 100644 --- a/libsolidity/interface/CompilerStack.h +++ b/libsolidity/interface/CompilerStack.h @@ -116,6 +116,13 @@ public: m_optimizeRuns = _runs; } + /// Sets the list of requested contract names. If empty, no filtering is performed and every contract + /// found in the supplied sources is compiled. Names are cleared iff @a _contractNames is missing. + void setRequestedContractNames(std::set<std::string> const& _contractNames = std::set<std::string>{}) + { + m_requestedContractNames = _contractNames; + } + /// @arg _metadataLiteralSources When true, store sources as literals in the contract metadata. void useMetadataLiteralSources(bool _metadataLiteralSources) { m_metadataLiteralSources = _metadataLiteralSources; } @@ -259,6 +266,9 @@ private: /// Helper function to return path converted strings. std::string sanitizePath(std::string const& _path) const { return boost::filesystem::path(_path).generic_string(); } + /// @returns true if the contract is requested to be compiled. + bool isRequestedContract(ContractDefinition const& _contract) const; + /// Compile a single contract and put the result in @a _compiledContracts. void compileContract( ContractDefinition const& _contract, @@ -297,6 +307,7 @@ private: ReadCallback::Callback m_smtQuery; bool m_optimize = false; unsigned m_optimizeRuns = 200; + std::set<std::string> m_requestedContractNames; std::map<std::string, h160> m_libraries; /// list of path prefix remappings, e.g. mylibrary: github.com/ethereum = /usr/local/ethereum /// "context:prefix=target" diff --git a/libsolidity/interface/StandardCompiler.cpp b/libsolidity/interface/StandardCompiler.cpp index b4fbbef9..430739ac 100644 --- a/libsolidity/interface/StandardCompiler.cpp +++ b/libsolidity/interface/StandardCompiler.cpp @@ -92,6 +92,22 @@ Json::Value formatErrorWithException( return formatError(_warning, _type, _component, message, formattedMessage, location); } +set<string> requestedContractNames(Json::Value const& _outputSelection) +{ + set<string> names; + for (auto const& sourceName: _outputSelection.getMemberNames()) + { + for (auto const& contractName: _outputSelection[sourceName].getMemberNames()) + { + /// Consider the "all sources" shortcuts as requesting everything. + if (contractName == "*" || contractName == "") + return set<string>(); + names.insert((sourceName == "*" ? "" : sourceName) + ":" + contractName); + } + } + return names; +} + /// Returns true iff @a _hash (hex with 0x prefix) is the Keccak256 hash of the binary data in @a _content. bool hashMatchesContent(string const& _hash, string const& _content) { @@ -265,6 +281,9 @@ Json::Value StandardCompiler::compileInternal(Json::Value const& _input) Json::Value metadataSettings = settings.get("metadata", Json::Value()); m_compilerStack.useMetadataLiteralSources(metadataSettings.get("useLiteralContent", Json::Value(false)).asBool()); + Json::Value outputSelection = settings.get("outputSelection", Json::Value()); + m_compilerStack.setRequestedContractNames(requestedContractNames(outputSelection)); + auto scannerFromSourceName = [&](string const& _sourceName) -> solidity::Scanner const& { return m_compilerStack.scanner(_sourceName); }; try |