diff --git a/language/CMakeLists.txt b/language/CMakeLists.txt index a698bf2be8..9a61acb39e 100644 --- a/language/CMakeLists.txt +++ b/language/CMakeLists.txt @@ -1,354 +1,355 @@ add_definitions( -DKDE_DEFAULT_DEBUG_AREA=9505 ) add_subdirectory(highlighting/tests) add_subdirectory(duchain/tests) add_subdirectory(backgroundparser/tests) add_subdirectory(codegen/tests) set(kdevplatformlanguage_LIB_SRCS editor/persistentmovingrangeprivate.cpp editor/persistentmovingrange.cpp editor/modificationrevisionset.cpp editor/modificationrevision.cpp backgroundparser/backgroundparser.cpp backgroundparser/parsejob.cpp backgroundparser/parserdependencypolicy.cpp backgroundparser/documentchangetracker.cpp backgroundparser/parseprojectjob.cpp backgroundparser/urlparselock.cpp duchain/referencecounting.cpp duchain/specializationstore.cpp duchain/codemodel.cpp duchain/duchain.cpp duchain/waitforupdate.cpp duchain/duchainpointer.cpp duchain/ducontext.cpp duchain/indexedducontext.cpp duchain/indexedtopducontext.cpp duchain/localindexedducontext.cpp duchain/indexeddeclaration.cpp duchain/localindexeddeclaration.cpp duchain/topducontext.cpp duchain/topducontextdynamicdata.cpp duchain/functiondefinition.cpp duchain/declaration.cpp duchain/classmemberdeclaration.cpp duchain/classfunctiondeclaration.cpp duchain/classdeclaration.cpp duchain/use.cpp duchain/forwarddeclaration.cpp duchain/duchainbase.cpp duchain/duchainlock.cpp duchain/identifier.cpp duchain/parsingenvironment.cpp duchain/abstractfunctiondeclaration.cpp duchain/functiondeclaration.cpp duchain/stringhelpers.cpp duchain/namespacealiasdeclaration.cpp duchain/aliasdeclaration.cpp duchain/dumpdotgraph.cpp duchain/duchainobserver.cpp duchain/duchainutils.cpp duchain/declarationid.cpp duchain/definitions.cpp duchain/uses.cpp duchain/importers.cpp duchain/dumpchain.cpp duchain/indexedstring.cpp duchain/duchainregister.cpp duchain/persistentsymboltable.cpp duchain/instantiationinformation.cpp duchain/types/typesystem.cpp duchain/types/typeregister.cpp duchain/types/identifiedtype.cpp duchain/types/abstracttype.cpp duchain/types/integraltype.cpp duchain/types/functiontype.cpp duchain/types/structuretype.cpp duchain/types/pointertype.cpp duchain/types/referencetype.cpp duchain/types/delayedtype.cpp duchain/types/arraytype.cpp duchain/types/indexedtype.cpp duchain/types/enumerationtype.cpp duchain/types/constantintegraltype.cpp duchain/types/enumeratortype.cpp duchain/types/typeutils.cpp duchain/types/typealiastype.cpp duchain/types/unsuretype.cpp duchain/repositories/itemrepository.cpp duchain/repositories/typerepository.cpp duchain/navigation/problemnavigationcontext.cpp duchain/navigation/abstractnavigationwidget.cpp duchain/navigation/abstractnavigationcontext.cpp duchain/navigation/usesnavigationcontext.cpp duchain/navigation/abstractdeclarationnavigationcontext.cpp duchain/navigation/abstractincludenavigationcontext.cpp duchain/navigation/useswidget.cpp duchain/navigation/usescollector.cpp interfaces/iastcontainer.cpp interfaces/ilanguagesupport.cpp interfaces/quickopendataprovider.cpp interfaces/iproblem.cpp interfaces/iquickopen.cpp interfaces/editorcontext.cpp interfaces/codecontext.cpp interfaces/icreateclasshelper.cpp interfaces/icontextbrowser.cpp codecompletion/codecompletion.cpp codecompletion/codecompletionworker.cpp codecompletion/codecompletionmodel.cpp codecompletion/codecompletionitem.cpp codecompletion/codecompletioncontext.cpp codecompletion/codecompletionitemgrouper.cpp codecompletion/codecompletionhelper.cpp codecompletion/normaldeclarationcompletionitem.cpp codegen/applychangeswidget.cpp codegen/coderepresentation.cpp codegen/documentchangeset.cpp codegen/duchainchangeset.cpp codegen/komparesupport.cpp codegen/utilities.cpp codegen/templatesmodel.cpp codegen/templateclassgenerator.cpp codegen/codedescription.cpp codegen/sourcefiletemplate.cpp codegen/templaterenderer.cpp codegen/templateengine.cpp codegen/archivetemplateloader.cpp util/setrepository.cpp util/includeitem.cpp util/navigationtooltip.cpp highlighting/colorcache.cpp highlighting/configurablecolors.cpp highlighting/codehighlighting.cpp checks/dataaccessrepository.cpp checks/dataaccess.cpp checks/controlflowgraph.cpp checks/controlflownode.cpp ) kde4_add_library(kdevplatformlanguage SHARED ${kdevplatformlanguage_LIB_SRCS}) target_link_libraries(kdevplatformlanguage ${KDE4_KPARTS_LIBS} ${KDE4_KTEXTEDITOR_LIBS} ${KDE4_THREADWEAVER_LIBRARIES} ${KDE4_KNEWSTUFF3_LIBS} kdevplatforminterfaces kdevplatformutil ${Grantlee_CORE_LIBRARIES}) # Need to add kdevplatforminterfaces and kdevplatformutil when those are exported targets target_link_libraries(kdevplatformlanguage LINK_INTERFACE_LIBRARIES kdevplatforminterfaces) set_target_properties(kdevplatformlanguage PROPERTIES VERSION ${KDEVPLATFORM_LIB_VERSION} SOVERSION ${KDEVPLATFORM_LIB_SOVERSION}) install(TARGETS kdevplatformlanguage EXPORT KDevPlatformTargets ${INSTALL_TARGETS_DEFAULT_ARGS} ) ########### install files ############### install(FILES languageexport.h DESTINATION ${INCLUDE_INSTALL_DIR}/kdevplatform/language COMPONENT Devel ) install(FILES interfaces/ilanguagesupport.h interfaces/icodehighlighting.h interfaces/quickopendataprovider.h interfaces/quickopenfilter.h interfaces/iquickopen.h interfaces/iproblem.h interfaces/codecontext.h interfaces/editorcontext.h interfaces/iastcontainer.h interfaces/icreateclasshelper.h interfaces/icontextbrowser.h DESTINATION ${INCLUDE_INSTALL_DIR}/kdevplatform/language/interfaces COMPONENT Devel ) install(FILES editor/persistentmovingrange.h editor/documentrange.h editor/documentcursor.h editor/simplecursor.h editor/simplerange.h editor/cursorinrevision.h editor/rangeinrevision.h editor/modificationrevision.h editor/modificationrevisionset.h DESTINATION ${INCLUDE_INSTALL_DIR}/kdevplatform/language/editor COMPONENT Devel ) install(FILES backgroundparser/backgroundparser.h backgroundparser/parsejob.h backgroundparser/parseprojectjob.h backgroundparser/urlparselock.h backgroundparser/documentchangetracker.h DESTINATION ${INCLUDE_INSTALL_DIR}/kdevplatform/language/backgroundparser COMPONENT Devel ) install(FILES util/navigationtooltip.h util/setrepository.h util/basicsetrepository.h util/includeitem.h util/debuglanguageparserhelper.h + util/kdevhash.h DESTINATION ${INCLUDE_INSTALL_DIR}/kdevplatform/language/util COMPONENT Devel ) install(FILES duchain/referencecounting.h duchain/parsingenvironment.h duchain/duchain.h duchain/codemodel.h duchain/ducontext.h duchain/ducontextdata.h duchain/topducontext.h duchain/topducontextutils.h duchain/topducontextdata.h duchain/declaration.h duchain/declarationdata.h duchain/classmemberdeclaration.h duchain/classmemberdeclarationdata.h duchain/classfunctiondeclaration.h duchain/classdeclaration.h duchain/functiondefinition.h duchain/use.h duchain/forwarddeclaration.h duchain/duchainbase.h duchain/duchainpointer.h duchain/duchainobserver.h duchain/duchainlock.h duchain/identifier.h duchain/abstractfunctiondeclaration.h duchain/functiondeclaration.h duchain/stringhelpers.h duchain/safetycounter.h duchain/namespacealiasdeclaration.h duchain/aliasdeclaration.h duchain/dumpdotgraph.h duchain/duchainutils.h duchain/dumpchain.h duchain/indexedstring.h duchain/declarationid.h duchain/appendedlist.h duchain/duchainregister.h duchain/persistentsymboltable.h duchain/instantiationinformation.h duchain/specializationstore.h duchain/persistentsetmap.h duchain/indexedducontext.h duchain/indexedtopducontext.h duchain/localindexedducontext.h duchain/indexeddeclaration.h duchain/localindexeddeclaration.h duchain/definitions.h DESTINATION ${INCLUDE_INSTALL_DIR}/kdevplatform/language/duchain COMPONENT Devel ) install(FILES duchain/types/unsuretype.h duchain/types/identifiedtype.h duchain/types/typesystem.h duchain/types/typeregister.h duchain/types/typepointer.h duchain/types/typesystemdata.h duchain/types/abstracttype.h duchain/types/integraltype.h duchain/types/functiontype.h duchain/types/structuretype.h duchain/types/pointertype.h duchain/types/referencetype.h duchain/types/delayedtype.h duchain/types/arraytype.h duchain/types/indexedtype.h duchain/types/enumerationtype.h duchain/types/constantintegraltype.h duchain/types/enumeratortype.h duchain/types/alltypes.h duchain/types/typeutils.h duchain/types/typealiastype.h DESTINATION ${INCLUDE_INSTALL_DIR}/kdevplatform/language/duchain/types COMPONENT Devel ) install(FILES duchain/builders/abstractcontextbuilder.h duchain/builders/abstractdeclarationbuilder.h duchain/builders/abstracttypebuilder.h duchain/builders/abstractusebuilder.h DESTINATION ${INCLUDE_INSTALL_DIR}/kdevplatform/language/duchain/builders COMPONENT Devel ) install(FILES duchain/repositories/itemrepository.h duchain/repositories/typerepository.h DESTINATION ${INCLUDE_INSTALL_DIR}/kdevplatform/language/duchain/repositories COMPONENT Devel ) install(FILES codecompletion/codecompletion.h codecompletion/codecompletionworker.h codecompletion/codecompletionmodel.h codecompletion/codecompletionitem.h codecompletion/codecompletioncontext.h codecompletion/codecompletionitemgrouper.h codecompletion/codecompletionhelper.h codecompletion/normaldeclarationcompletionitem.h codecompletion/abstractincludefilecompletionitem.h codecompletion/codecompletiontesthelper.h DESTINATION ${INCLUDE_INSTALL_DIR}/kdevplatform/language/codecompletion COMPONENT Devel ) install(FILES codegen/applychangeswidget.h codegen/astchangeset.h codegen/duchainchangeset.h codegen/documentchangeset.h codegen/coderepresentation.h codegen/utilities.h codegen/templatesmodel.h codegen/templaterenderer.h codegen/templateengine.h codegen/sourcefiletemplate.h codegen/templateclassgenerator.h codegen/codedescription.h codegen/sourcefiletemplate.h DESTINATION ${INCLUDE_INSTALL_DIR}/kdevplatform/language/codegen COMPONENT Devel ) install(FILES duchain/navigation/usesnavigationcontext.h duchain/navigation/abstractnavigationcontext.h duchain/navigation/abstractdeclarationnavigationcontext.h duchain/navigation/abstractincludenavigationcontext.h duchain/navigation/abstractnavigationwidget.h duchain/navigation/navigationaction.h duchain/navigation/useswidget.h duchain/navigation/usescollector.h DESTINATION ${INCLUDE_INSTALL_DIR}/kdevplatform/language/duchain/navigation COMPONENT Devel ) install(FILES highlighting/codehighlighting.h highlighting/colorcache.h highlighting/configurablecolors.h DESTINATION ${INCLUDE_INSTALL_DIR}/kdevplatform/language/highlighting COMPONENT Devel ) install(FILES checks/dataaccess.h checks/dataaccessrepository.h checks/controlflowgraph.h checks/controlflownode.h DESTINATION ${INCLUDE_INSTALL_DIR}/kdevplatform/language/checks COMPONENT Devel ) diff --git a/language/duchain/declarationid.h b/language/duchain/declarationid.h index 7caccf5cf2..a6663b8ab3 100644 --- a/language/duchain/declarationid.h +++ b/language/duchain/declarationid.h @@ -1,200 +1,201 @@ /* This file is part of KDevelop Copyright 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 DECLARATION_ID_H #define DECLARATION_ID_H #include "../editor/cursorinrevision.h" #include "indexeddeclaration.h" #include "identifier.h" #include "instantiationinformation.h" +#include //krazy:excludeall=dpointer class QString; namespace KDevelop { class Declaration; class TopDUContext; /** * \short Allows clearly identifying a Declaration. * * DeclarationId is needed to uniquely address Declarations that are in another top-context, * because there may be multiple parsed versions of a file. * * There are two forms of DeclarationId, one indirect and one direct. The direct form * holds a reference to the Declaration instance, whereas the indirect form stores the qualified * identifier and an additional index to disambiguate instances of multiple declarations with the same * identifier. * * Both forms also have a specialization index. It can be used in a language-specific way to pick other * versions of the declaration. When the declaration is found, Declaration::specialize() is called on * the found declaration with this value, and the returned value is the actually found declaration. * * \note This only works when the Declaration is in the symbol table. * */ class KDEVPLATFORMLANGUAGE_EXPORT DeclarationId { public: /** * Constructor for indirect access to a declaration. The resulting DeclarationId will not * have a direct reference to the Declaration, but will look it up as needed. * * \param id Identifier for this declaration id. * \param additionalId Additional index to disambiguate * \param specialization Specialization index (see class documentation). */ explicit DeclarationId(const IndexedQualifiedIdentifier& id = IndexedQualifiedIdentifier(), uint additionalId = 0, const IndexedInstantiationInformation& specialization = IndexedInstantiationInformation()); /** * Constructor for direct access to a declaration. The resulting DeclarationId will * directly reference the Declaration * * \param decl Declaration to reference. * \param specialization Specialization index (see class documentation). */ explicit DeclarationId(const IndexedDeclaration& decl, const IndexedInstantiationInformation& specialization = IndexedInstantiationInformation()); /** * Equality operator. * * \param rhs declaration identifier to compare. * \returns true if equal, otherwise false. */ bool operator==(const DeclarationId& rhs) const { if(m_direct != rhs.m_direct) return false; if(!m_direct) return indirect.m_identifier == rhs.indirect.m_identifier && indirect.m_additionalIdentity == rhs.indirect.m_additionalIdentity && m_specialization == rhs.m_specialization; else return direct == rhs.direct && m_specialization == rhs.m_specialization; } /** * Not equal operator. * * \param rhs declaration identifier to compare. * \returns true if not equal, otherwise false. */ bool operator!=(const DeclarationId& rhs) const { return !operator==(rhs); } /** * Determine whether this declaration identifier references a valid declaration. */ bool isValid() const { return (m_direct && direct.isValid()) || indirect.m_identifier.isValid(); } /** * Hash function for this declaration identifier. * * \warning This may return different hashes for the same declaration, * depending on whether the id is direct or indirect, * and thus you cannot compare hashes for declaration equality (use operator==() instead) */ uint hash() const { if(m_direct) - return direct.hash() + m_specialization.index() * 101; + return KDevHash() << direct.hash() << m_specialization.index(); else - return indirect.m_identifier.getIndex() * 13 + indirect.m_additionalIdentity + m_specialization.index() * 101; + return KDevHash() << indirect.m_identifier.getIndex() << indirect.m_additionalIdentity << m_specialization.index(); } /** * Retrieve the declaration, from the perspective of \a context. * In order to be retrievable, the declaration must be in the symbol table. * * \param context Context in which to search for the Declaration. * \param instantiateIfRequired Whether the declaration should be instantiated if required * \returns the referenced Declaration, or null if none was found. * */ Declaration* getDeclaration(const TopDUContext* context, bool instantiateIfRequired = true) const; /** * Same as getDeclaration(..), but returns all matching declarations if there are multiple. * This also returns found forward-declarations. */ KDevVarLengthArray getDeclarations(const TopDUContext* context) const; /** * Set the specialization index (see class documentation). * * \param specializationIndex the new specialization index. */ void setSpecialization(const IndexedInstantiationInformation& spec); /** * Retrieve the specialization index (see class documentation). * * \returns the specialization index. */ IndexedInstantiationInformation specialization() const; /** * Determine whether this DeclarationId directly references a Declaration by indices, * or if it uses identifiers and other data to reference the Declaration. * * \returns true if direct, false if indirect. */ bool isDirect() const; /** * Return the qualified identifier for this declaration. * * \warning This is relatively expensive, and not 100% correct in all cases(actually a top-context would be needed to resolve this correctly), * so avoid using this, except for debugging purposes. */ QualifiedIdentifier qualifiedIdentifier() const; private: struct Indirect { IndexedQualifiedIdentifier m_identifier; // Hash from signature, or similar. // Used to disambiguate multiple declarations of the same name. uint m_additionalIdentity; } ; //union { //An indirect reference to the declaration, which uses the symbol-table for lookup. Should be preferred for all //declarations that are in the symbol-table Indirect indirect; IndexedDeclaration direct; //}; bool m_direct; // Can be used in a language-specific way to pick other versions of the declaration. // When the declaration is found, pickSpecialization is called on the found declaration // with this value, and the returned value is the actually found declaration. IndexedInstantiationInformation m_specialization; }; inline uint qHash(const KDevelop::DeclarationId& id) { return id.hash(); } } Q_DECLARE_TYPEINFO(KDevelop::DeclarationId, Q_MOVABLE_TYPE); #endif diff --git a/language/duchain/identifier.cpp b/language/duchain/identifier.cpp index ef6dbe3274..ea0839b8bd 100644 --- a/language/duchain/identifier.cpp +++ b/language/duchain/identifier.cpp @@ -1,1289 +1,1291 @@ /* This file is part of KDevelop Copyright 2006 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. */ #include "identifier.h" #include #include "stringhelpers.h" #include "indexedstring.h" #include "appendedlist_static.h" #include "repositories/itemrepository.h" +#include "util/kdevhash.h" #define ifDebug(x) namespace KDevelop { template class IdentifierPrivate { public: IdentifierPrivate() : m_unique(0), m_refCount(0), m_hash(0) { } template IdentifierPrivate(const IdentifierPrivate& rhs) : m_unique(rhs.m_unique), m_identifier(rhs.m_identifier), m_refCount(0), m_hash(rhs.m_hash) { copyListsFrom(rhs); } ~IdentifierPrivate() { templateIdentifiersList.free(const_cast(templateIdentifiers())); } //Flags the stored hash-value invalid void clearHash() { //This is always called on an object private to an Identifier, so there is no threading-problem. Q_ASSERT(dynamic); m_hash = 0; } uint hash() const { //Since this only needs reading and the data needs not to be private, this may be called by multiple threads simultaneously, so computeHash() must be thread-safe. if( !m_hash && dynamic ) computeHash(); return m_hash; } int m_unique; IndexedString m_identifier; uint m_refCount; START_APPENDED_LISTS_STATIC(IdentifierPrivate) APPENDED_LIST_FIRST_STATIC(IndexedTypeIdentifier, templateIdentifiers) END_APPENDED_LISTS_STATIC(templateIdentifiers) unsigned int itemSize() const { return sizeof(IdentifierPrivate) + lastOffsetBehind(); } void computeHash() const { Q_ASSERT(dynamic); //this must stay thread-safe(may be called by multiple threads at a time) //The thread-safety is given because all threads will have the same result, and it will only be written once at the end. - uint hash = m_identifier.hash(); + KDevHash kdevhash; + kdevhash << m_identifier.hash() << m_unique; FOREACH_FUNCTION_STATIC(const IndexedTypeIdentifier& templateIdentifier, templateIdentifiers) - hash = hash * 13 + templateIdentifier.hash(); - hash += m_unique; - m_hash = hash; + kdevhash << IndexedTypeIdentifier(templateIdentifier).hash(); + m_hash = kdevhash; } mutable uint m_hash; }; typedef IdentifierPrivate DynamicIdentifierPrivate; typedef IdentifierPrivate ConstantIdentifierPrivate; struct IdentifierItemRequest { IdentifierItemRequest(const DynamicIdentifierPrivate& identifier) : m_identifier(identifier) { identifier.hash(); //Make sure the hash is valid by calling this } enum { AverageSize = sizeof(IdentifierPrivate)+4 }; //Should return the hash-value associated with this request(For example the hash of a string) unsigned int hash() const { return m_identifier.hash(); } //Should return the size of an item created with createItem unsigned int itemSize() const { return m_identifier.itemSize(); } //Should create an item where the information of the requested item is permanently stored. The pointer //@param item equals an allocated range with the size of itemSize(). void createItem(ConstantIdentifierPrivate* item) const { new (item) ConstantIdentifierPrivate(m_identifier); } static bool persistent(const ConstantIdentifierPrivate* item) { return (bool)item->m_refCount; } static void destroy(ConstantIdentifierPrivate* item, KDevelop::AbstractItemRepository&) { item->~ConstantIdentifierPrivate(); } //Should return whether the here requested item equals the given item bool equals(const ConstantIdentifierPrivate* item) const { return item->m_hash == m_identifier.m_hash && item->m_unique == m_identifier.m_unique && item->m_identifier == m_identifier.m_identifier && m_identifier.listsEqual(*item); } const DynamicIdentifierPrivate& m_identifier; }; static RepositoryManager< ItemRepository, false>& identifierRepository() { static RepositoryManager< ItemRepository, false> identifierRepositoryObject("Identifier Repository"); return identifierRepositoryObject; } ///This has to be initialized now, else we will get a crash when multiple threads try accessing it for the first time in the same moment uint emptyConstantIdentifierPrivateIndex() { static uint index = identifierRepository()->index(DynamicIdentifierPrivate()); if(index == 0) ///Just so the function is instantiated right now identifierRepository()->deleteItem(0); return index; } const ConstantIdentifierPrivate* emptyConstantIdentifierPrivate() { return identifierRepository()->itemFromIndex(emptyConstantIdentifierPrivateIndex()); } bool IndexedIdentifier::isEmpty() const { return index == emptyConstantIdentifierPrivateIndex(); } ///Before something is modified in QualifiedIdentifierPrivate, it must be made sure that it is private to the QualifiedIdentifier it is used in(@see QualifiedIdentifier::prepareWrite) template class QualifiedIdentifierPrivate { public: QualifiedIdentifierPrivate() : m_explicitlyGlobal(false), m_isExpression(false), m_hash(0), m_refCount(0) { } template QualifiedIdentifierPrivate(const QualifiedIdentifierPrivate& rhs) : m_explicitlyGlobal(rhs.m_explicitlyGlobal) , m_isExpression(rhs.m_isExpression) , m_hash(rhs.m_hash) , m_refCount(0) { copyListsFrom(rhs); } ~QualifiedIdentifierPrivate() { identifiersList.free(const_cast(identifiers())); } bool m_explicitlyGlobal:1; bool m_isExpression:1; mutable uint m_hash; uint m_refCount; START_APPENDED_LISTS_STATIC(QualifiedIdentifierPrivate) APPENDED_LIST_FIRST_STATIC(IndexedIdentifier, identifiers) END_APPENDED_LISTS_STATIC(identifiers) unsigned int itemSize() const { return sizeof(QualifiedIdentifierPrivate) + lastOffsetBehind(); } //Constructs m_identifiers void splitIdentifiers( const QString& str, int start ) { Q_ASSERT(dynamic); uint currentStart = start; while( currentStart < (uint)str.length() ) { identifiersList.append(IndexedIdentifier(Identifier( str, currentStart, ¤tStart ))); while( currentStart < (uint)str.length() && (str[currentStart] == ' ' ) ) ++currentStart; currentStart += 2; //Skip "::" } } inline void clearHash() const { m_hash = 0; } uint hash() const { if( m_hash == 0 ) { uint mhash = 0; FOREACH_FUNCTION_STATIC( const IndexedIdentifier& identifier, identifiers ) mhash = 11*mhash + Identifier(identifier).hash(); if(mhash != m_hash) m_hash = mhash;//The local class may be in read-only memory, so only change m_hash if it's actually a change } return m_hash; } }; typedef QualifiedIdentifierPrivate DynamicQualifiedIdentifierPrivate; typedef QualifiedIdentifierPrivate ConstantQualifiedIdentifierPrivate; struct QualifiedIdentifierItemRequest { QualifiedIdentifierItemRequest(const DynamicQualifiedIdentifierPrivate& identifier) : m_identifier(identifier) { identifier.hash(); //Make sure the hash is valid by calling this } enum { AverageSize = sizeof(QualifiedIdentifierPrivate)+8 }; //Should return the hash-value associated with this request(For example the hash of a string) unsigned int hash() const { return m_identifier.hash(); } //Should return the size of an item created with createItem unsigned int itemSize() const { return m_identifier.itemSize(); } //Should create an item where the information of the requested item is permanently stored. The pointer //@param item equals an allocated range with the size of itemSize(). void createItem(ConstantQualifiedIdentifierPrivate* item) const { Q_ASSERT(shouldDoDUChainReferenceCounting(item)); Q_ASSERT(shouldDoDUChainReferenceCounting(((char*)item) + (itemSize()-1))); new (item) ConstantQualifiedIdentifierPrivate(m_identifier); } static bool persistent(const ConstantQualifiedIdentifierPrivate* item) { return (bool)item->m_refCount; } static void destroy(ConstantQualifiedIdentifierPrivate* item, KDevelop::AbstractItemRepository&) { Q_ASSERT(shouldDoDUChainReferenceCounting(item)); item->~ConstantQualifiedIdentifierPrivate(); } //Should return whether the here requested item equals the given item bool equals(const ConstantQualifiedIdentifierPrivate* item) const { return item->m_explicitlyGlobal == m_identifier.m_explicitlyGlobal && item->m_isExpression == m_identifier.m_isExpression && item->m_hash == m_identifier.m_hash && m_identifier.listsEqual(*item); } const DynamicQualifiedIdentifierPrivate& m_identifier; }; AbstractRepositoryManager* returnIdentifierRepository() { return &identifierRepository(); } static RepositoryManager< ItemRepository, false>& qualifiedidentifierRepository() { static RepositoryManager< ItemRepository, false> qualifiedidentifierRepositoryObject("Qualified Identifier Repository", 1, &returnIdentifierRepository); return qualifiedidentifierRepositoryObject; } uint emptyConstantQualifiedIdentifierPrivateIndex() { static uint index = qualifiedidentifierRepository()->index(DynamicQualifiedIdentifierPrivate()); if(index == 0) ///Just so the function is instantiated right now identifierRepository()->deleteItem(0); return index; } const ConstantQualifiedIdentifierPrivate* emptyConstantQualifiedIdentifierPrivate() { return qualifiedidentifierRepository()->itemFromIndex(emptyConstantQualifiedIdentifierPrivateIndex()); } // uint QualifiedIdentifier::combineHash(uint leftHash, uint /*leftSize*/, Identifier appendIdentifier) { // return 11*leftHash + appendIdentifier.hash(); // } Identifier::Identifier(const Identifier& rhs) { rhs.makeConstant(); cd = rhs.cd; m_index = rhs.m_index; } Identifier::Identifier(uint index) : m_index(index) { Q_ASSERT(m_index); cd = identifierRepository()->itemFromIndex(index); } Identifier::~Identifier() { if(!m_index) delete dd; } bool Identifier::nameEquals(const Identifier& rhs) const { return identifier() == rhs.identifier(); } uint Identifier::hash() const { if(!m_index) return dd->hash(); else return cd->hash(); } bool Identifier::isEmpty() const { if(!m_index) return dd->m_identifier.isEmpty() && dd->m_unique == 0 && dd->templateIdentifiersSize() == 0; else return cd->m_identifier.isEmpty() && cd->m_unique == 0 && cd->templateIdentifiersSize() == 0; } Identifier::Identifier(const IndexedString& str) : m_index(0), dd(new IdentifierPrivate) { dd->m_identifier = str; } Identifier::Identifier(const QString& id, uint start, uint* takenRange) : m_index(0), dd(new IdentifierPrivate) { ///Extract template-parameters ParamIterator paramIt("<>:", id, start); dd->m_identifier = IndexedString(paramIt.prefix().trimmed()); while( paramIt ) { appendTemplateIdentifier( IndexedTypeIdentifier(IndexedQualifiedIdentifier(QualifiedIdentifier(*paramIt))) ); ++paramIt; } if( takenRange ) *takenRange = paramIt.position(); } Identifier::Identifier() : m_index(emptyConstantIdentifierPrivateIndex()), cd(emptyConstantIdentifierPrivate()) { } Identifier Identifier::unique(int token) { Identifier ret; ret.setUnique(token); return ret; } bool Identifier::isUnique() const { if(!m_index) return dd->m_unique; else return cd->m_unique; } int Identifier::uniqueToken() const { if(!m_index) return dd->m_unique; else return cd->m_unique; } void Identifier::setUnique(int token) { prepareWrite(); dd->m_unique = token; } const IndexedString Identifier::identifier() const { if(!m_index) return dd->m_identifier; else return cd->m_identifier; } void Identifier::setIdentifier(const QString& identifier) { prepareWrite(); dd->m_identifier = IndexedString(identifier); } void Identifier::setIdentifier(const IndexedString& identifier) { prepareWrite(); dd->m_identifier = identifier; } IndexedTypeIdentifier Identifier::templateIdentifier(int num) const { if(!m_index) return dd->templateIdentifiers()[num]; else return cd->templateIdentifiers()[num]; } uint Identifier::templateIdentifiersCount() const { if(!m_index) return dd->templateIdentifiersSize(); else return cd->templateIdentifiersSize(); } void Identifier::appendTemplateIdentifier(const IndexedTypeIdentifier& identifier) { prepareWrite(); dd->templateIdentifiersList.append(identifier); } void Identifier::clearTemplateIdentifiers() { prepareWrite(); dd->templateIdentifiersList.clear(); } uint Identifier::index() const { makeConstant(); Q_ASSERT(m_index); return m_index; } void Identifier::setTemplateIdentifiers(const QList& templateIdentifiers) { prepareWrite(); dd->templateIdentifiersList.clear(); foreach(const IndexedTypeIdentifier& id, templateIdentifiers) dd->templateIdentifiersList.append(id); } QString Identifier::toString() const { if (!this) { return "(null identifier)"; } QString ret = identifier().str(); /* if(isUnique()) ret += "unique";*/ if (templateIdentifiersCount()) { ret.append("< "); for (uint i = 0; i < templateIdentifiersCount(); ++i) { ret.append(templateIdentifier(i).toString()); if (i != templateIdentifiersCount() - 1) ret.append(", "); } ret.append(" >"); } return ret; } bool Identifier::operator==(const Identifier& rhs) const { return index() == rhs.index(); } bool Identifier::operator!=(const Identifier& rhs) const { return !operator==(rhs); } Identifier& Identifier::operator=(const Identifier& rhs) { if(dd == rhs.dd && cd == rhs.cd) return *this; if(!m_index) delete dd; dd = 0; rhs.makeConstant(); cd = rhs.cd; m_index = rhs.m_index; Q_ASSERT(cd); return *this; } uint QualifiedIdentifier::index() const { makeConstant(); Q_ASSERT(m_index); return m_index; } void Identifier::makeConstant() const { if(m_index) return; m_index = identifierRepository()->index( IdentifierItemRequest(*dd) ); delete dd; cd = identifierRepository()->itemFromIndex( m_index ); } void Identifier::prepareWrite() { if(m_index) { const IdentifierPrivate* oldCc = cd; dd = new IdentifierPrivate; dd->m_hash = oldCc->m_hash; dd->m_unique = oldCc->m_unique; dd->m_identifier = oldCc->m_identifier; dd->copyListsFrom(*oldCc); m_index = 0; } dd->clearHash(); } bool QualifiedIdentifier::inRepository() const { if(m_index) return true; else return (bool)qualifiedidentifierRepository()->findIndex( QualifiedIdentifierItemRequest(*dd) ); } QualifiedIdentifier::QualifiedIdentifier(uint index) : m_index(index), cd( qualifiedidentifierRepository()->itemFromIndex(index) ) { } QualifiedIdentifier::QualifiedIdentifier(const QString& id, bool isExpression) : m_index(0), dd(new DynamicQualifiedIdentifierPrivate) { if(isExpression) { setIsExpression(true); if(!id.isEmpty()) { //Prevent tokenization, since we may lose information there Identifier finishedId; finishedId.setIdentifier(id); push(finishedId); } }else{ if (id.startsWith("::")) { dd->m_explicitlyGlobal = true; dd->splitIdentifiers(id, 2); } else { dd->m_explicitlyGlobal = false; dd->splitIdentifiers(id, 0); } } } QualifiedIdentifier::QualifiedIdentifier(const Identifier& id) : m_index(0), dd(new DynamicQualifiedIdentifierPrivate) { if (id.dd->m_identifier.str().isEmpty()) { dd->m_explicitlyGlobal = true; } else { dd->m_explicitlyGlobal = false; dd->identifiersList.append(IndexedIdentifier(id)); } } QualifiedIdentifier::QualifiedIdentifier() : m_index(emptyConstantQualifiedIdentifierPrivateIndex()), cd(emptyConstantQualifiedIdentifierPrivate()) { } QualifiedIdentifier::~QualifiedIdentifier() { if(!m_index) delete dd; } QualifiedIdentifier::QualifiedIdentifier(const QualifiedIdentifier& id) { if(id.m_index) { m_index = id.m_index; cd = id.cd; }else{ m_index = 0; dd = new QualifiedIdentifierPrivate(*id.dd); } } QStringList QualifiedIdentifier::toStringList() const { QStringList ret; if (explicitlyGlobal()) ret.append(QString()); if(m_index) { FOREACH_FUNCTION_STATIC(const IndexedIdentifier& index, cd->identifiers) ret << index.identifier().toString(); }else{ FOREACH_FUNCTION_STATIC(const IndexedIdentifier& index, dd->identifiers) ret << index.identifier().toString(); } return ret; } QString QualifiedIdentifier::toString(bool ignoreExplicitlyGlobal) const { QString ret; if( !ignoreExplicitlyGlobal && explicitlyGlobal() ) ret = "::"; bool first = true; if(m_index) { FOREACH_FUNCTION_STATIC(const IndexedIdentifier& index, cd->identifiers) { if( !first ) ret += "::"; else first = false; ret += index.identifier().toString(); } }else{ FOREACH_FUNCTION_STATIC(const IndexedIdentifier& index, dd->identifiers) { if( !first ) ret += "::"; else first = false; ret += index.identifier().toString(); } } return ret; } QualifiedIdentifier QualifiedIdentifier::merge(const QualifiedIdentifier& base) const { QualifiedIdentifier ret(base); ret.prepareWrite(); if(m_index) ret.dd->identifiersList.append(cd->identifiers(), cd->identifiersSize()); else ret.dd->identifiersList.append(dd->identifiers(), dd->identifiersSize()); if( explicitlyGlobal() ) ret.setExplicitlyGlobal(true); return ret; } QualifiedIdentifier QualifiedIdentifier::operator+(const QualifiedIdentifier& rhs) const { return rhs.merge(*this); } QualifiedIdentifier& QualifiedIdentifier::operator+=(const QualifiedIdentifier& rhs) { push(rhs); return *this; } QualifiedIdentifier QualifiedIdentifier::operator+(const Identifier& rhs) const { QualifiedIdentifier ret(*this); ret.push(rhs); return ret; } QualifiedIdentifier& QualifiedIdentifier::operator+=(const Identifier& rhs) { push(rhs); return *this; } // QualifiedIdentifier QualifiedIdentifier::strip(const QualifiedIdentifier & unwantedBase) const // { // // Don't strip the top identifier // if (count() <= unwantedBase.count()) // return *this; // // //Make sure this one starts with unwantedBase // for( int a = 0; a < unwantedBase.count(); a++ ) // if( d->m_identifiers[a] != unwantedBase.d->m_identifiers[a] ) // return *this; // // // QualifiedIdentifier ret; // ret.setExplicitlyGlobal(false); // ret.prepareWrite(); // // int remove = unwantedBase.d->m_identifiers.count(); // // ret.d->m_identifiers.append(&d->m_identifiers[remove], d->m_identifiers.size() - remove); // // return ret; // } bool QualifiedIdentifier::isExpression() const { if(m_index) return cd->m_isExpression; else return dd->m_isExpression; } void QualifiedIdentifier::setIsExpression(bool is) { prepareWrite(); dd->m_isExpression = is; } bool QualifiedIdentifier::explicitlyGlobal() const { // True if started with "::" if(m_index) return cd->m_explicitlyGlobal; else return dd->m_explicitlyGlobal; } void QualifiedIdentifier::setExplicitlyGlobal(bool eg) { prepareWrite(); dd->m_explicitlyGlobal = eg; } bool QualifiedIdentifier::sameIdentifiers(const QualifiedIdentifier& rhs) const { if(m_index && rhs.m_index) return cd->listsEqual(*rhs.cd); else if(m_index && !rhs.m_index) return cd->listsEqual(*rhs.dd); else if(!m_index && !rhs.m_index) return dd->listsEqual(*rhs.dd); else return dd->listsEqual(*rhs.cd); } // bool QualifiedIdentifier::isSame(const QualifiedIdentifier& rhs, bool ignoreExplicitlyGlobal) const // { // if( cd == rhs.cd ) // return true; // // if (!ignoreExplicitlyGlobal && (explicitlyGlobal() != rhs.explicitlyGlobal())) // return false; // // if( isExpression() != rhs.isExpression() ) // return false; // // if( hash() != rhs.hash() ) // return false; // // return sameIdentifiers(rhs); // } bool QualifiedIdentifier::operator==(const QualifiedIdentifier& rhs) const { if( cd == rhs.cd ) return true; return hash() == rhs.hash() && sameIdentifiers(rhs); } bool QualifiedIdentifier::operator!=(const QualifiedIdentifier& rhs) const { return !operator==(rhs); } QualifiedIdentifier& QualifiedIdentifier::operator=(const QualifiedIdentifier& rhs) { if(!m_index) delete dd; rhs.makeConstant(); cd = rhs.cd; m_index = rhs.m_index; return *this; } bool QualifiedIdentifier::beginsWith(const QualifiedIdentifier& other) const { uint c = count(); uint oc = other.count(); for (uint i = 0; i < c && i < oc; ++i) if (at(i) == other.at(i)) { continue; } else { return false; } return true; } struct Visitor { Visitor(KDevVarLengthArray& _target, uint _hash) : target(_target), hash(_hash) { } bool operator()(const ConstantQualifiedIdentifierPrivate* item, uint index) const { if(item->m_hash == hash) target.append(QualifiedIdentifier(index)); return true; } KDevVarLengthArray& target; uint hash; }; void QualifiedIdentifier::findByHash(HashType hash, KDevVarLengthArray& target) { Visitor v(target, hash); qualifiedidentifierRepository()->visitItemsWithHash(v, hash); } uint QualifiedIdentifier::hash() const { if(m_index) return cd->hash(); else return dd->hash(); } uint qHash(const IndexedTypeIdentifier& id) { return id.hash(); } uint qHash(const QualifiedIdentifier& id) { return id.hash(); } uint qHash(const Identifier& id) { return id.hash(); } bool QualifiedIdentifier::isQualified() const { return count() > 1 || explicitlyGlobal(); } void QualifiedIdentifier::push(const Identifier& id) { if(id.isEmpty()) return; prepareWrite(); dd->identifiersList.append(IndexedIdentifier(id)); } void QualifiedIdentifier::push(const QualifiedIdentifier& id) { if(id.isEmpty()) return; prepareWrite(); id.makeConstant(); dd->identifiersList.append(id.cd->identifiers(), id.cd->identifiersSize()); } void QualifiedIdentifier::pop() { prepareWrite(); if(!dd->identifiersSize()) return; dd->identifiersList.resize(dd->identifiersList.size()-1); } void QualifiedIdentifier::clear() { prepareWrite(); dd->identifiersList.clear(); dd->m_explicitlyGlobal = false; dd->m_isExpression = false; } bool QualifiedIdentifier::isEmpty() const { if(m_index) return cd->identifiersSize() == 0; else return dd->identifiersSize() == 0; } int QualifiedIdentifier::count() const { if(m_index) return cd->identifiersSize(); else return dd->identifiersSize(); } Identifier QualifiedIdentifier::first() const { if( (m_index && cd->identifiersSize() == 0) || (!m_index && dd->identifiersSize() == 0) ) return Identifier(); else return at(0); } Identifier QualifiedIdentifier::last() const { uint c = count(); if(c) return at(c-1); else return Identifier(); } Identifier QualifiedIdentifier::top() const { return last(); } QualifiedIdentifier QualifiedIdentifier::mid(int pos, int len) const { QualifiedIdentifier ret; if( pos == 0 ) ret.setExplicitlyGlobal(explicitlyGlobal()); int cnt = (int)count(); if( len == -1 ) len = cnt - pos; if( pos+len > cnt ) len -= cnt - (pos+len); for( int a = pos; a < pos+len; a++ ) ret.push(at(a)); return ret; } const Identifier QualifiedIdentifier::at(int i) const { if(m_index) { Q_ASSERT(i >= 0 && i < (int)cd->identifiersSize()); return cd->identifiers()[i]; }else{ Q_ASSERT(i >= 0 && i < (int)dd->identifiersSize()); return dd->identifiers()[i]; } } void QualifiedIdentifier::makeConstant() const { if(m_index) return; m_index = qualifiedidentifierRepository()->index( QualifiedIdentifierItemRequest(*dd) ); delete dd; cd = qualifiedidentifierRepository()->itemFromIndex( m_index ); } void QualifiedIdentifier::prepareWrite() { if(m_index) { const QualifiedIdentifierPrivate* oldCc = cd; dd = new QualifiedIdentifierPrivate; dd->m_explicitlyGlobal = oldCc->m_explicitlyGlobal; dd->m_isExpression = oldCc->m_isExpression; dd->m_hash = oldCc->m_hash; dd->copyListsFrom(*oldCc); m_index = 0; } dd->clearHash(); } uint IndexedTypeIdentifier::hash() const { - return m_identifier.getIndex() * 13 + (m_isConstant ? 17 : 0) + (m_isReference ? 12371 : 0) + (m_isRValue ? 4543 : 0) + m_pointerConstMask * 89321 + m_pointerDepth * 1023; + uint bitfields = m_isConstant | (m_isReference << 1) | (m_isRValue << 2) | (m_pointerDepth << 3) | (m_pointerConstMask << 8); + return KDevHash() << m_identifier.getIndex() << bitfields; } bool IndexedTypeIdentifier::operator==(const IndexedTypeIdentifier& rhs) const { return m_identifier == rhs.m_identifier && m_isConstant == rhs.m_isConstant && m_isReference == rhs.m_isReference && m_isRValue == rhs.m_isRValue && m_pointerConstMask == rhs.m_pointerConstMask && m_pointerDepth == rhs.m_pointerDepth; } bool IndexedTypeIdentifier::operator!=(const IndexedTypeIdentifier& rhs) const { return !operator==(rhs); } bool IndexedTypeIdentifier::isReference() const { return m_isReference; } void IndexedTypeIdentifier::setIsReference(bool isRef) { m_isReference = isRef; } bool IndexedTypeIdentifier::isRValue() const { return m_isRValue; } void IndexedTypeIdentifier::setIsRValue(bool isRVal) { m_isRValue = isRVal; } bool IndexedTypeIdentifier::isConstant() const { return m_isConstant; } void IndexedTypeIdentifier::setIsConstant(bool isConst) { m_isConstant = isConst; } ///Returns the pointer depth. Example for C++: "char*" has pointer-depth 1, "char***" has pointer-depth 3 int IndexedTypeIdentifier::pointerDepth() const { return m_pointerDepth; } /**Sets the pointer-depth to the specified count * For efficiency-reasons the maximum currently is 32. */ void IndexedTypeIdentifier::setPointerDepth(int depth) { ///Clear the mask in removed fields for(int s = depth; s < (int)m_pointerDepth; ++s) setIsConstPointer(s, false); m_pointerDepth = depth; } bool IndexedTypeIdentifier::isConstPointer(int depthNumber) const { return m_pointerConstMask & (1 << depthNumber); } void IndexedTypeIdentifier::setIsConstPointer(int depthNumber, bool constant) { if(constant) m_pointerConstMask |= (1 << depthNumber); else m_pointerConstMask &= (~(1 << depthNumber)); } QString IndexedTypeIdentifier::toString(bool ignoreExplicitlyGlobal) const { QString ret; if(isConstant()) ret += "const "; ret += m_identifier.identifier().toString(ignoreExplicitlyGlobal); for(int a = 0; a < pointerDepth(); ++a) { ret += '*'; if( isConstPointer(a) ) ret += "const"; } if(isRValue()) ret += "&&"; else if(isReference()) ret += '&'; return ret; } IndexedTypeIdentifier::IndexedTypeIdentifier(KDevelop::IndexedQualifiedIdentifier identifier) : m_identifier(identifier) , m_isConstant(false) , m_isReference(false) , m_isRValue(false) , m_pointerDepth(0) , m_pointerConstMask(0) { } IndexedTypeIdentifier::IndexedTypeIdentifier(const QString& identifier, bool isExpression) : m_identifier(QualifiedIdentifier(identifier, isExpression)) , m_isConstant(false) , m_isReference(false) , m_isRValue(false) , m_pointerDepth(0) , m_pointerConstMask(0) { } IndexedIdentifier::IndexedIdentifier() : index(emptyConstantIdentifierPrivateIndex()) { if(shouldDoDUChainReferenceCounting(this)) { QMutexLocker lock(identifierRepository()->mutex()); increase(identifierRepository()->dynamicItemFromIndexSimple(index)->m_refCount, index); } } IndexedIdentifier::IndexedIdentifier(const Identifier& id) : index(id.index()) { if(shouldDoDUChainReferenceCounting(this)) { QMutexLocker lock(identifierRepository()->mutex()); increase(identifierRepository()->dynamicItemFromIndexSimple(index)->m_refCount, index); } } IndexedIdentifier::IndexedIdentifier(const IndexedIdentifier& rhs) : index(rhs.index) { if(shouldDoDUChainReferenceCounting(this)) { QMutexLocker lock(identifierRepository()->mutex()); increase(identifierRepository()->dynamicItemFromIndexSimple(index)->m_refCount, index); } } IndexedIdentifier::~IndexedIdentifier() { if(shouldDoDUChainReferenceCounting(this)) { QMutexLocker lock(identifierRepository()->mutex()); decrease(identifierRepository()->dynamicItemFromIndexSimple(index)->m_refCount, index); } } IndexedIdentifier& IndexedIdentifier::operator=(const Identifier& id) { if(shouldDoDUChainReferenceCounting(this)) { QMutexLocker lock(identifierRepository()->mutex()); decrease(identifierRepository()->dynamicItemFromIndexSimple(index)->m_refCount, index); } index = id.index(); if(shouldDoDUChainReferenceCounting(this)) { QMutexLocker lock(identifierRepository()->mutex()); increase(identifierRepository()->dynamicItemFromIndexSimple(index)->m_refCount, index); } return *this; } IndexedIdentifier& IndexedIdentifier::operator=(const IndexedIdentifier& id) { if(shouldDoDUChainReferenceCounting(this)) { QMutexLocker lock(identifierRepository()->mutex()); decrease(identifierRepository()->dynamicItemFromIndexSimple(index)->m_refCount, index); } index = id.index; if(shouldDoDUChainReferenceCounting(this)) { QMutexLocker lock(identifierRepository()->mutex()); increase(identifierRepository()->dynamicItemFromIndexSimple(index)->m_refCount, index); } return *this; } bool IndexedIdentifier::operator==(const IndexedIdentifier& rhs) const { return index == rhs.index; } bool IndexedIdentifier::operator!=(const IndexedIdentifier& rhs) const { return index != rhs.index; } bool IndexedIdentifier::operator==(const Identifier& id) const { return index == id.index(); } Identifier IndexedIdentifier::identifier() const { return Identifier(index); } IndexedIdentifier::operator Identifier() const { return Identifier(index); } bool IndexedQualifiedIdentifier::isValid() const { return index != emptyConstantQualifiedIdentifierPrivateIndex(); } int cnt = 0; IndexedQualifiedIdentifier IndexedTypeIdentifier::identifier() const { return m_identifier; } void IndexedTypeIdentifier::setIdentifier(KDevelop::IndexedQualifiedIdentifier id) { m_identifier = id; } IndexedQualifiedIdentifier::IndexedQualifiedIdentifier() : index(emptyConstantQualifiedIdentifierPrivateIndex()) { ifDebug( kDebug() << "(" << ++cnt << ")" << identifier().toString() << index; ) if(shouldDoDUChainReferenceCounting(this)) { ifDebug( kDebug() << "increasing"; ) //kDebug() << "(" << ++cnt << ")" << this << identifier().toString() << "inc" << index; QMutexLocker lock(qualifiedidentifierRepository()->mutex()); increase(qualifiedidentifierRepository()->dynamicItemFromIndexSimple(index)->m_refCount, index); } } IndexedQualifiedIdentifier::IndexedQualifiedIdentifier(const QualifiedIdentifier& id) : index(id.index()) { ifDebug( kDebug() << "(" << ++cnt << ")" << identifier().toString() << index; ) if(shouldDoDUChainReferenceCounting(this)) { ifDebug( kDebug() << "increasing"; ) QMutexLocker lock(qualifiedidentifierRepository()->mutex()); increase(qualifiedidentifierRepository()->dynamicItemFromIndexSimple(index)->m_refCount, index); } } IndexedQualifiedIdentifier::IndexedQualifiedIdentifier(const IndexedQualifiedIdentifier& id) : index(id.index) { ifDebug( kDebug() << "(" << ++cnt << ")" << identifier().toString() << index; ) if(shouldDoDUChainReferenceCounting(this)) { ifDebug( kDebug() << "increasing"; ) QMutexLocker lock(qualifiedidentifierRepository()->mutex()); increase(qualifiedidentifierRepository()->dynamicItemFromIndexSimple(index)->m_refCount, index); } } IndexedQualifiedIdentifier& IndexedQualifiedIdentifier::operator=(const QualifiedIdentifier& id) { ifDebug( kDebug() << "(" << ++cnt << ")" << identifier().toString() << index; ) if(shouldDoDUChainReferenceCounting(this)) { QMutexLocker lock(qualifiedidentifierRepository()->mutex()); ifDebug( kDebug() << "decreasing"; ) decrease(qualifiedidentifierRepository()->dynamicItemFromIndexSimple(index)->m_refCount, index); index = id.index(); ifDebug( kDebug() << index << "increasing"; ) increase(qualifiedidentifierRepository()->dynamicItemFromIndexSimple(index)->m_refCount, index); } else { index = id.index(); } return *this; } IndexedQualifiedIdentifier& IndexedQualifiedIdentifier::operator=(const IndexedQualifiedIdentifier& rhs) { ifDebug( kDebug() << "(" << ++cnt << ")" << identifier().toString() << index; ) if(shouldDoDUChainReferenceCounting(this)) { QMutexLocker lock(qualifiedidentifierRepository()->mutex()); ifDebug( kDebug() << "decreasing"; ) decrease(qualifiedidentifierRepository()->dynamicItemFromIndexSimple(index)->m_refCount, index); index = rhs.index; ifDebug( kDebug() << index << "increasing"; ) increase(qualifiedidentifierRepository()->dynamicItemFromIndexSimple(index)->m_refCount, index); } else { index = rhs.index; } return *this; } IndexedQualifiedIdentifier::~IndexedQualifiedIdentifier() { ifDebug( kDebug() << "(" << ++cnt << ")" << identifier().toString() << index; ) if(shouldDoDUChainReferenceCounting(this)) { ifDebug( kDebug() << index << "decreasing"; ) QMutexLocker lock(qualifiedidentifierRepository()->mutex()); decrease(qualifiedidentifierRepository()->dynamicItemFromIndexSimple(index)->m_refCount, index); } } bool IndexedQualifiedIdentifier::operator==(const IndexedQualifiedIdentifier& rhs) const { return index == rhs.index; } bool IndexedQualifiedIdentifier::operator==(const QualifiedIdentifier& id) const { return index == id.index(); } QualifiedIdentifier IndexedQualifiedIdentifier::identifier() const { return QualifiedIdentifier(index); } IndexedQualifiedIdentifier::operator QualifiedIdentifier() const { return QualifiedIdentifier(index); } void initIdentifierRepository() { identifierRepository(); qualifiedidentifierRepository(); } } QDebug operator<<(QDebug s, const KDevelop::Identifier& identifier) { s.nospace() << identifier.toString(); return s.space(); } QDebug operator<<(QDebug s, const KDevelop::QualifiedIdentifier& identifier) { s.nospace() << identifier.toString(); return s.space(); } // kate: space-indent on; indent-width 2; tab-width 4; replace-tabs on; auto-insert-doxygen on diff --git a/language/duchain/indexeddeclaration.h b/language/duchain/indexeddeclaration.h index 6f486ab989..0dc25188ae 100644 --- a/language/duchain/indexeddeclaration.h +++ b/language/duchain/indexeddeclaration.h @@ -1,148 +1,149 @@ /* This file is part of KDevelop Copyright 2007 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 INDEXEDDECLARATION_H #define INDEXEDDECLARATION_H #include "../languageexport.h" #include "indexedtopducontext.h" +#include namespace KDevelop { class Declaration; /** * Represents a declaration only by its global indices */ class KDEVPLATFORMLANGUAGE_EXPORT IndexedDeclaration { public: IndexedDeclaration(Declaration* decl = 0); IndexedDeclaration(uint topContext, uint declarationIndex); /** * \warning Duchain must be read locked */ Declaration* declaration() const; /** * \warning Duchain must be read locked */ Declaration* data() const { return declaration(); } inline bool operator==(const IndexedDeclaration& rhs) const { return m_topContext == rhs.m_topContext && m_declarationIndex == rhs.m_declarationIndex; } inline uint hash() const { if(isDummy()) return 0; - return (m_topContext * 53 + m_declarationIndex) * 23; + return KDevHash() << m_topContext << m_declarationIndex; } ///@warning The duchain needs to be locked when this is called inline bool isValid() const { return !isDummy() && declaration() != 0; } inline bool operator<(const IndexedDeclaration& rhs) const { Q_ASSERT(!isDummy()); return m_topContext < rhs.m_topContext || (m_topContext == rhs.m_topContext && m_declarationIndex < rhs.m_declarationIndex); } /** * \return Index of the Declaration within the top context */ inline uint localIndex() const { if(isDummy()) return 0; else return m_declarationIndex; } inline uint topContextIndex() const { if(isDummy()) return 0; else return m_topContext; } inline IndexedTopDUContext indexedTopContext() const { if(isDummy()) return IndexedTopDUContext(); else return IndexedTopDUContext(m_topContext); } /** * The following functions allow storing 2 integers in this object and marking it as a dummy, * which makes the isValid() function always return false for this object, and use the integers * for other purposes. * * Clears the contained data */ void setIsDummy(bool dummy) { if(isDummy() == dummy) return; if(dummy) m_topContext = 1u << 31u; else m_topContext = 0; m_declarationIndex = 0; } inline bool isDummy() const { //We use the second highest bit to mark dummies, because the highest is used for the sign bit of stored //integers return (bool)(m_topContext & static_cast(1u << 31u)); } inline QPair dummyData() const { Q_ASSERT(isDummy()); return qMakePair(m_topContext & (~(1u<<31u)), m_declarationIndex); } /** * \warning Do not call this when this object is valid. * * The first integer loses one bit of precision. */ void setDummyData(QPair data) { Q_ASSERT(isDummy()); m_topContext = data.first; m_declarationIndex = data.second; Q_ASSERT(!isDummy()); m_topContext |= (1u << 31u); //Mark as dummy Q_ASSERT(isDummy()); Q_ASSERT(dummyData() == data); } private: uint m_topContext; uint m_declarationIndex; }; } Q_DECLARE_METATYPE(KDevelop::IndexedDeclaration) Q_DECLARE_TYPEINFO(KDevelop::IndexedDeclaration, Q_MOVABLE_TYPE); #endif // INDEXEDDECLARATION_H diff --git a/language/duchain/indexedducontext.h b/language/duchain/indexedducontext.h index d972202bcf..2220fd14b8 100644 --- a/language/duchain/indexedducontext.h +++ b/language/duchain/indexedducontext.h @@ -1,127 +1,128 @@ /* This file is part of KDevelop Copyright 2006 Hamish Rodda Copyright 2007-2009 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 INDEXEDDUCONTEXT_H #define INDEXEDDUCONTEXT_H #include "../languageexport.h" +#include #include namespace KDevelop { class DUContext; class IndexedTopDUContext; /** * Represents a context only by its global indices */ class KDEVPLATFORMLANGUAGE_EXPORT IndexedDUContext { public: IndexedDUContext(DUContext* decl); IndexedDUContext(uint topContext = 0, uint contextIndex = 0); ///Duchain must be read locked DUContext* context() const; ///Duchain must be read locked DUContext* data() const { return context(); } bool operator==(const IndexedDUContext& rhs) const { return m_topContext == rhs.m_topContext && m_contextIndex == rhs.m_contextIndex; } uint hash() const { - return (m_topContext * 57 + m_contextIndex) * 29; + return KDevHash() << m_topContext << m_contextIndex; } bool isValid() const { return !isDummy() && context() != 0; } bool operator<(const IndexedDUContext& rhs) const { Q_ASSERT(!isDummy()); return m_topContext < rhs.m_topContext || (m_topContext == rhs.m_topContext && m_contextIndex < rhs.m_contextIndex); } //Index within the top-context uint localIndex() const { if(isDummy()) return 0; return m_contextIndex; } uint topContextIndex() const { return m_topContext; } IndexedTopDUContext indexedTopContext() const; /** * The following functions allow storing 2 integers in this object and marking it as a dummy, * which makes the isValid() function always return false for this object, and use the integers * for other purposes * Clears the contained data */ void setIsDummy(bool dummy) { if(isDummy() == dummy) return; if(dummy) m_topContext = 1 << 31; else m_topContext = 0; m_contextIndex = 0; } bool isDummy() const { //We use the second highest bit to mark dummies, because the highest is used for the sign bit of stored //integers return (bool)(m_topContext & (1 << 31)); } QPair dummyData() const { Q_ASSERT(isDummy()); return qMakePair(m_topContext & (~(1<<31)), m_contextIndex); } ///Do not call this when this object is valid. The first integer loses one bit of precision. void setDummyData(QPair data) { Q_ASSERT(isDummy()); m_topContext = data.first; m_contextIndex = data.second; Q_ASSERT(!isDummy()); m_topContext |= (1 << 31); //Mark as dummy Q_ASSERT(isDummy()); Q_ASSERT(dummyData() == data); } private: uint m_topContext; uint m_contextIndex; }; } Q_DECLARE_TYPEINFO(KDevelop::IndexedDUContext, Q_MOVABLE_TYPE); #endif // INDEXEDDUCONTEXT_H diff --git a/language/duchain/instantiationinformation.cpp b/language/duchain/instantiationinformation.cpp index dbc236da75..11028c59ee 100644 --- a/language/duchain/instantiationinformation.cpp +++ b/language/duchain/instantiationinformation.cpp @@ -1,193 +1,192 @@ /* This file is part of KDevelop Copyright 2007-2009 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. */ #include "./instantiationinformation.h" #include "identifier.h" #include "repositories/itemrepository.h" #include "types/typeutils.h" #include #include "types/typealiastype.h" #include "repositories/typerepository.h" namespace KDevelop { DEFINE_LIST_MEMBER_HASH(InstantiationInformation, templateParameters, IndexedType) QualifiedIdentifier InstantiationInformation::applyToIdentifier(const QualifiedIdentifier& id) const { QualifiedIdentifier ret; if(id.count() > 1) { ret = id; ret.pop(); if(previousInstantiationInformation.index()) ret = previousInstantiationInformation.information().applyToIdentifier(ret); } Identifier lastId(id.last()); KDevVarLengthArray oldTemplateIdentifiers; for(uint a = 0; a < lastId.templateIdentifiersCount(); ++a) oldTemplateIdentifiers.append(lastId.templateIdentifier(a)); lastId.clearTemplateIdentifiers(); for(uint a = 0; a < templateParametersSize(); ++a) { if(templateParameters()[a].abstractType()) { lastId.appendTemplateIdentifier(IndexedTypeIdentifier(templateParameters()[a].abstractType()->toString(), true)); }else{ lastId.appendTemplateIdentifier((uint) oldTemplateIdentifiers.size() > a ? oldTemplateIdentifiers[a] : IndexedTypeIdentifier()); } } for(int a = templateParametersSize(); a < oldTemplateIdentifiers.size(); ++a) lastId.appendTemplateIdentifier(oldTemplateIdentifiers[a]); ret.push(lastId); return ret; } void InstantiationInformation::addTemplateParameter(KDevelop::AbstractType::Ptr type) { templateParametersList().append(type->indexed()); } QString InstantiationInformation::toString(bool local) const { QString ret; if(previousInstantiationInformation.index() && !local) ret = previousInstantiationInformation.information().toString() + "::"; ret += '<'; for(uint a = 0; a < templateParametersSize(); ++a) { if(a) ret += ", "; if(templateParameters()[a].abstractType()) ret += templateParameters()[a].abstractType()->toString(); } ret += '>'; return ret; } InstantiationInformation::InstantiationInformation() : m_refCount(0) { initializeAppendedLists(); } InstantiationInformation::InstantiationInformation(const InstantiationInformation& rhs, bool dynamic) : previousInstantiationInformation(rhs.previousInstantiationInformation), m_refCount(0) { initializeAppendedLists(dynamic); copyListsFrom(rhs); } InstantiationInformation::~InstantiationInformation() { freeAppendedLists(); } InstantiationInformation& InstantiationInformation::operator=(const InstantiationInformation& rhs) { previousInstantiationInformation = rhs.previousInstantiationInformation; copyListsFrom(rhs); return *this; } bool InstantiationInformation::operator==(const InstantiationInformation& rhs) const { if(!(previousInstantiationInformation == rhs.previousInstantiationInformation)) return false; return listsEqual(rhs); } uint InstantiationInformation::hash() const { - uint ret = 0; + KDevHash kdevhash; FOREACH_FUNCTION(const IndexedType& param, templateParameters) { - ret = (ret + param.hash()) * 117; + kdevhash << param.hash(); } - - return (ret + previousInstantiationInformation.index()) * 31; + return kdevhash << previousInstantiationInformation.index(); } AbstractRepositoryManager* returnTypeRepository() { return typeRepositoryManager(); } static KDevelop::RepositoryManager > >& instantiationInformationRepository() { static KDevelop::RepositoryManager > > instantiationInformationRepositoryObject("Instantiation Information Repository", 1, &returnTypeRepository); return instantiationInformationRepositoryObject; } void initInstantiationInformationRepository() { instantiationInformationRepository(); } uint standardInstantiationInformationIndex() { static uint idx = instantiationInformationRepository()->index( InstantiationInformation() ); return idx; } IndexedInstantiationInformation::IndexedInstantiationInformation() : m_index(0) { } IndexedInstantiationInformation::IndexedInstantiationInformation(uint index) : m_index(index) { if(m_index == standardInstantiationInformationIndex()) m_index = 0; if(m_index && shouldDoDUChainReferenceCounting(this)) { QMutexLocker lock(instantiationInformationRepository()->mutex()); increase(instantiationInformationRepository()->dynamicItemFromIndexSimple(m_index)->m_refCount, m_index); } } IndexedInstantiationInformation::IndexedInstantiationInformation(const IndexedInstantiationInformation& rhs) : m_index(rhs.m_index) { if(m_index && shouldDoDUChainReferenceCounting(this)) { QMutexLocker lock(instantiationInformationRepository()->mutex()); increase(instantiationInformationRepository()->dynamicItemFromIndexSimple(m_index)->m_refCount, m_index); } } IndexedInstantiationInformation& IndexedInstantiationInformation::operator=(const IndexedInstantiationInformation& rhs) { if(m_index && shouldDoDUChainReferenceCounting(this)) { QMutexLocker lock(instantiationInformationRepository()->mutex()); decrease(instantiationInformationRepository()->dynamicItemFromIndexSimple(m_index)->m_refCount, m_index); } m_index = rhs.m_index; if(m_index && shouldDoDUChainReferenceCounting(this)) { QMutexLocker lock(instantiationInformationRepository()->mutex()); increase(instantiationInformationRepository()->dynamicItemFromIndexSimple(m_index)->m_refCount, m_index); } return *this; } IndexedInstantiationInformation::~IndexedInstantiationInformation() { if(m_index && shouldDoDUChainReferenceCounting(this)) { QMutexLocker lock(instantiationInformationRepository()->mutex()); decrease(instantiationInformationRepository()->dynamicItemFromIndexSimple(m_index)->m_refCount, m_index); } } bool IndexedInstantiationInformation::isValid() const { return m_index; } const InstantiationInformation& IndexedInstantiationInformation::information() const { return *instantiationInformationRepository()->itemFromIndex(m_index ? m_index : standardInstantiationInformationIndex()); } IndexedInstantiationInformation InstantiationInformation::indexed() const { return IndexedInstantiationInformation(instantiationInformationRepository()->index(*this)); } } diff --git a/language/duchain/referencecounting.cpp b/language/duchain/referencecounting.cpp index a4dece25c7..ab3fc2bccb 100644 --- a/language/duchain/referencecounting.cpp +++ b/language/duchain/referencecounting.cpp @@ -1,264 +1,264 @@ /* * This file is part of KDevelop * * Copyright 2009 David Nolden * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "referencecounting.h" #include #include #include #include #include "repositories/itemrepository.h" #include namespace KDevelop { bool doReferenceCounting = false; //Protects the reference-counting data through a spin-lock SpinLockData refCountingLock; QMap >* refCountingRanges = new QMap >(); //ptr, , leaked intentionally! bool refCountingHasAdditionalRanges = false; //Whether 'refCountingRanges' is non-empty //Speedup: In most cases there is only exactly one reference-counted range active, //so the first reference-counting range can be marked here. void* refCountingFirstRangeStart = 0; QPair refCountingFirstRangeExtent = qMakePair(0u, 0u); } void KDevelop::disableDUChainReferenceCounting(void* start) { SpinLock<> lock(refCountingLock); if(refCountingFirstRangeStart && ((char*)refCountingFirstRangeStart) <= (char*)start && (char*)start < ((char*)refCountingFirstRangeStart) + refCountingFirstRangeExtent.first) { Q_ASSERT(refCountingFirstRangeExtent.second > 0); --refCountingFirstRangeExtent.second; if(refCountingFirstRangeExtent.second == 0) { refCountingFirstRangeExtent = qMakePair(0, 0); refCountingFirstRangeStart = 0; } } else if(refCountingHasAdditionalRanges) { QMap< void*, QPair >::iterator it = refCountingRanges->upperBound(start); if(it != refCountingRanges->begin()) { --it; if(((char*)it.key()) <= (char*)start && (char*)start < ((char*)it.key()) + it.value().first) { //Contained }else{ Q_ASSERT(0); } } Q_ASSERT(it.value().second > 0); --it.value().second; if(it.value().second == 0) refCountingRanges->erase(it); refCountingHasAdditionalRanges = !refCountingRanges->isEmpty(); }else{ Q_ASSERT(0); } if(!refCountingFirstRangeStart && !refCountingHasAdditionalRanges) doReferenceCounting = false; } void KDevelop::enableDUChainReferenceCounting(void* start, unsigned int size) { SpinLock<> lock(refCountingLock); doReferenceCounting = true; if(refCountingFirstRangeStart && ((char*)refCountingFirstRangeStart) <= (char*)start && (char*)start < ((char*)refCountingFirstRangeStart) + refCountingFirstRangeExtent.first) { //Increase the count for the first range ++refCountingFirstRangeExtent.second; }else if(refCountingHasAdditionalRanges || refCountingFirstRangeStart) { //There is additional ranges in the ranges-structure. Add any new ranges there as well. QMap< void*, QPair >::iterator it = refCountingRanges->upperBound(start); if(it != refCountingRanges->begin()) { --it; if(((char*)it.key()) <= (char*)start && (char*)start < ((char*)it.key()) + it.value().first) { //Contained, count up }else{ it = refCountingRanges->end(); //Insert own item } }else if(it != refCountingRanges->end() && it.key() > start) { //The item is behind it = refCountingRanges->end(); } if(it == refCountingRanges->end()) { QMap< void*, QPair >::iterator inserted = refCountingRanges->insert(start, qMakePair(size, 1u)); //Merge following ranges QMap< void*, QPair >::iterator it = inserted; ++it; while(it != refCountingRanges->end() && it.key() < ((char*)start) + size) { inserted.value().second += it.value().second; //Accumulate count if(((char*)start) + size < ((char*)inserted.key()) + it.value().first) { //Update end position inserted.value().first = (((char*)inserted.key()) + it.value().first) - ((char*)start); } it = refCountingRanges->erase(it); } }else{ ++it.value().second; if(it.value().first < size) it.value().first = size; } refCountingHasAdditionalRanges = true; }else{ refCountingFirstRangeStart = start; refCountingFirstRangeExtent.first = size; refCountingFirstRangeExtent.second = 1; } Q_ASSERT(refCountingHasAdditionalRanges == (refCountingRanges && !refCountingRanges->isEmpty())); #ifdef TEST_REFERENCE_COUNTING Q_ASSERT(shouldDoDUChainReferenceCounting(start)); Q_ASSERT(shouldDoDUChainReferenceCounting(((char*)start + (size-1)))); #endif } #ifdef TEST_REFERENCE_COUNTING QAtomicInt& id() { static QAtomicInt& ret(KDevelop::globalItemRepositoryRegistry().getCustomCounter("referencer ids", 1)); return ret; } namespace KDevelop { ReferenceCountManager::ReferenceCountManager() : m_id(id().fetchAndAddRelaxed(1)) { } struct ReferenceCountItem { ///Item entries: ReferenceCountItem(uint id, uint target) : m_id(id), m_targetId(target) { } //Every item has to implement this function, and return a valid hash. //Must be exactly the same hash value as ReferenceCountItemRequest::hash() has returned while creating the item. unsigned int hash() const { - return m_id * 17 + m_targetId * 18921; + return KDevHash() << m_id << m_targetId; } //Every item has to implement this function, and return the complete size this item takes in memory. //Must be exactly the same value as ReferenceCountItemRequest::itemSize() has returned while creating the item. unsigned short int itemSize() const { return sizeof(ReferenceCountItem); } uint m_id; uint m_targetId; ///Request entries: enum { AverageSize = 8 }; void createItem(ReferenceCountItem* item) const { *item = *this; } static void destroy(ReferenceCountItem* /*item*/, AbstractItemRepository&) { } static bool persistent(const ReferenceCountItem*) { return true; } bool equals(const ReferenceCountItem* item) const { return m_id == item->m_id && m_targetId == item->m_targetId; } }; static RepositoryManager< ItemRepository, false>& references() { static RepositoryManager< ItemRepository, false> referencesObject("Reference Count Debugging"); return referencesObject; } static RepositoryManager< ItemRepository, false>& oldReferences() { static RepositoryManager< ItemRepository, false> oldReferencesObject("Old Reference Count Debugging"); return oldReferencesObject; } namespace KDevelop { void initReferenceCounting() { references(); oldReferences(); } } ReferenceCountManager::~ReferenceCountManager() { //Make sure everything is cleaned up when the object is destroyed // Q_ASSERT(!references().contains(m_id)); } ReferenceCountManager::ReferenceCountManager(const ReferenceCountManager& rhs) : m_id(id().fetchAndAddRelaxed(1)) { //New id } ReferenceCountManager& ReferenceCountManager::ReferenceCountManager::operator=(const ReferenceCountManager& rhs) { //Keep id return *this; } // bool ReferenceCountManager::hasReferenceCount() const { // return references->findIndex(ReferenceCountItem); // } void ReferenceCountManager::increase(uint& ref, uint targetId) { Q_ASSERT(shouldDoDUChainReferenceCounting(this)); Q_ASSERT(!references->findIndex(ReferenceCountItem(m_id, targetId))); ++ref; { int oldIndex = oldReferences->findIndex(ReferenceCountItem(m_id, targetId)); if(oldIndex) oldReferences->deleteItem(oldIndex); } Q_ASSERT(references->index(ReferenceCountItem(m_id, targetId))); } void ReferenceCountManager::decrease(uint& ref, uint targetId) { Q_ASSERT(ref > 0); Q_ASSERT(shouldDoDUChainReferenceCounting(this)); Q_ASSERT(!oldReferences->findIndex(ReferenceCountItem(m_id, targetId))); uint refIndex = references->findIndex(ReferenceCountItem(m_id, targetId)); Q_ASSERT(refIndex); --ref; references->deleteItem(refIndex); oldReferences->index(ReferenceCountItem(m_id, targetId)); } } #else namespace KDevelop { void initReferenceCounting() { } } #endif diff --git a/language/duchain/types/abstracttype.cpp b/language/duchain/types/abstracttype.cpp index e7f7d991a8..460c564f99 100644 --- a/language/duchain/types/abstracttype.cpp +++ b/language/duchain/types/abstracttype.cpp @@ -1,173 +1,155 @@ /* 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. */ #include "abstracttype.h" #include "../indexedstring.h" #include "typesystemdata.h" #include "typeregister.h" #include "typesystem.h" #include "../repositories/typerepository.h" namespace KDevelop { //REGISTER_TYPE(AbstractType); void AbstractType::makeDynamic() { if(d_ptr->m_dynamic) return; AbstractType::Ptr newType(clone()); //While cloning, all the data is cloned as well. So we use that mechanism and steal the cloned data. Q_ASSERT(newType->equals(this)); AbstractTypeData* oldData = d_ptr; d_ptr = newType->d_ptr; newType->d_ptr = oldData; Q_ASSERT(d_ptr->m_dynamic); } AbstractType::AbstractType( AbstractTypeData& dd ) : d_ptr(&dd) { } quint64 AbstractType::modifiers() const { return d_func()->m_modifiers; } void AbstractType::setModifiers(quint64 modifiers) { d_func_dynamic()->m_modifiers = modifiers; } AbstractType::AbstractType() : d_ptr(&createData()) { } AbstractType::~AbstractType() { if(!d_ptr->inRepository) { TypeSystem::self().callDestructor(d_ptr); delete[] (char*)d_ptr; } } void AbstractType::accept(TypeVisitor *v) const { if (v->preVisit (this)) this->accept0 (v); v->postVisit (this); } void AbstractType::acceptType(AbstractType::Ptr type, TypeVisitor *v) { if (! type) return; type->accept (v); } AbstractType::WhichType AbstractType::whichType() const { return TypeAbstract; } void AbstractType::exchangeTypes( TypeExchanger* /*exchanger */) { } IndexedType AbstractType::indexed() const { if(this == 0) return IndexedType(); else { return IndexedType(TypeRepository::indexForType(AbstractType::Ptr(const_cast(this)))); } } bool AbstractType::equals(const AbstractType* rhs) const { //kDebug() << this << rhs << modifiers() << rhs->modifiers(); return d_func()->typeClassId == rhs->d_func()->typeClassId && modifiers() == rhs->modifiers(); } uint AbstractType::hash() const { - // TODO include other items in the hash - - uint hash = d_func()->typeClassId; - hash = hash * 301 + hash / 3; - - uint mod = d_func()->m_modifiers; - - if (mod & ShortModifier) - hash += 0x1; - if (mod & LongModifier) - hash += 0x2; - if (mod & LongLongModifier) - hash += 0x4; - if (mod & SignedModifier) - hash += 0x8; - if (mod & UnsignedModifier) - hash += 0x10; - - return (mod & ConstModifier ? 7 : 0) + (mod & VolatileModifier ? 3 : 0) + 83 * hash; + return KDevHash() << d_func()->typeClassId << d_func()->m_modifiers; } QString AbstractType::toString() const { return toString(false); } QString AbstractType::toString(bool spaceOnLeft) const { // TODO complete if(!spaceOnLeft) { if(modifiers() & ConstModifier) { if(modifiers() & VolatileModifier) { return "const volatile "; }else{ return "const "; } }else{ if(modifiers() & VolatileModifier) return "volatile "; else return QString(); } }else{ if(modifiers() & ConstModifier) { if(modifiers() & VolatileModifier) { return " const volatile"; }else{ return " const"; } }else{ if(modifiers() & VolatileModifier) return " volatile"; else return QString(); } } } } // kate: space-indent on; indent-width 2; tab-width 4; replace-tabs on; auto-insert-doxygen on diff --git a/language/duchain/types/arraytype.cpp b/language/duchain/types/arraytype.cpp index 673f691355..5085ea937c 100644 --- a/language/duchain/types/arraytype.cpp +++ b/language/duchain/types/arraytype.cpp @@ -1,125 +1,126 @@ /* 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. */ #include "arraytype.h" #include "../indexedstring.h" #include "../repositories/typerepository.h" #include "typesystemdata.h" #include "typeregister.h" #include "typesystem.h" namespace KDevelop { REGISTER_TYPE(ArrayType); ArrayType::ArrayType(const ArrayType& rhs) : AbstractType(copyData(*rhs.d_func())) { } ArrayType::ArrayType(ArrayTypeData& data) : AbstractType(data) { } AbstractType* ArrayType::clone() const { return new ArrayType(*this); } bool ArrayType::equals(const AbstractType* _rhs) const { if (!AbstractType::equals(_rhs)) return false; Q_ASSERT(fastCast(_rhs)); const ArrayType* rhs = static_cast(_rhs); TYPE_D(ArrayType); if( d->m_dimension != rhs->d_func()->m_dimension ) return false; return d->m_elementType == rhs->d_func()->m_elementType; } ArrayType::ArrayType() : AbstractType(createData()) { } ArrayType::~ArrayType() { } int ArrayType::dimension () const { return d_func()->m_dimension; } void ArrayType::setDimension(int dimension) { d_func_dynamic()->m_dimension = dimension; } AbstractType::Ptr ArrayType::elementType () const { return d_func()->m_elementType.abstractType(); } void ArrayType::setElementType(AbstractType::Ptr type) { d_func_dynamic()->m_elementType = type->indexed(); } QString ArrayType::toString() const { if (d_func()->m_dimension == 0) { return QString("%1[]").arg(elementType() ? elementType()->toString() : QString("")); } return QString("%1[%2]").arg(elementType() ? elementType()->toString() : QString("")).arg(d_func()->m_dimension); } void ArrayType::accept0 (TypeVisitor *v) const { if (v->visit (this)) { acceptType (d_func()->m_elementType.abstractType(), v); } v->endVisit (this); } void ArrayType::exchangeTypes( TypeExchanger* exchanger ) { TYPE_D_DYNAMIC(ArrayType); d->m_elementType = exchanger->exchange( d->m_elementType.abstractType() )->indexed(); } AbstractType::WhichType ArrayType::whichType() const { return TypeArray; } uint ArrayType::hash() const { - return AbstractType::hash() + (elementType() ? elementType()->hash() : 0) * 47 + 117* dimension(); + return KDevHash(AbstractType::hash()) + << (elementType() ? elementType()->hash() : 0) << dimension(); } } // kate: space-indent on; indent-width 2; tab-width 4; replace-tabs on; auto-insert-doxygen on diff --git a/language/duchain/types/constantintegraltype.cpp b/language/duchain/types/constantintegraltype.cpp index 4cb8a36977..ecb104141a 100644 --- a/language/duchain/types/constantintegraltype.cpp +++ b/language/duchain/types/constantintegraltype.cpp @@ -1,161 +1,159 @@ /* 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. */ #include "constantintegraltype.h" #include "typesystemdata.h" #include "typeregister.h" namespace KDevelop { REGISTER_TYPE(ConstantIntegralType); ConstantIntegralType::ConstantIntegralType(const ConstantIntegralType& rhs) : IntegralType(copyData(*rhs.d_func())) { } ConstantIntegralType::ConstantIntegralType(ConstantIntegralTypeData& data) : IntegralType(data) { } ConstantIntegralType::ConstantIntegralType(uint type) : IntegralType(createData()) { setDataType(type); setModifiers(ConstModifier); } qint64 ConstantIntegralType::plainValue() const { return d_func()->m_value; } AbstractType* ConstantIntegralType::clone() const { return new ConstantIntegralType(*this); } bool ConstantIntegralType::equals(const AbstractType* _rhs) const { if( this == _rhs ) return true; if (!IntegralType::equals(_rhs)) return false; Q_ASSERT(fastCast(_rhs)); const ConstantIntegralType* rhs = static_cast(_rhs); return d_func()->m_value == rhs->d_func()->m_value; } QString ConstantIntegralType::toString() const { QString ret; switch(dataType()) { case TypeNone: ret += "none"; break; case TypeChar: ret += QString("%1").arg((char)d_func()->m_value); break; case TypeWchar_t: ret += QString("%1").arg((wchar_t)d_func()->m_value); break; case TypeChar16_t: ///TODO: cast to char16_t once we can depend on c++0x ret += QString("%1").arg((char)d_func()->m_value); break; case TypeChar32_t: ///TODO: cast to char32_t once we can depend on c++0x ret += QString("%1").arg((char)d_func()->m_value); break; case TypeBoolean: ret += d_func()->m_value ? "true" : "false"; break; case TypeInt: ret += (modifiers() & UnsignedModifier) ? QString("%1u").arg((uint)d_func()->m_value) : QString("%1").arg((int)d_func()->m_value); break; case TypeFloat: ret += QString("%1").arg( value() ); break; case TypeDouble: ret += QString("%1").arg( value() ); break; case TypeVoid: ret += "void"; break; default: ret += ""; break; } return ret; } uint ConstantIntegralType::hash() const { - uint ret = IntegralType::hash(); - ret += 47 * (uint)d_func()->m_value; - return ret; + return KDevHash(IntegralType::hash()) << d_func()->m_value; } template<> KDEVPLATFORMLANGUAGE_EXPORT void ConstantIntegralType::setValueInternal(qint64 value) { if((modifiers() & UnsignedModifier)) { kDebug() << "setValue(signed) called on unsigned type"; } d_func_dynamic()->m_value = value; } template<> KDEVPLATFORMLANGUAGE_EXPORT void ConstantIntegralType::setValueInternal(quint64 value) { if(!(modifiers() & UnsignedModifier)) { kDebug() << "setValue(unsigned) called on not unsigned type"; } d_func_dynamic()->m_value = (qint64)value; } template<> KDEVPLATFORMLANGUAGE_EXPORT void ConstantIntegralType::setValueInternal(float value) { if(dataType() != TypeFloat) { kDebug() << "setValue(float) called on non-float type"; } memcpy(&d_func_dynamic()->m_value, &value, sizeof(float)); } template<> KDEVPLATFORMLANGUAGE_EXPORT void ConstantIntegralType::setValueInternal(double value) { if(dataType() != TypeDouble) { kDebug() << "setValue(double) called on non-double type"; } memcpy(&d_func_dynamic()->m_value, &value, sizeof(double)); } } diff --git a/language/duchain/types/delayedtype.cpp b/language/duchain/types/delayedtype.cpp index 5506a45f87..6ba6f4ec73 100644 --- a/language/duchain/types/delayedtype.cpp +++ b/language/duchain/types/delayedtype.cpp @@ -1,108 +1,108 @@ /* 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. */ #include "delayedtype.h" #include "../indexedstring.h" #include "../repositories/typerepository.h" #include "typesystemdata.h" #include "typeregister.h" #include "typesystem.h" namespace KDevelop { REGISTER_TYPE(DelayedType); DelayedType::DelayedType(DelayedTypeData& data) : AbstractType(data) { } AbstractType* DelayedType::clone() const { return new DelayedType(*this); } bool DelayedType::equals(const AbstractType* _rhs) const { if( this == _rhs ) return true; if (!AbstractType::equals(_rhs)) return false; Q_ASSERT(fastCast(_rhs)); const DelayedType* rhs = static_cast(_rhs); return d_func()->m_identifier == rhs->d_func()->m_identifier && rhs->d_func()->m_kind == d_func()->m_kind; } AbstractType::WhichType DelayedType::whichType() const { return AbstractType::TypeDelayed; } QString DelayedType::toString() const { return AbstractType::toString(false) + identifier().toString(); } DelayedType::Kind DelayedType::kind() const { return d_func()->m_kind; } void DelayedType::setKind(Kind kind) { d_func_dynamic()->m_kind = kind; } DelayedType::DelayedType() : AbstractType(createData()) { } DelayedType::DelayedType(const DelayedType& rhs) : AbstractType(copyData(*rhs.d_func())) { } DelayedType::~DelayedType() { } void DelayedType::setIdentifier(const IndexedTypeIdentifier& identifier) { d_func_dynamic()->m_identifier = identifier; } IndexedTypeIdentifier DelayedType::identifier() const { return d_func()->m_identifier; } void DelayedType::accept0 (KDevelop::TypeVisitor *v) const { v->visit(this); /* v->endVisit(this);*/ } uint DelayedType::hash() const { - return AbstractType::hash() + 37*((d_func()->m_identifier.hash()>>1) + (uint)d_func()->m_kind); + return KDevHash(AbstractType::hash()) << d_func()->m_identifier.hash() << d_func()->m_kind; } } // kate: space-indent on; indent-width 2; tab-width 4; replace-tabs on; auto-insert-doxygen on diff --git a/language/duchain/types/enumerationtype.cpp b/language/duchain/types/enumerationtype.cpp index 4901136924..d87b05700e 100644 --- a/language/duchain/types/enumerationtype.cpp +++ b/language/duchain/types/enumerationtype.cpp @@ -1,82 +1,82 @@ /* 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. */ #include "enumerationtype.h" #include "typesystemdata.h" #include "typeregister.h" namespace KDevelop { //Because all these classes have no d-pointers, shallow copies are perfectly fine REGISTER_TYPE(EnumerationType); EnumerationType::EnumerationType(const EnumerationType& rhs) : EnumerationTypeBase(copyData(*rhs.d_func())) { } EnumerationType::EnumerationType(EnumerationTypeData& data) : EnumerationTypeBase(data) { } AbstractType* EnumerationType::clone() const { return new EnumerationType(*this); } bool EnumerationType::equals(const AbstractType* _rhs) const { if( this == _rhs ) return true; if (!EnumerationTypeBase::equals(_rhs)) return false; Q_ASSERT(fastCast(_rhs)); // Nothing enumeration type-specific to compare return true; } EnumerationType::EnumerationType() : EnumerationTypeBase(createData()) { IntegralType::setDataType(TypeInt); } QString EnumerationType::toString() const { return qualifiedIdentifier().toString(); } uint EnumerationType::hash() const { - return IdentifiedType::hash() + 57*IntegralType::hash(); + return KDevHash(IntegralType::hash()) << IdentifiedType::hash(); } AbstractType::WhichType EnumerationType::whichType() const { return TypeEnumeration; } } diff --git a/language/duchain/types/enumeratortype.cpp b/language/duchain/types/enumeratortype.cpp index a3d3ab63c8..6bfe33b265 100644 --- a/language/duchain/types/enumeratortype.cpp +++ b/language/duchain/types/enumeratortype.cpp @@ -1,82 +1,82 @@ /* 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. */ #include "enumeratortype.h" #include "typesystemdata.h" #include "typeregister.h" namespace KDevelop { REGISTER_TYPE(EnumeratorType); EnumeratorType::EnumeratorType(const EnumeratorType& rhs) : EnumeratorTypeBase(copyData(*rhs.d_func())) { } EnumeratorType::EnumeratorType(EnumeratorTypeData& data) : EnumeratorTypeBase(data) { } EnumeratorType::EnumeratorType() : EnumeratorTypeBase(createData()) { IntegralType::setDataType(TypeInt); setModifiers(ConstModifier); } AbstractType* EnumeratorType::clone() const { return new EnumeratorType(*this); } bool EnumeratorType::equals(const AbstractType* _rhs) const { if( this == _rhs ) return true; if (!EnumeratorTypeBase::equals(_rhs)) return false; Q_ASSERT(fastCast(_rhs)); // Nothing Enumerator-type specific to compare return true; } uint EnumeratorType::hash() const { - return 27*(IdentifiedType::hash() + 13*ConstantIntegralType::hash()); + return KDevHash(ConstantIntegralType::hash()) << IdentifiedType::hash(); } AbstractType::WhichType EnumeratorType::whichType() const { return TypeEnumerator; } QString EnumeratorType::toString() const { return IdentifiedType::qualifiedIdentifier().toString(); } } diff --git a/language/duchain/types/functiontype.cpp b/language/duchain/types/functiontype.cpp index bc6b842172..0cb953c250 100644 --- a/language/duchain/types/functiontype.cpp +++ b/language/duchain/types/functiontype.cpp @@ -1,200 +1,200 @@ /* 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. */ #include "functiontype.h" #include "../indexedstring.h" #include "../repositories/typerepository.h" #include "typesystemdata.h" #include "typeregister.h" #include "typesystem.h" namespace KDevelop { REGISTER_TYPE(FunctionType); DEFINE_LIST_MEMBER_HASH(FunctionTypeData, m_arguments, IndexedType) FunctionType::FunctionType(const FunctionType& rhs) : AbstractType(copyData(*rhs.d_func())) { } FunctionType::FunctionType(FunctionTypeData& data) : AbstractType(data) { } AbstractType* FunctionType::clone() const { return new FunctionType(*this); } bool FunctionType::equals(const AbstractType* _rhs) const { if( this == _rhs ) return true; if (!AbstractType::equals(_rhs)) return false; Q_ASSERT(fastCast(_rhs)); const FunctionType* rhs = static_cast(_rhs); TYPE_D(FunctionType); if( d->m_argumentsSize() != rhs->d_func()->m_argumentsSize() ) return false; if( (bool)rhs->d_func()->m_returnType != (bool)d->m_returnType ) return false; if( d->m_returnType != rhs->d_func()->m_returnType ) return false; for(unsigned int a = 0; a < d->m_argumentsSize(); ++a) if(d->m_arguments()[a] != rhs->d_func()->m_arguments()[a]) return false; return true; } FunctionType::FunctionType() : AbstractType(createData()) { } FunctionType::~FunctionType() { } void FunctionType::addArgument(AbstractType::Ptr argument, int index) { if ( index == -1 ) d_func_dynamic()->m_argumentsList().append(argument->indexed()); else d_func_dynamic()->m_argumentsList().insert(index, argument->indexed()); } void FunctionType::removeArgument(int i) { d_func_dynamic()->m_argumentsList().remove(i); } void FunctionType::setReturnType(AbstractType::Ptr returnType) { d_func_dynamic()->m_returnType = returnType->indexed(); } AbstractType::Ptr FunctionType::returnType () const { return d_func()->m_returnType.abstractType(); } QList FunctionType::arguments () const { ///@todo Don't do the conversion QList ret; FOREACH_FUNCTION(const IndexedType& arg, d_func()->m_arguments) ret << arg.abstractType(); return ret; } const IndexedType* FunctionType::indexedArguments() const { return d_func()->m_arguments(); } uint FunctionType::indexedArgumentsSize() const { return d_func()->m_argumentsSize(); } void FunctionType::accept0 (TypeVisitor *v) const { TYPE_D(FunctionType); if (v->visit (this)) { acceptType (d->m_returnType.abstractType(), v); for (unsigned int i = 0; i < d->m_argumentsSize (); ++i) acceptType (d->m_arguments()[i].abstractType(), v); } v->endVisit (this); } void FunctionType::exchangeTypes( TypeExchanger* exchanger ) { TYPE_D_DYNAMIC(FunctionType); for (uint i = 0; i < d->m_argumentsSize (); ++i) d->m_argumentsList()[i] = exchanger->exchange( d->m_arguments()[i].abstractType() )->indexed(); d->m_returnType = exchanger->exchange(d->m_returnType.abstractType())->indexed(); } QString FunctionType::partToString( SignaturePart sigPart ) const { QString args; TYPE_D(FunctionType); if( sigPart == SignatureArguments || sigPart == SignatureWhole ) { args += '('; bool first = true; FOREACH_FUNCTION(const IndexedType& type, d->m_arguments) { if (first) first = false; else args.append(", "); args.append(type ? type.abstractType()->toString() : QString("")); } args += ')'; } if( sigPart == SignatureArguments ) return args; else if( sigPart == SignatureWhole ) return QString("function %1 %2").arg(returnType() ? returnType()->toString() : QString("")).arg(args); else if( sigPart == SignatureReturn ) return returnType() ? returnType()->toString() : QString(); return QString("ERROR"); } QString FunctionType::toString() const { return partToString(SignatureWhole) + AbstractType::toString(true); } AbstractType::WhichType FunctionType::whichType() const { return TypeFunction; } uint FunctionType::hash() const { - uint hash_value = AbstractType::hash(); - hash_value += d_func()->m_returnType.hash() * 859321; + KDevHash kdevhash(AbstractType::hash()); + kdevhash << d_func()->m_returnType.hash(); FOREACH_FUNCTION(const IndexedType& t, d_func()->m_arguments) { - hash_value = (hash_value << 5) - hash_value + t.hash(); + kdevhash << t.hash(); } - return hash_value; + return kdevhash; } } // kate: space-indent on; indent-width 2; tab-width 4; replace-tabs on; auto-insert-doxygen on diff --git a/language/duchain/types/integraltype.cpp b/language/duchain/types/integraltype.cpp index f40f05b48a..a55110d6ca 100644 --- a/language/duchain/types/integraltype.cpp +++ b/language/duchain/types/integraltype.cpp @@ -1,162 +1,162 @@ /* 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. */ #include "integraltype.h" #include "../indexedstring.h" #include "typesystemdata.h" #include "typeregister.h" #include "typesystem.h" namespace KDevelop { REGISTER_TYPE(IntegralType); IntegralType::IntegralType(const IntegralType& rhs) : AbstractType(copyData(*rhs.d_func())) { } IntegralType::IntegralType(IntegralTypeData& data) : AbstractType(data) { } uint IntegralType::dataType() const { return d_func()->m_dataType; } void IntegralType::setDataType(uint dataType) { d_func_dynamic()->m_dataType = dataType; } AbstractType* IntegralType::clone() const { return new IntegralType(*this); } bool IntegralType::equals(const AbstractType* _rhs) const { if( this == _rhs ) return true; if (!AbstractType::equals(_rhs)) return false; Q_ASSERT(fastCast(_rhs)); const IntegralType* rhs = static_cast(_rhs); return d_func()->m_dataType == rhs->d_func()->m_dataType; } IntegralType::IntegralType(uint type) : AbstractType(createData()) { d_func_dynamic()->setTypeClassId(); setDataType(type); } IntegralType::~IntegralType() { } QString IntegralType::toString() const { TYPE_D(IntegralType); QString name; switch (d->m_dataType) { case TypeChar: name = "char"; break; case TypeChar16_t: name = "char16_t"; break; case TypeChar32_t: name = "char32_t"; break; case TypeWchar_t: name = "wchar_t"; break; case TypeBoolean: name = "bool"; break; case TypeInt: name = "int"; break; case TypeFloat: name = "float"; break; case TypeDouble: name = "double"; break; case TypeVoid: name = "void"; break; case TypeMixed: name = "mixed"; break; case TypeString: name = "string"; break; case TypeArray: name = "array"; break; case TypeNull: name = "null"; break; default: name = ""; break; } if (modifiers() & UnsignedModifier) name.prepend("unsigned "); else if (modifiers() & SignedModifier) name.prepend("signed "); if (modifiers() & ShortModifier) name.prepend("short "); else if (modifiers() & LongLongModifier) name.prepend("long long "); else if (modifiers() & LongModifier) name.prepend("long "); return AbstractType::toString() + name; } void IntegralType::accept0(TypeVisitor *v) const { v->visit (this); } AbstractType::WhichType IntegralType::whichType() const { return TypeIntegral; } uint IntegralType::hash() const { - return AbstractType::hash() + d_func()->m_dataType * 11; + return KDevHash(AbstractType::hash()) << d_func()->m_dataType; } } // kate: space-indent on; indent-width 2; tab-width 4; replace-tabs on; auto-insert-doxygen on diff --git a/language/duchain/types/pointertype.cpp b/language/duchain/types/pointertype.cpp index fbb214309b..4bf657dd44 100644 --- a/language/duchain/types/pointertype.cpp +++ b/language/duchain/types/pointertype.cpp @@ -1,108 +1,108 @@ /* 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. */ #include "pointertype.h" #include "../indexedstring.h" #include "../repositories/typerepository.h" #include "typesystemdata.h" #include "typeregister.h" #include "typesystem.h" namespace KDevelop { REGISTER_TYPE(PointerType); PointerType::PointerType(const PointerType& rhs) : AbstractType(copyData(*rhs.d_func())) { } PointerType::PointerType(PointerTypeData& data) : AbstractType(data) { } AbstractType* PointerType::clone() const { return new PointerType(*this); } bool PointerType::equals(const AbstractType* _rhs) const { if( this == _rhs ) return true; if (!AbstractType::equals(_rhs)) return false; Q_ASSERT(fastCast(_rhs)); const PointerType* rhs = static_cast(_rhs); return d_func()->m_baseType == rhs->d_func()->m_baseType; } PointerType::PointerType() : AbstractType(createData()) { } void PointerType::accept0 (TypeVisitor *v) const { if (v->visit (this)) acceptType (d_func()->m_baseType.abstractType(), v); v->endVisit (this); } void PointerType::exchangeTypes( TypeExchanger* exchanger ) { d_func_dynamic()->m_baseType = exchanger->exchange( d_func()->m_baseType.abstractType() )->indexed(); } PointerType::~PointerType() { } AbstractType::Ptr PointerType::baseType () const { return d_func()->m_baseType.abstractType(); } void PointerType::setBaseType(AbstractType::Ptr type) { d_func_dynamic()->m_baseType = type->indexed(); } QString PointerType::toString() const { QString baseString = (baseType() ? baseType()->toString() : ""); return QString("%1*").arg(baseString) + AbstractType::toString(true); } AbstractType::WhichType PointerType::whichType() const { return TypePointer; } uint PointerType::hash() const { - return AbstractType::hash() + d_func()->m_baseType.hash() * 13; + return KDevHash(AbstractType::hash()) << d_func()->m_baseType.hash(); } } // kate: space-indent on; indent-width 2; tab-width 4; replace-tabs on; auto-insert-doxygen on diff --git a/language/duchain/types/referencetype.cpp b/language/duchain/types/referencetype.cpp index 8919f7f126..7a1aa7d5cc 100644 --- a/language/duchain/types/referencetype.cpp +++ b/language/duchain/types/referencetype.cpp @@ -1,125 +1,125 @@ /* 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. */ #include "referencetype.h" #include "../indexedstring.h" #include "../repositories/typerepository.h" #include "typesystemdata.h" #include "typeregister.h" #include "typesystem.h" #include "integraltype.h" #include "structuretype.h" namespace KDevelop { REGISTER_TYPE(ReferenceType); ReferenceType::ReferenceType(const ReferenceType& rhs) : AbstractType(copyData(*rhs.d_func())) { } ReferenceType::ReferenceType(ReferenceTypeData& data) : AbstractType(data) { } AbstractType* ReferenceType::clone() const { return new ReferenceType(*this); } bool ReferenceType::equals(const AbstractType* _rhs) const { if( this == _rhs ) return true; if (!AbstractType::equals(_rhs)) return false; Q_ASSERT(fastCast(_rhs)); const ReferenceType* rhs = static_cast(_rhs); return d_func()->m_baseType == rhs->d_func()->m_baseType; } ReferenceType::ReferenceType() : AbstractType(createData()) { } ReferenceType::~ReferenceType() { } AbstractType::Ptr ReferenceType::baseType () const { return d_func()->m_baseType.abstractType(); } void ReferenceType::setBaseType(AbstractType::Ptr type) { d_func_dynamic()->m_baseType = type->indexed(); } bool ReferenceType::isRValue() const { return d_func()->m_isRValue; } void ReferenceType::setIsRValue(bool isRValue) { d_func_dynamic()->m_isRValue = isRValue; } void ReferenceType::accept0 (TypeVisitor *v) const { if (v->visit (this)) acceptType (d_func()->m_baseType.abstractType(), v); v->endVisit (this); } void ReferenceType::exchangeTypes( TypeExchanger* exchanger ) { d_func_dynamic()->m_baseType = exchanger->exchange( d_func()->m_baseType.abstractType() )->indexed(); } QString ReferenceType::toString() const { AbstractType::Ptr base = baseType(); QString baseString = (base ? base->toString() : ""); const QString ampersands = d_func()->m_isRValue ? "&&" : "&"; if(base.cast() || base.cast()) return AbstractType::toString(false) + baseString + ampersands; else return baseString + AbstractType::toString(true) + ampersands; } AbstractType::WhichType ReferenceType::whichType() const { return TypeReference; } uint ReferenceType::hash() const { - return AbstractType::hash() + (d_func()->m_baseType.hash()+1) * 29 + (d_func()->m_isRValue ? 43768 : 0); + return KDevHash(AbstractType::hash()) << d_func()->m_baseType.hash() << d_func()->m_isRValue; } } // kate: space-indent on; indent-width 2; tab-width 4; replace-tabs on; auto-insert-doxygen on diff --git a/language/duchain/types/structuretype.cpp b/language/duchain/types/structuretype.cpp index 27b00889c4..a9cdfbf0c0 100644 --- a/language/duchain/types/structuretype.cpp +++ b/language/duchain/types/structuretype.cpp @@ -1,104 +1,104 @@ /* This file is part of KDevelop Copyright 2006 Roberto Raggi Copyright 2006 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. */ #include "structuretype.h" #include "../indexedstring.h" #include "../repositories/typerepository.h" #include "typesystemdata.h" #include "typeregister.h" #include "typesystem.h" namespace KDevelop { REGISTER_TYPE(StructureType); StructureType::StructureType(const StructureType& rhs) : StructureTypeBase(copyData(*rhs.d_func())) { } StructureType::StructureType(StructureTypeData& data) : StructureTypeBase(data) { } AbstractType* StructureType::clone() const { return new StructureType(*this); } bool StructureType::equals(const AbstractType* _rhs) const { if( this == _rhs ) return true; if (!StructureTypeBase::equals(_rhs)) return false; // Q_ASSERT(fastCast(_rhs)); // const StructureType* rhs = static_cast(_rhs); return true; } StructureType::StructureType() : StructureTypeBase(createData()) { } StructureType::~StructureType() { } void StructureType::accept0 (TypeVisitor *v) const { // TYPE_D(StructureType); v->visit (this); v->endVisit (this); } QString StructureType::toString() const { QualifiedIdentifier id = qualifiedIdentifier(); if (!id.isEmpty()) { return AbstractType::toString() + id.toString(); } QString type = "class"; return QString("<%1>").arg(type) + AbstractType::toString(true); } AbstractType::WhichType StructureType::whichType() const { return TypeStructure; } uint StructureType::hash() const { - return 19 * (AbstractType::hash() + IdentifiedType::hash() + 101); + return KDevHash(AbstractType::hash()) << IdentifiedType::hash(); } } // kate: space-indent on; indent-width 2; tab-width 4; replace-tabs on; auto-insert-doxygen on diff --git a/language/duchain/types/typealiastype.cpp b/language/duchain/types/typealiastype.cpp index 903e2e1cdf..8f3c3e754f 100644 --- a/language/duchain/types/typealiastype.cpp +++ b/language/duchain/types/typealiastype.cpp @@ -1,98 +1,98 @@ /* Copyright 2009 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. */ #include "typealiastype.h" #include "typeregister.h" #include "typesystem.h" namespace KDevelop { REGISTER_TYPE(TypeAliasType); AbstractType* TypeAliasType::clone() const { return new TypeAliasType(*this); } bool TypeAliasType::equals(const AbstractType* _rhs) const { if( !fastCast(_rhs)) return false; const TypeAliasType* rhs = static_cast(_rhs); if( this == rhs ) return true; if( AbstractType::equals(rhs) && IdentifiedType::equals(rhs) ) { if( (bool)d_func()->m_type != (bool)rhs->d_func()->m_type ) return false; if( !d_func()->m_type ) return true; return d_func()->m_type == rhs->d_func()->m_type; } else { return false; } } AbstractType::Ptr TypeAliasType::type() const { return d_func()->m_type.abstractType(); } void TypeAliasType::setType(AbstractType::Ptr type) { d_func_dynamic()->m_type = type->indexed(); } uint TypeAliasType::hash() const { - return 31 * IdentifiedType::hash() + (type() ? type()->hash() + 83 : 0); + return KDevHash(AbstractType::hash()) << IdentifiedType::hash() << (type() ? type()->hash() : 0); } QString TypeAliasType::toString() const { QualifiedIdentifier id = qualifiedIdentifier(); if (!id.isEmpty()) return AbstractType::toString(false) + id.toString(); if (type()) return AbstractType::toString(false) + type()->toString(); return "typedef "; } void TypeAliasType::accept0 (KDevelop::TypeVisitor *v) const { if (v->visit (this)) acceptType (d_func()->m_type.abstractType(), v); // v->endVisit (this); } KDevelop::AbstractType::WhichType TypeAliasType::whichType() const { return TypeAlias; } void TypeAliasType::exchangeTypes(KDevelop::TypeExchanger* exchanger) { d_func_dynamic()->m_type = exchanger->exchange( d_func()->m_type.abstractType() )->indexed(); } } diff --git a/language/duchain/types/unsuretype.cpp b/language/duchain/types/unsuretype.cpp index cba3984102..707df286c4 100644 --- a/language/duchain/types/unsuretype.cpp +++ b/language/duchain/types/unsuretype.cpp @@ -1,124 +1,123 @@ /* Copyright 2009 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. */ #include "unsuretype.h" #include "typeregister.h" #include "typesystem.h" namespace KDevelop { REGISTER_TYPE(UnsureType); DEFINE_LIST_MEMBER_HASH(UnsureTypeData, m_types, IndexedType) UnsureType::UnsureType(const KDevelop::UnsureType& rhs): AbstractType(copyData(*rhs.d_func())) { } UnsureType::UnsureType() : AbstractType(createData()) { } void UnsureType::accept0(KDevelop::TypeVisitor* v) const { FOREACH_FUNCTION(const IndexedType& type, d_func()->m_types) { AbstractType::Ptr t = type.abstractType(); v->visit(t.unsafeData()); } } KDevelop::AbstractType* UnsureType::clone() const { return new UnsureType(*this); } QString UnsureType::toString() const { QString ret = "unsure ("; bool first = true; FOREACH_FUNCTION(const IndexedType& type, d_func()->m_types) { if(!first) ret += ", "; first = false; AbstractType::Ptr t = type.abstractType(); if(t) ret += t->toString(); else ret += "none"; } ret += ')'; return ret; } bool UnsureType::equals(const KDevelop::AbstractType* rhs) const { const UnsureType* rhsU = dynamic_cast(rhs); if(!rhsU) return false; if(d_func()->typeClassId != rhsU->d_func()->typeClassId) return false; if(d_func()->m_typesSize() != rhsU->d_func()->m_typesSize()) return false; for(uint a = 0; a < d_func()->m_typesSize(); ++a) if(d_func()->m_types()[a] != rhsU->d_func()->m_types()[a]) return false; return KDevelop::AbstractType::equals(rhs); } uint UnsureType::hash() const { - uint ret = AbstractType::hash(); + KDevHash kdevhash(AbstractType::hash()); FOREACH_FUNCTION(const IndexedType& type, d_func()->m_types) - ret = 17 * ret + type.hash(); - - return ret; + kdevhash << type.hash(); + return kdevhash << d_func()->m_typesSize(); } KDevelop::AbstractType::WhichType UnsureType::whichType() const { return TypeUnsure; } void UnsureType::exchangeTypes(KDevelop::TypeExchanger* exchanger) { for(uint a = 0; a < d_func()->m_typesSize(); ++a) { AbstractType::Ptr from = d_func()->m_types()[a].abstractType(); AbstractType::Ptr exchanged = exchanger->exchange(from); if(exchanged != from) d_func_dynamic()->m_typesList()[a] = exchanged->indexed(); } KDevelop::AbstractType::exchangeTypes(exchanger); } void UnsureType::addType(KDevelop::IndexedType type) { if ( !d_func_dynamic()->m_typesList().contains(type) ) { d_func_dynamic()->m_typesList().append(type); } } void UnsureType::removeType(KDevelop::IndexedType type) { d_func_dynamic()->m_typesList().removeOne(type); } const KDevelop::IndexedType* UnsureType::types() const { return d_func()->m_types(); } uint UnsureType::typesSize() const { return d_func()->m_typesSize(); } UnsureType::UnsureType(KDevelop::UnsureTypeData& data): AbstractType(data) { } }