Bug Summary

File:build/source/openmp/libomptarget/src/api.cpp
Warning:line 260, column 3
Undefined or garbage value returned to caller

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 api.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 -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -ffunction-sections -fdata-sections -fcoverage-compilation-dir=/build/source/build-llvm/tools/clang/stage2-bins -resource-dir /usr/lib/llvm-16/lib/clang/16.0.0 -D _DEBUG -D _GNU_SOURCE -D __STDC_CONSTANT_MACROS -D __STDC_FORMAT_MACROS -D __STDC_LIMIT_MACROS -I projects/openmp/libomptarget/src -I /build/source/openmp/libomptarget/src -I include -I /build/source/llvm/include -I /build/source/openmp/libomptarget/include -D _FORTIFY_SOURCE=2 -D NDEBUG -U NDEBUG -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/x86_64-linux-gnu/c++/10 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/backward -internal-isystem /usr/lib/llvm-16/lib/clang/16.0.0/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -fmacro-prefix-map=/build/source/build-llvm/tools/clang/stage2-bins=build-llvm/tools/clang/stage2-bins -fmacro-prefix-map=/build/source/= -fcoverage-prefix-map=/build/source/build-llvm/tools/clang/stage2-bins=build-llvm/tools/clang/stage2-bins -fcoverage-prefix-map=/build/source/= -source-date-epoch 1668078801 -O2 -Wno-unused-command-line-argument -Wno-unused-parameter -Wwrite-strings -Wno-missing-field-initializers -Wno-long-long -Wno-maybe-uninitialized -Wno-class-memaccess -Wno-redundant-move -Wno-pessimizing-move -Wno-noexcept-type -Wno-comment -Wno-misleading-indentation -Wno-enum-constexpr-conversion -Wno-extra -Wno-pedantic -Wno-maybe-uninitialized -std=c++17 -fdeprecated-macro -fdebug-compilation-dir=/build/source/build-llvm/tools/clang/stage2-bins -fdebug-prefix-map=/build/source/build-llvm/tools/clang/stage2-bins=build-llvm/tools/clang/stage2-bins -fdebug-prefix-map=/build/source/= -ferror-limit 19 -fvisibility-inlines-hidden -stack-protector 2 -fgnuc-version=4.2.1 -fcolor-diagnostics -vectorize-loops -vectorize-slp -analyzer-output=html -analyzer-config stable-report-filename=true -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2022-11-10-135928-647445-1 -x c++ /build/source/openmp/libomptarget/src/api.cpp
1//===----------- api.cpp - Target independent OpenMP target RTL -----------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// Implementation of OpenMP API interface functions.
10//
11//===----------------------------------------------------------------------===//
12
13#include "device.h"
14#include "omptarget.h"
15#include "private.h"
16#include "rtl.h"
17
18#include <climits>
19#include <cstdlib>
20#include <cstring>
21
22EXTERNextern "C" int omp_get_num_devices(void) {
23 TIMESCOPE()llvm::TimeTraceScope TimeScope(__FUNCTION__);
24 PM->RTLsMtx.lock();
25 size_t DevicesSize = PM->Devices.size();
26 PM->RTLsMtx.unlock();
27
28 DP("Call to omp_get_num_devices returning %zd\n", DevicesSize){};
29
30 return DevicesSize;
31}
32
33EXTERNextern "C" int omp_get_device_num(void) {
34 TIMESCOPE()llvm::TimeTraceScope TimeScope(__FUNCTION__);
35 int HostDevice = omp_get_initial_device();
36
37 DP("Call to omp_get_device_num returning %d\n", HostDevice){};
38
39 return HostDevice;
40}
41
42EXTERNextern "C" int omp_get_initial_device(void) {
43 TIMESCOPE()llvm::TimeTraceScope TimeScope(__FUNCTION__);
44 int HostDevice = omp_get_num_devices();
45 DP("Call to omp_get_initial_device returning %d\n", HostDevice){};
46 return HostDevice;
47}
48
49EXTERNextern "C" void *omp_target_alloc(size_t Size, int DeviceNum) {
50 return targetAllocExplicit(Size, DeviceNum, TARGET_ALLOC_DEFAULT, __func__);
51}
52
53EXTERNextern "C" void *llvm_omp_target_alloc_device(size_t Size, int DeviceNum) {
54 return targetAllocExplicit(Size, DeviceNum, TARGET_ALLOC_DEVICE, __func__);
55}
56
57EXTERNextern "C" void *llvm_omp_target_alloc_host(size_t Size, int DeviceNum) {
58 return targetAllocExplicit(Size, DeviceNum, TARGET_ALLOC_HOST, __func__);
59}
60
61EXTERNextern "C" void *llvm_omp_target_alloc_shared(size_t Size, int DeviceNum) {
62 return targetAllocExplicit(Size, DeviceNum, TARGET_ALLOC_SHARED, __func__);
63}
64
65EXTERNextern "C" void omp_target_free(void *Ptr, int DeviceNum) {
66 return targetFreeExplicit(Ptr, DeviceNum, TARGET_ALLOC_DEFAULT, __func__);
67}
68
69EXTERNextern "C" void llvm_omp_target_free_device(void *Ptr, int DeviceNum) {
70 return targetFreeExplicit(Ptr, DeviceNum, TARGET_ALLOC_DEVICE, __func__);
71}
72
73EXTERNextern "C" void llvm_omp_target_free_host(void *Ptr, int DeviceNum) {
74 return targetFreeExplicit(Ptr, DeviceNum, TARGET_ALLOC_HOST, __func__);
75}
76
77EXTERNextern "C" void llvm_omp_target_free_shared(void *Ptre, int DeviceNum) {
78 return targetFreeExplicit(Ptre, DeviceNum, TARGET_ALLOC_SHARED, __func__);
79}
80
81EXTERNextern "C" void *llvm_omp_target_dynamic_shared_alloc() { return nullptr; }
82EXTERNextern "C" void *llvm_omp_get_dynamic_shared() { return nullptr; }
83
84EXTERNextern "C" int omp_target_is_present(const void *Ptr, int DeviceNum) {
85 TIMESCOPE()llvm::TimeTraceScope TimeScope(__FUNCTION__);
86 DP("Call to omp_target_is_present for device %d and address " DPxMOD "\n",{}
87 DeviceNum, DPxPTR(Ptr)){};
88
89 if (!Ptr) {
90 DP("Call to omp_target_is_present with NULL ptr, returning false\n"){};
91 return false;
92 }
93
94 if (DeviceNum == omp_get_initial_device()) {
95 DP("Call to omp_target_is_present on host, returning true\n"){};
96 return true;
97 }
98
99 PM->RTLsMtx.lock();
100 size_t DevicesSize = PM->Devices.size();
101 PM->RTLsMtx.unlock();
102 if (DevicesSize <= (size_t)DeviceNum) {
103 DP("Call to omp_target_is_present with invalid device ID, returning "{}
104 "false\n"){};
105 return false;
106 }
107
108 DeviceTy &Device = *PM->Devices[DeviceNum];
109 bool IsLast; // not used
110 bool IsHostPtr;
111 // omp_target_is_present tests whether a host pointer refers to storage that
112 // is mapped to a given device. However, due to the lack of the storage size,
113 // only check 1 byte. Cannot set size 0 which checks whether the pointer (zero
114 // lengh array) is mapped instead of the referred storage.
115 TargetPointerResultTy TPR =
116 Device.getTgtPtrBegin(const_cast<void *>(Ptr), 1, IsLast,
117 /*UpdateRefCount=*/false,
118 /*UseHoldRefCount=*/false, IsHostPtr);
119 int Rc = TPR.isPresent();
120 DP("Call to omp_target_is_present returns %d\n", Rc){};
121 return Rc;
122}
123
124EXTERNextern "C" int omp_target_memcpy(void *Dst, const void *Src, size_t Length,
125 size_t DstOffset, size_t SrcOffset, int DstDevice,
126 int SrcDevice) {
127 TIMESCOPE()llvm::TimeTraceScope TimeScope(__FUNCTION__);
128 DP("Call to omp_target_memcpy, dst device %d, src device %d, "{}
129 "dst addr " DPxMOD ", src addr " DPxMOD ", dst offset %zu, "{}
130 "src offset %zu, length %zu\n",{}
131 DstDevice, SrcDevice, DPxPTR(Dst), DPxPTR(Src), DstOffset, SrcOffset,{}
132 Length){};
133
134 if (!Dst || !Src || Length <= 0) {
135 if (Length == 0) {
136 DP("Call to omp_target_memcpy with zero length, nothing to do\n"){};
137 return OFFLOAD_SUCCESS(0);
138 }
139
140 REPORT("Call to omp_target_memcpy with invalid arguments\n")do { fprintf(stderr, "Libomptarget" " error: "); fprintf(stderr
, "Call to omp_target_memcpy with invalid arguments\n"); } while
(0);
;
141 return OFFLOAD_FAIL(~0);
142 }
143
144 if (SrcDevice != omp_get_initial_device() && !deviceIsReady(SrcDevice)) {
145 REPORT("omp_target_memcpy returns OFFLOAD_FAIL\n")do { fprintf(stderr, "Libomptarget" " error: "); fprintf(stderr
, "omp_target_memcpy returns OFFLOAD_FAIL\n"); } while (0);
;
146 return OFFLOAD_FAIL(~0);
147 }
148
149 if (DstDevice != omp_get_initial_device() && !deviceIsReady(DstDevice)) {
150 REPORT("omp_target_memcpy returns OFFLOAD_FAIL\n")do { fprintf(stderr, "Libomptarget" " error: "); fprintf(stderr
, "omp_target_memcpy returns OFFLOAD_FAIL\n"); } while (0);
;
151 return OFFLOAD_FAIL(~0);
152 }
153
154 int Rc = OFFLOAD_SUCCESS(0);
155 void *SrcAddr = (char *)const_cast<void *>(Src) + SrcOffset;
156 void *DstAddr = (char *)Dst + DstOffset;
157
158 if (SrcDevice == omp_get_initial_device() &&
159 DstDevice == omp_get_initial_device()) {
160 DP("copy from host to host\n"){};
161 const void *P = memcpy(DstAddr, SrcAddr, Length);
162 if (P == NULL__null)
163 Rc = OFFLOAD_FAIL(~0);
164 } else if (SrcDevice == omp_get_initial_device()) {
165 DP("copy from host to device\n"){};
166 DeviceTy &DstDev = *PM->Devices[DstDevice];
167 AsyncInfoTy AsyncInfo(DstDev);
168 Rc = DstDev.submitData(DstAddr, SrcAddr, Length, AsyncInfo);
169 } else if (DstDevice == omp_get_initial_device()) {
170 DP("copy from device to host\n"){};
171 DeviceTy &SrcDev = *PM->Devices[SrcDevice];
172 AsyncInfoTy AsyncInfo(SrcDev);
173 Rc = SrcDev.retrieveData(DstAddr, SrcAddr, Length, AsyncInfo);
174 } else {
175 DP("copy from device to device\n"){};
176 DeviceTy &SrcDev = *PM->Devices[SrcDevice];
177 DeviceTy &DstDev = *PM->Devices[DstDevice];
178 // First try to use D2D memcpy which is more efficient. If fails, fall back
179 // to unefficient way.
180 if (SrcDev.isDataExchangable(DstDev)) {
181 AsyncInfoTy AsyncInfo(SrcDev);
182 Rc = SrcDev.dataExchange(SrcAddr, DstDev, DstAddr, Length, AsyncInfo);
183 if (Rc == OFFLOAD_SUCCESS(0))
184 return OFFLOAD_SUCCESS(0);
185 }
186
187 void *Buffer = malloc(Length);
188 {
189 AsyncInfoTy AsyncInfo(SrcDev);
190 Rc = SrcDev.retrieveData(Buffer, SrcAddr, Length, AsyncInfo);
191 }
192 if (Rc == OFFLOAD_SUCCESS(0)) {
193 AsyncInfoTy AsyncInfo(DstDev);
194 Rc = DstDev.submitData(DstAddr, Buffer, Length, AsyncInfo);
195 }
196 free(Buffer);
197 }
198
199 DP("omp_target_memcpy returns %d\n", Rc){};
200 return Rc;
201}
202
203EXTERNextern "C" int
204omp_target_memcpy_rect(void *Dst, const void *Src, size_t ElementSize,
205 int NumDims, const size_t *Volume,
206 const size_t *DstOffsets, const size_t *SrcOffsets,
207 const size_t *DstDimensions, const size_t *SrcDimensions,
208 int DstDevice, int SrcDevice) {
209 TIMESCOPE()llvm::TimeTraceScope TimeScope(__FUNCTION__);
210 DP("Call to omp_target_memcpy_rect, dst device %d, src device %d, "{}
211 "dst addr " DPxMOD ", src addr " DPxMOD ", dst offsets " DPxMOD ", "{}
212 "src offsets " DPxMOD ", dst dims " DPxMOD ", src dims " DPxMOD ", "{}
213 "volume " DPxMOD ", element size %zu, num_dims %d\n",{}
214 DstDevice, SrcDevice, DPxPTR(Dst), DPxPTR(Src), DPxPTR(DstOffsets),{}
215 DPxPTR(SrcOffsets), DPxPTR(DstDimensions), DPxPTR(SrcDimensions),{}
216 DPxPTR(Volume), ElementSize, NumDims){};
217
218 if (!(Dst || Src)) {
1
Assuming 'Dst' is non-null
219 DP("Call to omp_target_memcpy_rect returns max supported dimensions %d\n",{}
220 INT_MAX){};
221 return INT_MAX2147483647;
222 }
223
224 if (!Dst
1.1
'Dst' is non-null
|| !Src || ElementSize < 1 || NumDims < 1 || !Volume ||
2
Assuming 'Src' is non-null
3
Assuming 'ElementSize' is >= 1
4
Assuming 'NumDims' is >= 1
5
Assuming 'Volume' is non-null
10
Taking false branch
225 !DstOffsets || !SrcOffsets || !DstDimensions || !SrcDimensions) {
6
Assuming 'DstOffsets' is non-null
7
Assuming 'SrcOffsets' is non-null
8
Assuming 'DstDimensions' is non-null
9
Assuming 'SrcDimensions' is non-null
226 REPORT("Call to omp_target_memcpy_rect with invalid arguments\n")do { fprintf(stderr, "Libomptarget" " error: "); fprintf(stderr
, "Call to omp_target_memcpy_rect with invalid arguments\n");
} while (0);
;
227 return OFFLOAD_FAIL(~0);
228 }
229
230 int Rc;
11
'Rc' declared without an initial value
231 if (NumDims == 1) {
12
Assuming 'NumDims' is not equal to 1
13
Taking false branch
232 Rc = omp_target_memcpy(Dst, Src, ElementSize * Volume[0],
233 ElementSize * DstOffsets[0],
234 ElementSize * SrcOffsets[0], DstDevice, SrcDevice);
235 } else {
236 size_t DstSliceSize = ElementSize;
237 size_t SrcSliceSize = ElementSize;
238 for (int I = 1; I
13.1
'I' is < 'NumDims'
< NumDims
; ++I) {
14
Loop condition is true. Entering loop body
15
Assuming 'I' is >= 'NumDims'
16
Loop condition is false. Execution continues on line 243
239 DstSliceSize *= DstDimensions[I];
240 SrcSliceSize *= SrcDimensions[I];
241 }
242
243 size_t DstOff = DstOffsets[0] * DstSliceSize;
244 size_t SrcOff = SrcOffsets[0] * SrcSliceSize;
245 for (size_t I = 0; I < Volume[0]; ++I) {
17
Assuming the condition is false
18
Loop condition is false. Execution continues on line 260
246 Rc = omp_target_memcpy_rect(
247 (char *)Dst + DstOff + DstSliceSize * I,
248 (char *)const_cast<void *>(Src) + SrcOff + SrcSliceSize * I,
249 ElementSize, NumDims - 1, Volume + 1, DstOffsets + 1, SrcOffsets + 1,
250 DstDimensions + 1, SrcDimensions + 1, DstDevice, SrcDevice);
251
252 if (Rc) {
253 DP("Recursive call to omp_target_memcpy_rect returns unsuccessfully\n"){};
254 return Rc;
255 }
256 }
257 }
258
259 DP("omp_target_memcpy_rect returns %d\n", Rc){};
260 return Rc;
19
Undefined or garbage value returned to caller
261}
262
263EXTERNextern "C" int omp_target_associate_ptr(const void *HostPtr, const void *DevicePtr,
264 size_t Size, size_t DeviceOffset,
265 int DeviceNum) {
266 TIMESCOPE()llvm::TimeTraceScope TimeScope(__FUNCTION__);
267 DP("Call to omp_target_associate_ptr with host_ptr " DPxMOD ", "{}
268 "device_ptr " DPxMOD ", size %zu, device_offset %zu, device_num %d\n",{}
269 DPxPTR(HostPtr), DPxPTR(DevicePtr), Size, DeviceOffset, DeviceNum){};
270
271 if (!HostPtr || !DevicePtr || Size <= 0) {
272 REPORT("Call to omp_target_associate_ptr with invalid arguments\n")do { fprintf(stderr, "Libomptarget" " error: "); fprintf(stderr
, "Call to omp_target_associate_ptr with invalid arguments\n"
); } while (0);
;
273 return OFFLOAD_FAIL(~0);
274 }
275
276 if (DeviceNum == omp_get_initial_device()) {
277 REPORT("omp_target_associate_ptr: no association possible on the host\n")do { fprintf(stderr, "Libomptarget" " error: "); fprintf(stderr
, "omp_target_associate_ptr: no association possible on the host\n"
); } while (0);
;
278 return OFFLOAD_FAIL(~0);
279 }
280
281 if (!deviceIsReady(DeviceNum)) {
282 REPORT("omp_target_associate_ptr returns OFFLOAD_FAIL\n")do { fprintf(stderr, "Libomptarget" " error: "); fprintf(stderr
, "omp_target_associate_ptr returns OFFLOAD_FAIL\n"); } while
(0);
;
283 return OFFLOAD_FAIL(~0);
284 }
285
286 DeviceTy &Device = *PM->Devices[DeviceNum];
287 void *DeviceAddr = (void *)((uint64_t)DevicePtr + (uint64_t)DeviceOffset);
288 int Rc = Device.associatePtr(const_cast<void *>(HostPtr),
289 const_cast<void *>(DeviceAddr), Size);
290 DP("omp_target_associate_ptr returns %d\n", Rc){};
291 return Rc;
292}
293
294EXTERNextern "C" int omp_target_disassociate_ptr(const void *HostPtr, int DeviceNum) {
295 TIMESCOPE()llvm::TimeTraceScope TimeScope(__FUNCTION__);
296 DP("Call to omp_target_disassociate_ptr with host_ptr " DPxMOD ", "{}
297 "device_num %d\n",{}
298 DPxPTR(HostPtr), DeviceNum){};
299
300 if (!HostPtr) {
301 REPORT("Call to omp_target_associate_ptr with invalid host_ptr\n")do { fprintf(stderr, "Libomptarget" " error: "); fprintf(stderr
, "Call to omp_target_associate_ptr with invalid host_ptr\n")
; } while (0);
;
302 return OFFLOAD_FAIL(~0);
303 }
304
305 if (DeviceNum == omp_get_initial_device()) {
306 REPORT(do { fprintf(stderr, "Libomptarget" " error: "); fprintf(stderr
, "omp_target_disassociate_ptr: no association possible on the host\n"
); } while (0);
307 "omp_target_disassociate_ptr: no association possible on the host\n")do { fprintf(stderr, "Libomptarget" " error: "); fprintf(stderr
, "omp_target_disassociate_ptr: no association possible on the host\n"
); } while (0);
;
308 return OFFLOAD_FAIL(~0);
309 }
310
311 if (!deviceIsReady(DeviceNum)) {
312 REPORT("omp_target_disassociate_ptr returns OFFLOAD_FAIL\n")do { fprintf(stderr, "Libomptarget" " error: "); fprintf(stderr
, "omp_target_disassociate_ptr returns OFFLOAD_FAIL\n"); } while
(0);
;
313 return OFFLOAD_FAIL(~0);
314 }
315
316 DeviceTy &Device = *PM->Devices[DeviceNum];
317 int Rc = Device.disassociatePtr(const_cast<void *>(HostPtr));
318 DP("omp_target_disassociate_ptr returns %d\n", Rc){};
319 return Rc;
320}