1 /*
2 SPDX-FileCopyrightText: 2006 Hamish Rodda <rodda@kde.org>
3 SPDX-FileCopyrightText: 2007-2008 David Nolden <david.nolden.kdevelop@art-master.de>
4
5 SPDX-License-Identifier: LGPL-2.0-only
6 */
7
8 #include "identifier.h"
9
10 #include <QHash>
11 #include "stringhelpers.h"
12 #include "appendedlist_static.h"
13 #include "serialization/itemrepository.h"
14 #include "util/kdevhash.h"
15 #include <debug.h>
16
17 #include <serialization/indexedstring.h>
18 #include <utility>
19
20 #define ifDebug(x)
21
22 namespace KDevelop {
23 template <bool dynamic = false>
24 class IdentifierPrivate
25 {
26 public:
IdentifierPrivate()27 IdentifierPrivate()
28 {
29 }
30
31 template <bool rhsDynamic>
IdentifierPrivate(const IdentifierPrivate<rhsDynamic> & rhs)32 explicit IdentifierPrivate(const IdentifierPrivate<rhsDynamic>& rhs)
33 : m_unique(rhs.m_unique)
34 , m_identifier(rhs.m_identifier)
35 , m_refCount(0)
36 , m_hash(rhs.m_hash)
37 {
38 copyListsFrom(rhs);
39 }
40
~IdentifierPrivate()41 ~IdentifierPrivate()
42 {
43 templateIdentifiersList.free(const_cast<IndexedTypeIdentifier*>(templateIdentifiers()));
44 }
45
46 IdentifierPrivate& operator=(const IdentifierPrivate& rhs) = delete;
47
48 //Flags the stored hash-value invalid
clearHash()49 void clearHash()
50 {
51 //This is always called on an object private to an Identifier, so there is no threading-problem.
52 Q_ASSERT(dynamic);
53 m_hash = 0;
54 }
55
hash() const56 uint hash() const
57 {
58 // Since this only needs reading and the data needs not to be private, this may be called by
59 // multiple threads simultaneously, so computeHash() must be thread-safe.
60 if (!m_hash && dynamic)
61 computeHash();
62 return m_hash;
63 }
64
65 int m_unique = 0;
66 IndexedString m_identifier;
67 uint m_refCount = 0;
68
69 START_APPENDED_LISTS_STATIC(IdentifierPrivate)
70
APPENDED_LIST_FIRST_STATIC(IndexedTypeIdentifier,templateIdentifiers)71 APPENDED_LIST_FIRST_STATIC(IndexedTypeIdentifier, templateIdentifiers)
72
73 END_APPENDED_LISTS_STATIC(templateIdentifiers)
74
75 uint itemSize() const
76 {
77 return sizeof(IdentifierPrivate<false> ) + lastOffsetBehind();
78 }
79
computeHash() const80 void computeHash() const
81 {
82 Q_ASSERT(dynamic);
83 //this must stay thread-safe(may be called by multiple threads at a time)
84 //The thread-safety is given because all threads will have the same result, and it will only be written once at the end.
85 KDevHash kdevhash;
86 kdevhash << m_identifier.hash() << m_unique;
87 FOREACH_FUNCTION_STATIC(const IndexedTypeIdentifier &templateIdentifier, templateIdentifiers)
88 kdevhash << templateIdentifier.hash();
89 m_hash = kdevhash;
90 }
91
92 mutable uint m_hash = 0;
93 };
94
95 using DynamicIdentifierPrivate = IdentifierPrivate<true>;
96 using ConstantIdentifierPrivate = IdentifierPrivate<false>;
97
98 struct IdentifierItemRequest
99 {
IdentifierItemRequestKDevelop::IdentifierItemRequest100 IdentifierItemRequest(const DynamicIdentifierPrivate& identifier)
101 : m_identifier(identifier)
102 {
103 identifier.hash(); //Make sure the hash is valid by calling this
104 }
105
106 enum {
107 AverageSize = sizeof(IdentifierPrivate<false> ) + 4
108 };
109
110 //Should return the hash-value associated with this request(For example the hash of a string)
hashKDevelop::IdentifierItemRequest111 uint hash() const
112 {
113 return m_identifier.hash();
114 }
115
116 //Should return the size of an item created with createItem
itemSizeKDevelop::IdentifierItemRequest117 uint itemSize() const
118 {
119 return m_identifier.itemSize();
120 }
121 //Should create an item where the information of the requested item is permanently stored. The pointer
122 //@param item equals an allocated range with the size of itemSize().
createItemKDevelop::IdentifierItemRequest123 void createItem(ConstantIdentifierPrivate* item) const
124 {
125 new (item) ConstantIdentifierPrivate(m_identifier);
126 }
127
persistentKDevelop::IdentifierItemRequest128 static bool persistent(const ConstantIdentifierPrivate* item)
129 {
130 return ( bool )item->m_refCount;
131 }
132
destroyKDevelop::IdentifierItemRequest133 static void destroy(ConstantIdentifierPrivate* item, AbstractItemRepository&)
134 {
135 item->~ConstantIdentifierPrivate();
136 }
137
138 //Should return whether the here requested item equals the given item
equalsKDevelop::IdentifierItemRequest139 bool equals(const ConstantIdentifierPrivate* item) const
140 {
141 return item->m_hash == m_identifier.m_hash
142 && item->m_unique == m_identifier.m_unique
143 && item->m_identifier == m_identifier.m_identifier
144 && m_identifier.listsEqual(*item);
145 }
146
147 const DynamicIdentifierPrivate& m_identifier;
148 };
149
150 using IdentifierRepository = RepositoryManager<ItemRepository<ConstantIdentifierPrivate, IdentifierItemRequest>, false>;
identifierRepository()151 static IdentifierRepository& identifierRepository()
152 {
153 static IdentifierRepository identifierRepositoryObject(QStringLiteral("Identifier Repository"));
154 return identifierRepositoryObject;
155 }
156
emptyConstantIdentifierPrivateIndex()157 static uint emptyConstantIdentifierPrivateIndex()
158 {
159 static const uint index = identifierRepository()->index(DynamicIdentifierPrivate());
160 return index;
161 }
162
emptyConstantIdentifierPrivate()163 static const ConstantIdentifierPrivate* emptyConstantIdentifierPrivate()
164 {
165 static const ConstantIdentifierPrivate item;
166 return &item;
167 }
168
isEmpty() const169 bool IndexedIdentifier::isEmpty() const
170 {
171 return m_index == emptyConstantIdentifierPrivateIndex();
172 }
173
174 /**
175 * Before something is modified in QualifiedIdentifierPrivate, it must be made sure that
176 * it is private to the QualifiedIdentifier it is used in(@see QualifiedIdentifier::prepareWrite)
177 */
178 template <bool dynamic>
179 class QualifiedIdentifierPrivate
180 {
181 public:
QualifiedIdentifierPrivate()182 QualifiedIdentifierPrivate()
183 : m_explicitlyGlobal(false)
184 , m_isExpression(false)
185
186 {
187 }
188
189 template <bool rhsDynamic>
QualifiedIdentifierPrivate(const QualifiedIdentifierPrivate<rhsDynamic> & rhs)190 explicit QualifiedIdentifierPrivate(const QualifiedIdentifierPrivate<rhsDynamic>& rhs)
191 : m_explicitlyGlobal(rhs.m_explicitlyGlobal)
192 , m_isExpression(rhs.m_isExpression)
193 , m_hash(rhs.m_hash)
194 , m_refCount(0)
195 {
196 copyListsFrom(rhs);
197 }
198
~QualifiedIdentifierPrivate()199 ~QualifiedIdentifierPrivate()
200 {
201 identifiersList.free(const_cast<IndexedIdentifier*>(identifiers()));
202 }
203
204 QualifiedIdentifierPrivate& operator=(const QualifiedIdentifierPrivate& rhs) = delete;
205
206 bool m_explicitlyGlobal : 1;
207 bool m_isExpression : 1;
208 mutable uint m_hash = 0;
209 uint m_refCount = 0;
210
211 START_APPENDED_LISTS_STATIC(QualifiedIdentifierPrivate)
212
APPENDED_LIST_FIRST_STATIC(IndexedIdentifier,identifiers)213 APPENDED_LIST_FIRST_STATIC(IndexedIdentifier, identifiers)
214
215 END_APPENDED_LISTS_STATIC(identifiers)
216
217 uint itemSize() const
218 {
219 return sizeof(QualifiedIdentifierPrivate<false> ) + lastOffsetBehind();
220 }
221
222 //Constructs m_identifiers
splitIdentifiers(const QString & str,int start)223 void splitIdentifiers(const QString& str, int start)
224 {
225 Q_ASSERT(dynamic);
226 uint currentStart = start;
227
228 while (currentStart < ( uint )str.length()) {
229 identifiersList.append(IndexedIdentifier(Identifier(str, currentStart, ¤tStart)));
230 while (currentStart < ( uint )str.length() && (str[currentStart] == QLatin1Char(' ')))
231 ++currentStart;
232 currentStart += 2; //Skip "::"
233 }
234 }
235
clearHash() const236 inline void clearHash() const
237 {
238 m_hash = 0;
239 }
240
hash() const241 uint hash() const
242 {
243 if (m_hash == 0) {
244 KDevHash hash;
245
246 quint32 bitfields = static_cast<quint32>(m_explicitlyGlobal)
247 | (m_isExpression << 1);
248 hash << bitfields << identifiersSize();
249 FOREACH_FUNCTION_STATIC(const IndexedIdentifier &identifier, identifiers) {
250 hash << identifier.index();
251 }
252
253 m_hash = hash;
254 }
255 return m_hash;
256 }
257 };
258
259 using DynamicQualifiedIdentifierPrivate = QualifiedIdentifierPrivate<true>;
260 using ConstantQualifiedIdentifierPrivate = QualifiedIdentifierPrivate<false>;
261
262 struct QualifiedIdentifierItemRequest
263 {
QualifiedIdentifierItemRequestKDevelop::QualifiedIdentifierItemRequest264 QualifiedIdentifierItemRequest(const DynamicQualifiedIdentifierPrivate& identifier)
265 : m_identifier(identifier)
266 {
267 identifier.hash(); //Make sure the hash is valid by calling this
268 }
269
270 enum {
271 AverageSize = sizeof(QualifiedIdentifierPrivate<false> ) + 8
272 };
273
274 //Should return the hash-value associated with this request(For example the hash of a string)
hashKDevelop::QualifiedIdentifierItemRequest275 uint hash() const
276 {
277 return m_identifier.hash();
278 }
279
280 //Should return the size of an item created with createItem
itemSizeKDevelop::QualifiedIdentifierItemRequest281 uint itemSize() const
282 {
283 return m_identifier.itemSize();
284 }
285
286 /**
287 * Should create an item where the information of the requested item is permanently stored. The pointer
288 * @param item equals an allocated range with the size of itemSize().
289 */
createItemKDevelop::QualifiedIdentifierItemRequest290 void createItem(ConstantQualifiedIdentifierPrivate* item) const
291 {
292 Q_ASSERT(shouldDoDUChainReferenceCounting(item));
293 Q_ASSERT(shouldDoDUChainReferenceCounting(reinterpret_cast<char*>(item) + (itemSize() - 1)));
294 new (item) ConstantQualifiedIdentifierPrivate(m_identifier);
295 }
296
persistentKDevelop::QualifiedIdentifierItemRequest297 static bool persistent(const ConstantQualifiedIdentifierPrivate* item)
298 {
299 return ( bool )item->m_refCount;
300 }
301
destroyKDevelop::QualifiedIdentifierItemRequest302 static void destroy(ConstantQualifiedIdentifierPrivate* item, AbstractItemRepository&)
303 {
304 Q_ASSERT(shouldDoDUChainReferenceCounting(item));
305 item->~ConstantQualifiedIdentifierPrivate();
306 }
307
308 //Should return whether the here requested item equals the given item
equalsKDevelop::QualifiedIdentifierItemRequest309 bool equals(const ConstantQualifiedIdentifierPrivate* item) const
310 {
311 return item->m_explicitlyGlobal == m_identifier.m_explicitlyGlobal
312 && item->m_isExpression == m_identifier.m_isExpression
313 && item->m_hash == m_identifier.m_hash
314 && m_identifier.listsEqual(*item);
315 }
316
317 const DynamicQualifiedIdentifierPrivate& m_identifier;
318 };
319
320 using QualifiedIdentifierRepository = RepositoryManager<ItemRepository<ConstantQualifiedIdentifierPrivate,
321 QualifiedIdentifierItemRequest>, false>;
322
qualifiedidentifierRepository()323 static QualifiedIdentifierRepository& qualifiedidentifierRepository()
324 {
325 static QualifiedIdentifierRepository repo(QStringLiteral("Qualified Identifier Repository"), 1,
326 []() -> AbstractRepositoryManager* {
327 return &identifierRepository();
328 });
329 return repo;
330 }
331
emptyConstantQualifiedIdentifierPrivateIndex()332 static uint emptyConstantQualifiedIdentifierPrivateIndex()
333 {
334 static const uint index = qualifiedidentifierRepository()->index(DynamicQualifiedIdentifierPrivate());
335 return index;
336 }
337
emptyConstantQualifiedIdentifierPrivate()338 static const ConstantQualifiedIdentifierPrivate* emptyConstantQualifiedIdentifierPrivate()
339 {
340 static const ConstantQualifiedIdentifierPrivate item;
341 return &item;
342 }
343
Identifier(const Identifier & rhs)344 Identifier::Identifier(const Identifier& rhs)
345 {
346 rhs.makeConstant();
347 cd = rhs.cd;
348 m_index = rhs.m_index;
349 }
350
Identifier(uint index)351 Identifier::Identifier(uint index)
352 : m_index(index)
353 {
354 Q_ASSERT(m_index);
355 cd = identifierRepository()->itemFromIndex(index);
356 }
357
Identifier(const IndexedString & str)358 Identifier::Identifier(const IndexedString& str)
359 {
360 if (str.isEmpty()) {
361 m_index = emptyConstantIdentifierPrivateIndex();
362 cd = emptyConstantIdentifierPrivate();
363 } else {
364 m_index = 0;
365 dd = new IdentifierPrivate<true>;
366 dd->m_identifier = str;
367 }
368 }
369
Identifier(const QString & id,uint start,uint * takenRange)370 Identifier::Identifier(const QString& id, uint start, uint* takenRange)
371 {
372 if (id.isEmpty()) {
373 m_index = emptyConstantIdentifierPrivateIndex();
374 cd = emptyConstantIdentifierPrivate();
375 return;
376 }
377
378 m_index = 0;
379 dd = new IdentifierPrivate<true>;
380
381 ///Extract template-parameters
382 ParamIterator paramIt(QStringLiteral("<>:"), id, start);
383 dd->m_identifier = IndexedString(paramIt.prefix().trimmed());
384 while (paramIt) {
385 appendTemplateIdentifier(IndexedTypeIdentifier(IndexedQualifiedIdentifier(QualifiedIdentifier(*paramIt))));
386 ++paramIt;
387 }
388
389 if (takenRange)
390 *takenRange = paramIt.position();
391 }
392
Identifier()393 Identifier::Identifier()
394 : m_index(emptyConstantIdentifierPrivateIndex())
395 , cd(emptyConstantIdentifierPrivate())
396 {
397 }
398
operator =(const Identifier & rhs)399 Identifier& Identifier::operator=(const Identifier& rhs)
400 {
401 if (dd == rhs.dd && cd == rhs.cd)
402 return *this;
403
404 if (!m_index)
405 delete dd;
406 dd = nullptr;
407
408 rhs.makeConstant();
409 cd = rhs.cd;
410 m_index = rhs.m_index;
411 Q_ASSERT(cd);
412 return *this;
413 }
414
Identifier(Identifier && rhs)415 Identifier::Identifier(Identifier&& rhs) Q_DECL_NOEXCEPT
416 : m_index(rhs.m_index)
417 {
418 if (m_index) {
419 cd = rhs.cd;
420 } else {
421 dd = rhs.dd;
422 }
423 rhs.cd = emptyConstantIdentifierPrivate();
424 rhs.m_index = emptyConstantIdentifierPrivateIndex();
425 }
426
operator =(Identifier && rhs)427 Identifier& Identifier::operator=(Identifier&& rhs) Q_DECL_NOEXCEPT
428 {
429 if (dd == rhs.dd && cd == rhs.cd)
430 return *this;
431
432 if (!m_index) {
433 delete dd;
434 dd = nullptr;
435 }
436
437 m_index = rhs.m_index;
438
439 if (m_index) {
440 cd = rhs.cd;
441 } else {
442 dd = rhs.dd;
443 }
444 rhs.cd = emptyConstantIdentifierPrivate();
445 rhs.m_index = emptyConstantIdentifierPrivateIndex();
446
447 return *this;
448 }
449
~Identifier()450 Identifier::~Identifier()
451 {
452 if (!m_index)
453 delete dd;
454 }
455
nameEquals(const Identifier & rhs) const456 bool Identifier::nameEquals(const Identifier& rhs) const
457 {
458 return identifier() == rhs.identifier();
459 }
460
hash() const461 uint Identifier::hash() const
462 {
463 if (!m_index)
464 return dd->hash();
465 else
466 return cd->hash();
467 }
468
isEmpty() const469 bool Identifier::isEmpty() const
470 {
471 if (!m_index)
472 return dd->m_identifier.isEmpty() && dd->m_unique == 0 && dd->templateIdentifiersSize() == 0;
473 else
474 return cd->m_identifier.isEmpty() && cd->m_unique == 0 && cd->templateIdentifiersSize() == 0;
475 }
476
unique(int token)477 Identifier Identifier::unique(int token)
478 {
479 Identifier ret;
480 ret.setUnique(token);
481 return ret;
482 }
483
isUnique() const484 bool Identifier::isUnique() const
485 {
486 if (!m_index)
487 return dd->m_unique;
488 else
489 return cd->m_unique;
490 }
491
uniqueToken() const492 int Identifier::uniqueToken() const
493 {
494 if (!m_index)
495 return dd->m_unique;
496 else
497 return cd->m_unique;
498 }
499
setUnique(int token)500 void Identifier::setUnique(int token)
501 {
502 if (token != uniqueToken()) {
503 prepareWrite();
504 dd->m_unique = token;
505 }
506 }
507
identifier() const508 const IndexedString Identifier::identifier() const
509 {
510 if (!m_index)
511 return dd->m_identifier;
512 else
513 return cd->m_identifier;
514 }
515
setIdentifier(const QString & identifier)516 void Identifier::setIdentifier(const QString& identifier)
517 {
518 IndexedString id(identifier);
519 if (id != this->identifier()) {
520 prepareWrite();
521 dd->m_identifier = std::move(id);
522 }
523 }
524
setIdentifier(const IndexedString & identifier)525 void Identifier::setIdentifier(const IndexedString& identifier)
526 {
527 if (identifier != this->identifier()) {
528 prepareWrite();
529 dd->m_identifier = identifier;
530 }
531 }
532
templateIdentifier(int num) const533 IndexedTypeIdentifier Identifier::templateIdentifier(int num) const
534 {
535 if (!m_index)
536 return dd->templateIdentifiers()[num];
537 else
538 return cd->templateIdentifiers()[num];
539 }
540
templateIdentifiersCount() const541 uint Identifier::templateIdentifiersCount() const
542 {
543 if (!m_index)
544 return dd->templateIdentifiersSize();
545 else
546 return cd->templateIdentifiersSize();
547 }
548
appendTemplateIdentifier(const IndexedTypeIdentifier & identifier)549 void Identifier::appendTemplateIdentifier(const IndexedTypeIdentifier& identifier)
550 {
551 prepareWrite();
552 dd->templateIdentifiersList.append(identifier);
553 }
554
clearTemplateIdentifiers()555 void Identifier::clearTemplateIdentifiers()
556 {
557 prepareWrite();
558 dd->templateIdentifiersList.clear();
559 }
560
index() const561 uint Identifier::index() const
562 {
563 makeConstant();
564 Q_ASSERT(m_index);
565 return m_index;
566 }
567
inRepository() const568 bool Identifier::inRepository() const
569 {
570 return m_index;
571 }
572
setTemplateIdentifiers(const QList<IndexedTypeIdentifier> & templateIdentifiers)573 void Identifier::setTemplateIdentifiers(const QList<IndexedTypeIdentifier>& templateIdentifiers)
574 {
575 prepareWrite();
576 dd->templateIdentifiersList.clear();
577 for (const IndexedTypeIdentifier& id : templateIdentifiers) {
578 dd->templateIdentifiersList.append(id);
579 }
580 }
581
toString(IdentifierStringFormattingOptions options) const582 QString Identifier::toString(IdentifierStringFormattingOptions options) const
583 {
584 QString ret = identifier().str();
585
586 if (!options.testFlag(RemoveTemplateInformation) && templateIdentifiersCount()) {
587 QStringList templateIds;
588 templateIds.reserve(templateIdentifiersCount());
589 for (uint i = 0; i < templateIdentifiersCount(); ++i) {
590 templateIds.append(templateIdentifier(i).toString(options));
591 }
592
593 ret += QLatin1String("< ") + templateIds.join(QLatin1String(", ")) + QLatin1String(" >");
594 }
595
596 return ret;
597 }
598
operator ==(const Identifier & rhs) const599 bool Identifier::operator==(const Identifier& rhs) const
600 {
601 return index() == rhs.index();
602 }
603
operator !=(const Identifier & rhs) const604 bool Identifier::operator!=(const Identifier& rhs) const
605 {
606 return !operator==(rhs);
607 }
608
index() const609 uint QualifiedIdentifier::index() const
610 {
611 makeConstant();
612 Q_ASSERT(m_index);
613 return m_index;
614 }
615
makeConstant() const616 void Identifier::makeConstant() const
617 {
618 if (m_index)
619 return;
620 m_index = identifierRepository()->index(IdentifierItemRequest(*dd));
621 delete dd;
622 cd = identifierRepository()->itemFromIndex(m_index);
623 }
624
prepareWrite()625 void Identifier::prepareWrite()
626 {
627 if (m_index) {
628 const IdentifierPrivate<false>* oldCc = cd;
629 dd = new IdentifierPrivate<true>;
630 dd->m_hash = oldCc->m_hash;
631 dd->m_unique = oldCc->m_unique;
632 dd->m_identifier = oldCc->m_identifier;
633 dd->copyListsFrom(*oldCc);
634 m_index = 0;
635 }
636
637 dd->clearHash();
638 }
639
inRepository() const640 bool QualifiedIdentifier::inRepository() const
641 {
642 if (m_index)
643 return true;
644 else
645 return ( bool )qualifiedidentifierRepository()->findIndex(QualifiedIdentifierItemRequest(*dd));
646 }
647
QualifiedIdentifier(uint index)648 QualifiedIdentifier::QualifiedIdentifier(uint index)
649 : m_index(index)
650 , cd(qualifiedidentifierRepository()->itemFromIndex(index))
651 {
652 }
653
QualifiedIdentifier(const QString & id,bool isExpression)654 QualifiedIdentifier::QualifiedIdentifier(const QString& id, bool isExpression)
655 {
656 if (id.isEmpty()) {
657 m_index = emptyConstantQualifiedIdentifierPrivateIndex();
658 cd = emptyConstantQualifiedIdentifierPrivate();
659 return;
660 }
661
662 m_index = 0;
663 dd = new DynamicQualifiedIdentifierPrivate;
664
665 if (isExpression) {
666 setIsExpression(true);
667 if (!id.isEmpty()) {
668 //Prevent tokenization, since we may lose information there
669 Identifier finishedId;
670 finishedId.setIdentifier(id);
671 push(finishedId);
672 }
673 } else {
674 if (id.startsWith(QLatin1String("::"))) {
675 dd->m_explicitlyGlobal = true;
676 dd->splitIdentifiers(id, 2);
677 } else {
678 dd->m_explicitlyGlobal = false;
679 dd->splitIdentifiers(id, 0);
680 }
681 }
682 }
683
QualifiedIdentifier(const Identifier & id)684 QualifiedIdentifier::QualifiedIdentifier(const Identifier& id)
685 {
686 if (id.isEmpty()) {
687 m_index = emptyConstantQualifiedIdentifierPrivateIndex();
688 cd = emptyConstantQualifiedIdentifierPrivate();
689 return;
690 }
691
692 m_index = 0;
693 dd = new DynamicQualifiedIdentifierPrivate;
694
695 if (id.dd->m_identifier.str().isEmpty()) {
696 dd->m_explicitlyGlobal = true;
697 } else {
698 dd->m_explicitlyGlobal = false;
699 dd->identifiersList.append(IndexedIdentifier(id));
700 }
701 }
702
QualifiedIdentifier()703 QualifiedIdentifier::QualifiedIdentifier()
704 : m_index(emptyConstantQualifiedIdentifierPrivateIndex())
705 , cd(emptyConstantQualifiedIdentifierPrivate())
706 {
707 }
708
QualifiedIdentifier(const QualifiedIdentifier & id)709 QualifiedIdentifier::QualifiedIdentifier(const QualifiedIdentifier& id)
710 {
711 if (id.m_index) {
712 m_index = id.m_index;
713 cd = id.cd;
714 } else {
715 m_index = 0;
716 dd = new QualifiedIdentifierPrivate<true>(*id.dd);
717 }
718 }
719
QualifiedIdentifier(QualifiedIdentifier && rhs)720 QualifiedIdentifier::QualifiedIdentifier(QualifiedIdentifier&& rhs) Q_DECL_NOEXCEPT
721 : m_index(rhs.m_index)
722 {
723 if (m_index) {
724 cd = rhs.cd;
725 } else {
726 dd = rhs.dd;
727 }
728 rhs.m_index = emptyConstantQualifiedIdentifierPrivateIndex();
729 rhs.cd = emptyConstantQualifiedIdentifierPrivate();
730 }
731
operator =(const QualifiedIdentifier & rhs)732 QualifiedIdentifier& QualifiedIdentifier::operator=(const QualifiedIdentifier& rhs)
733 {
734 if (dd == rhs.dd && cd == rhs.cd)
735 return *this;
736
737 if (!m_index)
738 delete dd;
739 rhs.makeConstant();
740 cd = rhs.cd;
741 m_index = rhs.m_index;
742 return *this;
743 }
744
operator =(QualifiedIdentifier && rhs)745 QualifiedIdentifier& QualifiedIdentifier::operator=(QualifiedIdentifier&& rhs) Q_DECL_NOEXCEPT
746 {
747 if (!m_index)
748 delete dd;
749 m_index = rhs.m_index;
750 if (m_index) {
751 cd = rhs.cd;
752 } else {
753 dd = rhs.dd;
754 }
755 rhs.cd = emptyConstantQualifiedIdentifierPrivate();
756 rhs.m_index = emptyConstantQualifiedIdentifierPrivateIndex();
757 return *this;
758 }
759
~QualifiedIdentifier()760 QualifiedIdentifier::~QualifiedIdentifier()
761 {
762 if (!m_index)
763 delete dd;
764 }
765
toStringList(IdentifierStringFormattingOptions options) const766 QStringList QualifiedIdentifier::toStringList(IdentifierStringFormattingOptions options) const
767 {
768 QStringList ret;
769 ret.reserve(explicitlyGlobal() + count());
770 if (explicitlyGlobal())
771 ret.append(QString());
772
773 if (m_index) {
774 ret.reserve(ret.size() + cd->identifiersSize());
775 FOREACH_FUNCTION_STATIC(const IndexedIdentifier &index, cd->identifiers)
776 ret << index.identifier().toString(options);
777 } else {
778 ret.reserve(ret.size() + dd->identifiersSize());
779 FOREACH_FUNCTION_STATIC(const IndexedIdentifier &index, dd->identifiers)
780 ret << index.identifier().toString(options);
781 }
782
783 return ret;
784 }
785
toString(IdentifierStringFormattingOptions options) const786 QString QualifiedIdentifier::toString(IdentifierStringFormattingOptions options) const
787 {
788 const QString doubleColon = QStringLiteral("::");
789
790 QString ret;
791 if (!options.testFlag(RemoveExplicitlyGlobalPrefix) && explicitlyGlobal())
792 ret = doubleColon;
793
794 QStringList identifiers;
795 if (m_index) {
796 identifiers.reserve(cd->identifiersSize());
797 FOREACH_FUNCTION_STATIC(const IndexedIdentifier &index, cd->identifiers)
798 {
799 identifiers += index.identifier().toString(options);
800 }
801 } else {
802 identifiers.reserve(dd->identifiersSize());
803 FOREACH_FUNCTION_STATIC(const IndexedIdentifier &index, dd->identifiers)
804 {
805 identifiers += index.identifier().toString(options);
806 }
807 }
808
809 return ret + identifiers.join(doubleColon);
810 }
811
merge(const QualifiedIdentifier & base) const812 QualifiedIdentifier QualifiedIdentifier::merge(const QualifiedIdentifier& base) const
813 {
814 QualifiedIdentifier ret(base);
815 ret.push(*this);
816 return ret;
817 }
818
operator +(const QualifiedIdentifier & rhs) const819 QualifiedIdentifier QualifiedIdentifier::operator+(const QualifiedIdentifier& rhs) const
820 {
821 return rhs.merge(*this);
822 }
823
operator +=(const QualifiedIdentifier & rhs)824 QualifiedIdentifier& QualifiedIdentifier::operator+=(const QualifiedIdentifier& rhs)
825 {
826 push(rhs);
827 return *this;
828 }
829
operator +(const Identifier & rhs) const830 QualifiedIdentifier QualifiedIdentifier::operator+(const Identifier& rhs) const
831 {
832 QualifiedIdentifier ret(*this);
833 ret.push(rhs);
834 return ret;
835 }
836
operator +=(const Identifier & rhs)837 QualifiedIdentifier& QualifiedIdentifier::operator+=(const Identifier& rhs)
838 {
839 push(rhs);
840 return *this;
841 }
842
operator +(const IndexedIdentifier & rhs) const843 QualifiedIdentifier QualifiedIdentifier::operator+(const IndexedIdentifier& rhs) const
844 {
845 QualifiedIdentifier ret(*this);
846 ret.push(rhs);
847 return ret;
848 }
849
operator +=(const IndexedIdentifier & rhs)850 QualifiedIdentifier& QualifiedIdentifier::operator+=(const IndexedIdentifier& rhs)
851 {
852 push(rhs);
853 return *this;
854 }
855
isExpression() const856 bool QualifiedIdentifier::isExpression() const
857 {
858 if (m_index)
859 return cd->m_isExpression;
860 else
861 return dd->m_isExpression;
862 }
863
setIsExpression(bool is)864 void QualifiedIdentifier::setIsExpression(bool is)
865 {
866 if (is != isExpression()) {
867 prepareWrite();
868 dd->m_isExpression = is;
869 }
870 }
871
explicitlyGlobal() const872 bool QualifiedIdentifier::explicitlyGlobal() const
873 {
874 // True if started with "::"
875 if (m_index)
876 return cd->m_explicitlyGlobal;
877 else
878 return dd->m_explicitlyGlobal;
879 }
880
setExplicitlyGlobal(bool eg)881 void QualifiedIdentifier::setExplicitlyGlobal(bool eg)
882 {
883 if (eg != explicitlyGlobal()) {
884 prepareWrite();
885 dd->m_explicitlyGlobal = eg;
886 }
887 }
888
sameIdentifiers(const QualifiedIdentifier & rhs) const889 bool QualifiedIdentifier::sameIdentifiers(const QualifiedIdentifier& rhs) const
890 {
891 if (m_index && rhs.m_index)
892 return cd->listsEqual(*rhs.cd);
893 else if (m_index && !rhs.m_index)
894 return cd->listsEqual(*rhs.dd);
895 else if (!m_index && !rhs.m_index)
896 return dd->listsEqual(*rhs.dd);
897 else
898 return dd->listsEqual(*rhs.cd);
899 }
900
operator ==(const QualifiedIdentifier & rhs) const901 bool QualifiedIdentifier::operator==(const QualifiedIdentifier& rhs) const
902 {
903 if (cd == rhs.cd)
904 return true;
905 return hash() == rhs.hash() && sameIdentifiers(rhs);
906 }
907
operator !=(const QualifiedIdentifier & rhs) const908 bool QualifiedIdentifier::operator!=(const QualifiedIdentifier& rhs) const
909 {
910 return !operator==(rhs);
911 }
912
beginsWith(const QualifiedIdentifier & other) const913 bool QualifiedIdentifier::beginsWith(const QualifiedIdentifier& other) const
914 {
915 uint c = count();
916 uint oc = other.count();
917
918 for (uint i = 0; i < c && i < oc; ++i)
919 if (at(i) == other.at(i)) {
920 continue;
921 } else {
922 return false;
923 }
924
925 return true;
926 }
927
928 struct Visitor
929 {
VisitorKDevelop::Visitor930 Visitor(KDevVarLengthArray<QualifiedIdentifier>& target, uint hash)
931 : target(target)
932 , hash(hash)
933 {
934 }
935
operator ()KDevelop::Visitor936 bool operator()(const ConstantQualifiedIdentifierPrivate* item, uint index) const
937 {
938 if (item->m_hash == hash)
939 target.append(QualifiedIdentifier(index));
940 return true;
941 }
942
943 KDevVarLengthArray<QualifiedIdentifier>& target;
944 const uint hash;
945 };
946
hash() const947 uint QualifiedIdentifier::hash() const
948 {
949 if (m_index)
950 return cd->hash();
951 else
952 return dd->hash();
953 }
954
qHash(const IndexedTypeIdentifier & id)955 uint qHash(const IndexedTypeIdentifier& id)
956 {
957 return id.hash();
958 }
959
qHash(const QualifiedIdentifier & id)960 uint qHash(const QualifiedIdentifier& id)
961 {
962 return id.hash();
963 }
964
qHash(const Identifier & id)965 uint qHash(const Identifier& id)
966 {
967 return id.hash();
968 }
969
isQualified() const970 bool QualifiedIdentifier::isQualified() const
971 {
972 return count() > 1 || explicitlyGlobal();
973 }
974
push(const Identifier & id)975 void QualifiedIdentifier::push(const Identifier& id)
976 {
977 if (id.isEmpty())
978 return;
979
980 push(IndexedIdentifier(id));
981 }
982
push(const IndexedIdentifier & id)983 void QualifiedIdentifier::push(const IndexedIdentifier& id)
984 {
985 if (id.isEmpty()) {
986 return;
987 }
988
989 prepareWrite();
990
991 dd->identifiersList.append(id);
992 }
993
push(const QualifiedIdentifier & id)994 void QualifiedIdentifier::push(const QualifiedIdentifier& id)
995 {
996 if (id.isEmpty()) {
997 return;
998 }
999
1000 prepareWrite();
1001
1002 if (id.m_index) {
1003 dd->identifiersList.append(id.cd->identifiers(), id.cd->identifiersSize());
1004 } else {
1005 dd->identifiersList.append(id.dd->identifiers(), id.dd->identifiersSize());
1006 }
1007
1008 if (id.explicitlyGlobal()) {
1009 setExplicitlyGlobal(true);
1010 }
1011 }
1012
pop()1013 void QualifiedIdentifier::pop()
1014 {
1015 prepareWrite();
1016 if (!dd->identifiersSize())
1017 return;
1018 dd->identifiersList.resize(dd->identifiersList.size() - 1);
1019 }
1020
clear()1021 void QualifiedIdentifier::clear()
1022 {
1023 prepareWrite();
1024 dd->identifiersList.clear();
1025 dd->m_explicitlyGlobal = false;
1026 dd->m_isExpression = false;
1027 }
1028
isEmpty() const1029 bool QualifiedIdentifier::isEmpty() const
1030 {
1031 if (m_index)
1032 return cd->identifiersSize() == 0;
1033 else
1034 return dd->identifiersSize() == 0;
1035 }
1036
count() const1037 int QualifiedIdentifier::count() const
1038 {
1039 if (m_index)
1040 return cd->identifiersSize();
1041 else
1042 return dd->identifiersSize();
1043 }
1044
first() const1045 Identifier QualifiedIdentifier::first() const
1046 {
1047 return indexedFirst().identifier();
1048 }
1049
indexedFirst() const1050 IndexedIdentifier QualifiedIdentifier::indexedFirst() const
1051 {
1052 if ((m_index && cd->identifiersSize() == 0) || (!m_index && dd->identifiersSize() == 0))
1053 return IndexedIdentifier();
1054 else
1055 return indexedAt(0);
1056 }
1057
last() const1058 Identifier QualifiedIdentifier::last() const
1059 {
1060 return indexedLast().identifier();
1061 }
1062
indexedLast() const1063 IndexedIdentifier QualifiedIdentifier::indexedLast() const
1064 {
1065 uint c = count();
1066 if (c)
1067 return indexedAt(c - 1);
1068 else
1069 return IndexedIdentifier();
1070 }
1071
top() const1072 Identifier QualifiedIdentifier::top() const
1073 {
1074 return last();
1075 }
1076
mid(int pos,int len) const1077 QualifiedIdentifier QualifiedIdentifier::mid(int pos, int len) const
1078 {
1079 QualifiedIdentifier ret;
1080 if (pos == 0)
1081 ret.setExplicitlyGlobal(explicitlyGlobal());
1082
1083 int cnt = ( int )count();
1084
1085 if (len == -1)
1086 len = cnt - pos;
1087
1088 if (pos + len > cnt)
1089 len -= cnt - (pos + len);
1090
1091 for (int a = pos; a < pos + len; a++)
1092 ret.push(at(a));
1093
1094 return ret;
1095 }
1096
at(int i) const1097 Identifier QualifiedIdentifier::at(int i) const
1098 {
1099 return indexedAt(i).identifier();
1100 }
1101
indexedAt(int i) const1102 IndexedIdentifier QualifiedIdentifier::indexedAt(int i) const
1103 {
1104 if (m_index) {
1105 Q_ASSERT(i >= 0 && i < ( int )cd->identifiersSize());
1106 return cd->identifiers()[i];
1107 } else {
1108 Q_ASSERT(i >= 0 && i < ( int )dd->identifiersSize());
1109 return dd->identifiers()[i];
1110 }
1111 }
1112
makeConstant() const1113 void QualifiedIdentifier::makeConstant() const
1114 {
1115 if (m_index)
1116 return;
1117 m_index = qualifiedidentifierRepository()->index(QualifiedIdentifierItemRequest(*dd));
1118 delete dd;
1119 cd = qualifiedidentifierRepository()->itemFromIndex(m_index);
1120 }
1121
prepareWrite()1122 void QualifiedIdentifier::prepareWrite()
1123 {
1124 if (m_index) {
1125 const QualifiedIdentifierPrivate<false>* oldCc = cd;
1126 dd = new QualifiedIdentifierPrivate<true>;
1127 dd->m_explicitlyGlobal = oldCc->m_explicitlyGlobal;
1128 dd->m_isExpression = oldCc->m_isExpression;
1129 dd->m_hash = oldCc->m_hash;
1130
1131 dd->copyListsFrom(*oldCc);
1132 m_index = 0;
1133 }
1134
1135 dd->clearHash();
1136 }
1137
hash() const1138 uint IndexedTypeIdentifier::hash() const
1139 {
1140 quint32 bitfields = static_cast<quint32>(m_isConstant)
1141 | (m_isReference << 1)
1142 | (m_isRValue << 2)
1143 | (m_isVolatile << 3)
1144 | (m_pointerDepth << 4)
1145 | (m_pointerConstMask << 9);
1146 return KDevHash() << m_identifier.index() << bitfields;
1147 }
1148
operator ==(const IndexedTypeIdentifier & rhs) const1149 bool IndexedTypeIdentifier::operator==(const IndexedTypeIdentifier& rhs) const
1150 {
1151 return m_identifier == rhs.m_identifier
1152 && m_isConstant == rhs.m_isConstant
1153 && m_isReference == rhs.m_isReference
1154 && m_isRValue == rhs.m_isRValue
1155 && m_isVolatile == rhs.m_isVolatile
1156 && m_pointerConstMask == rhs.m_pointerConstMask
1157 && m_pointerDepth == rhs.m_pointerDepth;
1158 }
1159
operator !=(const IndexedTypeIdentifier & rhs) const1160 bool IndexedTypeIdentifier::operator!=(const IndexedTypeIdentifier& rhs) const
1161 {
1162 return !operator==(rhs);
1163 }
1164
isReference() const1165 bool IndexedTypeIdentifier::isReference() const
1166 {
1167 return m_isReference;
1168 }
1169
setIsReference(bool isRef)1170 void IndexedTypeIdentifier::setIsReference(bool isRef)
1171 {
1172 m_isReference = isRef;
1173 }
1174
isRValue() const1175 bool IndexedTypeIdentifier::isRValue() const
1176 {
1177 return m_isRValue;
1178 }
1179
setIsRValue(bool isRVal)1180 void IndexedTypeIdentifier::setIsRValue(bool isRVal)
1181 {
1182 m_isRValue = isRVal;
1183 }
1184
isConstant() const1185 bool IndexedTypeIdentifier::isConstant() const
1186 {
1187 return m_isConstant;
1188 }
1189
setIsConstant(bool isConst)1190 void IndexedTypeIdentifier::setIsConstant(bool isConst)
1191 {
1192 m_isConstant = isConst;
1193 }
1194
isVolatile() const1195 bool IndexedTypeIdentifier::isVolatile() const
1196 {
1197 return m_isVolatile;
1198 }
1199
setIsVolatile(bool isVolatile)1200 void IndexedTypeIdentifier::setIsVolatile(bool isVolatile)
1201 {
1202 m_isVolatile = isVolatile;
1203 }
1204
pointerDepth() const1205 int IndexedTypeIdentifier::pointerDepth() const
1206 {
1207 return m_pointerDepth;
1208 }
1209
setPointerDepth(int depth)1210 void IndexedTypeIdentifier::setPointerDepth(int depth)
1211 {
1212 Q_ASSERT(depth <= 23 && depth >= 0);
1213 ///Clear the mask in removed fields
1214 for (int s = depth; s < ( int )m_pointerDepth; ++s)
1215 setIsConstPointer(s, false);
1216
1217 m_pointerDepth = depth;
1218 }
1219
isConstPointer(int depthNumber) const1220 bool IndexedTypeIdentifier::isConstPointer(int depthNumber) const
1221 {
1222 return m_pointerConstMask & (1 << depthNumber);
1223 }
1224
setIsConstPointer(int depthNumber,bool constant)1225 void IndexedTypeIdentifier::setIsConstPointer(int depthNumber, bool constant)
1226 {
1227 if (constant)
1228 m_pointerConstMask |= (1 << depthNumber);
1229 else
1230 m_pointerConstMask &= (~(1 << depthNumber));
1231 }
1232
toString(IdentifierStringFormattingOptions options) const1233 QString IndexedTypeIdentifier::toString(IdentifierStringFormattingOptions options) const
1234 {
1235 QString ret;
1236 if (isConstant())
1237 ret += QLatin1String("const ");
1238 if (isVolatile())
1239 ret += QLatin1String("volatile ");
1240
1241 ret += m_identifier.identifier().toString(options);
1242 for (int a = 0; a < pointerDepth(); ++a) {
1243 ret += QLatin1Char('*');
1244 if (isConstPointer(a))
1245 ret += QLatin1String("const");
1246 }
1247
1248 if (isRValue())
1249 ret += QLatin1String("&&");
1250 else if (isReference())
1251 ret += QLatin1Char('&');
1252 return ret;
1253 }
1254
IndexedTypeIdentifier(const IndexedQualifiedIdentifier & identifier)1255 IndexedTypeIdentifier::IndexedTypeIdentifier(const IndexedQualifiedIdentifier& identifier)
1256 : m_identifier(identifier)
1257 , m_isConstant(false)
1258 , m_isReference(false)
1259 , m_isRValue(false)
1260 , m_isVolatile(false)
1261 , m_pointerDepth(0)
1262 , m_pointerConstMask(0)
1263 { }
1264
IndexedTypeIdentifier(const QString & identifier,bool isExpression)1265 IndexedTypeIdentifier::IndexedTypeIdentifier(const QString& identifier, bool isExpression)
1266 : m_identifier(QualifiedIdentifier(identifier, isExpression))
1267 , m_isConstant(false)
1268 , m_isReference(false)
1269 , m_isRValue(false)
1270 , m_isVolatile(false)
1271 , m_pointerDepth(0)
1272 , m_pointerConstMask(0)
1273 { }
1274
IndexedIdentifier()1275 IndexedIdentifier::IndexedIdentifier()
1276 : m_index(emptyConstantIdentifierPrivateIndex())
1277 {
1278 if (shouldDoDUChainReferenceCounting(this)) {
1279 QMutexLocker lock(identifierRepository()->mutex());
1280 increase(identifierRepository()->dynamicItemFromIndexSimple(m_index)->m_refCount, m_index);
1281 }
1282 }
1283
IndexedIdentifier(const Identifier & id)1284 IndexedIdentifier::IndexedIdentifier(const Identifier& id)
1285 : m_index(id.index())
1286 {
1287 if (shouldDoDUChainReferenceCounting(this)) {
1288 QMutexLocker lock(identifierRepository()->mutex());
1289 increase(identifierRepository()->dynamicItemFromIndexSimple(m_index)->m_refCount, m_index);
1290 }
1291 }
1292
IndexedIdentifier(const IndexedIdentifier & rhs)1293 IndexedIdentifier::IndexedIdentifier(const IndexedIdentifier& rhs)
1294 : m_index(rhs.m_index)
1295 {
1296 if (shouldDoDUChainReferenceCounting(this)) {
1297 QMutexLocker lock(identifierRepository()->mutex());
1298 increase(identifierRepository()->dynamicItemFromIndexSimple(m_index)->m_refCount, m_index);
1299 }
1300 }
1301
IndexedIdentifier(IndexedIdentifier && rhs)1302 IndexedIdentifier::IndexedIdentifier(IndexedIdentifier&& rhs) Q_DECL_NOEXCEPT
1303 : m_index(rhs.m_index)
1304 {
1305 rhs.m_index = emptyConstantIdentifierPrivateIndex();
1306 }
1307
~IndexedIdentifier()1308 IndexedIdentifier::~IndexedIdentifier()
1309 {
1310 if (shouldDoDUChainReferenceCounting(this)) {
1311 QMutexLocker lock(identifierRepository()->mutex());
1312 decrease(identifierRepository()->dynamicItemFromIndexSimple(m_index)->m_refCount, m_index);
1313 }
1314 }
1315
operator =(const Identifier & id)1316 IndexedIdentifier& IndexedIdentifier::operator=(const Identifier& id)
1317 {
1318 if (shouldDoDUChainReferenceCounting(this)) {
1319 QMutexLocker lock(identifierRepository()->mutex());
1320 decrease(identifierRepository()->dynamicItemFromIndexSimple(m_index)->m_refCount, m_index);
1321 }
1322
1323 m_index = id.index();
1324
1325 if (shouldDoDUChainReferenceCounting(this)) {
1326 QMutexLocker lock(identifierRepository()->mutex());
1327 increase(identifierRepository()->dynamicItemFromIndexSimple(m_index)->m_refCount, m_index);
1328 }
1329 return *this;
1330 }
1331
operator =(IndexedIdentifier && rhs)1332 IndexedIdentifier& IndexedIdentifier::operator=(IndexedIdentifier&& rhs) Q_DECL_NOEXCEPT
1333 {
1334 if (shouldDoDUChainReferenceCounting(this)) {
1335 QMutexLocker lock(identifierRepository()->mutex());
1336 ifDebug(qCDebug(LANGUAGE) << "decreasing"; )
1337
1338 decrease(identifierRepository()->dynamicItemFromIndexSimple(m_index)->m_refCount, m_index);
1339 } else if (shouldDoDUChainReferenceCounting(&rhs)) {
1340 QMutexLocker lock(identifierRepository()->mutex());
1341 ifDebug(qCDebug(LANGUAGE) << "decreasing"; )
1342
1343 decrease(identifierRepository()->dynamicItemFromIndexSimple(rhs.m_index)->m_refCount, rhs.m_index);
1344 }
1345
1346 m_index = rhs.m_index;
1347 rhs.m_index = emptyConstantIdentifierPrivateIndex();
1348
1349 if (shouldDoDUChainReferenceCounting(this) && !(shouldDoDUChainReferenceCounting(&rhs))) {
1350 QMutexLocker lock(identifierRepository()->mutex());
1351 ifDebug(qCDebug(LANGUAGE) << "increasing"; )
1352
1353 increase(identifierRepository()->dynamicItemFromIndexSimple(m_index)->m_refCount, m_index);
1354 }
1355
1356 return *this;
1357 }
1358
operator =(const IndexedIdentifier & id)1359 IndexedIdentifier& IndexedIdentifier::operator=(const IndexedIdentifier& id)
1360 {
1361 if (shouldDoDUChainReferenceCounting(this)) {
1362 QMutexLocker lock(identifierRepository()->mutex());
1363 decrease(identifierRepository()->dynamicItemFromIndexSimple(m_index)->m_refCount, m_index);
1364 }
1365
1366 m_index = id.m_index;
1367
1368 if (shouldDoDUChainReferenceCounting(this)) {
1369 QMutexLocker lock(identifierRepository()->mutex());
1370 increase(identifierRepository()->dynamicItemFromIndexSimple(m_index)->m_refCount, m_index);
1371 }
1372 return *this;
1373 }
1374
operator ==(const IndexedIdentifier & rhs) const1375 bool IndexedIdentifier::operator==(const IndexedIdentifier& rhs) const
1376 {
1377 return m_index == rhs.m_index;
1378 }
1379
operator !=(const IndexedIdentifier & rhs) const1380 bool IndexedIdentifier::operator!=(const IndexedIdentifier& rhs) const
1381 {
1382 return m_index != rhs.m_index;
1383 }
1384
operator ==(const Identifier & id) const1385 bool IndexedIdentifier::operator==(const Identifier& id) const
1386 {
1387 return m_index == id.index();
1388 }
1389
identifier() const1390 Identifier IndexedIdentifier::identifier() const
1391 {
1392 return Identifier(m_index);
1393 }
1394
operator Identifier() const1395 IndexedIdentifier::operator Identifier() const
1396 {
1397 return Identifier(m_index);
1398 }
1399
isValid() const1400 bool IndexedQualifiedIdentifier::isValid() const
1401 {
1402 return m_index != emptyConstantQualifiedIdentifierPrivateIndex();
1403 }
1404
isEmpty() const1405 bool IndexedQualifiedIdentifier::isEmpty() const
1406 {
1407 return m_index == emptyConstantQualifiedIdentifierPrivateIndex();
1408 }
1409
1410 int cnt = 0;
1411
identifier() const1412 IndexedQualifiedIdentifier IndexedTypeIdentifier::identifier() const
1413 {
1414 return m_identifier;
1415 }
1416
setIdentifier(const IndexedQualifiedIdentifier & id)1417 void IndexedTypeIdentifier::setIdentifier(const IndexedQualifiedIdentifier& id)
1418 {
1419 m_identifier = id;
1420 }
1421
IndexedQualifiedIdentifier()1422 IndexedQualifiedIdentifier::IndexedQualifiedIdentifier()
1423 : m_index(emptyConstantQualifiedIdentifierPrivateIndex())
1424 {
1425 ifDebug(qCDebug(LANGUAGE) << "(" << ++cnt << ")" << identifier().toString() << m_index; )
1426
1427 if (shouldDoDUChainReferenceCounting(this)) {
1428 ifDebug(qCDebug(LANGUAGE) << "increasing"; )
1429
1430 //qCDebug(LANGUAGE) << "(" << ++cnt << ")" << this << identifier().toString() << "inc" << index;
1431 QMutexLocker lock(qualifiedidentifierRepository()->mutex());
1432 increase(qualifiedidentifierRepository()->dynamicItemFromIndexSimple(m_index)->m_refCount, m_index);
1433 }
1434 }
1435
IndexedQualifiedIdentifier(const QualifiedIdentifier & id)1436 IndexedQualifiedIdentifier::IndexedQualifiedIdentifier(const QualifiedIdentifier& id)
1437 : m_index(id.index())
1438 {
1439 ifDebug(qCDebug(LANGUAGE) << "(" << ++cnt << ")" << identifier().toString() << m_index; )
1440
1441 if (shouldDoDUChainReferenceCounting(this)) {
1442 ifDebug(qCDebug(LANGUAGE) << "increasing"; )
1443 QMutexLocker lock(qualifiedidentifierRepository()->mutex());
1444 increase(qualifiedidentifierRepository()->dynamicItemFromIndexSimple(m_index)->m_refCount, m_index);
1445 }
1446 }
1447
IndexedQualifiedIdentifier(const IndexedQualifiedIdentifier & id)1448 IndexedQualifiedIdentifier::IndexedQualifiedIdentifier(const IndexedQualifiedIdentifier& id)
1449 : m_index(id.m_index)
1450 {
1451 ifDebug(qCDebug(LANGUAGE) << "(" << ++cnt << ")" << identifier().toString() << m_index; )
1452
1453 if (shouldDoDUChainReferenceCounting(this)) {
1454 ifDebug(qCDebug(LANGUAGE) << "increasing"; )
1455
1456 QMutexLocker lock(qualifiedidentifierRepository()->mutex());
1457 increase(qualifiedidentifierRepository()->dynamicItemFromIndexSimple(m_index)->m_refCount, m_index);
1458 }
1459 }
1460
IndexedQualifiedIdentifier(IndexedQualifiedIdentifier && rhs)1461 IndexedQualifiedIdentifier::IndexedQualifiedIdentifier(IndexedQualifiedIdentifier&& rhs) Q_DECL_NOEXCEPT
1462 : m_index(rhs.m_index)
1463 {
1464 rhs.m_index = emptyConstantQualifiedIdentifierPrivateIndex();
1465 }
1466
operator =(const QualifiedIdentifier & id)1467 IndexedQualifiedIdentifier& IndexedQualifiedIdentifier::operator=(const QualifiedIdentifier& id)
1468 {
1469 ifDebug(qCDebug(LANGUAGE) << "(" << ++cnt << ")" << identifier().toString() << m_index; )
1470
1471 if (shouldDoDUChainReferenceCounting(this)) {
1472 QMutexLocker lock(qualifiedidentifierRepository()->mutex());
1473
1474 ifDebug(qCDebug(LANGUAGE) << "decreasing"; )
1475 decrease(qualifiedidentifierRepository()->dynamicItemFromIndexSimple(m_index)->m_refCount, m_index);
1476
1477 m_index = id.index();
1478
1479 ifDebug(qCDebug(LANGUAGE) << m_index << "increasing"; )
1480 increase(qualifiedidentifierRepository()->dynamicItemFromIndexSimple(m_index)->m_refCount, m_index);
1481 } else {
1482 m_index = id.index();
1483 }
1484
1485 return *this;
1486 }
1487
operator =(const IndexedQualifiedIdentifier & rhs)1488 IndexedQualifiedIdentifier& IndexedQualifiedIdentifier::operator=(const IndexedQualifiedIdentifier& rhs)
1489 {
1490 ifDebug(qCDebug(LANGUAGE) << "(" << ++cnt << ")" << identifier().toString() << m_index; )
1491
1492 if (shouldDoDUChainReferenceCounting(this)) {
1493 QMutexLocker lock(qualifiedidentifierRepository()->mutex());
1494 ifDebug(qCDebug(LANGUAGE) << "decreasing"; )
1495
1496 decrease(qualifiedidentifierRepository()->dynamicItemFromIndexSimple(m_index)->m_refCount, m_index);
1497
1498 m_index = rhs.m_index;
1499
1500 ifDebug(qCDebug(LANGUAGE) << m_index << "increasing"; )
1501 increase(qualifiedidentifierRepository()->dynamicItemFromIndexSimple(m_index)->m_refCount, m_index);
1502 } else {
1503 m_index = rhs.m_index;
1504 }
1505
1506 return *this;
1507 }
1508
operator =(IndexedQualifiedIdentifier && rhs)1509 IndexedQualifiedIdentifier& IndexedQualifiedIdentifier::operator=(IndexedQualifiedIdentifier&& rhs) Q_DECL_NOEXCEPT
1510 {
1511 if (shouldDoDUChainReferenceCounting(this)) {
1512 QMutexLocker lock(qualifiedidentifierRepository()->mutex());
1513 ifDebug(qCDebug(LANGUAGE) << "decreasing"; )
1514
1515 decrease(qualifiedidentifierRepository()->dynamicItemFromIndexSimple(m_index)->m_refCount, m_index);
1516 } else if (shouldDoDUChainReferenceCounting(&rhs)) {
1517 QMutexLocker lock(qualifiedidentifierRepository()->mutex());
1518 ifDebug(qCDebug(LANGUAGE) << "decreasing"; )
1519
1520 decrease(qualifiedidentifierRepository()->dynamicItemFromIndexSimple(rhs.m_index)->m_refCount, rhs.m_index);
1521 }
1522
1523 m_index = rhs.m_index;
1524 rhs.m_index = emptyConstantQualifiedIdentifierPrivateIndex();
1525
1526 if (shouldDoDUChainReferenceCounting(this) && !(shouldDoDUChainReferenceCounting(&rhs))) {
1527 QMutexLocker lock(qualifiedidentifierRepository()->mutex());
1528 ifDebug(qCDebug(LANGUAGE) << "increasing"; )
1529
1530 increase(qualifiedidentifierRepository()->dynamicItemFromIndexSimple(m_index)->m_refCount, m_index);
1531 }
1532
1533 return *this;
1534 }
1535
~IndexedQualifiedIdentifier()1536 IndexedQualifiedIdentifier::~IndexedQualifiedIdentifier()
1537 {
1538 ifDebug(qCDebug(LANGUAGE) << "(" << ++cnt << ")" << identifier().toString() << index; )
1539 if (shouldDoDUChainReferenceCounting(this)) {
1540 ifDebug(qCDebug(LANGUAGE) << index << "decreasing"; )
1541 QMutexLocker lock(qualifiedidentifierRepository()->mutex());
1542 decrease(qualifiedidentifierRepository()->dynamicItemFromIndexSimple(m_index)->m_refCount, m_index);
1543 }
1544 }
1545
operator ==(const IndexedQualifiedIdentifier & rhs) const1546 bool IndexedQualifiedIdentifier::operator==(const IndexedQualifiedIdentifier& rhs) const
1547 {
1548 return m_index == rhs.m_index;
1549 }
1550
operator ==(const QualifiedIdentifier & id) const1551 bool IndexedQualifiedIdentifier::operator==(const QualifiedIdentifier& id) const
1552 {
1553 return m_index == id.index();
1554 }
1555
identifier() const1556 QualifiedIdentifier IndexedQualifiedIdentifier::identifier() const
1557 {
1558 return QualifiedIdentifier(m_index);
1559 }
1560
operator QualifiedIdentifier() const1561 IndexedQualifiedIdentifier::operator QualifiedIdentifier() const
1562 {
1563 return QualifiedIdentifier(m_index);
1564 }
1565
initIdentifierRepository()1566 void initIdentifierRepository()
1567 {
1568 emptyConstantIdentifierPrivateIndex();
1569 emptyConstantIdentifierPrivate();
1570 emptyConstantQualifiedIdentifierPrivateIndex();
1571 emptyConstantQualifiedIdentifierPrivate();
1572 }
1573 }
1574
operator <<(QDebug s,const KDevelop::Identifier & identifier)1575 QDebug operator<<(QDebug s, const KDevelop::Identifier& identifier)
1576 {
1577 s.nospace() << identifier.toString();
1578 return s.space();
1579 }
1580
operator <<(QDebug s,const KDevelop::QualifiedIdentifier & identifier)1581 QDebug operator<<(QDebug s, const KDevelop::QualifiedIdentifier& identifier)
1582 {
1583 s.nospace() << identifier.toString();
1584 return s.space();
1585 }
1586