225 lines · cpp
1// RUN: %clang_analyze_cc1 -analyzer-checker=core,cplusplus.NewDelete -std=c++11 -verify %s2// RUN: %clang_analyze_cc1 -analyzer-checker=core,cplusplus.NewDeleteLeaks -DLEAKS -std=c++11 -verify %s3// RUN: %clang_analyze_cc1 -analyzer-checker=core,cplusplus.NewDelete -std=c++11 -DTEST_INLINABLE_ALLOCATORS -verify %s4// RUN: %clang_analyze_cc1 -analyzer-checker=core,cplusplus.NewDeleteLeaks -DLEAKS -std=c++11 -DTEST_INLINABLE_ALLOCATORS -verify %s5// RUN: %clang_analyze_cc1 -analyzer-inline-max-stack-depth 2 -analyzer-config ipa-always-inline-size=2 -analyzer-checker=core,cplusplus.NewDelete -std=c++11 -verify %s6// RUN: %clang_analyze_cc1 -analyzer-inline-max-stack-depth 2 -analyzer-config ipa-always-inline-size=2 -analyzer-checker=core,cplusplus.NewDeleteLeaks -DLEAKS -std=c++11 -verify %s7// RUN: %clang_analyze_cc1 -analyzer-inline-max-stack-depth 2 -analyzer-config ipa-always-inline-size=2 -analyzer-checker=core,cplusplus.NewDelete -std=c++11 -DTEST_INLINABLE_ALLOCATORS -verify %s8// RUN: %clang_analyze_cc1 -analyzer-inline-max-stack-depth 2 -analyzer-config ipa-always-inline-size=2 -analyzer-checker=core,cplusplus.NewDeleteLeaks -DLEAKS -std=c++11 -DTEST_INLINABLE_ALLOCATORS -verify %s9 10// expected-no-diagnostics11 12#include "Inputs/system-header-simulator-cxx.h"13 14typedef enum memory_order {15 memory_order_relaxed = __ATOMIC_RELAXED,16 memory_order_consume = __ATOMIC_CONSUME,17 memory_order_acquire = __ATOMIC_ACQUIRE,18 memory_order_release = __ATOMIC_RELEASE,19 memory_order_acq_rel = __ATOMIC_ACQ_REL,20 memory_order_seq_cst = __ATOMIC_SEQ_CST21} memory_order;22 23class RawObj {24 int RefCnt;25 26public:27 int incRef() {28 return __c11_atomic_fetch_add((volatile _Atomic(int) *)&RefCnt, 1,29 memory_order_relaxed);30 }31 32 int decRef() {33 return __c11_atomic_fetch_sub((volatile _Atomic(int) *)&RefCnt, 1,34 memory_order_relaxed);35 }36 37 void foo();38};39 40class StdAtomicObj {41 std::atomic<int> RefCnt;42 43public:44 int incRef() {45 return ++RefCnt;46 }47 48 int decRef() {49 return --RefCnt;50 }51 52 void foo();53};54 55template <typename T>56class IntrusivePtr {57 T *Ptr;58 59public:60 IntrusivePtr(T *Ptr) : Ptr(Ptr) {61 Ptr->incRef();62 }63 64 IntrusivePtr(const IntrusivePtr &Other) : Ptr(Other.Ptr) {65 Ptr->incRef();66 }67 68 ~IntrusivePtr() {69 // We should not take the path on which the object is deleted.70 if (Ptr->decRef() == 1)71 delete Ptr;72 }73 74 T *getPtr() const { return Ptr; } // no-warning75};76 77// Also IntrusivePtr but let's dodge name-based heuristics.78template <typename T>79class DifferentlyNamed {80 T *Ptr;81 82public:83 DifferentlyNamed(T *Ptr) : Ptr(Ptr) {84 Ptr->incRef();85 }86 87 DifferentlyNamed(const DifferentlyNamed &Other) : Ptr(Other.Ptr) {88 Ptr->incRef();89 }90 91 ~DifferentlyNamed() {92 // We should not take the path on which the object is deleted.93 if (Ptr->decRef() == 1)94 delete Ptr;95 }96 97 T *getPtr() const { return Ptr; } // no-warning98};99 100// Also IntrusivePtr with different name and outline release in destructor101template <typename T>102class DifferentlyNamedOutlineRelease {103 T *Ptr;104 105public:106 DifferentlyNamedOutlineRelease(T *Ptr) : Ptr(Ptr) {107 Ptr->incRef();108 }109 110 DifferentlyNamedOutlineRelease(const DifferentlyNamedOutlineRelease &Other) : Ptr(Other.Ptr) {111 Ptr->incRef();112 }113 114 void releasePtr(void) {115 delete Ptr;116 }117 118 ~DifferentlyNamedOutlineRelease() {119 if (Ptr->decRef() == 1)120 releasePtr();121 }122 123 T *getPtr() const { return Ptr; } // no-warning124};125 126void testDestroyLocalRefPtr() {127 IntrusivePtr<RawObj> p1(new RawObj());128 {129 IntrusivePtr<RawObj> p2(p1);130 }131 132 // p1 still maintains ownership. The object is not deleted.133 p1.getPtr()->foo(); // no-warning134}135 136void testDestroySymbolicRefPtr(const IntrusivePtr<RawObj> &p1) {137 {138 IntrusivePtr<RawObj> p2(p1);139 }140 141 // p1 still maintains ownership. The object is not deleted.142 p1.getPtr()->foo(); // no-warning143}144 145void testDestroyLocalRefPtrWithAtomics() {146 IntrusivePtr<StdAtomicObj> p1(new StdAtomicObj());147 {148 IntrusivePtr<StdAtomicObj> p2(p1);149 }150 151 // p1 still maintains ownership. The object is not deleted.152 p1.getPtr()->foo(); // no-warning153}154 155 156void testDestroyLocalRefPtrWithAtomics(const IntrusivePtr<StdAtomicObj> &p1) {157 {158 IntrusivePtr<StdAtomicObj> p2(p1);159 }160 161 // p1 still maintains ownership. The object is not deleted.162 p1.getPtr()->foo(); // no-warning163}164 165void testDestroyLocalRefPtrDifferentlyNamed() {166 DifferentlyNamed<RawObj> p1(new RawObj());167 {168 DifferentlyNamed<RawObj> p2(p1);169 }170 171 // p1 still maintains ownership. The object is not deleted.172 p1.getPtr()->foo(); // no-warning173}174 175void testDestroySymbolicRefPtrDifferentlyNamed(176 const DifferentlyNamed<RawObj> &p1) {177 {178 DifferentlyNamed<RawObj> p2(p1);179 }180 181 // p1 still maintains ownership. The object is not deleted.182 p1.getPtr()->foo(); // no-warning183}184 185void testDestroyLocalRefPtrWithAtomicsDifferentlyNamed() {186 DifferentlyNamed<StdAtomicObj> p1(new StdAtomicObj());187 {188 DifferentlyNamed<StdAtomicObj> p2(p1);189 }190 191 // p1 still maintains ownership. The object is not deleted.192 p1.getPtr()->foo(); // no-warning193}194 195 196void testDestroyLocalRefPtrWithAtomicsDifferentlyNamed(197 const DifferentlyNamed<StdAtomicObj> &p1) {198 {199 DifferentlyNamed<StdAtomicObj> p2(p1);200 }201 202 // p1 still maintains ownership. The object is not deleted.203 p1.getPtr()->foo(); // no-warning204}205 206void testDestroyLocalRefPtrWithOutlineRelease() {207 DifferentlyNamedOutlineRelease <RawObj> p1(new RawObj());208 {209 DifferentlyNamedOutlineRelease <RawObj> p2(p1);210 }211 212 // p1 still maintains ownership. The object is not deleted.213 p1.getPtr()->foo(); // no-warning214}215 216void testDestroySymbolicRefPtrWithOutlineRelease(217 const DifferentlyNamedOutlineRelease<RawObj> &p1) {218 {219 DifferentlyNamedOutlineRelease <RawObj> p2(p1);220 }221 222 // p1 still maintains ownership. The object is not deleted.223 p1.getPtr()->foo(); // no-warning224}225