1 /* 2 This file is part of solidity. 3 4 solidity is free software: you can redistribute it and/or modify 5 it under the terms of the GNU General Public License as published by 6 the Free Software Foundation, either version 3 of the License, or 7 (at your option) any later version. 8 9 solidity is distributed in the hope that it will be useful, 10 but WITHOUT ANY WARRANTY; without even the implied warranty of 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 GNU General Public License for more details. 13 14 You should have received a copy of the GNU General Public License 15 along with solidity. If not, see <http://www.gnu.org/licenses/>. 16 */ 17 // SPDX-License-Identifier: GPL-3.0 18 19 #pragma once 20 21 #include <libsolidity/ast/Types.h> 22 23 #include <array> 24 #include <map> 25 #include <memory> 26 #include <optional> 27 #include <utility> 28 29 namespace solidity::frontend 30 { 31 32 /** 33 * API for accessing the Solidity Type System. 34 * 35 * This is the Solidity Compiler's type provider. Use it to request for types. The caller does 36 * <b>not</b> own the types. 37 * 38 * It is not recommended to explicitly instantiate types unless you really know what and why 39 * you are doing it. 40 */ 41 class TypeProvider 42 { 43 public: 44 TypeProvider() = default; 45 TypeProvider(TypeProvider&&) = default; 46 TypeProvider(TypeProvider const&) = delete; 47 TypeProvider& operator=(TypeProvider&&) = default; 48 TypeProvider& operator=(TypeProvider const&) = delete; 49 ~TypeProvider() = default; 50 51 /// Resets state of this TypeProvider to initial state, wiping all mutable types. 52 /// This invalidates all dangling pointers to types provided by this TypeProvider. 53 static void reset(); 54 55 /// @name Factory functions 56 /// Factory functions that convert an AST @ref TypeName to a Type. 57 static Type const* fromElementaryTypeName(ElementaryTypeNameToken const& _type, std::optional<StateMutability> _stateMutability = {}); 58 59 /// Converts a given elementary type name with optional data location 60 /// suffix " storage", " calldata" or " memory" to a type pointer. If suffix not given, defaults to " storage". 61 static Type const* fromElementaryTypeName(std::string const& _name); 62 63 /// @returns boolean type. boolean()64 static BoolType const* boolean() noexcept { return &m_boolean; } 65 byte()66 static FixedBytesType const* byte() { return fixedBytes(1); } fixedBytes(unsigned m)67 static FixedBytesType const* fixedBytes(unsigned m) { return m_bytesM.at(m - 1).get(); } 68 69 static ArrayType const* bytesStorage(); 70 static ArrayType const* bytesMemory(); 71 static ArrayType const* bytesCalldata(); 72 static ArrayType const* stringStorage(); 73 static ArrayType const* stringMemory(); 74 75 /// Constructor for a byte array ("bytes") and string. 76 static ArrayType const* array(DataLocation _location, bool _isString = false); 77 78 /// Constructor for a dynamically sized array type ("type[]") 79 static ArrayType const* array(DataLocation _location, Type const* _baseType); 80 81 /// Constructor for a fixed-size array type ("type[20]") 82 static ArrayType const* array(DataLocation _location, Type const* _baseType, u256 const& _length); 83 84 static ArraySliceType const* arraySlice(ArrayType const& _arrayType); 85 payableAddress()86 static AddressType const* payableAddress() noexcept { return &m_payableAddress; } address()87 static AddressType const* address() noexcept { return &m_address; } 88 integer(unsigned _bits,IntegerType::Modifier _modifier)89 static IntegerType const* integer(unsigned _bits, IntegerType::Modifier _modifier) 90 { 91 solAssert((_bits % 8) == 0, ""); 92 if (_modifier == IntegerType::Modifier::Unsigned) 93 return m_uintM.at(_bits / 8 - 1).get(); 94 else 95 return m_intM.at(_bits / 8 - 1).get(); 96 } uint(unsigned _bits)97 static IntegerType const* uint(unsigned _bits) { return integer(_bits, IntegerType::Modifier::Unsigned); } 98 uint256()99 static IntegerType const* uint256() { return uint(256); } int256()100 static IntegerType const* int256() { return integer(256, IntegerType::Modifier::Signed); } 101 102 static FixedPointType const* fixedPoint(unsigned m, unsigned n, FixedPointType::Modifier _modifier); 103 104 static StringLiteralType const* stringLiteral(std::string const& literal); 105 106 /// @param members the member types the tuple type must contain. This is passed by value on purspose. 107 /// @returns a tuple type with the given members. 108 static TupleType const* tuple(std::vector<Type const*> members); 109 emptyTuple()110 static TupleType const* emptyTuple() noexcept { return &m_emptyTuple; } 111 112 static ReferenceType const* withLocation(ReferenceType const* _type, DataLocation _location, bool _isPointer); 113 114 /// @returns a copy of @a _type having the same location as this (and is not a pointer type) 115 /// if _type is a reference type and an unmodified copy of _type otherwise. 116 /// This function is mostly useful to modify inner types appropriately. 117 static Type const* withLocationIfReference(DataLocation _location, Type const* _type, bool _isPointer = false) 118 { 119 if (auto refType = dynamic_cast<ReferenceType const*>(_type)) 120 return withLocation(refType, _location, _isPointer); 121 122 return _type; 123 } 124 isReferenceWithLocation(Type const * _type,DataLocation _location)125 static bool isReferenceWithLocation(Type const* _type, DataLocation _location) 126 { 127 if (auto const* refType = dynamic_cast<ReferenceType const*>(_type)) 128 if (refType->location() == _location) 129 return true; 130 return false; 131 } 132 133 /// @returns the internally-facing or externally-facing type of a function or the type of a function declaration. 134 static FunctionType const* function(FunctionDefinition const& _function, FunctionType::Kind _kind = FunctionType::Kind::Declaration); 135 136 /// @returns the accessor function type of a state variable. 137 static FunctionType const* function(VariableDeclaration const& _varDecl); 138 139 /// @returns the function type of an event. 140 static FunctionType const* function(EventDefinition const& _event); 141 142 static FunctionType const* function(ErrorDefinition const& _error); 143 144 /// @returns the type of a function type name. 145 static FunctionType const* function(FunctionTypeName const& _typeName); 146 147 /// @returns the function type to be used for a plain type (not derived from a declaration). 148 static FunctionType const* function( 149 strings const& _parameterTypes, 150 strings const& _returnParameterTypes, 151 FunctionType::Kind _kind = FunctionType::Kind::Internal, 152 bool _arbitraryParameters = false, 153 StateMutability _stateMutability = StateMutability::NonPayable 154 ); 155 156 /// @returns a highly customized FunctionType, use with care. 157 static FunctionType const* function( 158 TypePointers const& _parameterTypes, 159 TypePointers const& _returnParameterTypes, 160 strings _parameterNames = strings{}, 161 strings _returnParameterNames = strings{}, 162 FunctionType::Kind _kind = FunctionType::Kind::Internal, 163 bool _arbitraryParameters = false, 164 StateMutability _stateMutability = StateMutability::NonPayable, 165 Declaration const* _declaration = nullptr, 166 bool _gasSet = false, 167 bool _valueSet = false, 168 bool _bound = false, 169 bool _saltSet = false 170 ); 171 172 /// Auto-detect the proper type for a literal. @returns an empty pointer if the literal does 173 /// not fit any type. 174 static Type const* forLiteral(Literal const& _literal); 175 static RationalNumberType const* rationalNumber(Literal const& _literal); 176 177 static RationalNumberType const* rationalNumber( 178 rational const& _value, 179 Type const* _compatibleBytesType = nullptr 180 ); 181 182 static ContractType const* contract(ContractDefinition const& _contract, bool _isSuper = false); 183 inaccessibleDynamic()184 static InaccessibleDynamicType const* inaccessibleDynamic() noexcept { return &m_inaccessibleDynamic; } 185 186 /// @returns the type of an enum instance for given definition, there is one distinct type per enum definition. 187 static EnumType const* enumType(EnumDefinition const& _enum); 188 189 /// @returns special type for imported modules. These mainly give access to their scope via members. 190 static ModuleType const* module(SourceUnit const& _source); 191 192 static TypeType const* typeType(Type const* _actualType); 193 194 static StructType const* structType(StructDefinition const& _struct, DataLocation _location); 195 196 static ModifierType const* modifier(ModifierDefinition const& _modifierDef); 197 198 static MagicType const* magic(MagicType::Kind _kind); 199 200 static MagicType const* meta(Type const* _type); 201 202 static MappingType const* mapping(Type const* _keyType, Type const* _valueType); 203 204 static UserDefinedValueType const* userDefinedValueType(UserDefinedValueTypeDefinition const& _definition); 205 206 private: 207 /// Global TypeProvider instance. instance()208 static TypeProvider& instance() 209 { 210 static TypeProvider _provider; 211 return _provider; 212 } 213 214 template <typename T, typename... Args> 215 static inline T const* createAndGet(Args&& ... _args); 216 217 static BoolType const m_boolean; 218 static InaccessibleDynamicType const m_inaccessibleDynamic; 219 220 /// These are lazy-initialized because they depend on `byte` being available. 221 static std::unique_ptr<ArrayType> m_bytesStorage; 222 static std::unique_ptr<ArrayType> m_bytesMemory; 223 static std::unique_ptr<ArrayType> m_bytesCalldata; 224 static std::unique_ptr<ArrayType> m_stringStorage; 225 static std::unique_ptr<ArrayType> m_stringMemory; 226 227 static TupleType const m_emptyTuple; 228 static AddressType const m_payableAddress; 229 static AddressType const m_address; 230 static std::array<std::unique_ptr<IntegerType>, 32> const m_intM; 231 static std::array<std::unique_ptr<IntegerType>, 32> const m_uintM; 232 static std::array<std::unique_ptr<FixedBytesType>, 32> const m_bytesM; 233 static std::array<std::unique_ptr<MagicType>, 4> const m_magics; ///< MagicType's except MetaType 234 235 std::map<std::pair<unsigned, unsigned>, std::unique_ptr<FixedPointType>> m_ufixedMxN{}; 236 std::map<std::pair<unsigned, unsigned>, std::unique_ptr<FixedPointType>> m_fixedMxN{}; 237 std::map<std::string, std::unique_ptr<StringLiteralType>> m_stringLiteralTypes{}; 238 std::vector<std::unique_ptr<Type>> m_generalTypes{}; 239 }; 240 241 } 242