From 293690e5a444df780a2306b68a503b480f33e342 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Tue, 4 Apr 2023 15:19:37 +0200 Subject: [PATCH 1/2] Add util::capitalized() and Type::categoryName() --- libsolidity/ast/Types.cpp | 29 +++++++++++++++++++++++++++++ libsolidity/ast/Types.h | 25 ++++++++++++++++++++++--- libsolutil/StringUtils.h | 9 +++++++++ 3 files changed, 60 insertions(+), 3 deletions(-) diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp index 8fa330da4..c2356ad81 100644 --- a/libsolidity/ast/Types.cpp +++ b/libsolidity/ast/Types.cpp @@ -294,6 +294,35 @@ Type const* Type::commonType(Type const* _a, Type const* _b) return nullptr; } +char const* Type::categoryName(Type::Category _category) +{ + switch (_category) + { + case Category::Address: return "address"; + case Category::Integer: return "integer"; + case Category::RationalNumber: return "rational number literal"; + case Category::StringLiteral: return "string literal"; + case Category::Bool: return "boolean"; + case Category::FixedPoint: return "fixed-point number"; + case Category::Array: return "array"; + case Category::ArraySlice: return "array slice"; + case Category::FixedBytes: return "fixed-size byte array"; + case Category::Contract: return "contract"; + case Category::Struct: return "struct"; + case Category::Function: return "function"; + case Category::Enum: return "enum"; + case Category::UserDefinedValueType: return "user-defined value type"; + case Category::Tuple: return "tuple"; + case Category::Mapping: return "mapping"; + case Category::TypeType: return "type of a type"; + case Category::Modifier: return "modifier"; + case Category::Magic: return "magic variable"; + case Category::Module: return "module"; + case Category::InaccessibleDynamic: return "inaccessible dynamic value"; + } + util::unreachable(); +} + MemberList const& Type::members(ASTNode const* _currentScope) const { if (!m_members[_currentScope]) diff --git a/libsolidity/ast/Types.h b/libsolidity/ast/Types.h index d7312aa1d..9c6389a29 100644 --- a/libsolidity/ast/Types.h +++ b/libsolidity/ast/Types.h @@ -174,9 +174,26 @@ public: enum class Category { - Address, Integer, RationalNumber, StringLiteral, Bool, FixedPoint, Array, ArraySlice, - FixedBytes, Contract, Struct, Function, Enum, UserDefinedValueType, Tuple, - Mapping, TypeType, Modifier, Magic, Module, + Address, + Integer, + RationalNumber, + StringLiteral, + Bool, + FixedPoint, + Array, + ArraySlice, + FixedBytes, + Contract, + Struct, + Function, + Enum, + UserDefinedValueType, + Tuple, + Mapping, + TypeType, + Modifier, + Magic, + Module, InaccessibleDynamic }; @@ -184,6 +201,8 @@ public: static Type const* commonType(Type const* _a, Type const* _b); virtual Category category() const = 0; + static char const* categoryName(Type::Category _category); + /// @returns a valid solidity identifier such that two types should compare equal if and /// only if they have the same identifier. /// The identifier should start with "t_". diff --git a/libsolutil/StringUtils.h b/libsolutil/StringUtils.h index 0d5bc7839..b01dba63b 100644 --- a/libsolutil/StringUtils.h +++ b/libsolutil/StringUtils.h @@ -160,6 +160,15 @@ inline std::string toLower(std::string _s) return _s; } +/// Returns a copy of the string with the first character converted to its uppercase equivalent. +/// Uses the classic "C" locale semantics. +inline std::string capitalized(std::string _s) +{ + if (_s.size() > 0) + _s[0] = toUpper(_s[0]); + return _s; +} + /// Checks whether _c is a decimal digit character. It uses the classic "C" locale semantics. /// @param _c character to be checked /// @return true if _c is a decimal digit character, false otherwise From a019f400d080aeab3fd02fd4e7b699e965a893f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Mon, 3 Apr 2023 16:30:42 +0200 Subject: [PATCH 2/2] Better error message when trying to call things that are not functions --- libsolidity/analysis/TypeChecker.cpp | 6 +++++- .../functionCalls/enum_value_not_callable.sol | 7 +++++++ .../syntaxTests/functionCalls/int_not_callable.sol | 2 +- .../syntaxTests/functionCalls/magic_not_callable.sol | 5 +++++ .../syntaxTests/functionCalls/mapping_not_callable.sol | 6 ++++++ .../syntaxTests/functionCalls/modifier_not_callable.sol | 7 +++++++ .../syntaxTests/functionCalls/module_not_callable.sol | 9 +++++++++ .../syntaxTests/functionCalls/this_not_callable.sol | 2 +- .../nameAndTypeResolution/462_callable_crash.sol | 2 +- .../492_do_not_crash_on_not_lvalue.sol | 2 +- .../state_variable_function_conflict_former_crash.sol | 2 +- .../tupleAssignments/double_storage_crash.sol | 2 +- .../libsolidity/syntaxTests/types/function_call_fail.sol | 2 +- 13 files changed, 46 insertions(+), 8 deletions(-) create mode 100644 test/libsolidity/syntaxTests/functionCalls/enum_value_not_callable.sol create mode 100644 test/libsolidity/syntaxTests/functionCalls/magic_not_callable.sol create mode 100644 test/libsolidity/syntaxTests/functionCalls/mapping_not_callable.sol create mode 100644 test/libsolidity/syntaxTests/functionCalls/modifier_not_callable.sol create mode 100644 test/libsolidity/syntaxTests/functionCalls/module_not_callable.sol diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index 717fa043b..efbbc5741 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -2847,7 +2847,11 @@ bool TypeChecker::visit(FunctionCall const& _functionCall) } default: - m_errorReporter.fatalTypeError(5704_error, _functionCall.location(), "Type is not callable"); + m_errorReporter.fatalTypeError( + 5704_error, + _functionCall.location(), + capitalized(Type::categoryName(expressionType->category())) + " is not callable." + ); // Unreachable, because fatalTypeError throws. We don't set kind, but that's okay because the switch below // is never reached. And, even if it was, SetOnce would trigger an assertion violation and not UB. funcCallAnno.isPure = argumentsArePure; diff --git a/test/libsolidity/syntaxTests/functionCalls/enum_value_not_callable.sol b/test/libsolidity/syntaxTests/functionCalls/enum_value_not_callable.sol new file mode 100644 index 000000000..0735f446f --- /dev/null +++ b/test/libsolidity/syntaxTests/functionCalls/enum_value_not_callable.sol @@ -0,0 +1,7 @@ +enum E { A, B, C } + +contract C { + uint a = E.B(1000); +} +// ---- +// TypeError 5704: (46-55): Enum is not callable. diff --git a/test/libsolidity/syntaxTests/functionCalls/int_not_callable.sol b/test/libsolidity/syntaxTests/functionCalls/int_not_callable.sol index 5c7260f36..5481ff1a3 100644 --- a/test/libsolidity/syntaxTests/functionCalls/int_not_callable.sol +++ b/test/libsolidity/syntaxTests/functionCalls/int_not_callable.sol @@ -5,4 +5,4 @@ contract C } } // ---- -// TypeError 5704: (53-60): Type is not callable +// TypeError 5704: (53-60): Rational number literal is not callable. diff --git a/test/libsolidity/syntaxTests/functionCalls/magic_not_callable.sol b/test/libsolidity/syntaxTests/functionCalls/magic_not_callable.sol new file mode 100644 index 000000000..b74685d4b --- /dev/null +++ b/test/libsolidity/syntaxTests/functionCalls/magic_not_callable.sol @@ -0,0 +1,5 @@ +contract C { + uint a = msg(1000); +} +// ---- +// TypeError 5704: (26-35): Magic variable is not callable. diff --git a/test/libsolidity/syntaxTests/functionCalls/mapping_not_callable.sol b/test/libsolidity/syntaxTests/functionCalls/mapping_not_callable.sol new file mode 100644 index 000000000..d06712999 --- /dev/null +++ b/test/libsolidity/syntaxTests/functionCalls/mapping_not_callable.sol @@ -0,0 +1,6 @@ +contract C { + mapping (uint => uint) m; + uint a = m(1000); +} +// ---- +// TypeError 5704: (56-63): Mapping is not callable. diff --git a/test/libsolidity/syntaxTests/functionCalls/modifier_not_callable.sol b/test/libsolidity/syntaxTests/functionCalls/modifier_not_callable.sol new file mode 100644 index 000000000..31ef66fe1 --- /dev/null +++ b/test/libsolidity/syntaxTests/functionCalls/modifier_not_callable.sol @@ -0,0 +1,7 @@ +contract C { + uint a = m(1000); + + modifier m(uint) { _; } +} +// ---- +// TypeError 5704: (26-33): Modifier is not callable. diff --git a/test/libsolidity/syntaxTests/functionCalls/module_not_callable.sol b/test/libsolidity/syntaxTests/functionCalls/module_not_callable.sol new file mode 100644 index 000000000..63debdab7 --- /dev/null +++ b/test/libsolidity/syntaxTests/functionCalls/module_not_callable.sol @@ -0,0 +1,9 @@ +==== Source: A.sol ==== +==== Source: B.sol ==== +import "A.sol" as A; + +contract C { + uint a = A(1000); +} +// ---- +// TypeError 5704: (B.sol:48-55): Module is not callable. diff --git a/test/libsolidity/syntaxTests/functionCalls/this_not_callable.sol b/test/libsolidity/syntaxTests/functionCalls/this_not_callable.sol index 52e6986bb..35c04d473 100644 --- a/test/libsolidity/syntaxTests/functionCalls/this_not_callable.sol +++ b/test/libsolidity/syntaxTests/functionCalls/this_not_callable.sol @@ -6,4 +6,4 @@ contract C { } } // ---- -// TypeError 5704: (72-78): Type is not callable +// TypeError 5704: (72-78): Contract is not callable. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/462_callable_crash.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/462_callable_crash.sol index 05239fa1b..6c5539e3b 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/462_callable_crash.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/462_callable_crash.sol @@ -6,4 +6,4 @@ contract C { } } // ---- -// TypeError 5704: (90-108): Type is not callable +// TypeError 5704: (90-108): Rational number literal is not callable. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/492_do_not_crash_on_not_lvalue.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/492_do_not_crash_on_not_lvalue.sol index 392d02e9f..595785e93 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/492_do_not_crash_on_not_lvalue.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/492_do_not_crash_on_not_lvalue.sol @@ -6,4 +6,4 @@ contract C { } } // ---- -// TypeError 5704: (153-157): Type is not callable +// TypeError 5704: (153-157): Mapping is not callable. diff --git a/test/libsolidity/syntaxTests/scoping/state_variable_function_conflict_former_crash.sol b/test/libsolidity/syntaxTests/scoping/state_variable_function_conflict_former_crash.sol index 049fca274..eeef3e7ea 100644 --- a/test/libsolidity/syntaxTests/scoping/state_variable_function_conflict_former_crash.sol +++ b/test/libsolidity/syntaxTests/scoping/state_variable_function_conflict_former_crash.sol @@ -11,4 +11,4 @@ contract SomeContract { } // ---- // DeclarationError 2333: (106-145): Identifier already declared. -// TypeError 5704: (185-195): Type is not callable +// TypeError 5704: (185-195): Integer is not callable. diff --git a/test/libsolidity/syntaxTests/tupleAssignments/double_storage_crash.sol b/test/libsolidity/syntaxTests/tupleAssignments/double_storage_crash.sol index a251b3a9b..701af022b 100644 --- a/test/libsolidity/syntaxTests/tupleAssignments/double_storage_crash.sol +++ b/test/libsolidity/syntaxTests/tupleAssignments/double_storage_crash.sol @@ -7,4 +7,4 @@ contract CrashContract { } } // ---- -// TypeError 5704: (170-177): Type is not callable +// TypeError 5704: (170-177): Rational number literal is not callable. diff --git a/test/libsolidity/syntaxTests/types/function_call_fail.sol b/test/libsolidity/syntaxTests/types/function_call_fail.sol index 7e2d0b230..042b78f01 100644 --- a/test/libsolidity/syntaxTests/types/function_call_fail.sol +++ b/test/libsolidity/syntaxTests/types/function_call_fail.sol @@ -4,4 +4,4 @@ contract C { } } // ---- -// TypeError 5704: (59-63): Type is not callable +// TypeError 5704: (59-63): Rational number literal is not callable.