• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • kdevelop API Reference
  • KDE Home
  • Contact Us
 

kdevplatform/language/duchain

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

KDE's Doxygen guidelines are available online.

kdevplatform/language/duchain

Skip menu "kdevplatform/language/duchain"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Related Pages

kdevelop API Reference

Skip menu "kdevelop API Reference"
  • kdevplatform
  •   debugger
  •   documentation
  •   interfaces
  •   language
  •     assistant
  •     backgroundparser
  •     checks
  •     classmodel
  •     codecompletion
  •     codegen
  •     duchain
  •     editor
  •     highlighting
  •     interfaces
  •     util
  •   outputview
  •   project
  •   serialization
  •   shell
  •   sublime
  •   tests
  •   util
  •   vcs

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal