diff options
-rw-r--r-- | docs/frequently-asked-questions.rst | 33 | ||||
-rw-r--r-- | libsolidity/ast/Types.cpp | 59 | ||||
-rw-r--r-- | test/libsolidity/SolidityNameAndTypeResolution.cpp | 20 |
3 files changed, 61 insertions, 51 deletions
diff --git a/docs/frequently-asked-questions.rst b/docs/frequently-asked-questions.rst index a6bead29..3c83cbc7 100644 --- a/docs/frequently-asked-questions.rst +++ b/docs/frequently-asked-questions.rst @@ -40,9 +40,9 @@ Is there a decompiler available? ================================ There is no exact decompiler to Solidity, but -`Porosity <https://github.com/comaeio/porosity>`_ is close. -Because some information like variable names, comments, and -source code formatting is lost in the compilation process, +`Porosity <https://github.com/comaeio/porosity>`_ is close. +Because some information like variable names, comments, and +source code formatting is lost in the compilation process, it is not possible to completely recover the original source code. Bytecode can be disassembled to opcodes, a service that is provided by @@ -542,12 +542,27 @@ contract level) with ``arrayname.length = <some new length>;``. If you get the :: - int8[] memory memArr; // Case 1 - memArr.length++; // illegal - int8[5] storageArr; // Case 2 - somearray.length++; // legal - int8[5] storage storageArr2; // Explicit case 2 - somearray2.length++; // legal + // This will not compile + + pragma solidity ^0.4.18; + + contract C { + int8[] dynamicStorageArray; + int8[5] fixedStorageArray; + + function f() { + int8[] memory memArr; // Case 1 + memArr.length++; // illegal + + int8[5] storage storageArr = fixedStorageArray; // Case 2 + storageArr.length++; // illegal + + int8[] storage storageArr2 = dynamicStorageArray; + storageArr2.length++; // legal + + + } + } **Important note:** In Solidity, array dimensions are declared backwards from the way you might be used to declaring them in C or Java, but they are access as in diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp index fadaf621..771ae643 100644 --- a/libsolidity/ast/Types.cpp +++ b/libsolidity/ast/Types.cpp @@ -2164,32 +2164,19 @@ FunctionType::FunctionType(FunctionDefinition const& _function, bool _isInternal m_stateMutability(_function.stateMutability()), m_declaration(&_function) { - TypePointers params; - vector<string> paramNames; - TypePointers retParams; - vector<string> retParamNames; - if (_isInternal && m_stateMutability == StateMutability::Payable) m_stateMutability = StateMutability::NonPayable; - params.reserve(_function.parameters().size()); - paramNames.reserve(_function.parameters().size()); for (ASTPointer<VariableDeclaration> const& var: _function.parameters()) { - paramNames.push_back(var->name()); - params.push_back(var->annotation().type); + m_parameterNames.push_back(var->name()); + m_parameterTypes.push_back(var->annotation().type); } - retParams.reserve(_function.returnParameters().size()); - retParamNames.reserve(_function.returnParameters().size()); for (ASTPointer<VariableDeclaration> const& var: _function.returnParameters()) { - retParamNames.push_back(var->name()); - retParams.push_back(var->annotation().type); + m_returnParameterNames.push_back(var->name()); + m_returnParameterTypes.push_back(var->annotation().type); } - swap(params, m_parameterTypes); - swap(paramNames, m_parameterNames); - swap(retParams, m_returnParameterTypes); - swap(retParamNames, m_returnParameterNames); } FunctionType::FunctionType(VariableDeclaration const& _varDecl): @@ -2197,16 +2184,14 @@ FunctionType::FunctionType(VariableDeclaration const& _varDecl): m_stateMutability(StateMutability::View), m_declaration(&_varDecl) { - TypePointers paramTypes; - vector<string> paramNames; auto returnType = _varDecl.annotation().type; while (true) { if (auto mappingType = dynamic_cast<MappingType const*>(returnType.get())) { - paramTypes.push_back(mappingType->keyType()); - paramNames.push_back(""); + m_parameterTypes.push_back(mappingType->keyType()); + m_parameterNames.push_back(""); returnType = mappingType->valueType(); } else if (auto arrayType = dynamic_cast<ArrayType const*>(returnType.get())) @@ -2215,15 +2200,13 @@ FunctionType::FunctionType(VariableDeclaration const& _varDecl): // Return byte arrays as as whole. break; returnType = arrayType->baseType(); - paramNames.push_back(""); - paramTypes.push_back(make_shared<IntegerType>(256)); + m_parameterNames.push_back(""); + m_parameterTypes.push_back(make_shared<IntegerType>(256)); } else break; } - TypePointers retParams; - vector<string> retParamNames; if (auto structType = dynamic_cast<StructType const*>(returnType.get())) { for (auto const& member: structType->members(nullptr)) @@ -2234,24 +2217,22 @@ FunctionType::FunctionType(VariableDeclaration const& _varDecl): if (auto arrayType = dynamic_cast<ArrayType const*>(member.type.get())) if (!arrayType->isByteArray()) continue; - retParams.push_back(member.type); - retParamNames.push_back(member.name); + m_returnParameterTypes.push_back(ReferenceType::copyForLocationIfReference( + DataLocation::Memory, + member.type + )); + m_returnParameterNames.push_back(member.name); } } } else { - retParams.push_back(ReferenceType::copyForLocationIfReference( + m_returnParameterTypes.push_back(ReferenceType::copyForLocationIfReference( DataLocation::Memory, returnType )); - retParamNames.push_back(""); + m_returnParameterNames.push_back(""); } - - swap(paramTypes, m_parameterTypes); - swap(paramNames, m_parameterNames); - swap(retParams, m_returnParameterTypes); - swap(retParamNames, m_returnParameterNames); } FunctionType::FunctionType(EventDefinition const& _event): @@ -2259,17 +2240,11 @@ FunctionType::FunctionType(EventDefinition const& _event): m_stateMutability(StateMutability::NonPayable), m_declaration(&_event) { - TypePointers params; - vector<string> paramNames; - params.reserve(_event.parameters().size()); - paramNames.reserve(_event.parameters().size()); for (ASTPointer<VariableDeclaration> const& var: _event.parameters()) { - paramNames.push_back(var->name()); - params.push_back(var->annotation().type); + m_parameterNames.push_back(var->name()); + m_parameterTypes.push_back(var->annotation().type); } - swap(params, m_parameterTypes); - swap(paramNames, m_parameterNames); } FunctionType::FunctionType(FunctionTypeName const& _typeName): diff --git a/test/libsolidity/SolidityNameAndTypeResolution.cpp b/test/libsolidity/SolidityNameAndTypeResolution.cpp index 27761066..93abee0d 100644 --- a/test/libsolidity/SolidityNameAndTypeResolution.cpp +++ b/test/libsolidity/SolidityNameAndTypeResolution.cpp @@ -7841,6 +7841,26 @@ BOOST_AUTO_TEST_CASE(old_style_events_050) CHECK_ERROR(text, TypeError, "have to be prefixed"); } +BOOST_AUTO_TEST_CASE(getter_is_memory_type) +{ + char const* text = R"( + contract C { + struct S { string m; } + string[] public x; + S[] public y; + } + )"; + CHECK_SUCCESS_NO_WARNINGS(text); + // Check that the getters return a memory strings, not a storage strings. + ContractDefinition const& c = dynamic_cast<ContractDefinition const&>(*m_compiler.ast("").nodes().at(1)); + BOOST_CHECK(c.interfaceFunctions().size() == 2); + for (auto const& f: c.interfaceFunctions()) + { + auto const& retType = f.second->returnParameterTypes().at(0); + BOOST_CHECK(retType->dataStoredIn(DataLocation::Memory)); + } +} + BOOST_AUTO_TEST_SUITE_END() } |