diff --git a/language/duchain/declarationid.h b/language/duchain/declarationid.h --- a/language/duchain/declarationid.h +++ b/language/duchain/declarationid.h @@ -74,20 +74,29 @@ explicit DeclarationId(const IndexedDeclaration& decl, const IndexedInstantiationInformation& specialization = IndexedInstantiationInformation()); + + DeclarationId(const DeclarationId& rhs); + + ~DeclarationId(); + + DeclarationId& operator=(const DeclarationId& rhs); + /** * 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) + if(m_isDirect != rhs.m_isDirect) 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; + if(!m_isDirect) + return m_indirectData.identifier == rhs.m_indirectData.identifier + && m_indirectData.additionalIdentity == rhs.m_indirectData.additionalIdentity + && m_specialization == rhs.m_specialization; else - return direct == rhs.direct && m_specialization == rhs.m_specialization; + return m_directData == rhs.m_directData && m_specialization == rhs.m_specialization; } /** @@ -104,7 +113,7 @@ * Determine whether this declaration identifier references a valid declaration. */ bool isValid() const { - return (m_direct && direct.isValid()) || indirect.m_identifier.isValid(); + return (m_isDirect && m_directData.isValid()) || m_indirectData.identifier.isValid(); } /** @@ -115,10 +124,10 @@ * and thus you cannot compare hashes for declaration equality (use operator==() instead) */ uint hash() const { - if(m_direct) - return KDevHash() << direct.hash() << m_specialization.index(); + if(m_isDirect) + return KDevHash() << m_directData.hash() << m_specialization.index(); else - return KDevHash() << indirect.m_identifier.getIndex() << indirect.m_additionalIdentity << m_specialization.index(); + return KDevHash() << m_indirectData.identifier.getIndex() << m_indirectData.additionalIdentity << m_specialization.index(); } /** @@ -168,20 +177,22 @@ QualifiedIdentifier qualifiedIdentifier() const; private: + /// 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 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; + IndexedQualifiedIdentifier identifier; + /// Hash from signature, or similar. Used to disambiguate multiple declarations of the same name. + uint additionalIdentity; + + Indirect& operator=(const Indirect& rhs) = default; + }; + + union { + Indirect m_indirectData; + IndexedDeclaration m_directData; + }; + bool m_isDirect; + // 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. diff --git a/language/duchain/declarationid.cpp b/language/duchain/declarationid.cpp --- a/language/duchain/declarationid.cpp +++ b/language/duchain/declarationid.cpp @@ -33,25 +33,58 @@ DeclarationId::DeclarationId(const IndexedQualifiedIdentifier& id, uint additionalId, const IndexedInstantiationInformation& specialization) - : m_direct(false) + : m_indirectData{id, additionalId} + , m_isDirect(false) , m_specialization(specialization) { - indirect.m_identifier = id; - indirect.m_additionalIdentity = additionalId; } DeclarationId::DeclarationId(const IndexedDeclaration& decl, const IndexedInstantiationInformation& specialization) - : direct(decl) - , m_direct(true) + : m_directData(decl) + , m_isDirect(true) , m_specialization(specialization) { +} + +DeclarationId::DeclarationId(const DeclarationId& rhs) + : m_isDirect(rhs.m_isDirect) + , m_specialization(rhs.m_specialization) +{ + if (!m_isDirect) { + // IndexedQualifiedIdentifier doesn't like zero-initialization... + new (&m_indirectData.identifier) IndexedQualifiedIdentifier(rhs.m_indirectData.identifier); + m_indirectData.additionalIdentity = rhs.m_indirectData.additionalIdentity; + } else { + m_directData = rhs.m_directData; + } +} + +DeclarationId::~DeclarationId() +{ + if (!m_isDirect) { + m_indirectData.~Indirect(); + } +} +DeclarationId& DeclarationId::operator=(const DeclarationId& rhs) +{ + if (&rhs == this) + return *this; + + m_isDirect = rhs.m_isDirect; + m_specialization = rhs.m_specialization; + if (!m_isDirect) { + m_indirectData = rhs.m_indirectData; + } else { + m_directData = rhs.m_directData; + } + return *this; } bool DeclarationId::isDirect() const { - return m_direct; + return m_isDirect; } void DeclarationId::setSpecialization(const IndexedInstantiationInformation& spec) @@ -68,17 +101,17 @@ { KDevVarLengthArray ret; - if(m_direct == false) { + if(m_isDirect == false) { //Find the declaration by its qualified identifier and additionalIdentity - QualifiedIdentifier id(indirect.m_identifier); + QualifiedIdentifier id(m_indirectData.identifier); if(top) { //Do filtering PersistentSymbolTable::FilteredDeclarationIterator filter = PersistentSymbolTable::self().getFilteredDeclarations(id, top->recursiveImportIndices()); for(; filter; ++filter) { Declaration* decl = filter->data(); - if(decl && indirect.m_additionalIdentity == decl->additionalIdentity()) { + if(decl && m_indirectData.additionalIdentity == decl->additionalIdentity()) { //Hit ret.append(decl); } @@ -97,15 +130,15 @@ if(!top) { Declaration* decl = iDecl.data(); - if(decl && indirect.m_additionalIdentity == decl->additionalIdentity()) { + if(decl && m_indirectData.additionalIdentity == decl->additionalIdentity()) { //Hit ret.append(decl); } } } } }else{ - Declaration* decl = direct.declaration(); + Declaration* decl = m_directData.declaration(); if(decl) ret.append(decl); } @@ -126,17 +159,17 @@ { Declaration* ret = 0; - if(m_direct == false) { + if(m_isDirect == false) { //Find the declaration by its qualified identifier and additionalIdentity - QualifiedIdentifier id(indirect.m_identifier); + QualifiedIdentifier id(m_indirectData.identifier); if(top) { //Do filtering PersistentSymbolTable::FilteredDeclarationIterator filter = PersistentSymbolTable::self().getFilteredDeclarations(id, top->recursiveImportIndices()); for(; filter; ++filter) { Declaration* decl = filter->data(); - if(decl && indirect.m_additionalIdentity == decl->additionalIdentity()) { + if(decl && m_indirectData.additionalIdentity == decl->additionalIdentity()) { //Hit ret = decl; if(!ret->isForwardDeclaration()) @@ -157,7 +190,7 @@ if(!top) { Declaration* decl = iDecl.data(); - if(decl && indirect.m_additionalIdentity == decl->additionalIdentity()) { + if(decl && m_indirectData.additionalIdentity == decl->additionalIdentity()) { //Hit ret = decl; if(!ret->isForwardDeclaration()) @@ -168,7 +201,7 @@ } }else{ //Find the declaration by m_topContext and m_declaration - ret = direct.declaration(); + ret = m_directData.declaration(); } @@ -193,8 +226,8 @@ QualifiedIdentifier DeclarationId::qualifiedIdentifier() const { - if(!m_direct) { - QualifiedIdentifier baseIdentifier = indirect.m_identifier.identifier(); + if(!m_isDirect) { + QualifiedIdentifier baseIdentifier = m_indirectData.identifier.identifier(); if(!m_specialization.index()) return baseIdentifier; return m_specialization.information().applyToIdentifier(baseIdentifier); @@ -206,7 +239,7 @@ return QualifiedIdentifier(i18n("(unknown direct declaration)")); } - return QualifiedIdentifier(i18n("(missing)")) + indirect.m_identifier.identifier(); + return QualifiedIdentifier(i18n("(missing)")) + m_indirectData.identifier.identifier(); } }