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 derived.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 -relaxed-aliasing -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-17/lib/clang/17 -isystem /build/source/llvm/../mlir/include -isystem tools/mlir/include -isystem tools/clang/include -isystem /build/source/llvm/../clang/include -D FLANG_INCLUDE_TESTS=1 -D FLANG_LITTLE_ENDIAN=1 -D FLANG_VENDOR="Debian " -D _DEBUG -D _GLIBCXX_ASSERTIONS -D _GNU_SOURCE -D _LIBCPP_ENABLE_ASSERTIONS -D __STDC_CONSTANT_MACROS -D __STDC_FORMAT_MACROS -D __STDC_LIMIT_MACROS -I tools/flang/runtime -I /build/source/flang/runtime -I /build/source/flang/include -I tools/flang/include -I include -I /build/source/llvm/include -D _FORTIFY_SOURCE=2 -D NDEBUG -U _GLIBCXX_ASSERTIONS -U _LIBCPP_ENABLE_ASSERTIONS -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-17/lib/clang/17/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 1683717183 -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-deprecated-copy -Wno-ctad-maybe-unsupported -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-2023-05-10-133810-16478-1 -x c++ /build/source/flang/runtime/derived.cpp
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | #include "derived.h" |
10 | #include "stat.h" |
11 | #include "terminator.h" |
12 | #include "type-info.h" |
13 | #include "flang/Runtime/descriptor.h" |
14 | |
15 | namespace Fortran::runtime { |
16 | |
17 | int Initialize(const Descriptor &instance, const typeInfo::DerivedType &derived, |
18 | Terminator &terminator, bool hasStat, const Descriptor *errMsg) { |
19 | const Descriptor &componentDesc{derived.component()}; |
20 | std::size_t elements{instance.Elements()}; |
21 | std::size_t byteStride{instance.ElementBytes()}; |
22 | int stat{StatOk}; |
23 | |
24 | |
25 | std::size_t myComponents{componentDesc.Elements()}; |
26 | for (std::size_t k{0}; k < myComponents; ++k) { |
| 1 | Assuming 'k' is < 'myComponents' | |
|
| 2 | | Loop condition is true. Entering loop body | |
|
27 | const auto &comp{ |
| 3 | | Dereference of null pointer |
|
28 | *componentDesc.ZeroBasedIndexedElement<typeInfo::Component>(k)}; |
29 | if (comp.genre() == typeInfo::Component::Genre::Allocatable || |
30 | comp.genre() == typeInfo::Component::Genre::Automatic) { |
31 | for (std::size_t j{0}; j < elements; ++j) { |
32 | Descriptor &allocDesc{*instance.OffsetElement<Descriptor>( |
33 | j * byteStride + comp.offset())}; |
34 | comp.EstablishDescriptor(allocDesc, instance, terminator); |
35 | allocDesc.raw().attribute = CFI_attribute_allocatable; |
36 | if (comp.genre() == typeInfo::Component::Genre::Automatic) { |
37 | stat = ReturnError(terminator, allocDesc.Allocate(), errMsg, hasStat); |
38 | if (stat == StatOk) { |
39 | if (const DescriptorAddendum * addendum{allocDesc.Addendum()}) { |
40 | if (const auto *derived{addendum->derivedType()}) { |
41 | if (!derived->noInitializationNeeded()) { |
42 | stat = Initialize( |
43 | allocDesc, *derived, terminator, hasStat, errMsg); |
44 | } |
45 | } |
46 | } |
47 | } |
48 | if (stat != StatOk) { |
49 | break; |
50 | } |
51 | } |
52 | } |
53 | } else if (const void *init{comp.initialization()}) { |
54 | |
55 | |
56 | std::size_t bytes{comp.SizeInBytes(instance)}; |
57 | for (std::size_t j{0}; j < elements; ++j) { |
58 | char *ptr{instance.ZeroBasedIndexedElement<char>(j) + comp.offset()}; |
59 | std::memcpy(ptr, init, bytes); |
60 | } |
61 | } else if (comp.genre() == typeInfo::Component::Genre::Pointer) { |
62 | |
63 | |
64 | |
65 | for (std::size_t j{0}; j < elements; ++j) { |
66 | Descriptor &ptrDesc{*instance.OffsetElement<Descriptor>( |
67 | j * byteStride + comp.offset())}; |
68 | comp.EstablishDescriptor(ptrDesc, instance, terminator); |
69 | ptrDesc.raw().attribute = CFI_attribute_pointer; |
70 | } |
71 | } else if (comp.genre() == typeInfo::Component::Genre::Data && |
72 | comp.derivedType() && !comp.derivedType()->noInitializationNeeded()) { |
73 | |
74 | |
75 | SubscriptValue extent[maxRank]; |
76 | const typeInfo::Value *bounds{comp.bounds()}; |
77 | for (int dim{0}; dim < comp.rank(); ++dim) { |
78 | typeInfo::TypeParameterValue lb{ |
79 | bounds[2 * dim].GetValue(&instance).value_or(0)}; |
80 | typeInfo::TypeParameterValue ub{ |
81 | bounds[2 * dim + 1].GetValue(&instance).value_or(0)}; |
82 | extent[dim] = ub >= lb ? ub - lb + 1 : 0; |
83 | } |
84 | StaticDescriptor<maxRank, true, 0> staticDescriptor; |
85 | Descriptor &compDesc{staticDescriptor.descriptor()}; |
86 | const typeInfo::DerivedType &compType{*comp.derivedType()}; |
87 | for (std::size_t j{0}; j < elements; ++j) { |
88 | compDesc.Establish(compType, |
89 | instance.OffsetElement<char>(j * byteStride + comp.offset()), |
90 | comp.rank(), extent); |
91 | stat = Initialize(compDesc, compType, terminator, hasStat, errMsg); |
92 | if (stat != StatOk) { |
93 | break; |
94 | } |
95 | } |
96 | } |
97 | } |
98 | |
99 | const Descriptor &procPtrDesc{derived.procPtr()}; |
100 | std::size_t myProcPtrs{procPtrDesc.Elements()}; |
101 | for (std::size_t k{0}; k < myProcPtrs; ++k) { |
102 | const auto &comp{ |
103 | *procPtrDesc.ZeroBasedIndexedElement<typeInfo::ProcPtrComponent>(k)}; |
104 | for (std::size_t j{0}; j < elements; ++j) { |
105 | auto &pptr{*instance.OffsetElement<typeInfo::ProcedurePointer>( |
106 | j * byteStride + comp.offset)}; |
107 | pptr = comp.procInitialization; |
108 | } |
109 | } |
110 | return stat; |
111 | } |
112 | |
113 | static const typeInfo::SpecialBinding *FindFinal( |
114 | const typeInfo::DerivedType &derived, int rank) { |
115 | if (const auto *ranked{derived.FindSpecialBinding( |
116 | typeInfo::SpecialBinding::RankFinal(rank))}) { |
117 | return ranked; |
118 | } else if (const auto *assumed{derived.FindSpecialBinding( |
119 | typeInfo::SpecialBinding::Which::AssumedRankFinal)}) { |
120 | return assumed; |
121 | } else { |
122 | return derived.FindSpecialBinding( |
123 | typeInfo::SpecialBinding::Which::ElementalFinal); |
124 | } |
125 | } |
126 | |
127 | static void CallFinalSubroutine( |
128 | const Descriptor &descriptor, const typeInfo::DerivedType &derived) { |
129 | if (const auto *special{FindFinal(derived, descriptor.rank())}) { |
130 | |
131 | |
132 | if (special->which() == typeInfo::SpecialBinding::Which::ElementalFinal) { |
133 | std::size_t byteStride{descriptor.ElementBytes()}; |
134 | std::size_t elements{descriptor.Elements()}; |
135 | if (special->IsArgDescriptor(0)) { |
136 | StaticDescriptor<maxRank, true, 8 > statDesc; |
137 | Descriptor &elemDesc{statDesc.descriptor()}; |
138 | elemDesc = descriptor; |
139 | elemDesc.raw().attribute = CFI_attribute_pointer; |
140 | elemDesc.raw().rank = 0; |
141 | auto *p{special->GetProc<void (*)(const Descriptor &)>()}; |
142 | for (std::size_t j{0}; j < elements; ++j) { |
143 | elemDesc.set_base_addr( |
144 | descriptor.OffsetElement<char>(j * byteStride)); |
145 | p(elemDesc); |
146 | } |
147 | } else { |
148 | auto *p{special->GetProc<void (*)(char *)>()}; |
149 | for (std::size_t j{0}; j < elements; ++j) { |
150 | p(descriptor.OffsetElement<char>(j * byteStride)); |
151 | } |
152 | } |
153 | } else if (special->IsArgDescriptor(0)) { |
154 | StaticDescriptor<maxRank, true, 8 > statDesc; |
155 | Descriptor &tmpDesc{statDesc.descriptor()}; |
156 | tmpDesc = descriptor; |
157 | tmpDesc.raw().attribute = CFI_attribute_pointer; |
158 | tmpDesc.Addendum()->set_derivedType(&derived); |
159 | auto *p{special->GetProc<void (*)(const Descriptor &)>()}; |
160 | p(tmpDesc); |
161 | } else { |
162 | auto *p{special->GetProc<void (*)(char *)>()}; |
163 | p(descriptor.OffsetElement<char>()); |
164 | } |
165 | } |
166 | } |
167 | |
168 | |
169 | void Finalize( |
170 | const Descriptor &descriptor, const typeInfo::DerivedType &derived) { |
171 | if (derived.noFinalizationNeeded() || !descriptor.IsAllocated()) { |
172 | return; |
173 | } |
174 | CallFinalSubroutine(descriptor, derived); |
175 | const auto *parentType{derived.GetParentType()}; |
176 | bool recurse{parentType && !parentType->noFinalizationNeeded()}; |
177 | |
178 | |
179 | |
180 | const Descriptor &componentDesc{derived.component()}; |
181 | std::size_t myComponents{componentDesc.Elements()}; |
182 | std::size_t elements{descriptor.Elements()}; |
183 | std::size_t byteStride{descriptor.ElementBytes()}; |
184 | for (auto k{recurse |
185 | ? std::size_t{1} |
186 | : 0}; |
187 | k < myComponents; ++k) { |
188 | const auto &comp{ |
189 | *componentDesc.ZeroBasedIndexedElement<typeInfo::Component>(k)}; |
190 | if (comp.genre() == typeInfo::Component::Genre::Allocatable || |
191 | comp.genre() == typeInfo::Component::Genre::Automatic) { |
192 | if (const typeInfo::DerivedType * compType{comp.derivedType()}) { |
193 | if (!compType->noFinalizationNeeded()) { |
194 | for (std::size_t j{0}; j < elements; ++j) { |
195 | const Descriptor &compDesc{*descriptor.OffsetElement<Descriptor>( |
196 | j * byteStride + comp.offset())}; |
197 | if (compDesc.IsAllocated()) { |
198 | Finalize(compDesc, *compType); |
199 | } |
200 | } |
201 | } |
202 | } |
203 | } else if (comp.genre() == typeInfo::Component::Genre::Data && |
204 | comp.derivedType() && !comp.derivedType()->noFinalizationNeeded()) { |
205 | SubscriptValue extent[maxRank]; |
206 | const typeInfo::Value *bounds{comp.bounds()}; |
207 | for (int dim{0}; dim < comp.rank(); ++dim) { |
208 | SubscriptValue lb{bounds[2 * dim].GetValue(&descriptor).value_or(0)}; |
209 | SubscriptValue ub{ |
210 | bounds[2 * dim + 1].GetValue(&descriptor).value_or(0)}; |
211 | extent[dim] = ub >= lb ? ub - lb + 1 : 0; |
212 | } |
213 | StaticDescriptor<maxRank, true, 0> staticDescriptor; |
214 | Descriptor &compDesc{staticDescriptor.descriptor()}; |
215 | const typeInfo::DerivedType &compType{*comp.derivedType()}; |
216 | for (std::size_t j{0}; j < elements; ++j) { |
217 | compDesc.Establish(compType, |
218 | descriptor.OffsetElement<char>(j * byteStride + comp.offset()), |
219 | comp.rank(), extent); |
220 | Finalize(compDesc, compType); |
221 | } |
222 | } |
223 | } |
224 | if (recurse) { |
225 | Finalize(descriptor, *parentType); |
226 | } |
227 | } |
228 | |
229 | |
230 | |
231 | |
232 | |
233 | void Destroy(const Descriptor &descriptor, bool finalize, |
234 | const typeInfo::DerivedType &derived) { |
235 | if (derived.noDestructionNeeded() || !descriptor.IsAllocated()) { |
236 | return; |
237 | } |
238 | if (finalize && !derived.noFinalizationNeeded()) { |
239 | Finalize(descriptor, derived); |
240 | } |
241 | const Descriptor &componentDesc{derived.component()}; |
242 | std::size_t myComponents{componentDesc.Elements()}; |
243 | std::size_t elements{descriptor.Elements()}; |
244 | SubscriptValue at[maxRank]; |
245 | descriptor.GetLowerBounds(at); |
246 | for (std::size_t k{0}; k < myComponents; ++k) { |
247 | const auto &comp{ |
248 | *componentDesc.ZeroBasedIndexedElement<typeInfo::Component>(k)}; |
249 | if (comp.genre() == typeInfo::Component::Genre::Allocatable || |
250 | comp.genre() == typeInfo::Component::Genre::Automatic) { |
251 | for (std::size_t j{0}; j < elements; ++j) { |
252 | Descriptor *d{reinterpret_cast<Descriptor *>( |
253 | descriptor.Element<char>(at) + comp.offset())}; |
254 | d->Deallocate(); |
255 | descriptor.IncrementSubscripts(at); |
256 | } |
257 | } |
258 | } |
259 | } |
260 | |
261 | } |