Bug Summary

File:src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/lib/Transforms/Utils/PredicateInfo.cpp
Warning:line 593, column 21
Access to field 'AssumeInst' results in a dereference of a null pointer (loaded from variable 'PAssume')

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 PredicateInfo.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 pic -pic-level 1 -fhalf-no-semantic-interposition -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" -D PIC -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 -D_RET_PROTECTOR -ret-protector -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/Transforms/Utils/PredicateInfo.cpp

/usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/lib/Transforms/Utils/PredicateInfo.cpp

1//===-- PredicateInfo.cpp - PredicateInfo Builder--------------------===//
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// This file implements the PredicateInfo class.
10//
11//===----------------------------------------------------------------===//
12
13#include "llvm/Transforms/Utils/PredicateInfo.h"
14#include "llvm/ADT/DenseMap.h"
15#include "llvm/ADT/DepthFirstIterator.h"
16#include "llvm/ADT/STLExtras.h"
17#include "llvm/ADT/SmallPtrSet.h"
18#include "llvm/ADT/Statistic.h"
19#include "llvm/ADT/StringExtras.h"
20#include "llvm/Analysis/AssumptionCache.h"
21#include "llvm/Analysis/CFG.h"
22#include "llvm/IR/AssemblyAnnotationWriter.h"
23#include "llvm/IR/DataLayout.h"
24#include "llvm/IR/Dominators.h"
25#include "llvm/IR/GlobalVariable.h"
26#include "llvm/IR/IRBuilder.h"
27#include "llvm/IR/InstIterator.h"
28#include "llvm/IR/IntrinsicInst.h"
29#include "llvm/IR/LLVMContext.h"
30#include "llvm/IR/Metadata.h"
31#include "llvm/IR/Module.h"
32#include "llvm/IR/PatternMatch.h"
33#include "llvm/InitializePasses.h"
34#include "llvm/Support/CommandLine.h"
35#include "llvm/Support/Debug.h"
36#include "llvm/Support/DebugCounter.h"
37#include "llvm/Support/FormattedStream.h"
38#include "llvm/Transforms/Utils.h"
39#include <algorithm>
40#define DEBUG_TYPE"predicateinfo" "predicateinfo"
41using namespace llvm;
42using namespace PatternMatch;
43
44INITIALIZE_PASS_BEGIN(PredicateInfoPrinterLegacyPass, "print-predicateinfo",static void *initializePredicateInfoPrinterLegacyPassPassOnce
(PassRegistry &Registry) {
45 "PredicateInfo Printer", false, false)static void *initializePredicateInfoPrinterLegacyPassPassOnce
(PassRegistry &Registry) {
46INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)initializeDominatorTreeWrapperPassPass(Registry);
47INITIALIZE_PASS_DEPENDENCY(AssumptionCacheTracker)initializeAssumptionCacheTrackerPass(Registry);
48INITIALIZE_PASS_END(PredicateInfoPrinterLegacyPass, "print-predicateinfo",PassInfo *PI = new PassInfo( "PredicateInfo Printer", "print-predicateinfo"
, &PredicateInfoPrinterLegacyPass::ID, PassInfo::NormalCtor_t
(callDefaultCtor<PredicateInfoPrinterLegacyPass>), false
, false); Registry.registerPass(*PI, true); return PI; } static
llvm::once_flag InitializePredicateInfoPrinterLegacyPassPassFlag
; void llvm::initializePredicateInfoPrinterLegacyPassPass(PassRegistry
&Registry) { llvm::call_once(InitializePredicateInfoPrinterLegacyPassPassFlag
, initializePredicateInfoPrinterLegacyPassPassOnce, std::ref(
Registry)); }
49 "PredicateInfo Printer", false, false)PassInfo *PI = new PassInfo( "PredicateInfo Printer", "print-predicateinfo"
, &PredicateInfoPrinterLegacyPass::ID, PassInfo::NormalCtor_t
(callDefaultCtor<PredicateInfoPrinterLegacyPass>), false
, false); Registry.registerPass(*PI, true); return PI; } static
llvm::once_flag InitializePredicateInfoPrinterLegacyPassPassFlag
; void llvm::initializePredicateInfoPrinterLegacyPassPass(PassRegistry
&Registry) { llvm::call_once(InitializePredicateInfoPrinterLegacyPassPassFlag
, initializePredicateInfoPrinterLegacyPassPassOnce, std::ref(
Registry)); }
50static cl::opt<bool> VerifyPredicateInfo(
51 "verify-predicateinfo", cl::init(false), cl::Hidden,
52 cl::desc("Verify PredicateInfo in legacy printer pass."));
53DEBUG_COUNTER(RenameCounter, "predicateinfo-rename",static const unsigned RenameCounter = DebugCounter::registerCounter
("predicateinfo-rename", "Controls which variables are renamed with predicateinfo"
)
54 "Controls which variables are renamed with predicateinfo")static const unsigned RenameCounter = DebugCounter::registerCounter
("predicateinfo-rename", "Controls which variables are renamed with predicateinfo"
)
;
55
56// Maximum number of conditions considered for renaming for each branch/assume.
57// This limits renaming of deep and/or chains.
58static const unsigned MaxCondsPerBranch = 8;
59
60namespace {
61// Given a predicate info that is a type of branching terminator, get the
62// branching block.
63const BasicBlock *getBranchBlock(const PredicateBase *PB) {
64 assert(isa<PredicateWithEdge>(PB) &&((void)0)
65 "Only branches and switches should have PHIOnly defs that "((void)0)
66 "require branch blocks.")((void)0);
67 return cast<PredicateWithEdge>(PB)->From;
68}
69
70// Given a predicate info that is a type of branching terminator, get the
71// branching terminator.
72static Instruction *getBranchTerminator(const PredicateBase *PB) {
73 assert(isa<PredicateWithEdge>(PB) &&((void)0)
74 "Not a predicate info type we know how to get a terminator from.")((void)0);
75 return cast<PredicateWithEdge>(PB)->From->getTerminator();
76}
77
78// Given a predicate info that is a type of branching terminator, get the
79// edge this predicate info represents
80std::pair<BasicBlock *, BasicBlock *> getBlockEdge(const PredicateBase *PB) {
81 assert(isa<PredicateWithEdge>(PB) &&((void)0)
82 "Not a predicate info type we know how to get an edge from.")((void)0);
83 const auto *PEdge = cast<PredicateWithEdge>(PB);
84 return std::make_pair(PEdge->From, PEdge->To);
85}
86}
87
88namespace llvm {
89enum LocalNum {
90 // Operations that must appear first in the block.
91 LN_First,
92 // Operations that are somewhere in the middle of the block, and are sorted on
93 // demand.
94 LN_Middle,
95 // Operations that must appear last in a block, like successor phi node uses.
96 LN_Last
97};
98
99// Associate global and local DFS info with defs and uses, so we can sort them
100// into a global domination ordering.
101struct ValueDFS {
102 int DFSIn = 0;
103 int DFSOut = 0;
104 unsigned int LocalNum = LN_Middle;
105 // Only one of Def or Use will be set.
106 Value *Def = nullptr;
107 Use *U = nullptr;
108 // Neither PInfo nor EdgeOnly participate in the ordering
109 PredicateBase *PInfo = nullptr;
110 bool EdgeOnly = false;
111};
112
113// Perform a strict weak ordering on instructions and arguments.
114static bool valueComesBefore(const Value *A, const Value *B) {
115 auto *ArgA = dyn_cast_or_null<Argument>(A);
116 auto *ArgB = dyn_cast_or_null<Argument>(B);
117 if (ArgA && !ArgB)
118 return true;
119 if (ArgB && !ArgA)
120 return false;
121 if (ArgA && ArgB)
122 return ArgA->getArgNo() < ArgB->getArgNo();
123 return cast<Instruction>(A)->comesBefore(cast<Instruction>(B));
124}
125
126// This compares ValueDFS structures. Doing so allows us to walk the minimum
127// number of instructions necessary to compute our def/use ordering.
128struct ValueDFS_Compare {
129 DominatorTree &DT;
130 ValueDFS_Compare(DominatorTree &DT) : DT(DT) {}
131
132 bool operator()(const ValueDFS &A, const ValueDFS &B) const {
133 if (&A == &B)
134 return false;
135 // The only case we can't directly compare them is when they in the same
136 // block, and both have localnum == middle. In that case, we have to use
137 // comesbefore to see what the real ordering is, because they are in the
138 // same basic block.
139
140 assert((A.DFSIn != B.DFSIn || A.DFSOut == B.DFSOut) &&((void)0)
141 "Equal DFS-in numbers imply equal out numbers")((void)0);
142 bool SameBlock = A.DFSIn == B.DFSIn;
143
144 // We want to put the def that will get used for a given set of phi uses,
145 // before those phi uses.
146 // So we sort by edge, then by def.
147 // Note that only phi nodes uses and defs can come last.
148 if (SameBlock && A.LocalNum == LN_Last && B.LocalNum == LN_Last)
149 return comparePHIRelated(A, B);
150
151 bool isADef = A.Def;
152 bool isBDef = B.Def;
153 if (!SameBlock || A.LocalNum != LN_Middle || B.LocalNum != LN_Middle)
154 return std::tie(A.DFSIn, A.LocalNum, isADef) <
155 std::tie(B.DFSIn, B.LocalNum, isBDef);
156 return localComesBefore(A, B);
157 }
158
159 // For a phi use, or a non-materialized def, return the edge it represents.
160 std::pair<BasicBlock *, BasicBlock *> getBlockEdge(const ValueDFS &VD) const {
161 if (!VD.Def && VD.U) {
162 auto *PHI = cast<PHINode>(VD.U->getUser());
163 return std::make_pair(PHI->getIncomingBlock(*VD.U), PHI->getParent());
164 }
165 // This is really a non-materialized def.
166 return ::getBlockEdge(VD.PInfo);
167 }
168
169 // For two phi related values, return the ordering.
170 bool comparePHIRelated(const ValueDFS &A, const ValueDFS &B) const {
171 BasicBlock *ASrc, *ADest, *BSrc, *BDest;
172 std::tie(ASrc, ADest) = getBlockEdge(A);
173 std::tie(BSrc, BDest) = getBlockEdge(B);
174
175#ifndef NDEBUG1
176 // This function should only be used for values in the same BB, check that.
177 DomTreeNode *DomASrc = DT.getNode(ASrc);
178 DomTreeNode *DomBSrc = DT.getNode(BSrc);
179 assert(DomASrc->getDFSNumIn() == (unsigned)A.DFSIn &&((void)0)
180 "DFS numbers for A should match the ones of the source block")((void)0);
181 assert(DomBSrc->getDFSNumIn() == (unsigned)B.DFSIn &&((void)0)
182 "DFS numbers for B should match the ones of the source block")((void)0);
183 assert(A.DFSIn == B.DFSIn && "Values must be in the same block")((void)0);
184#endif
185 (void)ASrc;
186 (void)BSrc;
187
188 // Use DFS numbers to compare destination blocks, to guarantee a
189 // deterministic order.
190 DomTreeNode *DomADest = DT.getNode(ADest);
191 DomTreeNode *DomBDest = DT.getNode(BDest);
192 unsigned AIn = DomADest->getDFSNumIn();
193 unsigned BIn = DomBDest->getDFSNumIn();
194 bool isADef = A.Def;
195 bool isBDef = B.Def;
196 assert((!A.Def || !A.U) && (!B.Def || !B.U) &&((void)0)
197 "Def and U cannot be set at the same time")((void)0);
198 // Now sort by edge destination and then defs before uses.
199 return std::tie(AIn, isADef) < std::tie(BIn, isBDef);
200 }
201
202 // Get the definition of an instruction that occurs in the middle of a block.
203 Value *getMiddleDef(const ValueDFS &VD) const {
204 if (VD.Def)
205 return VD.Def;
206 // It's possible for the defs and uses to be null. For branches, the local
207 // numbering will say the placed predicaeinfos should go first (IE
208 // LN_beginning), so we won't be in this function. For assumes, we will end
209 // up here, beause we need to order the def we will place relative to the
210 // assume. So for the purpose of ordering, we pretend the def is right
211 // after the assume, because that is where we will insert the info.
212 if (!VD.U) {
213 assert(VD.PInfo &&((void)0)
214 "No def, no use, and no predicateinfo should not occur")((void)0);
215 assert(isa<PredicateAssume>(VD.PInfo) &&((void)0)
216 "Middle of block should only occur for assumes")((void)0);
217 return cast<PredicateAssume>(VD.PInfo)->AssumeInst->getNextNode();
218 }
219 return nullptr;
220 }
221
222 // Return either the Def, if it's not null, or the user of the Use, if the def
223 // is null.
224 const Instruction *getDefOrUser(const Value *Def, const Use *U) const {
225 if (Def)
226 return cast<Instruction>(Def);
227 return cast<Instruction>(U->getUser());
228 }
229
230 // This performs the necessary local basic block ordering checks to tell
231 // whether A comes before B, where both are in the same basic block.
232 bool localComesBefore(const ValueDFS &A, const ValueDFS &B) const {
233 auto *ADef = getMiddleDef(A);
234 auto *BDef = getMiddleDef(B);
235
236 // See if we have real values or uses. If we have real values, we are
237 // guaranteed they are instructions or arguments. No matter what, we are
238 // guaranteed they are in the same block if they are instructions.
239 auto *ArgA = dyn_cast_or_null<Argument>(ADef);
240 auto *ArgB = dyn_cast_or_null<Argument>(BDef);
241
242 if (ArgA || ArgB)
243 return valueComesBefore(ArgA, ArgB);
244
245 auto *AInst = getDefOrUser(ADef, A.U);
246 auto *BInst = getDefOrUser(BDef, B.U);
247 return valueComesBefore(AInst, BInst);
248 }
249};
250
251class PredicateInfoBuilder {
252 // Used to store information about each value we might rename.
253 struct ValueInfo {
254 SmallVector<PredicateBase *, 4> Infos;
255 };
256
257 PredicateInfo &PI;
258 Function &F;
259 DominatorTree &DT;
260 AssumptionCache &AC;
261
262 // This stores info about each operand or comparison result we make copies
263 // of. The real ValueInfos start at index 1, index 0 is unused so that we
264 // can more easily detect invalid indexing.
265 SmallVector<ValueInfo, 32> ValueInfos;
266
267 // This gives the index into the ValueInfos array for a given Value. Because
268 // 0 is not a valid Value Info index, you can use DenseMap::lookup and tell
269 // whether it returned a valid result.
270 DenseMap<Value *, unsigned int> ValueInfoNums;
271
272 // The set of edges along which we can only handle phi uses, due to critical
273 // edges.
274 DenseSet<std::pair<BasicBlock *, BasicBlock *>> EdgeUsesOnly;
275
276 ValueInfo &getOrCreateValueInfo(Value *);
277 const ValueInfo &getValueInfo(Value *) const;
278
279 void processAssume(IntrinsicInst *, BasicBlock *,
280 SmallVectorImpl<Value *> &OpsToRename);
281 void processBranch(BranchInst *, BasicBlock *,
282 SmallVectorImpl<Value *> &OpsToRename);
283 void processSwitch(SwitchInst *, BasicBlock *,
284 SmallVectorImpl<Value *> &OpsToRename);
285 void renameUses(SmallVectorImpl<Value *> &OpsToRename);
286 void addInfoFor(SmallVectorImpl<Value *> &OpsToRename, Value *Op,
287 PredicateBase *PB);
288
289 typedef SmallVectorImpl<ValueDFS> ValueDFSStack;
290 void convertUsesToDFSOrdered(Value *, SmallVectorImpl<ValueDFS> &);
291 Value *materializeStack(unsigned int &, ValueDFSStack &, Value *);
292 bool stackIsInScope(const ValueDFSStack &, const ValueDFS &) const;
293 void popStackUntilDFSScope(ValueDFSStack &, const ValueDFS &);
294
295public:
296 PredicateInfoBuilder(PredicateInfo &PI, Function &F, DominatorTree &DT,
297 AssumptionCache &AC)
298 : PI(PI), F(F), DT(DT), AC(AC) {
299 // Push an empty operand info so that we can detect 0 as not finding one
300 ValueInfos.resize(1);
301 }
302
303 void buildPredicateInfo();
304};
305
306bool PredicateInfoBuilder::stackIsInScope(const ValueDFSStack &Stack,
307 const ValueDFS &VDUse) const {
308 if (Stack.empty())
309 return false;
310 // If it's a phi only use, make sure it's for this phi node edge, and that the
311 // use is in a phi node. If it's anything else, and the top of the stack is
312 // EdgeOnly, we need to pop the stack. We deliberately sort phi uses next to
313 // the defs they must go with so that we can know it's time to pop the stack
314 // when we hit the end of the phi uses for a given def.
315 if (Stack.back().EdgeOnly) {
316 if (!VDUse.U)
317 return false;
318 auto *PHI = dyn_cast<PHINode>(VDUse.U->getUser());
319 if (!PHI)
320 return false;
321 // Check edge
322 BasicBlock *EdgePred = PHI->getIncomingBlock(*VDUse.U);
323 if (EdgePred != getBranchBlock(Stack.back().PInfo))
324 return false;
325
326 // Use dominates, which knows how to handle edge dominance.
327 return DT.dominates(getBlockEdge(Stack.back().PInfo), *VDUse.U);
328 }
329
330 return (VDUse.DFSIn >= Stack.back().DFSIn &&
331 VDUse.DFSOut <= Stack.back().DFSOut);
332}
333
334void PredicateInfoBuilder::popStackUntilDFSScope(ValueDFSStack &Stack,
335 const ValueDFS &VD) {
336 while (!Stack.empty() && !stackIsInScope(Stack, VD))
337 Stack.pop_back();
338}
339
340// Convert the uses of Op into a vector of uses, associating global and local
341// DFS info with each one.
342void PredicateInfoBuilder::convertUsesToDFSOrdered(
343 Value *Op, SmallVectorImpl<ValueDFS> &DFSOrderedSet) {
344 for (auto &U : Op->uses()) {
345 if (auto *I = dyn_cast<Instruction>(U.getUser())) {
346 ValueDFS VD;
347 // Put the phi node uses in the incoming block.
348 BasicBlock *IBlock;
349 if (auto *PN = dyn_cast<PHINode>(I)) {
350 IBlock = PN->getIncomingBlock(U);
351 // Make phi node users appear last in the incoming block
352 // they are from.
353 VD.LocalNum = LN_Last;
354 } else {
355 // If it's not a phi node use, it is somewhere in the middle of the
356 // block.
357 IBlock = I->getParent();
358 VD.LocalNum = LN_Middle;
359 }
360 DomTreeNode *DomNode = DT.getNode(IBlock);
361 // It's possible our use is in an unreachable block. Skip it if so.
362 if (!DomNode)
363 continue;
364 VD.DFSIn = DomNode->getDFSNumIn();
365 VD.DFSOut = DomNode->getDFSNumOut();
366 VD.U = &U;
367 DFSOrderedSet.push_back(VD);
368 }
369 }
370}
371
372bool shouldRename(Value *V) {
373 // Only want real values, not constants. Additionally, operands with one use
374 // are only being used in the comparison, which means they will not be useful
375 // for us to consider for predicateinfo.
376 return (isa<Instruction>(V) || isa<Argument>(V)) && !V->hasOneUse();
377}
378
379// Collect relevant operations from Comparison that we may want to insert copies
380// for.
381void collectCmpOps(CmpInst *Comparison, SmallVectorImpl<Value *> &CmpOperands) {
382 auto *Op0 = Comparison->getOperand(0);
383 auto *Op1 = Comparison->getOperand(1);
384 if (Op0 == Op1)
385 return;
386
387 CmpOperands.push_back(Op0);
388 CmpOperands.push_back(Op1);
389}
390
391// Add Op, PB to the list of value infos for Op, and mark Op to be renamed.
392void PredicateInfoBuilder::addInfoFor(SmallVectorImpl<Value *> &OpsToRename,
393 Value *Op, PredicateBase *PB) {
394 auto &OperandInfo = getOrCreateValueInfo(Op);
395 if (OperandInfo.Infos.empty())
396 OpsToRename.push_back(Op);
397 PI.AllInfos.push_back(PB);
398 OperandInfo.Infos.push_back(PB);
399}
400
401// Process an assume instruction and place relevant operations we want to rename
402// into OpsToRename.
403void PredicateInfoBuilder::processAssume(
404 IntrinsicInst *II, BasicBlock *AssumeBB,
405 SmallVectorImpl<Value *> &OpsToRename) {
406 SmallVector<Value *, 4> Worklist;
407 SmallPtrSet<Value *, 4> Visited;
408 Worklist.push_back(II->getOperand(0));
409 while (!Worklist.empty()) {
410 Value *Cond = Worklist.pop_back_val();
411 if (!Visited.insert(Cond).second)
412 continue;
413 if (Visited.size() > MaxCondsPerBranch)
414 break;
415
416 Value *Op0, *Op1;
417 if (match(Cond, m_LogicalAnd(m_Value(Op0), m_Value(Op1)))) {
418 Worklist.push_back(Op1);
419 Worklist.push_back(Op0);
420 }
421
422 SmallVector<Value *, 4> Values;
423 Values.push_back(Cond);
424 if (auto *Cmp = dyn_cast<CmpInst>(Cond))
425 collectCmpOps(Cmp, Values);
426
427 for (Value *V : Values) {
428 if (shouldRename(V)) {
429 auto *PA = new PredicateAssume(V, II, Cond);
430 addInfoFor(OpsToRename, V, PA);
431 }
432 }
433 }
434}
435
436// Process a block terminating branch, and place relevant operations to be
437// renamed into OpsToRename.
438void PredicateInfoBuilder::processBranch(
439 BranchInst *BI, BasicBlock *BranchBB,
440 SmallVectorImpl<Value *> &OpsToRename) {
441 BasicBlock *FirstBB = BI->getSuccessor(0);
442 BasicBlock *SecondBB = BI->getSuccessor(1);
443
444 for (BasicBlock *Succ : {FirstBB, SecondBB}) {
445 bool TakenEdge = Succ == FirstBB;
446 // Don't try to insert on a self-edge. This is mainly because we will
447 // eliminate during renaming anyway.
448 if (Succ == BranchBB)
449 continue;
450
451 SmallVector<Value *, 4> Worklist;
452 SmallPtrSet<Value *, 4> Visited;
453 Worklist.push_back(BI->getCondition());
454 while (!Worklist.empty()) {
455 Value *Cond = Worklist.pop_back_val();
456 if (!Visited.insert(Cond).second)
457 continue;
458 if (Visited.size() > MaxCondsPerBranch)
459 break;
460
461 Value *Op0, *Op1;
462 if (TakenEdge ? match(Cond, m_LogicalAnd(m_Value(Op0), m_Value(Op1)))
463 : match(Cond, m_LogicalOr(m_Value(Op0), m_Value(Op1)))) {
464 Worklist.push_back(Op1);
465 Worklist.push_back(Op0);
466 }
467
468 SmallVector<Value *, 4> Values;
469 Values.push_back(Cond);
470 if (auto *Cmp = dyn_cast<CmpInst>(Cond))
471 collectCmpOps(Cmp, Values);
472
473 for (Value *V : Values) {
474 if (shouldRename(V)) {
475 PredicateBase *PB =
476 new PredicateBranch(V, BranchBB, Succ, Cond, TakenEdge);
477 addInfoFor(OpsToRename, V, PB);
478 if (!Succ->getSinglePredecessor())
479 EdgeUsesOnly.insert({BranchBB, Succ});
480 }
481 }
482 }
483 }
484}
485// Process a block terminating switch, and place relevant operations to be
486// renamed into OpsToRename.
487void PredicateInfoBuilder::processSwitch(
488 SwitchInst *SI, BasicBlock *BranchBB,
489 SmallVectorImpl<Value *> &OpsToRename) {
490 Value *Op = SI->getCondition();
491 if ((!isa<Instruction>(Op) && !isa<Argument>(Op)) || Op->hasOneUse())
492 return;
493
494 // Remember how many outgoing edges there are to every successor.
495 SmallDenseMap<BasicBlock *, unsigned, 16> SwitchEdges;
496 for (unsigned i = 0, e = SI->getNumSuccessors(); i != e; ++i) {
497 BasicBlock *TargetBlock = SI->getSuccessor(i);
498 ++SwitchEdges[TargetBlock];
499 }
500
501 // Now propagate info for each case value
502 for (auto C : SI->cases()) {
503 BasicBlock *TargetBlock = C.getCaseSuccessor();
504 if (SwitchEdges.lookup(TargetBlock) == 1) {
505 PredicateSwitch *PS = new PredicateSwitch(
506 Op, SI->getParent(), TargetBlock, C.getCaseValue(), SI);
507 addInfoFor(OpsToRename, Op, PS);
508 if (!TargetBlock->getSinglePredecessor())
509 EdgeUsesOnly.insert({BranchBB, TargetBlock});
510 }
511 }
512}
513
514// Build predicate info for our function
515void PredicateInfoBuilder::buildPredicateInfo() {
516 DT.updateDFSNumbers();
517 // Collect operands to rename from all conditional branch terminators, as well
518 // as assume statements.
519 SmallVector<Value *, 8> OpsToRename;
520 for (auto DTN : depth_first(DT.getRootNode())) {
521 BasicBlock *BranchBB = DTN->getBlock();
522 if (auto *BI = dyn_cast<BranchInst>(BranchBB->getTerminator())) {
523 if (!BI->isConditional())
524 continue;
525 // Can't insert conditional information if they all go to the same place.
526 if (BI->getSuccessor(0) == BI->getSuccessor(1))
527 continue;
528 processBranch(BI, BranchBB, OpsToRename);
529 } else if (auto *SI = dyn_cast<SwitchInst>(BranchBB->getTerminator())) {
530 processSwitch(SI, BranchBB, OpsToRename);
531 }
532 }
533 for (auto &Assume : AC.assumptions()) {
4
Assuming '__begin1' is equal to '__end1'
534 if (auto *II = dyn_cast_or_null<IntrinsicInst>(Assume))
535 if (DT.isReachableFromEntry(II->getParent()))
536 processAssume(II, II->getParent(), OpsToRename);
537 }
538 // Now rename all our operations.
539 renameUses(OpsToRename);
5
Calling 'PredicateInfoBuilder::renameUses'
540}
541
542// Given the renaming stack, make all the operands currently on the stack real
543// by inserting them into the IR. Return the last operation's value.
544Value *PredicateInfoBuilder::materializeStack(unsigned int &Counter,
545 ValueDFSStack &RenameStack,
546 Value *OrigOp) {
547 // Find the first thing we have to materialize
548 auto RevIter = RenameStack.rbegin();
549 for (; RevIter != RenameStack.rend(); ++RevIter)
23
Loop condition is false. Execution continues on line 553
550 if (RevIter->Def)
551 break;
552
553 size_t Start = RevIter - RenameStack.rbegin();
554 // The maximum number of things we should be trying to materialize at once
555 // right now is 4, depending on if we had an assume, a branch, and both used
556 // and of conditions.
557 for (auto RenameIter = RenameStack.end() - Start;
25
Loop condition is true. Entering loop body
558 RenameIter != RenameStack.end(); ++RenameIter) {
24
Assuming the condition is true
559 auto *Op =
560 RenameIter == RenameStack.begin() ? OrigOp : (RenameIter - 1)->Def;
26
Assuming the condition is true
27
'?' condition is true
561 ValueDFS &Result = *RenameIter;
562 auto *ValInfo = Result.PInfo;
563 ValInfo->RenamedOp = (RenameStack.end() - Start) == RenameStack.begin()
28
Assuming the condition is true
29
'?' condition is true
564 ? OrigOp
565 : (RenameStack.end() - Start - 1)->Def;
566 // For edge predicates, we can just place the operand in the block before
567 // the terminator. For assume, we have to place it right before the assume
568 // to ensure we dominate all of our uses. Always insert right before the
569 // relevant instruction (terminator, assume), so that we insert in proper
570 // order in the case of multiple predicateinfo in the same block.
571 // The number of named values is used to detect if a new declaration was
572 // added. If so, that declaration is tracked so that it can be removed when
573 // the analysis is done. The corner case were a new declaration results in
574 // a name clash and the old name being renamed is not considered as that
575 // represents an invalid module.
576 if (isa<PredicateWithEdge>(ValInfo)) {
30
Assuming 'ValInfo' is not a 'PredicateWithEdge'
31
Taking false branch
577 IRBuilder<> B(getBranchTerminator(ValInfo));
578 auto NumDecls = F.getParent()->getNumNamedValues();
579 Function *IF = Intrinsic::getDeclaration(
580 F.getParent(), Intrinsic::ssa_copy, Op->getType());
581 if (NumDecls != F.getParent()->getNumNamedValues())
582 PI.CreatedDeclarations.insert(IF);
583 CallInst *PIC =
584 B.CreateCall(IF, Op, Op->getName() + "." + Twine(Counter++));
585 PI.PredicateMap.insert({PIC, ValInfo});
586 Result.Def = PIC;
587 } else {
588 auto *PAssume = dyn_cast<PredicateAssume>(ValInfo);
32
Assuming 'ValInfo' is not a 'PredicateAssume'
33
'PAssume' initialized to a null pointer value
589 assert(PAssume &&((void)0)
590 "Should not have gotten here without it being an assume")((void)0);
591 // Insert the predicate directly after the assume. While it also holds
592 // directly before it, assume(i1 true) is not a useful fact.
593 IRBuilder<> B(PAssume->AssumeInst->getNextNode());
34
Access to field 'AssumeInst' results in a dereference of a null pointer (loaded from variable 'PAssume')
594 auto NumDecls = F.getParent()->getNumNamedValues();
595 Function *IF = Intrinsic::getDeclaration(
596 F.getParent(), Intrinsic::ssa_copy, Op->getType());
597 if (NumDecls != F.getParent()->getNumNamedValues())
598 PI.CreatedDeclarations.insert(IF);
599 CallInst *PIC = B.CreateCall(IF, Op);
600 PI.PredicateMap.insert({PIC, ValInfo});
601 Result.Def = PIC;
602 }
603 }
604 return RenameStack.back().Def;
605}
606
607// Instead of the standard SSA renaming algorithm, which is O(Number of
608// instructions), and walks the entire dominator tree, we walk only the defs +
609// uses. The standard SSA renaming algorithm does not really rely on the
610// dominator tree except to order the stack push/pops of the renaming stacks, so
611// that defs end up getting pushed before hitting the correct uses. This does
612// not require the dominator tree, only the *order* of the dominator tree. The
613// complete and correct ordering of the defs and uses, in dominator tree is
614// contained in the DFS numbering of the dominator tree. So we sort the defs and
615// uses into the DFS ordering, and then just use the renaming stack as per
616// normal, pushing when we hit a def (which is a predicateinfo instruction),
617// popping when we are out of the dfs scope for that def, and replacing any uses
618// with top of stack if it exists. In order to handle liveness without
619// propagating liveness info, we don't actually insert the predicateinfo
620// instruction def until we see a use that it would dominate. Once we see such
621// a use, we materialize the predicateinfo instruction in the right place and
622// use it.
623//
624// TODO: Use this algorithm to perform fast single-variable renaming in
625// promotememtoreg and memoryssa.
626void PredicateInfoBuilder::renameUses(SmallVectorImpl<Value *> &OpsToRename) {
627 ValueDFS_Compare Compare(DT);
628 // Compute liveness, and rename in O(uses) per Op.
629 for (auto *Op : OpsToRename) {
6
Assuming '__begin1' is not equal to '__end1'
630 LLVM_DEBUG(dbgs() << "Visiting " << *Op << "\n")do { } while (false);
7
Loop condition is false. Exiting loop
631 unsigned Counter = 0;
632 SmallVector<ValueDFS, 16> OrderedUses;
633 const auto &ValueInfo = getValueInfo(Op);
634 // Insert the possible copies into the def/use list.
635 // They will become real copies if we find a real use for them, and never
636 // created otherwise.
637 for (auto &PossibleCopy : ValueInfo.Infos) {
8
Assuming '__begin2' is equal to '__end2'
638 ValueDFS VD;
639 // Determine where we are going to place the copy by the copy type.
640 // The predicate info for branches always come first, they will get
641 // materialized in the split block at the top of the block.
642 // The predicate info for assumes will be somewhere in the middle,
643 // it will get materialized in front of the assume.
644 if (const auto *PAssume = dyn_cast<PredicateAssume>(PossibleCopy)) {
645 VD.LocalNum = LN_Middle;
646 DomTreeNode *DomNode = DT.getNode(PAssume->AssumeInst->getParent());
647 if (!DomNode)
648 continue;
649 VD.DFSIn = DomNode->getDFSNumIn();
650 VD.DFSOut = DomNode->getDFSNumOut();
651 VD.PInfo = PossibleCopy;
652 OrderedUses.push_back(VD);
653 } else if (isa<PredicateWithEdge>(PossibleCopy)) {
654 // If we can only do phi uses, we treat it like it's in the branch
655 // block, and handle it specially. We know that it goes last, and only
656 // dominate phi uses.
657 auto BlockEdge = getBlockEdge(PossibleCopy);
658 if (EdgeUsesOnly.count(BlockEdge)) {
659 VD.LocalNum = LN_Last;
660 auto *DomNode = DT.getNode(BlockEdge.first);
661 if (DomNode) {
662 VD.DFSIn = DomNode->getDFSNumIn();
663 VD.DFSOut = DomNode->getDFSNumOut();
664 VD.PInfo = PossibleCopy;
665 VD.EdgeOnly = true;
666 OrderedUses.push_back(VD);
667 }
668 } else {
669 // Otherwise, we are in the split block (even though we perform
670 // insertion in the branch block).
671 // Insert a possible copy at the split block and before the branch.
672 VD.LocalNum = LN_First;
673 auto *DomNode = DT.getNode(BlockEdge.second);
674 if (DomNode) {
675 VD.DFSIn = DomNode->getDFSNumIn();
676 VD.DFSOut = DomNode->getDFSNumOut();
677 VD.PInfo = PossibleCopy;
678 OrderedUses.push_back(VD);
679 }
680 }
681 }
682 }
683
684 convertUsesToDFSOrdered(Op, OrderedUses);
685 // Here we require a stable sort because we do not bother to try to
686 // assign an order to the operands the uses represent. Thus, two
687 // uses in the same instruction do not have a strict sort order
688 // currently and will be considered equal. We could get rid of the
689 // stable sort by creating one if we wanted.
690 llvm::stable_sort(OrderedUses, Compare);
691 SmallVector<ValueDFS, 8> RenameStack;
692 // For each use, sorted into dfs order, push values and replaces uses with
693 // top of stack, which will represent the reaching def.
694 for (auto &VD : OrderedUses) {
9
Assuming '__begin2' is not equal to '__end2'
695 // We currently do not materialize copy over copy, but we should decide if
696 // we want to.
697 bool PossibleCopy = VD.PInfo != nullptr;
10
Assuming the condition is false
698 if (RenameStack.empty()) {
11
Taking false branch
699 LLVM_DEBUG(dbgs() << "Rename Stack is empty\n")do { } while (false);
700 } else {
701 LLVM_DEBUG(dbgs() << "Rename Stack Top DFS numbers are ("do { } while (false)
12
Loop condition is false. Exiting loop
702 << RenameStack.back().DFSIn << ","do { } while (false)
703 << RenameStack.back().DFSOut << ")\n")do { } while (false);
704 }
705
706 LLVM_DEBUG(dbgs() << "Current DFS numbers are (" << VD.DFSIn << ","do { } while (false)
13
Loop condition is false. Exiting loop
707 << VD.DFSOut << ")\n")do { } while (false);
708
709 bool ShouldPush = (VD.Def || PossibleCopy);
14
Assuming field 'Def' is null
710 bool OutOfScope = !stackIsInScope(RenameStack, VD);
711 if (OutOfScope
14.1
'OutOfScope' is true
14.1
'OutOfScope' is true
|| ShouldPush) {
712 // Sync to our current scope.
713 popStackUntilDFSScope(RenameStack, VD);
714 if (ShouldPush
14.2
'ShouldPush' is false
14.2
'ShouldPush' is false
) {
15
Taking false branch
715 RenameStack.push_back(VD);
716 }
717 }
718 // If we get to this point, and the stack is empty we must have a use
719 // with no renaming needed, just skip it.
720 if (RenameStack.empty())
16
Taking false branch
721 continue;
722 // Skip values, only want to rename the uses
723 if (VD.Def
16.1
Field 'Def' is null
16.1
Field 'Def' is null
|| PossibleCopy
16.2
'PossibleCopy' is false
16.2
'PossibleCopy' is false
)
17
Taking false branch
724 continue;
725 if (!DebugCounter::shouldExecute(RenameCounter)) {
18
Assuming the condition is false
19
Taking false branch
726 LLVM_DEBUG(dbgs() << "Skipping execution due to debug counter\n")do { } while (false);
727 continue;
728 }
729 ValueDFS &Result = RenameStack.back();
730
731 // If the possible copy dominates something, materialize our stack up to
732 // this point. This ensures every comparison that affects our operation
733 // ends up with predicateinfo.
734 if (!Result.Def)
20
Assuming field 'Def' is null
21
Taking true branch
735 Result.Def = materializeStack(Counter, RenameStack, Op);
22
Calling 'PredicateInfoBuilder::materializeStack'
736
737 LLVM_DEBUG(dbgs() << "Found replacement " << *Result.Def << " for "do { } while (false)
738 << *VD.U->get() << " in " << *(VD.U->getUser())do { } while (false)
739 << "\n")do { } while (false);
740 assert(DT.dominates(cast<Instruction>(Result.Def), *VD.U) &&((void)0)
741 "Predicateinfo def should have dominated this use")((void)0);
742 VD.U->set(Result.Def);
743 }
744 }
745}
746
747PredicateInfoBuilder::ValueInfo &
748PredicateInfoBuilder::getOrCreateValueInfo(Value *Operand) {
749 auto OIN = ValueInfoNums.find(Operand);
750 if (OIN == ValueInfoNums.end()) {
751 // This will grow it
752 ValueInfos.resize(ValueInfos.size() + 1);
753 // This will use the new size and give us a 0 based number of the info
754 auto InsertResult = ValueInfoNums.insert({Operand, ValueInfos.size() - 1});
755 assert(InsertResult.second && "Value info number already existed?")((void)0);
756 return ValueInfos[InsertResult.first->second];
757 }
758 return ValueInfos[OIN->second];
759}
760
761const PredicateInfoBuilder::ValueInfo &
762PredicateInfoBuilder::getValueInfo(Value *Operand) const {
763 auto OINI = ValueInfoNums.lookup(Operand);
764 assert(OINI != 0 && "Operand was not really in the Value Info Numbers")((void)0);
765 assert(OINI < ValueInfos.size() &&((void)0)
766 "Value Info Number greater than size of Value Info Table")((void)0);
767 return ValueInfos[OINI];
768}
769
770PredicateInfo::PredicateInfo(Function &F, DominatorTree &DT,
771 AssumptionCache &AC)
772 : F(F) {
773 PredicateInfoBuilder Builder(*this, F, DT, AC);
774 Builder.buildPredicateInfo();
3
Calling 'PredicateInfoBuilder::buildPredicateInfo'
775}
776
777// Remove all declarations we created . The PredicateInfo consumers are
778// responsible for remove the ssa_copy calls created.
779PredicateInfo::~PredicateInfo() {
780 // Collect function pointers in set first, as SmallSet uses a SmallVector
781 // internally and we have to remove the asserting value handles first.
782 SmallPtrSet<Function *, 20> FunctionPtrs;
783 for (auto &F : CreatedDeclarations)
784 FunctionPtrs.insert(&*F);
785 CreatedDeclarations.clear();
786
787 for (Function *F : FunctionPtrs) {
788 assert(F->user_begin() == F->user_end() &&((void)0)
789 "PredicateInfo consumer did not remove all SSA copies.")((void)0);
790 F->eraseFromParent();
791 }
792}
793
794Optional<PredicateConstraint> PredicateBase::getConstraint() const {
795 switch (Type) {
796 case PT_Assume:
797 case PT_Branch: {
798 bool TrueEdge = true;
799 if (auto *PBranch = dyn_cast<PredicateBranch>(this))
800 TrueEdge = PBranch->TrueEdge;
801
802 if (Condition == RenamedOp) {
803 return {{CmpInst::ICMP_EQ,
804 TrueEdge ? ConstantInt::getTrue(Condition->getType())
805 : ConstantInt::getFalse(Condition->getType())}};
806 }
807
808 CmpInst *Cmp = dyn_cast<CmpInst>(Condition);
809 if (!Cmp) {
810 // TODO: Make this an assertion once RenamedOp is fully accurate.
811 return None;
812 }
813
814 CmpInst::Predicate Pred;
815 Value *OtherOp;
816 if (Cmp->getOperand(0) == RenamedOp) {
817 Pred = Cmp->getPredicate();
818 OtherOp = Cmp->getOperand(1);
819 } else if (Cmp->getOperand(1) == RenamedOp) {
820 Pred = Cmp->getSwappedPredicate();
821 OtherOp = Cmp->getOperand(0);
822 } else {
823 // TODO: Make this an assertion once RenamedOp is fully accurate.
824 return None;
825 }
826
827 // Invert predicate along false edge.
828 if (!TrueEdge)
829 Pred = CmpInst::getInversePredicate(Pred);
830
831 return {{Pred, OtherOp}};
832 }
833 case PT_Switch:
834 if (Condition != RenamedOp) {
835 // TODO: Make this an assertion once RenamedOp is fully accurate.
836 return None;
837 }
838
839 return {{CmpInst::ICMP_EQ, cast<PredicateSwitch>(this)->CaseValue}};
840 }
841 llvm_unreachable("Unknown predicate type")__builtin_unreachable();
842}
843
844void PredicateInfo::verifyPredicateInfo() const {}
845
846char PredicateInfoPrinterLegacyPass::ID = 0;
847
848PredicateInfoPrinterLegacyPass::PredicateInfoPrinterLegacyPass()
849 : FunctionPass(ID) {
850 initializePredicateInfoPrinterLegacyPassPass(
851 *PassRegistry::getPassRegistry());
852}
853
854void PredicateInfoPrinterLegacyPass::getAnalysisUsage(AnalysisUsage &AU) const {
855 AU.setPreservesAll();
856 AU.addRequiredTransitive<DominatorTreeWrapperPass>();
857 AU.addRequired<AssumptionCacheTracker>();
858}
859
860// Replace ssa_copy calls created by PredicateInfo with their operand.
861static void replaceCreatedSSACopys(PredicateInfo &PredInfo, Function &F) {
862 for (Instruction &Inst : llvm::make_early_inc_range(instructions(F))) {
863 const auto *PI = PredInfo.getPredicateInfoFor(&Inst);
864 auto *II = dyn_cast<IntrinsicInst>(&Inst);
865 if (!PI || !II || II->getIntrinsicID() != Intrinsic::ssa_copy)
866 continue;
867
868 Inst.replaceAllUsesWith(II->getOperand(0));
869 Inst.eraseFromParent();
870 }
871}
872
873bool PredicateInfoPrinterLegacyPass::runOnFunction(Function &F) {
874 auto &DT = getAnalysis<DominatorTreeWrapperPass>().getDomTree();
875 auto &AC = getAnalysis<AssumptionCacheTracker>().getAssumptionCache(F);
876 auto PredInfo = std::make_unique<PredicateInfo>(F, DT, AC);
877 PredInfo->print(dbgs());
878 if (VerifyPredicateInfo)
879 PredInfo->verifyPredicateInfo();
880
881 replaceCreatedSSACopys(*PredInfo, F);
882 return false;
883}
884
885PreservedAnalyses PredicateInfoPrinterPass::run(Function &F,
886 FunctionAnalysisManager &AM) {
887 auto &DT = AM.getResult<DominatorTreeAnalysis>(F);
888 auto &AC = AM.getResult<AssumptionAnalysis>(F);
889 OS << "PredicateInfo for function: " << F.getName() << "\n";
890 auto PredInfo = std::make_unique<PredicateInfo>(F, DT, AC);
891 PredInfo->print(OS);
892
893 replaceCreatedSSACopys(*PredInfo, F);
894 return PreservedAnalyses::all();
895}
896
897/// An assembly annotator class to print PredicateInfo information in
898/// comments.
899class PredicateInfoAnnotatedWriter : public AssemblyAnnotationWriter {
900 friend class PredicateInfo;
901 const PredicateInfo *PredInfo;
902
903public:
904 PredicateInfoAnnotatedWriter(const PredicateInfo *M) : PredInfo(M) {}
905
906 void emitBasicBlockStartAnnot(const BasicBlock *BB,
907 formatted_raw_ostream &OS) override {}
908
909 void emitInstructionAnnot(const Instruction *I,
910 formatted_raw_ostream &OS) override {
911 if (const auto *PI = PredInfo->getPredicateInfoFor(I)) {
912 OS << "; Has predicate info\n";
913 if (const auto *PB = dyn_cast<PredicateBranch>(PI)) {
914 OS << "; branch predicate info { TrueEdge: " << PB->TrueEdge
915 << " Comparison:" << *PB->Condition << " Edge: [";
916 PB->From->printAsOperand(OS);
917 OS << ",";
918 PB->To->printAsOperand(OS);
919 OS << "]";
920 } else if (const auto *PS = dyn_cast<PredicateSwitch>(PI)) {
921 OS << "; switch predicate info { CaseValue: " << *PS->CaseValue
922 << " Switch:" << *PS->Switch << " Edge: [";
923 PS->From->printAsOperand(OS);
924 OS << ",";
925 PS->To->printAsOperand(OS);
926 OS << "]";
927 } else if (const auto *PA = dyn_cast<PredicateAssume>(PI)) {
928 OS << "; assume predicate info {"
929 << " Comparison:" << *PA->Condition;
930 }
931 OS << ", RenamedOp: ";
932 PI->RenamedOp->printAsOperand(OS, false);
933 OS << " }\n";
934 }
935 }
936};
937
938void PredicateInfo::print(raw_ostream &OS) const {
939 PredicateInfoAnnotatedWriter Writer(this);
940 F.print(OS, &Writer);
941}
942
943void PredicateInfo::dump() const {
944 PredicateInfoAnnotatedWriter Writer(this);
945 F.print(dbgs(), &Writer);
946}
947
948PreservedAnalyses PredicateInfoVerifierPass::run(Function &F,
949 FunctionAnalysisManager &AM) {
950 auto &DT = AM.getResult<DominatorTreeAnalysis>(F);
951 auto &AC = AM.getResult<AssumptionAnalysis>(F);
952 std::make_unique<PredicateInfo>(F, DT, AC)->verifyPredicateInfo();
1
Calling 'make_unique<llvm::PredicateInfo, llvm::Function &, llvm::DominatorTree &, llvm::AssumptionCache &>'
953
954 return PreservedAnalyses::all();
955}
956}

/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)...));
2
Calling constructor for 'PredicateInfo'
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