diff options
Diffstat (limited to 'libsolidity')
-rw-r--r-- | libsolidity/analysis/ReferencesResolver.cpp | 8 | ||||
-rw-r--r-- | libsolidity/analysis/TypeChecker.cpp | 2 | ||||
-rw-r--r-- | libsolidity/ast/AST.cpp | 4 | ||||
-rw-r--r-- | libsolidity/ast/AST.h | 4 | ||||
-rw-r--r-- | libsolidity/ast/ASTJsonConverter.cpp | 2 | ||||
-rw-r--r-- | libsolidity/ast/Types.cpp | 20 | ||||
-rw-r--r-- | libsolidity/ast/Types.h | 1 | ||||
-rw-r--r-- | libsolidity/codegen/ExpressionCompiler.cpp | 81 | ||||
-rw-r--r-- | libsolidity/parsing/Parser.cpp | 4 | ||||
-rw-r--r-- | libsolidity/parsing/Token.cpp | 4 |
10 files changed, 77 insertions, 53 deletions
diff --git a/libsolidity/analysis/ReferencesResolver.cpp b/libsolidity/analysis/ReferencesResolver.cpp index f33de7b7..8750b47b 100644 --- a/libsolidity/analysis/ReferencesResolver.cpp +++ b/libsolidity/analysis/ReferencesResolver.cpp @@ -332,7 +332,7 @@ void ReferencesResolver::endVisit(VariableDeclaration const& _variable) case Location::Memory: return "\"memory\""; case Location::Storage: return "\"storage\""; case Location::CallData: return "\"calldata\""; - case Location::Default: return "none"; + case Location::Unspecified: return "none"; } return {}; }; @@ -368,12 +368,12 @@ void ReferencesResolver::endVisit(VariableDeclaration const& _variable) // Find correct data location. if (_variable.isEventParameter()) { - solAssert(varLoc == Location::Default, ""); + solAssert(varLoc == Location::Unspecified, ""); typeLoc = DataLocation::Memory; } else if (_variable.isStateVariable()) { - solAssert(varLoc == Location::Default, ""); + solAssert(varLoc == Location::Unspecified, ""); typeLoc = _variable.isConstant() ? DataLocation::Memory : DataLocation::Storage; } else if ( @@ -394,7 +394,7 @@ void ReferencesResolver::endVisit(VariableDeclaration const& _variable) case Location::CallData: typeLoc = DataLocation::CallData; break; - case Location::Default: + case Location::Unspecified: solAssert(!_variable.hasReferenceOrMappingType(), "Data location not properly set."); } diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index fca64f6a..ae733cff 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -1217,7 +1217,7 @@ bool TypeChecker::visit(VariableDeclarationStatement const& _statement) if (ref->dataStoredIn(DataLocation::Storage)) { string errorText{"Uninitialized storage pointer."}; - if (varDecl.referenceLocation() == VariableDeclaration::Location::Default) + if (varDecl.referenceLocation() == VariableDeclaration::Location::Unspecified) errorText += " Did you mean '<type> memory " + varDecl.name() + "'?"; solAssert(m_scope, ""); m_errorReporter.declarationError(varDecl.location(), errorText); diff --git a/libsolidity/ast/AST.cpp b/libsolidity/ast/AST.cpp index 635ab024..8e7a81a6 100644 --- a/libsolidity/ast/AST.cpp +++ b/libsolidity/ast/AST.cpp @@ -517,7 +517,7 @@ set<VariableDeclaration::Location> VariableDeclaration::allowedDataLocations() c using Location = VariableDeclaration::Location; if (!hasReferenceOrMappingType() || isStateVariable() || isEventParameter()) - return set<Location>{ Location::Default }; + return set<Location>{ Location::Unspecified }; else if (isStateVariable() && isConstant()) return set<Location>{ Location::Memory }; else if (isExternalCallableParameter()) @@ -546,7 +546,7 @@ set<VariableDeclaration::Location> VariableDeclaration::allowedDataLocations() c } else // Struct members etc. - return set<Location>{ Location::Default }; + return set<Location>{ Location::Unspecified }; } TypePointer VariableDeclaration::type() const diff --git a/libsolidity/ast/AST.h b/libsolidity/ast/AST.h index b953211d..a5cd277d 100644 --- a/libsolidity/ast/AST.h +++ b/libsolidity/ast/AST.h @@ -655,7 +655,7 @@ private: class VariableDeclaration: public Declaration { public: - enum Location { Default, Storage, Memory, CallData }; + enum Location { Unspecified, Storage, Memory, CallData }; VariableDeclaration( SourceLocation const& _sourceLocation, @@ -666,7 +666,7 @@ public: bool _isStateVar = false, bool _isIndexed = false, bool _isConstant = false, - Location _referenceLocation = Location::Default + Location _referenceLocation = Location::Unspecified ): Declaration(_sourceLocation, _name, _visibility), m_typeName(_type), diff --git a/libsolidity/ast/ASTJsonConverter.cpp b/libsolidity/ast/ASTJsonConverter.cpp index 72b20b3b..beab356c 100644 --- a/libsolidity/ast/ASTJsonConverter.cpp +++ b/libsolidity/ast/ASTJsonConverter.cpp @@ -739,7 +739,7 @@ string ASTJsonConverter::location(VariableDeclaration::Location _location) { switch (_location) { - case VariableDeclaration::Location::Default: + case VariableDeclaration::Location::Unspecified: return "default"; case VariableDeclaration::Location::Storage: return "storage"; diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp index a725618e..a6867dcb 100644 --- a/libsolidity/ast/Types.cpp +++ b/libsolidity/ast/Types.cpp @@ -617,11 +617,11 @@ MemberList::MemberMap IntegerType::nativeMembers(ContractDefinition const*) cons if (isAddress()) return { {"balance", make_shared<IntegerType>(256)}, - {"call", make_shared<FunctionType>(strings{"bytes memory"}, strings{"bool"}, FunctionType::Kind::BareCall, false, StateMutability::Payable)}, - {"callcode", make_shared<FunctionType>(strings{"bytes memory"}, strings{"bool"}, FunctionType::Kind::BareCallCode, false, StateMutability::Payable)}, - {"delegatecall", make_shared<FunctionType>(strings{"bytes memory"}, strings{"bool"}, FunctionType::Kind::BareDelegateCall, false)}, + {"call", make_shared<FunctionType>(strings{"bytes memory"}, strings{"bool", "bytes memory"}, FunctionType::Kind::BareCall, false, StateMutability::Payable)}, + {"callcode", make_shared<FunctionType>(strings{"bytes memory"}, strings{"bool", "bytes memory"}, FunctionType::Kind::BareCallCode, false, StateMutability::Payable)}, + {"delegatecall", make_shared<FunctionType>(strings{"bytes memory"}, strings{"bool", "bytes memory"}, FunctionType::Kind::BareDelegateCall, false)}, {"send", make_shared<FunctionType>(strings{"uint"}, strings{"bool"}, FunctionType::Kind::Send)}, - {"staticcall", make_shared<FunctionType>(strings{"bytes memory"}, strings{"bool"}, FunctionType::Kind::BareStaticCall, false, StateMutability::View)}, + {"staticcall", make_shared<FunctionType>(strings{"bytes memory"}, strings{"bool", "bytes memory"}, FunctionType::Kind::BareStaticCall, false, StateMutability::View)}, {"transfer", make_shared<FunctionType>(strings{"uint"}, strings(), FunctionType::Kind::Transfer)} }; else @@ -2492,7 +2492,14 @@ TypePointers FunctionType::returnParameterTypesWithoutDynamicTypes() const { TypePointers returnParameterTypes = m_returnParameterTypes; - if (m_kind == Kind::External || m_kind == Kind::CallCode || m_kind == Kind::DelegateCall) + if ( + m_kind == Kind::External || + m_kind == Kind::DelegateCall || + m_kind == Kind::BareCall || + m_kind == Kind::BareCallCode || + m_kind == Kind::BareDelegateCall || + m_kind == Kind::BareStaticCall + ) for (auto& param: returnParameterTypes) if (param->isDynamicallySized() && !param->dataStoredIn(DataLocation::Storage)) param = make_shared<InaccessibleDynamicType>(); @@ -2514,7 +2521,6 @@ string FunctionType::richIdentifier() const { case Kind::Internal: id += "internal"; break; case Kind::External: id += "external"; break; - case Kind::CallCode: id += "callcode"; break; case Kind::DelegateCall: id += "delegatecall"; break; case Kind::BareCall: id += "barecall"; break; case Kind::BareCallCode: id += "barecallcode"; break; @@ -2695,7 +2701,6 @@ unsigned FunctionType::sizeOnStack() const switch(kind) { case Kind::External: - case Kind::CallCode: case Kind::DelegateCall: size = 2; break; @@ -2928,7 +2933,6 @@ string FunctionType::externalSignature() const { case Kind::Internal: case Kind::External: - case Kind::CallCode: case Kind::DelegateCall: case Kind::Event: break; diff --git a/libsolidity/ast/Types.h b/libsolidity/ast/Types.h index 0b1b5d6d..b860bf6a 100644 --- a/libsolidity/ast/Types.h +++ b/libsolidity/ast/Types.h @@ -899,7 +899,6 @@ public: { Internal, ///< stack-call using plain JUMP External, ///< external call using CALL - CallCode, ///< external call using CALLCODE, i.e. not exchanging the storage DelegateCall, ///< external call using DELEGATECALL, i.e. not exchanging the storage BareCall, ///< CALL without function hash BareCallCode, ///< CALLCODE without function hash diff --git a/libsolidity/codegen/ExpressionCompiler.cpp b/libsolidity/codegen/ExpressionCompiler.cpp index 53a06090..3e8b7337 100644 --- a/libsolidity/codegen/ExpressionCompiler.cpp +++ b/libsolidity/codegen/ExpressionCompiler.cpp @@ -281,19 +281,19 @@ bool ExpressionCompiler::visit(TupleExpression const& _tuple) if (_tuple.isInlineArray()) { ArrayType const& arrayType = dynamic_cast<ArrayType const&>(*_tuple.annotation().type); - + solAssert(!arrayType.isDynamicallySized(), "Cannot create dynamically sized inline array."); m_context << max(u256(32u), arrayType.memorySize()); utils().allocateMemory(); m_context << Instruction::DUP1; - + for (auto const& component: _tuple.components()) { component->accept(*this); utils().convertType(*component->annotation().type, *arrayType.baseType(), true); - utils().storeInMemoryDynamic(*arrayType.baseType(), true); + utils().storeInMemoryDynamic(*arrayType.baseType(), true); } - + m_context << Instruction::POP; } else @@ -566,7 +566,6 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall) break; } case FunctionType::Kind::External: - case FunctionType::Kind::CallCode: case FunctionType::Kind::DelegateCall: case FunctionType::Kind::BareCall: case FunctionType::Kind::BareCallCode: @@ -1169,7 +1168,6 @@ bool ExpressionCompiler::visit(MemberAccess const& _memberAccess) _memberAccess.expression().accept(*this); m_context << funType->externalIdentifier(); break; - case FunctionType::Kind::CallCode: case FunctionType::Kind::External: case FunctionType::Kind::Creation: case FunctionType::Kind::Send: @@ -1571,7 +1569,7 @@ void ExpressionCompiler::endVisit(Literal const& _literal) { CompilerContext::LocationSetter locationSetter(m_context, _literal); TypePointer type = _literal.annotation().type; - + switch (type->category()) { case Type::Category::RationalNumber: @@ -1830,32 +1828,33 @@ void ExpressionCompiler::appendExternalFunctionCall( solAssert(funKind != FunctionType::Kind::BareStaticCall || m_context.evmVersion().hasStaticCall(), ""); - bool returnSuccessCondition = funKind == FunctionType::Kind::BareCall || funKind == FunctionType::Kind::BareCallCode || funKind == FunctionType::Kind::BareDelegateCall || funKind == FunctionType::Kind::BareStaticCall; - bool isCallCode = funKind == FunctionType::Kind::BareCallCode || funKind == FunctionType::Kind::CallCode; + bool returnSuccessConditionAndReturndata = funKind == FunctionType::Kind::BareCall || funKind == FunctionType::Kind::BareCallCode || funKind == FunctionType::Kind::BareDelegateCall || funKind == FunctionType::Kind::BareStaticCall; + bool isCallCode = funKind == FunctionType::Kind::BareCallCode; bool isDelegateCall = funKind == FunctionType::Kind::BareDelegateCall || funKind == FunctionType::Kind::DelegateCall; bool useStaticCall = funKind == FunctionType::Kind::BareStaticCall || (_functionType.stateMutability() <= StateMutability::View && m_context.evmVersion().hasStaticCall()); bool haveReturndatacopy = m_context.evmVersion().supportsReturndata(); unsigned retSize = 0; - TypePointers returnTypes; - if (returnSuccessCondition) - retSize = 0; // return value actually is success condition - else if (haveReturndatacopy) - returnTypes = _functionType.returnParameterTypes(); - else - returnTypes = _functionType.returnParameterTypesWithoutDynamicTypes(); - bool dynamicReturnSize = false; - for (auto const& retType: returnTypes) - if (retType->isDynamicallyEncoded()) - { - solAssert(haveReturndatacopy, ""); - dynamicReturnSize = true; - retSize = 0; - break; - } + TypePointers returnTypes; + if (!returnSuccessConditionAndReturndata) + { + if (haveReturndatacopy) + returnTypes = _functionType.returnParameterTypes(); else - retSize += retType->calldataEncodedSize(); + returnTypes = _functionType.returnParameterTypesWithoutDynamicTypes(); + + for (auto const& retType: returnTypes) + if (retType->isDynamicallyEncoded()) + { + solAssert(haveReturndatacopy, ""); + dynamicReturnSize = true; + retSize = 0; + break; + } + else + retSize += retType->calldataEncodedSize(); + } // Evaluate arguments. TypePointers argumentTypes; @@ -1959,7 +1958,7 @@ void ExpressionCompiler::appendExternalFunctionCall( bool existenceChecked = false; // Check the the target contract exists (has code) for non-low-level calls. - if (funKind == FunctionType::Kind::External || funKind == FunctionType::Kind::CallCode || funKind == FunctionType::Kind::DelegateCall) + if (funKind == FunctionType::Kind::External || funKind == FunctionType::Kind::DelegateCall) { m_context << Instruction::DUP1 << Instruction::EXTCODESIZE << Instruction::ISZERO; // TODO: error message? @@ -1999,7 +1998,7 @@ void ExpressionCompiler::appendExternalFunctionCall( (_functionType.gasSet() ? 1 : 0) + (!_functionType.isBareCall() ? 1 : 0); - if (returnSuccessCondition) + if (returnSuccessConditionAndReturndata) m_context << swapInstruction(remainsSize); else { @@ -2010,9 +2009,31 @@ void ExpressionCompiler::appendExternalFunctionCall( utils().popStackSlots(remainsSize); - if (returnSuccessCondition) + if (returnSuccessConditionAndReturndata) { - // already there + // success condition is already there + // The return parameter types can be empty, when this function is used as + // an internal helper function e.g. for ``send`` and ``transfer``. In that + // case we're only interested in the success condition, not the return data. + if (!_functionType.returnParameterTypes().empty()) + { + if (haveReturndatacopy) + { + m_context << Instruction::RETURNDATASIZE; + m_context.appendInlineAssembly(R"({ + switch v case 0 { + v := 0x60 + } default { + v := mload(0x40) + mstore(0x40, add(v, and(add(returndatasize(), 0x3f), not(0x1f)))) + mstore(v, returndatasize()) + returndatacopy(add(v, 0x20), 0, returndatasize()) + } + })", {"v"}); + } + else + utils().pushZeroPointer(); + } } else if (funKind == FunctionType::Kind::RIPEMD160) { diff --git a/libsolidity/parsing/Parser.cpp b/libsolidity/parsing/Parser.cpp index 0bee2a91..bfa0ad24 100644 --- a/libsolidity/parsing/Parser.cpp +++ b/libsolidity/parsing/Parser.cpp @@ -564,7 +564,7 @@ ASTPointer<VariableDeclaration> Parser::parseVariableDeclaration( bool isIndexed = false; bool isDeclaredConst = false; Declaration::Visibility visibility(Declaration::Visibility::Default); - VariableDeclaration::Location location = VariableDeclaration::Location::Default; + VariableDeclaration::Location location = VariableDeclaration::Location::Unspecified; ASTPointer<ASTString> identifier; while (true) @@ -592,7 +592,7 @@ ASTPointer<VariableDeclaration> Parser::parseVariableDeclaration( isDeclaredConst = true; else if (_options.allowLocationSpecifier && Token::isLocationSpecifier(token)) { - if (location != VariableDeclaration::Location::Default) + if (location != VariableDeclaration::Location::Unspecified) parserError(string("Location already specified.")); else if (!type) parserError(string("Location specifier needs explicit type name.")); diff --git a/libsolidity/parsing/Token.cpp b/libsolidity/parsing/Token.cpp index 5ce74316..27acb7d4 100644 --- a/libsolidity/parsing/Token.cpp +++ b/libsolidity/parsing/Token.cpp @@ -63,7 +63,7 @@ void ElementaryTypeNameToken::assertDetails(Token::Value _baseType, unsigned con { solAssert(_second == 0, "There should not be a second size argument to type " + string(Token::toString(_baseType)) + "."); solAssert( - _first <= 256 && _first % 8 == 0, + _first <= 256 && _first % 8 == 0, "No elementary type " + string(Token::toString(_baseType)) + to_string(_first) + "." ); } @@ -165,7 +165,7 @@ tuple<Token::Value, unsigned int, unsigned int> Token::fromIdentifierOrKeyword(s else return make_tuple(Token::FixedMxN, m, n); } - } + } } return make_tuple(Token::Identifier, 0, 0); } |