diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index dc6536499..e0ac3f9d5 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -1224,10 +1224,10 @@ bool TypeChecker::visit(TupleExpression const& _tuple) if (!dynamic_cast(*types[i]).mobileType()) m_errorReporter.fatalTypeError(components[i]->location(), "Invalid rational number."); - if (_tuple.isInlineArray()) - solAssert(!!types[i], "Inline array cannot have empty components"); if (_tuple.isInlineArray()) { + solAssert(!!types[i], "Inline array cannot have empty components"); + if ((i == 0 || inlineArrayType) && !types[i]->mobileType()) m_errorReporter.fatalTypeError(components[i]->location(), "Invalid mobile type."); @@ -1677,17 +1677,10 @@ void TypeChecker::typeCheckFunctionGeneralChecks( { auto const& parameterNames = _functionType->parameterNames(); - // Check for expected number of named arguments - if (parameterNames.size() != argumentNames.size()) - { - m_errorReporter.typeError( - _functionCall.location(), - parameterNames.size() > argumentNames.size() ? - "Some argument names are missing." : - "Too many arguments." - ); - return; - } + solAssert( + parameterNames.size() == argumentNames.size(), + "Unexpected parameter length mismatch!" + ); // Check for duplicate argument names { @@ -1971,8 +1964,8 @@ void TypeChecker::endVisit(NewExpression const& _newExpression) _newExpression.annotation().type = make_shared( TypePointers{make_shared(256)}, TypePointers{type}, - strings(), - strings(), + strings(1, ""), + strings(1, ""), FunctionType::Kind::ObjectCreation, false, StateMutability::Pure diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp index 04d2602d9..cca632446 100644 --- a/libsolidity/ast/Types.cpp +++ b/libsolidity/ast/Types.cpp @@ -1836,8 +1836,8 @@ MemberList::MemberMap ArrayType::nativeMembers(ContractDefinition const*) const members.emplace_back("pop", make_shared( TypePointers{}, TypePointers{}, - strings{string()}, - strings{string()}, + strings{}, + strings{}, FunctionType::Kind::ArrayPop )); } @@ -2191,7 +2191,7 @@ FunctionTypePointer StructType::constructorType() const paramTypes, TypePointers{copyForLocation(DataLocation::Memory, false)}, paramNames, - strings(), + strings(1, ""), FunctionType::Kind::Internal ); } @@ -2423,6 +2423,16 @@ FunctionType::FunctionType(FunctionDefinition const& _function, bool _isInternal m_returnParameterNames.push_back(var->name()); m_returnParameterTypes.push_back(var->annotation().type); } + + solAssert( + m_parameterNames.size() == m_parameterTypes.size(), + "Parameter names list must match parameter types list!" + ); + + solAssert( + m_returnParameterNames.size() == m_returnParameterTypes.size(), + "Return parameter names list must match return parameter types list!" + ); } FunctionType::FunctionType(VariableDeclaration const& _varDecl): @@ -2479,6 +2489,15 @@ FunctionType::FunctionType(VariableDeclaration const& _varDecl): )); m_returnParameterNames.emplace_back(""); } + + solAssert( + m_parameterNames.size() == m_parameterTypes.size(), + "Parameter names list must match parameter types list!" + ); + solAssert( + m_returnParameterNames.size() == m_returnParameterTypes.size(), + "Return parameter names list must match return parameter types list!" + ); } FunctionType::FunctionType(EventDefinition const& _event): @@ -2491,9 +2510,20 @@ FunctionType::FunctionType(EventDefinition const& _event): m_parameterNames.push_back(var->name()); m_parameterTypes.push_back(var->annotation().type); } + + solAssert( + m_parameterNames.size() == m_parameterTypes.size(), + "Parameter names list must match parameter types list!" + ); + solAssert( + m_returnParameterNames.size() == m_returnParameterTypes.size(), + "Return parameter names list must match return parameter types list!" + ); } FunctionType::FunctionType(FunctionTypeName const& _typeName): + m_parameterNames(_typeName.parameterTypes().size(), ""), + m_returnParameterNames(_typeName.returnParameterTypes().size(), ""), m_kind(_typeName.visibility() == VariableDeclaration::Visibility::External ? Kind::External : Kind::Internal), m_stateMutability(_typeName.stateMutability()) { @@ -2519,6 +2549,15 @@ FunctionType::FunctionType(FunctionTypeName const& _typeName): ); m_returnParameterTypes.push_back(t->annotation().type); } + + solAssert( + m_parameterNames.size() == m_parameterTypes.size(), + "Parameter names list must match parameter types list!" + ); + solAssert( + m_returnParameterNames.size() == m_returnParameterTypes.size(), + "Return parameter names list must match return parameter types list!" + ); } FunctionTypePointer FunctionType::newExpressionType(ContractDefinition const& _contract) @@ -2856,8 +2895,8 @@ MemberList::MemberMap FunctionType::nativeMembers(ContractDefinition const*) con make_shared( parseElementaryTypeVector({"uint"}), TypePointers{copyAndSetGasOrValue(false, true)}, - strings(), - strings(), + strings(1, ""), + strings(1, ""), Kind::SetValue, false, StateMutability::NonPayable, @@ -2873,8 +2912,8 @@ MemberList::MemberMap FunctionType::nativeMembers(ContractDefinition const*) con make_shared( parseElementaryTypeVector({"uint"}), TypePointers{copyAndSetGasOrValue(true, false)}, - strings(), - strings(), + strings(1, ""), + strings(1, ""), Kind::SetGas, false, StateMutability::NonPayable, @@ -3377,7 +3416,7 @@ MemberList::MemberMap MagicType::nativeMembers(ContractDefinition const*) const TypePointers(), TypePointers{make_shared(DataLocation::Memory)}, strings{}, - strings{}, + strings{1, ""}, FunctionType::Kind::ABIEncode, true, StateMutability::Pure @@ -3386,7 +3425,7 @@ MemberList::MemberMap MagicType::nativeMembers(ContractDefinition const*) const TypePointers(), TypePointers{make_shared(DataLocation::Memory)}, strings{}, - strings{}, + strings{1, ""}, FunctionType::Kind::ABIEncodePacked, true, StateMutability::Pure @@ -3394,8 +3433,8 @@ MemberList::MemberMap MagicType::nativeMembers(ContractDefinition const*) const {"encodeWithSelector", make_shared( TypePointers{make_shared(4)}, TypePointers{make_shared(DataLocation::Memory)}, - strings{}, - strings{}, + strings{1, ""}, + strings{1, ""}, FunctionType::Kind::ABIEncodeWithSelector, true, StateMutability::Pure @@ -3403,8 +3442,8 @@ MemberList::MemberMap MagicType::nativeMembers(ContractDefinition const*) const {"encodeWithSignature", make_shared( TypePointers{make_shared(DataLocation::Memory, true)}, TypePointers{make_shared(DataLocation::Memory)}, - strings{}, - strings{}, + strings{1, ""}, + strings{1, ""}, FunctionType::Kind::ABIEncodeWithSignature, true, StateMutability::Pure diff --git a/libsolidity/ast/Types.h b/libsolidity/ast/Types.h index 53109de15..bd249c633 100644 --- a/libsolidity/ast/Types.h +++ b/libsolidity/ast/Types.h @@ -1012,8 +1012,8 @@ public: ): FunctionType( parseElementaryTypeVector(_parameterTypes), parseElementaryTypeVector(_returnParameterTypes), - strings(), - strings(), + strings(_parameterTypes.size(), ""), + strings(_returnParameterTypes.size(), ""), _kind, _arbitraryParameters, _stateMutability @@ -1050,6 +1050,14 @@ public: m_bound(_bound), m_declaration(_declaration) { + solAssert( + m_parameterNames.size() == m_parameterTypes.size(), + "Parameter names list must match parameter types list!" + ); + solAssert( + m_returnParameterNames.size() == m_returnParameterTypes.size(), + "Return parameter names list must match return parameter types list!" + ); solAssert( !m_bound || !m_parameterTypes.empty(), "Attempted construction of bound function without self type" diff --git a/test/libsolidity/SolidityTypes.cpp b/test/libsolidity/SolidityTypes.cpp index 251835fe2..050fdaf2e 100644 --- a/test/libsolidity/SolidityTypes.cpp +++ b/test/libsolidity/SolidityTypes.cpp @@ -197,7 +197,7 @@ BOOST_AUTO_TEST_CASE(type_identifiers) TypePointer keccak256fun = make_shared(strings{}, strings{}, FunctionType::Kind::KECCAK256); BOOST_CHECK_EQUAL(keccak256fun->identifier(), "t_function_keccak256_nonpayable$__$returns$__$"); - FunctionType metaFun(TypePointers{keccak256fun}, TypePointers{s.type()}); + FunctionType metaFun(TypePointers{keccak256fun}, TypePointers{s.type()}, strings{""}, strings{""}); BOOST_CHECK_EQUAL(metaFun.identifier(), "t_function_internal_nonpayable$_t_function_keccak256_nonpayable$__$returns$__$_$returns$_t_type$_t_struct$_Struct_$3_storage_ptr_$_$"); TypePointer m = make_shared(Type::fromElementaryTypeName("bytes32"), s.type());