diff --git a/kdevplatform/language/duchain/types/abstracttype.h b/kdevplatform/language/duchain/types/abstracttype.h index b359ddfd46..8fd843fd55 100644 --- a/kdevplatform/language/duchain/types/abstracttype.h +++ b/kdevplatform/language/duchain/types/abstracttype.h @@ -1,315 +1,313 @@ /* This file is part of KDevelop Copyright 2006 Roberto Raggi Copyright 2006-2008 Hamish Rodda Copyright 2007-2008 David Nolden This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License version 2 as published by the Free Software Foundation. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KDEVPLATFORM_ABSTRACTTYPE_H #define KDEVPLATFORM_ABSTRACTTYPE_H #include "typepointer.h" #include class QString; namespace KDevelop { class AbstractTypeData; class IndexedType; class TypeVisitor; class TypeExchanger; /// This macro is used to declare type-specific data-access functions within subclasses of AbstractType #define TYPE_DECLARE_DATA(Class) \ inline Class ## Data * d_func_dynamic() { makeDynamic(); return reinterpret_cast(d_ptr); } \ inline const Class ## Data* d_func() const { return reinterpret_cast(d_ptr); } /// This function creates a local variable named 'd' pointing to the data type (as shortcut) #define TYPE_D(Class) const Class ## Data * const d = d_func() #define TYPE_D_DYNAMIC(Class) Class ## Data * const d = d_func_dynamic() /** * \brief Base class for all types. * * The AbstractType class is a base class from which all types derive. It features: * - mechanisms for visiting types * - toString() feature * - equivalence feature * - cloning of types, and * - hashing and indexing * - efficient, persistent, and reference-counted storage of types using IndexedType * * Type classes are created in a way that allows storing them in memory or on disk * efficiently. They are classes which can store arbitrary lists immediately after their * private data structures in memory (thus enabling them to be mmapped or memcopied), * or being "dynamic" where you use exactly the same class and same access functions, * but the list data is stored in a temporary KDevVarLengthArray from a central repository, * until we save it back to the static memory-region again. * * When creating an own (sub-) type, you must: * - Override equals(..), hash(). * - The functions should _fully_ distinguish all types, * in regard to all stored information, and regarding their identity. * - This can be skipped if you're overriding a base-type which already incorporates * all of your own types status within its equals/hash functions (eg. you don't add own data). * - Implement a copy-constructor in which you copy the data from the source using copyData() * - Override the clone() function in which you use the copy-constructor to clone the type * - Add an enumerator "Identity" that contains an arbitrary unique identity value of the type * - Register your type in a source-file using REGISTER_TYPE(..), @see typeregister.h * - Add a typedef "Data", that contains the actual data of the type using the mechanisms described in appendedlist.h. * That data type must follow the same inheritance chain as the type itself, so it must be based on the Data object * of the base class. See AbstractTypeData. * - Use createData() to create the data-object in a constructor (which you then reach to the parent constructor) * - Use TYPE_DECLARE_DATA(YourType) to declare the data access functions d_func and d_func_dynamic, * and then use d_func()->.. and d_func_dynamic()->.. to access your type data * - Create a constructor that only takes a reference to the type data, and passes it to the parent type * * Every type can have only one other type as base-type, * but it can have additional base-classes that are not a direct part of the type-system(@see IdentifiedType). * * \sa appendedlist.h */ class KDEVPLATFORMLANGUAGE_EXPORT AbstractType : public QSharedData { public: using Ptr = TypePtr; /** * An enumeration of common modifiers for data types. * If you have any language-specific modifiers that don't belong here, * you can add them at/after LanguageSpecificModifier * @warning Think twice what information you store into the type-system. * The type-system should store information that is shared among many declarations, * and attributes of specific Declarations like public/private should be stored in * the Declarations themselves, not in the type-system. */ enum CommonModifiers : quint32 { NoModifiers = 0, ConstModifier = 1 << 0, VolatileModifier = 1 << 1, TransientModifier = 1 << 2, NewModifier = 1 << 3, SealedModifier = 1 << 4, UnsafeModifier = 1 << 5, FixedModifier = 1 << 6, ShortModifier = 1 << 7, LongModifier = 1 << 8, LongLongModifier = 1 << 9, SignedModifier = 1 << 10, UnsignedModifier = 1 << 11, LanguageSpecificModifier = 1 << 12 }; /// Constructor. AbstractType(); /// Constructor from data. explicit AbstractType(AbstractTypeData& dd); /// Destructor. virtual ~AbstractType (); + AbstractType(const AbstractType& rhs) = delete; AbstractType& operator=(const AbstractType& rhs) = delete; /** * Access the type modifiers * * \returns the type's modifiers. */ quint32 modifiers() const; /** * Set the type's modifiers. * * \param modifiers modifiers of this type. */ void setModifiers(quint32 modifiers); /** * Visitor method. Called by TypeVisitor to visit the type hierarchy. * Do not reimplement this, reimplement accept0 instead. * * \param v visitor which is calling this function. */ void accept(TypeVisitor* v) const; /** * Convenience visitor method which can be called with a null type. * * \param type type to visit, may be null. * \param v visitor which is visiting the given \a type */ static void acceptType(AbstractType::Ptr type, TypeVisitor* v); /** * Returns this type as a string, preferably the same as it is expressed in the code. * * \return this type as a string */ virtual QString toString() const; ///Must always be called before anything in the data pointer is changed! ///If it's not called beforehand, the type-repository gets corrupted void makeDynamic(); ///Should return whether this type's content equals the given one ///Since this is used by the type-repository, it must compare ALL members of the data type. virtual bool equals(const AbstractType* rhs) const; /** * Should create a clone of the source-type, with as much data copied as possible without breaking the du-chain. * */ virtual AbstractType* clone() const = 0; /** * A hash-value that should have the following properties: * - When two types match on equals(), it should be same. * - When two types don't match on equals(), it should be different with a high probability. * */ virtual uint hash() const; ///This can also be called on zero types, those can then be reconstructed from the zero index IndexedType indexed() const; /// Enumeration of major data types. enum WhichType : quint8 { TypeAbstract /**< an abstract type */, TypeIntegral /**< an integral */, TypePointer /**< a pointer*/, TypeReference /**< a reference */, TypeFunction /**< a function */, TypeStructure /**< a structure */, TypeArray /**< an array */, TypeDelayed /**< a delayed type */, TypeEnumeration /**< an enumeration type */, TypeEnumerator /**< an enumerator type */, TypeAlias /**< a type-alias type */, TypeUnsure /**< may represent multiple different types */ }; /** * Determine which data type this abstract type represents. * * \returns the data type represented by this type. */ virtual WhichType whichType() const; enum { Identity = 1 }; /** * Should, like accept0, be implemented by all types that hold references to other types. * * If this is called on one type, that type should call exchangeTypes(..) with all its referenced sub-types. * The type itself does not recurse into the sub-types, that can be done by the exchanger itself if desired. * */ virtual void exchangeTypes(TypeExchanger* exchanger); /** * Method to create copies of internal type data. You must use this to create the internal * data instances in copy constructors. It is needed, because it may need to allocate more memory * for appended lists. * * \param rhs data to copy * \returns copy of the data */ template static typename Type::Data& copyData(const typename Type::Data& rhs) { uint size; if (!rhs.m_dynamic) size = sizeof(typename Type::Data); //Create a dynamic data instance else size = rhs.dynamicSize(); //Create a constant data instance, that holds all the data embedded. typename Type::Data& ret(*new (new char[size]) typename Type::Data(rhs)); ret.template setTypeClassId(); return ret; } /** * As above, but does not support copying data into a lower class(Should not be used while cloning) */ template static DataType& copyDataDirectly(const DataType& rhs) { uint size; if (!rhs.m_dynamic) size = sizeof(DataType); //Create a dynamic data instance else size = rhs.dynamicSize(); //Create a constant data instance, that holds all the data embedded. return *new (new char[size]) DataType(rhs); } /** * Method to create internal data structures. Use this in normal constructors. * * \returns the internal data structure */ template static typename Type::Data& createData() { typename Type::Data& ret(*new (new char[sizeof(typename Type::Data)]) typename Type::Data()); ret.template setTypeClassId(); return ret; } using Data = AbstractTypeData; protected: /** * Visitor method, reimplement to allow visiting of types. * * \param v visitor which is visiting. */ virtual void accept0 (TypeVisitor* v) const = 0; /// toString() function which can provide \a spaceOnLeft rather than on right if desired. QString toString(bool spaceOnLeft) const; AbstractTypeData* d_ptr; TYPE_DECLARE_DATA(AbstractType) friend class AbstractTypeDataRequest; - -private: - AbstractType(const AbstractType& rhs); }; /** * You can use these instead of dynamic_cast, for basic types it has better performance because it checks the whichType() member */ template inline To fastCast(AbstractType* from) { return dynamic_cast(from); } template inline const To fastCast(const AbstractType* from) { return const_cast(fastCast(const_cast(from))); //Hack so we don't need to define the functions twice, once for const, and once for not const } } #endif diff --git a/kdevplatform/language/duchain/types/identifiedtype.h b/kdevplatform/language/duchain/types/identifiedtype.h index 25b28f5fca..f84702de43 100644 --- a/kdevplatform/language/duchain/types/identifiedtype.h +++ b/kdevplatform/language/duchain/types/identifiedtype.h @@ -1,181 +1,180 @@ /* This file is part of KDevelop Copyright 2002-2005 Roberto Raggi Copyright 2006 Adam Treat Copyright 2006-2008 Hamish Rodda Copyright 2007-2008 David Nolden This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License version 2 as published by the Free Software Foundation. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KDEVPLATFORM_IDENTIFIEDTYPE_H #define KDEVPLATFORM_IDENTIFIEDTYPE_H #include "../identifier.h" #include "../declarationid.h" namespace KDevelop { class DUContext; class Declaration; class DeclarationId; class TopDUContext; class AbstractType; /** * Data structure for identified types. */ class IdentifiedTypeData { public: DeclarationId m_id; }; /** * \short An IdentifiedType is a type that has a declaration. * * Example of an identified type: * - A class type * * Example of types which are not identified: * - Pointer types (they can point to identified types, but by themselves have no declaration) * - Reference types (the same) * */ class KDEVPLATFORMLANGUAGE_EXPORT IdentifiedType { public: /// Destructor virtual ~IdentifiedType(); /** * Test for equivalence with another type. * * \param rhs other type to check for equivalence * \returns true if equal, otherwise false. */ bool equals(const IdentifiedType* rhs) const; /// Clear the identifier void clear(); /** * Determine the qualified identifier for this identified type. * * \note This is relatively expensive. Use declarationId() instead when possible! * \returns the type's qualified identifier */ QualifiedIdentifier qualifiedIdentifier() const; /// Determine this identified type's hash value. \returns the hash value uint hash() const; /** * Access the identified type's declaration id, which is a unique global identifier for the * type even when the same identifier represents a different type in a different context * or source file. * * \returns the declaration identifier. * \sa DeclarationId */ DeclarationId declarationId() const; /** * Set the globally unique declaration \a id. * \param id new identifier */ void setDeclarationId(const DeclarationId& id); /** * Look up the declaration of this type in the given \a top context. * * \param top Top context to search for the declaration within * \returns the declaration corresponding to this identified type */ Declaration* declaration(const TopDUContext* top) const; /** * \param top Top context to search for the declaration within * Convenience function that returns the internal context of the attached declaration, * or zero if no declaration is found, or if it does not have an internal context. */ DUContext* internalContext(const TopDUContext* top) const; /** * Set the declaration which created this type. * * \note You should be careful when setting this, because it also changes the meaning of the declaration. * * The logic is: * If a declaration has a set abstractType(), and that abstractType() has set the same declaration as declaration(), * then the declaration declares the type(thus it is a type-declaration, see Declaration::kind()) * * \param declaration Declaration which created the type * */ void setDeclaration(Declaration* declaration); /// Allow IdentifiedType to access its data. virtual IdentifiedTypeData* idData() = 0; /// Allow IdentifiedType to access its data. virtual const IdentifiedTypeData* idData() const = 0; }; ///Implements everything necessary to merge the given Parent class with IdentifiedType ///Your used Data class must be based on the Data member class template class MergeIdentifiedType : public Parent , public IdentifiedType { public: class Data : public Parent::Data , public IdentifiedTypeData { }; MergeIdentifiedType() { } explicit MergeIdentifiedType(Data& data) : Parent(data) { } + MergeIdentifiedType(const MergeIdentifiedType& rhs) = delete; + IdentifiedTypeData* idData() override { return static_cast(this->d_func_dynamic()); } const IdentifiedTypeData* idData() const override { return static_cast(this->d_func()); } bool equals(const KDevelop::AbstractType* rhs) const override { if (!Parent::equals(rhs)) return false; const auto* rhsId = dynamic_cast(rhs); Q_ASSERT(rhsId); return IdentifiedType::equals(static_cast(rhsId)); } - -private: - MergeIdentifiedType(const MergeIdentifiedType& rhs); }; } #endif