Bug Summary

File:src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/lib/Analysis/LoopNestAnalysis.cpp
Warning:line 232, column 3
Returning null reference

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name LoopNestAnalysis.cpp -analyzer-store=region -analyzer-opt-analyze-nested-blocks -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 -mrelocation-model static -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/gnu/usr.bin/clang/libLLVM/obj -resource-dir /usr/local/lib/clang/13.0.0 -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms -I /usr/src/gnu/usr.bin/clang/libLLVM/obj/../include/llvm/AMDGPU -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/lib/Target/AMDGPU -I /usr/src/gnu/usr.bin/clang/libLLVM/obj/../include/llvm/AMDGPU -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/lib/Target/AMDGPU -I /usr/src/gnu/usr.bin/clang/libLLVM/obj/../include/llvm/AMDGPU -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/lib/Target/AMDGPU -I /usr/src/gnu/usr.bin/clang/libLLVM/obj/../include/llvm/AMDGPU -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/lib/Target/AMDGPU -I /usr/src/gnu/usr.bin/clang/libLLVM/obj/../include/llvm/AMDGPU -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/lib/Target/AMDGPU -I /usr/src/gnu/usr.bin/clang/libLLVM/obj/../include/llvm/AMDGPU -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/lib/Target/AMDGPU -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Analysis -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/ASMParser -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/BinaryFormat -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Bitcode -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Bitcode -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Bitstream -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms -I /include/llvm/CodeGen -I /include/llvm/CodeGen/PBQP -I /usr/src/gnu/usr.bin/clang/libLLVM/obj/../include/llvm/IR -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/IR -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms/Coroutines -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/ProfileData/Coverage -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/DebugInfo/CodeView -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/DebugInfo/DWARF -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/DebugInfo -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/DebugInfo/MSF -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/DebugInfo/PDB -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Demangle -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/ExecutionEngine -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/ExecutionEngine/JITLink -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/ExecutionEngine/Orc -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Frontend -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Frontend/OpenACC -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Frontend -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Frontend/OpenMP -I /include/llvm/CodeGen/GlobalISel -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/IRReader -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms/InstCombine -I /usr/src/gnu/usr.bin/clang/libLLVM/obj/../include/llvm/Transforms/InstCombine -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/LTO -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Linker -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/MC -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/MC/MCParser -I /include/llvm/CodeGen/MIRParser -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Object -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Option -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Passes -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/ -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/ProfileData -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms/Scalar -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/ADT -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Support -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/DebugInfo/Symbolize -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Target -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms/Utils -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms/Vectorize -I /usr/src/gnu/usr.bin/clang/libLLVM/obj/../include/llvm/X86 -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/lib/Target/X86 -I /usr/src/gnu/usr.bin/clang/libLLVM/obj/../include/llvm/X86 -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/lib/Target/X86 -I /usr/src/gnu/usr.bin/clang/libLLVM/obj/../include/llvm/X86 -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/lib/Target/X86 -I /usr/src/gnu/usr.bin/clang/libLLVM/obj/../include/llvm/X86 -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/lib/Target/X86 -I /usr/src/gnu/usr.bin/clang/libLLVM/obj/../include/llvm/X86 -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/lib/Target/X86 -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms/IPO -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include -I /usr/src/gnu/usr.bin/clang/libLLVM/../include -I /usr/src/gnu/usr.bin/clang/libLLVM/obj -I /usr/src/gnu/usr.bin/clang/libLLVM/obj/../include -D NDEBUG -D __STDC_LIMIT_MACROS -D __STDC_CONSTANT_MACROS -D __STDC_FORMAT_MACROS -D LLVM_PREFIX="/usr" -internal-isystem /usr/include/c++/v1 -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -Wwrite-strings -Wno-missing-field-initializers -Wno-long-long -Wno-comment -std=c++14 -fdeprecated-macro -fdebug-compilation-dir=/usr/src/gnu/usr.bin/clang/libLLVM/obj -ferror-limit 19 -fvisibility-inlines-hidden -fwrapv -stack-protector 2 -fno-rtti -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/vmm/scan-build/2022-01-12-194120-40624-1 -x c++ /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/lib/Analysis/LoopNestAnalysis.cpp

/usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/lib/Analysis/LoopNestAnalysis.cpp

1//===- LoopNestAnalysis.cpp - Loop Nest Analysis --------------------------==//
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/// \file
10/// The implementation for the loop nest analysis.
11///
12//===----------------------------------------------------------------------===//
13
14#include "llvm/Analysis/LoopNestAnalysis.h"
15#include "llvm/ADT/BreadthFirstIterator.h"
16#include "llvm/ADT/Statistic.h"
17#include "llvm/Analysis/PostDominators.h"
18#include "llvm/Analysis/ValueTracking.h"
19
20using namespace llvm;
21
22#define DEBUG_TYPE"loopnest" "loopnest"
23#ifndef NDEBUG1
24static const char *VerboseDebug = DEBUG_TYPE"loopnest" "-verbose";
25#endif
26
27/// Determine whether the loops structure violates basic requirements for
28/// perfect nesting:
29/// - the inner loop should be the outer loop's only child
30/// - the outer loop header should 'flow' into the inner loop preheader
31/// or jump around the inner loop to the outer loop latch
32/// - if the inner loop latch exits the inner loop, it should 'flow' into
33/// the outer loop latch.
34/// Returns true if the loop structure satisfies the basic requirements and
35/// false otherwise.
36static bool checkLoopsStructure(const Loop &OuterLoop, const Loop &InnerLoop,
37 ScalarEvolution &SE);
38
39//===----------------------------------------------------------------------===//
40// LoopNest implementation
41//
42
43LoopNest::LoopNest(Loop &Root, ScalarEvolution &SE)
44 : MaxPerfectDepth(getMaxPerfectDepth(Root, SE)) {
4
Calling 'LoopNest::getMaxPerfectDepth'
45 append_range(Loops, breadth_first(&Root));
46}
47
48std::unique_ptr<LoopNest> LoopNest::getLoopNest(Loop &Root,
49 ScalarEvolution &SE) {
50 return std::make_unique<LoopNest>(Root, SE);
2
Calling 'make_unique<llvm::LoopNest, llvm::Loop &, llvm::ScalarEvolution &>'
51}
52
53bool LoopNest::arePerfectlyNested(const Loop &OuterLoop, const Loop &InnerLoop,
54 ScalarEvolution &SE) {
55 assert(!OuterLoop.isInnermost() && "Outer loop should have subloops")((void)0);
56 assert(!InnerLoop.isOutermost() && "Inner loop should have a parent")((void)0);
57 LLVM_DEBUG(dbgs() << "Checking whether loop '" << OuterLoop.getName()do { } while (false)
9
Loop condition is false. Exiting loop
58 << "' and '" << InnerLoop.getName()do { } while (false)
59 << "' are perfectly nested.\n")do { } while (false);
60
61 // Determine whether the loops structure satisfies the following requirements:
62 // - the inner loop should be the outer loop's only child
63 // - the outer loop header should 'flow' into the inner loop preheader
64 // or jump around the inner loop to the outer loop latch
65 // - if the inner loop latch exits the inner loop, it should 'flow' into
66 // the outer loop latch.
67 if (!checkLoopsStructure(OuterLoop, InnerLoop, SE)) {
10
Calling 'checkLoopsStructure'
68 LLVM_DEBUG(dbgs() << "Not perfectly nested: invalid loop structure.\n")do { } while (false);
69 return false;
70 }
71
72 // Bail out if we cannot retrieve the outer loop bounds.
73 auto OuterLoopLB = OuterLoop.getBounds(SE);
74 if (OuterLoopLB == None) {
75 LLVM_DEBUG(dbgs() << "Cannot compute loop bounds of OuterLoop: "do { } while (false)
76 << OuterLoop << "\n";)do { } while (false);
77 return false;
78 }
79
80 // Identify the outer loop latch comparison instruction.
81 const BasicBlock *Latch = OuterLoop.getLoopLatch();
82 assert(Latch && "Expecting a valid loop latch")((void)0);
83 const BranchInst *BI = dyn_cast<BranchInst>(Latch->getTerminator());
84 assert(BI && BI->isConditional() &&((void)0)
85 "Expecting loop latch terminator to be a branch instruction")((void)0);
86
87 const CmpInst *OuterLoopLatchCmp = dyn_cast<CmpInst>(BI->getCondition());
88 DEBUG_WITH_TYPE(do { } while (false)
89 VerboseDebug, if (OuterLoopLatchCmp) {do { } while (false)
90 dbgs() << "Outer loop latch compare instruction: " << *OuterLoopLatchCmpdo { } while (false)
91 << "\n";do { } while (false)
92 })do { } while (false);
93
94 // Identify the inner loop guard instruction.
95 BranchInst *InnerGuard = InnerLoop.getLoopGuardBranch();
96 const CmpInst *InnerLoopGuardCmp =
97 (InnerGuard) ? dyn_cast<CmpInst>(InnerGuard->getCondition()) : nullptr;
98
99 DEBUG_WITH_TYPE(do { } while (false)
100 VerboseDebug, if (InnerLoopGuardCmp) {do { } while (false)
101 dbgs() << "Inner loop guard compare instruction: " << *InnerLoopGuardCmpdo { } while (false)
102 << "\n";do { } while (false)
103 })do { } while (false);
104
105 // Determine whether instructions in a basic block are one of:
106 // - the inner loop guard comparison
107 // - the outer loop latch comparison
108 // - the outer loop induction variable increment
109 // - a phi node, a cast or a branch
110 auto containsOnlySafeInstructions = [&](const BasicBlock &BB) {
111 return llvm::all_of(BB, [&](const Instruction &I) {
112 bool isAllowed = isSafeToSpeculativelyExecute(&I) || isa<PHINode>(I) ||
113 isa<BranchInst>(I);
114 if (!isAllowed) {
115 DEBUG_WITH_TYPE(VerboseDebug, {do { } while (false)
116 dbgs() << "Instruction: " << I << "\nin basic block: " << BBdo { } while (false)
117 << " is considered unsafe.\n";do { } while (false)
118 })do { } while (false);
119 return false;
120 }
121
122 // The only binary instruction allowed is the outer loop step instruction,
123 // the only comparison instructions allowed are the inner loop guard
124 // compare instruction and the outer loop latch compare instruction.
125 if ((isa<BinaryOperator>(I) && &I != &OuterLoopLB->getStepInst()) ||
126 (isa<CmpInst>(I) && &I != OuterLoopLatchCmp &&
127 &I != InnerLoopGuardCmp)) {
128 DEBUG_WITH_TYPE(VerboseDebug, {do { } while (false)
129 dbgs() << "Instruction: " << I << "\nin basic block:" << BBdo { } while (false)
130 << "is unsafe.\n";do { } while (false)
131 })do { } while (false);
132 return false;
133 }
134 return true;
135 });
136 };
137
138 // Check the code surrounding the inner loop for instructions that are deemed
139 // unsafe.
140 const BasicBlock *OuterLoopHeader = OuterLoop.getHeader();
141 const BasicBlock *OuterLoopLatch = OuterLoop.getLoopLatch();
142 const BasicBlock *InnerLoopPreHeader = InnerLoop.getLoopPreheader();
143
144 if (!containsOnlySafeInstructions(*OuterLoopHeader) ||
145 !containsOnlySafeInstructions(*OuterLoopLatch) ||
146 (InnerLoopPreHeader != OuterLoopHeader &&
147 !containsOnlySafeInstructions(*InnerLoopPreHeader)) ||
148 !containsOnlySafeInstructions(*InnerLoop.getExitBlock())) {
149 LLVM_DEBUG(dbgs() << "Not perfectly nested: code surrounding inner loop is "do { } while (false)
150 "unsafe\n";)do { } while (false);
151 return false;
152 }
153
154 LLVM_DEBUG(dbgs() << "Loop '" << OuterLoop.getName() << "' and '"do { } while (false)
155 << InnerLoop.getName() << "' are perfectly nested.\n")do { } while (false);
156
157 return true;
158}
159
160SmallVector<LoopVectorTy, 4>
161LoopNest::getPerfectLoops(ScalarEvolution &SE) const {
162 SmallVector<LoopVectorTy, 4> LV;
163 LoopVectorTy PerfectNest;
164
165 for (Loop *L : depth_first(const_cast<Loop *>(Loops.front()))) {
166 if (PerfectNest.empty())
167 PerfectNest.push_back(L);
168
169 auto &SubLoops = L->getSubLoops();
170 if (SubLoops.size() == 1 && arePerfectlyNested(*L, *SubLoops.front(), SE)) {
171 PerfectNest.push_back(SubLoops.front());
172 } else {
173 LV.push_back(PerfectNest);
174 PerfectNest.clear();
175 }
176 }
177
178 return LV;
179}
180
181unsigned LoopNest::getMaxPerfectDepth(const Loop &Root, ScalarEvolution &SE) {
182 LLVM_DEBUG(dbgs() << "Get maximum perfect depth of loop nest rooted by loop '"do { } while (false)
5
Loop condition is false. Exiting loop
183 << Root.getName() << "'\n")do { } while (false);
184
185 const Loop *CurrentLoop = &Root;
186 const auto *SubLoops = &CurrentLoop->getSubLoops();
187 unsigned CurrentDepth = 1;
188
189 while (SubLoops->size() == 1) {
6
Assuming the condition is true
7
Loop condition is true. Entering loop body
190 const Loop *InnerLoop = SubLoops->front();
191 if (!arePerfectlyNested(*CurrentLoop, *InnerLoop, SE)) {
8
Calling 'LoopNest::arePerfectlyNested'
192 LLVM_DEBUG({do { } while (false)
193 dbgs() << "Not a perfect nest: loop '" << CurrentLoop->getName()do { } while (false)
194 << "' is not perfectly nested with loop '"do { } while (false)
195 << InnerLoop->getName() << "'\n";do { } while (false)
196 })do { } while (false);
197 break;
198 }
199
200 CurrentLoop = InnerLoop;
201 SubLoops = &CurrentLoop->getSubLoops();
202 ++CurrentDepth;
203 }
204
205 return CurrentDepth;
206}
207
208const BasicBlock &LoopNest::skipEmptyBlockUntil(const BasicBlock *From,
209 const BasicBlock *End,
210 bool CheckUniquePred) {
211 assert(From && "Expecting valid From")((void)0);
212 assert(End && "Expecting valid End")((void)0);
213
214 if (From
23.1
'From' is not equal to 'End'
23.1
'From' is not equal to 'End'
== End || !From->getUniqueSuccessor())
24
Assuming the condition is false
25
Taking false branch
215 return *From;
216
217 auto IsEmpty = [](const BasicBlock *BB) {
218 return (BB->getInstList().size() == 1);
219 };
220
221 // Visited is used to avoid running into an infinite loop.
222 SmallPtrSet<const BasicBlock *, 4> Visited;
223 const BasicBlock *BB = From->getUniqueSuccessor();
224 const BasicBlock *PredBB = From;
225 while (BB && BB != End && IsEmpty(BB) && !Visited.count(BB) &&
26
Assuming 'BB' is null
226 (!CheckUniquePred || BB->getUniquePredecessor())) {
227 Visited.insert(BB);
228 PredBB = BB;
229 BB = BB->getUniqueSuccessor();
230 }
231
232 return (BB == End) ? *End : *PredBB;
27
Assuming 'BB' is equal to 'End'
28
'?' condition is true
29
Returning null reference
233}
234
235static bool checkLoopsStructure(const Loop &OuterLoop, const Loop &InnerLoop,
236 ScalarEvolution &SE) {
237 // The inner loop must be the only outer loop's child.
238 if ((OuterLoop.getSubLoops().size() != 1) ||
11
Assuming the condition is false
13
Taking false branch
239 (InnerLoop.getParentLoop() != &OuterLoop))
12
Assuming the condition is false
240 return false;
241
242 // We expect loops in normal form which have a preheader, header, latch...
243 if (!OuterLoop.isLoopSimplifyForm() || !InnerLoop.isLoopSimplifyForm())
14
Assuming the condition is false
15
Assuming the condition is false
16
Taking false branch
244 return false;
245
246 const BasicBlock *OuterLoopHeader = OuterLoop.getHeader();
247 const BasicBlock *OuterLoopLatch = OuterLoop.getLoopLatch();
248 const BasicBlock *InnerLoopPreHeader = InnerLoop.getLoopPreheader();
249 const BasicBlock *InnerLoopLatch = InnerLoop.getLoopLatch();
250 const BasicBlock *InnerLoopExit = InnerLoop.getExitBlock();
251
252 // We expect rotated loops. The inner loop should have a single exit block.
253 if (OuterLoop.getExitingBlock() != OuterLoopLatch ||
17
Assuming the condition is false
20
Taking false branch
254 InnerLoop.getExitingBlock() != InnerLoopLatch || !InnerLoopExit)
18
Assuming the condition is false
19
Assuming 'InnerLoopExit' is non-null
255 return false;
256
257 // Returns whether the block `ExitBlock` contains at least one LCSSA Phi node.
258 auto ContainsLCSSAPhi = [](const BasicBlock &ExitBlock) {
259 return any_of(ExitBlock.phis(), [](const PHINode &PN) {
260 return PN.getNumIncomingValues() == 1;
261 });
262 };
263
264 // Returns whether the block `BB` qualifies for being an extra Phi block. The
265 // extra Phi block is the additional block inserted after the exit block of an
266 // "guarded" inner loop which contains "only" Phi nodes corresponding to the
267 // LCSSA Phi nodes in the exit block.
268 auto IsExtraPhiBlock = [&](const BasicBlock &BB) {
269 return BB.getFirstNonPHI() == BB.getTerminator() &&
270 all_of(BB.phis(), [&](const PHINode &PN) {
271 return all_of(PN.blocks(), [&](const BasicBlock *IncomingBlock) {
272 return IncomingBlock == InnerLoopExit ||
273 IncomingBlock == OuterLoopHeader;
274 });
275 });
276 };
277
278 const BasicBlock *ExtraPhiBlock = nullptr;
279 // Ensure the only branch that may exist between the loops is the inner loop
280 // guard.
281 if (OuterLoopHeader != InnerLoopPreHeader) {
21
Assuming 'OuterLoopHeader' is not equal to 'InnerLoopPreHeader'
22
Taking true branch
282 const BasicBlock &SingleSucc =
283 LoopNest::skipEmptyBlockUntil(OuterLoopHeader, InnerLoopPreHeader);
23
Calling 'LoopNest::skipEmptyBlockUntil'
284
285 // no conditional branch present
286 if (&SingleSucc != InnerLoopPreHeader) {
287 const BranchInst *BI = dyn_cast<BranchInst>(SingleSucc.getTerminator());
288
289 if (!BI || BI != InnerLoop.getLoopGuardBranch())
290 return false;
291
292 bool InnerLoopExitContainsLCSSA = ContainsLCSSAPhi(*InnerLoopExit);
293
294 // The successors of the inner loop guard should be the inner loop
295 // preheader or the outer loop latch possibly through empty blocks.
296 for (const BasicBlock *Succ : BI->successors()) {
297 const BasicBlock *PotentialInnerPreHeader = Succ;
298 const BasicBlock *PotentialOuterLatch = Succ;
299
300 // Ensure the inner loop guard successor is empty before skipping
301 // blocks.
302 if (Succ->getInstList().size() == 1) {
303 PotentialInnerPreHeader =
304 &LoopNest::skipEmptyBlockUntil(Succ, InnerLoopPreHeader);
305 PotentialOuterLatch =
306 &LoopNest::skipEmptyBlockUntil(Succ, OuterLoopLatch);
307 }
308
309 if (PotentialInnerPreHeader == InnerLoopPreHeader)
310 continue;
311 if (PotentialOuterLatch == OuterLoopLatch)
312 continue;
313
314 // If `InnerLoopExit` contains LCSSA Phi instructions, additional block
315 // may be inserted before the `OuterLoopLatch` to which `BI` jumps. The
316 // loops are still considered perfectly nested if the extra block only
317 // contains Phi instructions from InnerLoopExit and OuterLoopHeader.
318 if (InnerLoopExitContainsLCSSA && IsExtraPhiBlock(*Succ) &&
319 Succ->getSingleSuccessor() == OuterLoopLatch) {
320 // Points to the extra block so that we can reference it later in the
321 // final check. We can also conclude that the inner loop is
322 // guarded and there exists LCSSA Phi node in the exit block later if
323 // we see a non-null `ExtraPhiBlock`.
324 ExtraPhiBlock = Succ;
325 continue;
326 }
327
328 DEBUG_WITH_TYPE(VerboseDebug, {do { } while (false)
329 dbgs() << "Inner loop guard successor " << Succ->getName()do { } while (false)
330 << " doesn't lead to inner loop preheader or "do { } while (false)
331 "outer loop latch.\n";do { } while (false)
332 })do { } while (false);
333 return false;
334 }
335 }
336 }
337
338 // Ensure the inner loop exit block lead to the outer loop latch possibly
339 // through empty blocks.
340 if ((!ExtraPhiBlock ||
341 &LoopNest::skipEmptyBlockUntil(InnerLoop.getExitBlock(),
342 ExtraPhiBlock) != ExtraPhiBlock) &&
343 (&LoopNest::skipEmptyBlockUntil(InnerLoop.getExitBlock(),
344 OuterLoopLatch) != OuterLoopLatch)) {
345 DEBUG_WITH_TYPE(do { } while (false)
346 VerboseDebug,do { } while (false)
347 dbgs() << "Inner loop exit block " << *InnerLoopExitdo { } while (false)
348 << " does not directly lead to the outer loop latch.\n";)do { } while (false);
349 return false;
350 }
351
352 return true;
353}
354
355AnalysisKey LoopNestAnalysis::Key;
356
357raw_ostream &llvm::operator<<(raw_ostream &OS, const LoopNest &LN) {
358 OS << "IsPerfect=";
359 if (LN.getMaxPerfectDepth() == LN.getNestDepth())
360 OS << "true";
361 else
362 OS << "false";
363 OS << ", Depth=" << LN.getNestDepth();
364 OS << ", OutermostLoop: " << LN.getOutermostLoop().getName();
365 OS << ", Loops: ( ";
366 for (const Loop *L : LN.getLoops())
367 OS << L->getName() << " ";
368 OS << ")";
369
370 return OS;
371}
372
373//===----------------------------------------------------------------------===//
374// LoopNestPrinterPass implementation
375//
376
377PreservedAnalyses LoopNestPrinterPass::run(Loop &L, LoopAnalysisManager &AM,
378 LoopStandardAnalysisResults &AR,
379 LPMUpdater &U) {
380 if (auto LN = LoopNest::getLoopNest(L, AR.SE))
1
Calling 'LoopNest::getLoopNest'
381 OS << *LN << "\n";
382
383 return PreservedAnalyses::all();
384}

/usr/include/c++/v1/__memory/unique_ptr.h

1// -*- C++ -*-
2//===----------------------------------------------------------------------===//
3//
4// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5// See https://llvm.org/LICENSE.txt for license information.
6// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7//
8//===----------------------------------------------------------------------===//
9
10#ifndef _LIBCPP___MEMORY_UNIQUE_PTR_H
11#define _LIBCPP___MEMORY_UNIQUE_PTR_H
12
13#include <__config>
14#include <__functional_base>
15#include <__functional/hash.h>
16#include <__functional/operations.h>
17#include <__memory/allocator_traits.h> // __pointer
18#include <__memory/compressed_pair.h>
19#include <__utility/forward.h>
20#include <cstddef>
21#include <type_traits>
22#include <utility>
23
24#if _LIBCPP_STD_VER14 <= 14 || defined(_LIBCPP_ENABLE_CXX17_REMOVED_AUTO_PTR)
25# include <__memory/auto_ptr.h>
26#endif
27
28#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
29#pragma GCC system_header
30#endif
31
32_LIBCPP_PUSH_MACROSpush_macro("min") push_macro("max")
33#include <__undef_macros>
34
35_LIBCPP_BEGIN_NAMESPACE_STDnamespace std { inline namespace __1 {
36
37template <class _Tp>
38struct _LIBCPP_TEMPLATE_VIS__attribute__ ((__type_visibility__("default"))) default_delete {
39 static_assert(!is_function<_Tp>::value,
40 "default_delete cannot be instantiated for function types");
41#ifndef _LIBCPP_CXX03_LANG
42 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
constexpr default_delete() _NOEXCEPTnoexcept = default;
43#else
44 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
default_delete() {}
45#endif
46 template <class _Up>
47 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
48 default_delete(const default_delete<_Up>&,
49 typename enable_if<is_convertible<_Up*, _Tp*>::value>::type* =
50 0) _NOEXCEPTnoexcept {}
51
52 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
void operator()(_Tp* __ptr) const _NOEXCEPTnoexcept {
53 static_assert(sizeof(_Tp) > 0,
54 "default_delete can not delete incomplete type");
55 static_assert(!is_void<_Tp>::value,
56 "default_delete can not delete incomplete type");
57 delete __ptr;
58 }
59};
60
61template <class _Tp>
62struct _LIBCPP_TEMPLATE_VIS__attribute__ ((__type_visibility__("default"))) default_delete<_Tp[]> {
63private:
64 template <class _Up>
65 struct _EnableIfConvertible
66 : enable_if<is_convertible<_Up(*)[], _Tp(*)[]>::value> {};
67
68public:
69#ifndef _LIBCPP_CXX03_LANG
70 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
constexpr default_delete() _NOEXCEPTnoexcept = default;
71#else
72 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
default_delete() {}
73#endif
74
75 template <class _Up>
76 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
77 default_delete(const default_delete<_Up[]>&,
78 typename _EnableIfConvertible<_Up>::type* = 0) _NOEXCEPTnoexcept {}
79
80 template <class _Up>
81 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
82 typename _EnableIfConvertible<_Up>::type
83 operator()(_Up* __ptr) const _NOEXCEPTnoexcept {
84 static_assert(sizeof(_Tp) > 0,
85 "default_delete can not delete incomplete type");
86 static_assert(!is_void<_Tp>::value,
87 "default_delete can not delete void type");
88 delete[] __ptr;
89 }
90};
91
92template <class _Deleter>
93struct __unique_ptr_deleter_sfinae {
94 static_assert(!is_reference<_Deleter>::value, "incorrect specialization");
95 typedef const _Deleter& __lval_ref_type;
96 typedef _Deleter&& __good_rval_ref_type;
97 typedef true_type __enable_rval_overload;
98};
99
100template <class _Deleter>
101struct __unique_ptr_deleter_sfinae<_Deleter const&> {
102 typedef const _Deleter& __lval_ref_type;
103 typedef const _Deleter&& __bad_rval_ref_type;
104 typedef false_type __enable_rval_overload;
105};
106
107template <class _Deleter>
108struct __unique_ptr_deleter_sfinae<_Deleter&> {
109 typedef _Deleter& __lval_ref_type;
110 typedef _Deleter&& __bad_rval_ref_type;
111 typedef false_type __enable_rval_overload;
112};
113
114#if defined(_LIBCPP_ABI_ENABLE_UNIQUE_PTR_TRIVIAL_ABI)
115# define _LIBCPP_UNIQUE_PTR_TRIVIAL_ABI __attribute__((trivial_abi))
116#else
117# define _LIBCPP_UNIQUE_PTR_TRIVIAL_ABI
118#endif
119
120template <class _Tp, class _Dp = default_delete<_Tp> >
121class _LIBCPP_UNIQUE_PTR_TRIVIAL_ABI _LIBCPP_TEMPLATE_VIS__attribute__ ((__type_visibility__("default"))) unique_ptr {
122public:
123 typedef _Tp element_type;
124 typedef _Dp deleter_type;
125 typedef _LIBCPP_NODEBUG_TYPE__attribute__((nodebug)) typename __pointer<_Tp, deleter_type>::type pointer;
126
127 static_assert(!is_rvalue_reference<deleter_type>::value,
128 "the specified deleter type cannot be an rvalue reference");
129
130private:
131 __compressed_pair<pointer, deleter_type> __ptr_;
132
133 struct __nat { int __for_bool_; };
134
135 typedef _LIBCPP_NODEBUG_TYPE__attribute__((nodebug)) __unique_ptr_deleter_sfinae<_Dp> _DeleterSFINAE;
136
137 template <bool _Dummy>
138 using _LValRefType _LIBCPP_NODEBUG_TYPE__attribute__((nodebug)) =
139 typename __dependent_type<_DeleterSFINAE, _Dummy>::__lval_ref_type;
140
141 template <bool _Dummy>
142 using _GoodRValRefType _LIBCPP_NODEBUG_TYPE__attribute__((nodebug)) =
143 typename __dependent_type<_DeleterSFINAE, _Dummy>::__good_rval_ref_type;
144
145 template <bool _Dummy>
146 using _BadRValRefType _LIBCPP_NODEBUG_TYPE__attribute__((nodebug)) =
147 typename __dependent_type<_DeleterSFINAE, _Dummy>::__bad_rval_ref_type;
148
149 template <bool _Dummy, class _Deleter = typename __dependent_type<
150 __identity<deleter_type>, _Dummy>::type>
151 using _EnableIfDeleterDefaultConstructible _LIBCPP_NODEBUG_TYPE__attribute__((nodebug)) =
152 typename enable_if<is_default_constructible<_Deleter>::value &&
153 !is_pointer<_Deleter>::value>::type;
154
155 template <class _ArgType>
156 using _EnableIfDeleterConstructible _LIBCPP_NODEBUG_TYPE__attribute__((nodebug)) =
157 typename enable_if<is_constructible<deleter_type, _ArgType>::value>::type;
158
159 template <class _UPtr, class _Up>
160 using _EnableIfMoveConvertible _LIBCPP_NODEBUG_TYPE__attribute__((nodebug)) = typename enable_if<
161 is_convertible<typename _UPtr::pointer, pointer>::value &&
162 !is_array<_Up>::value
163 >::type;
164
165 template <class _UDel>
166 using _EnableIfDeleterConvertible _LIBCPP_NODEBUG_TYPE__attribute__((nodebug)) = typename enable_if<
167 (is_reference<_Dp>::value && is_same<_Dp, _UDel>::value) ||
168 (!is_reference<_Dp>::value && is_convertible<_UDel, _Dp>::value)
169 >::type;
170
171 template <class _UDel>
172 using _EnableIfDeleterAssignable = typename enable_if<
173 is_assignable<_Dp&, _UDel&&>::value
174 >::type;
175
176public:
177 template <bool _Dummy = true,
178 class = _EnableIfDeleterDefaultConstructible<_Dummy> >
179 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
180 _LIBCPP_CONSTEXPRconstexpr unique_ptr() _NOEXCEPTnoexcept : __ptr_(pointer(), __default_init_tag()) {}
181
182 template <bool _Dummy = true,
183 class = _EnableIfDeleterDefaultConstructible<_Dummy> >
184 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
185 _LIBCPP_CONSTEXPRconstexpr unique_ptr(nullptr_t) _NOEXCEPTnoexcept : __ptr_(pointer(), __default_init_tag()) {}
186
187 template <bool _Dummy = true,
188 class = _EnableIfDeleterDefaultConstructible<_Dummy> >
189 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
190 explicit unique_ptr(pointer __p) _NOEXCEPTnoexcept : __ptr_(__p, __default_init_tag()) {}
191
192 template <bool _Dummy = true,
193 class = _EnableIfDeleterConstructible<_LValRefType<_Dummy> > >
194 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
195 unique_ptr(pointer __p, _LValRefType<_Dummy> __d) _NOEXCEPTnoexcept
196 : __ptr_(__p, __d) {}
197
198 template <bool _Dummy = true,
199 class = _EnableIfDeleterConstructible<_GoodRValRefType<_Dummy> > >
200 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
201 unique_ptr(pointer __p, _GoodRValRefType<_Dummy> __d) _NOEXCEPTnoexcept
202 : __ptr_(__p, _VSTDstd::__1::move(__d)) {
203 static_assert(!is_reference<deleter_type>::value,
204 "rvalue deleter bound to reference");
205 }
206
207 template <bool _Dummy = true,
208 class = _EnableIfDeleterConstructible<_BadRValRefType<_Dummy> > >
209 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
210 unique_ptr(pointer __p, _BadRValRefType<_Dummy> __d) = delete;
211
212 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
213 unique_ptr(unique_ptr&& __u) _NOEXCEPTnoexcept
214 : __ptr_(__u.release(), _VSTDstd::__1::forward<deleter_type>(__u.get_deleter())) {
215 }
216
217 template <class _Up, class _Ep,
218 class = _EnableIfMoveConvertible<unique_ptr<_Up, _Ep>, _Up>,
219 class = _EnableIfDeleterConvertible<_Ep>
220 >
221 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
222 unique_ptr(unique_ptr<_Up, _Ep>&& __u) _NOEXCEPTnoexcept
223 : __ptr_(__u.release(), _VSTDstd::__1::forward<_Ep>(__u.get_deleter())) {}
224
225#if _LIBCPP_STD_VER14 <= 14 || defined(_LIBCPP_ENABLE_CXX17_REMOVED_AUTO_PTR)
226 template <class _Up>
227 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
228 unique_ptr(auto_ptr<_Up>&& __p,
229 typename enable_if<is_convertible<_Up*, _Tp*>::value &&
230 is_same<_Dp, default_delete<_Tp> >::value,
231 __nat>::type = __nat()) _NOEXCEPTnoexcept
232 : __ptr_(__p.release(), __default_init_tag()) {}
233#endif
234
235 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
236 unique_ptr& operator=(unique_ptr&& __u) _NOEXCEPTnoexcept {
237 reset(__u.release());
238 __ptr_.second() = _VSTDstd::__1::forward<deleter_type>(__u.get_deleter());
239 return *this;
240 }
241
242 template <class _Up, class _Ep,
243 class = _EnableIfMoveConvertible<unique_ptr<_Up, _Ep>, _Up>,
244 class = _EnableIfDeleterAssignable<_Ep>
245 >
246 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
247 unique_ptr& operator=(unique_ptr<_Up, _Ep>&& __u) _NOEXCEPTnoexcept {
248 reset(__u.release());
249 __ptr_.second() = _VSTDstd::__1::forward<_Ep>(__u.get_deleter());
250 return *this;
251 }
252
253#if _LIBCPP_STD_VER14 <= 14 || defined(_LIBCPP_ENABLE_CXX17_REMOVED_AUTO_PTR)
254 template <class _Up>
255 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
256 typename enable_if<is_convertible<_Up*, _Tp*>::value &&
257 is_same<_Dp, default_delete<_Tp> >::value,
258 unique_ptr&>::type
259 operator=(auto_ptr<_Up> __p) {
260 reset(__p.release());
261 return *this;
262 }
263#endif
264
265#ifdef _LIBCPP_CXX03_LANG
266 unique_ptr(unique_ptr const&) = delete;
267 unique_ptr& operator=(unique_ptr const&) = delete;
268#endif
269
270
271 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
272 ~unique_ptr() { reset(); }
273
274 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
275 unique_ptr& operator=(nullptr_t) _NOEXCEPTnoexcept {
276 reset();
277 return *this;
278 }
279
280 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
281 typename add_lvalue_reference<_Tp>::type
282 operator*() const {
283 return *__ptr_.first();
284 }
285 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
286 pointer operator->() const _NOEXCEPTnoexcept {
287 return __ptr_.first();
288 }
289 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
290 pointer get() const _NOEXCEPTnoexcept {
291 return __ptr_.first();
292 }
293 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
294 deleter_type& get_deleter() _NOEXCEPTnoexcept {
295 return __ptr_.second();
296 }
297 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
298 const deleter_type& get_deleter() const _NOEXCEPTnoexcept {
299 return __ptr_.second();
300 }
301 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
302 explicit operator bool() const _NOEXCEPTnoexcept {
303 return __ptr_.first() != nullptr;
304 }
305
306 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
307 pointer release() _NOEXCEPTnoexcept {
308 pointer __t = __ptr_.first();
309 __ptr_.first() = pointer();
310 return __t;
311 }
312
313 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
314 void reset(pointer __p = pointer()) _NOEXCEPTnoexcept {
315 pointer __tmp = __ptr_.first();
316 __ptr_.first() = __p;
317 if (__tmp)
318 __ptr_.second()(__tmp);
319 }
320
321 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
322 void swap(unique_ptr& __u) _NOEXCEPTnoexcept {
323 __ptr_.swap(__u.__ptr_);
324 }
325};
326
327
328template <class _Tp, class _Dp>
329class _LIBCPP_UNIQUE_PTR_TRIVIAL_ABI _LIBCPP_TEMPLATE_VIS__attribute__ ((__type_visibility__("default"))) unique_ptr<_Tp[], _Dp> {
330public:
331 typedef _Tp element_type;
332 typedef _Dp deleter_type;
333 typedef typename __pointer<_Tp, deleter_type>::type pointer;
334
335private:
336 __compressed_pair<pointer, deleter_type> __ptr_;
337
338 template <class _From>
339 struct _CheckArrayPointerConversion : is_same<_From, pointer> {};
340
341 template <class _FromElem>
342 struct _CheckArrayPointerConversion<_FromElem*>
343 : integral_constant<bool,
344 is_same<_FromElem*, pointer>::value ||
345 (is_same<pointer, element_type*>::value &&
346 is_convertible<_FromElem(*)[], element_type(*)[]>::value)
347 >
348 {};
349
350 typedef __unique_ptr_deleter_sfinae<_Dp> _DeleterSFINAE;
351
352 template <bool _Dummy>
353 using _LValRefType _LIBCPP_NODEBUG_TYPE__attribute__((nodebug)) =
354 typename __dependent_type<_DeleterSFINAE, _Dummy>::__lval_ref_type;
355
356 template <bool _Dummy>
357 using _GoodRValRefType _LIBCPP_NODEBUG_TYPE__attribute__((nodebug)) =
358 typename __dependent_type<_DeleterSFINAE, _Dummy>::__good_rval_ref_type;
359
360 template <bool _Dummy>
361 using _BadRValRefType _LIBCPP_NODEBUG_TYPE__attribute__((nodebug)) =
362 typename __dependent_type<_DeleterSFINAE, _Dummy>::__bad_rval_ref_type;
363
364 template <bool _Dummy, class _Deleter = typename __dependent_type<
365 __identity<deleter_type>, _Dummy>::type>
366 using _EnableIfDeleterDefaultConstructible _LIBCPP_NODEBUG_TYPE__attribute__((nodebug)) =
367 typename enable_if<is_default_constructible<_Deleter>::value &&
368 !is_pointer<_Deleter>::value>::type;
369
370 template <class _ArgType>
371 using _EnableIfDeleterConstructible _LIBCPP_NODEBUG_TYPE__attribute__((nodebug)) =
372 typename enable_if<is_constructible<deleter_type, _ArgType>::value>::type;
373
374 template <class _Pp>
375 using _EnableIfPointerConvertible _LIBCPP_NODEBUG_TYPE__attribute__((nodebug)) = typename enable_if<
376 _CheckArrayPointerConversion<_Pp>::value
377 >::type;
378
379 template <class _UPtr, class _Up,
380 class _ElemT = typename _UPtr::element_type>
381 using _EnableIfMoveConvertible _LIBCPP_NODEBUG_TYPE__attribute__((nodebug)) = typename enable_if<
382 is_array<_Up>::value &&
383 is_same<pointer, element_type*>::value &&
384 is_same<typename _UPtr::pointer, _ElemT*>::value &&
385 is_convertible<_ElemT(*)[], element_type(*)[]>::value
386 >::type;
387
388 template <class _UDel>
389 using _EnableIfDeleterConvertible _LIBCPP_NODEBUG_TYPE__attribute__((nodebug)) = typename enable_if<
390 (is_reference<_Dp>::value && is_same<_Dp, _UDel>::value) ||
391 (!is_reference<_Dp>::value && is_convertible<_UDel, _Dp>::value)
392 >::type;
393
394 template <class _UDel>
395 using _EnableIfDeleterAssignable _LIBCPP_NODEBUG_TYPE__attribute__((nodebug)) = typename enable_if<
396 is_assignable<_Dp&, _UDel&&>::value
397 >::type;
398
399public:
400 template <bool _Dummy = true,
401 class = _EnableIfDeleterDefaultConstructible<_Dummy> >
402 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
403 _LIBCPP_CONSTEXPRconstexpr unique_ptr() _NOEXCEPTnoexcept : __ptr_(pointer(), __default_init_tag()) {}
404
405 template <bool _Dummy = true,
406 class = _EnableIfDeleterDefaultConstructible<_Dummy> >
407 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
408 _LIBCPP_CONSTEXPRconstexpr unique_ptr(nullptr_t) _NOEXCEPTnoexcept : __ptr_(pointer(), __default_init_tag()) {}
409
410 template <class _Pp, bool _Dummy = true,
411 class = _EnableIfDeleterDefaultConstructible<_Dummy>,
412 class = _EnableIfPointerConvertible<_Pp> >
413 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
414 explicit unique_ptr(_Pp __p) _NOEXCEPTnoexcept
415 : __ptr_(__p, __default_init_tag()) {}
416
417 template <class _Pp, bool _Dummy = true,
418 class = _EnableIfDeleterConstructible<_LValRefType<_Dummy> >,
419 class = _EnableIfPointerConvertible<_Pp> >
420 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
421 unique_ptr(_Pp __p, _LValRefType<_Dummy> __d) _NOEXCEPTnoexcept
422 : __ptr_(__p, __d) {}
423
424 template <bool _Dummy = true,
425 class = _EnableIfDeleterConstructible<_LValRefType<_Dummy> > >
426 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
427 unique_ptr(nullptr_t, _LValRefType<_Dummy> __d) _NOEXCEPTnoexcept
428 : __ptr_(nullptr, __d) {}
429
430 template <class _Pp, bool _Dummy = true,
431 class = _EnableIfDeleterConstructible<_GoodRValRefType<_Dummy> >,
432 class = _EnableIfPointerConvertible<_Pp> >
433 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
434 unique_ptr(_Pp __p, _GoodRValRefType<_Dummy> __d) _NOEXCEPTnoexcept
435 : __ptr_(__p, _VSTDstd::__1::move(__d)) {
436 static_assert(!is_reference<deleter_type>::value,
437 "rvalue deleter bound to reference");
438 }
439
440 template <bool _Dummy = true,
441 class = _EnableIfDeleterConstructible<_GoodRValRefType<_Dummy> > >
442 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
443 unique_ptr(nullptr_t, _GoodRValRefType<_Dummy> __d) _NOEXCEPTnoexcept
444 : __ptr_(nullptr, _VSTDstd::__1::move(__d)) {
445 static_assert(!is_reference<deleter_type>::value,
446 "rvalue deleter bound to reference");
447 }
448
449 template <class _Pp, bool _Dummy = true,
450 class = _EnableIfDeleterConstructible<_BadRValRefType<_Dummy> >,
451 class = _EnableIfPointerConvertible<_Pp> >
452 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
453 unique_ptr(_Pp __p, _BadRValRefType<_Dummy> __d) = delete;
454
455 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
456 unique_ptr(unique_ptr&& __u) _NOEXCEPTnoexcept
457 : __ptr_(__u.release(), _VSTDstd::__1::forward<deleter_type>(__u.get_deleter())) {
458 }
459
460 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
461 unique_ptr& operator=(unique_ptr&& __u) _NOEXCEPTnoexcept {
462 reset(__u.release());
463 __ptr_.second() = _VSTDstd::__1::forward<deleter_type>(__u.get_deleter());
464 return *this;
465 }
466
467 template <class _Up, class _Ep,
468 class = _EnableIfMoveConvertible<unique_ptr<_Up, _Ep>, _Up>,
469 class = _EnableIfDeleterConvertible<_Ep>
470 >
471 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
472 unique_ptr(unique_ptr<_Up, _Ep>&& __u) _NOEXCEPTnoexcept
473 : __ptr_(__u.release(), _VSTDstd::__1::forward<_Ep>(__u.get_deleter())) {
474 }
475
476 template <class _Up, class _Ep,
477 class = _EnableIfMoveConvertible<unique_ptr<_Up, _Ep>, _Up>,
478 class = _EnableIfDeleterAssignable<_Ep>
479 >
480 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
481 unique_ptr&
482 operator=(unique_ptr<_Up, _Ep>&& __u) _NOEXCEPTnoexcept {
483 reset(__u.release());
484 __ptr_.second() = _VSTDstd::__1::forward<_Ep>(__u.get_deleter());
485 return *this;
486 }
487
488#ifdef _LIBCPP_CXX03_LANG
489 unique_ptr(unique_ptr const&) = delete;
490 unique_ptr& operator=(unique_ptr const&) = delete;
491#endif
492
493public:
494 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
495 ~unique_ptr() { reset(); }
496
497 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
498 unique_ptr& operator=(nullptr_t) _NOEXCEPTnoexcept {
499 reset();
500 return *this;
501 }
502
503 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
504 typename add_lvalue_reference<_Tp>::type
505 operator[](size_t __i) const {
506 return __ptr_.first()[__i];
507 }
508 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
509 pointer get() const _NOEXCEPTnoexcept {
510 return __ptr_.first();
511 }
512
513 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
514 deleter_type& get_deleter() _NOEXCEPTnoexcept {
515 return __ptr_.second();
516 }
517
518 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
519 const deleter_type& get_deleter() const _NOEXCEPTnoexcept {
520 return __ptr_.second();
521 }
522 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
523 explicit operator bool() const _NOEXCEPTnoexcept {
524 return __ptr_.first() != nullptr;
525 }
526
527 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
528 pointer release() _NOEXCEPTnoexcept {
529 pointer __t = __ptr_.first();
530 __ptr_.first() = pointer();
531 return __t;
532 }
533
534 template <class _Pp>
535 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
536 typename enable_if<
537 _CheckArrayPointerConversion<_Pp>::value
538 >::type
539 reset(_Pp __p) _NOEXCEPTnoexcept {
540 pointer __tmp = __ptr_.first();
541 __ptr_.first() = __p;
542 if (__tmp)
543 __ptr_.second()(__tmp);
544 }
545
546 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
547 void reset(nullptr_t = nullptr) _NOEXCEPTnoexcept {
548 pointer __tmp = __ptr_.first();
549 __ptr_.first() = nullptr;
550 if (__tmp)
551 __ptr_.second()(__tmp);
552 }
553
554 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
555 void swap(unique_ptr& __u) _NOEXCEPTnoexcept {
556 __ptr_.swap(__u.__ptr_);
557 }
558
559};
560
561template <class _Tp, class _Dp>
562inline _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
563typename enable_if<
564 __is_swappable<_Dp>::value,
565 void
566>::type
567swap(unique_ptr<_Tp, _Dp>& __x, unique_ptr<_Tp, _Dp>& __y) _NOEXCEPTnoexcept {__x.swap(__y);}
568
569template <class _T1, class _D1, class _T2, class _D2>
570inline _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
571bool
572operator==(const unique_ptr<_T1, _D1>& __x, const unique_ptr<_T2, _D2>& __y) {return __x.get() == __y.get();}
573
574template <class _T1, class _D1, class _T2, class _D2>
575inline _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
576bool
577operator!=(const unique_ptr<_T1, _D1>& __x, const unique_ptr<_T2, _D2>& __y) {return !(__x == __y);}
578
579template <class _T1, class _D1, class _T2, class _D2>
580inline _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
581bool
582operator< (const unique_ptr<_T1, _D1>& __x, const unique_ptr<_T2, _D2>& __y)
583{
584 typedef typename unique_ptr<_T1, _D1>::pointer _P1;
585 typedef typename unique_ptr<_T2, _D2>::pointer _P2;
586 typedef typename common_type<_P1, _P2>::type _Vp;
587 return less<_Vp>()(__x.get(), __y.get());
588}
589
590template <class _T1, class _D1, class _T2, class _D2>
591inline _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
592bool
593operator> (const unique_ptr<_T1, _D1>& __x, const unique_ptr<_T2, _D2>& __y) {return __y < __x;}
594
595template <class _T1, class _D1, class _T2, class _D2>
596inline _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
597bool
598operator<=(const unique_ptr<_T1, _D1>& __x, const unique_ptr<_T2, _D2>& __y) {return !(__y < __x);}
599
600template <class _T1, class _D1, class _T2, class _D2>
601inline _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
602bool
603operator>=(const unique_ptr<_T1, _D1>& __x, const unique_ptr<_T2, _D2>& __y) {return !(__x < __y);}
604
605template <class _T1, class _D1>
606inline _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
607bool
608operator==(const unique_ptr<_T1, _D1>& __x, nullptr_t) _NOEXCEPTnoexcept
609{
610 return !__x;
611}
612
613template <class _T1, class _D1>
614inline _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
615bool
616operator==(nullptr_t, const unique_ptr<_T1, _D1>& __x) _NOEXCEPTnoexcept
617{
618 return !__x;
619}
620
621template <class _T1, class _D1>
622inline _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
623bool
624operator!=(const unique_ptr<_T1, _D1>& __x, nullptr_t) _NOEXCEPTnoexcept
625{
626 return static_cast<bool>(__x);
627}
628
629template <class _T1, class _D1>
630inline _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
631bool
632operator!=(nullptr_t, const unique_ptr<_T1, _D1>& __x) _NOEXCEPTnoexcept
633{
634 return static_cast<bool>(__x);
635}
636
637template <class _T1, class _D1>
638inline _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
639bool
640operator<(const unique_ptr<_T1, _D1>& __x, nullptr_t)
641{
642 typedef typename unique_ptr<_T1, _D1>::pointer _P1;
643 return less<_P1>()(__x.get(), nullptr);
644}
645
646template <class _T1, class _D1>
647inline _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
648bool
649operator<(nullptr_t, const unique_ptr<_T1, _D1>& __x)
650{
651 typedef typename unique_ptr<_T1, _D1>::pointer _P1;
652 return less<_P1>()(nullptr, __x.get());
653}
654
655template <class _T1, class _D1>
656inline _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
657bool
658operator>(const unique_ptr<_T1, _D1>& __x, nullptr_t)
659{
660 return nullptr < __x;
661}
662
663template <class _T1, class _D1>
664inline _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
665bool
666operator>(nullptr_t, const unique_ptr<_T1, _D1>& __x)
667{
668 return __x < nullptr;
669}
670
671template <class _T1, class _D1>
672inline _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
673bool
674operator<=(const unique_ptr<_T1, _D1>& __x, nullptr_t)
675{
676 return !(nullptr < __x);
677}
678
679template <class _T1, class _D1>
680inline _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
681bool
682operator<=(nullptr_t, const unique_ptr<_T1, _D1>& __x)
683{
684 return !(__x < nullptr);
685}
686
687template <class _T1, class _D1>
688inline _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
689bool
690operator>=(const unique_ptr<_T1, _D1>& __x, nullptr_t)
691{
692 return !(__x < nullptr);
693}
694
695template <class _T1, class _D1>
696inline _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
697bool
698operator>=(nullptr_t, const unique_ptr<_T1, _D1>& __x)
699{
700 return !(nullptr < __x);
701}
702
703#if _LIBCPP_STD_VER14 > 11
704
705template<class _Tp>
706struct __unique_if
707{
708 typedef unique_ptr<_Tp> __unique_single;
709};
710
711template<class _Tp>
712struct __unique_if<_Tp[]>
713{
714 typedef unique_ptr<_Tp[]> __unique_array_unknown_bound;
715};
716
717template<class _Tp, size_t _Np>
718struct __unique_if<_Tp[_Np]>
719{
720 typedef void __unique_array_known_bound;
721};
722
723template<class _Tp, class... _Args>
724inline _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
725typename __unique_if<_Tp>::__unique_single
726make_unique(_Args&&... __args)
727{
728 return unique_ptr<_Tp>(new _Tp(_VSTDstd::__1::forward<_Args>(__args)...));
3
Calling constructor for 'LoopNest'
729}
730
731template<class _Tp>
732inline _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
733typename __unique_if<_Tp>::__unique_array_unknown_bound
734make_unique(size_t __n)
735{
736 typedef typename remove_extent<_Tp>::type _Up;
737 return unique_ptr<_Tp>(new _Up[__n]());
738}
739
740template<class _Tp, class... _Args>
741 typename __unique_if<_Tp>::__unique_array_known_bound
742 make_unique(_Args&&...) = delete;
743
744#endif // _LIBCPP_STD_VER > 11
745
746template <class _Tp> struct _LIBCPP_TEMPLATE_VIS__attribute__ ((__type_visibility__("default"))) hash;
747
748template <class _Tp, class _Dp>
749#ifdef _LIBCPP_CXX03_LANG
750struct _LIBCPP_TEMPLATE_VIS__attribute__ ((__type_visibility__("default"))) hash<unique_ptr<_Tp, _Dp> >
751#else
752struct _LIBCPP_TEMPLATE_VIS__attribute__ ((__type_visibility__("default"))) hash<__enable_hash_helper<
753 unique_ptr<_Tp, _Dp>, typename unique_ptr<_Tp, _Dp>::pointer> >
754#endif
755{
756#if _LIBCPP_STD_VER14 <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_BINDER_TYPEDEFS)
757 _LIBCPP_DEPRECATED_IN_CXX17 typedef unique_ptr<_Tp, _Dp> argument_type;
758 _LIBCPP_DEPRECATED_IN_CXX17 typedef size_t result_type;
759#endif
760
761 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
762 size_t operator()(const unique_ptr<_Tp, _Dp>& __ptr) const
763 {
764 typedef typename unique_ptr<_Tp, _Dp>::pointer pointer;
765 return hash<pointer>()(__ptr.get());
766 }
767};
768
769_LIBCPP_END_NAMESPACE_STD} }
770
771_LIBCPP_POP_MACROSpop_macro("min") pop_macro("max")
772
773#endif // _LIBCPP___MEMORY_UNIQUE_PTR_H