From 8639cf8e3df10bedf8ce808aa7146ac88624df44 Mon Sep 17 00:00:00 2001 From: chriseth Date: Mon, 22 Jun 2015 18:05:13 +0200 Subject: [PATCH] Remove dynamic return types. --- ExpressionCompiler.cpp | 9 ++++++++- Types.cpp | 40 +++++++++++++++++++++++++++++++++++----- Types.h | 23 +++++++++++++++-------- 3 files changed, 58 insertions(+), 14 deletions(-) diff --git a/ExpressionCompiler.cpp b/ExpressionCompiler.cpp index 4714b84e3..7d6ed346a 100644 --- a/ExpressionCompiler.cpp +++ b/ExpressionCompiler.cpp @@ -457,6 +457,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall) strings(), Location::Bare, false, + nullptr, true, true ), @@ -1004,9 +1005,14 @@ void ExpressionCompiler::appendExternalFunctionCall( _functionType.getReturnParameterTypes().empty() ? nullptr : _functionType.getReturnParameterTypes().front().get(); - unsigned retSize = firstReturnType ? firstReturnType->getCalldataEncodedSize() : 0; + unsigned retSize = 0; if (returnSuccessCondition) retSize = 0; // return value actually is success condition + else if (firstReturnType) + { + retSize = firstReturnType->getCalldataEncodedSize(); + solAssert(retSize > 0, "Unable to return dynamic type from external call."); + } // Evaluate arguments. TypePointers argumentTypes; @@ -1123,6 +1129,7 @@ void ExpressionCompiler::appendExternalFunctionCall( //@todo manually update free memory pointer if we accept returning memory-stored objects utils().fetchFreeMemoryPointer(); utils().loadFromMemoryDynamic(*firstReturnType, false, true, false); + } } diff --git a/Types.cpp b/Types.cpp index b90b88846..377b2b157 100644 --- a/Types.cpp +++ b/Types.cpp @@ -822,16 +822,16 @@ string ArrayType::toString(bool _short) const TypePointer ArrayType::externalType() const { if (m_arrayKind != ArrayKind::Ordinary) - return shared_from_this(); + return this->copyForLocation(DataLocation::Memory, true); if (!m_baseType->externalType()) return TypePointer(); if (m_baseType->getCategory() == Category::Array && m_baseType->isDynamicallySized()) return TypePointer(); if (isDynamicallySized()) - return std::make_shared(DataLocation::CallData, m_baseType->externalType()); + return std::make_shared(DataLocation::Memory, m_baseType->externalType()); else - return std::make_shared(DataLocation::CallData, m_baseType->externalType(), m_length); + return std::make_shared(DataLocation::Memory, m_baseType->externalType(), m_length); } TypePointer ArrayType::copyForLocation(DataLocation _location, bool _isPointer) const @@ -903,7 +903,7 @@ MemberList const& ContractType::getMembers() const for (auto const& it: m_contract.getInterfaceFunctions()) members.push_back(MemberList::Member( it.second->getDeclaration().getName(), - it.second, + it.second->removeDynamicReturnTypes(), &it.second->getDeclaration() )); m_members.reset(new MemberList(members)); @@ -1084,7 +1084,11 @@ FunctionType::FunctionType(FunctionDefinition const& _function, bool _isInternal for (ASTPointer const& var: _function.getParameters()) { paramNames.push_back(var->getName()); - params.push_back(var->getType()); + if (_isInternal) + params.push_back(var->getType()); + else + params.push_back(var->getType()->externalType()); + solAssert(!!params.back(), "Function argument type not valid in this context."); } retParams.reserve(_function.getReturnParameters().size()); retParamNames.reserve(_function.getReturnParameters().size()); @@ -1284,6 +1288,7 @@ MemberList const& FunctionType::getMembers() const strings(), Location::SetValue, false, + nullptr, m_gasSet, m_valueSet ) @@ -1300,6 +1305,7 @@ MemberList const& FunctionType::getMembers() const strings(), Location::SetGas, false, + nullptr, m_gasSet, m_valueSet ) @@ -1404,11 +1410,35 @@ TypePointer FunctionType::copyAndSetGasOrValue(bool _setGas, bool _setValue) con m_returnParameterNames, m_location, m_arbitraryParameters, + m_declaration, m_gasSet || _setGas, m_valueSet || _setValue ); } +FunctionTypePointer FunctionType::removeDynamicReturnTypes() const +{ + //@todo make this more intelligent once we support destructuring assignments + TypePointers returnParameterTypes; + vector returnParameterNames; + if (!m_returnParameterTypes.empty() && m_returnParameterTypes.front()->getCalldataEncodedSize() > 0) + { + returnParameterTypes.push_back(m_returnParameterTypes.front()); + returnParameterNames.push_back(m_returnParameterNames.front()); + } + return make_shared( + m_parameterTypes, + returnParameterTypes, + m_parameterNames, + returnParameterNames, + m_location, + m_arbitraryParameters, + m_declaration, + m_gasSet, + m_valueSet + ); +} + vector const FunctionType::getParameterTypeNames() const { vector names; diff --git a/Types.h b/Types.h index cca5dde71..11bc35361 100644 --- a/Types.h +++ b/Types.h @@ -669,17 +669,19 @@ public: strings _returnParameterNames = strings(), Location _location = Location::Internal, bool _arbitraryParameters = false, + Declaration const* _declaration = nullptr, bool _gasSet = false, bool _valueSet = false ): - m_parameterTypes (_parameterTypes), - m_returnParameterTypes (_returnParameterTypes), - m_parameterNames (_parameterNames), - m_returnParameterNames (_returnParameterNames), - m_location (_location), - m_arbitraryParameters (_arbitraryParameters), - m_gasSet (_gasSet), - m_valueSet (_valueSet) + m_parameterTypes(_parameterTypes), + m_returnParameterTypes(_returnParameterTypes), + m_parameterNames(_parameterNames), + m_returnParameterNames(_returnParameterNames), + m_location(_location), + m_arbitraryParameters(_arbitraryParameters), + m_gasSet(_gasSet), + m_valueSet(_valueSet), + m_declaration(_declaration) {} TypePointers const& getParameterTypes() const { return m_parameterTypes; } @@ -733,6 +735,11 @@ public: /// of the parameters to fals. TypePointer copyAndSetGasOrValue(bool _setGas, bool _setValue) const; + /// @returns a copy of this function type where all return parameters of dynamic size are removed. + /// This is needed if external functions are called internally, as they cannot return dynamic + /// values. + FunctionTypePointer removeDynamicReturnTypes() const; + private: static TypePointers parseElementaryTypeVector(strings const& _types);