Bug Summary

File:var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/include/mozilla/cxxalloc.h
Warning:line 51, column 10
Memory allocated by 'operator new' should be deallocated by 'delete', not 'free()'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name SkVertices.cpp -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -relaxed-aliasing -ffp-contract=off -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/gfx/skia -fcoverage-compilation-dir=/var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/gfx/skia -resource-dir /usr/lib/llvm-20/lib/clang/20 -include /var/lib/jenkins/workspace/firefox-scan-build/config/gcc_hidden.h -include /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/mozilla-config.h -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/stl_wrappers -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/system_wrappers -U _FORTIFY_SOURCE -D _FORTIFY_SOURCE=2 -D _GLIBCXX_ASSERTIONS -D DEBUG=1 -D MOZ_SKIA -D SKIA_IMPLEMENTATION=1 -D SK_PDF_USE_HARFBUZZ_SUBSETTING=1 -D MOZ_HAS_MOZGLUE -D MOZILLA_INTERNAL_API -D IMPL_LIBXUL -D MOZ_SUPPORT_LEAKCHECKING -D STATIC_EXPORTABLE_JS_API -I /var/lib/jenkins/workspace/firefox-scan-build/gfx/skia -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/gfx/skia -I /var/lib/jenkins/workspace/firefox-scan-build/gfx/skia/skia -I /var/lib/jenkins/workspace/firefox-scan-build/gfx/cairo/cairo/src -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/include -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/include/nspr -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/include/nss -D MOZILLA_CLIENT -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib/x86_64-linux-gnu/glib-2.0/include -I /usr/include/sysprof-6 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/cairo -I /usr/include/pixman-1 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/x86_64-linux-gnu/c++/14 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/backward -internal-isystem /usr/lib/llvm-20/lib/clang/20/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-error=tautological-type-limit-compare -Wno-invalid-offsetof -Wno-range-loop-analysis -Wno-deprecated-anon-enum-enum-conversion -Wno-deprecated-enum-enum-conversion -Wno-deprecated-this-capture -Wno-inline-new-delete -Wno-error=deprecated-declarations -Wno-error=array-bounds -Wno-error=free-nonheap-object -Wno-error=atomic-alignment -Wno-error=deprecated-builtins -Wno-psabi -Wno-error=builtin-macro-redefined -Wno-vla-cxx-extension -Wno-unknown-warning-option -Wno-deprecated-declarations -Wno-overloaded-virtual -Wno-sign-compare -Wno-unreachable-code -Wno-unused-function -Wno-implicit-fallthrough -Wno-inconsistent-missing-override -Wno-macro-redefined -Wno-unused-private-field -fdeprecated-macro -ferror-limit 19 -fstrict-flex-arrays=1 -stack-protector 2 -fstack-clash-protection -ftrivial-auto-var-init=pattern -fno-rtti -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -fno-sized-deallocation -fno-aligned-allocation -vectorize-loops -vectorize-slp -analyzer-checker optin.performance.Padding -analyzer-output=html -analyzer-config stable-report-filename=true -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2025-01-20-090804-167946-1 -x c++ /var/lib/jenkins/workspace/firefox-scan-build/gfx/skia/skia/src/core/SkVertices.cpp

/var/lib/jenkins/workspace/firefox-scan-build/gfx/skia/skia/src/core/SkVertices.cpp

1/*
2 * Copyright 2017 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7#include "include/core/SkVertices.h"
8
9#include "include/core/SkTypes.h"
10#include "include/private/base/SkMalloc.h"
11#include "include/private/base/SkTo.h"
12#include "src/base/SkSafeMath.h"
13#include "src/core/SkPicturePriv.h"
14#include "src/core/SkReadBuffer.h"
15#include "src/core/SkSafeRange.h"
16#include "src/core/SkVerticesPriv.h"
17#include "src/core/SkWriteBuffer.h"
18
19#include <atomic>
20#include <new>
21#include <utility>
22
23static uint32_t next_id() {
24 static std::atomic<uint32_t> nextID{1};
25
26 uint32_t id;
27 do {
28 id = nextID.fetch_add(1, std::memory_order_relaxed);
29 } while (id == SK_InvalidGenID);
30 return id;
31}
32
33struct SkVertices::Desc {
34 VertexMode fMode;
35 int fVertexCount,
36 fIndexCount;
37 bool fHasTexs,
38 fHasColors;
39};
40
41struct SkVertices::Sizes {
42 Sizes(const Desc& desc) {
43 SkSafeMath safe;
44
45 fVSize = safe.mul(desc.fVertexCount, sizeof(SkPoint));
46 fTSize = desc.fHasTexs ? safe.mul(desc.fVertexCount, sizeof(SkPoint)) : 0;
47 fCSize = desc.fHasColors ? safe.mul(desc.fVertexCount, sizeof(SkColor)) : 0;
48
49 fBuilderTriFanISize = 0;
50 fISize = safe.mul(desc.fIndexCount, sizeof(uint16_t));
51 if (kTriangleFan_VertexMode == desc.fMode) {
52 int numFanTris = 0;
53 if (desc.fIndexCount) {
54 fBuilderTriFanISize = fISize;
55 numFanTris = desc.fIndexCount - 2;
56 } else {
57 numFanTris = desc.fVertexCount - 2;
58 // By forcing this to become indexed we are adding a constraint to the maximum
59 // number of vertices.
60 if (desc.fVertexCount > (SkTo<int>(UINT16_MAX(65535)) + 1)) {
61 sk_bzero(this, sizeof(*this));
62 return;
63 }
64 }
65 if (numFanTris <= 0) {
66 sk_bzero(this, sizeof(*this));
67 return;
68 }
69 fISize = safe.mul(numFanTris, 3 * sizeof(uint16_t));
70 }
71
72 fTotal = safe.add(sizeof(SkVertices),
73 safe.add(fVSize,
74 safe.add(fTSize,
75 safe.add(fCSize,
76 fISize))));
77
78 if (safe.ok()) {
79 fArrays = fVSize + fTSize + fCSize + fISize; // just the sum of the arrays
80 } else {
81 sk_bzero(this, sizeof(*this));
82 }
83 }
84
85 bool isValid() const { return fTotal != 0; }
86
87 size_t fTotal = 0; // size of entire SkVertices allocation (obj + arrays)
88 size_t fArrays; // size of all the data arrays (V + D + T + C + I)
89 size_t fVSize;
90 size_t fTSize;
91 size_t fCSize;
92 size_t fISize;
93
94 // For indexed tri-fans this is the number of amount of space fo indices needed in the builder
95 // before conversion to indexed triangles (or zero if not indexed or not a triangle fan).
96 size_t fBuilderTriFanISize;
97};
98
99SkVertices::Builder::Builder(VertexMode mode, int vertexCount, int indexCount,
100 uint32_t builderFlags) {
101 bool hasTexs = SkToBool(builderFlags & SkVertices::kHasTexCoords_BuilderFlag);
102 bool hasColors = SkToBool(builderFlags & SkVertices::kHasColors_BuilderFlag);
103 this->init({mode, vertexCount, indexCount, hasTexs, hasColors});
104}
105
106SkVertices::Builder::Builder(const Desc& desc) {
107 this->init(desc);
8
Calling 'Builder::init'
12
Returned allocated memory
108}
109
110void SkVertices::Builder::init(const Desc& desc) {
111 Sizes sizes(desc);
112 if (!sizes.isValid()) {
9
Taking false branch
113 SkASSERT(!this->isValid())static_cast<void>( __builtin_expect(static_cast<bool
>(!this->isValid()), 1) ? static_cast<void>(0) : [
]{ do { if (sk_abort_is_enabled()) { do { SkDebugf("%s:%d" ": fatal error: \""
"check(%s)" "\"\n", "/var/lib/jenkins/workspace/firefox-scan-build/gfx/skia/skia/src/core/SkVertices.cpp"
, 113, "!this->isValid()"); ; sk_abort_no_print(); } while
(false); } } while(false); }() )
;
114 return;
115 }
116
117 void* storage = ::operator new (sizes.fTotal);
10
Memory is allocated
118 if (sizes.fBuilderTriFanISize
10.1
Field 'fBuilderTriFanISize' is 0
10.1
Field 'fBuilderTriFanISize' is 0
10.1
Field 'fBuilderTriFanISize' is 0
10.1
Field 'fBuilderTriFanISize' is 0
) {
11
Taking false branch
119 fIntermediateFanIndices.reset(new uint8_t[sizes.fBuilderTriFanISize]);
120 }
121
122 fVertices.reset(new (storage) SkVertices);
123
124 // need to point past the object to store the arrays
125 char* ptr = (char*)storage + sizeof(SkVertices);
126
127 // return the original ptr (or null), but then advance it by size
128 auto advance = [&ptr](size_t size) {
129 char* new_ptr = size ? ptr : nullptr;
130 ptr += size;
131 return new_ptr;
132 };
133
134 fVertices->fPositions = (SkPoint*) advance(sizes.fVSize);
135 fVertices->fTexs = (SkPoint*) advance(sizes.fTSize);
136 fVertices->fColors = (SkColor*) advance(sizes.fCSize);
137 fVertices->fIndices = (uint16_t*)advance(sizes.fISize);
138
139 fVertices->fVertexCount = desc.fVertexCount;
140 fVertices->fIndexCount = desc.fIndexCount;
141 fVertices->fMode = desc.fMode;
142
143 // We defer assigning fBounds and fUniqueID until detach() is called
144}
145
146sk_sp<SkVertices> SkVertices::Builder::detach() {
147 if (fVertices) {
148 fVertices->fBounds.setBounds(fVertices->fPositions, fVertices->fVertexCount);
149 if (fVertices->fMode == kTriangleFan_VertexMode) {
150 if (fIntermediateFanIndices) {
151 SkASSERT(fVertices->fIndexCount)static_cast<void>( __builtin_expect(static_cast<bool
>(fVertices->fIndexCount), 1) ? static_cast<void>
(0) : []{ do { if (sk_abort_is_enabled()) { do { SkDebugf("%s:%d"
": fatal error: \"" "check(%s)" "\"\n", "/var/lib/jenkins/workspace/firefox-scan-build/gfx/skia/skia/src/core/SkVertices.cpp"
, 151, "fVertices->fIndexCount"); ; sk_abort_no_print(); }
while (false); } } while(false); }() )
;
152 auto tempIndices = this->indices();
153 for (int t = 0; t < fVertices->fIndexCount - 2; ++t) {
154 fVertices->fIndices[3 * t + 0] = tempIndices[0];
155 fVertices->fIndices[3 * t + 1] = tempIndices[t + 1];
156 fVertices->fIndices[3 * t + 2] = tempIndices[t + 2];
157 }
158 fVertices->fIndexCount = 3 * (fVertices->fIndexCount - 2);
159 } else {
160 SkASSERT(!fVertices->fIndexCount)static_cast<void>( __builtin_expect(static_cast<bool
>(!fVertices->fIndexCount), 1) ? static_cast<void>
(0) : []{ do { if (sk_abort_is_enabled()) { do { SkDebugf("%s:%d"
": fatal error: \"" "check(%s)" "\"\n", "/var/lib/jenkins/workspace/firefox-scan-build/gfx/skia/skia/src/core/SkVertices.cpp"
, 160, "!fVertices->fIndexCount"); ; sk_abort_no_print(); }
while (false); } } while(false); }() )
;
161 for (int t = 0; t < fVertices->fVertexCount - 2; ++t) {
162 fVertices->fIndices[3 * t + 0] = 0;
163 fVertices->fIndices[3 * t + 1] = SkToU16(t + 1);
164 fVertices->fIndices[3 * t + 2] = SkToU16(t + 2);
165 }
166 fVertices->fIndexCount = 3 * (fVertices->fVertexCount - 2);
167 }
168 fVertices->fMode = kTriangles_VertexMode;
169 }
170 fVertices->fUniqueID = next_id();
171 return std::move(fVertices); // this will null fVertices after the return
172 }
173 return nullptr;
174}
175
176SkPoint* SkVertices::Builder::positions() {
177 return fVertices ? const_cast<SkPoint*>(fVertices->fPositions) : nullptr;
178}
179
180SkPoint* SkVertices::Builder::texCoords() {
181 return fVertices ? const_cast<SkPoint*>(fVertices->fTexs) : nullptr;
182}
183
184SkColor* SkVertices::Builder::colors() {
185 return fVertices ? const_cast<SkColor*>(fVertices->fColors) : nullptr;
186}
187
188uint16_t* SkVertices::Builder::indices() {
189 if (!fVertices) {
190 return nullptr;
191 }
192 if (fIntermediateFanIndices) {
193 return reinterpret_cast<uint16_t*>(fIntermediateFanIndices.get());
194 }
195 return const_cast<uint16_t*>(fVertices->fIndices);
196}
197
198///////////////////////////////////////////////////////////////////////////////////////////////////
199
200sk_sp<SkVertices> SkVertices::MakeCopy(VertexMode mode, int vertexCount,
201 const SkPoint pos[], const SkPoint texs[],
202 const SkColor colors[],
203 int indexCount, const uint16_t indices[]) {
204 auto desc = Desc{mode, vertexCount, indexCount, !!texs, !!colors};
205 Builder builder(desc);
206 if (!builder.isValid()) {
207 return nullptr;
208 }
209
210 Sizes sizes(desc);
211 SkASSERT(sizes.isValid())static_cast<void>( __builtin_expect(static_cast<bool
>(sizes.isValid()), 1) ? static_cast<void>(0) : []{ do
{ if (sk_abort_is_enabled()) { do { SkDebugf("%s:%d" ": fatal error: \""
"check(%s)" "\"\n", "/var/lib/jenkins/workspace/firefox-scan-build/gfx/skia/skia/src/core/SkVertices.cpp"
, 211, "sizes.isValid()"); ; sk_abort_no_print(); } while (false
); } } while(false); }() )
;
212 sk_careful_memcpy(builder.positions(), pos, sizes.fVSize);
213 sk_careful_memcpy(builder.texCoords(), texs, sizes.fTSize);
214 sk_careful_memcpy(builder.colors(), colors, sizes.fCSize);
215 size_t isize = (mode == kTriangleFan_VertexMode) ? sizes.fBuilderTriFanISize : sizes.fISize;
216 sk_careful_memcpy(builder.indices(), indices, isize);
217
218 return builder.detach();
219}
220
221size_t SkVertices::approximateSize() const {
222 return this->getSizes().fTotal;
223}
224
225SkVertices::Sizes SkVertices::getSizes() const {
226 Sizes sizes({fMode, fVertexCount, fIndexCount, !!fTexs, !!fColors});
227 SkASSERT(sizes.isValid())static_cast<void>( __builtin_expect(static_cast<bool
>(sizes.isValid()), 1) ? static_cast<void>(0) : []{ do
{ if (sk_abort_is_enabled()) { do { SkDebugf("%s:%d" ": fatal error: \""
"check(%s)" "\"\n", "/var/lib/jenkins/workspace/firefox-scan-build/gfx/skia/skia/src/core/SkVertices.cpp"
, 227, "sizes.isValid()"); ; sk_abort_no_print(); } while (false
); } } while(false); }() )
;
228 return sizes;
229}
230
231///////////////////////////////////////////////////////////////////////////////////////////////////
232
233// storage = packed | vertex_count | index_count | attr_count
234// | pos[] | custom[] | texs[] | colors[] | indices[]
235
236#define kMode_Mask0x0FF 0x0FF
237#define kHasTexs_Mask0x100 0x100
238#define kHasColors_Mask0x200 0x200
239
240void SkVerticesPriv::encode(SkWriteBuffer& buffer) const {
241 // packed has room for additional flags in the future
242 uint32_t packed = static_cast<uint32_t>(fVertices->fMode);
243 SkASSERT((packed & ~kMode_Mask) == 0)static_cast<void>( __builtin_expect(static_cast<bool
>((packed & ~0x0FF) == 0), 1) ? static_cast<void>
(0) : []{ do { if (sk_abort_is_enabled()) { do { SkDebugf("%s:%d"
": fatal error: \"" "check(%s)" "\"\n", "/var/lib/jenkins/workspace/firefox-scan-build/gfx/skia/skia/src/core/SkVertices.cpp"
, 243, "(packed & ~0x0FF) == 0"); ; sk_abort_no_print(); }
while (false); } } while(false); }() )
; // our mode fits in the mask bits
244 if (fVertices->fTexs) {
245 packed |= kHasTexs_Mask0x100;
246 }
247 if (fVertices->fColors) {
248 packed |= kHasColors_Mask0x200;
249 }
250
251 SkVertices::Sizes sizes = fVertices->getSizes();
252 SkASSERT(!sizes.fBuilderTriFanISize)static_cast<void>( __builtin_expect(static_cast<bool
>(!sizes.fBuilderTriFanISize), 1) ? static_cast<void>
(0) : []{ do { if (sk_abort_is_enabled()) { do { SkDebugf("%s:%d"
": fatal error: \"" "check(%s)" "\"\n", "/var/lib/jenkins/workspace/firefox-scan-build/gfx/skia/skia/src/core/SkVertices.cpp"
, 252, "!sizes.fBuilderTriFanISize"); ; sk_abort_no_print(); }
while (false); } } while(false); }() )
;
253
254 // Header
255 buffer.writeUInt(packed);
256 buffer.writeInt(fVertices->fVertexCount);
257 buffer.writeInt(fVertices->fIndexCount);
258
259 // Data arrays
260 buffer.writeByteArray(fVertices->fPositions, sizes.fVSize);
261 buffer.writeByteArray(fVertices->fTexs, sizes.fTSize);
262 buffer.writeByteArray(fVertices->fColors, sizes.fCSize);
263 // if index-count is odd, we won't be 4-bytes aligned, so we call the pad version
264 buffer.writeByteArray(fVertices->fIndices, sizes.fISize);
265}
266
267sk_sp<SkVertices> SkVerticesPriv::Decode(SkReadBuffer& buffer) {
268 auto decode = [](SkReadBuffer& buffer) -> sk_sp<SkVertices> {
269 SkSafeRange safe;
270 bool hasCustomData = buffer.isVersionLT(SkPicturePriv::kVerticesRemoveCustomData_Version);
271
272 const uint32_t packed = buffer.readUInt();
273 const int vertexCount = safe.checkGE(buffer.readInt(), 0);
274 const int indexCount = safe.checkGE(buffer.readInt(), 0);
275 const int attrCount = hasCustomData
1.1
'hasCustomData' is false
1.1
'hasCustomData' is false
1.1
'hasCustomData' is false
1.1
'hasCustomData' is false
? safe.checkGE(buffer.readInt(), 0) : 0;
2
'?' condition is false
276 const SkVertices::VertexMode mode = safe.checkLE<SkVertices::VertexMode>(
277 packed & kMode_Mask0x0FF, SkVertices::kLast_VertexMode);
278 const bool hasTexs = SkToBool(packed & kHasTexs_Mask0x100);
279 const bool hasColors = SkToBool(packed & kHasColors_Mask0x200);
280
281 // Check that the header fields and buffer are valid. If this is data with the experimental
282 // custom attributes feature - we don't support that any more.
283 // We also don't support serialized triangle-fan data. We stopped writing that long ago,
284 // so it should never appear in valid encoded data.
285 if (!safe || !buffer.isValid() || attrCount
2.1
'attrCount' is 0
2.1
'attrCount' is 0
2.1
'attrCount' is 0
2.1
'attrCount' is 0
||
4
Taking false branch
286 mode == SkVertices::kTriangleFan_VertexMode) {
3
Assuming 'mode' is not equal to kTriangleFan_VertexMode
287 return nullptr;
288 }
289
290 const SkVertices::Desc desc{mode, vertexCount, indexCount, hasTexs, hasColors};
291 SkVertices::Sizes sizes(desc);
292 if (!sizes.isValid() || sizes.fArrays > buffer.available()) {
5
Assuming the condition is false
6
Taking false branch
293 return nullptr;
294 }
295
296 SkVertices::Builder builder(desc);
7
Calling constructor for 'Builder'
13
Returning from constructor for 'Builder'
297 if (!builder.isValid()) {
14
Taking false branch
298 return nullptr;
299 }
300
301 buffer.readByteArray(builder.positions(), sizes.fVSize);
302 if (hasCustomData
14.1
'hasCustomData' is false
14.1
'hasCustomData' is false
14.1
'hasCustomData' is false
14.1
'hasCustomData' is false
) {
15
Taking false branch
303 size_t customDataSize = 0;
304 buffer.skipByteArray(&customDataSize);
305 if (customDataSize != 0) {
306 return nullptr;
307 }
308 }
309 buffer.readByteArray(builder.texCoords(), sizes.fTSize);
310 buffer.readByteArray(builder.colors(), sizes.fCSize);
311 buffer.readByteArray(builder.indices(), sizes.fISize);
312
313 if (!buffer.isValid()) {
16
Taking true branch
314 return nullptr;
17
Calling implicit destructor for 'Builder'
18
Calling '~sk_sp'
315 }
316
317 if (indexCount > 0) {
318 // validate that the indices are in range
319 const uint16_t* indices = builder.indices();
320 for (int i = 0; i < indexCount; ++i) {
321 if (indices[i] >= (unsigned)vertexCount) {
322 return nullptr;
323 }
324 }
325 }
326
327 return builder.detach();
328 };
329
330 if (auto verts = decode(buffer)) {
1
Calling 'operator()'
331 return verts;
332 }
333 buffer.validate(false);
334 return nullptr;
335}
336
337void SkVertices::operator delete(void* p) {
338 ::operator delete(p);
25
Calling 'operator delete'
339}

/var/lib/jenkins/workspace/firefox-scan-build/gfx/skia/skia/include/core/SkVertices.h

1/*
2 * Copyright 2017 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#ifndef SkVertices_DEFINED
9#define SkVertices_DEFINED
10
11#include "include/core/SkColor.h"
12#include "include/core/SkPoint.h"
13#include "include/core/SkRect.h"
14#include "include/core/SkRefCnt.h"
15#include "include/private/base/SkAPI.h"
16
17#include <cstddef>
18#include <cstdint>
19#include <memory>
20
21class SkVerticesPriv;
22
23/**
24 * An immutable set of vertex data that can be used with SkCanvas::drawVertices.
25 */
26class SK_API SkVertices : public SkNVRefCnt<SkVertices> {
27 struct Desc;
28 struct Sizes;
29public:
30 enum VertexMode {
31 kTriangles_VertexMode,
32 kTriangleStrip_VertexMode,
33 kTriangleFan_VertexMode,
34
35 kLast_VertexMode = kTriangleFan_VertexMode,
36 };
37
38 /**
39 * Create a vertices by copying the specified arrays. texs, colors may be nullptr,
40 * and indices is ignored if indexCount == 0.
41 */
42 static sk_sp<SkVertices> MakeCopy(VertexMode mode, int vertexCount,
43 const SkPoint positions[],
44 const SkPoint texs[],
45 const SkColor colors[],
46 int indexCount,
47 const uint16_t indices[]);
48
49 static sk_sp<SkVertices> MakeCopy(VertexMode mode, int vertexCount,
50 const SkPoint positions[],
51 const SkPoint texs[],
52 const SkColor colors[]) {
53 return MakeCopy(mode,
54 vertexCount,
55 positions,
56 texs,
57 colors,
58 0,
59 nullptr);
60 }
61
62 enum BuilderFlags {
63 kHasTexCoords_BuilderFlag = 1 << 0,
64 kHasColors_BuilderFlag = 1 << 1,
65 };
66 class SK_API Builder {
67 public:
68 Builder(VertexMode mode, int vertexCount, int indexCount, uint32_t flags);
69
70 bool isValid() const { return fVertices != nullptr; }
71
72 SkPoint* positions();
73 uint16_t* indices(); // returns null if there are no indices
74
75 // If we have custom attributes, these will always be null
76 SkPoint* texCoords(); // returns null if there are no texCoords
77 SkColor* colors(); // returns null if there are no colors
78
79 // Detach the built vertices object. After the first call, this will always return null.
80 sk_sp<SkVertices> detach();
81
82 private:
83 Builder(const Desc&);
84
85 void init(const Desc&);
86
87 // holds a partially complete object. only completed in detach()
88 sk_sp<SkVertices> fVertices;
89 // Extra storage for intermediate vertices in the case where the client specifies indexed
90 // triangle fans. These get converted to indexed triangles when the Builder is finalized.
91 std::unique_ptr<uint8_t[]> fIntermediateFanIndices;
92
93 friend class SkVertices;
94 friend class SkVerticesPriv;
95 };
96
97 uint32_t uniqueID() const { return fUniqueID; }
98 const SkRect& bounds() const { return fBounds; }
99
100 // returns approximate byte size of the vertices object
101 size_t approximateSize() const;
102
103 // Provides access to functions that aren't part of the public API.
104 SkVerticesPriv priv();
105 const SkVerticesPriv priv() const; // NOLINT(readability-const-return-type)
106
107private:
108 SkVertices() {}
109
110 friend class SkVerticesPriv;
111
112 // these are needed since we've manually sized our allocation (see Builder::init)
113 friend class SkNVRefCnt<SkVertices>;
114 void operator delete(void* p);
115
116 Sizes getSizes() const;
117
118 // we store this first, to pair with the refcnt in our base-class, so we don't have an
119 // unnecessary pad between it and the (possibly 8-byte aligned) ptrs.
120 uint32_t fUniqueID;
121
122 // these point inside our allocation, so none of these can be "freed"
123 SkPoint* fPositions; // [vertexCount]
124 uint16_t* fIndices; // [indexCount] or null
125 SkPoint* fTexs; // [vertexCount] or null
126 SkColor* fColors; // [vertexCount] or null
127
128 SkRect fBounds; // computed to be the union of the fPositions[]
129 int fVertexCount;
130 int fIndexCount;
131
132 VertexMode fMode;
133 // below here is where the actual array data is stored.
134};
135
136#endif

/var/lib/jenkins/workspace/firefox-scan-build/gfx/skia/skia/include/core/SkRefCnt.h

1/*
2 * Copyright 2006 The Android Open Source Project
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#ifndef SkRefCnt_DEFINED
9#define SkRefCnt_DEFINED
10
11#include "include/core/SkTypes.h"
12#include "include/private/base/SkDebug.h"
13
14#include <atomic>
15#include <cstddef>
16#include <cstdint>
17#include <iosfwd>
18#include <type_traits>
19#include <utility>
20
21/** \class SkRefCntBase
22
23 SkRefCntBase is the base class for objects that may be shared by multiple
24 objects. When an existing owner wants to share a reference, it calls ref().
25 When an owner wants to release its reference, it calls unref(). When the
26 shared object's reference count goes to zero as the result of an unref()
27 call, its (virtual) destructor is called. It is an error for the
28 destructor to be called explicitly (or via the object going out of scope on
29 the stack or calling delete) if getRefCnt() > 1.
30*/
31class SK_API SkRefCntBase {
32public:
33 /** Default construct, initializing the reference count to 1.
34 */
35 SkRefCntBase() : fRefCnt(1) {}
36
37 /** Destruct, asserting that the reference count is 1.
38 */
39 virtual ~SkRefCntBase() {
40 #ifdef SK_DEBUG
41 SkASSERTF(this->getRefCnt() == 1, "fRefCnt was %d", this->getRefCnt())static_cast<void>( __builtin_expect(static_cast<bool
>(this->getRefCnt() == 1), 1) ? static_cast<void>
(0) : [&]{ do { if (sk_abort_is_enabled()) { do { SkDebugf
("%s:%d" ": fatal error: \"" "assertf(%s): " "fRefCnt was %d"
"\"\n", "/var/lib/jenkins/workspace/firefox-scan-build/gfx/skia/skia/include/core/SkRefCnt.h"
, 41, "this->getRefCnt() == 1", this->getRefCnt()); ; sk_abort_no_print
(); } while (false); } } while(false); }() )
;
42 // illegal value, to catch us if we reuse after delete
43 fRefCnt.store(0, std::memory_order_relaxed);
44 #endif
45 }
46
47 /** May return true if the caller is the only owner.
48 * Ensures that all previous owner's actions are complete.
49 */
50 bool unique() const {
51 if (1 == fRefCnt.load(std::memory_order_acquire)) {
52 // The acquire barrier is only really needed if we return true. It
53 // prevents code conditioned on the result of unique() from running
54 // until previous owners are all totally done calling unref().
55 return true;
56 }
57 return false;
58 }
59
60 /** Increment the reference count. Must be balanced by a call to unref().
61 */
62 void ref() const {
63 SkASSERT(this->getRefCnt() > 0)static_cast<void>( __builtin_expect(static_cast<bool
>(this->getRefCnt() > 0), 1) ? static_cast<void>
(0) : []{ do { if (sk_abort_is_enabled()) { do { SkDebugf("%s:%d"
": fatal error: \"" "check(%s)" "\"\n", "/var/lib/jenkins/workspace/firefox-scan-build/gfx/skia/skia/include/core/SkRefCnt.h"
, 63, "this->getRefCnt() > 0"); ; sk_abort_no_print(); }
while (false); } } while(false); }() )
;
64 // No barrier required.
65 (void)fRefCnt.fetch_add(+1, std::memory_order_relaxed);
66 }
67
68 /** Decrement the reference count. If the reference count is 1 before the
69 decrement, then delete the object. Note that if this is the case, then
70 the object needs to have been allocated via new, and not on the stack.
71 */
72 void unref() const {
73 SkASSERT(this->getRefCnt() > 0)static_cast<void>( __builtin_expect(static_cast<bool
>(this->getRefCnt() > 0), 1) ? static_cast<void>
(0) : []{ do { if (sk_abort_is_enabled()) { do { SkDebugf("%s:%d"
": fatal error: \"" "check(%s)" "\"\n", "/var/lib/jenkins/workspace/firefox-scan-build/gfx/skia/skia/include/core/SkRefCnt.h"
, 73, "this->getRefCnt() > 0"); ; sk_abort_no_print(); }
while (false); } } while(false); }() )
;
74 // A release here acts in place of all releases we "should" have been doing in ref().
75 if (1 == fRefCnt.fetch_add(-1, std::memory_order_acq_rel)) {
76 // Like unique(), the acquire is only needed on success, to make sure
77 // code in internal_dispose() doesn't happen before the decrement.
78 this->internal_dispose();
79 }
80 }
81
82private:
83
84#ifdef SK_DEBUG
85 /** Return the reference count. Use only for debugging. */
86 int32_t getRefCnt() const {
87 return fRefCnt.load(std::memory_order_relaxed);
88 }
89#endif
90
91 /**
92 * Called when the ref count goes to 0.
93 */
94 virtual void internal_dispose() const {
95 #ifdef SK_DEBUG
96 SkASSERT(0 == this->getRefCnt())static_cast<void>( __builtin_expect(static_cast<bool
>(0 == this->getRefCnt()), 1) ? static_cast<void>
(0) : []{ do { if (sk_abort_is_enabled()) { do { SkDebugf("%s:%d"
": fatal error: \"" "check(%s)" "\"\n", "/var/lib/jenkins/workspace/firefox-scan-build/gfx/skia/skia/include/core/SkRefCnt.h"
, 96, "0 == this->getRefCnt()"); ; sk_abort_no_print(); } while
(false); } } while(false); }() )
;
97 fRefCnt.store(1, std::memory_order_relaxed);
98 #endif
99 delete this;
100 }
101
102 // The following friends are those which override internal_dispose()
103 // and conditionally call SkRefCnt::internal_dispose().
104 friend class SkWeakRefCnt;
105
106 mutable std::atomic<int32_t> fRefCnt;
107
108 SkRefCntBase(SkRefCntBase&&) = delete;
109 SkRefCntBase(const SkRefCntBase&) = delete;
110 SkRefCntBase& operator=(SkRefCntBase&&) = delete;
111 SkRefCntBase& operator=(const SkRefCntBase&) = delete;
112};
113
114#ifdef SK_REF_CNT_MIXIN_INCLUDE
115// It is the responsibility of the following include to define the type SkRefCnt.
116// This SkRefCnt should normally derive from SkRefCntBase.
117#include SK_REF_CNT_MIXIN_INCLUDE
118#else
119class SK_API SkRefCnt : public SkRefCntBase {
120 // "#include SK_REF_CNT_MIXIN_INCLUDE" doesn't work with this build system.
121 #if defined(SK_BUILD_FOR_GOOGLE3)
122 public:
123 void deref() const { this->unref(); }
124 #endif
125};
126#endif
127
128///////////////////////////////////////////////////////////////////////////////
129
130/** Call obj->ref() and return obj. The obj must not be nullptr.
131 */
132template <typename T> static inline T* SkRef(T* obj) {
133 SkASSERT(obj)static_cast<void>( __builtin_expect(static_cast<bool
>(obj), 1) ? static_cast<void>(0) : []{ do { if (sk_abort_is_enabled
()) { do { SkDebugf("%s:%d" ": fatal error: \"" "check(%s)" "\"\n"
, "/var/lib/jenkins/workspace/firefox-scan-build/gfx/skia/skia/include/core/SkRefCnt.h"
, 133, "obj"); ; sk_abort_no_print(); } while (false); } } while
(false); }() )
;
134 obj->ref();
135 return obj;
136}
137
138/** Check if the argument is non-null, and if so, call obj->ref() and return obj.
139 */
140template <typename T> static inline T* SkSafeRef(T* obj) {
141 if (obj) {
142 obj->ref();
143 }
144 return obj;
145}
146
147/** Check if the argument is non-null, and if so, call obj->unref()
148 */
149template <typename T> static inline void SkSafeUnref(T* obj) {
150 if (obj
19.1
'obj' is non-null
19.1
'obj' is non-null
19.1
'obj' is non-null
19.1
'obj' is non-null
) {
20
Taking true branch
151 obj->unref();
21
Calling 'SkNVRefCnt::unref'
152 }
153}
154
155///////////////////////////////////////////////////////////////////////////////
156
157// This is a variant of SkRefCnt that's Not Virtual, so weighs 4 bytes instead of 8 or 16.
158// There's only benefit to using this if the deriving class does not otherwise need a vtable.
159template <typename Derived>
160class SkNVRefCnt {
161public:
162 SkNVRefCnt() : fRefCnt(1) {}
163 ~SkNVRefCnt() {
164 #ifdef SK_DEBUG
165 int rc = fRefCnt.load(std::memory_order_relaxed);
166 SkASSERTF(rc == 1, "NVRefCnt was %d", rc)static_cast<void>( __builtin_expect(static_cast<bool
>(rc == 1), 1) ? static_cast<void>(0) : [&]{ do {
if (sk_abort_is_enabled()) { do { SkDebugf("%s:%d" ": fatal error: \""
"assertf(%s): " "NVRefCnt was %d" "\"\n", "/var/lib/jenkins/workspace/firefox-scan-build/gfx/skia/skia/include/core/SkRefCnt.h"
, 166, "rc == 1", rc); ; sk_abort_no_print(); } while (false)
; } } while(false); }() )
;
167 #endif
168 }
169
170 // Implementation is pretty much the same as SkRefCntBase. All required barriers are the same:
171 // - unique() needs acquire when it returns true, and no barrier if it returns false;
172 // - ref() doesn't need any barrier;
173 // - unref() needs a release barrier, and an acquire if it's going to call delete.
174
175 bool unique() const { return 1 == fRefCnt.load(std::memory_order_acquire); }
176 void ref() const { (void)fRefCnt.fetch_add(+1, std::memory_order_relaxed); }
177 void unref() const {
178 if (1 == fRefCnt.fetch_add(-1, std::memory_order_acq_rel)) {
22
Assuming the condition is true
23
Taking true branch
179 // restore the 1 for our destructor's assert
180 SkDEBUGCODE(fRefCnt.store(1, std::memory_order_relaxed))fRefCnt.store(1, std::memory_order_relaxed);
181 delete (const Derived*)this;
24
Calling 'SkVertices::operator delete'
182 }
183 }
184 void deref() const { this->unref(); }
185
186 // This must be used with caution. It is only valid to call this when 'threadIsolatedTestCnt'
187 // refs are known to be isolated to the current thread. That is, it is known that there are at
188 // least 'threadIsolatedTestCnt' refs for which no other thread may make a balancing unref()
189 // call. Assuming the contract is followed, if this returns false then no other thread has
190 // ownership of this. If it returns true then another thread *may* have ownership.
191 bool refCntGreaterThan(int32_t threadIsolatedTestCnt) const {
192 int cnt = fRefCnt.load(std::memory_order_acquire);
193 // If this fails then the above contract has been violated.
194 SkASSERT(cnt >= threadIsolatedTestCnt)static_cast<void>( __builtin_expect(static_cast<bool
>(cnt >= threadIsolatedTestCnt), 1) ? static_cast<void
>(0) : []{ do { if (sk_abort_is_enabled()) { do { SkDebugf
("%s:%d" ": fatal error: \"" "check(%s)" "\"\n", "/var/lib/jenkins/workspace/firefox-scan-build/gfx/skia/skia/include/core/SkRefCnt.h"
, 194, "cnt >= threadIsolatedTestCnt"); ; sk_abort_no_print
(); } while (false); } } while(false); }() )
;
195 return cnt > threadIsolatedTestCnt;
196 }
197
198private:
199 mutable std::atomic<int32_t> fRefCnt;
200
201 SkNVRefCnt(SkNVRefCnt&&) = delete;
202 SkNVRefCnt(const SkNVRefCnt&) = delete;
203 SkNVRefCnt& operator=(SkNVRefCnt&&) = delete;
204 SkNVRefCnt& operator=(const SkNVRefCnt&) = delete;
205};
206
207///////////////////////////////////////////////////////////////////////////////////////////////////
208
209/**
210 * Shared pointer class to wrap classes that support a ref()/unref() interface.
211 *
212 * This can be used for classes inheriting from SkRefCnt, but it also works for other
213 * classes that match the interface, but have different internal choices: e.g. the hosted class
214 * may have its ref/unref be thread-safe, but that is not assumed/imposed by sk_sp.
215 *
216 * Declared with the trivial_abi attribute where supported so that sk_sp and types containing it
217 * may be considered as trivially relocatable by the compiler so that destroying-move operations
218 * i.e. move constructor followed by destructor can be optimized to memcpy.
219 */
220template <typename T> class SK_TRIVIAL_ABI sk_sp {
221public:
222 using element_type = T;
223
224 constexpr sk_sp() : fPtr(nullptr) {}
225 constexpr sk_sp(std::nullptr_t) : fPtr(nullptr) {}
226
227 /**
228 * Shares the underlying object by calling ref(), so that both the argument and the newly
229 * created sk_sp both have a reference to it.
230 */
231 sk_sp(const sk_sp<T>& that) : fPtr(SkSafeRef(that.get())) {}
232 template <typename U,
233 typename = typename std::enable_if<std::is_convertible<U*, T*>::value>::type>
234 sk_sp(const sk_sp<U>& that) : fPtr(SkSafeRef(that.get())) {}
235
236 /**
237 * Move the underlying object from the argument to the newly created sk_sp. Afterwards only
238 * the new sk_sp will have a reference to the object, and the argument will point to null.
239 * No call to ref() or unref() will be made.
240 */
241 sk_sp(sk_sp<T>&& that) : fPtr(that.release()) {}
242 template <typename U,
243 typename = typename std::enable_if<std::is_convertible<U*, T*>::value>::type>
244 sk_sp(sk_sp<U>&& that) : fPtr(that.release()) {}
245
246 /**
247 * Adopt the bare pointer into the newly created sk_sp.
248 * No call to ref() or unref() will be made.
249 */
250 explicit sk_sp(T* obj) : fPtr(obj) {}
251
252 /**
253 * Calls unref() on the underlying object pointer.
254 */
255 ~sk_sp() {
256 SkSafeUnref(fPtr);
19
Calling 'SkSafeUnref<SkVertices>'
257 SkDEBUGCODE(fPtr = nullptr)fPtr = nullptr;
258 }
259
260 sk_sp<T>& operator=(std::nullptr_t) { this->reset(); return *this; }
261
262 /**
263 * Shares the underlying object referenced by the argument by calling ref() on it. If this
264 * sk_sp previously had a reference to an object (i.e. not null) it will call unref() on that
265 * object.
266 */
267 sk_sp<T>& operator=(const sk_sp<T>& that) {
268 if (this != &that) {
269 this->reset(SkSafeRef(that.get()));
270 }
271 return *this;
272 }
273 template <typename U,
274 typename = typename std::enable_if<std::is_convertible<U*, T*>::value>::type>
275 sk_sp<T>& operator=(const sk_sp<U>& that) {
276 this->reset(SkSafeRef(that.get()));
277 return *this;
278 }
279
280 /**
281 * Move the underlying object from the argument to the sk_sp. If the sk_sp previously held
282 * a reference to another object, unref() will be called on that object. No call to ref()
283 * will be made.
284 */
285 sk_sp<T>& operator=(sk_sp<T>&& that) {
286 this->reset(that.release());
287 return *this;
288 }
289 template <typename U,
290 typename = typename std::enable_if<std::is_convertible<U*, T*>::value>::type>
291 sk_sp<T>& operator=(sk_sp<U>&& that) {
292 this->reset(that.release());
293 return *this;
294 }
295
296 T& operator*() const {
297 SkASSERT(this->get() != nullptr)static_cast<void>( __builtin_expect(static_cast<bool
>(this->get() != nullptr), 1) ? static_cast<void>
(0) : []{ do { if (sk_abort_is_enabled()) { do { SkDebugf("%s:%d"
": fatal error: \"" "check(%s)" "\"\n", "/var/lib/jenkins/workspace/firefox-scan-build/gfx/skia/skia/include/core/SkRefCnt.h"
, 297, "this->get() != nullptr"); ; sk_abort_no_print(); }
while (false); } } while(false); }() )
;
298 return *this->get();
299 }
300
301 explicit operator bool() const { return this->get() != nullptr; }
302
303 T* get() const { return fPtr; }
304 T* operator->() const { return fPtr; }
305
306 /**
307 * Adopt the new bare pointer, and call unref() on any previously held object (if not null).
308 * No call to ref() will be made.
309 */
310 void reset(T* ptr = nullptr) {
311 // Calling fPtr->unref() may call this->~() or this->reset(T*).
312 // http://wg21.cmeerw.net/lwg/issue998
313 // http://wg21.cmeerw.net/lwg/issue2262
314 T* oldPtr = fPtr;
315 fPtr = ptr;
316 SkSafeUnref(oldPtr);
317 }
318
319 /**
320 * Return the bare pointer, and set the internal object pointer to nullptr.
321 * The caller must assume ownership of the object, and manage its reference count directly.
322 * No call to unref() will be made.
323 */
324 [[nodiscard]] T* release() {
325 T* ptr = fPtr;
326 fPtr = nullptr;
327 return ptr;
328 }
329
330 void swap(sk_sp<T>& that) /*noexcept*/ {
331 using std::swap;
332 swap(fPtr, that.fPtr);
333 }
334
335 using sk_is_trivially_relocatable = std::true_type;
336
337private:
338 T* fPtr;
339};
340
341template <typename T> inline void swap(sk_sp<T>& a, sk_sp<T>& b) /*noexcept*/ {
342 a.swap(b);
343}
344
345template <typename T, typename U> inline bool operator==(const sk_sp<T>& a, const sk_sp<U>& b) {
346 return a.get() == b.get();
347}
348template <typename T> inline bool operator==(const sk_sp<T>& a, std::nullptr_t) /*noexcept*/ {
349 return !a;
350}
351template <typename T> inline bool operator==(std::nullptr_t, const sk_sp<T>& b) /*noexcept*/ {
352 return !b;
353}
354
355template <typename T, typename U> inline bool operator!=(const sk_sp<T>& a, const sk_sp<U>& b) {
356 return a.get() != b.get();
357}
358template <typename T> inline bool operator!=(const sk_sp<T>& a, std::nullptr_t) /*noexcept*/ {
359 return static_cast<bool>(a);
360}
361template <typename T> inline bool operator!=(std::nullptr_t, const sk_sp<T>& b) /*noexcept*/ {
362 return static_cast<bool>(b);
363}
364
365template <typename C, typename CT, typename T>
366auto operator<<(std::basic_ostream<C, CT>& os, const sk_sp<T>& sp) -> decltype(os << sp.get()) {
367 return os << sp.get();
368}
369
370template <typename T> sk_sp(T*) -> sk_sp<T>;
371
372template <typename T, typename... Args>
373sk_sp<T> sk_make_sp(Args&&... args) {
374 return sk_sp<T>(new T(std::forward<Args>(args)...));
375}
376
377/*
378 * Returns a sk_sp wrapping the provided ptr AND calls ref on it (if not null).
379 *
380 * This is different than the semantics of the constructor for sk_sp, which just wraps the ptr,
381 * effectively "adopting" it.
382 */
383template <typename T> sk_sp<T> sk_ref_sp(T* obj) {
384 return sk_sp<T>(SkSafeRef(obj));
385}
386
387template <typename T> sk_sp<T> sk_ref_sp(const T* obj) {
388 return sk_sp<T>(const_cast<T*>(SkSafeRef(obj)));
389}
390
391#endif

/var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/include/mozilla/cxxalloc.h

1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5#ifndef mozilla_cxxalloc_h
6#define mozilla_cxxalloc_h
7
8/*
9 * We implement the default operators new/delete as part of
10 * libmozalloc, replacing their definitions in libstdc++. The
11 * operator new* definitions in libmozalloc will never return a NULL
12 * pointer.
13 *
14 * Each operator new immediately below returns a pointer to memory
15 * that can be delete'd by any of
16 *
17 * (1) the matching infallible operator delete immediately below
18 * (2) the matching system |operator delete(void*, std::nothrow)|
19 * (3) the matching system |operator delete(void*) noexcept(false)|
20 *
21 * NB: these are declared |noexcept(false)|, though they will never
22 * throw that exception. This declaration is consistent with the rule
23 * that |::operator new() noexcept(false)| will never return NULL.
24 *
25 * NB: mozilla::fallible can be used instead of std::nothrow.
26 */
27
28#ifndef MOZALLOC_EXPORT_NEW__attribute__((always_inline)) inline
29# define MOZALLOC_EXPORT_NEW__attribute__((always_inline)) inline MFBT_API__attribute__((weak)) __attribute__((visibility("default")))
30#endif
31
32MOZALLOC_EXPORT_NEW__attribute__((always_inline)) inline void* operator new(size_t size) noexcept(false) {
33 return moz_xmalloc(size);
34}
35
36MOZALLOC_EXPORT_NEW__attribute__((always_inline)) inline void* operator new(size_t size,
37 const std::nothrow_t&) noexcept(true) {
38 return malloc_impl(size);
39}
40
41MOZALLOC_EXPORT_NEW__attribute__((always_inline)) inline void* operator new[](size_t size) noexcept(false) {
42 return moz_xmalloc(size);
43}
44
45MOZALLOC_EXPORT_NEW__attribute__((always_inline)) inline void* operator new[](size_t size,
46 const std::nothrow_t&) noexcept(true) {
47 return malloc_impl(size);
48}
49
50MOZALLOC_EXPORT_NEW__attribute__((always_inline)) inline void operator delete(void* ptr) noexcept(true) {
51 return free_impl(ptr);
26
Memory allocated by 'operator new' should be deallocated by 'delete', not 'free()'
52}
53
54MOZALLOC_EXPORT_NEW__attribute__((always_inline)) inline void operator delete(void* ptr,
55 const std::nothrow_t&) noexcept(true) {
56 return free_impl(ptr);
57}
58
59MOZALLOC_EXPORT_NEW__attribute__((always_inline)) inline void operator delete[](void* ptr) noexcept(true) {
60 return free_impl(ptr);
61}
62
63MOZALLOC_EXPORT_NEW__attribute__((always_inline)) inline void operator delete[](
64 void* ptr, const std::nothrow_t&) noexcept(true) {
65 return free_impl(ptr);
66}
67
68#if defined(XP_WIN)
69// We provide the global sized delete overloads unconditionally because the
70// MSVC runtime headers do, despite compiling with /Zc:sizedDealloc-
71MOZALLOC_EXPORT_NEW__attribute__((always_inline)) inline void operator delete(void* ptr,
72 size_t /*size*/) noexcept(true) {
73 return free_impl(ptr);
74}
75
76MOZALLOC_EXPORT_NEW__attribute__((always_inline)) inline void operator delete[](void* ptr,
77 size_t /*size*/) noexcept(true) {
78 return free_impl(ptr);
79}
80#endif
81
82#endif /* mozilla_cxxalloc_h */