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