QtBase  v6.3.1
tst_qsharedpointer.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2021 The Qt Company Ltd.
4 ** Copyright (C) 2022 Intel Corporation.
5 ** Copyright (C) 2021 Klarälvdalens Datakonsult AB.
6 ** Contact: https://www.qt.io/licensing/
7 **
8 ** This file is part of the test suite of the Qt Toolkit.
9 **
10 ** $QT_BEGIN_LICENSE:GPL-EXCEPT$
11 ** Commercial License Usage
12 ** Licensees holding valid commercial Qt licenses may use this file in
13 ** accordance with the commercial license agreement provided with the
14 ** Software or, alternatively, in accordance with the terms contained in
15 ** a written agreement between you and The Qt Company. For licensing terms
16 ** and conditions see https://www.qt.io/terms-conditions. For further
17 ** information use the contact form at https://www.qt.io/contact-us.
18 **
19 ** GNU General Public License Usage
20 ** Alternatively, this file may be used under the terms of the GNU
21 ** General Public License version 3 as published by the Free Software
22 ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
23 ** included in the packaging of this file. Please review the following
24 ** information to ensure the GNU General Public License requirements will
25 ** be met: https://www.gnu.org/licenses/gpl-3.0.html.
26 **
27 ** $QT_END_LICENSE$
28 **
29 ****************************************************************************/
30 
31 #define QT_SHAREDPOINTER_TRACK_POINTERS
32 #include "qsharedpointer.h"
33 #include <QTest>
34 #include <QPointer>
35 #include <QRandomGenerator>
36 #include <QtCore/QHash>
37 #include <QtCore/QList>
38 #include <QtCore/QMap>
39 #include <QtCore/QThread>
40 #include <QtCore/private/qvolatile_p.h>
41 
42 #include "forwarddeclared.h"
43 #include "nontracked.h"
44 #include "wrapper.h"
45 
46 #include <array>
47 #include <memory>
48 #include <stdlib.h>
49 #include <time.h>
50 
51 #if defined(Q_OS_UNIX) && !defined(Q_OS_INTEGRITY)
52 #include <sys/resource.h>
53 #endif
54 
56 namespace QtSharedPointer {
57  Q_CORE_EXPORT void internalSafetyCheckCleanCheck();
58 }
60 
62 {
63  Q_OBJECT
64 
65 private slots:
66  void initTestCase();
67  void basics_data();
68  void basics();
69  void operators();
70  void nullptrOps();
71  void swap();
72  void moveSemantics();
73  void useOfForwardDeclared();
74  void memoryManagement();
75  void dropLastReferenceOfForwardDeclared();
76  void nonVirtualDestructors();
77  void lock();
78  void downCast();
79  void functionCallDownCast();
80  void upCast();
81  void qobjectWeakManagement();
82  void weakQObjectFromSharedPointer();
83  void objectCast();
84  void objectCastStdSharedPtr();
85  void differentPointers();
86  void virtualBaseDifferentPointers();
87 #ifndef QTEST_NO_RTTI
88  void dynamicCast();
89  void dynamicCastDifferentPointers();
90  void dynamicCastVirtualBase();
91  void dynamicCastFailure();
92  void dynamicCastFailureNoLeak();
93 #endif
94  void constCorrectness();
95  void customDeleter();
96  void lambdaCustomDeleter();
97  void customDeleterOnNullptr();
98  void creating();
99  void creatingCvQualified();
100  void creatingVariadic();
101  void creatingQObject();
102  void mixTrackingPointerCode();
103  void reentrancyWhileDestructing();
104  void map();
105  void hash();
106  void qvariantCast();
107  void sharedFromThis();
108 
109  void constructorThrow();
110  void overloads();
111 
112  void threadStressTest_data();
113  void threadStressTest();
114  void validConstructs();
115 #if 0
116  void invalidConstructs_data();
117  void invalidConstructs();
118 #endif
119 
120  // let invalidConstructs be the last test, because it's the slowest;
121  // add new tests above this block
122 public slots:
123  void cleanup() { safetyCheck(); }
124 
125 public:
126  inline void safetyCheck()
127  {
128 #ifdef QT_BUILD_INTERNAL
130 #endif
131  }
132 };
133 
134 void tst_QSharedPointer::initTestCase()
135 {
136 #if defined(Q_OS_UNIX) && !defined(Q_OS_INTEGRITY)
137  // The tests create a lot of threads, which require file descriptors. On systems like
138  // OS X low defaults such as 256 as the limit for the number of simultaneously
139  // open files is not sufficient.
140  struct rlimit numFiles;
141  if (getrlimit(RLIMIT_NOFILE, &numFiles) == 0 && numFiles.rlim_cur < 1024) {
142  numFiles.rlim_cur = qMin(rlim_t(1024), numFiles.rlim_max);
143  setrlimit(RLIMIT_NOFILE, &numFiles);
144  }
145 #endif
146 }
147 
148 template<typename T> static inline
150 {
151  // access d-pointer:
152  struct Dummy {
153  void* value;
155  };
156  // sanity checks:
157  static_assert(sizeof(QSharedPointer<T>) == sizeof(Dummy));
158  Q_ASSERT(static_cast<const Dummy*>(static_cast<const void*>(&b))->value == b.data());
159  return static_cast<const Dummy*>(static_cast<const void*>(&b))->data;
160 }
161 
162 class Data
163 {
164 public:
165  static int destructorCounter;
166  static int generationCounter;
168 
170  { }
171 
172  virtual ~Data()
173  {
174  if (generation <= 0)
175  qFatal("tst_qsharedpointer: Double deletion!");
176  generation = 0;
178  }
179 
180  void doDelete()
181  {
182  delete this;
183  }
184 
185  bool alsoDelete()
186  {
187  doDelete();
188  return true;
189  }
190 
191  virtual void virtualDelete()
192  {
193  delete this;
194  }
195 
196  virtual int classLevel() { return 1; }
197 };
200 
202 {
203  int i;
206 };
207 
209 {
210  int &i;
212 };
213 
215 {
216  void *ptr;
217  int i;
218  NoDefaultConstructor2(void *ptr, int i) : ptr(ptr), i(i) {}
219 };
220 
222 {
224  int i;
226 };
227 
229 {
231  int i;
233  NoDefaultConstructorConstRef2(const QByteArray &ba, int i = 42) : str(QString::fromLatin1(ba)), i(i) {}
234 };
235 
237 {
238  int &i;
240 };
241 
243 {
244  std::unique_ptr<int> i;
245  NoDefaultConstructorRRef2(std::unique_ptr<int> &&i) : i(std::move(i)) {}
246 };
247 
248 void tst_QSharedPointer::basics_data()
249 {
250  QTest::addColumn<bool>("isNull");
251  QTest::newRow("null") << true;
252  QTest::newRow("non-null") << false;
253 }
254 
255 void tst_QSharedPointer::basics()
256 {
257  {
260 
261  QCOMPARE(sizeof(ptr), 2*sizeof(void*));
262  QCOMPARE(sizeof(weakref), 2*sizeof(void*));
263  }
264 
265  {
268 
269  QCOMPARE(sizeof(ptr), 2*sizeof(void*));
270  QCOMPARE(sizeof(weakref), 2*sizeof(void*));
271  }
272 
273  QFETCH(bool, isNull);
274  Data *aData = 0;
275  if (!isNull)
276  aData = new Data;
277  Data *otherData = new Data;
278  QSharedPointer<Data> ptr(aData);
279 
280  {
281  // basic self tests
282  QCOMPARE(ptr.isNull(), isNull);
283  QCOMPARE(bool(ptr), !isNull);
284  QCOMPARE(!ptr, isNull);
285 
286  QCOMPARE(ptr.data(), aData);
287  QCOMPARE(ptr.get(), aData);
288  QCOMPARE(ptr.operator->(), aData);
289  if (!isNull) {
290  Data &dataReference = *ptr;
291  QCOMPARE(&dataReference, aData);
292  }
293 
294  QVERIFY(ptr == aData);
295  QVERIFY(!(ptr != aData));
296  QVERIFY(aData == ptr);
297  QVERIFY(!(aData != ptr));
298 
299  QVERIFY(ptr != otherData);
300  QVERIFY(otherData != ptr);
301  QVERIFY(! (ptr == otherData));
302  QVERIFY(! (otherData == ptr));
303  }
304  QVERIFY(!refCountData(ptr) || refCountData(ptr)->weakref.loadRelaxed() == 1);
305  QVERIFY(!refCountData(ptr) || refCountData(ptr)->strongref.loadRelaxed() == 1);
306 
307  {
308  // create another object:
309  QSharedPointer<Data> otherCopy(otherData);
310  QVERIFY(ptr != otherCopy);
311  QVERIFY(otherCopy != ptr);
312  QVERIFY(! (ptr == otherCopy));
313  QVERIFY(! (otherCopy == ptr));
314 
315  // otherData is deleted here
316  }
317  QVERIFY(!refCountData(ptr) || refCountData(ptr)->weakref.loadRelaxed() == 1);
318  QVERIFY(!refCountData(ptr) || refCountData(ptr)->strongref.loadRelaxed() == 1);
319 
320  {
321  // create a copy:
322  QSharedPointer<Data> copy(ptr);
323  QVERIFY(copy == ptr);
324  QVERIFY(ptr == copy);
325  QVERIFY(! (copy != ptr));
326  QVERIFY(! (ptr != copy));
327  QCOMPARE(copy, ptr);
328  QCOMPARE(ptr, copy);
329 
330  QCOMPARE(copy.isNull(), isNull);
331  QCOMPARE(copy.data(), aData);
332  QCOMPARE(copy.get(), aData);
333  QVERIFY(copy == aData);
334  }
335  QVERIFY(!refCountData(ptr) || refCountData(ptr)->weakref.loadRelaxed() == 1);
336  QVERIFY(!refCountData(ptr) || refCountData(ptr)->strongref.loadRelaxed() == 1);
337 
338  {
339  // create a weak reference:
340  QWeakPointer<Data> weak(ptr);
341  QCOMPARE(weak.isNull(), isNull);
342  QCOMPARE(!weak, isNull);
343  QCOMPARE(bool(weak), !isNull);
344 
345  QCOMPARE(weak.isNull(), (weak == nullptr));
346  QCOMPARE(weak.isNull(), (nullptr == weak));
347  QCOMPARE(!weak.isNull(), (weak != nullptr));
348  QCOMPARE(!weak.isNull(), (nullptr != weak));
349 
350  QVERIFY(ptr == weak);
351  QVERIFY(weak == ptr);
352  QVERIFY(! (ptr != weak));
353  QVERIFY(! (weak != ptr));
354 
355  // create another reference:
356  QWeakPointer<Data> weak2(weak);
357  QCOMPARE(weak2.isNull(), isNull);
358  QCOMPARE(!weak2, isNull);
359  QCOMPARE(bool(weak2), !isNull);
360 
361  QVERIFY(weak2 == weak);
362  QVERIFY(weak == weak2);
363  QVERIFY(! (weak2 != weak));
364  QVERIFY(! (weak != weak2));
365 
366  // create a strong reference back:
368  QVERIFY(strong == weak);
369  QVERIFY(strong == ptr);
370  QCOMPARE(strong.data(), aData);
371  QCOMPARE(strong.get(), aData);
372  }
373  QVERIFY(!refCountData(ptr) || refCountData(ptr)->weakref.loadRelaxed() == 1);
374  QVERIFY(!refCountData(ptr) || refCountData(ptr)->strongref.loadRelaxed() == 1);
375 
376  // aData is deleted here
377 }
378 
379 void tst_QSharedPointer::operators()
380 {
382  QSharedPointer<char> p2(new char);
383  qptrdiff diff = p2.data() - p1.data();
384  QVERIFY(p1.data() != p2.data());
385  QVERIFY(p1.get() != p2.get());
386  QVERIFY(diff != 0);
387 
388  // operator-
389  QCOMPARE(p2 - p1.data(), diff);
390  QCOMPARE(p2 - p1.get(), diff);
391  QCOMPARE(p2.data() - p1, diff);
392  QCOMPARE(p2.get() - p1, diff);
393  QCOMPARE(p2 - p1, diff);
394  QCOMPARE(p1 - p2, -diff);
395  QCOMPARE(p1 - p1, qptrdiff(0));
396  QCOMPARE(p2 - p2, qptrdiff(0));
397 
398  // operator<
399  QVERIFY(p1 < p2.data());
400  QVERIFY(p1 < p2.get());
401  QVERIFY(p1.data() < p2);
402  QVERIFY(p1.get() < p2);
403  QVERIFY(p1 < p2);
404  QVERIFY(!(p2 < p1));
405  QVERIFY(!(p2 < p2));
406  QVERIFY(!(p1 < p1));
407 
408  // qHash
409  QCOMPARE(qHash(p1), qHash(p1.data()));
410  QCOMPARE(qHash(p1), qHash(p1.get()));
411  QCOMPARE(qHash(p2), qHash(p2.data()));
412  QCOMPARE(qHash(p2), qHash(p2.get()));
413 }
414 
415 void tst_QSharedPointer::nullptrOps()
416 {
417  QSharedPointer<char> p1(nullptr);
418  QSharedPointer<char> p2 = nullptr;
420 
421  QVERIFY(p1 == null);
422  QVERIFY(p1 == nullptr);
423  QVERIFY(nullptr == p1);
424  QVERIFY(!p1);
425  QVERIFY(!p1.data());
426  QVERIFY(!p1.get());
427  QVERIFY(p2 == null);
428  QVERIFY(p2 == nullptr);
429  QVERIFY(nullptr == p2);
430  QVERIFY(!p2);
431  QVERIFY(!p2.data());
432  QVERIFY(!p2.get());
433  QVERIFY(p1 == p2);
434 
435  QWeakPointer<char> wp1 = p1;
436  QVERIFY(wp1 == nullptr);
437  QVERIFY(nullptr == wp1);
438  QCOMPARE(wp1, nullptr);
439  QCOMPARE(nullptr, wp1);
440 
442  QVERIFY(p3 == p1);
443  QVERIFY(p3 == null);
444  QVERIFY(p3 == nullptr);
445  QVERIFY(nullptr == p3);
446  QVERIFY(!p3.data());
447  QVERIFY(!p3.get());
448 
449  p3 = nullptr;
450 
451  // check for non-ambiguity
452  QSharedPointer<char> p1_zero(0);
453  QSharedPointer<char> p2_zero = 0;
454 
455  p3 = 0;
456 
457  QSharedPointer<char> p4(new char);
458  QVERIFY(p4);
459  QVERIFY(p4.data());
460  QVERIFY(p4.get());
461  QVERIFY(p4 != nullptr);
462  QVERIFY(nullptr != p4);
463  QVERIFY(p4 != p1);
464  QVERIFY(p4 != p2);
465  QVERIFY(p4 != null);
466  QVERIFY(p4 != p3);
467 
468  QWeakPointer<char> wp2 = p4;
469  QVERIFY(wp2 != nullptr);
470  QVERIFY(nullptr != wp2);
471 }
472 
473 void tst_QSharedPointer::swap()
474 {
475  QSharedPointer<int> p1, p2(new int(42)), control = p2;
476  QVERIFY(p1 != control);
477  QVERIFY(p1.isNull());
478  QVERIFY(p2 == control);
479  QVERIFY(!p2.isNull());
480  QVERIFY(*p2 == 42);
481 
482  p1.swap(p2);
483  QVERIFY(p1 == control);
484  QVERIFY(!p1.isNull());
485  QVERIFY(p2 != control);
486  QVERIFY(p2.isNull());
487  QVERIFY(*p1 == 42);
488 
489  p1.swap(p2);
490  QVERIFY(p1 != control);
491  QVERIFY(p1.isNull());
492  QVERIFY(p2 == control);
493  QVERIFY(!p2.isNull());
494  QVERIFY(*p2 == 42);
495 
496  qSwap(p1, p2);
497  QVERIFY(p1 == control);
498  QVERIFY(!p1.isNull());
499  QVERIFY(p2 != control);
500  QVERIFY(p2.isNull());
501  QVERIFY(*p1 == 42);
502 
503  QWeakPointer<int> w1, w2 = control;
504 
505  QVERIFY(w1.isNull());
506  QVERIFY(!w2.isNull());
507  QVERIFY(w2.lock() == control);
508  QVERIFY(!w1.lock());
509 
510  w1.swap(w2);
511  QVERIFY(w2.isNull());
512  QVERIFY(!w1.isNull());
513  QVERIFY(w1.lock() == control);
514  QVERIFY(!w2.lock());
515 
516  qSwap(w1, w2);
517  QVERIFY(w1.isNull());
518  QVERIFY(w2.lock() == control);
519 
520  p1.reset();
521  p2.reset();
522  control.reset();
523 
524  QVERIFY(w1.isNull());
525  QVERIFY(w2.isNull());
526 }
527 
528 void tst_QSharedPointer::moveSemantics()
529 {
530  QSharedPointer<int> p1, p2(new int(42)), control = p2;
531  QVERIFY(p1 != control);
532  QVERIFY(p1.isNull());
533  QVERIFY(p2 == control);
534  QVERIFY(!p2.isNull());
535  QVERIFY(*p2 == 42);
536 
537  // move assignment
538  p1 = std::move(p2);
539  QVERIFY(p1 == control);
540  QVERIFY(!p1.isNull());
541  QVERIFY(p2 != control);
542  QVERIFY(p2.isNull());
543  QVERIFY(*p1 == 42);
544 
545  // move construction
546  QSharedPointer<int> p3 = std::move(p1);
547  QVERIFY(p1 != control);
548  QVERIFY(p1.isNull());
549  QVERIFY(p3 == control);
550  QVERIFY(!p3.isNull());
551  QVERIFY(*p3 == 42);
552 
553  QWeakPointer<int> w1, w2 = control;
554 
555  QVERIFY(w1.isNull());
556  QVERIFY(!w2.isNull());
557  QVERIFY(w2.lock() == control);
558  QVERIFY(!w1.lock());
559 
560  // move assignment
561  w1 = std::move(w2);
562  QVERIFY(w2.isNull());
563  QVERIFY(!w1.isNull());
564  QVERIFY(w1.lock() == control);
565  QVERIFY(!w2.lock());
566 
567  // move construction
568  QWeakPointer<int> w3 = std::move(w1);
569  QVERIFY(w1.isNull());
570  QVERIFY(!w3.isNull());
571  QVERIFY(w3.lock() == control);
572  QVERIFY(!w1.lock());
573 
574  p1.reset();
575  p2.reset();
576  p3.reset();
577  control.reset();
578 
579  QVERIFY(w1.isNull());
580  QVERIFY(w2.isNull());
581  QVERIFY(w3.isNull());
582 }
583 
584 void tst_QSharedPointer::useOfForwardDeclared()
585 {
586  // this just a compile test: use the forward-declared class
588 
589  // copying should work, too:
591 
592  // and assignment:
594  sp3 = sp;
595 
596  // move assignment:
598  sp4 = std::move(sp);
599 
600  // and move constuction:
601  QSharedPointer<ForwardDeclared> sp5 = std::move(sp2);
602 
603  // swapping:
604  sp4.swap(sp3);
605  qSwap(sp4, sp3);
606 
607  // and, of course, destruction
608 }
609 
610 
611 void tst_QSharedPointer::memoryManagement()
612 {
614 QT_WARNING_DISABLE_CLANG("-Wself-assign-overloaded")
615 
616  int generation = Data::generationCounter + 1;
617  int destructorCounter = Data::destructorCounter;
618 
620  QCOMPARE(ptr->generation, generation);
621  QCOMPARE(Data::destructorCounter, destructorCounter);
622  QCOMPARE(Data::generationCounter, generation);
623 
624  ptr = ptr;
625  QCOMPARE(ptr->generation, generation);
626  QCOMPARE(Data::destructorCounter, destructorCounter);
627  QCOMPARE(Data::generationCounter, generation);
628 
629  {
630  QSharedPointer<Data> copy = ptr;
631  QCOMPARE(ptr->generation, generation);
632  QCOMPARE(copy->generation, generation);
633 
634  // copy goes out of scope, ptr continues
635  }
636  QCOMPARE(ptr->generation, generation);
637  QCOMPARE(Data::destructorCounter, destructorCounter);
638  QCOMPARE(Data::generationCounter, generation);
639 
640  {
641  QWeakPointer<Data> weak = ptr;
642  weak = ptr;
643  QCOMPARE(ptr->generation, generation);
644  QCOMPARE(Data::destructorCounter, destructorCounter);
645  QCOMPARE(Data::generationCounter, generation);
646 
647  weak = weak;
648  QCOMPARE(ptr->generation, generation);
649  QCOMPARE(Data::destructorCounter, destructorCounter);
650  QCOMPARE(Data::generationCounter, generation);
651 
653  QCOMPARE(ptr->generation, generation);
654  QCOMPARE(strong->generation, generation);
655  QCOMPARE(Data::destructorCounter, destructorCounter);
656  QCOMPARE(Data::generationCounter, generation);
657 
658  // both weak and strong go out of scope
659  }
660  QCOMPARE(ptr->generation, generation);
661  QCOMPARE(Data::destructorCounter, destructorCounter);
662  QCOMPARE(Data::generationCounter, generation);
663 
664  QWeakPointer<Data> weak = ptr;
665  ptr = QSharedPointer<Data>();
666 
667  // destructor must have been called
668  QCOMPARE(Data::destructorCounter, destructorCounter + 1);
669  QVERIFY(ptr.isNull());
670  QVERIFY(weak.isNull());
671 
672  // if we create a strong pointer from the weak, it must still be null
673  ptr = weak;
674  QVERIFY(ptr.isNull());
675  QVERIFY(ptr == 0);
676  QCOMPARE(ptr.data(), (Data*)0);
678 }
679 
680 void tst_QSharedPointer::dropLastReferenceOfForwardDeclared()
681 {
682  // pointer to shared-pointer is weird, but we need to do it so that
683  // we can drop the last reference in a different .cpp than where it was created
685  delete forwardPointer();
687 }
688 
689 // NVD for "non-virtual destructor"
690 struct NVDData
691 {
692  static int destructorCounter;
694 
695  int dummy;
696 };
698 
700 {
701  static int destructorCounter;
703 };
705 
706 void tst_QSharedPointer::nonVirtualDestructors()
707 {
709  {
711  }
714 
716  {
718  }
721 
723  {
726  bptr = ptr;
727  }
730 
732  {
734  }
737 }
738 
739 void tst_QSharedPointer::lock()
740 {
742  QVERIFY(sp);
743  QWeakPointer<int> wp = sp;
744  QVERIFY(sp == wp);
745  QVERIFY(sp == wp.lock());
746  QVERIFY(sp == wp.toStrongRef());
747 
748  sp.reset();
749  QVERIFY(!wp);
750  QVERIFY(sp != wp); // this is why op(shared_ptr, weak_ptr) is a bad idea (apart from MT races)...
751  QVERIFY(sp == wp.lock());
752  QVERIFY(sp == wp.toStrongRef());
753 }
754 
755 class DerivedData: public Data
756 {
757 public:
759  int moreData;
762 
763  void virtualDelete() override
764  {
765  delete this;
766  }
767 
768  int classLevel() override { return 2; }
769 };
771 
772 class Stuffing
773 {
774 public:
775  char buffer[16];
776  Stuffing() { for (uint i = 0; i < sizeof buffer; ++i) buffer[i] = 16 - i; }
777  virtual ~Stuffing() { }
778 };
779 
780 class DiffPtrDerivedData: public Stuffing, public Data
781 {
782 public:
783  int classLevel() override { return 3; }
784 };
785 
786 class VirtualDerived: virtual public Data
787 {
788 public:
789  int moreData;
790 
791  VirtualDerived() : moreData(0xc0ffee) { }
792  int classLevel() override { return 4; }
793 };
794 
795 void tst_QSharedPointer::downCast()
796 {
797  {
798  // copy construction
800  QSharedPointer<DerivedData> copy = ptr;
801  QSharedPointer<Data> baseptr = qSharedPointerCast<Data>(ptr);
803  QWeakPointer<DerivedData> weak = ptr;
804  QWeakPointer<Data> baseweak = qSharedPointerCast<Data>(ptr);
805  QWeakPointer<Data> baseweak2 = qSharedPointerCast<Data>(weak);
806 
807  QVERIFY(ptr == baseptr);
808  QVERIFY(baseptr == ptr);
809  QVERIFY(! (ptr != baseptr));
810  QVERIFY(! (baseptr != ptr));
811 
812  QVERIFY(ptr != other);
813  QVERIFY(other != ptr);
814  QVERIFY(! (ptr == other));
815  QVERIFY(! (other == ptr));
816 
817  // copy assignments
818  baseptr = qSharedPointerCast<Data>(ptr);
819  baseweak = qSharedPointerCast<Data>(ptr);
820  baseweak2 = baseweak;
821 
822  // move assignments (these don't actually move)
823  baseptr = qSharedPointerCast<Data>(std::move(ptr));
824  ptr = copy;
825  baseweak = qSharedPointerCast<Data>(std::move(ptr));
826  ptr = copy;
827  baseweak2 = qSharedPointerCast<Data>(std::move(baseweak));
828 
829  // move construction (these don't actually move)
830  ptr = copy;
831  QSharedPointer<Data> ptr3(qSharedPointerCast<Data>(std::move(ptr)));
832  ptr = copy;
833  QWeakPointer<Data> baseweak3(qSharedPointerCast<Data>(std::move(ptr)));
834  ptr = copy;
835  QWeakPointer<Data> baseweak4(qSharedPointerCast<Data>(std::move(weak)));
836  }
837 
838  {
839  // copy construction
841  QSharedPointer<DerivedData> copy = ptr;
842  QSharedPointer<Data> baseptr = ptr;
843  QWeakPointer<DerivedData> weak = ptr;
844  QWeakPointer<Data> baseweak = ptr;
845  QWeakPointer<Data> baseweak2 = weak;
846 
847  // copy assignments
848  baseptr = ptr;
849  baseweak = ptr;
850  baseweak2 = weak;
851 
852  // move assignments (only the QSharedPointer-QSharedPointer actually moves)
853  baseweak = std::move(ptr);
854  baseweak2 = std::move(weak);
855  ptr = copy;
856  baseptr = std::move(ptr);
857 
858  // move construction (only the QSharedPointer-QSharedPointer actually moves)
859  ptr = copy;
860  QWeakPointer<Data> baseweak3(std::move(ptr));
861  ptr = copy;
862  QWeakPointer<Data> baseweak4(std::move(weak));
863  ptr = copy;
864  QSharedPointer<Data> baseptr2(std::move(ptr));
865  }
866 
867  int destructorCount;
868  destructorCount = DerivedData::derivedDestructorCounter;
869  {
870  QSharedPointer<Data> baseptr;
871  {
873  baseptr = ptr;
874  QVERIFY(baseptr == ptr);
875  }
876  }
877  QCOMPARE(DerivedData::derivedDestructorCounter, destructorCount + 1);
878 
879  destructorCount = DerivedData::derivedDestructorCounter;
880  {
882  QWeakPointer<Data> baseptr = ptr;
883  QVERIFY(baseptr == ptr);
884 
886  QVERIFY(baseptr.isNull());
887  }
888  QCOMPARE(DerivedData::derivedDestructorCounter, destructorCount + 1);
889 
890  destructorCount = DerivedData::derivedDestructorCounter;
891  {
893  QWeakPointer<DerivedData> weakptr(ptr);
894 
895  QSharedPointer<Data> baseptr = weakptr;
896  QVERIFY(baseptr == ptr);
897  QWeakPointer<Data> baseweakptr = weakptr;
898  QVERIFY(baseweakptr == ptr);
899  }
900  QCOMPARE(DerivedData::derivedDestructorCounter, destructorCount + 1);
901 }
902 
905 void tst_QSharedPointer::functionCallDownCast()
906 {
910 }
911 
912 void tst_QSharedPointer::upCast()
913 {
915 
916  {
917  QSharedPointer<DerivedData> derivedptr = qSharedPointerCast<DerivedData>(baseptr);
918  QVERIFY(baseptr == derivedptr);
919  QCOMPARE(static_cast<Data *>(derivedptr.data()), baseptr.data());
920  }
921  QCOMPARE(int(refCountData(baseptr)->weakref.loadRelaxed()), 1);
922  QCOMPARE(int(refCountData(baseptr)->strongref.loadRelaxed()), 1);
923 
924  {
925  QWeakPointer<DerivedData> derivedptr = qWeakPointerCast<DerivedData>(baseptr);
926  QVERIFY(baseptr == derivedptr);
927  }
928  QCOMPARE(int(refCountData(baseptr)->weakref.loadRelaxed()), 1);
929  QCOMPARE(int(refCountData(baseptr)->strongref.loadRelaxed()), 1);
930 
931  {
932  QWeakPointer<Data> weakptr = baseptr;
933  QSharedPointer<DerivedData> derivedptr = qSharedPointerCast<DerivedData>(weakptr);
934  QVERIFY(baseptr == derivedptr);
935  QCOMPARE(static_cast<Data *>(derivedptr.data()), baseptr.data());
936  }
937  QCOMPARE(int(refCountData(baseptr)->weakref.loadRelaxed()), 1);
938  QCOMPARE(int(refCountData(baseptr)->strongref.loadRelaxed()), 1);
939 
940  {
941  QSharedPointer<DerivedData> derivedptr = baseptr.staticCast<DerivedData>();
942  QVERIFY(baseptr == derivedptr);
943  QCOMPARE(static_cast<Data *>(derivedptr.data()), baseptr.data());
944  }
945  QCOMPARE(int(refCountData(baseptr)->weakref.loadRelaxed()), 1);
946  QCOMPARE(int(refCountData(baseptr)->strongref.loadRelaxed()), 1);
947 }
948 
949 class OtherObject: public QObject
950 {
951  Q_OBJECT
952 };
953 
954 void tst_QSharedPointer::qobjectWeakManagement()
955 {
956  {
958  weak = QWeakPointer<QObject>();
959  QVERIFY(weak.isNull());
960  QVERIFY(weak.toStrongRef().isNull());
961  }
962 
963  {
964  QObject *obj = new QObject;
966  QWeakPointer<QObject> weak(shared);
967  QVERIFY(!weak.isNull());
968  QVERIFY(weak.toStrongRef() == obj);
969 
970  // now delete
971  shared.reset();
972  QVERIFY(weak.isNull());
973  }
974  safetyCheck();
975 
976  {
977  // same, bit with operator=
978  QObject *obj = new QObject;
981  weak = shared;
982  QVERIFY(!weak.isNull());
983  QVERIFY(weak.toStrongRef() == obj);
984 
985  // now delete
986  shared.reset();
987  QVERIFY(weak.isNull());
988  }
989  safetyCheck();
990 
991  {
992  // with two QWeakPointers
993  QObject *obj = new QObject;
995  QWeakPointer<QObject> weak(shared);
996 
997  {
998  QWeakPointer<QObject> weak2(shared);
999  QVERIFY(!weak2.isNull());
1000  QVERIFY(weak == weak2);
1001  }
1002  QVERIFY(!weak.isNull());
1003 
1004  shared.reset();
1005  QVERIFY(weak.isNull());
1006  }
1007  safetyCheck();
1008 
1009  {
1010  // same, but delete the pointer while two QWeakPointers exist
1011  QObject *obj = new QObject;
1012  QSharedPointer<QObject> shared(obj);
1013  QWeakPointer<QObject> weak(shared);
1014 
1015  {
1016  QWeakPointer<QObject> weak2(shared);
1017  QVERIFY(!weak2.isNull());
1018 
1019  shared.reset();
1020  QVERIFY(weak.isNull());
1021  QVERIFY(weak2.isNull());
1022  }
1023  QVERIFY(weak.isNull());
1024  }
1025  safetyCheck();
1026 }
1027 
1028 void tst_QSharedPointer::weakQObjectFromSharedPointer()
1029 {
1030  {
1031  QSharedPointer<QObject> shared(new QObject);
1032  QWeakPointer<QObject> weak = shared;
1033  QVERIFY(!weak.isNull());
1034 
1035  // delete:
1036  shared.clear();
1037  QVERIFY(weak.isNull());
1038  }
1039 }
1040 
1041 void tst_QSharedPointer::objectCast()
1042 {
1043  {
1044  OtherObject *data = new OtherObject;
1046  QVERIFY(baseptr == data);
1047  QVERIFY(data == baseptr);
1048 
1049  // perform object cast
1050  QSharedPointer<OtherObject> ptr = qSharedPointerObjectCast<OtherObject>(baseptr);
1051  QVERIFY(!ptr.isNull());
1052  QCOMPARE(ptr.data(), data);
1053  QVERIFY(ptr == data);
1054 
1055  // again:
1056  ptr = baseptr.objectCast<OtherObject>();
1057  QVERIFY(ptr == data);
1058 
1059  // again:
1060  ptr = qobject_cast<OtherObject *>(baseptr);
1061  QVERIFY(ptr == data);
1062 
1063  // again:
1064  ptr = qobject_cast<QSharedPointer<OtherObject> >(baseptr);
1065  QVERIFY(ptr == data);
1066  }
1067  safetyCheck();
1068 
1069  {
1070  const OtherObject *data = new OtherObject;
1072  QVERIFY(baseptr == data);
1073  QVERIFY(data == baseptr);
1074 
1075  // perform object cast
1076  QSharedPointer<const OtherObject> ptr = qSharedPointerObjectCast<const OtherObject>(baseptr);
1077  QVERIFY(!ptr.isNull());
1078  QCOMPARE(ptr.data(), data);
1079  QVERIFY(ptr == data);
1080 
1081  // again:
1082  ptr = baseptr.objectCast<const OtherObject>();
1083  QVERIFY(ptr == data);
1084 
1085  // again:
1086  ptr = qobject_cast<const OtherObject *>(baseptr);
1087  QVERIFY(ptr == data);
1088 
1089  // again:
1090  ptr = qobject_cast<QSharedPointer<const OtherObject> >(baseptr);
1091  QVERIFY(ptr == data);
1092  }
1093  safetyCheck();
1094 
1095  {
1096  OtherObject *data = new OtherObject;
1098  QWeakPointer<QObject> weakptr = ptr;
1099 
1100  {
1101  // perform object cast
1102  QSharedPointer<OtherObject> otherptr = qSharedPointerObjectCast<OtherObject>(weakptr);
1103  QVERIFY(otherptr == ptr);
1104 
1105  // again:
1106  otherptr = qobject_cast<OtherObject *>(weakptr);
1107  QVERIFY(otherptr == ptr);
1108 
1109  // again:
1110  otherptr = qobject_cast<QSharedPointer<OtherObject> >(weakptr);
1111  QVERIFY(otherptr == ptr);
1112  }
1113 
1114  // drop the reference:
1115  ptr.clear();
1116  QVERIFY(ptr.isNull());
1117  QVERIFY(weakptr.toStrongRef().isNull());
1118  QVERIFY(weakptr.lock().isNull());
1119 
1120  // verify that the object casts fail without crash
1121  QSharedPointer<OtherObject> otherptr = qSharedPointerObjectCast<OtherObject>(weakptr);
1122  QVERIFY(otherptr.isNull());
1123 
1124  // again:
1125  otherptr = qobject_cast<OtherObject *>(weakptr);
1126  QVERIFY(otherptr.isNull());
1127 
1128  // again:
1129  otherptr = qobject_cast<QSharedPointer<OtherObject> >(weakptr);
1130  QVERIFY(otherptr.isNull());
1131  }
1132  safetyCheck();
1133 }
1134 
1135 
1136 void tst_QSharedPointer::objectCastStdSharedPtr()
1137 {
1138  {
1139  OtherObject *data = new OtherObject;
1140  std::shared_ptr<QObject> baseptr = std::shared_ptr<QObject>(data);
1141  QVERIFY(baseptr.get() == data);
1142 
1143  // perform successful object cast
1144  std::shared_ptr<OtherObject> ptr = qobject_pointer_cast<OtherObject>(baseptr);
1145  QVERIFY(ptr.get());
1146  QVERIFY(ptr.get() == data);
1147 
1148  QVERIFY(baseptr.get() == data);
1149  }
1150 
1151  {
1152  OtherObject *data = new OtherObject;
1153  std::shared_ptr<QObject> baseptr = std::shared_ptr<QObject>(data);
1154  QVERIFY(baseptr.get() == data);
1155 
1156  // perform successful object cast
1157  std::shared_ptr<OtherObject> ptr = qobject_pointer_cast<OtherObject>(std::move(baseptr));
1158  QVERIFY(ptr.get());
1159  QVERIFY(ptr.get() == data);
1160 
1161  QVERIFY(!baseptr.get());
1162  }
1163 
1164  {
1165  QObject *data = new QObject;
1166  std::shared_ptr<QObject> baseptr = std::shared_ptr<QObject>(data);
1167  QVERIFY(baseptr.get() == data);
1168 
1169  // perform unsuccessful object cast
1170  std::shared_ptr<OtherObject> ptr = qobject_pointer_cast<OtherObject>(baseptr);
1171  QVERIFY(!ptr.get());
1172 
1173  QVERIFY(baseptr.get() == data);
1174  }
1175 
1176  {
1177  QObject *data = new QObject;
1178  std::shared_ptr<QObject> baseptr = std::shared_ptr<QObject>(data);
1179  QVERIFY(baseptr.get() == data);
1180 
1181  // perform unsuccessful object cast
1182  std::shared_ptr<OtherObject> ptr = qobject_pointer_cast<OtherObject>(std::move(baseptr));
1183  QVERIFY(!ptr.get());
1184 
1185  QVERIFY(baseptr.get() == data);
1186  }
1187 }
1188 
1189 void tst_QSharedPointer::differentPointers()
1190 {
1191  {
1193  Data *aBase = aData;
1194 
1195  // ensure that this compiler isn't broken
1196  if (*reinterpret_cast<quintptr *>(&aData) == *reinterpret_cast<quintptr *>(&aBase))
1197  QFAIL("Something went very wrong -- we couldn't create two different pointers to the same object");
1198  if (aData != aBase || aBase != aData)
1199  QSKIP("Broken compiler");
1200 
1202  QSharedPointer<Data> baseptr = qSharedPointerCast<Data>(ptr);
1203  qDebug("naked: orig: %p; base: %p (%s) -- QSharedPointer: orig: %p; base %p (%s) -- result: %s",
1204  aData, aBase, aData == aBase ? "equal" : "not equal",
1205  ptr.data(), baseptr.data(), ptr.data() == baseptr.data() ? "equal" : "not equal",
1206  baseptr.data() == aData ? "equal" : "not equal");
1207 
1208  QVERIFY(ptr.data() == baseptr.data());
1209  QVERIFY(baseptr.data() == ptr.data());
1210  QVERIFY(ptr == baseptr);
1211  QVERIFY(baseptr == ptr);
1212 
1213  QVERIFY(ptr.data() == aBase);
1214  QVERIFY(aBase == ptr.data());
1215  QVERIFY(ptr.data() == aData);
1216  QVERIFY(aData == ptr.data());
1217 
1218  QVERIFY(ptr == aBase);
1219  QVERIFY(aBase == ptr);
1220  QVERIFY(ptr == aData);
1221  QVERIFY(aData == ptr);
1222 
1223  QVERIFY(baseptr.data() == aBase);
1224  QVERIFY(aBase == baseptr.data());
1225  QVERIFY(baseptr == aBase);
1226  QVERIFY(aBase == baseptr);
1227 
1228  QVERIFY(baseptr.data() == aData);
1229  QVERIFY(aData == baseptr.data());
1230  QVERIFY(baseptr == aData);
1231  QVERIFY(aData == baseptr);
1232  }
1233  safetyCheck();
1234 
1235  {
1237  Data *aBase = aData;
1238  QVERIFY(aData == aBase);
1239  QVERIFY(*reinterpret_cast<quintptr *>(&aData) != *reinterpret_cast<quintptr *>(&aBase));
1240 
1241  QSharedPointer<Data> baseptr = QSharedPointer<Data>(aData);
1242  QSharedPointer<DiffPtrDerivedData> ptr = qSharedPointerCast<DiffPtrDerivedData>(baseptr);
1243  QVERIFY(ptr == baseptr);
1244  QVERIFY(ptr.data() == baseptr.data());
1245  QVERIFY(ptr == aBase);
1246  QVERIFY(baseptr == aData);
1247  }
1248  safetyCheck();
1249 
1250  {
1252  Data *aBase = aData;
1253  QVERIFY(aData == aBase);
1254  QVERIFY(*reinterpret_cast<quintptr *>(&aData) != *reinterpret_cast<quintptr *>(&aBase));
1255 
1257  QSharedPointer<Data> baseptr = ptr;
1258  QVERIFY(ptr == baseptr);
1259  QVERIFY(ptr.data() == baseptr.data());
1260  QVERIFY(ptr == aBase);
1261  QVERIFY(ptr == aData);
1262  QVERIFY(baseptr == aData);
1263  QVERIFY(baseptr == aBase);
1264  }
1265  safetyCheck();
1266 }
1267 
1268 void tst_QSharedPointer::virtualBaseDifferentPointers()
1269 {
1270  {
1271  VirtualDerived *aData = new VirtualDerived;
1272  Data *aBase = aData;
1273  QVERIFY(aData == aBase);
1274  QVERIFY(*reinterpret_cast<quintptr *>(&aData) != *reinterpret_cast<quintptr *>(&aBase));
1275 
1277  QSharedPointer<Data> baseptr = qSharedPointerCast<Data>(ptr);
1278  QVERIFY(ptr == baseptr);
1279  QVERIFY(ptr.data() == baseptr.data());
1280  QVERIFY(ptr == aBase);
1281  QVERIFY(ptr == aData);
1282  QVERIFY(baseptr == aData);
1283  QVERIFY(baseptr == aBase);
1284  }
1285  safetyCheck();
1286 
1287  {
1288  VirtualDerived *aData = new VirtualDerived;
1289  Data *aBase = aData;
1290  QVERIFY(aData == aBase);
1291  QVERIFY(*reinterpret_cast<quintptr *>(&aData) != *reinterpret_cast<quintptr *>(&aBase));
1292 
1294  QSharedPointer<Data> baseptr = ptr;
1295  QVERIFY(ptr == baseptr);
1296  QVERIFY(ptr.data() == baseptr.data());
1297  QVERIFY(ptr == aBase);
1298  QVERIFY(ptr == aData);
1299  QVERIFY(baseptr == aData);
1300  QVERIFY(baseptr == aBase);
1301  }
1302  safetyCheck();
1303 }
1304 
1305 #ifndef QTEST_NO_RTTI
1306 void tst_QSharedPointer::dynamicCast()
1307 {
1308  DerivedData *aData = new DerivedData;
1309  QSharedPointer<Data> baseptr = QSharedPointer<Data>(aData);
1310 
1311  {
1312  QSharedPointer<DerivedData> derivedptr = qSharedPointerDynamicCast<DerivedData>(baseptr);
1313  QVERIFY(baseptr == derivedptr);
1314  QCOMPARE(derivedptr.data(), aData);
1315  QCOMPARE(static_cast<Data *>(derivedptr.data()), baseptr.data());
1316  }
1317  QCOMPARE(int(refCountData(baseptr)->weakref.loadRelaxed()), 1);
1318  QCOMPARE(int(refCountData(baseptr)->strongref.loadRelaxed()), 1);
1319 
1320  {
1321  QWeakPointer<Data> weakptr = baseptr;
1322  QSharedPointer<DerivedData> derivedptr = qSharedPointerDynamicCast<DerivedData>(weakptr);
1323  QVERIFY(baseptr == derivedptr);
1324  QCOMPARE(derivedptr.data(), aData);
1325  QCOMPARE(static_cast<Data *>(derivedptr.data()), baseptr.data());
1326  }
1327  QCOMPARE(int(refCountData(baseptr)->weakref.loadRelaxed()), 1);
1328  QCOMPARE(int(refCountData(baseptr)->strongref.loadRelaxed()), 1);
1329 
1330  {
1331  QSharedPointer<DerivedData> derivedptr = baseptr.dynamicCast<DerivedData>();
1332  QVERIFY(baseptr == derivedptr);
1333  QCOMPARE(derivedptr.data(), aData);
1334  QCOMPARE(static_cast<Data *>(derivedptr.data()), baseptr.data());
1335  }
1336  QCOMPARE(int(refCountData(baseptr)->weakref.loadRelaxed()), 1);
1337  QCOMPARE(int(refCountData(baseptr)->strongref.loadRelaxed()), 1);
1338 }
1339 
1340 void tst_QSharedPointer::dynamicCastDifferentPointers()
1341 {
1342  // DiffPtrDerivedData derives from both Data and Stuffing
1344  QSharedPointer<Data> baseptr = QSharedPointer<Data>(aData);
1345 
1346  {
1347  QSharedPointer<DiffPtrDerivedData> derivedptr = qSharedPointerDynamicCast<DiffPtrDerivedData>(baseptr);
1348  QVERIFY(baseptr == derivedptr);
1349  QCOMPARE(derivedptr.data(), aData);
1350  QCOMPARE(static_cast<Data *>(derivedptr.data()), baseptr.data());
1351  }
1352  QCOMPARE(int(refCountData(baseptr)->weakref.loadRelaxed()), 1);
1353  QCOMPARE(int(refCountData(baseptr)->strongref.loadRelaxed()), 1);
1354 
1355  {
1356  QWeakPointer<Data> weakptr = baseptr;
1357  QSharedPointer<DiffPtrDerivedData> derivedptr = qSharedPointerDynamicCast<DiffPtrDerivedData>(weakptr);
1358  QVERIFY(baseptr == derivedptr);
1359  QCOMPARE(derivedptr.data(), aData);
1360  QCOMPARE(static_cast<Data *>(derivedptr.data()), baseptr.data());
1361  }
1362  QCOMPARE(int(refCountData(baseptr)->weakref.loadRelaxed()), 1);
1363  QCOMPARE(int(refCountData(baseptr)->strongref.loadRelaxed()), 1);
1364 
1365  {
1367  QVERIFY(baseptr == derivedptr);
1368  QCOMPARE(derivedptr.data(), aData);
1369  QCOMPARE(static_cast<Data *>(derivedptr.data()), baseptr.data());
1370  }
1371  QCOMPARE(int(refCountData(baseptr)->weakref.loadRelaxed()), 1);
1372  QCOMPARE(int(refCountData(baseptr)->strongref.loadRelaxed()), 1);
1373 
1374  {
1375  Stuffing *nakedptr = dynamic_cast<Stuffing *>(baseptr.data());
1376  QVERIFY(nakedptr);
1377 
1378  QSharedPointer<Stuffing> otherbaseptr = qSharedPointerDynamicCast<Stuffing>(baseptr);
1379  QVERIFY(!otherbaseptr.isNull());
1380  QVERIFY(otherbaseptr == nakedptr);
1381  QCOMPARE(otherbaseptr.data(), nakedptr);
1382  QCOMPARE(static_cast<DiffPtrDerivedData*>(otherbaseptr.data()), aData);
1383  }
1384 }
1385 
1386 void tst_QSharedPointer::dynamicCastVirtualBase()
1387 {
1388  VirtualDerived *aData = new VirtualDerived;
1389  QSharedPointer<Data> baseptr = QSharedPointer<Data>(aData);
1390 
1391  {
1392  QSharedPointer<VirtualDerived> derivedptr = qSharedPointerDynamicCast<VirtualDerived>(baseptr);
1393  QVERIFY(baseptr == derivedptr);
1394  QCOMPARE(derivedptr.data(), aData);
1395  QCOMPARE(static_cast<Data *>(derivedptr.data()), baseptr.data());
1396  }
1397  QCOMPARE(int(refCountData(baseptr)->weakref.loadRelaxed()), 1);
1398  QCOMPARE(int(refCountData(baseptr)->strongref.loadRelaxed()), 1);
1399 
1400  {
1401  QWeakPointer<Data> weakptr = baseptr;
1402  QSharedPointer<VirtualDerived> derivedptr = qSharedPointerDynamicCast<VirtualDerived>(weakptr);
1403  QVERIFY(baseptr == derivedptr);
1404  QCOMPARE(derivedptr.data(), aData);
1405  QCOMPARE(static_cast<Data *>(derivedptr.data()), baseptr.data());
1406  }
1407  QCOMPARE(int(refCountData(baseptr)->weakref.loadRelaxed()), 1);
1408  QCOMPARE(int(refCountData(baseptr)->strongref.loadRelaxed()), 1);
1409 
1410  {
1412  QVERIFY(baseptr == derivedptr);
1413  QCOMPARE(derivedptr.data(), aData);
1414  QCOMPARE(static_cast<Data *>(derivedptr.data()), baseptr.data());
1415  }
1416  QCOMPARE(int(refCountData(baseptr)->weakref.loadRelaxed()), 1);
1417  QCOMPARE(int(refCountData(baseptr)->strongref.loadRelaxed()), 1);
1418 }
1419 
1420 void tst_QSharedPointer::dynamicCastFailure()
1421 {
1423  QVERIFY(dynamic_cast<DerivedData *>(baseptr.data()) == 0);
1424 
1425  {
1426  QSharedPointer<DerivedData> derivedptr = qSharedPointerDynamicCast<DerivedData>(baseptr);
1427  QVERIFY(derivedptr.isNull());
1428  }
1429  QCOMPARE(int(refCountData(baseptr)->weakref.loadRelaxed()), 1);
1430  QCOMPARE(int(refCountData(baseptr)->strongref.loadRelaxed()), 1);
1431 
1432  {
1433  QSharedPointer<DerivedData> derivedptr = baseptr.dynamicCast<DerivedData>();
1434  QVERIFY(derivedptr.isNull());
1435  }
1436  QCOMPARE(int(refCountData(baseptr)->weakref.loadRelaxed()), 1);
1437  QCOMPARE(int(refCountData(baseptr)->strongref.loadRelaxed()), 1);
1438 }
1439 
1440 void tst_QSharedPointer::dynamicCastFailureNoLeak()
1441 {
1443 }
1444 #endif
1445 
1446 void tst_QSharedPointer::constCorrectness()
1447 {
1448  {
1450  QSharedPointer<const Data> cptr(ptr);
1452  cptr = ptr;
1453  vptr = ptr;
1454 
1455  ptr = qSharedPointerConstCast<Data>(cptr);
1456  ptr = qSharedPointerConstCast<Data>(vptr);
1457  ptr = cptr.constCast<Data>();
1458  ptr = vptr.constCast<Data>();
1459 
1463  cvptr = ptr;
1464  cvptr2 = cptr;
1465  cvptr3 = vptr;
1466  ptr = qSharedPointerConstCast<Data>(cvptr);
1467  ptr = cvptr.constCast<Data>();
1468  }
1469  safetyCheck();
1470 
1471  {
1472  Data *aData = new Data;
1474  const QSharedPointer<Data> cptr = ptr;
1475 
1476  ptr = cptr;
1477  QSharedPointer<Data> other = qSharedPointerCast<Data>(cptr);
1478 
1479 #ifndef QT_NO_DYNAMIC_CAST
1480  other = qSharedPointerDynamicCast<Data>(cptr);
1481 #endif
1482 
1483  QCOMPARE(cptr.data(), aData);
1484  QCOMPARE(cptr.operator->(), aData);
1485  }
1486  safetyCheck();
1487 }
1488 
1489 static int customDeleterFnCallCount;
1491 {
1492  ++customDeleterFnCallCount;
1493  delete ptr;
1494 }
1495 
1496 static int refcount;
1497 
1498 template <typename T>
1500 {
1501  CustomDeleter() { ++refcount; }
1502  CustomDeleter(const CustomDeleter &) { ++refcount; }
1503  ~CustomDeleter() { --refcount; }
1504  inline void operator()(T *ptr)
1505  {
1506  delete ptr;
1507  ++callCount;
1508  }
1509  static int callCount;
1510 };
1511 template<typename T> int CustomDeleter<T>::callCount = 0;
1512 
1513 void tst_QSharedPointer::customDeleter()
1514 {
1515  {
1519  }
1520  safetyCheck();
1521  {
1522  QSharedPointer<Data> ptr(nullptr, &Data::doDelete);
1523  QSharedPointer<Data> ptr2(nullptr, &Data::alsoDelete);
1524  QSharedPointer<Data> ptr3(nullptr, &Data::virtualDelete);
1525  }
1526  safetyCheck();
1527  {
1531  }
1532  safetyCheck();
1533  {
1537  }
1538  safetyCheck();
1539 
1540  customDeleterFnCallCount = 0;
1541  {
1543  ptr.data();
1544  QCOMPARE(customDeleterFnCallCount, 0);
1545  }
1546  QCOMPARE(customDeleterFnCallCount, 1);
1547  safetyCheck();
1548 
1549  customDeleterFnCallCount = 0;
1550  {
1552  QCOMPARE(customDeleterFnCallCount, 0);
1553  ptr.clear();
1554  QCOMPARE(customDeleterFnCallCount, 1);
1555  }
1556  QCOMPARE(customDeleterFnCallCount, 1);
1557  safetyCheck();
1558 
1559  customDeleterFnCallCount = 0;
1560  {
1562  QCOMPARE(customDeleterFnCallCount, 0);
1563  ptr = QSharedPointer<Data>(new Data);
1564  QCOMPARE(customDeleterFnCallCount, 1);
1565  }
1566  QCOMPARE(customDeleterFnCallCount, 1);
1567  safetyCheck();
1568 
1569  customDeleterFnCallCount = 0;
1570  {
1572  ptr.data();
1573  QCOMPARE(customDeleterFnCallCount, 0);
1574  }
1575  QCOMPARE(customDeleterFnCallCount, 1);
1576  safetyCheck();
1577 
1578  customDeleterFnCallCount = 0;
1579  {
1581  ptr.data();
1582  QCOMPARE(customDeleterFnCallCount, 0);
1583  }
1584  QCOMPARE(customDeleterFnCallCount, 1);
1585  safetyCheck();
1586 
1587  customDeleterFnCallCount = 0;
1588  {
1590  {
1592  other = ptr;
1593  QCOMPARE(customDeleterFnCallCount, 0);
1594  }
1595  QCOMPARE(customDeleterFnCallCount, 0);
1596  }
1597  QCOMPARE(customDeleterFnCallCount, 1);
1598  safetyCheck();
1599 
1600  customDeleterFnCallCount = 0;
1601  {
1603  {
1605  other = ptr;
1606  QCOMPARE(customDeleterFnCallCount, 0);
1607  }
1608  QCOMPARE(customDeleterFnCallCount, 0);
1609  }
1610  QCOMPARE(customDeleterFnCallCount, 1);
1611  safetyCheck();
1612 
1613  refcount = 0;
1614  CustomDeleter<Data> dataDeleter;
1615  dataDeleter.callCount = 0;
1616  {
1617  QSharedPointer<Data> ptr = QSharedPointer<Data>(new Data, dataDeleter);
1618  ptr.data();
1619  QCOMPARE(dataDeleter.callCount, 0);
1620  }
1621  QCOMPARE(dataDeleter.callCount, 1);
1622  QCOMPARE(refcount, 1);
1623  safetyCheck();
1624 
1625  dataDeleter.callCount = 0;
1626  {
1627  QSharedPointer<Data> ptr = QSharedPointer<Data>(new Data, dataDeleter);
1629  other.clear();
1630  QCOMPARE(dataDeleter.callCount, 0);
1631  }
1632  QCOMPARE(dataDeleter.callCount, 1);
1633  QCOMPARE(refcount, 1);
1634  safetyCheck();
1635 
1636  dataDeleter.callCount = 0;
1637  {
1639  {
1640  QSharedPointer<Data> ptr = QSharedPointer<Data>(new Data, dataDeleter);
1641  other = ptr;
1642  QCOMPARE(dataDeleter.callCount, 0);
1643  }
1644  QCOMPARE(dataDeleter.callCount, 0);
1645  }
1646  QCOMPARE(dataDeleter.callCount, 1);
1647  QCOMPARE(refcount, 1);
1648  safetyCheck();
1649 
1650  dataDeleter.callCount = 0;
1651  {
1653  ptr.data();
1654  QCOMPARE(dataDeleter.callCount, 0);
1655  }
1656  QCOMPARE(dataDeleter.callCount, 1);
1657  QCOMPARE(refcount, 1);
1658  safetyCheck();
1659 
1660  CustomDeleter<DerivedData> derivedDataDeleter;
1661  derivedDataDeleter.callCount = 0;
1662  dataDeleter.callCount = 0;
1663  {
1665  ptr.data();
1666  QCOMPARE(dataDeleter.callCount, 0);
1667  QCOMPARE(derivedDataDeleter.callCount, 0);
1668  }
1669  QCOMPARE(dataDeleter.callCount, 0);
1670  QCOMPARE(derivedDataDeleter.callCount, 1);
1671  QCOMPARE(refcount, 2);
1672  safetyCheck();
1673 
1674  derivedDataDeleter.callCount = 0;
1675  dataDeleter.callCount = 0;
1676  {
1678  {
1680  other = ptr;
1681  QCOMPARE(dataDeleter.callCount, 0);
1682  QCOMPARE(derivedDataDeleter.callCount, 0);
1683  }
1684  QCOMPARE(dataDeleter.callCount, 0);
1685  QCOMPARE(derivedDataDeleter.callCount, 0);
1686  }
1687  QCOMPARE(dataDeleter.callCount, 1);
1688  QCOMPARE(derivedDataDeleter.callCount, 0);
1689  QCOMPARE(refcount, 2);
1690  safetyCheck();
1691 
1692  derivedDataDeleter.callCount = 0;
1693  dataDeleter.callCount = 0;
1694  {
1696  {
1698  other = ptr;
1699  QCOMPARE(dataDeleter.callCount, 0);
1700  QCOMPARE(derivedDataDeleter.callCount, 0);
1701  }
1702  QCOMPARE(dataDeleter.callCount, 0);
1703  QCOMPARE(derivedDataDeleter.callCount, 0);
1704  }
1705  QCOMPARE(dataDeleter.callCount, 0);
1706  QCOMPARE(derivedDataDeleter.callCount, 1);
1707  QCOMPARE(refcount, 2);
1708  safetyCheck();
1709 
1710  CustomDeleter<NVDData> nvdeleter;
1711  nvdeleter.callCount = 0;
1712  {
1713  QSharedPointer<NVDData> ptr(new NVDData, nvdeleter);
1714  }
1715  QCOMPARE(nvdeleter.callCount, 1);
1716  safetyCheck();
1717 
1718  CustomDeleter<NVDDerivedData> nvderiveddeleter;
1719  nvdeleter.callCount = 0;
1720  nvderiveddeleter.callCount = 0;
1721  {
1722  QSharedPointer<NVDDerivedData> ptr(new NVDDerivedData, nvderiveddeleter);
1723  }
1724  QCOMPARE(nvdeleter.callCount, 0);
1725  QCOMPARE(nvderiveddeleter.callCount, 1);
1726  safetyCheck();
1727 
1728  nvdeleter.callCount = 0;
1729  nvderiveddeleter.callCount = 0;
1730  {
1731  QSharedPointer<NVDData> ptr(new NVDDerivedData, nvderiveddeleter);
1732  }
1733  QCOMPARE(nvdeleter.callCount, 0);
1734  QCOMPARE(nvderiveddeleter.callCount, 1);
1735  safetyCheck();
1736 
1737  // a custom deleter with a different pointer parameter
1738  {
1739  QSharedPointer<char> ptr(static_cast<char *>(malloc(1)), free);
1740  }
1741  safetyCheck();
1742 }
1743 
1744 // The compiler needs to be in C++11 mode and to support lambdas
1745 void tst_QSharedPointer::lambdaCustomDeleter()
1746 {
1747  {
1748  // stateless, one-argument
1749  QSharedPointer<Data> ptr(new Data, [](Data *d) { delete d; });
1750  QSharedPointer<Data> ptr2(new Data, [](Data *d) { d->doDelete(); });
1751  }
1752  safetyCheck();
1753 
1754  customDeleterFnCallCount = 0;
1755  {
1756  // stateless, one-argument, modifies globals
1757  QSharedPointer<Data> ptr(new Data, [](Data *d) { ++customDeleterFnCallCount; delete d; });
1758  }
1759  safetyCheck();
1760  QCOMPARE(customDeleterFnCallCount, 1);
1761 
1762  {
1763  // stateful by ref, one-argument
1764  int i = 0;
1765  QSharedPointer<Data> ptr(new Data, [&i](Data *d) { i = 42; delete d; });
1766  ptr.clear();
1767  QCOMPARE(i, 42);
1768  }
1769  safetyCheck();
1770 }
1771 
1772 void tst_QSharedPointer::customDeleterOnNullptr()
1773 {
1774  Data *null = nullptr;
1775  int callCount = 0;
1776  auto deleter = [&callCount](Data *) { ++callCount; };
1777  {
1778  QSharedPointer<Data> ptr(null, deleter);
1779  }
1780  safetyCheck();
1781  QCOMPARE(callCount, 1);
1782 
1783  callCount = 0;
1784  {
1785  QSharedPointer<Data> ptr(nullptr, deleter);
1786  }
1787  safetyCheck();
1788  QCOMPARE(callCount, 1);
1789 
1790  callCount = 0;
1791  {
1792  QSharedPointer<Data> ptr1(null, deleter);
1793  QSharedPointer<Data> ptr2(nullptr, deleter);
1794  }
1795  safetyCheck();
1796  QCOMPARE(callCount, 2);
1797 }
1798 
1800 {
1801  ++customDeleterFnCallCount;
1802  delete obj;
1803 }
1804 
1805 void tst_QSharedPointer::creating()
1806 {
1808  {
1810  QVERIFY(ptr.data());
1812  QCOMPARE(ptr->generation, 1);
1814 
1815  QCOMPARE(ptr->classLevel(), 1);
1816 
1817  ptr.clear();
1819  }
1820  safetyCheck();
1821 
1823  {
1825  QWeakPointer<Data> weakptr = ptr;
1826  QtSharedPointer::ExternalRefCountData *d = refCountData(ptr);
1827 
1828  ptr.clear();
1829  QVERIFY(ptr.isNull());
1831 
1832  // valgrind will complain here if something happened to the pointer
1833  QVERIFY(d->weakref.loadRelaxed() == 1);
1834  QVERIFY(d->strongref.loadRelaxed() == 0);
1835  }
1836  safetyCheck();
1837 
1840  {
1842  QCOMPARE(ptr->classLevel(), 2);
1844  ptr.clear();
1845 
1848  }
1849  safetyCheck();
1850 
1851  {
1853  QCOMPARE(ptr->classLevel(), 3);
1854  QCOMPARE(ptr.staticCast<DiffPtrDerivedData>()->buffer[7]+0, 16-7);
1855  QCOMPARE(ptr.staticCast<DiffPtrDerivedData>()->buffer[3]+0, 16-3);
1856  QCOMPARE(ptr.staticCast<DiffPtrDerivedData>()->buffer[0]+0, 16);
1857  }
1858  safetyCheck();
1859 
1860  {
1862  QCOMPARE(ptr->classLevel(), 4);
1863  QCOMPARE(ptr->moreData, 0xc0ffee);
1864 
1865  QSharedPointer<Data> baseptr = ptr;
1866  QCOMPARE(baseptr->classLevel(), 4);
1867  }
1868  safetyCheck();
1869 }
1870 
1871 void tst_QSharedPointer::creatingCvQualified()
1872 {
1873  auto cptr = QSharedPointer<const Data>::create();
1876 }
1877 
1878 void tst_QSharedPointer::creatingVariadic()
1879 {
1880  int i = 42;
1881 
1882  {
1883  NoDefaultConstructor1(1); // control check
1885  QCOMPARE(ptr->i, 1);
1886 
1887  NoDefaultConstructor1(0u); // control check
1889  QCOMPARE(ptr->i, 42);
1890 
1891  NoDefaultConstructor1 x(i); // control check
1893  QCOMPARE(ptr->i, i);
1894  }
1895  {
1896  NoDefaultConstructor2((void*)0, 1); // control check
1898  QCOMPARE(ptr->i, 1);
1899  QCOMPARE(ptr->ptr, (void*)0);
1900 
1901  int *null = 0;
1902  NoDefaultConstructor2(null, 2); // control check
1904  QCOMPARE(ptr->i, 2);
1905  QCOMPARE(ptr->ptr, (void*)0);
1906 
1907  NoDefaultConstructor2(nullptr, 3); // control check
1909  QCOMPARE(ptr->i, 3);
1910  QCOMPARE(ptr->ptr, (void*)nullptr);
1911  }
1912  {
1913  NoDefaultConstructorRef1 x(i); // control check
1915  QCOMPARE(ptr->i, i);
1916  QCOMPARE(&ptr->i, &i);
1917  }
1918  {
1919  NoDefaultConstructorRRef1(std::move(i)); // control check
1921  QCOMPARE(ptr->i, i);
1922  }
1923  {
1924  NoDefaultConstructorRRef2(std::unique_ptr<int>(new int(1))); // control check
1926  QCOMPARE(*ptr->i, 1);
1927 
1928  std::unique_ptr<int> p(new int(i));
1930  QCOMPARE(*ptr->i, i);
1931  }
1932  {
1933  QString text("Hello, World");
1934  NoDefaultConstructorRef2(text, 1); // control check
1936  QCOMPARE(ptr->str, text);
1937  QCOMPARE(ptr->i, 1);
1938  }
1939  {
1941  NoDefaultConstructorConstRef2(QLatin1String("string"), 1); // control check
1943  QCOMPARE(ptr->str, QString("string"));
1944  QCOMPARE(ptr->i, 1);
1945 
1946  NoDefaultConstructorConstRef2(QByteArray("bytearray")); // control check
1948  QCOMPARE(ptr->str, QString("bytearray"));
1949  QCOMPARE(ptr->i, 42);
1950  }
1951 }
1952 
1953 void tst_QSharedPointer::creatingQObject()
1954 {
1955  {
1957  QCOMPARE(ptr->metaObject(), &QObject::staticMetaObject);
1958 
1959  QPointer<QObject> qptr = ptr.data();
1960  ptr.clear();
1961 
1962  QVERIFY(qptr.isNull());
1963  }
1964  safetyCheck();
1965 
1966  {
1968  QCOMPARE(ptr->metaObject(), &OtherObject::staticMetaObject);
1969  }
1970  safetyCheck();
1971 }
1972 
1973 void tst_QSharedPointer::mixTrackingPointerCode()
1974 {
1975  {
1976  // pointer created with tracking
1977  // deleted in code without tracking
1978  QSharedPointer<int> ptr = QSharedPointer<int>(new int(42));
1979  Wrapper w(ptr);
1980  ptr.clear();
1981  }
1982  safetyCheck();
1983 
1984  {
1985  // pointer created without tracking
1986  // deleted in code with tracking
1988  w.ptr.clear();
1989  }
1990 }
1991 
1993 {
1994  QAtomicInt * volatile ptr;
1995 public:
1996  ThreadData(QAtomicInt *p) : ptr(p) { }
1998  void ref()
1999  {
2000  // if we're called after the destructor, we'll crash
2001  ptr->ref();
2002  }
2003 };
2004 
2005 class StrongThread: public QThread
2006 {
2007 protected:
2008  void run() override
2009  {
2010  usleep(QRandomGenerator::global()->bounded(2000));
2011  ptr->ref();
2012  ptr.clear();
2013  }
2014 public:
2016 };
2017 
2018 class WeakThread: public QThread
2019 {
2020 protected:
2021  void run() override
2022  {
2023  usleep(QRandomGenerator::global()->bounded(2000));
2025  if (ptr)
2026  ptr->ref();
2027  ptr.clear();
2028  }
2029 public:
2031 };
2032 
2033 void tst_QSharedPointer::threadStressTest_data()
2034 {
2035  QTest::addColumn<int>("strongThreadCount");
2036  QTest::addColumn<int>("weakThreadCount");
2037 
2038  QTest::newRow("0+0") << 0 << 0;
2039  QTest::newRow("1+0") << 1 << 0;
2040  QTest::newRow("2+0") << 2 << 0;
2041  QTest::newRow("10+0") << 10 << 0;
2042 
2043  QTest::newRow("0+1") << 0 << 1;
2044  QTest::newRow("1+1") << 1 << 1;
2045 
2046  QTest::newRow("2+10") << 2 << 10;
2047 
2048  QTest::newRow("5+10") << 5 << 10;
2049  QTest::newRow("5+30") << 5 << 30;
2050 
2051  QTest::newRow("100+100") << 100 << 100;
2052 }
2053 
2054 void tst_QSharedPointer::threadStressTest()
2055 {
2056  QFETCH(int, strongThreadCount);
2057  QFETCH(int, weakThreadCount);
2058 
2059  int guard1[128];
2061  int guard2[128];
2062 
2063  memset(guard1, 0, sizeof guard1);
2064  memset(guard2, 0, sizeof guard2);
2065 
2066  for (int r = 0; r < 5; ++r) {
2067  QList<QThread*> allThreads(6 * qMax(strongThreadCount, weakThreadCount) + 3, 0);
2069  counter.storeRelaxed(0);
2070 
2071  // set the pointers
2072  for (int i = 0; i < strongThreadCount; ++i) {
2073  StrongThread *t = new StrongThread;
2074  t->ptr = base;
2075  allThreads[2 * i] = t;
2076  }
2077  for (int i = 0; i < weakThreadCount; ++i) {
2078  WeakThread *t = new WeakThread;
2079  t->weak = base;
2080  allThreads[6 * i + 3] = t;
2081  }
2082 
2083  base.clear();
2084 
2085  // start threads
2086  for (int i = 0; i < allThreads.count(); ++i)
2087  if (allThreads[i]) allThreads[i]->start();
2088 
2089  // wait for them to finish
2090  for (int i = 0; i < allThreads.count(); ++i)
2091  if (allThreads[i]) allThreads[i]->wait();
2092  qDeleteAll(allThreads);
2093 
2094  // ensure the guards aren't touched
2095  for (uint i = 0; i < sizeof guard1 / sizeof guard1[0]; ++i)
2096  QVERIFY(!guard1[i]);
2097  for (uint i = 0; i < sizeof guard2 / sizeof guard2[0]; ++i)
2098  QVERIFY(!guard2[i]);
2099 
2100  // verify that the count is the right range
2101  int minValue = strongThreadCount;
2102  int maxValue = strongThreadCount + weakThreadCount;
2103  QVERIFY(counter.loadRelaxed() >= minValue);
2104  QVERIFY(counter.loadRelaxed() <= maxValue);
2105  }
2106 }
2107 
2108 template<typename Container, bool Ordered, bool Multi>
2110 {
2111  typedef typename Container::key_type Key;
2112  typedef typename Container::mapped_type Value;
2113 
2114  Container c;
2115  QVERIFY(c.isEmpty());
2116 
2117  Key k0;
2118  c.insert(k0, Value(0));
2119  QVERIFY(!c.isEmpty());
2120 
2121  typename Container::iterator it;
2122  it = c.find(k0);
2123  QVERIFY(it != c.end());
2124  it = c.find(Key());
2125  QVERIFY(it != c.end());
2126  it = c.find(Key(0));
2127  QVERIFY(it != c.end());
2128 
2129  Key k1(new typename Key::value_type(42));
2130  it = c.find(k1);
2131  QVERIFY(it == c.end());
2132 
2133  c.insert(k1, Value(42));
2134  it = c.find(k1);
2135  QVERIFY(it != c.end());
2136  QVERIFY(it != c.find(Key()));
2137 
2138  if (Ordered) {
2139  QVERIFY(k0 < k1);
2140 
2141  it = c.begin();
2142  QCOMPARE(it.key(), k0);
2143  QCOMPARE(it.value(), Value(0));
2144 
2145  ++it;
2146  QCOMPARE(it.key(), k1);
2147  QCOMPARE(it.value(), Value(42));
2148 
2149  ++it;
2150  QVERIFY(it == c.end());
2151  }
2152 
2153  if (Multi) {
2154  c.insert(k1, Value(47));
2155  it = c.find(k1);
2156  QVERIFY(it != c.end());
2157  QCOMPARE(it.key(), k1);
2158  ++it;
2159  QVERIFY(it != c.end());
2160  QCOMPARE(it.key(), k1);
2161  ++it;
2162  if (Ordered)
2163  QVERIFY(it == c.end());
2164  }
2165 }
2166 
2167 void tst_QSharedPointer::map()
2168 {
2169  hashAndMapTest<QMap<QSharedPointer<int>, int>, true, false>();
2170  hashAndMapTest<QMultiMap<QSharedPointer<int>, int>, true, true>();
2171 }
2172 
2173 void tst_QSharedPointer::hash()
2174 {
2175  hashAndMapTest<QHash<QSharedPointer<int>, int>, false, false>();
2176  hashAndMapTest<QMultiHash<QSharedPointer<int>, int>, false, true>();
2177 }
2178 
2179 void tst_QSharedPointer::validConstructs()
2180 {
2181  {
2182  Data *aData = new Data;
2184 
2186 QT_WARNING_DISABLE_CLANG("-Wself-assign-overloaded")
2187  ptr1 = ptr1; // valid
2189 
2190  QSharedPointer<Data> ptr2(ptr1);
2191 
2192  ptr1 = ptr2;
2193  ptr2 = ptr1;
2194 
2195  ptr1 = QSharedPointer<Data>();
2196  ptr1 = ptr2;
2197  }
2198 }
2199 
2200 #if 0
2201 typedef bool (QTest::QExternalTest:: * TestFunction)(const QByteArray &body);
2203 void tst_QSharedPointer::invalidConstructs_data()
2204 {
2205  QTest::addColumn<TestFunction>("testFunction");
2206  QTest::addColumn<QString>("code");
2207  QTest::newRow("sanity-checking") << &QTest::QExternalTest::tryCompile << "";
2208 
2209  // QSharedPointer<void> is not allowed
2210  QTest::newRow("void") << &QTest::QExternalTest::tryCompileFail << "QSharedPointer<void> ptr;";
2211 
2212  // implicit initialization
2213  QTest::newRow("implicit-initialization1")
2215  << "QSharedPointer<Data> ptr = new Data;";
2216  QTest::newRow("implicit-initialization2")
2218  << "QSharedPointer<Data> ptr;"
2219  "ptr = new Data;";
2220  QTest::newRow("implicit-initialization3")
2222  << "QWeakPointer<Data> ptr = new Data;";
2223  QTest::newRow("implicit-initialization4")
2225  << "QWeakPointer<Data> ptr;"
2226  "ptr = new Data;";
2227 
2228  // use of forward-declared class
2229  QTest::newRow("creating-forward-declaration")
2231  << "QSharedPointer<ForwardDeclared>::create();";
2232 
2233  // upcast without cast operator:
2234  QTest::newRow("upcast1")
2236  << "QSharedPointer<Data> baseptr = QSharedPointer<Data>(new DerivedData);\n"
2237  "QSharedPointer<DerivedData> ptr(baseptr);";
2238  QTest::newRow("upcast2")
2240  << "QSharedPointer<Data> baseptr = QSharedPointer<Data>(new DerivedData);\n"
2241  "QSharedPointer<DerivedData> ptr;\n"
2242  "ptr = baseptr;";
2243 
2244  // dropping of const
2245  QTest::newRow("const-dropping1")
2247  << "QSharedPointer<const Data> baseptr = QSharedPointer<const Data>(new Data);\n"
2248  "QSharedPointer<Data> ptr(baseptr);";
2249  QTest::newRow("const-dropping2")
2251  << "QSharedPointer<const Data> baseptr = QSharedPointer<const Data>(new Data);\n"
2252  "QSharedPointer<Data> ptr;"
2253  "ptr = baseptr;";
2254  QTest::newRow("const-dropping-static-cast")
2256  << "QSharedPointer<const Data> baseptr = QSharedPointer<const Data>(new Data);\n"
2257  "qSharedPointerCast<DerivedData>(baseptr);";
2258 #ifndef QTEST_NO_RTTI
2259  QTest::newRow("const-dropping-dynamic-cast")
2261  << "QSharedPointer<const Data> baseptr = QSharedPointer<const Data>(new Data);\n"
2262  "qSharedPointerDynamicCast<DerivedData>(baseptr);";
2263 #endif
2264  QTest::newRow("const-dropping-object-cast1")
2266  << "QSharedPointer<const QObject> baseptr = QSharedPointer<const QObject>(new QObject);\n"
2267  "qSharedPointerObjectCast<QCoreApplication>(baseptr);";
2268  QTest::newRow("const-dropping-object-cast2")
2270  << "QSharedPointer<const QObject> baseptr = QSharedPointer<const QObject>(new QObject);\n"
2271  "qobject_cast<QCoreApplication *>(baseptr);";
2272 
2273  // arithmethics through automatic cast operators
2274  QTest::newRow("arithmethic1")
2276  << "QSharedPointer<int> a;"
2277  "QSharedPointer<Data> b;\n"
2278  "if (a == b) return;";
2279  QTest::newRow("arithmethic2")
2281  << "QSharedPointer<int> a;"
2282  "QSharedPointer<Data> b;\n"
2283  "if (a + b) return;";
2284 
2285  // two objects with the same pointer
2286  QTest::newRow("same-pointer")
2288  << "Data *aData = new Data;\n"
2289  "QSharedPointer<Data> ptr1 = QSharedPointer<Data>(aData);\n"
2290  "QSharedPointer<Data> ptr2 = QSharedPointer<Data>(aData);\n";
2291 
2292  // two QObjects with the same pointer
2293  QTest::newRow("same-pointer-to-qobject")
2295  << "QObject *anObj = new QObject;\n"
2296  "QSharedPointer<QObject> ptr1 = QSharedPointer<QObject>(anObj);\n"
2297  "QSharedPointer<QObject> ptr2 = QSharedPointer<QObject>(anObj);\n";
2298 
2299  // re-creation:
2300  QTest::newRow("re-creation")
2302  << "Data *aData = new Data;\n"
2303  "QSharedPointer<Data> ptr1 = QSharedPointer<Data>(aData);"
2304  "ptr1 = QSharedPointer<Data>(aData);";
2305 
2306  // any type of cast for unrelated types:
2307  // (we have no reinterpret_cast)
2308  QTest::newRow("invalid-cast1")
2310  << "QSharedPointer<Data> ptr1;\n"
2311  "QSharedPointer<int> ptr2 = qSharedPointerCast<int>(ptr1);";
2312 #ifndef QTEST_NO_RTTI
2313  QTest::newRow("invalid-cast2")
2315  << "QSharedPointer<Data> ptr1;\n"
2316  "QSharedPointer<int> ptr2 = qSharedPointerDynamicCast<int>(ptr1);";
2317 #endif
2318  QTest::newRow("invalid-cast3")
2320  << "QSharedPointer<Data> ptr1;\n"
2321  "QSharedPointer<int> ptr2 = qSharedPointerConstCast<int>(ptr1);";
2322  QTest::newRow("invalid-cast4")
2324  << "QSharedPointer<Data> ptr1;\n"
2325  "QSharedPointer<int> ptr2 = qSharedPointerObjectCast<int>(ptr1);";
2326 
2327  QTest::newRow("weak-pointer-from-regular-pointer")
2329  << "Data *ptr = nullptr;\n"
2330  "QWeakPointer<Data> weakptr(ptr);\n";
2331 
2332  QTest::newRow("shared-pointer-implicit-from-uninitialized")
2334  << "Data *ptr = nullptr;\n"
2335  "QSharedPointer<Data> weakptr = Qt::Uninitialized;\n";
2336 
2337  QTest::newRow("incompatible-custom-deleter1")
2339  << "extern void incompatibleCustomDeleter(int *);\n"
2340  "QSharedPointer<Data> ptr(new Data, incompatibleCustomDeleter);\n";
2341  QTest::newRow("incompatible-custom-deleter2")
2343  << "struct IncompatibleCustomDeleter { void operator()(int *); };\n"
2344  "QSharedPointer<Data> ptr(new Data, IncompatibleCustomDeleter());\n";
2345  QTest::newRow("incompatible-custom-lambda-deleter")
2347  << "QSharedPointer<Data> ptr(new Data, [](int *) {});\n";
2348 
2349  QTest::newRow("incompatible-overload")
2351  << "void foo(QSharedPointer<DerivedData>) {}\n"
2352  "void bar() { foo(QSharedPointer<Data>()); }\n";
2353 }
2354 
2355 void tst_QSharedPointer::invalidConstructs()
2356 {
2357 #ifdef Q_CC_MINGW
2358  QSKIP("The maintainer of QSharedPointer: 'We don't know what the problem is so skip the tests.'");
2359 #endif
2360 #ifdef QTEST_CROSS_COMPILED
2361  QSKIP("This test does not work on cross compiled systems");
2362 #endif
2363 
2365  test.setQtModules(QTest::QExternalTest::QtCore);
2366  test.setProgramHeader(
2367  "#define QT_SHAREDPOINTER_TRACK_POINTERS\n"
2368  "#define QT_DEBUG\n"
2369  "#include <QtCore/qsharedpointer.h>\n"
2370  "#include <QtCore/qcoreapplication.h>\n"
2371  "\n"
2372  "struct Data { int i; };\n"
2373  "struct DerivedData: public Data { int j; };\n"
2374  "\n"
2375  "class ForwardDeclared;\n"
2376  );
2377 
2378  QFETCH(QString, code);
2379  static bool sane = true;
2380  if (code.isEmpty()) {
2381  if (!test.tryRun("")
2382  || !test.tryRunFail("exit(1);")
2383  || !test.tryRun("QSharedPointer<Data> baseptr; QSharedPointer<DerivedData> ptr;")) {
2384  sane = false;
2385  qWarning("Sanity checking failed\nCode:\n%s\n",
2386  qPrintable(test.errorReport()));
2387  }
2388  }
2389  if (!sane)
2390  QFAIL("External testing failed sanity checking, cannot proceed");
2391 
2393 
2394  QByteArray body = code.toLatin1();
2395 
2396  bool result = (test.*testFunction)(body);
2397  if (!result || qgetenv("QTEST_EXTERNAL_DEBUG").toInt() > 0) {
2398  qDebug("External test output:");
2399 #ifdef Q_CC_MSVC
2400  // MSVC prints errors to stdout
2401  printf("%s\n", test.standardOutput().constData());
2402 #endif
2403  printf("%s\n", test.standardError().constData());
2404  }
2405  if (!result) {
2406  qWarning("External code testing failed\nCode:\n%s\n", body.constData());
2407  QFAIL("Fail");
2408  }
2409 }
2410 #endif // #if 0
2411 
2412 void tst_QSharedPointer::qvariantCast()
2413 {
2415  sp->setObjectName("A test name");
2417 
2418  {
2419  QSharedPointer<QObject> other = qSharedPointerFromVariant<QObject>(v);
2420  QCOMPARE(other->objectName(), QString::fromLatin1("A test name"));
2421  }
2422  {
2423  QSharedPointer<QIODevice> other = qSharedPointerFromVariant<QIODevice>(v);
2424  QCOMPARE(other->objectName(), QString::fromLatin1("A test name"));
2425  }
2426  {
2427  QSharedPointer<QFile> other = qSharedPointerFromVariant<QFile>(v);
2428  QCOMPARE(other->objectName(), QString::fromLatin1("A test name"));
2429  }
2430  {
2431  QSharedPointer<QThread> other = qSharedPointerFromVariant<QThread>(v);
2432  QVERIFY(!other);
2433  }
2434  // Intentionally does not compile.
2435 // QSharedPointer<int> sop = qSharedPointerFromVariant<int>(v);
2436 }
2437 
2438 class SomeClass : public QEnableSharedFromThis<SomeClass>
2439 {
2440 public:
2442  {
2443  }
2444 
2446  {
2447  return sharedFromThis();
2448  }
2449 
2451  {
2452  return sharedFromThis();
2453  }
2454 
2456 };
2457 
2458 void tst_QSharedPointer::sharedFromThis()
2459 {
2460  const int generations = Data::generationCounter;
2461  const int destructions = Data::destructorCounter;
2462 
2463  {
2464  SomeClass sc;
2466  QVERIFY(scp.isNull());
2467  QCOMPARE(Data::generationCounter, generations + 1);
2468  QCOMPARE(Data::destructorCounter, destructions);
2469 
2471  QVERIFY(const_scp.isNull());
2472  QCOMPARE(Data::generationCounter, generations + 1);
2473  QCOMPARE(Data::destructorCounter, destructions);
2474 
2476  QVERIFY(wcp.isNull());
2477  QCOMPARE(Data::generationCounter, generations + 1);
2478  QCOMPARE(Data::destructorCounter, destructions);
2479 
2481  QVERIFY(const_wcp.isNull());
2482  QCOMPARE(Data::generationCounter, generations + 1);
2483  QCOMPARE(Data::destructorCounter, destructions);
2484  }
2485 
2486  QCOMPARE(Data::generationCounter, generations + 1);
2487  QCOMPARE(Data::destructorCounter, destructions + 1);
2488 
2489  {
2490  const SomeClass sc;
2492  QVERIFY(const_scp.isNull());
2493  QCOMPARE(Data::generationCounter, generations + 2);
2494  QCOMPARE(Data::destructorCounter, destructions + 1);
2495 
2497  QVERIFY(const_wcp.isNull());
2498  QCOMPARE(Data::generationCounter, generations + 2);
2499  QCOMPARE(Data::destructorCounter, destructions + 1);
2500  }
2501 
2502  QCOMPARE(Data::generationCounter, generations + 2);
2503  QCOMPARE(Data::destructorCounter, destructions + 2);
2504 
2505  {
2506  SomeClass *sc = new SomeClass;
2507  QCOMPARE(Data::generationCounter, generations + 3);
2508  QCOMPARE(Data::destructorCounter, destructions + 2);
2509 
2511  QVERIFY(scp.isNull());
2512  QCOMPARE(Data::generationCounter, generations + 3);
2513  QCOMPARE(Data::destructorCounter, destructions + 2);
2514 
2515  scp = sc->sharedFromThis();
2516  QVERIFY(scp.isNull());
2517  QCOMPARE(Data::generationCounter, generations + 3);
2518  QCOMPARE(Data::destructorCounter, destructions + 2);
2519 
2520  scp = QSharedPointer<SomeClass>(sc);
2521  QVERIFY(!scp.isNull());
2522  QCOMPARE(scp.data(), sc);
2523  QCOMPARE(Data::generationCounter, generations + 3);
2524  QCOMPARE(Data::destructorCounter, destructions + 2);
2525 
2527  QVERIFY(scp2.isNull());
2528  QCOMPARE(Data::generationCounter, generations + 3);
2529  QCOMPARE(Data::destructorCounter, destructions + 2);
2530 
2531  scp2 = sc->sharedFromThis();
2532  QVERIFY(!scp2.isNull());
2533  QVERIFY(scp == scp2);
2534  QCOMPARE(scp2.data(), sc);
2535  QCOMPARE(Data::generationCounter, generations + 3);
2536  QCOMPARE(Data::destructorCounter, destructions + 2);
2537 
2539  QVERIFY(scp3.isNull());
2540  QCOMPARE(Data::generationCounter, generations + 3);
2541  QCOMPARE(Data::destructorCounter, destructions + 2);
2542 
2543  scp3 = sc->sharedFromThis();
2544  QVERIFY(!scp3.isNull());
2545  QVERIFY(scp == scp3);
2546  QVERIFY(scp2 == scp3);
2547  QCOMPARE(scp3.data(), sc);
2548  QCOMPARE(Data::generationCounter, generations + 3);
2549  QCOMPARE(Data::destructorCounter, destructions + 2);
2550 
2552  QVERIFY(scp4.isNull());
2553  QCOMPARE(Data::generationCounter, generations + 3);
2554  QCOMPARE(Data::destructorCounter, destructions + 2);
2555 
2556  scp4 = sc->getSharedPtr();
2557  QVERIFY(!scp4.isNull());
2558  QVERIFY(scp == scp4);
2559  QVERIFY(scp2 == scp4);
2560  QVERIFY(scp3 == scp4);
2561  QCOMPARE(scp4.data(), sc);
2562  QCOMPARE(Data::generationCounter, generations + 3);
2563  QCOMPARE(Data::destructorCounter, destructions + 2);
2564 
2566  QVERIFY(scp5.isNull());
2567  QCOMPARE(Data::generationCounter, generations + 3);
2568  QCOMPARE(Data::destructorCounter, destructions + 2);
2569 
2570  scp5 = const_cast<const SomeClass *>(sc)->getSharedPtr();
2571  QVERIFY(!scp4.isNull());
2572  QVERIFY(scp == scp5);
2573  QVERIFY(scp2 == scp5);
2574  QVERIFY(scp3 == scp5);
2575  QVERIFY(scp4 == scp5);
2576  QCOMPARE(scp5.data(), sc);
2577  QCOMPARE(Data::generationCounter, generations + 3);
2578  QCOMPARE(Data::destructorCounter, destructions + 2);
2579  }
2580 
2581  QCOMPARE(Data::generationCounter, generations + 3);
2582  QCOMPARE(Data::destructorCounter, destructions + 3);
2583 
2585 
2586  QVERIFY(scp.isNull());
2587 
2588  {
2590  QVERIFY(!scp2.isNull());
2591 
2592  scp = scp2->sharedFromThis();
2593  QVERIFY(!scp.isNull());
2594 
2595  QVERIFY(scp == scp2);
2596  QCOMPARE(Data::generationCounter, generations + 4);
2597  QCOMPARE(Data::destructorCounter, destructions + 3);
2598  }
2599 
2600 
2601  QCOMPARE(Data::generationCounter, generations + 4);
2602  QCOMPARE(Data::destructorCounter, destructions + 3);
2603  QVERIFY(!scp.isNull());
2604 
2605  {
2607  scp2 = scp->sharedFromThis();
2608  QVERIFY(!scp2.isNull());
2609 
2610  QVERIFY(scp == scp2);
2611  QCOMPARE(Data::generationCounter, generations + 4);
2612  QCOMPARE(Data::destructorCounter, destructions + 3);
2613  }
2614 
2615  QCOMPARE(Data::generationCounter, generations + 4);
2616  QCOMPARE(Data::destructorCounter, destructions + 3);
2617  QVERIFY(!scp.isNull());
2618 
2619  {
2621  scp2 = scp->getSharedPtr();
2622  QVERIFY(!scp2.isNull());
2623 
2624  QVERIFY(scp == scp2);
2625  QCOMPARE(Data::generationCounter, generations + 4);
2626  QCOMPARE(Data::destructorCounter, destructions + 3);
2627  }
2628 
2629  QCOMPARE(Data::generationCounter, generations + 4);
2630  QCOMPARE(Data::destructorCounter, destructions + 3);
2631  QVERIFY(!scp.isNull());
2632 
2633  {
2635  scp2 = qSharedPointerConstCast<const SomeClass>(scp)->getSharedPtr();
2636  QVERIFY(!scp2.isNull());
2637 
2638  QVERIFY(scp == scp2);
2639  QCOMPARE(Data::generationCounter, generations + 4);
2640  QCOMPARE(Data::destructorCounter, destructions + 3);
2641  }
2642 
2643  QCOMPARE(Data::generationCounter, generations + 4);
2644  QCOMPARE(Data::destructorCounter, destructions + 3);
2645  QVERIFY(!scp.isNull());
2646 
2647  {
2649  scp2 = scp->sharedFromThis();
2650  QVERIFY(!scp2.isNull());
2651 
2652  QVERIFY(scp == scp2);
2653  QCOMPARE(Data::generationCounter, generations + 4);
2654  QCOMPARE(Data::destructorCounter, destructions + 3);
2655 
2656  scp2.clear();
2657 
2658  QCOMPARE(Data::generationCounter, generations + 4);
2659  QCOMPARE(Data::destructorCounter, destructions + 3);
2660  QVERIFY(!scp.isNull());
2661  QVERIFY(scp2.isNull());
2662  }
2663 
2664  QCOMPARE(Data::generationCounter, generations + 4);
2665  QCOMPARE(Data::destructorCounter, destructions + 3);
2666  QVERIFY(!scp.isNull());
2667 
2668  scp.clear();
2669 
2670  QCOMPARE(Data::generationCounter, generations + 4);
2671  QCOMPARE(Data::destructorCounter, destructions + 4);
2672 
2673  {
2675  QVERIFY(!scp2.isNull());
2676 
2677  scp = scp2->sharedFromThis();
2678  QVERIFY(!scp.isNull());
2679 
2680  QVERIFY(scp == scp2);
2681  QCOMPARE(Data::generationCounter, generations + 5);
2682  QCOMPARE(Data::destructorCounter, destructions + 4);
2683  }
2684  QCOMPARE(Data::generationCounter, generations + 5);
2685  QCOMPARE(Data::destructorCounter, destructions + 4);
2686 
2687  scp.clear();
2688 
2689  QCOMPARE(Data::generationCounter, generations + 5);
2690  QCOMPARE(Data::destructorCounter, destructions + 5);
2691 
2692  {
2694  QVERIFY(!scp2.isNull());
2695  QCOMPARE(Data::generationCounter, generations + 6);
2696  QCOMPARE(Data::destructorCounter, destructions + 5);
2697 
2699  QVERIFY(!wcp2.isNull());
2700  QCOMPARE(Data::generationCounter, generations + 6);
2701  QCOMPARE(Data::destructorCounter, destructions + 5);
2702  }
2703 
2704  QCOMPARE(Data::generationCounter, generations + 6);
2705  QCOMPARE(Data::destructorCounter, destructions + 6);
2706 }
2707 
2708 #ifndef QT_NO_EXCEPTIONS
2709 class ThrowData: public Data
2710 {
2711 public:
2714 
2716  {
2717  childGenerationCounter++;
2718  throw QStringLiteral("Dummy exception");
2719  }
2720 
2722  {
2723  childDestructorCounter++;
2724  }
2725 };
2728 #endif // !QT_NO_EXCEPTIONS
2729 
2730 void tst_QSharedPointer::constructorThrow()
2731 {
2732 #ifndef QT_NO_EXCEPTIONS
2733  int generation = Data::generationCounter;
2734  int destructorCounter = Data::destructorCounter;
2735 
2736  int childGeneration = ThrowData::childGenerationCounter;
2737  int childDestructorCounter = ThrowData::childDestructorCounter;
2738 
2741  QVERIFY(ptr.isNull());
2742  QCOMPARE(ThrowData::childGenerationCounter, childGeneration + 1);
2743  // destructor should never be called, if a constructor throws
2744  // an exception
2745  QCOMPARE(ThrowData::childDestructorCounter, childDestructorCounter);
2746 
2747  QCOMPARE(Data::generationCounter, generation + 1);
2748  // but base class constructor doesn't throw, so base class destructor
2749  // should be called
2750  QCOMPARE(Data::destructorCounter, destructorCounter + 1);
2751 #else
2752  QSKIP("Needs exceptions");
2753 #endif // !QT_NO_EXCEPTIONS
2754 }
2755 
2757  struct IB
2758  {
2759  virtual ~IB() {}
2760  };
2761 
2762  struct IA
2763  {
2764  virtual QSharedPointer<IB> getB() = 0;
2765  };
2766 
2767  struct B: public IB
2768  {
2770  B(IA *a_a) :m_a(a_a)
2771  { }
2772  ~B()
2773  {
2774  QSharedPointer<IB> b = m_a->getB();
2775  }
2776  };
2777 
2778  struct A: public IA
2779  {
2781 
2782  virtual QSharedPointer<IB> getB() override
2783  {
2784  return b;
2785  }
2786 
2787  A()
2788  {
2789  b = QSharedPointer<IB>(new B(this));
2790  }
2791 
2792  ~A()
2793  {
2794  b.clear();
2795  }
2796  };
2797 }
2798 
2799 // This is a regression test for QTBUG-11730, where there would be a crash if
2800 // the destructor of a QSharedPointer object being deleted recursed back into
2801 // the same QSharedPointer object. There are no explicit verification steps
2802 // in this test -- it is sufficient that the code does not crash.
2803 void tst_QSharedPointer::reentrancyWhileDestructing()
2804 {
2806 }
2807 
2808 namespace {
2809 struct Base1 {};
2810 struct Base2 {};
2811 
2812 struct Child1 : Base1 {};
2813 struct Child2 : Base2 {};
2814 
2815 template<template<typename> class SmartPtr>
2816 struct Overloaded
2817 {
2818  std::array<int, 1> call(const SmartPtr<const Base1> &)
2819  {
2820  return {};
2821  }
2822  std::array<int, 2> call(const SmartPtr<const Base2> &)
2823  {
2824  return {};
2825  }
2826  static const constexpr uint base1Called = sizeof(std::array<int, 1>);
2827  static const constexpr uint base2Called = sizeof(std::array<int, 2>);
2828 
2829  void test()
2830  {
2831 #define QVERIFY_CALLS(expr, base) static_assert(sizeof(call(expr)) == base##Called)
2832  QVERIFY_CALLS(SmartPtr<Base1>{}, base1);
2833  QVERIFY_CALLS(SmartPtr<Base2>{}, base2);
2834  QVERIFY_CALLS(SmartPtr<const Base1>{}, base1);
2835  QVERIFY_CALLS(SmartPtr<const Base2>{}, base2);
2836  QVERIFY_CALLS(SmartPtr<Child1>{}, base1);
2837  QVERIFY_CALLS(SmartPtr<Child2>{}, base2);
2838  QVERIFY_CALLS(SmartPtr<const Child1>{}, base1);
2839  QVERIFY_CALLS(SmartPtr<const Child2>{}, base2);
2840 #undef QVERIFY_CALLS
2841  }
2842 };
2843 }
2844 
2845 void tst_QSharedPointer::overloads()
2846 {
2847  Overloaded<QSharedPointer> sharedOverloaded;
2848  sharedOverloaded.test();
2849  Overloaded<QWeakPointer> weakOverloaded;
2850  weakOverloaded.test();
2851 }
2852 
2854 #include "tst_qsharedpointer.moc"
small capitals from c petite p scientific f u
Definition: afcover.h:88
small capitals from c petite p scientific i
[1]
Definition: afcover.h:80
#define value
[5]
size_t qHash(const FixStringCacheKey &f)
Definition: cachekeys.h:68
int classLevel() override
void virtualDelete() override
static int derivedDestructorCounter
The QAtomicInt class provides platform-independent atomic operations on int.
Definition: qatomic.h:158
bool ref() noexcept
Definition: qbasicatomic.h:101
The QByteArray class provides an array of bytes.
Definition: qbytearray.h:85
A base class that allows obtaining a QSharedPointer for an object already managed by a shared pointer...
QSharedPointer< T > sharedFromThis()
The QLatin1String class provides a thin wrapper around an US-ASCII/Latin-1 encoded string literal.
Definition: qstring.h:84
The QObject class is the base class of all Qt objects.
Definition: qobject.h:125
Q_INVOKABLE QObject(QObject *parent=nullptr)
Definition: qobject.cpp:913
void swap(QPixmap &other) noexcept
Definition: qpixmap.h:79
bool isNull() const
Definition: qpixmap.cpp:491
bool isNull() const
Definition: qpointer.h:87
static Q_DECL_CONST_FUNCTION QRandomGenerator * global()
Definition: qrandom.h:311
The QSharedPointer class holds a strong reference to a shared pointer.
bool isNull() const noexcept
QSharedPointer< X > constCast() const
QSharedPointer< X > objectCast() const
T * data() const noexcept
QSharedPointer< X > dynamicCast() const
T * get() const noexcept
static QSharedPointer create(Args &&...arguments)
QSharedPointer< X > staticCast() const
void swap(QSharedPointer &other) noexcept
The QString class provides a Unicode character string.
Definition: qstring.h:388
static QString fromLatin1(QByteArrayView ba)
Definition: qstring.cpp:5488
bool tryCompileFail(const QByteArray &body)
bool tryRunFail(const QByteArray &body)
bool tryCompile(const QByteArray &body)
static void usleep(unsigned long)
The QVariant class acts like a union for the most common Qt data types.
Definition: qvariant.h:95
static auto fromValue(const T &value) -> std::enable_if_t< std::is_copy_constructible_v< T >, QVariant >
Definition: qvariant.h:391
The QWeakPointer class holds a weak reference to a shared pointer.
QSharedPointer< T > toStrongRef() const
QSharedPointer< T > lock() const
bool isNull() const noexcept
QSharedPointer< const SomeClass > getSharedPtr() const
QSharedPointer< SomeClass > getSharedPtr()
QSharedPointer< ThreadData > ptr
void run() override
virtual ~Stuffing()
ThreadData(QAtomicInt *p)
static int childDestructorCounter
static int childGenerationCounter
int classLevel() override
void run() override
QWeakPointer< ThreadData > weak
static Wrapper create()
Definition: wrapper.cpp:44
Definition: base.h:37
QPixmap p2
QPixmap p1
[0]
qSwap(pi, e)
qDeleteAll(list.begin(), list.end())
QCOMPARE(spy.count(), 1)
QSharedPointer< ForwardDeclared > * forwardPointer()
int forwardDeclaredDestructorRunCount
void dynamicCastFailureNoLeak()
Definition: nontracked.cpp:83
HBUINT16 Value
QPainterPath body()
Definition: paths.cpp:95
typename C::value_type value_type
typename C::key_type key_type
typename C::mapped_type mapped_type
typename C::iterator iterator
Q_TESTLIB_EXPORT QTestData & newRow(const char *dataTag)
Definition: qtestcase.cpp:2658
auto volatilePreIncrement(T &x)
Definition: qvolatile_p.h:70
Q_AUTOTEST_EXPORT void internalSafetyCheckCleanCheck()
typing.Tuple[int, int] test(str binary_directory, *debug=False)
Definition: qfloat16.h:381
#define QT_WARNING_POP
#define QT_WARNING_PUSH
#define QT_WARNING_DISABLE_CLANG(text)
typedef QByteArray(EGLAPIENTRYP PFNQGSGETDISPLAYSPROC)()
EGLOutputLayerEXT EGLint EGLAttrib value
size_t quintptr
Definition: qglobal.h:310
ptrdiff_t qptrdiff
Definition: qglobal.h:307
unsigned int uint
Definition: qglobal.h:334
@ text
#define qDebug
[1]
Definition: qlogging.h:177
#define qWarning
Definition: qlogging.h:179
#define qFatal
Definition: qlogging.h:181
#define Q_DECLARE_METATYPE(TYPE)
Definition: qmetatype.h:1417
GLboolean GLboolean GLboolean b
GLsizei const GLfloat * v
[13]
GLint GLint GLint GLint GLint x
[0]
GLboolean r
[2]
GLfloat GLfloat GLfloat w
[0]
GLenum GLuint buffer
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLuint counter
GLhandleARB obj
[2]
Definition: qopenglext.h:4164
GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint GLdouble GLdouble w2
Definition: qopenglext.h:12395
const GLubyte * c
Definition: qopenglext.h:12701
GLdouble GLdouble t
[9]
Definition: qopenglext.h:243
GLuint64EXT * result
[6]
Definition: qopenglext.h:10932
GLfloat GLfloat p
[1]
Definition: qopenglext.h:12698
GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint GLdouble w1
Definition: qopenglext.h:12395
#define Q_ASSERT(cond)
Definition: qrandom.cpp:84
@ Data
#define QStringLiteral(str)
#define sp
#define k0
#define k1
#define QTEST_MAIN(TestObject)
Definition: qtest.h:664
#define QSKIP(statement,...)
Definition: qtestcase.h:222
#define QFETCH(Type, name)
Definition: qtestcase.h:230
#define QVERIFY_THROWS_EXCEPTION(exceptiontype,...)
Definition: qtestcase.h:121
#define QFAIL(message)
Definition: qtestcase.h:70
#define QVERIFY(statement)
Definition: qtestcase.h:64
#define Q_OBJECT
Definition: qtmetamacros.h:158
#define slots
Definition: qtmetamacros.h:76
Q_UNUSED(salary)
[21]
QByteArray ba
[0]
QString base
QSharedPointer< T > other(t)
[5]
QWeakPointer< int > weakref
[10]
QSharedPointer< int > strong
QStringList::Iterator it
void operator()(T *ptr)
CustomDeleter(const CustomDeleter &)
virtual void virtualDelete()
static int destructorCounter
virtual int classLevel()
bool alsoDelete()
void doDelete()
virtual ~Data()
static int generationCounter
static int destructorCounter
static int destructorCounter
NoDefaultConstructor2(void *ptr, int i)
NoDefaultConstructorConstRef2(const QString &str, int i)
NoDefaultConstructorConstRef2(const QByteArray &ba, int i=42)
NoDefaultConstructorRRef2(std::unique_ptr< int > &&i)
std::unique_ptr< int > i
NoDefaultConstructorRef2(QString &str, int i)
virtual QSharedPointer< IB > getB() override
virtual QSharedPointer< IB > getB()=0
Definition: main.cpp:38
Definition: inftrees.h:24
int SomeClass
[6]
Definition: threads.cpp:93
void testFunction()
void hashAndMapTest()
void customDeleterFn(Data *ptr)
void functionDataByValue(QSharedPointer< Data > p)
void customQObjectDeleterFn(QObject *obj)
void functionDataByRef(const QSharedPointer< Data > &p)
#define QVERIFY_CALLS(expr, base)