File indexing completed on 2024-06-23 04:34:44
0001 /* 0002 SPDX-FileCopyrightText: 2006 Roberto Raggi <roberto@kdevelop.org> 0003 SPDX-FileCopyrightText: 2006-2008 Hamish Rodda <rodda@kde.org> 0004 SPDX-FileCopyrightText: 2007-2008 David Nolden <david.nolden.kdevelop@art-master.de> 0005 0006 SPDX-License-Identifier: LGPL-2.0-only 0007 */ 0008 0009 #ifndef KDEVPLATFORM_ABSTRACTTYPE_H 0010 #define KDEVPLATFORM_ABSTRACTTYPE_H 0011 0012 #include "typepointer.h" 0013 #include <language/languageexport.h> 0014 0015 class QString; 0016 0017 namespace KDevelop { 0018 class AbstractTypeData; 0019 0020 class IndexedType; 0021 0022 class TypeVisitor; 0023 class TypeExchanger; 0024 0025 /// This macro is used to declare type-specific data-access functions within subclasses of AbstractType 0026 #define TYPE_DECLARE_DATA(Class) \ 0027 inline Class ## Data * d_func_dynamic() { makeDynamic(); return reinterpret_cast<Class ## Data*>(d_ptr); } \ 0028 inline const Class ## Data* d_func() const { return reinterpret_cast<const Class ## Data*>(d_ptr); } 0029 0030 /// This function creates a local variable named 'd' pointing to the data type (as shortcut) 0031 #define TYPE_D(Class) const Class ## Data * const d = d_func() 0032 #define TYPE_D_DYNAMIC(Class) Class ## Data * const d = d_func_dynamic() 0033 0034 /** 0035 * \brief Base class for all types. 0036 * 0037 * The AbstractType class is a base class from which all types derive. It features: 0038 * - mechanisms for visiting types 0039 * - toString() feature 0040 * - equivalence feature 0041 * - cloning of types, and 0042 * - hashing and indexing 0043 * - efficient, persistent, and reference-counted storage of types using IndexedType 0044 * 0045 * Type classes are created in a way that allows storing them in memory or on disk 0046 * efficiently. They are classes which can store arbitrary lists immediately after their 0047 * private data structures in memory (thus enabling them to be mmapped or memcopied), 0048 * or being "dynamic" where you use exactly the same class and same access functions, 0049 * but the list data is stored in a temporary KDevVarLengthArray from a central repository, 0050 * until we save it back to the static memory-region again. 0051 * 0052 * When creating an own (sub-) type, you must: 0053 * - Override equals(..), hash(). 0054 * - The functions should _fully_ distinguish all types, 0055 * in regard to all stored information, and regarding their identity. 0056 * - This can be skipped if you're overriding a base-type which already incorporates 0057 * all of your own types status within its equals/hash functions (eg. you don't add own data). 0058 * - Implement a copy-constructor in which you copy the data from the source using copyData<YourType>() 0059 * - Override the clone() function in which you use the copy-constructor to clone the type 0060 * - Add an enumerator "Identity" that contains an arbitrary unique identity value of the type 0061 * - Register your type in a source-file using REGISTER_TYPE(..), @see typeregister.h 0062 * - Add a typedef "Data", that contains the actual data of the type using the mechanisms described in appendedlist.h. 0063 * That data type must follow the same inheritance chain as the type itself, so it must be based on the Data object 0064 * of the base class. See AbstractTypeData. 0065 * - Use createData<YourType>() to create the data-object in a constructor (which you then reach to the parent constructor) 0066 * - Use TYPE_DECLARE_DATA(YourType) to declare the data access functions d_func and d_func_dynamic, 0067 * and then use d_func()->.. and d_func_dynamic()->.. to access your type data 0068 * - Create a constructor that only takes a reference to the type data, and passes it to the parent type 0069 * 0070 * Every type can have only one other type as base-type, 0071 * but it can have additional base-classes that are not a direct part of the type-system(@see IdentifiedType). 0072 * 0073 * \sa appendedlist.h 0074 */ 0075 class KDEVPLATFORMLANGUAGE_EXPORT AbstractType 0076 : public QSharedData 0077 { 0078 public: 0079 using Ptr = TypePtr<AbstractType>; 0080 0081 /** 0082 * An enumeration of common modifiers for data types. 0083 * If you have any language-specific modifiers that don't belong here, 0084 * you can add them at/after LanguageSpecificModifier 0085 * @warning Think twice what information you store into the type-system. 0086 * The type-system should store information that is shared among many declarations, 0087 * and attributes of specific Declarations like public/private should be stored in 0088 * the Declarations themselves, not in the type-system. 0089 */ 0090 enum CommonModifiers : quint32 { 0091 NoModifiers = 0, 0092 0093 ConstModifier = 1 << 0, 0094 VolatileModifier = 1 << 1, 0095 TransientModifier = 1 << 2, 0096 NewModifier = 1 << 3, 0097 SealedModifier = 1 << 4, 0098 UnsafeModifier = 1 << 5, 0099 FixedModifier = 1 << 6, 0100 ShortModifier = 1 << 7, 0101 LongModifier = 1 << 8, 0102 LongLongModifier = 1 << 9, 0103 SignedModifier = 1 << 10, 0104 UnsignedModifier = 1 << 11, 0105 AtomicModifier = 1 << 12, 0106 0107 LanguageSpecificModifier = 1 << 13 0108 }; 0109 0110 /// Constructor. 0111 AbstractType(); 0112 /// Constructor from data. 0113 explicit AbstractType(AbstractTypeData& dd); 0114 /// Destructor. 0115 virtual ~AbstractType (); 0116 0117 AbstractType(const AbstractType& rhs) = delete; 0118 AbstractType& operator=(const AbstractType& rhs) = delete; 0119 0120 /** 0121 * Access the type modifiers 0122 * 0123 * \returns the type's modifiers. 0124 */ 0125 quint32 modifiers() const; 0126 0127 /** 0128 * Set the type's modifiers. 0129 * 0130 * \param modifiers modifiers of this type. 0131 */ 0132 void setModifiers(quint32 modifiers); 0133 0134 /** 0135 * \returns The size in bytes or -1 if unknown. 0136 */ 0137 int64_t sizeOf() const; 0138 0139 /** 0140 * Set the size to given number of bytes. Use -1 to represent unknown size. 0141 */ 0142 void setSizeOf(int64_t sizeOf); 0143 0144 /** 0145 * \returns The alignment in bytes or -1 if unknown. 0146 */ 0147 int64_t alignOf() const; 0148 0149 /** 0150 * Set the alignment to given number of bytes. 0151 * 0152 * The value must be non-negative power of 2 or -1 to represent unknown alignment. 0153 */ 0154 void setAlignOf(int64_t alignedTo); 0155 0156 /** 0157 * Visitor method. Called by TypeVisitor to visit the type hierarchy. 0158 * Do not reimplement this, reimplement accept0 instead. 0159 * 0160 * \param v visitor which is calling this function. 0161 */ 0162 void accept(TypeVisitor* v) const; 0163 0164 /** 0165 * Convenience visitor method which can be called with a null type. 0166 * 0167 * \param type type to visit, may be null. 0168 * \param v visitor which is visiting the given \a type 0169 */ 0170 static void acceptType(AbstractType::Ptr type, TypeVisitor* v); 0171 0172 /** 0173 * Returns this type as a string, preferably the same as it is expressed in the code. 0174 * 0175 * \return this type as a string 0176 */ 0177 virtual QString toString() const; 0178 0179 ///Must always be called before anything in the data pointer is changed! 0180 ///If it's not called beforehand, the type-repository gets corrupted 0181 void makeDynamic(); 0182 0183 ///Should return whether this type's content equals the given one 0184 ///Since this is used by the type-repository, it must compare ALL members of the data type. 0185 virtual bool equals(const AbstractType* rhs) const; 0186 0187 ///Should return whether this type contains the given one 0188 ///For types holding only a single type, this is identical to equals() 0189 virtual bool contains(const AbstractType* type) const; 0190 0191 /** 0192 * Should create a clone of the source-type, with as much data copied as possible without breaking the du-chain. 0193 * */ 0194 virtual AbstractType* clone() const = 0; 0195 0196 /** 0197 * A hash-value that should have the following properties: 0198 * - When two types match on equals(), it should be same. 0199 * - When two types don't match on equals(), it should be different with a high probability. 0200 * */ 0201 virtual uint hash() const; 0202 0203 IndexedType indexed() const; 0204 0205 /// Enumeration of major data types. 0206 enum WhichType : quint8 { 0207 TypeAbstract /**< an abstract type */, 0208 TypeIntegral /**< an integral */, 0209 TypePointer /**< a pointer*/, 0210 TypeReference /**< a reference */, 0211 TypeFunction /**< a function */, 0212 TypeStructure /**< a structure */, 0213 TypeArray /**< an array */, 0214 TypeDelayed /**< a delayed type */, 0215 TypeEnumeration /**< an enumeration type */, 0216 TypeEnumerator /**< an enumerator type */, 0217 TypeAlias /**< a type-alias type */, 0218 TypeUnsure /**< may represent multiple different types */ 0219 }; 0220 0221 /** 0222 * Determine which data type this abstract type represents. 0223 * 0224 * \returns the data type represented by this type. 0225 */ 0226 virtual WhichType whichType() const; 0227 0228 enum { 0229 Identity = 1 0230 }; 0231 0232 /** 0233 * Should, like accept0, be implemented by all types that hold references to other types. 0234 * 0235 * If this is called on one type, that type should call exchangeTypes(..) with all its referenced sub-types. 0236 * The type itself does not recurse into the sub-types, that can be done by the exchanger itself if desired. 0237 * */ 0238 virtual void exchangeTypes(TypeExchanger* exchanger); 0239 0240 /** 0241 * Method to create copies of internal type data. You must use this to create the internal 0242 * data instances in copy constructors. It is needed, because it may need to allocate more memory 0243 * for appended lists. 0244 * 0245 * \param rhs data to copy 0246 * \returns copy of the data 0247 */ 0248 0249 template <class Type> 0250 static typename Type::Data& copyData(const typename Type::Data& rhs) 0251 { 0252 uint size; 0253 if (!rhs.m_dynamic) 0254 size = sizeof(typename Type::Data); //Create a dynamic data instance 0255 else 0256 size = rhs.dynamicSize(); //Create a constant data instance, that holds all the data embedded. 0257 0258 typename Type::Data& ret(*new (new char[size]) typename Type::Data(rhs)); 0259 ret.template setTypeClassId<Type>(); 0260 return ret; 0261 } 0262 0263 /** 0264 * As above, but does not support copying data into a lower class(Should not be used while cloning) 0265 */ 0266 template <class DataType> 0267 static DataType& copyDataDirectly(const DataType& rhs) 0268 { 0269 uint size; 0270 if (!rhs.m_dynamic) 0271 size = sizeof(DataType); //Create a dynamic data instance 0272 else 0273 size = rhs.dynamicSize(); //Create a constant data instance, that holds all the data embedded. 0274 0275 return *new (new char[size]) DataType(rhs); 0276 } 0277 0278 /** 0279 * Method to create internal data structures. Use this in normal constructors. 0280 * 0281 * \returns the internal data structure 0282 */ 0283 template <class Type> 0284 static typename Type::Data& createData() 0285 { 0286 typename Type::Data& ret(*new (new char[sizeof(typename Type::Data)]) typename Type::Data()); 0287 ret.template setTypeClassId<Type>(); 0288 return ret; 0289 } 0290 0291 using Data = AbstractTypeData; 0292 0293 protected: 0294 /** 0295 * Visitor method, reimplement to allow visiting of types. 0296 * 0297 * \param v visitor which is visiting. 0298 */ 0299 virtual void accept0 (TypeVisitor* v) const = 0; 0300 0301 /// toString() function which can provide \a spaceOnLeft rather than on right if desired. 0302 QString toString(bool spaceOnLeft) const; 0303 0304 AbstractTypeData* d_ptr; 0305 0306 TYPE_DECLARE_DATA(AbstractType) 0307 0308 friend class AbstractTypeDataRequest; 0309 }; 0310 } 0311 0312 #endif