Bug Summary

File:src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/lib/Transforms/Scalar/GuardWidening.cpp
Warning:line 559, column 9
Called C++ object pointer is null

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 GuardWidening.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/Transforms/Scalar/GuardWidening.cpp

/usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/lib/Transforms/Scalar/GuardWidening.cpp

1//===- GuardWidening.cpp - ---- Guard widening ----------------------------===//
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 guard widening pass. The semantics of the
10// @llvm.experimental.guard intrinsic lets LLVM transform it so that it fails
11// more often that it did before the transform. This optimization is called
12// "widening" and can be used hoist and common runtime checks in situations like
13// these:
14//
15// %cmp0 = 7 u< Length
16// call @llvm.experimental.guard(i1 %cmp0) [ "deopt"(...) ]
17// call @unknown_side_effects()
18// %cmp1 = 9 u< Length
19// call @llvm.experimental.guard(i1 %cmp1) [ "deopt"(...) ]
20// ...
21//
22// =>
23//
24// %cmp0 = 9 u< Length
25// call @llvm.experimental.guard(i1 %cmp0) [ "deopt"(...) ]
26// call @unknown_side_effects()
27// ...
28//
29// If %cmp0 is false, @llvm.experimental.guard will "deoptimize" back to a
30// generic implementation of the same function, which will have the correct
31// semantics from that point onward. It is always _legal_ to deoptimize (so
32// replacing %cmp0 with false is "correct"), though it may not always be
33// profitable to do so.
34//
35// NB! This pass is a work in progress. It hasn't been tuned to be "production
36// ready" yet. It is known to have quadriatic running time and will not scale
37// to large numbers of guards
38//
39//===----------------------------------------------------------------------===//
40
41#include "llvm/Transforms/Scalar/GuardWidening.h"
42#include "llvm/ADT/DenseMap.h"
43#include "llvm/ADT/DepthFirstIterator.h"
44#include "llvm/ADT/Statistic.h"
45#include "llvm/Analysis/BranchProbabilityInfo.h"
46#include "llvm/Analysis/GuardUtils.h"
47#include "llvm/Analysis/LoopInfo.h"
48#include "llvm/Analysis/LoopPass.h"
49#include "llvm/Analysis/PostDominators.h"
50#include "llvm/Analysis/ValueTracking.h"
51#include "llvm/IR/ConstantRange.h"
52#include "llvm/IR/Dominators.h"
53#include "llvm/IR/IntrinsicInst.h"
54#include "llvm/IR/PatternMatch.h"
55#include "llvm/InitializePasses.h"
56#include "llvm/Pass.h"
57#include "llvm/Support/CommandLine.h"
58#include "llvm/Support/Debug.h"
59#include "llvm/Support/KnownBits.h"
60#include "llvm/Transforms/Scalar.h"
61#include "llvm/Transforms/Utils/GuardUtils.h"
62#include "llvm/Transforms/Utils/LoopUtils.h"
63#include <functional>
64
65using namespace llvm;
66
67#define DEBUG_TYPE"guard-widening" "guard-widening"
68
69STATISTIC(GuardsEliminated, "Number of eliminated guards")static llvm::Statistic GuardsEliminated = {"guard-widening", "GuardsEliminated"
, "Number of eliminated guards"}
;
70STATISTIC(CondBranchEliminated, "Number of eliminated conditional branches")static llvm::Statistic CondBranchEliminated = {"guard-widening"
, "CondBranchEliminated", "Number of eliminated conditional branches"
}
;
71
72static cl::opt<bool>
73 WidenBranchGuards("guard-widening-widen-branch-guards", cl::Hidden,
74 cl::desc("Whether or not we should widen guards "
75 "expressed as branches by widenable conditions"),
76 cl::init(true));
77
78namespace {
79
80// Get the condition of \p I. It can either be a guard or a conditional branch.
81static Value *getCondition(Instruction *I) {
82 if (IntrinsicInst *GI = dyn_cast<IntrinsicInst>(I)) {
83 assert(GI->getIntrinsicID() == Intrinsic::experimental_guard &&((void)0)
84 "Bad guard intrinsic?")((void)0);
85 return GI->getArgOperand(0);
86 }
87 Value *Cond, *WC;
88 BasicBlock *IfTrueBB, *IfFalseBB;
89 if (parseWidenableBranch(I, Cond, WC, IfTrueBB, IfFalseBB))
90 return Cond;
91
92 return cast<BranchInst>(I)->getCondition();
93}
94
95// Set the condition for \p I to \p NewCond. \p I can either be a guard or a
96// conditional branch.
97static void setCondition(Instruction *I, Value *NewCond) {
98 if (IntrinsicInst *GI = dyn_cast<IntrinsicInst>(I)) {
99 assert(GI->getIntrinsicID() == Intrinsic::experimental_guard &&((void)0)
100 "Bad guard intrinsic?")((void)0);
101 GI->setArgOperand(0, NewCond);
102 return;
103 }
104 cast<BranchInst>(I)->setCondition(NewCond);
105}
106
107// Eliminates the guard instruction properly.
108static void eliminateGuard(Instruction *GuardInst) {
109 GuardInst->eraseFromParent();
110 ++GuardsEliminated;
111}
112
113class GuardWideningImpl {
114 DominatorTree &DT;
115 PostDominatorTree *PDT;
116 LoopInfo &LI;
117
118 /// Together, these describe the region of interest. This might be all of
119 /// the blocks within a function, or only a given loop's blocks and preheader.
120 DomTreeNode *Root;
121 std::function<bool(BasicBlock*)> BlockFilter;
122
123 /// The set of guards and conditional branches whose conditions have been
124 /// widened into dominating guards.
125 SmallVector<Instruction *, 16> EliminatedGuardsAndBranches;
126
127 /// The set of guards which have been widened to include conditions to other
128 /// guards.
129 DenseSet<Instruction *> WidenedGuards;
130
131 /// Try to eliminate instruction \p Instr by widening it into an earlier
132 /// dominating guard. \p DFSI is the DFS iterator on the dominator tree that
133 /// is currently visiting the block containing \p Guard, and \p GuardsPerBlock
134 /// maps BasicBlocks to the set of guards seen in that block.
135 bool eliminateInstrViaWidening(
136 Instruction *Instr, const df_iterator<DomTreeNode *> &DFSI,
137 const DenseMap<BasicBlock *, SmallVector<Instruction *, 8>> &
138 GuardsPerBlock, bool InvertCondition = false);
139
140 /// Used to keep track of which widening potential is more effective.
141 enum WideningScore {
142 /// Don't widen.
143 WS_IllegalOrNegative,
144
145 /// Widening is performance neutral as far as the cycles spent in check
146 /// conditions goes (but can still help, e.g., code layout, having less
147 /// deopt state).
148 WS_Neutral,
149
150 /// Widening is profitable.
151 WS_Positive,
152
153 /// Widening is very profitable. Not significantly different from \c
154 /// WS_Positive, except by the order.
155 WS_VeryPositive
156 };
157
158 static StringRef scoreTypeToString(WideningScore WS);
159
160 /// Compute the score for widening the condition in \p DominatedInstr
161 /// into \p DominatingGuard. If \p InvertCond is set, then we widen the
162 /// inverted condition of the dominating guard.
163 WideningScore computeWideningScore(Instruction *DominatedInstr,
164 Instruction *DominatingGuard,
165 bool InvertCond);
166
167 /// Helper to check if \p V can be hoisted to \p InsertPos.
168 bool isAvailableAt(const Value *V, const Instruction *InsertPos) const {
169 SmallPtrSet<const Instruction *, 8> Visited;
170 return isAvailableAt(V, InsertPos, Visited);
171 }
172
173 bool isAvailableAt(const Value *V, const Instruction *InsertPos,
174 SmallPtrSetImpl<const Instruction *> &Visited) const;
175
176 /// Helper to hoist \p V to \p InsertPos. Guaranteed to succeed if \c
177 /// isAvailableAt returned true.
178 void makeAvailableAt(Value *V, Instruction *InsertPos) const;
179
180 /// Common helper used by \c widenGuard and \c isWideningCondProfitable. Try
181 /// to generate an expression computing the logical AND of \p Cond0 and (\p
182 /// Cond1 XOR \p InvertCondition).
183 /// Return true if the expression computing the AND is only as
184 /// expensive as computing one of the two. If \p InsertPt is true then
185 /// actually generate the resulting expression, make it available at \p
186 /// InsertPt and return it in \p Result (else no change to the IR is made).
187 bool widenCondCommon(Value *Cond0, Value *Cond1, Instruction *InsertPt,
188 Value *&Result, bool InvertCondition);
189
190 /// Represents a range check of the form \c Base + \c Offset u< \c Length,
191 /// with the constraint that \c Length is not negative. \c CheckInst is the
192 /// pre-existing instruction in the IR that computes the result of this range
193 /// check.
194 class RangeCheck {
195 const Value *Base;
196 const ConstantInt *Offset;
197 const Value *Length;
198 ICmpInst *CheckInst;
199
200 public:
201 explicit RangeCheck(const Value *Base, const ConstantInt *Offset,
202 const Value *Length, ICmpInst *CheckInst)
203 : Base(Base), Offset(Offset), Length(Length), CheckInst(CheckInst) {}
204
205 void setBase(const Value *NewBase) { Base = NewBase; }
206 void setOffset(const ConstantInt *NewOffset) { Offset = NewOffset; }
207
208 const Value *getBase() const { return Base; }
209 const ConstantInt *getOffset() const { return Offset; }
210 const APInt &getOffsetValue() const { return getOffset()->getValue(); }
211 const Value *getLength() const { return Length; };
212 ICmpInst *getCheckInst() const { return CheckInst; }
213
214 void print(raw_ostream &OS, bool PrintTypes = false) {
215 OS << "Base: ";
216 Base->printAsOperand(OS, PrintTypes);
217 OS << " Offset: ";
218 Offset->printAsOperand(OS, PrintTypes);
219 OS << " Length: ";
220 Length->printAsOperand(OS, PrintTypes);
221 }
222
223 LLVM_DUMP_METHOD__attribute__((noinline)) void dump() {
224 print(dbgs());
225 dbgs() << "\n";
226 }
227 };
228
229 /// Parse \p CheckCond into a conjunction (logical-and) of range checks; and
230 /// append them to \p Checks. Returns true on success, may clobber \c Checks
231 /// on failure.
232 bool parseRangeChecks(Value *CheckCond, SmallVectorImpl<RangeCheck> &Checks) {
233 SmallPtrSet<const Value *, 8> Visited;
234 return parseRangeChecks(CheckCond, Checks, Visited);
235 }
236
237 bool parseRangeChecks(Value *CheckCond, SmallVectorImpl<RangeCheck> &Checks,
238 SmallPtrSetImpl<const Value *> &Visited);
239
240 /// Combine the checks in \p Checks into a smaller set of checks and append
241 /// them into \p CombinedChecks. Return true on success (i.e. all of checks
242 /// in \p Checks were combined into \p CombinedChecks). Clobbers \p Checks
243 /// and \p CombinedChecks on success and on failure.
244 bool combineRangeChecks(SmallVectorImpl<RangeCheck> &Checks,
245 SmallVectorImpl<RangeCheck> &CombinedChecks) const;
246
247 /// Can we compute the logical AND of \p Cond0 and \p Cond1 for the price of
248 /// computing only one of the two expressions?
249 bool isWideningCondProfitable(Value *Cond0, Value *Cond1, bool InvertCond) {
250 Value *ResultUnused;
251 return widenCondCommon(Cond0, Cond1, /*InsertPt=*/nullptr, ResultUnused,
252 InvertCond);
253 }
254
255 /// If \p InvertCondition is false, Widen \p ToWiden to fail if
256 /// \p NewCondition is false, otherwise make it fail if \p NewCondition is
257 /// true (in addition to whatever it is already checking).
258 void widenGuard(Instruction *ToWiden, Value *NewCondition,
259 bool InvertCondition) {
260 Value *Result;
43
'Result' declared without an initial value
261
262 widenCondCommon(getCondition(ToWiden), NewCondition, ToWiden, Result,
44
Passing value via 4th parameter 'Result'
45
Calling 'GuardWideningImpl::widenCondCommon'
263 InvertCondition);
264 if (isGuardAsWidenableBranch(ToWiden)) {
265 setWidenableBranchCond(cast<BranchInst>(ToWiden), Result);
266 return;
267 }
268 setCondition(ToWiden, Result);
269 }
270
271public:
272
273 explicit GuardWideningImpl(DominatorTree &DT, PostDominatorTree *PDT,
274 LoopInfo &LI, DomTreeNode *Root,
275 std::function<bool(BasicBlock*)> BlockFilter)
276 : DT(DT), PDT(PDT), LI(LI), Root(Root), BlockFilter(BlockFilter)
277 {}
278
279 /// The entry point for this pass.
280 bool run();
281};
282}
283
284static bool isSupportedGuardInstruction(const Instruction *Insn) {
285 if (isGuard(Insn))
286 return true;
287 if (WidenBranchGuards && isGuardAsWidenableBranch(Insn))
288 return true;
289 return false;
290}
291
292bool GuardWideningImpl::run() {
293 DenseMap<BasicBlock *, SmallVector<Instruction *, 8>> GuardsInBlock;
294 bool Changed = false;
295 for (auto DFI = df_begin(Root), DFE = df_end(Root);
7
Loop condition is true. Entering loop body
296 DFI != DFE; ++DFI) {
297 auto *BB = (*DFI)->getBlock();
298 if (!BlockFilter(BB))
8
Calling 'function::operator()'
15
Returning from 'function::operator()'
16
Assuming the condition is false
17
Taking false branch
299 continue;
300
301 auto &CurrentList = GuardsInBlock[BB];
302
303 for (auto &I : *BB)
304 if (isSupportedGuardInstruction(&I))
305 CurrentList.push_back(cast<Instruction>(&I));
306
307 for (auto *II : CurrentList)
18
Assuming '__begin2' is not equal to '__end2'
308 Changed |= eliminateInstrViaWidening(II, DFI, GuardsInBlock);
19
Calling 'GuardWideningImpl::eliminateInstrViaWidening'
309 }
310
311 assert(EliminatedGuardsAndBranches.empty() || Changed)((void)0);
312 for (auto *I : EliminatedGuardsAndBranches)
313 if (!WidenedGuards.count(I)) {
314 assert(isa<ConstantInt>(getCondition(I)) && "Should be!")((void)0);
315 if (isSupportedGuardInstruction(I))
316 eliminateGuard(I);
317 else {
318 assert(isa<BranchInst>(I) &&((void)0)
319 "Eliminated something other than guard or branch?")((void)0);
320 ++CondBranchEliminated;
321 }
322 }
323
324 return Changed;
325}
326
327bool GuardWideningImpl::eliminateInstrViaWidening(
328 Instruction *Instr, const df_iterator<DomTreeNode *> &DFSI,
329 const DenseMap<BasicBlock *, SmallVector<Instruction *, 8>> &
330 GuardsInBlock, bool InvertCondition) {
331 // Ignore trivial true or false conditions. These instructions will be
332 // trivially eliminated by any cleanup pass. Do not erase them because other
333 // guards can possibly be widened into them.
334 if (isa<ConstantInt>(getCondition(Instr)))
20
Assuming the object is not a 'ConstantInt'
21
Taking false branch
335 return false;
336
337 Instruction *BestSoFar = nullptr;
338 auto BestScoreSoFar = WS_IllegalOrNegative;
339
340 // In the set of dominating guards, find the one we can merge GuardInst with
341 // for the most profit.
342 for (unsigned i = 0, e = DFSI.getPathLength(); i != e; ++i) {
22
Assuming 'i' is not equal to 'e'
23
Loop condition is true. Entering loop body
38
Assuming 'i' is equal to 'e'
39
Loop condition is false. Execution continues on line 381
343 auto *CurBB = DFSI.getPath(i)->getBlock();
344 if (!BlockFilter(CurBB))
24
Calling 'function::operator()'
30
Returning from 'function::operator()'
31
Assuming the condition is false
32
Taking false branch
345 break;
346 assert(GuardsInBlock.count(CurBB) && "Must have been populated by now!")((void)0);
347 const auto &GuardsInCurBB = GuardsInBlock.find(CurBB)->second;
348
349 auto I = GuardsInCurBB.begin();
350 auto E = Instr->getParent() == CurBB ? find(GuardsInCurBB, Instr)
33
Assuming the condition is false
34
'?' condition is false
351 : GuardsInCurBB.end();
352
353#ifndef NDEBUG1
354 {
355 unsigned Index = 0;
356 for (auto &I : *CurBB) {
357 if (Index == GuardsInCurBB.size())
358 break;
359 if (GuardsInCurBB[Index] == &I)
360 Index++;
361 }
362 assert(Index == GuardsInCurBB.size() &&((void)0)
363 "Guards expected to be in order!")((void)0);
364 }
365#endif
366
367 assert((i == (e - 1)) == (Instr->getParent() == CurBB) && "Bad DFS?")((void)0);
368
369 for (auto *Candidate : make_range(I, E)) {
35
Assuming '__begin2' is not equal to '__end2'
370 auto Score = computeWideningScore(Instr, Candidate, InvertCondition);
371 LLVM_DEBUG(dbgs() << "Score between " << *getCondition(Instr)do { } while (false)
36
Loop condition is false. Exiting loop
372 << " and " << *getCondition(Candidate) << " is "do { } while (false)
373 << scoreTypeToString(Score) << "\n")do { } while (false);
374 if (Score
36.1
'Score' is > 'BestScoreSoFar'
36.1
'Score' is > 'BestScoreSoFar'
> BestScoreSoFar) {
37
Taking true branch
375 BestScoreSoFar = Score;
376 BestSoFar = Candidate;
377 }
378 }
379 }
380
381 if (BestScoreSoFar
39.1
'BestScoreSoFar' is not equal to WS_IllegalOrNegative
39.1
'BestScoreSoFar' is not equal to WS_IllegalOrNegative
== WS_IllegalOrNegative) {
40
Taking false branch
382 LLVM_DEBUG(dbgs() << "Did not eliminate guard " << *Instr << "\n")do { } while (false);
383 return false;
384 }
385
386 assert(BestSoFar != Instr && "Should have never visited same guard!")((void)0);
387 assert(DT.dominates(BestSoFar, Instr) && "Should be!")((void)0);
388
389 LLVM_DEBUG(dbgs() << "Widening " << *Instr << " into " << *BestSoFardo { } while (false)
41
Loop condition is false. Exiting loop
390 << " with score " << scoreTypeToString(BestScoreSoFar)do { } while (false)
391 << "\n")do { } while (false);
392 widenGuard(BestSoFar, getCondition(Instr), InvertCondition);
42
Calling 'GuardWideningImpl::widenGuard'
393 auto NewGuardCondition = InvertCondition
394 ? ConstantInt::getFalse(Instr->getContext())
395 : ConstantInt::getTrue(Instr->getContext());
396 setCondition(Instr, NewGuardCondition);
397 EliminatedGuardsAndBranches.push_back(Instr);
398 WidenedGuards.insert(BestSoFar);
399 return true;
400}
401
402GuardWideningImpl::WideningScore
403GuardWideningImpl::computeWideningScore(Instruction *DominatedInstr,
404 Instruction *DominatingGuard,
405 bool InvertCond) {
406 Loop *DominatedInstrLoop = LI.getLoopFor(DominatedInstr->getParent());
407 Loop *DominatingGuardLoop = LI.getLoopFor(DominatingGuard->getParent());
408 bool HoistingOutOfLoop = false;
409
410 if (DominatingGuardLoop != DominatedInstrLoop) {
411 // Be conservative and don't widen into a sibling loop. TODO: If the
412 // sibling is colder, we should consider allowing this.
413 if (DominatingGuardLoop &&
414 !DominatingGuardLoop->contains(DominatedInstrLoop))
415 return WS_IllegalOrNegative;
416
417 HoistingOutOfLoop = true;
418 }
419
420 if (!isAvailableAt(getCondition(DominatedInstr), DominatingGuard))
421 return WS_IllegalOrNegative;
422
423 // If the guard was conditional executed, it may never be reached
424 // dynamically. There are two potential downsides to hoisting it out of the
425 // conditionally executed region: 1) we may spuriously deopt without need and
426 // 2) we have the extra cost of computing the guard condition in the common
427 // case. At the moment, we really only consider the second in our heuristic
428 // here. TODO: evaluate cost model for spurious deopt
429 // NOTE: As written, this also lets us hoist right over another guard which
430 // is essentially just another spelling for control flow.
431 if (isWideningCondProfitable(getCondition(DominatedInstr),
432 getCondition(DominatingGuard), InvertCond))
433 return HoistingOutOfLoop ? WS_VeryPositive : WS_Positive;
434
435 if (HoistingOutOfLoop)
436 return WS_Positive;
437
438 // Returns true if we might be hoisting above explicit control flow. Note
439 // that this completely ignores implicit control flow (guards, calls which
440 // throw, etc...). That choice appears arbitrary.
441 auto MaybeHoistingOutOfIf = [&]() {
442 auto *DominatingBlock = DominatingGuard->getParent();
443 auto *DominatedBlock = DominatedInstr->getParent();
444 if (isGuardAsWidenableBranch(DominatingGuard))
445 DominatingBlock = cast<BranchInst>(DominatingGuard)->getSuccessor(0);
446
447 // Same Block?
448 if (DominatedBlock == DominatingBlock)
449 return false;
450 // Obvious successor (common loop header/preheader case)
451 if (DominatedBlock == DominatingBlock->getUniqueSuccessor())
452 return false;
453 // TODO: diamond, triangle cases
454 if (!PDT) return true;
455 return !PDT->dominates(DominatedBlock, DominatingBlock);
456 };
457
458 return MaybeHoistingOutOfIf() ? WS_IllegalOrNegative : WS_Neutral;
459}
460
461bool GuardWideningImpl::isAvailableAt(
462 const Value *V, const Instruction *Loc,
463 SmallPtrSetImpl<const Instruction *> &Visited) const {
464 auto *Inst = dyn_cast<Instruction>(V);
465 if (!Inst || DT.dominates(Inst, Loc) || Visited.count(Inst))
466 return true;
467
468 if (!isSafeToSpeculativelyExecute(Inst, Loc, &DT) ||
469 Inst->mayReadFromMemory())
470 return false;
471
472 Visited.insert(Inst);
473
474 // We only want to go _up_ the dominance chain when recursing.
475 assert(!isa<PHINode>(Loc) &&((void)0)
476 "PHIs should return false for isSafeToSpeculativelyExecute")((void)0);
477 assert(DT.isReachableFromEntry(Inst->getParent()) &&((void)0)
478 "We did a DFS from the block entry!")((void)0);
479 return all_of(Inst->operands(),
480 [&](Value *Op) { return isAvailableAt(Op, Loc, Visited); });
481}
482
483void GuardWideningImpl::makeAvailableAt(Value *V, Instruction *Loc) const {
484 auto *Inst = dyn_cast<Instruction>(V);
485 if (!Inst || DT.dominates(Inst, Loc))
486 return;
487
488 assert(isSafeToSpeculativelyExecute(Inst, Loc, &DT) &&((void)0)
489 !Inst->mayReadFromMemory() && "Should've checked with isAvailableAt!")((void)0);
490
491 for (Value *Op : Inst->operands())
492 makeAvailableAt(Op, Loc);
493
494 Inst->moveBefore(Loc);
495}
496
497bool GuardWideningImpl::widenCondCommon(Value *Cond0, Value *Cond1,
498 Instruction *InsertPt, Value *&Result,
499 bool InvertCondition) {
500 using namespace llvm::PatternMatch;
501
502 {
503 // L >u C0 && L >u C1 -> L >u max(C0, C1)
504 ConstantInt *RHS0, *RHS1;
505 Value *LHS;
506 ICmpInst::Predicate Pred0, Pred1;
507 if (match(Cond0, m_ICmp(Pred0, m_Value(LHS), m_ConstantInt(RHS0))) &&
46
Assuming the condition is false
47
Taking false branch
508 match(Cond1, m_ICmp(Pred1, m_Specific(LHS), m_ConstantInt(RHS1)))) {
509 if (InvertCondition)
510 Pred1 = ICmpInst::getInversePredicate(Pred1);
511
512 ConstantRange CR0 =
513 ConstantRange::makeExactICmpRegion(Pred0, RHS0->getValue());
514 ConstantRange CR1 =
515 ConstantRange::makeExactICmpRegion(Pred1, RHS1->getValue());
516
517 // SubsetIntersect is a subset of the actual mathematical intersection of
518 // CR0 and CR1, while SupersetIntersect is a superset of the actual
519 // mathematical intersection. If these two ConstantRanges are equal, then
520 // we know we were able to represent the actual mathematical intersection
521 // of CR0 and CR1, and can use the same to generate an icmp instruction.
522 //
523 // Given what we're doing here and the semantics of guards, it would
524 // actually be correct to just use SubsetIntersect, but that may be too
525 // aggressive in cases we care about.
526 auto SubsetIntersect = CR0.inverse().unionWith(CR1.inverse()).inverse();
527 auto SupersetIntersect = CR0.intersectWith(CR1);
528
529 APInt NewRHSAP;
530 CmpInst::Predicate Pred;
531 if (SubsetIntersect == SupersetIntersect &&
532 SubsetIntersect.getEquivalentICmp(Pred, NewRHSAP)) {
533 if (InsertPt) {
534 ConstantInt *NewRHS = ConstantInt::get(Cond0->getContext(), NewRHSAP);
535 Result = new ICmpInst(InsertPt, Pred, LHS, NewRHS, "wide.chk");
536 }
537 return true;
538 }
539 }
540 }
541
542 {
543 SmallVector<GuardWideningImpl::RangeCheck, 4> Checks, CombinedChecks;
544 // TODO: Support InvertCondition case?
545 if (!InvertCondition
47.1
'InvertCondition' is false
47.1
'InvertCondition' is false
&&
51
Taking true branch
546 parseRangeChecks(Cond0, Checks) && parseRangeChecks(Cond1, Checks) &&
48
Assuming the condition is true
49
Assuming the condition is true
547 combineRangeChecks(Checks, CombinedChecks)) {
50
Assuming the condition is true
548 if (InsertPt
51.1
'InsertPt' is non-null
51.1
'InsertPt' is non-null
) {
52
Taking true branch
549 Result = nullptr;
53
Null pointer value stored to 'Result'
550 for (auto &RC : CombinedChecks) {
54
Assuming '__begin3' is equal to '__end3'
551 makeAvailableAt(RC.getCheckInst(), InsertPt);
552 if (Result)
553 Result = BinaryOperator::CreateAnd(RC.getCheckInst(), Result, "",
554 InsertPt);
555 else
556 Result = RC.getCheckInst();
557 }
558 assert(Result && "Failed to find result value")((void)0);
559 Result->setName("wide.chk");
55
Called C++ object pointer is null
560 }
561 return true;
562 }
563 }
564
565 // Base case -- just logical-and the two conditions together.
566
567 if (InsertPt) {
568 makeAvailableAt(Cond0, InsertPt);
569 makeAvailableAt(Cond1, InsertPt);
570 if (InvertCondition)
571 Cond1 = BinaryOperator::CreateNot(Cond1, "inverted", InsertPt);
572 Result = BinaryOperator::CreateAnd(Cond0, Cond1, "wide.chk", InsertPt);
573 }
574
575 // We were not able to compute Cond0 AND Cond1 for the price of one.
576 return false;
577}
578
579bool GuardWideningImpl::parseRangeChecks(
580 Value *CheckCond, SmallVectorImpl<GuardWideningImpl::RangeCheck> &Checks,
581 SmallPtrSetImpl<const Value *> &Visited) {
582 if (!Visited.insert(CheckCond).second)
583 return true;
584
585 using namespace llvm::PatternMatch;
586
587 {
588 Value *AndLHS, *AndRHS;
589 if (match(CheckCond, m_And(m_Value(AndLHS), m_Value(AndRHS))))
590 return parseRangeChecks(AndLHS, Checks) &&
591 parseRangeChecks(AndRHS, Checks);
592 }
593
594 auto *IC = dyn_cast<ICmpInst>(CheckCond);
595 if (!IC || !IC->getOperand(0)->getType()->isIntegerTy() ||
596 (IC->getPredicate() != ICmpInst::ICMP_ULT &&
597 IC->getPredicate() != ICmpInst::ICMP_UGT))
598 return false;
599
600 const Value *CmpLHS = IC->getOperand(0), *CmpRHS = IC->getOperand(1);
601 if (IC->getPredicate() == ICmpInst::ICMP_UGT)
602 std::swap(CmpLHS, CmpRHS);
603
604 auto &DL = IC->getModule()->getDataLayout();
605
606 GuardWideningImpl::RangeCheck Check(
607 CmpLHS, cast<ConstantInt>(ConstantInt::getNullValue(CmpRHS->getType())),
608 CmpRHS, IC);
609
610 if (!isKnownNonNegative(Check.getLength(), DL))
611 return false;
612
613 // What we have in \c Check now is a correct interpretation of \p CheckCond.
614 // Try to see if we can move some constant offsets into the \c Offset field.
615
616 bool Changed;
617 auto &Ctx = CheckCond->getContext();
618
619 do {
620 Value *OpLHS;
621 ConstantInt *OpRHS;
622 Changed = false;
623
624#ifndef NDEBUG1
625 auto *BaseInst = dyn_cast<Instruction>(Check.getBase());
626 assert((!BaseInst || DT.isReachableFromEntry(BaseInst->getParent())) &&((void)0)
627 "Unreachable instruction?")((void)0);
628#endif
629
630 if (match(Check.getBase(), m_Add(m_Value(OpLHS), m_ConstantInt(OpRHS)))) {
631 Check.setBase(OpLHS);
632 APInt NewOffset = Check.getOffsetValue() + OpRHS->getValue();
633 Check.setOffset(ConstantInt::get(Ctx, NewOffset));
634 Changed = true;
635 } else if (match(Check.getBase(),
636 m_Or(m_Value(OpLHS), m_ConstantInt(OpRHS)))) {
637 KnownBits Known = computeKnownBits(OpLHS, DL);
638 if ((OpRHS->getValue() & Known.Zero) == OpRHS->getValue()) {
639 Check.setBase(OpLHS);
640 APInt NewOffset = Check.getOffsetValue() + OpRHS->getValue();
641 Check.setOffset(ConstantInt::get(Ctx, NewOffset));
642 Changed = true;
643 }
644 }
645 } while (Changed);
646
647 Checks.push_back(Check);
648 return true;
649}
650
651bool GuardWideningImpl::combineRangeChecks(
652 SmallVectorImpl<GuardWideningImpl::RangeCheck> &Checks,
653 SmallVectorImpl<GuardWideningImpl::RangeCheck> &RangeChecksOut) const {
654 unsigned OldCount = Checks.size();
655 while (!Checks.empty()) {
656 // Pick all of the range checks with a specific base and length, and try to
657 // merge them.
658 const Value *CurrentBase = Checks.front().getBase();
659 const Value *CurrentLength = Checks.front().getLength();
660
661 SmallVector<GuardWideningImpl::RangeCheck, 3> CurrentChecks;
662
663 auto IsCurrentCheck = [&](GuardWideningImpl::RangeCheck &RC) {
664 return RC.getBase() == CurrentBase && RC.getLength() == CurrentLength;
665 };
666
667 copy_if(Checks, std::back_inserter(CurrentChecks), IsCurrentCheck);
668 erase_if(Checks, IsCurrentCheck);
669
670 assert(CurrentChecks.size() != 0 && "We know we have at least one!")((void)0);
671
672 if (CurrentChecks.size() < 3) {
673 llvm::append_range(RangeChecksOut, CurrentChecks);
674 continue;
675 }
676
677 // CurrentChecks.size() will typically be 3 here, but so far there has been
678 // no need to hard-code that fact.
679
680 llvm::sort(CurrentChecks, [&](const GuardWideningImpl::RangeCheck &LHS,
681 const GuardWideningImpl::RangeCheck &RHS) {
682 return LHS.getOffsetValue().slt(RHS.getOffsetValue());
683 });
684
685 // Note: std::sort should not invalidate the ChecksStart iterator.
686
687 const ConstantInt *MinOffset = CurrentChecks.front().getOffset();
688 const ConstantInt *MaxOffset = CurrentChecks.back().getOffset();
689
690 unsigned BitWidth = MaxOffset->getValue().getBitWidth();
691 if ((MaxOffset->getValue() - MinOffset->getValue())
692 .ugt(APInt::getSignedMinValue(BitWidth)))
693 return false;
694
695 APInt MaxDiff = MaxOffset->getValue() - MinOffset->getValue();
696 const APInt &HighOffset = MaxOffset->getValue();
697 auto OffsetOK = [&](const GuardWideningImpl::RangeCheck &RC) {
698 return (HighOffset - RC.getOffsetValue()).ult(MaxDiff);
699 };
700
701 if (MaxDiff.isMinValue() || !all_of(drop_begin(CurrentChecks), OffsetOK))
702 return false;
703
704 // We have a series of f+1 checks as:
705 //
706 // I+k_0 u< L ... Chk_0
707 // I+k_1 u< L ... Chk_1
708 // ...
709 // I+k_f u< L ... Chk_f
710 //
711 // with forall i in [0,f]: k_f-k_i u< k_f-k_0 ... Precond_0
712 // k_f-k_0 u< INT_MIN+k_f ... Precond_1
713 // k_f != k_0 ... Precond_2
714 //
715 // Claim:
716 // Chk_0 AND Chk_f implies all the other checks
717 //
718 // Informal proof sketch:
719 //
720 // We will show that the integer range [I+k_0,I+k_f] does not unsigned-wrap
721 // (i.e. going from I+k_0 to I+k_f does not cross the -1,0 boundary) and
722 // thus I+k_f is the greatest unsigned value in that range.
723 //
724 // This combined with Ckh_(f+1) shows that everything in that range is u< L.
725 // Via Precond_0 we know that all of the indices in Chk_0 through Chk_(f+1)
726 // lie in [I+k_0,I+k_f], this proving our claim.
727 //
728 // To see that [I+k_0,I+k_f] is not a wrapping range, note that there are
729 // two possibilities: I+k_0 u< I+k_f or I+k_0 >u I+k_f (they can't be equal
730 // since k_0 != k_f). In the former case, [I+k_0,I+k_f] is not a wrapping
731 // range by definition, and the latter case is impossible:
732 //
733 // 0-----I+k_f---I+k_0----L---INT_MAX,INT_MIN------------------(-1)
734 // xxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
735 //
736 // For Chk_0 to succeed, we'd have to have k_f-k_0 (the range highlighted
737 // with 'x' above) to be at least >u INT_MIN.
738
739 RangeChecksOut.emplace_back(CurrentChecks.front());
740 RangeChecksOut.emplace_back(CurrentChecks.back());
741 }
742
743 assert(RangeChecksOut.size() <= OldCount && "We pessimized!")((void)0);
744 return RangeChecksOut.size() != OldCount;
745}
746
747#ifndef NDEBUG1
748StringRef GuardWideningImpl::scoreTypeToString(WideningScore WS) {
749 switch (WS) {
750 case WS_IllegalOrNegative:
751 return "IllegalOrNegative";
752 case WS_Neutral:
753 return "Neutral";
754 case WS_Positive:
755 return "Positive";
756 case WS_VeryPositive:
757 return "VeryPositive";
758 }
759
760 llvm_unreachable("Fully covered switch above!")__builtin_unreachable();
761}
762#endif
763
764PreservedAnalyses GuardWideningPass::run(Function &F,
765 FunctionAnalysisManager &AM) {
766 auto &DT = AM.getResult<DominatorTreeAnalysis>(F);
767 auto &LI = AM.getResult<LoopAnalysis>(F);
768 auto &PDT = AM.getResult<PostDominatorTreeAnalysis>(F);
769 if (!GuardWideningImpl(DT, &PDT, LI, DT.getRootNode(),
770 [](BasicBlock*) { return true; } ).run())
771 return PreservedAnalyses::all();
772
773 PreservedAnalyses PA;
774 PA.preserveSet<CFGAnalyses>();
775 return PA;
776}
777
778PreservedAnalyses GuardWideningPass::run(Loop &L, LoopAnalysisManager &AM,
779 LoopStandardAnalysisResults &AR,
780 LPMUpdater &U) {
781 BasicBlock *RootBB = L.getLoopPredecessor();
782 if (!RootBB)
783 RootBB = L.getHeader();
784 auto BlockFilter = [&](BasicBlock *BB) {
785 return BB == RootBB || L.contains(BB);
786 };
787 if (!GuardWideningImpl(AR.DT, nullptr, AR.LI, AR.DT.getNode(RootBB),
788 BlockFilter).run())
789 return PreservedAnalyses::all();
790
791 return getLoopPassPreservedAnalyses();
792}
793
794namespace {
795struct GuardWideningLegacyPass : public FunctionPass {
796 static char ID;
797
798 GuardWideningLegacyPass() : FunctionPass(ID) {
799 initializeGuardWideningLegacyPassPass(*PassRegistry::getPassRegistry());
800 }
801
802 bool runOnFunction(Function &F) override {
803 if (skipFunction(F))
804 return false;
805 auto &DT = getAnalysis<DominatorTreeWrapperPass>().getDomTree();
806 auto &LI = getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
807 auto &PDT = getAnalysis<PostDominatorTreeWrapperPass>().getPostDomTree();
808 return GuardWideningImpl(DT, &PDT, LI, DT.getRootNode(),
809 [](BasicBlock*) { return true; } ).run();
810 }
811
812 void getAnalysisUsage(AnalysisUsage &AU) const override {
813 AU.setPreservesCFG();
814 AU.addRequired<DominatorTreeWrapperPass>();
815 AU.addRequired<PostDominatorTreeWrapperPass>();
816 AU.addRequired<LoopInfoWrapperPass>();
817 }
818};
819
820/// Same as above, but restricted to a single loop at a time. Can be
821/// scheduled with other loop passes w/o breaking out of LPM
822struct LoopGuardWideningLegacyPass : public LoopPass {
823 static char ID;
824
825 LoopGuardWideningLegacyPass() : LoopPass(ID) {
826 initializeLoopGuardWideningLegacyPassPass(*PassRegistry::getPassRegistry());
827 }
828
829 bool runOnLoop(Loop *L, LPPassManager &LPM) override {
830 if (skipLoop(L))
1
Assuming the condition is false
2
Taking false branch
831 return false;
832 auto &DT = getAnalysis<DominatorTreeWrapperPass>().getDomTree();
833 auto &LI = getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
834 auto *PDTWP = getAnalysisIfAvailable<PostDominatorTreeWrapperPass>();
835 auto *PDT = PDTWP
2.1
'PDTWP' is null
2.1
'PDTWP' is null
? &PDTWP->getPostDomTree() : nullptr;
3
'?' condition is false
836 BasicBlock *RootBB = L->getLoopPredecessor();
837 if (!RootBB)
4
Assuming 'RootBB' is non-null
5
Taking false branch
838 RootBB = L->getHeader();
839 auto BlockFilter = [&](BasicBlock *BB) {
840 return BB == RootBB || L->contains(BB);
841 };
842 return GuardWideningImpl(DT, PDT, LI,
6
Calling 'GuardWideningImpl::run'
843 DT.getNode(RootBB), BlockFilter).run();
844 }
845
846 void getAnalysisUsage(AnalysisUsage &AU) const override {
847 AU.setPreservesCFG();
848 getLoopAnalysisUsage(AU);
849 AU.addPreserved<PostDominatorTreeWrapperPass>();
850 }
851};
852}
853
854char GuardWideningLegacyPass::ID = 0;
855char LoopGuardWideningLegacyPass::ID = 0;
856
857INITIALIZE_PASS_BEGIN(GuardWideningLegacyPass, "guard-widening", "Widen guards",static void *initializeGuardWideningLegacyPassPassOnce(PassRegistry
&Registry) {
858 false, false)static void *initializeGuardWideningLegacyPassPassOnce(PassRegistry
&Registry) {
859INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)initializeDominatorTreeWrapperPassPass(Registry);
860INITIALIZE_PASS_DEPENDENCY(PostDominatorTreeWrapperPass)initializePostDominatorTreeWrapperPassPass(Registry);
861INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass)initializeLoopInfoWrapperPassPass(Registry);
862INITIALIZE_PASS_END(GuardWideningLegacyPass, "guard-widening", "Widen guards",PassInfo *PI = new PassInfo( "Widen guards", "guard-widening"
, &GuardWideningLegacyPass::ID, PassInfo::NormalCtor_t(callDefaultCtor
<GuardWideningLegacyPass>), false, false); Registry.registerPass
(*PI, true); return PI; } static llvm::once_flag InitializeGuardWideningLegacyPassPassFlag
; void llvm::initializeGuardWideningLegacyPassPass(PassRegistry
&Registry) { llvm::call_once(InitializeGuardWideningLegacyPassPassFlag
, initializeGuardWideningLegacyPassPassOnce, std::ref(Registry
)); }
863 false, false)PassInfo *PI = new PassInfo( "Widen guards", "guard-widening"
, &GuardWideningLegacyPass::ID, PassInfo::NormalCtor_t(callDefaultCtor
<GuardWideningLegacyPass>), false, false); Registry.registerPass
(*PI, true); return PI; } static llvm::once_flag InitializeGuardWideningLegacyPassPassFlag
; void llvm::initializeGuardWideningLegacyPassPass(PassRegistry
&Registry) { llvm::call_once(InitializeGuardWideningLegacyPassPassFlag
, initializeGuardWideningLegacyPassPassOnce, std::ref(Registry
)); }
864
865INITIALIZE_PASS_BEGIN(LoopGuardWideningLegacyPass, "loop-guard-widening",static void *initializeLoopGuardWideningLegacyPassPassOnce(PassRegistry
&Registry) {
866 "Widen guards (within a single loop, as a loop pass)",static void *initializeLoopGuardWideningLegacyPassPassOnce(PassRegistry
&Registry) {
867 false, false)static void *initializeLoopGuardWideningLegacyPassPassOnce(PassRegistry
&Registry) {
868INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)initializeDominatorTreeWrapperPassPass(Registry);
869INITIALIZE_PASS_DEPENDENCY(PostDominatorTreeWrapperPass)initializePostDominatorTreeWrapperPassPass(Registry);
870INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass)initializeLoopInfoWrapperPassPass(Registry);
871INITIALIZE_PASS_END(LoopGuardWideningLegacyPass, "loop-guard-widening",PassInfo *PI = new PassInfo( "Widen guards (within a single loop, as a loop pass)"
, "loop-guard-widening", &LoopGuardWideningLegacyPass::ID
, PassInfo::NormalCtor_t(callDefaultCtor<LoopGuardWideningLegacyPass
>), false, false); Registry.registerPass(*PI, true); return
PI; } static llvm::once_flag InitializeLoopGuardWideningLegacyPassPassFlag
; void llvm::initializeLoopGuardWideningLegacyPassPass(PassRegistry
&Registry) { llvm::call_once(InitializeLoopGuardWideningLegacyPassPassFlag
, initializeLoopGuardWideningLegacyPassPassOnce, std::ref(Registry
)); }
872 "Widen guards (within a single loop, as a loop pass)",PassInfo *PI = new PassInfo( "Widen guards (within a single loop, as a loop pass)"
, "loop-guard-widening", &LoopGuardWideningLegacyPass::ID
, PassInfo::NormalCtor_t(callDefaultCtor<LoopGuardWideningLegacyPass
>), false, false); Registry.registerPass(*PI, true); return
PI; } static llvm::once_flag InitializeLoopGuardWideningLegacyPassPassFlag
; void llvm::initializeLoopGuardWideningLegacyPassPass(PassRegistry
&Registry) { llvm::call_once(InitializeLoopGuardWideningLegacyPassPassFlag
, initializeLoopGuardWideningLegacyPassPassOnce, std::ref(Registry
)); }
873 false, false)PassInfo *PI = new PassInfo( "Widen guards (within a single loop, as a loop pass)"
, "loop-guard-widening", &LoopGuardWideningLegacyPass::ID
, PassInfo::NormalCtor_t(callDefaultCtor<LoopGuardWideningLegacyPass
>), false, false); Registry.registerPass(*PI, true); return
PI; } static llvm::once_flag InitializeLoopGuardWideningLegacyPassPassFlag
; void llvm::initializeLoopGuardWideningLegacyPassPass(PassRegistry
&Registry) { llvm::call_once(InitializeLoopGuardWideningLegacyPassPassFlag
, initializeLoopGuardWideningLegacyPassPassOnce, std::ref(Registry
)); }
874
875FunctionPass *llvm::createGuardWideningPass() {
876 return new GuardWideningLegacyPass();
877}
878
879Pass *llvm::createLoopGuardWideningPass() {
880 return new LoopGuardWideningLegacyPass();
881}

/usr/include/c++/v1/__functional/function.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___FUNCTIONAL_FUNCTION_H
11#define _LIBCPP___FUNCTIONAL_FUNCTION_H
12
13#include <__config>
14#include <__functional/binary_function.h>
15#include <__functional/invoke.h>
16#include <__functional/unary_function.h>
17#include <__iterator/iterator_traits.h>
18#include <__memory/allocator_traits.h>
19#include <__memory/compressed_pair.h>
20#include <__memory/shared_ptr.h>
21#include <exception>
22#include <memory> // TODO: replace with <__memory/__builtin_new_allocator.h>
23#include <type_traits>
24#include <utility>
25
26#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
27#pragma GCC system_header
28#endif
29
30_LIBCPP_BEGIN_NAMESPACE_STDnamespace std { inline namespace __1 {
31
32// bad_function_call
33
34class _LIBCPP_EXCEPTION_ABI__attribute__ ((__visibility__("default"))) bad_function_call
35 : public exception
36{
37#ifdef _LIBCPP_ABI_BAD_FUNCTION_CALL_KEY_FUNCTION
38public:
39 virtual ~bad_function_call() _NOEXCEPTnoexcept;
40
41 virtual const char* what() const _NOEXCEPTnoexcept;
42#endif
43};
44
45_LIBCPP_NORETURN[[noreturn]] inline _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
46void __throw_bad_function_call()
47{
48#ifndef _LIBCPP_NO_EXCEPTIONS
49 throw bad_function_call();
50#else
51 _VSTDstd::__1::abort();
52#endif
53}
54
55#if defined(_LIBCPP_CXX03_LANG) && !defined(_LIBCPP_DISABLE_DEPRECATION_WARNINGS) && __has_attribute(deprecated)1
56# define _LIBCPP_DEPRECATED_CXX03_FUNCTION \
57 __attribute__((deprecated("Using std::function in C++03 is not supported anymore. Please upgrade to C++11 or later, or use a different type")))
58#else
59# define _LIBCPP_DEPRECATED_CXX03_FUNCTION /* nothing */
60#endif
61
62template<class _Fp> class _LIBCPP_DEPRECATED_CXX03_FUNCTION _LIBCPP_TEMPLATE_VIS__attribute__ ((__type_visibility__("default"))) function; // undefined
63
64namespace __function
65{
66
67template<class _Rp>
68struct __maybe_derive_from_unary_function
69{
70};
71
72template<class _Rp, class _A1>
73struct __maybe_derive_from_unary_function<_Rp(_A1)>
74 : public unary_function<_A1, _Rp>
75{
76};
77
78template<class _Rp>
79struct __maybe_derive_from_binary_function
80{
81};
82
83template<class _Rp, class _A1, class _A2>
84struct __maybe_derive_from_binary_function<_Rp(_A1, _A2)>
85 : public binary_function<_A1, _A2, _Rp>
86{
87};
88
89template <class _Fp>
90_LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
91bool __not_null(_Fp const&) { return true; }
92
93template <class _Fp>
94_LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
95bool __not_null(_Fp* __ptr) { return __ptr; }
96
97template <class _Ret, class _Class>
98_LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
99bool __not_null(_Ret _Class::*__ptr) { return __ptr; }
100
101template <class _Fp>
102_LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
103bool __not_null(function<_Fp> const& __f) { return !!__f; }
104
105#ifdef _LIBCPP_HAS_EXTENSION_BLOCKS
106template <class _Rp, class ..._Args>
107_LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
108bool __not_null(_Rp (^__p)(_Args...)) { return __p; }
109#endif
110
111} // namespace __function
112
113#ifndef _LIBCPP_CXX03_LANG
114
115namespace __function {
116
117// __alloc_func holds a functor and an allocator.
118
119template <class _Fp, class _Ap, class _FB> class __alloc_func;
120template <class _Fp, class _FB>
121class __default_alloc_func;
122
123template <class _Fp, class _Ap, class _Rp, class... _ArgTypes>
124class __alloc_func<_Fp, _Ap, _Rp(_ArgTypes...)>
125{
126 __compressed_pair<_Fp, _Ap> __f_;
127
128 public:
129 typedef _LIBCPP_NODEBUG_TYPE__attribute__((nodebug)) _Fp _Target;
130 typedef _LIBCPP_NODEBUG_TYPE__attribute__((nodebug)) _Ap _Alloc;
131
132 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
133 const _Target& __target() const { return __f_.first(); }
134
135 // WIN32 APIs may define __allocator, so use __get_allocator instead.
136 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
137 const _Alloc& __get_allocator() const { return __f_.second(); }
138
139 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
140 explicit __alloc_func(_Target&& __f)
141 : __f_(piecewise_construct, _VSTDstd::__1::forward_as_tuple(_VSTDstd::__1::move(__f)),
142 _VSTDstd::__1::forward_as_tuple())
143 {
144 }
145
146 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
147 explicit __alloc_func(const _Target& __f, const _Alloc& __a)
148 : __f_(piecewise_construct, _VSTDstd::__1::forward_as_tuple(__f),
149 _VSTDstd::__1::forward_as_tuple(__a))
150 {
151 }
152
153 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
154 explicit __alloc_func(const _Target& __f, _Alloc&& __a)
155 : __f_(piecewise_construct, _VSTDstd::__1::forward_as_tuple(__f),
156 _VSTDstd::__1::forward_as_tuple(_VSTDstd::__1::move(__a)))
157 {
158 }
159
160 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
161 explicit __alloc_func(_Target&& __f, _Alloc&& __a)
162 : __f_(piecewise_construct, _VSTDstd::__1::forward_as_tuple(_VSTDstd::__1::move(__f)),
163 _VSTDstd::__1::forward_as_tuple(_VSTDstd::__1::move(__a)))
164 {
165 }
166
167 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
168 _Rp operator()(_ArgTypes&&... __arg)
169 {
170 typedef __invoke_void_return_wrapper<_Rp> _Invoker;
171 return _Invoker::__call(__f_.first(),
172 _VSTDstd::__1::forward<_ArgTypes>(__arg)...);
173 }
174
175 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
176 __alloc_func* __clone() const
177 {
178 typedef allocator_traits<_Alloc> __alloc_traits;
179 typedef
180 typename __rebind_alloc_helper<__alloc_traits, __alloc_func>::type
181 _AA;
182 _AA __a(__f_.second());
183 typedef __allocator_destructor<_AA> _Dp;
184 unique_ptr<__alloc_func, _Dp> __hold(__a.allocate(1), _Dp(__a, 1));
185 ::new ((void*)__hold.get()) __alloc_func(__f_.first(), _Alloc(__a));
186 return __hold.release();
187 }
188
189 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
190 void destroy() _NOEXCEPTnoexcept { __f_.~__compressed_pair<_Target, _Alloc>(); }
191
192 static void __destroy_and_delete(__alloc_func* __f) {
193 typedef allocator_traits<_Alloc> __alloc_traits;
194 typedef typename __rebind_alloc_helper<__alloc_traits, __alloc_func>::type
195 _FunAlloc;
196 _FunAlloc __a(__f->__get_allocator());
197 __f->destroy();
198 __a.deallocate(__f, 1);
199 }
200};
201
202template <class _Fp, class _Rp, class... _ArgTypes>
203class __default_alloc_func<_Fp, _Rp(_ArgTypes...)> {
204 _Fp __f_;
205
206public:
207 typedef _LIBCPP_NODEBUG_TYPE__attribute__((nodebug)) _Fp _Target;
208
209 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
210 const _Target& __target() const { return __f_; }
211
212 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
213 explicit __default_alloc_func(_Target&& __f) : __f_(_VSTDstd::__1::move(__f)) {}
214
215 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
216 explicit __default_alloc_func(const _Target& __f) : __f_(__f) {}
217
218 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
219 _Rp operator()(_ArgTypes&&... __arg) {
220 typedef __invoke_void_return_wrapper<_Rp> _Invoker;
221 return _Invoker::__call(__f_, _VSTDstd::__1::forward<_ArgTypes>(__arg)...);
222 }
223
224 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
225 __default_alloc_func* __clone() const {
226 __builtin_new_allocator::__holder_t __hold =
227 __builtin_new_allocator::__allocate_type<__default_alloc_func>(1);
228 __default_alloc_func* __res =
229 ::new ((void*)__hold.get()) __default_alloc_func(__f_);
230 (void)__hold.release();
231 return __res;
232 }
233
234 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
235 void destroy() _NOEXCEPTnoexcept { __f_.~_Target(); }
236
237 static void __destroy_and_delete(__default_alloc_func* __f) {
238 __f->destroy();
239 __builtin_new_allocator::__deallocate_type<__default_alloc_func>(__f, 1);
240 }
241};
242
243// __base provides an abstract interface for copyable functors.
244
245template<class _Fp> class _LIBCPP_TEMPLATE_VIS__attribute__ ((__type_visibility__("default"))) __base;
246
247template<class _Rp, class ..._ArgTypes>
248class __base<_Rp(_ArgTypes...)>
249{
250 __base(const __base&);
251 __base& operator=(const __base&);
252public:
253 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
__base() {}
254 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
virtual ~__base() {}
255 virtual __base* __clone() const = 0;
256 virtual void __clone(__base*) const = 0;
257 virtual void destroy() _NOEXCEPTnoexcept = 0;
258 virtual void destroy_deallocate() _NOEXCEPTnoexcept = 0;
259 virtual _Rp operator()(_ArgTypes&& ...) = 0;
260#ifndef _LIBCPP_NO_RTTI
261 virtual const void* target(const type_info&) const _NOEXCEPTnoexcept = 0;
262 virtual const std::type_info& target_type() const _NOEXCEPTnoexcept = 0;
263#endif // _LIBCPP_NO_RTTI
264};
265
266// __func implements __base for a given functor type.
267
268template<class _FD, class _Alloc, class _FB> class __func;
269
270template<class _Fp, class _Alloc, class _Rp, class ..._ArgTypes>
271class __func<_Fp, _Alloc, _Rp(_ArgTypes...)>
272 : public __base<_Rp(_ArgTypes...)>
273{
274 __alloc_func<_Fp, _Alloc, _Rp(_ArgTypes...)> __f_;
275public:
276 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
277 explicit __func(_Fp&& __f)
278 : __f_(_VSTDstd::__1::move(__f)) {}
279
280 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
281 explicit __func(const _Fp& __f, const _Alloc& __a)
282 : __f_(__f, __a) {}
283
284 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
285 explicit __func(const _Fp& __f, _Alloc&& __a)
286 : __f_(__f, _VSTDstd::__1::move(__a)) {}
287
288 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
289 explicit __func(_Fp&& __f, _Alloc&& __a)
290 : __f_(_VSTDstd::__1::move(__f), _VSTDstd::__1::move(__a)) {}
291
292 virtual __base<_Rp(_ArgTypes...)>* __clone() const;
293 virtual void __clone(__base<_Rp(_ArgTypes...)>*) const;
294 virtual void destroy() _NOEXCEPTnoexcept;
295 virtual void destroy_deallocate() _NOEXCEPTnoexcept;
296 virtual _Rp operator()(_ArgTypes&&... __arg);
297#ifndef _LIBCPP_NO_RTTI
298 virtual const void* target(const type_info&) const _NOEXCEPTnoexcept;
299 virtual const std::type_info& target_type() const _NOEXCEPTnoexcept;
300#endif // _LIBCPP_NO_RTTI
301};
302
303template<class _Fp, class _Alloc, class _Rp, class ..._ArgTypes>
304__base<_Rp(_ArgTypes...)>*
305__func<_Fp, _Alloc, _Rp(_ArgTypes...)>::__clone() const
306{
307 typedef allocator_traits<_Alloc> __alloc_traits;
308 typedef typename __rebind_alloc_helper<__alloc_traits, __func>::type _Ap;
309 _Ap __a(__f_.__get_allocator());
310 typedef __allocator_destructor<_Ap> _Dp;
311 unique_ptr<__func, _Dp> __hold(__a.allocate(1), _Dp(__a, 1));
312 ::new ((void*)__hold.get()) __func(__f_.__target(), _Alloc(__a));
313 return __hold.release();
314}
315
316template<class _Fp, class _Alloc, class _Rp, class ..._ArgTypes>
317void
318__func<_Fp, _Alloc, _Rp(_ArgTypes...)>::__clone(__base<_Rp(_ArgTypes...)>* __p) const
319{
320 ::new ((void*)__p) __func(__f_.__target(), __f_.__get_allocator());
321}
322
323template<class _Fp, class _Alloc, class _Rp, class ..._ArgTypes>
324void
325__func<_Fp, _Alloc, _Rp(_ArgTypes...)>::destroy() _NOEXCEPTnoexcept
326{
327 __f_.destroy();
328}
329
330template<class _Fp, class _Alloc, class _Rp, class ..._ArgTypes>
331void
332__func<_Fp, _Alloc, _Rp(_ArgTypes...)>::destroy_deallocate() _NOEXCEPTnoexcept
333{
334 typedef allocator_traits<_Alloc> __alloc_traits;
335 typedef typename __rebind_alloc_helper<__alloc_traits, __func>::type _Ap;
336 _Ap __a(__f_.__get_allocator());
337 __f_.destroy();
338 __a.deallocate(this, 1);
339}
340
341template<class _Fp, class _Alloc, class _Rp, class ..._ArgTypes>
342_Rp
343__func<_Fp, _Alloc, _Rp(_ArgTypes...)>::operator()(_ArgTypes&& ... __arg)
344{
345 return __f_(_VSTDstd::__1::forward<_ArgTypes>(__arg)...);
346}
347
348#ifndef _LIBCPP_NO_RTTI
349
350template<class _Fp, class _Alloc, class _Rp, class ..._ArgTypes>
351const void*
352__func<_Fp, _Alloc, _Rp(_ArgTypes...)>::target(const type_info& __ti) const _NOEXCEPTnoexcept
353{
354 if (__ti == typeid(_Fp))
355 return &__f_.__target();
356 return nullptr;
357}
358
359template<class _Fp, class _Alloc, class _Rp, class ..._ArgTypes>
360const std::type_info&
361__func<_Fp, _Alloc, _Rp(_ArgTypes...)>::target_type() const _NOEXCEPTnoexcept
362{
363 return typeid(_Fp);
364}
365
366#endif // _LIBCPP_NO_RTTI
367
368// __value_func creates a value-type from a __func.
369
370template <class _Fp> class __value_func;
371
372template <class _Rp, class... _ArgTypes> class __value_func<_Rp(_ArgTypes...)>
373{
374 typename aligned_storage<3 * sizeof(void*)>::type __buf_;
375
376 typedef __base<_Rp(_ArgTypes...)> __func;
377 __func* __f_;
378
379 _LIBCPP_NO_CFI__attribute__((__no_sanitize__("cfi"))) static __func* __as_base(void* p)
380 {
381 return reinterpret_cast<__func*>(p);
382 }
383
384 public:
385 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
386 __value_func() _NOEXCEPTnoexcept : __f_(nullptr) {}
387
388 template <class _Fp, class _Alloc>
389 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
__value_func(_Fp&& __f, const _Alloc& __a)
390 : __f_(nullptr)
391 {
392 typedef allocator_traits<_Alloc> __alloc_traits;
393 typedef __function::__func<_Fp, _Alloc, _Rp(_ArgTypes...)> _Fun;
394 typedef typename __rebind_alloc_helper<__alloc_traits, _Fun>::type
395 _FunAlloc;
396
397 if (__function::__not_null(__f))
398 {
399 _FunAlloc __af(__a);
400 if (sizeof(_Fun) <= sizeof(__buf_) &&
401 is_nothrow_copy_constructible<_Fp>::value &&
402 is_nothrow_copy_constructible<_FunAlloc>::value)
403 {
404 __f_ =
405 ::new ((void*)&__buf_) _Fun(_VSTDstd::__1::move(__f), _Alloc(__af));
406 }
407 else
408 {
409 typedef __allocator_destructor<_FunAlloc> _Dp;
410 unique_ptr<__func, _Dp> __hold(__af.allocate(1), _Dp(__af, 1));
411 ::new ((void*)__hold.get()) _Fun(_VSTDstd::__1::move(__f), _Alloc(__a));
412 __f_ = __hold.release();
413 }
414 }
415 }
416
417 template <class _Fp,
418 class = typename enable_if<!is_same<typename decay<_Fp>::type, __value_func>::value>::type>
419 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
explicit __value_func(_Fp&& __f)
420 : __value_func(_VSTDstd::__1::forward<_Fp>(__f), allocator<_Fp>()) {}
421
422 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
423 __value_func(const __value_func& __f)
424 {
425 if (__f.__f_ == nullptr)
426 __f_ = nullptr;
427 else if ((void*)__f.__f_ == &__f.__buf_)
428 {
429 __f_ = __as_base(&__buf_);
430 __f.__f_->__clone(__f_);
431 }
432 else
433 __f_ = __f.__f_->__clone();
434 }
435
436 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
437 __value_func(__value_func&& __f) _NOEXCEPTnoexcept
438 {
439 if (__f.__f_ == nullptr)
440 __f_ = nullptr;
441 else if ((void*)__f.__f_ == &__f.__buf_)
442 {
443 __f_ = __as_base(&__buf_);
444 __f.__f_->__clone(__f_);
445 }
446 else
447 {
448 __f_ = __f.__f_;
449 __f.__f_ = nullptr;
450 }
451 }
452
453 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
454 ~__value_func()
455 {
456 if ((void*)__f_ == &__buf_)
457 __f_->destroy();
458 else if (__f_)
459 __f_->destroy_deallocate();
460 }
461
462 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
463 __value_func& operator=(__value_func&& __f)
464 {
465 *this = nullptr;
466 if (__f.__f_ == nullptr)
467 __f_ = nullptr;
468 else if ((void*)__f.__f_ == &__f.__buf_)
469 {
470 __f_ = __as_base(&__buf_);
471 __f.__f_->__clone(__f_);
472 }
473 else
474 {
475 __f_ = __f.__f_;
476 __f.__f_ = nullptr;
477 }
478 return *this;
479 }
480
481 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
482 __value_func& operator=(nullptr_t)
483 {
484 __func* __f = __f_;
485 __f_ = nullptr;
486 if ((void*)__f == &__buf_)
487 __f->destroy();
488 else if (__f)
489 __f->destroy_deallocate();
490 return *this;
491 }
492
493 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
494 _Rp operator()(_ArgTypes&&... __args) const
495 {
496 if (__f_ == nullptr)
10
Assuming the condition is false
11
Taking false branch
26
Taking false branch
497 __throw_bad_function_call();
498 return (*__f_)(_VSTDstd::__1::forward<_ArgTypes>(__args)...);
12
Returning value, which participates in a condition later
27
Returning value, which participates in a condition later
499 }
500
501 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
502 void swap(__value_func& __f) _NOEXCEPTnoexcept
503 {
504 if (&__f == this)
505 return;
506 if ((void*)__f_ == &__buf_ && (void*)__f.__f_ == &__f.__buf_)
507 {
508 typename aligned_storage<sizeof(__buf_)>::type __tempbuf;
509 __func* __t = __as_base(&__tempbuf);
510 __f_->__clone(__t);
511 __f_->destroy();
512 __f_ = nullptr;
513 __f.__f_->__clone(__as_base(&__buf_));
514 __f.__f_->destroy();
515 __f.__f_ = nullptr;
516 __f_ = __as_base(&__buf_);
517 __t->__clone(__as_base(&__f.__buf_));
518 __t->destroy();
519 __f.__f_ = __as_base(&__f.__buf_);
520 }
521 else if ((void*)__f_ == &__buf_)
522 {
523 __f_->__clone(__as_base(&__f.__buf_));
524 __f_->destroy();
525 __f_ = __f.__f_;
526 __f.__f_ = __as_base(&__f.__buf_);
527 }
528 else if ((void*)__f.__f_ == &__f.__buf_)
529 {
530 __f.__f_->__clone(__as_base(&__buf_));
531 __f.__f_->destroy();
532 __f.__f_ = __f_;
533 __f_ = __as_base(&__buf_);
534 }
535 else
536 _VSTDstd::__1::swap(__f_, __f.__f_);
537 }
538
539 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
540 explicit operator bool() const _NOEXCEPTnoexcept { return __f_ != nullptr; }
541
542#ifndef _LIBCPP_NO_RTTI
543 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
544 const std::type_info& target_type() const _NOEXCEPTnoexcept
545 {
546 if (__f_ == nullptr)
547 return typeid(void);
548 return __f_->target_type();
549 }
550
551 template <typename _Tp>
552 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
const _Tp* target() const _NOEXCEPTnoexcept
553 {
554 if (__f_ == nullptr)
555 return nullptr;
556 return (const _Tp*)__f_->target(typeid(_Tp));
557 }
558#endif // _LIBCPP_NO_RTTI
559};
560
561// Storage for a functor object, to be used with __policy to manage copy and
562// destruction.
563union __policy_storage
564{
565 mutable char __small[sizeof(void*) * 2];
566 void* __large;
567};
568
569// True if _Fun can safely be held in __policy_storage.__small.
570template <typename _Fun>
571struct __use_small_storage
572 : public integral_constant<
573 bool, sizeof(_Fun) <= sizeof(__policy_storage) &&
574 _LIBCPP_ALIGNOF(_Fun)alignof(_Fun) <= _LIBCPP_ALIGNOF(__policy_storage)alignof(__policy_storage) &&
575 is_trivially_copy_constructible<_Fun>::value &&
576 is_trivially_destructible<_Fun>::value> {};
577
578// Policy contains information about how to copy, destroy, and move the
579// underlying functor. You can think of it as a vtable of sorts.
580struct __policy
581{
582 // Used to copy or destroy __large values. null for trivial objects.
583 void* (*const __clone)(const void*);
584 void (*const __destroy)(void*);
585
586 // True if this is the null policy (no value).
587 const bool __is_null;
588
589 // The target type. May be null if RTTI is disabled.
590 const std::type_info* const __type_info;
591
592 // Returns a pointer to a static policy object suitable for the functor
593 // type.
594 template <typename _Fun>
595 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
static const __policy* __create()
596 {
597 return __choose_policy<_Fun>(__use_small_storage<_Fun>());
598 }
599
600 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
601 static const __policy* __create_empty()
602 {
603 static const _LIBCPP_CONSTEXPRconstexpr __policy __policy_ = {nullptr, nullptr,
604 true,
605#ifndef _LIBCPP_NO_RTTI
606 &typeid(void)
607#else
608 nullptr
609#endif
610 };
611 return &__policy_;
612 }
613
614 private:
615 template <typename _Fun> static void* __large_clone(const void* __s)
616 {
617 const _Fun* __f = static_cast<const _Fun*>(__s);
618 return __f->__clone();
619 }
620
621 template <typename _Fun>
622 static void __large_destroy(void* __s) {
623 _Fun::__destroy_and_delete(static_cast<_Fun*>(__s));
624 }
625
626 template <typename _Fun>
627 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
static const __policy*
628 __choose_policy(/* is_small = */ false_type) {
629 static const _LIBCPP_CONSTEXPRconstexpr __policy __policy_ = {
630 &__large_clone<_Fun>, &__large_destroy<_Fun>, false,
631#ifndef _LIBCPP_NO_RTTI
632 &typeid(typename _Fun::_Target)
633#else
634 nullptr
635#endif
636 };
637 return &__policy_;
638 }
639
640 template <typename _Fun>
641 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
static const __policy*
642 __choose_policy(/* is_small = */ true_type)
643 {
644 static const _LIBCPP_CONSTEXPRconstexpr __policy __policy_ = {
645 nullptr, nullptr, false,
646#ifndef _LIBCPP_NO_RTTI
647 &typeid(typename _Fun::_Target)
648#else
649 nullptr
650#endif
651 };
652 return &__policy_;
653 }
654};
655
656// Used to choose between perfect forwarding or pass-by-value. Pass-by-value is
657// faster for types that can be passed in registers.
658template <typename _Tp>
659using __fast_forward =
660 typename conditional<is_scalar<_Tp>::value, _Tp, _Tp&&>::type;
661
662// __policy_invoker calls an instance of __alloc_func held in __policy_storage.
663
664template <class _Fp> struct __policy_invoker;
665
666template <class _Rp, class... _ArgTypes>
667struct __policy_invoker<_Rp(_ArgTypes...)>
668{
669 typedef _Rp (*__Call)(const __policy_storage*,
670 __fast_forward<_ArgTypes>...);
671
672 __Call __call_;
673
674 // Creates an invoker that throws bad_function_call.
675 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
676 __policy_invoker() : __call_(&__call_empty) {}
677
678 // Creates an invoker that calls the given instance of __func.
679 template <typename _Fun>
680 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
static __policy_invoker __create()
681 {
682 return __policy_invoker(&__call_impl<_Fun>);
683 }
684
685 private:
686 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
687 explicit __policy_invoker(__Call __c) : __call_(__c) {}
688
689 static _Rp __call_empty(const __policy_storage*,
690 __fast_forward<_ArgTypes>...)
691 {
692 __throw_bad_function_call();
693 }
694
695 template <typename _Fun>
696 static _Rp __call_impl(const __policy_storage* __buf,
697 __fast_forward<_ArgTypes>... __args)
698 {
699 _Fun* __f = reinterpret_cast<_Fun*>(__use_small_storage<_Fun>::value
700 ? &__buf->__small
701 : __buf->__large);
702 return (*__f)(_VSTDstd::__1::forward<_ArgTypes>(__args)...);
703 }
704};
705
706// __policy_func uses a __policy and __policy_invoker to create a type-erased,
707// copyable functor.
708
709template <class _Fp> class __policy_func;
710
711template <class _Rp, class... _ArgTypes> class __policy_func<_Rp(_ArgTypes...)>
712{
713 // Inline storage for small objects.
714 __policy_storage __buf_;
715
716 // Calls the value stored in __buf_. This could technically be part of
717 // policy, but storing it here eliminates a level of indirection inside
718 // operator().
719 typedef __function::__policy_invoker<_Rp(_ArgTypes...)> __invoker;
720 __invoker __invoker_;
721
722 // The policy that describes how to move / copy / destroy __buf_. Never
723 // null, even if the function is empty.
724 const __policy* __policy_;
725
726 public:
727 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
728 __policy_func() : __policy_(__policy::__create_empty()) {}
729
730 template <class _Fp, class _Alloc>
731 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
__policy_func(_Fp&& __f, const _Alloc& __a)
732 : __policy_(__policy::__create_empty())
733 {
734 typedef __alloc_func<_Fp, _Alloc, _Rp(_ArgTypes...)> _Fun;
735 typedef allocator_traits<_Alloc> __alloc_traits;
736 typedef typename __rebind_alloc_helper<__alloc_traits, _Fun>::type
737 _FunAlloc;
738
739 if (__function::__not_null(__f))
740 {
741 __invoker_ = __invoker::template __create<_Fun>();
742 __policy_ = __policy::__create<_Fun>();
743
744 _FunAlloc __af(__a);
745 if (__use_small_storage<_Fun>())
746 {
747 ::new ((void*)&__buf_.__small)
748 _Fun(_VSTDstd::__1::move(__f), _Alloc(__af));
749 }
750 else
751 {
752 typedef __allocator_destructor<_FunAlloc> _Dp;
753 unique_ptr<_Fun, _Dp> __hold(__af.allocate(1), _Dp(__af, 1));
754 ::new ((void*)__hold.get())
755 _Fun(_VSTDstd::__1::move(__f), _Alloc(__af));
756 __buf_.__large = __hold.release();
757 }
758 }
759 }
760
761 template <class _Fp, class = typename enable_if<!is_same<typename decay<_Fp>::type, __policy_func>::value>::type>
762 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
explicit __policy_func(_Fp&& __f)
763 : __policy_(__policy::__create_empty()) {
764 typedef __default_alloc_func<_Fp, _Rp(_ArgTypes...)> _Fun;
765
766 if (__function::__not_null(__f)) {
767 __invoker_ = __invoker::template __create<_Fun>();
768 __policy_ = __policy::__create<_Fun>();
769 if (__use_small_storage<_Fun>()) {
770 ::new ((void*)&__buf_.__small) _Fun(_VSTDstd::__1::move(__f));
771 } else {
772 __builtin_new_allocator::__holder_t __hold =
773 __builtin_new_allocator::__allocate_type<_Fun>(1);
774 __buf_.__large = ::new ((void*)__hold.get()) _Fun(_VSTDstd::__1::move(__f));
775 (void)__hold.release();
776 }
777 }
778 }
779
780 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
781 __policy_func(const __policy_func& __f)
782 : __buf_(__f.__buf_), __invoker_(__f.__invoker_),
783 __policy_(__f.__policy_)
784 {
785 if (__policy_->__clone)
786 __buf_.__large = __policy_->__clone(__f.__buf_.__large);
787 }
788
789 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
790 __policy_func(__policy_func&& __f)
791 : __buf_(__f.__buf_), __invoker_(__f.__invoker_),
792 __policy_(__f.__policy_)
793 {
794 if (__policy_->__destroy)
795 {
796 __f.__policy_ = __policy::__create_empty();
797 __f.__invoker_ = __invoker();
798 }
799 }
800
801 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
802 ~__policy_func()
803 {
804 if (__policy_->__destroy)
805 __policy_->__destroy(__buf_.__large);
806 }
807
808 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
809 __policy_func& operator=(__policy_func&& __f)
810 {
811 *this = nullptr;
812 __buf_ = __f.__buf_;
813 __invoker_ = __f.__invoker_;
814 __policy_ = __f.__policy_;
815 __f.__policy_ = __policy::__create_empty();
816 __f.__invoker_ = __invoker();
817 return *this;
818 }
819
820 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
821 __policy_func& operator=(nullptr_t)
822 {
823 const __policy* __p = __policy_;
824 __policy_ = __policy::__create_empty();
825 __invoker_ = __invoker();
826 if (__p->__destroy)
827 __p->__destroy(__buf_.__large);
828 return *this;
829 }
830
831 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
832 _Rp operator()(_ArgTypes&&... __args) const
833 {
834 return __invoker_.__call_(_VSTDstd::__1::addressof(__buf_),
835 _VSTDstd::__1::forward<_ArgTypes>(__args)...);
836 }
837
838 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
839 void swap(__policy_func& __f)
840 {
841 _VSTDstd::__1::swap(__invoker_, __f.__invoker_);
842 _VSTDstd::__1::swap(__policy_, __f.__policy_);
843 _VSTDstd::__1::swap(__buf_, __f.__buf_);
844 }
845
846 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
847 explicit operator bool() const _NOEXCEPTnoexcept
848 {
849 return !__policy_->__is_null;
850 }
851
852#ifndef _LIBCPP_NO_RTTI
853 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
854 const std::type_info& target_type() const _NOEXCEPTnoexcept
855 {
856 return *__policy_->__type_info;
857 }
858
859 template <typename _Tp>
860 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
const _Tp* target() const _NOEXCEPTnoexcept
861 {
862 if (__policy_->__is_null || typeid(_Tp) != *__policy_->__type_info)
863 return nullptr;
864 if (__policy_->__clone) // Out of line storage.
865 return reinterpret_cast<const _Tp*>(__buf_.__large);
866 else
867 return reinterpret_cast<const _Tp*>(&__buf_.__small);
868 }
869#endif // _LIBCPP_NO_RTTI
870};
871
872#if defined(_LIBCPP_HAS_BLOCKS_RUNTIME) && !defined(_LIBCPP_HAS_OBJC_ARC)
873
874extern "C" void *_Block_copy(const void *);
875extern "C" void _Block_release(const void *);
876
877template<class _Rp1, class ..._ArgTypes1, class _Alloc, class _Rp, class ..._ArgTypes>
878class __func<_Rp1(^)(_ArgTypes1...), _Alloc, _Rp(_ArgTypes...)>
879 : public __base<_Rp(_ArgTypes...)>
880{
881 typedef _Rp1(^__block_type)(_ArgTypes1...);
882 __block_type __f_;
883
884public:
885 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
886 explicit __func(__block_type const& __f)
887 : __f_(reinterpret_cast<__block_type>(__f ? _Block_copy(__f) : nullptr))
888 { }
889
890 // [TODO] add && to save on a retain
891
892 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
893 explicit __func(__block_type __f, const _Alloc& /* unused */)
894 : __f_(reinterpret_cast<__block_type>(__f ? _Block_copy(__f) : nullptr))
895 { }
896
897 virtual __base<_Rp(_ArgTypes...)>* __clone() const {
898 _LIBCPP_ASSERT(false,((void)0)
899 "Block pointers are just pointers, so they should always fit into "((void)0)
900 "std::function's small buffer optimization. This function should "((void)0)
901 "never be invoked.")((void)0);
902 return nullptr;
903 }
904
905 virtual void __clone(__base<_Rp(_ArgTypes...)>* __p) const {
906 ::new ((void*)__p) __func(__f_);
907 }
908
909 virtual void destroy() _NOEXCEPTnoexcept {
910 if (__f_)
911 _Block_release(__f_);
912 __f_ = 0;
913 }
914
915 virtual void destroy_deallocate() _NOEXCEPTnoexcept {
916 _LIBCPP_ASSERT(false,((void)0)
917 "Block pointers are just pointers, so they should always fit into "((void)0)
918 "std::function's small buffer optimization. This function should "((void)0)
919 "never be invoked.")((void)0);
920 }
921
922 virtual _Rp operator()(_ArgTypes&& ... __arg) {
923 return _VSTDstd::__1::__invoke(__f_, _VSTDstd::__1::forward<_ArgTypes>(__arg)...);
924 }
925
926#ifndef _LIBCPP_NO_RTTI
927 virtual const void* target(type_info const& __ti) const _NOEXCEPTnoexcept {
928 if (__ti == typeid(__func::__block_type))
929 return &__f_;
930 return (const void*)nullptr;
931 }
932
933 virtual const std::type_info& target_type() const _NOEXCEPTnoexcept {
934 return typeid(__func::__block_type);
935 }
936#endif // _LIBCPP_NO_RTTI
937};
938
939#endif // _LIBCPP_HAS_EXTENSION_BLOCKS && !_LIBCPP_HAS_OBJC_ARC
940
941} // __function
942
943template<class _Rp, class ..._ArgTypes>
944class _LIBCPP_TEMPLATE_VIS__attribute__ ((__type_visibility__("default"))) function<_Rp(_ArgTypes...)>
945#if _LIBCPP_STD_VER14 <= 17 || !defined(_LIBCPP_ABI_NO_BINDER_BASES)
946 : public __function::__maybe_derive_from_unary_function<_Rp(_ArgTypes...)>,
947 public __function::__maybe_derive_from_binary_function<_Rp(_ArgTypes...)>
948#endif
949{
950#ifndef _LIBCPP_ABI_OPTIMIZED_FUNCTION
951 typedef __function::__value_func<_Rp(_ArgTypes...)> __func;
952#else
953 typedef __function::__policy_func<_Rp(_ArgTypes...)> __func;
954#endif
955
956 __func __f_;
957
958 template <class _Fp, bool = _And<
959 _IsNotSame<__uncvref_t<_Fp>, function>,
960 __invokable<_Fp, _ArgTypes...>
961 >::value>
962 struct __callable;
963 template <class _Fp>
964 struct __callable<_Fp, true>
965 {
966 static const bool value = is_void<_Rp>::value ||
967 __is_core_convertible<typename __invoke_of<_Fp, _ArgTypes...>::type,
968 _Rp>::value;
969 };
970 template <class _Fp>
971 struct __callable<_Fp, false>
972 {
973 static const bool value = false;
974 };
975
976 template <class _Fp>
977 using _EnableIfLValueCallable = typename enable_if<__callable<_Fp&>::value>::type;
978public:
979 typedef _Rp result_type;
980
981 // construct/copy/destroy:
982 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
983 function() _NOEXCEPTnoexcept { }
984 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
985 function(nullptr_t) _NOEXCEPTnoexcept {}
986 function(const function&);
987 function(function&&) _NOEXCEPTnoexcept;
988 template<class _Fp, class = _EnableIfLValueCallable<_Fp>>
989 function(_Fp);
990
991#if _LIBCPP_STD_VER14 <= 14
992 template<class _Alloc>
993 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
994 function(allocator_arg_t, const _Alloc&) _NOEXCEPTnoexcept {}
995 template<class _Alloc>
996 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
997 function(allocator_arg_t, const _Alloc&, nullptr_t) _NOEXCEPTnoexcept {}
998 template<class _Alloc>
999 function(allocator_arg_t, const _Alloc&, const function&);
1000 template<class _Alloc>
1001 function(allocator_arg_t, const _Alloc&, function&&);
1002 template<class _Fp, class _Alloc, class = _EnableIfLValueCallable<_Fp>>
1003 function(allocator_arg_t, const _Alloc& __a, _Fp __f);
1004#endif
1005
1006 function& operator=(const function&);
1007 function& operator=(function&&) _NOEXCEPTnoexcept;
1008 function& operator=(nullptr_t) _NOEXCEPTnoexcept;
1009 template<class _Fp, class = _EnableIfLValueCallable<typename decay<_Fp>::type>>
1010 function& operator=(_Fp&&);
1011
1012 ~function();
1013
1014 // function modifiers:
1015 void swap(function&) _NOEXCEPTnoexcept;
1016
1017#if _LIBCPP_STD_VER14 <= 14
1018 template<class _Fp, class _Alloc>
1019 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
1020 void assign(_Fp&& __f, const _Alloc& __a)
1021 {function(allocator_arg, __a, _VSTDstd::__1::forward<_Fp>(__f)).swap(*this);}
1022#endif
1023
1024 // function capacity:
1025 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
1026 explicit operator bool() const _NOEXCEPTnoexcept {
1027 return static_cast<bool>(__f_);
1028 }
1029
1030 // deleted overloads close possible hole in the type system
1031 template<class _R2, class... _ArgTypes2>
1032 bool operator==(const function<_R2(_ArgTypes2...)>&) const = delete;
1033 template<class _R2, class... _ArgTypes2>
1034 bool operator!=(const function<_R2(_ArgTypes2...)>&) const = delete;
1035public:
1036 // function invocation:
1037 _Rp operator()(_ArgTypes...) const;
1038
1039#ifndef _LIBCPP_NO_RTTI
1040 // function target access:
1041 const std::type_info& target_type() const _NOEXCEPTnoexcept;
1042 template <typename _Tp> _Tp* target() _NOEXCEPTnoexcept;
1043 template <typename _Tp> const _Tp* target() const _NOEXCEPTnoexcept;
1044#endif // _LIBCPP_NO_RTTI
1045};
1046
1047#ifndef _LIBCPP_HAS_NO_DEDUCTION_GUIDES
1048template<class _Rp, class ..._Ap>
1049function(_Rp(*)(_Ap...)) -> function<_Rp(_Ap...)>;
1050
1051template<class _Fp>
1052struct __strip_signature;
1053
1054template<class _Rp, class _Gp, class ..._Ap>
1055struct __strip_signature<_Rp (_Gp::*) (_Ap...)> { using type = _Rp(_Ap...); };
1056template<class _Rp, class _Gp, class ..._Ap>
1057struct __strip_signature<_Rp (_Gp::*) (_Ap...) const> { using type = _Rp(_Ap...); };
1058template<class _Rp, class _Gp, class ..._Ap>
1059struct __strip_signature<_Rp (_Gp::*) (_Ap...) volatile> { using type = _Rp(_Ap...); };
1060template<class _Rp, class _Gp, class ..._Ap>
1061struct __strip_signature<_Rp (_Gp::*) (_Ap...) const volatile> { using type = _Rp(_Ap...); };
1062
1063template<class _Rp, class _Gp, class ..._Ap>
1064struct __strip_signature<_Rp (_Gp::*) (_Ap...) &> { using type = _Rp(_Ap...); };
1065template<class _Rp, class _Gp, class ..._Ap>
1066struct __strip_signature<_Rp (_Gp::*) (_Ap...) const &> { using type = _Rp(_Ap...); };
1067template<class _Rp, class _Gp, class ..._Ap>
1068struct __strip_signature<_Rp (_Gp::*) (_Ap...) volatile &> { using type = _Rp(_Ap...); };
1069template<class _Rp, class _Gp, class ..._Ap>
1070struct __strip_signature<_Rp (_Gp::*) (_Ap...) const volatile &> { using type = _Rp(_Ap...); };
1071
1072template<class _Rp, class _Gp, class ..._Ap>
1073struct __strip_signature<_Rp (_Gp::*) (_Ap...) noexcept> { using type = _Rp(_Ap...); };
1074template<class _Rp, class _Gp, class ..._Ap>
1075struct __strip_signature<_Rp (_Gp::*) (_Ap...) const noexcept> { using type = _Rp(_Ap...); };
1076template<class _Rp, class _Gp, class ..._Ap>
1077struct __strip_signature<_Rp (_Gp::*) (_Ap...) volatile noexcept> { using type = _Rp(_Ap...); };
1078template<class _Rp, class _Gp, class ..._Ap>
1079struct __strip_signature<_Rp (_Gp::*) (_Ap...) const volatile noexcept> { using type = _Rp(_Ap...); };
1080
1081template<class _Rp, class _Gp, class ..._Ap>
1082struct __strip_signature<_Rp (_Gp::*) (_Ap...) & noexcept> { using type = _Rp(_Ap...); };
1083template<class _Rp, class _Gp, class ..._Ap>
1084struct __strip_signature<_Rp (_Gp::*) (_Ap...) const & noexcept> { using type = _Rp(_Ap...); };
1085template<class _Rp, class _Gp, class ..._Ap>
1086struct __strip_signature<_Rp (_Gp::*) (_Ap...) volatile & noexcept> { using type = _Rp(_Ap...); };
1087template<class _Rp, class _Gp, class ..._Ap>
1088struct __strip_signature<_Rp (_Gp::*) (_Ap...) const volatile & noexcept> { using type = _Rp(_Ap...); };
1089
1090template<class _Fp, class _Stripped = typename __strip_signature<decltype(&_Fp::operator())>::type>
1091function(_Fp) -> function<_Stripped>;
1092#endif // !_LIBCPP_HAS_NO_DEDUCTION_GUIDES
1093
1094template<class _Rp, class ..._ArgTypes>
1095function<_Rp(_ArgTypes...)>::function(const function& __f) : __f_(__f.__f_) {}
1096
1097#if _LIBCPP_STD_VER14 <= 14
1098template<class _Rp, class ..._ArgTypes>
1099template <class _Alloc>
1100function<_Rp(_ArgTypes...)>::function(allocator_arg_t, const _Alloc&,
1101 const function& __f) : __f_(__f.__f_) {}
1102#endif
1103
1104template <class _Rp, class... _ArgTypes>
1105function<_Rp(_ArgTypes...)>::function(function&& __f) _NOEXCEPTnoexcept
1106 : __f_(_VSTDstd::__1::move(__f.__f_)) {}
1107
1108#if _LIBCPP_STD_VER14 <= 14
1109template<class _Rp, class ..._ArgTypes>
1110template <class _Alloc>
1111function<_Rp(_ArgTypes...)>::function(allocator_arg_t, const _Alloc&,
1112 function&& __f)
1113 : __f_(_VSTDstd::__1::move(__f.__f_)) {}
1114#endif
1115
1116template <class _Rp, class... _ArgTypes>
1117template <class _Fp, class>
1118function<_Rp(_ArgTypes...)>::function(_Fp __f) : __f_(_VSTDstd::__1::move(__f)) {}
1119
1120#if _LIBCPP_STD_VER14 <= 14
1121template <class _Rp, class... _ArgTypes>
1122template <class _Fp, class _Alloc, class>
1123function<_Rp(_ArgTypes...)>::function(allocator_arg_t, const _Alloc& __a,
1124 _Fp __f)
1125 : __f_(_VSTDstd::__1::move(__f), __a) {}
1126#endif
1127
1128template<class _Rp, class ..._ArgTypes>
1129function<_Rp(_ArgTypes...)>&
1130function<_Rp(_ArgTypes...)>::operator=(const function& __f)
1131{
1132 function(__f).swap(*this);
1133 return *this;
1134}
1135
1136template<class _Rp, class ..._ArgTypes>
1137function<_Rp(_ArgTypes...)>&
1138function<_Rp(_ArgTypes...)>::operator=(function&& __f) _NOEXCEPTnoexcept
1139{
1140 __f_ = _VSTDstd::__1::move(__f.__f_);
1141 return *this;
1142}
1143
1144template<class _Rp, class ..._ArgTypes>
1145function<_Rp(_ArgTypes...)>&
1146function<_Rp(_ArgTypes...)>::operator=(nullptr_t) _NOEXCEPTnoexcept
1147{
1148 __f_ = nullptr;
1149 return *this;
1150}
1151
1152template<class _Rp, class ..._ArgTypes>
1153template <class _Fp, class>
1154function<_Rp(_ArgTypes...)>&
1155function<_Rp(_ArgTypes...)>::operator=(_Fp&& __f)
1156{
1157 function(_VSTDstd::__1::forward<_Fp>(__f)).swap(*this);
1158 return *this;
1159}
1160
1161template<class _Rp, class ..._ArgTypes>
1162function<_Rp(_ArgTypes...)>::~function() {}
1163
1164template<class _Rp, class ..._ArgTypes>
1165void
1166function<_Rp(_ArgTypes...)>::swap(function& __f) _NOEXCEPTnoexcept
1167{
1168 __f_.swap(__f.__f_);
1169}
1170
1171template<class _Rp, class ..._ArgTypes>
1172_Rp
1173function<_Rp(_ArgTypes...)>::operator()(_ArgTypes... __arg) const
1174{
1175 return __f_(_VSTDstd::__1::forward<_ArgTypes>(__arg)...);
9
Calling '__value_func::operator()'
13
Returning from '__value_func::operator()'
14
Returning value, which participates in a condition later
25
Calling '__value_func::operator()'
28
Returning from '__value_func::operator()'
29
Returning value, which participates in a condition later
1176}
1177
1178#ifndef _LIBCPP_NO_RTTI
1179
1180template<class _Rp, class ..._ArgTypes>
1181const std::type_info&
1182function<_Rp(_ArgTypes...)>::target_type() const _NOEXCEPTnoexcept
1183{
1184 return __f_.target_type();
1185}
1186
1187template<class _Rp, class ..._ArgTypes>
1188template <typename _Tp>
1189_Tp*
1190function<_Rp(_ArgTypes...)>::target() _NOEXCEPTnoexcept
1191{
1192 return (_Tp*)(__f_.template target<_Tp>());
1193}
1194
1195template<class _Rp, class ..._ArgTypes>
1196template <typename _Tp>
1197const _Tp*
1198function<_Rp(_ArgTypes...)>::target() const _NOEXCEPTnoexcept
1199{
1200 return __f_.template target<_Tp>();
1201}
1202
1203#endif // _LIBCPP_NO_RTTI
1204
1205template <class _Rp, class... _ArgTypes>
1206inline _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
1207bool
1208operator==(const function<_Rp(_ArgTypes...)>& __f, nullptr_t) _NOEXCEPTnoexcept {return !__f;}
1209
1210template <class _Rp, class... _ArgTypes>
1211inline _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
1212bool
1213operator==(nullptr_t, const function<_Rp(_ArgTypes...)>& __f) _NOEXCEPTnoexcept {return !__f;}
1214
1215template <class _Rp, class... _ArgTypes>
1216inline _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
1217bool
1218operator!=(const function<_Rp(_ArgTypes...)>& __f, nullptr_t) _NOEXCEPTnoexcept {return (bool)__f;}
1219
1220template <class _Rp, class... _ArgTypes>
1221inline _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
1222bool
1223operator!=(nullptr_t, const function<_Rp(_ArgTypes...)>& __f) _NOEXCEPTnoexcept {return (bool)__f;}
1224
1225template <class _Rp, class... _ArgTypes>
1226inline _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
1227void
1228swap(function<_Rp(_ArgTypes...)>& __x, function<_Rp(_ArgTypes...)>& __y) _NOEXCEPTnoexcept
1229{return __x.swap(__y);}
1230
1231#else // _LIBCPP_CXX03_LANG
1232
1233namespace __function {
1234
1235template<class _Fp> class __base;
1236
1237template<class _Rp>
1238class __base<_Rp()>
1239{
1240 __base(const __base&);
1241 __base& operator=(const __base&);
1242public:
1243 __base() {}
1244 virtual ~__base() {}
1245 virtual __base* __clone() const = 0;
1246 virtual void __clone(__base*) const = 0;
1247 virtual void destroy() = 0;
1248 virtual void destroy_deallocate() = 0;
1249 virtual _Rp operator()() = 0;
1250#ifndef _LIBCPP_NO_RTTI
1251 virtual const void* target(const type_info&) const = 0;
1252 virtual const std::type_info& target_type() const = 0;
1253#endif // _LIBCPP_NO_RTTI
1254};
1255
1256template<class _Rp, class _A0>
1257class __base<_Rp(_A0)>
1258{
1259 __base(const __base&);
1260 __base& operator=(const __base&);
1261public:
1262 __base() {}
1263 virtual ~__base() {}
1264 virtual __base* __clone() const = 0;
1265 virtual void __clone(__base*) const = 0;
1266 virtual void destroy() = 0;
1267 virtual void destroy_deallocate() = 0;
1268 virtual _Rp operator()(_A0) = 0;
1269#ifndef _LIBCPP_NO_RTTI
1270 virtual const void* target(const type_info&) const = 0;
1271 virtual const std::type_info& target_type() const = 0;
1272#endif // _LIBCPP_NO_RTTI
1273};
1274
1275template<class _Rp, class _A0, class _A1>
1276class __base<_Rp(_A0, _A1)>
1277{
1278 __base(const __base&);
1279 __base& operator=(const __base&);
1280public:
1281 __base() {}
1282 virtual ~__base() {}
1283 virtual __base* __clone() const = 0;
1284 virtual void __clone(__base*) const = 0;
1285 virtual void destroy() = 0;
1286 virtual void destroy_deallocate() = 0;
1287 virtual _Rp operator()(_A0, _A1) = 0;
1288#ifndef _LIBCPP_NO_RTTI
1289 virtual const void* target(const type_info&) const = 0;
1290 virtual const std::type_info& target_type() const = 0;
1291#endif // _LIBCPP_NO_RTTI
1292};
1293
1294template<class _Rp, class _A0, class _A1, class _A2>
1295class __base<_Rp(_A0, _A1, _A2)>
1296{
1297 __base(const __base&);
1298 __base& operator=(const __base&);
1299public:
1300 __base() {}
1301 virtual ~__base() {}
1302 virtual __base* __clone() const = 0;
1303 virtual void __clone(__base*) const = 0;
1304 virtual void destroy() = 0;
1305 virtual void destroy_deallocate() = 0;
1306 virtual _Rp operator()(_A0, _A1, _A2) = 0;
1307#ifndef _LIBCPP_NO_RTTI
1308 virtual const void* target(const type_info&) const = 0;
1309 virtual const std::type_info& target_type() const = 0;
1310#endif // _LIBCPP_NO_RTTI
1311};
1312
1313template<class _FD, class _Alloc, class _FB> class __func;
1314
1315template<class _Fp, class _Alloc, class _Rp>
1316class __func<_Fp, _Alloc, _Rp()>
1317 : public __base<_Rp()>
1318{
1319 __compressed_pair<_Fp, _Alloc> __f_;
1320public:
1321 explicit __func(_Fp __f) : __f_(_VSTDstd::__1::move(__f), __default_init_tag()) {}
1322 explicit __func(_Fp __f, _Alloc __a) : __f_(_VSTDstd::__1::move(__f), _VSTDstd::__1::move(__a)) {}
1323 virtual __base<_Rp()>* __clone() const;
1324 virtual void __clone(__base<_Rp()>*) const;
1325 virtual void destroy();
1326 virtual void destroy_deallocate();
1327 virtual _Rp operator()();
1328#ifndef _LIBCPP_NO_RTTI
1329 virtual const void* target(const type_info&) const;
1330 virtual const std::type_info& target_type() const;
1331#endif // _LIBCPP_NO_RTTI
1332};
1333
1334template<class _Fp, class _Alloc, class _Rp>
1335__base<_Rp()>*
1336__func<_Fp, _Alloc, _Rp()>::__clone() const
1337{
1338 typedef allocator_traits<_Alloc> __alloc_traits;
1339 typedef typename __rebind_alloc_helper<__alloc_traits, __func>::type _Ap;
1340 _Ap __a(__f_.second());
1341 typedef __allocator_destructor<_Ap> _Dp;
1342 unique_ptr<__func, _Dp> __hold(__a.allocate(1), _Dp(__a, 1));
1343 ::new ((void*)__hold.get()) __func(__f_.first(), _Alloc(__a));
1344 return __hold.release();
1345}
1346
1347template<class _Fp, class _Alloc, class _Rp>
1348void
1349__func<_Fp, _Alloc, _Rp()>::__clone(__base<_Rp()>* __p) const
1350{
1351 ::new ((void*)__p) __func(__f_.first(), __f_.second());
1352}
1353
1354template<class _Fp, class _Alloc, class _Rp>
1355void
1356__func<_Fp, _Alloc, _Rp()>::destroy()
1357{
1358 __f_.~__compressed_pair<_Fp, _Alloc>();
1359}
1360
1361template<class _Fp, class _Alloc, class _Rp>
1362void
1363__func<_Fp, _Alloc, _Rp()>::destroy_deallocate()
1364{
1365 typedef allocator_traits<_Alloc> __alloc_traits;
1366 typedef typename __rebind_alloc_helper<__alloc_traits, __func>::type _Ap;
1367 _Ap __a(__f_.second());
1368 __f_.~__compressed_pair<_Fp, _Alloc>();
1369 __a.deallocate(this, 1);
1370}
1371
1372template<class _Fp, class _Alloc, class _Rp>
1373_Rp
1374__func<_Fp, _Alloc, _Rp()>::operator()()
1375{
1376 typedef __invoke_void_return_wrapper<_Rp> _Invoker;
1377 return _Invoker::__call(__f_.first());
1378}
1379
1380#ifndef _LIBCPP_NO_RTTI
1381
1382template<class _Fp, class _Alloc, class _Rp>
1383const void*
1384__func<_Fp, _Alloc, _Rp()>::target(const type_info& __ti) const
1385{
1386 if (__ti == typeid(_Fp))
1387 return &__f_.first();
1388 return (const void*)0;
1389}
1390
1391template<class _Fp, class _Alloc, class _Rp>
1392const std::type_info&
1393__func<_Fp, _Alloc, _Rp()>::target_type() const
1394{
1395 return typeid(_Fp);
1396}
1397
1398#endif // _LIBCPP_NO_RTTI
1399
1400template<class _Fp, class _Alloc, class _Rp, class _A0>
1401class __func<_Fp, _Alloc, _Rp(_A0)>
1402 : public __base<_Rp(_A0)>
1403{
1404 __compressed_pair<_Fp, _Alloc> __f_;
1405public:
1406 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
explicit __func(_Fp __f) : __f_(_VSTDstd::__1::move(__f), __default_init_tag()) {}
1407 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
explicit __func(_Fp __f, _Alloc __a)
1408 : __f_(_VSTDstd::__1::move(__f), _VSTDstd::__1::move(__a)) {}
1409 virtual __base<_Rp(_A0)>* __clone() const;
1410 virtual void __clone(__base<_Rp(_A0)>*) const;
1411 virtual void destroy();
1412 virtual void destroy_deallocate();
1413 virtual _Rp operator()(_A0);
1414#ifndef _LIBCPP_NO_RTTI
1415 virtual const void* target(const type_info&) const;
1416 virtual const std::type_info& target_type() const;
1417#endif // _LIBCPP_NO_RTTI
1418};
1419
1420template<class _Fp, class _Alloc, class _Rp, class _A0>
1421__base<_Rp(_A0)>*
1422__func<_Fp, _Alloc, _Rp(_A0)>::__clone() const
1423{
1424 typedef allocator_traits<_Alloc> __alloc_traits;
1425 typedef typename __rebind_alloc_helper<__alloc_traits, __func>::type _Ap;
1426 _Ap __a(__f_.second());
1427 typedef __allocator_destructor<_Ap> _Dp;
1428 unique_ptr<__func, _Dp> __hold(__a.allocate(1), _Dp(__a, 1));
1429 ::new ((void*)__hold.get()) __func(__f_.first(), _Alloc(__a));
1430 return __hold.release();
1431}
1432
1433template<class _Fp, class _Alloc, class _Rp, class _A0>
1434void
1435__func<_Fp, _Alloc, _Rp(_A0)>::__clone(__base<_Rp(_A0)>* __p) const
1436{
1437 ::new ((void*)__p) __func(__f_.first(), __f_.second());
1438}
1439
1440template<class _Fp, class _Alloc, class _Rp, class _A0>
1441void
1442__func<_Fp, _Alloc, _Rp(_A0)>::destroy()
1443{
1444 __f_.~__compressed_pair<_Fp, _Alloc>();
1445}
1446
1447template<class _Fp, class _Alloc, class _Rp, class _A0>
1448void
1449__func<_Fp, _Alloc, _Rp(_A0)>::destroy_deallocate()
1450{
1451 typedef allocator_traits<_Alloc> __alloc_traits;
1452 typedef typename __rebind_alloc_helper<__alloc_traits, __func>::type _Ap;
1453 _Ap __a(__f_.second());
1454 __f_.~__compressed_pair<_Fp, _Alloc>();
1455 __a.deallocate(this, 1);
1456}
1457
1458template<class _Fp, class _Alloc, class _Rp, class _A0>
1459_Rp
1460__func<_Fp, _Alloc, _Rp(_A0)>::operator()(_A0 __a0)
1461{
1462 typedef __invoke_void_return_wrapper<_Rp> _Invoker;
1463 return _Invoker::__call(__f_.first(), __a0);
1464}
1465
1466#ifndef _LIBCPP_NO_RTTI
1467
1468template<class _Fp, class _Alloc, class _Rp, class _A0>
1469const void*
1470__func<_Fp, _Alloc, _Rp(_A0)>::target(const type_info& __ti) const
1471{
1472 if (__ti == typeid(_Fp))
1473 return &__f_.first();
1474 return (const void*)0;
1475}
1476
1477template<class _Fp, class _Alloc, class _Rp, class _A0>
1478const std::type_info&
1479__func<_Fp, _Alloc, _Rp(_A0)>::target_type() const
1480{
1481 return typeid(_Fp);
1482}
1483
1484#endif // _LIBCPP_NO_RTTI
1485
1486template<class _Fp, class _Alloc, class _Rp, class _A0, class _A1>
1487class __func<_Fp, _Alloc, _Rp(_A0, _A1)>
1488 : public __base<_Rp(_A0, _A1)>
1489{
1490 __compressed_pair<_Fp, _Alloc> __f_;
1491public:
1492 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
explicit __func(_Fp __f) : __f_(_VSTDstd::__1::move(__f), __default_init_tag()) {}
1493 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
explicit __func(_Fp __f, _Alloc __a)
1494 : __f_(_VSTDstd::__1::move(__f), _VSTDstd::__1::move(__a)) {}
1495 virtual __base<_Rp(_A0, _A1)>* __clone() const;
1496 virtual void __clone(__base<_Rp(_A0, _A1)>*) const;
1497 virtual void destroy();
1498 virtual void destroy_deallocate();
1499 virtual _Rp operator()(_A0, _A1);
1500#ifndef _LIBCPP_NO_RTTI
1501 virtual const void* target(const type_info&) const;
1502 virtual const std::type_info& target_type() const;
1503#endif // _LIBCPP_NO_RTTI
1504};
1505
1506template<class _Fp, class _Alloc, class _Rp, class _A0, class _A1>
1507__base<_Rp(_A0, _A1)>*
1508__func<_Fp, _Alloc, _Rp(_A0, _A1)>::__clone() const
1509{
1510 typedef allocator_traits<_Alloc> __alloc_traits;
1511 typedef typename __rebind_alloc_helper<__alloc_traits, __func>::type _Ap;
1512 _Ap __a(__f_.second());
1513 typedef __allocator_destructor<_Ap> _Dp;
1514 unique_ptr<__func, _Dp> __hold(__a.allocate(1), _Dp(__a, 1));
1515 ::new ((void*)__hold.get()) __func(__f_.first(), _Alloc(__a));
1516 return __hold.release();
1517}
1518
1519template<class _Fp, class _Alloc, class _Rp, class _A0, class _A1>
1520void
1521__func<_Fp, _Alloc, _Rp(_A0, _A1)>::__clone(__base<_Rp(_A0, _A1)>* __p) const
1522{
1523 ::new ((void*)__p) __func(__f_.first(), __f_.second());
1524}
1525
1526template<class _Fp, class _Alloc, class _Rp, class _A0, class _A1>
1527void
1528__func<_Fp, _Alloc, _Rp(_A0, _A1)>::destroy()
1529{
1530 __f_.~__compressed_pair<_Fp, _Alloc>();
1531}
1532
1533template<class _Fp, class _Alloc, class _Rp, class _A0, class _A1>
1534void
1535__func<_Fp, _Alloc, _Rp(_A0, _A1)>::destroy_deallocate()
1536{
1537 typedef allocator_traits<_Alloc> __alloc_traits;
1538 typedef typename __rebind_alloc_helper<__alloc_traits, __func>::type _Ap;
1539 _Ap __a(__f_.second());
1540 __f_.~__compressed_pair<_Fp, _Alloc>();
1541 __a.deallocate(this, 1);
1542}
1543
1544template<class _Fp, class _Alloc, class _Rp, class _A0, class _A1>
1545_Rp
1546__func<_Fp, _Alloc, _Rp(_A0, _A1)>::operator()(_A0 __a0, _A1 __a1)
1547{
1548 typedef __invoke_void_return_wrapper<_Rp> _Invoker;
1549 return _Invoker::__call(__f_.first(), __a0, __a1);
1550}
1551
1552#ifndef _LIBCPP_NO_RTTI
1553
1554template<class _Fp, class _Alloc, class _Rp, class _A0, class _A1>
1555const void*
1556__func<_Fp, _Alloc, _Rp(_A0, _A1)>::target(const type_info& __ti) const
1557{
1558 if (__ti == typeid(_Fp))
1559 return &__f_.first();
1560 return (const void*)0;
1561}
1562
1563template<class _Fp, class _Alloc, class _Rp, class _A0, class _A1>
1564const std::type_info&
1565__func<_Fp, _Alloc, _Rp(_A0, _A1)>::target_type() const
1566{
1567 return typeid(_Fp);
1568}
1569
1570#endif // _LIBCPP_NO_RTTI
1571
1572template<class _Fp, class _Alloc, class _Rp, class _A0, class _A1, class _A2>
1573class __func<_Fp, _Alloc, _Rp(_A0, _A1, _A2)>
1574 : public __base<_Rp(_A0, _A1, _A2)>
1575{
1576 __compressed_pair<_Fp, _Alloc> __f_;
1577public:
1578 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
explicit __func(_Fp __f) : __f_(_VSTDstd::__1::move(__f), __default_init_tag()) {}
1579 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
explicit __func(_Fp __f, _Alloc __a)
1580 : __f_(_VSTDstd::__1::move(__f), _VSTDstd::__1::move(__a)) {}
1581 virtual __base<_Rp(_A0, _A1, _A2)>* __clone() const;
1582 virtual void __clone(__base<_Rp(_A0, _A1, _A2)>*) const;
1583 virtual void destroy();
1584 virtual void destroy_deallocate();
1585 virtual _Rp operator()(_A0, _A1, _A2);
1586#ifndef _LIBCPP_NO_RTTI
1587 virtual const void* target(const type_info&) const;
1588 virtual const std::type_info& target_type() const;
1589#endif // _LIBCPP_NO_RTTI
1590};
1591
1592template<class _Fp, class _Alloc, class _Rp, class _A0, class _A1, class _A2>
1593__base<_Rp(_A0, _A1, _A2)>*
1594__func<_Fp, _Alloc, _Rp(_A0, _A1, _A2)>::__clone() const
1595{
1596 typedef allocator_traits<_Alloc> __alloc_traits;
1597 typedef typename __rebind_alloc_helper<__alloc_traits, __func>::type _Ap;
1598 _Ap __a(__f_.second());
1599 typedef __allocator_destructor<_Ap> _Dp;
1600 unique_ptr<__func, _Dp> __hold(__a.allocate(1), _Dp(__a, 1));
1601 ::new ((void*)__hold.get()) __func(__f_.first(), _Alloc(__a));
1602 return __hold.release();
1603}
1604
1605template<class _Fp, class _Alloc, class _Rp, class _A0, class _A1, class _A2>
1606void
1607__func<_Fp, _Alloc, _Rp(_A0, _A1, _A2)>::__clone(__base<_Rp(_A0, _A1, _A2)>* __p) const
1608{
1609 ::new ((void*)__p) __func(__f_.first(), __f_.second());
1610}
1611
1612template<class _Fp, class _Alloc, class _Rp, class _A0, class _A1, class _A2>
1613void
1614__func<_Fp, _Alloc, _Rp(_A0, _A1, _A2)>::destroy()
1615{
1616 __f_.~__compressed_pair<_Fp, _Alloc>();
1617}
1618
1619template<class _Fp, class _Alloc, class _Rp, class _A0, class _A1, class _A2>
1620void
1621__func<_Fp, _Alloc, _Rp(_A0, _A1, _A2)>::destroy_deallocate()
1622{
1623 typedef allocator_traits<_Alloc> __alloc_traits;
1624 typedef typename __rebind_alloc_helper<__alloc_traits, __func>::type _Ap;
1625 _Ap __a(__f_.second());
1626 __f_.~__compressed_pair<_Fp, _Alloc>();
1627 __a.deallocate(this, 1);
1628}
1629
1630template<class _Fp, class _Alloc, class _Rp, class _A0, class _A1, class _A2>
1631_Rp
1632__func<_Fp, _Alloc, _Rp(_A0, _A1, _A2)>::operator()(_A0 __a0, _A1 __a1, _A2 __a2)
1633{
1634 typedef __invoke_void_return_wrapper<_Rp> _Invoker;
1635 return _Invoker::__call(__f_.first(), __a0, __a1, __a2);
1636}
1637
1638#ifndef _LIBCPP_NO_RTTI
1639
1640template<class _Fp, class _Alloc, class _Rp, class _A0, class _A1, class _A2>
1641const void*
1642__func<_Fp, _Alloc, _Rp(_A0, _A1, _A2)>::target(const type_info& __ti) const
1643{
1644 if (__ti == typeid(_Fp))
1645 return &__f_.first();
1646 return (const void*)0;
1647}
1648
1649template<class _Fp, class _Alloc, class _Rp, class _A0, class _A1, class _A2>
1650const std::type_info&
1651__func<_Fp, _Alloc, _Rp(_A0, _A1, _A2)>::target_type() const
1652{
1653 return typeid(_Fp);
1654}
1655
1656#endif // _LIBCPP_NO_RTTI
1657
1658} // __function
1659
1660template<class _Rp>
1661class _LIBCPP_TEMPLATE_VIS__attribute__ ((__type_visibility__("default"))) function<_Rp()>
1662{
1663 typedef __function::__base<_Rp()> __base;
1664 aligned_storage<3*sizeof(void*)>::type __buf_;
1665 __base* __f_;
1666
1667public:
1668 typedef _Rp result_type;
1669
1670 // 20.7.16.2.1, construct/copy/destroy:
1671 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
explicit function() : __f_(0) {}
1672 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
function(nullptr_t) : __f_(0) {}
1673 function(const function&);
1674 template<class _Fp>
1675 function(_Fp,
1676 typename enable_if<!is_integral<_Fp>::value>::type* = 0);
1677
1678 template<class _Alloc>
1679 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
1680 function(allocator_arg_t, const _Alloc&) : __f_(0) {}
1681 template<class _Alloc>
1682 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
1683 function(allocator_arg_t, const _Alloc&, nullptr_t) : __f_(0) {}
1684 template<class _Alloc>
1685 function(allocator_arg_t, const _Alloc&, const function&);
1686 template<class _Fp, class _Alloc>
1687 function(allocator_arg_t, const _Alloc& __a, _Fp __f,
1688 typename enable_if<!is_integral<_Fp>::value>::type* = 0);
1689
1690 function& operator=(const function&);
1691 function& operator=(nullptr_t);
1692 template<class _Fp>
1693 typename enable_if
1694 <
1695 !is_integral<_Fp>::value,
1696 function&
1697 >::type
1698 operator=(_Fp);
1699
1700 ~function();
1701
1702 // 20.7.16.2.2, function modifiers:
1703 void swap(function&);
1704 template<class _Fp, class _Alloc>
1705 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
1706 void assign(_Fp __f, const _Alloc& __a)
1707 {function(allocator_arg, __a, __f).swap(*this);}
1708
1709 // 20.7.16.2.3, function capacity:
1710 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
explicit operator bool() const {return __f_;}
1711
1712private:
1713 // deleted overloads close possible hole in the type system
1714 template<class _R2>
1715 bool operator==(const function<_R2()>&) const;// = delete;
1716 template<class _R2>
1717 bool operator!=(const function<_R2()>&) const;// = delete;
1718public:
1719 // 20.7.16.2.4, function invocation:
1720 _Rp operator()() const;
1721
1722#ifndef _LIBCPP_NO_RTTI
1723 // 20.7.16.2.5, function target access:
1724 const std::type_info& target_type() const;
1725 template <typename _Tp> _Tp* target();
1726 template <typename _Tp> const _Tp* target() const;
1727#endif // _LIBCPP_NO_RTTI
1728};
1729
1730template<class _Rp>
1731function<_Rp()>::function(const function& __f)
1732{
1733 if (__f.__f_ == 0)
1734 __f_ = 0;
1735 else if (__f.__f_ == (const __base*)&__f.__buf_)
1736 {
1737 __f_ = (__base*)&__buf_;
1738 __f.__f_->__clone(__f_);
1739 }
1740 else
1741 __f_ = __f.__f_->__clone();
1742}
1743
1744template<class _Rp>
1745template<class _Alloc>
1746function<_Rp()>::function(allocator_arg_t, const _Alloc&, const function& __f)
1747{
1748 if (__f.__f_ == 0)
1749 __f_ = 0;
1750 else if (__f.__f_ == (const __base*)&__f.__buf_)
1751 {
1752 __f_ = (__base*)&__buf_;
1753 __f.__f_->__clone(__f_);
1754 }
1755 else
1756 __f_ = __f.__f_->__clone();
1757}
1758
1759template<class _Rp>
1760template <class _Fp>
1761function<_Rp()>::function(_Fp __f,
1762 typename enable_if<!is_integral<_Fp>::value>::type*)
1763 : __f_(0)
1764{
1765 if (__function::__not_null(__f))
1766 {
1767 typedef __function::__func<_Fp, allocator<_Fp>, _Rp()> _FF;
1768 if (sizeof(_FF) <= sizeof(__buf_))
1769 {
1770 __f_ = (__base*)&__buf_;
1771 ::new ((void*)__f_) _FF(__f);
1772 }
1773 else
1774 {
1775 typedef allocator<_FF> _Ap;
1776 _Ap __a;
1777 typedef __allocator_destructor<_Ap> _Dp;
1778 unique_ptr<__base, _Dp> __hold(__a.allocate(1), _Dp(__a, 1));
1779 ::new ((void*)__hold.get()) _FF(__f, allocator<_Fp>(__a));
1780 __f_ = __hold.release();
1781 }
1782 }
1783}
1784
1785template<class _Rp>
1786template <class _Fp, class _Alloc>
1787function<_Rp()>::function(allocator_arg_t, const _Alloc& __a0, _Fp __f,
1788 typename enable_if<!is_integral<_Fp>::value>::type*)
1789 : __f_(0)
1790{
1791 typedef allocator_traits<_Alloc> __alloc_traits;
1792 if (__function::__not_null(__f))
1793 {
1794 typedef __function::__func<_Fp, _Alloc, _Rp()> _FF;
1795 if (sizeof(_FF) <= sizeof(__buf_))
1796 {
1797 __f_ = (__base*)&__buf_;
1798 ::new ((void*)__f_) _FF(__f, __a0);
1799 }
1800 else
1801 {
1802 typedef typename __rebind_alloc_helper<__alloc_traits, _FF>::type _Ap;
1803 _Ap __a(__a0);
1804 typedef __allocator_destructor<_Ap> _Dp;
1805 unique_ptr<__base, _Dp> __hold(__a.allocate(1), _Dp(__a, 1));
1806 ::new ((void*)__hold.get()) _FF(__f, _Alloc(__a));
1807 __f_ = __hold.release();
1808 }
1809 }
1810}
1811
1812template<class _Rp>
1813function<_Rp()>&
1814function<_Rp()>::operator=(const function& __f)
1815{
1816 if (__f)
1817 function(__f).swap(*this);
1818 else
1819 *this = nullptr;
1820 return *this;
1821}
1822
1823template<class _Rp>
1824function<_Rp()>&
1825function<_Rp()>::operator=(nullptr_t)
1826{
1827 __base* __t = __f_;
1828 __f_ = 0;
1829 if (__t == (__base*)&__buf_)
1830 __t->destroy();
1831 else if (__t)
1832 __t->destroy_deallocate();
1833 return *this;
1834}
1835
1836template<class _Rp>
1837template <class _Fp>
1838typename enable_if
1839<
1840 !is_integral<_Fp>::value,
1841 function<_Rp()>&
1842>::type
1843function<_Rp()>::operator=(_Fp __f)
1844{
1845 function(_VSTDstd::__1::move(__f)).swap(*this);
1846 return *this;
1847}
1848
1849template<class _Rp>
1850function<_Rp()>::~function()
1851{
1852 if (__f_ == (__base*)&__buf_)
1853 __f_->destroy();
1854 else if (__f_)
1855 __f_->destroy_deallocate();
1856}
1857
1858template<class _Rp>
1859void
1860function<_Rp()>::swap(function& __f)
1861{
1862 if (_VSTDstd::__1::addressof(__f) == this)
1863 return;
1864 if (__f_ == (__base*)&__buf_ && __f.__f_ == (__base*)&__f.__buf_)
1865 {
1866 typename aligned_storage<sizeof(__buf_)>::type __tempbuf;
1867 __base* __t = (__base*)&__tempbuf;
1868 __f_->__clone(__t);
1869 __f_->destroy();
1870 __f_ = 0;
1871 __f.__f_->__clone((__base*)&__buf_);
1872 __f.__f_->destroy();
1873 __f.__f_ = 0;
1874 __f_ = (__base*)&__buf_;
1875 __t->__clone((__base*)&__f.__buf_);
1876 __t->destroy();
1877 __f.__f_ = (__base*)&__f.__buf_;
1878 }
1879 else if (__f_ == (__base*)&__buf_)
1880 {
1881 __f_->__clone((__base*)&__f.__buf_);
1882 __f_->destroy();
1883 __f_ = __f.__f_;
1884 __f.__f_ = (__base*)&__f.__buf_;
1885 }
1886 else if (__f.__f_ == (__base*)&__f.__buf_)
1887 {
1888 __f.__f_->__clone((__base*)&__buf_);
1889 __f.__f_->destroy();
1890 __f.__f_ = __f_;
1891 __f_ = (__base*)&__buf_;
1892 }
1893 else
1894 _VSTDstd::__1::swap(__f_, __f.__f_);
1895}
1896
1897template<class _Rp>
1898_Rp
1899function<_Rp()>::operator()() const
1900{
1901 if (__f_ == 0)
1902 __throw_bad_function_call();
1903 return (*__f_)();
1904}
1905
1906#ifndef _LIBCPP_NO_RTTI
1907
1908template<class _Rp>
1909const std::type_info&
1910function<_Rp()>::target_type() const
1911{
1912 if (__f_ == 0)
1913 return typeid(void);
1914 return __f_->target_type();
1915}
1916
1917template<class _Rp>
1918template <typename _Tp>
1919_Tp*
1920function<_Rp()>::target()
1921{
1922 if (__f_ == 0)
1923 return (_Tp*)0;
1924 return (_Tp*) const_cast<void *>(__f_->target(typeid(_Tp)));
1925}
1926
1927template<class _Rp>
1928template <typename _Tp>
1929const _Tp*
1930function<_Rp()>::target() const
1931{
1932 if (__f_ == 0)
1933 return (const _Tp*)0;
1934 return (const _Tp*)__f_->target(typeid(_Tp));
1935}
1936
1937#endif // _LIBCPP_NO_RTTI
1938
1939template<class _Rp, class _A0>
1940class _LIBCPP_TEMPLATE_VIS__attribute__ ((__type_visibility__("default"))) function<_Rp(_A0)>
1941 : public unary_function<_A0, _Rp>
1942{
1943 typedef __function::__base<_Rp(_A0)> __base;
1944 aligned_storage<3*sizeof(void*)>::type __buf_;
1945 __base* __f_;
1946
1947public:
1948 typedef _Rp result_type;
1949
1950 // 20.7.16.2.1, construct/copy/destroy:
1951 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
explicit function() : __f_(0) {}
1952 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
function(nullptr_t) : __f_(0) {}
1953 function(const function&);
1954 template<class _Fp>
1955 function(_Fp,
1956 typename enable_if<!is_integral<_Fp>::value>::type* = 0);
1957
1958 template<class _Alloc>
1959 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
1960 function(allocator_arg_t, const _Alloc&) : __f_(0) {}
1961 template<class _Alloc>
1962 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
1963 function(allocator_arg_t, const _Alloc&, nullptr_t) : __f_(0) {}
1964 template<class _Alloc>
1965 function(allocator_arg_t, const _Alloc&, const function&);
1966 template<class _Fp, class _Alloc>
1967 function(allocator_arg_t, const _Alloc& __a, _Fp __f,
1968 typename enable_if<!is_integral<_Fp>::value>::type* = 0);
1969
1970 function& operator=(const function&);
1971 function& operator=(nullptr_t);
1972 template<class _Fp>
1973 typename enable_if
1974 <
1975 !is_integral<_Fp>::value,
1976 function&
1977 >::type
1978 operator=(_Fp);
1979
1980 ~function();
1981
1982 // 20.7.16.2.2, function modifiers:
1983 void swap(function&);
1984 template<class _Fp, class _Alloc>
1985 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
1986 void assign(_Fp __f, const _Alloc& __a)
1987 {function(allocator_arg, __a, __f).swap(*this);}
1988
1989 // 20.7.16.2.3, function capacity:
1990 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
explicit operator bool() const {return __f_;}
1991
1992private:
1993 // deleted overloads close possible hole in the type system
1994 template<class _R2, class _B0>
1995 bool operator==(const function<_R2(_B0)>&) const;// = delete;
1996 template<class _R2, class _B0>
1997 bool operator!=(const function<_R2(_B0)>&) const;// = delete;
1998public:
1999 // 20.7.16.2.4, function invocation:
2000 _Rp operator()(_A0) const;
2001
2002#ifndef _LIBCPP_NO_RTTI
2003 // 20.7.16.2.5, function target access:
2004 const std::type_info& target_type() const;
2005 template <typename _Tp> _Tp* target();
2006 template <typename _Tp> const _Tp* target() const;
2007#endif // _LIBCPP_NO_RTTI
2008};
2009
2010template<class _Rp, class _A0>
2011function<_Rp(_A0)>::function(const function& __f)
2012{
2013 if (__f.__f_ == 0)
2014 __f_ = 0;
2015 else if (__f.__f_ == (const __base*)&__f.__buf_)
2016 {
2017 __f_ = (__base*)&__buf_;
2018 __f.__f_->__clone(__f_);
2019 }
2020 else
2021 __f_ = __f.__f_->__clone();
2022}
2023
2024template<class _Rp, class _A0>
2025template<class _Alloc>
2026function<_Rp(_A0)>::function(allocator_arg_t, const _Alloc&, const function& __f)
2027{
2028 if (__f.__f_ == 0)
2029 __f_ = 0;
2030 else if (__f.__f_ == (const __base*)&__f.__buf_)
2031 {
2032 __f_ = (__base*)&__buf_;
2033 __f.__f_->__clone(__f_);
2034 }
2035 else
2036 __f_ = __f.__f_->__clone();
2037}
2038
2039template<class _Rp, class _A0>
2040template <class _Fp>
2041function<_Rp(_A0)>::function(_Fp __f,
2042 typename enable_if<!is_integral<_Fp>::value>::type*)
2043 : __f_(0)
2044{
2045 if (__function::__not_null(__f))
2046 {
2047 typedef __function::__func<_Fp, allocator<_Fp>, _Rp(_A0)> _FF;
2048 if (sizeof(_FF) <= sizeof(__buf_))
2049 {
2050 __f_ = (__base*)&__buf_;
2051 ::new ((void*)__f_) _FF(__f);
2052 }
2053 else
2054 {
2055 typedef allocator<_FF> _Ap;
2056 _Ap __a;
2057 typedef __allocator_destructor<_Ap> _Dp;
2058 unique_ptr<__base, _Dp> __hold(__a.allocate(1), _Dp(__a, 1));
2059 ::new ((void*)__hold.get()) _FF(__f, allocator<_Fp>(__a));
2060 __f_ = __hold.release();
2061 }
2062 }
2063}
2064
2065template<class _Rp, class _A0>
2066template <class _Fp, class _Alloc>
2067function<_Rp(_A0)>::function(allocator_arg_t, const _Alloc& __a0, _Fp __f,
2068 typename enable_if<!is_integral<_Fp>::value>::type*)
2069 : __f_(0)
2070{
2071 typedef allocator_traits<_Alloc> __alloc_traits;
2072 if (__function::__not_null(__f))
2073 {
2074 typedef __function::__func<_Fp, _Alloc, _Rp(_A0)> _FF;
2075 if (sizeof(_FF) <= sizeof(__buf_))
2076 {
2077 __f_ = (__base*)&__buf_;
2078 ::new ((void*)__f_) _FF(__f, __a0);
2079 }
2080 else
2081 {
2082 typedef typename __rebind_alloc_helper<__alloc_traits, _FF>::type _Ap;
2083 _Ap __a(__a0);
2084 typedef __allocator_destructor<_Ap> _Dp;
2085 unique_ptr<__base, _Dp> __hold(__a.allocate(1), _Dp(__a, 1));
2086 ::new ((void*)__hold.get()) _FF(__f, _Alloc(__a));
2087 __f_ = __hold.release();
2088 }
2089 }
2090}
2091
2092template<class _Rp, class _A0>
2093function<_Rp(_A0)>&
2094function<_Rp(_A0)>::operator=(const function& __f)
2095{
2096 if (__f)
2097 function(__f).swap(*this);
2098 else
2099 *this = nullptr;
2100 return *this;
2101}
2102
2103template<class _Rp, class _A0>
2104function<_Rp(_A0)>&
2105function<_Rp(_A0)>::operator=(nullptr_t)
2106{
2107 __base* __t = __f_;
2108 __f_ = 0;
2109 if (__t == (__base*)&__buf_)
2110 __t->destroy();
2111 else if (__t)
2112 __t->destroy_deallocate();
2113 return *this;
2114}
2115
2116template<class _Rp, class _A0>
2117template <class _Fp>
2118typename enable_if
2119<
2120 !is_integral<_Fp>::value,
2121 function<_Rp(_A0)>&
2122>::type
2123function<_Rp(_A0)>::operator=(_Fp __f)
2124{
2125 function(_VSTDstd::__1::move(__f)).swap(*this);
2126 return *this;
2127}
2128
2129template<class _Rp, class _A0>
2130function<_Rp(_A0)>::~function()
2131{
2132 if (__f_ == (__base*)&__buf_)
2133 __f_->destroy();
2134 else if (__f_)
2135 __f_->destroy_deallocate();
2136}
2137
2138template<class _Rp, class _A0>
2139void
2140function<_Rp(_A0)>::swap(function& __f)
2141{
2142 if (_VSTDstd::__1::addressof(__f) == this)
2143 return;
2144 if (__f_ == (__base*)&__buf_ && __f.__f_ == (__base*)&__f.__buf_)
2145 {
2146 typename aligned_storage<sizeof(__buf_)>::type __tempbuf;
2147 __base* __t = (__base*)&__tempbuf;
2148 __f_->__clone(__t);
2149 __f_->destroy();
2150 __f_ = 0;
2151 __f.__f_->__clone((__base*)&__buf_);
2152 __f.__f_->destroy();
2153 __f.__f_ = 0;
2154 __f_ = (__base*)&__buf_;
2155 __t->__clone((__base*)&__f.__buf_);
2156 __t->destroy();
2157 __f.__f_ = (__base*)&__f.__buf_;
2158 }
2159 else if (__f_ == (__base*)&__buf_)
2160 {
2161 __f_->__clone((__base*)&__f.__buf_);
2162 __f_->destroy();
2163 __f_ = __f.__f_;
2164 __f.__f_ = (__base*)&__f.__buf_;
2165 }
2166 else if (__f.__f_ == (__base*)&__f.__buf_)
2167 {
2168 __f.__f_->__clone((__base*)&__buf_);
2169 __f.__f_->destroy();
2170 __f.__f_ = __f_;
2171 __f_ = (__base*)&__buf_;
2172 }
2173 else
2174 _VSTDstd::__1::swap(__f_, __f.__f_);
2175}
2176
2177template<class _Rp, class _A0>
2178_Rp
2179function<_Rp(_A0)>::operator()(_A0 __a0) const
2180{
2181 if (__f_ == 0)
2182 __throw_bad_function_call();
2183 return (*__f_)(__a0);
2184}
2185
2186#ifndef _LIBCPP_NO_RTTI
2187
2188template<class _Rp, class _A0>
2189const std::type_info&
2190function<_Rp(_A0)>::target_type() const
2191{
2192 if (__f_ == 0)
2193 return typeid(void);
2194 return __f_->target_type();
2195}
2196
2197template<class _Rp, class _A0>
2198template <typename _Tp>
2199_Tp*
2200function<_Rp(_A0)>::target()
2201{
2202 if (__f_ == 0)
2203 return (_Tp*)0;
2204 return (_Tp*) const_cast<void *>(__f_->target(typeid(_Tp)));
2205}
2206
2207template<class _Rp, class _A0>
2208template <typename _Tp>
2209const _Tp*
2210function<_Rp(_A0)>::target() const
2211{
2212 if (__f_ == 0)
2213 return (const _Tp*)0;
2214 return (const _Tp*)__f_->target(typeid(_Tp));
2215}
2216
2217#endif // _LIBCPP_NO_RTTI
2218
2219template<class _Rp, class _A0, class _A1>
2220class _LIBCPP_TEMPLATE_VIS__attribute__ ((__type_visibility__("default"))) function<_Rp(_A0, _A1)>
2221 : public binary_function<_A0, _A1, _Rp>
2222{
2223 typedef __function::__base<_Rp(_A0, _A1)> __base;
2224 aligned_storage<3*sizeof(void*)>::type __buf_;
2225 __base* __f_;
2226
2227public:
2228 typedef _Rp result_type;
2229
2230 // 20.7.16.2.1, construct/copy/destroy:
2231 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
explicit function() : __f_(0) {}
2232 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
function(nullptr_t) : __f_(0) {}
2233 function(const function&);
2234 template<class _Fp>
2235 function(_Fp,
2236 typename enable_if<!is_integral<_Fp>::value>::type* = 0);
2237
2238 template<class _Alloc>
2239 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
2240 function(allocator_arg_t, const _Alloc&) : __f_(0) {}
2241 template<class _Alloc>
2242 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
2243 function(allocator_arg_t, const _Alloc&, nullptr_t) : __f_(0) {}
2244 template<class _Alloc>
2245 function(allocator_arg_t, const _Alloc&, const function&);
2246 template<class _Fp, class _Alloc>
2247 function(allocator_arg_t, const _Alloc& __a, _Fp __f,
2248 typename enable_if<!is_integral<_Fp>::value>::type* = 0);
2249
2250 function& operator=(const function&);
2251 function& operator=(nullptr_t);
2252 template<class _Fp>
2253 typename enable_if
2254 <
2255 !is_integral<_Fp>::value,
2256 function&
2257 >::type
2258 operator=(_Fp);
2259
2260 ~function();
2261
2262 // 20.7.16.2.2, function modifiers:
2263 void swap(function&);
2264 template<class _Fp, class _Alloc>
2265 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
2266 void assign(_Fp __f, const _Alloc& __a)
2267 {function(allocator_arg, __a, __f).swap(*this);}
2268
2269 // 20.7.16.2.3, function capacity:
2270 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
explicit operator bool() const {return __f_;}
2271
2272private:
2273 // deleted overloads close possible hole in the type system
2274 template<class _R2, class _B0, class _B1>
2275 bool operator==(const function<_R2(_B0, _B1)>&) const;// = delete;
2276 template<class _R2, class _B0, class _B1>
2277 bool operator!=(const function<_R2(_B0, _B1)>&) const;// = delete;
2278public:
2279 // 20.7.16.2.4, function invocation:
2280 _Rp operator()(_A0, _A1) const;
2281
2282#ifndef _LIBCPP_NO_RTTI
2283 // 20.7.16.2.5, function target access:
2284 const std::type_info& target_type() const;
2285 template <typename _Tp> _Tp* target();
2286 template <typename _Tp> const _Tp* target() const;
2287#endif // _LIBCPP_NO_RTTI
2288};
2289
2290template<class _Rp, class _A0, class _A1>
2291function<_Rp(_A0, _A1)>::function(const function& __f)
2292{
2293 if (__f.__f_ == 0)
2294 __f_ = 0;
2295 else if (__f.__f_ == (const __base*)&__f.__buf_)
2296 {
2297 __f_ = (__base*)&__buf_;
2298 __f.__f_->__clone(__f_);
2299 }
2300 else
2301 __f_ = __f.__f_->__clone();
2302}
2303
2304template<class _Rp, class _A0, class _A1>
2305template<class _Alloc>
2306function<_Rp(_A0, _A1)>::function(allocator_arg_t, const _Alloc&, const function& __f)
2307{
2308 if (__f.__f_ == 0)
2309 __f_ = 0;
2310 else if (__f.__f_ == (const __base*)&__f.__buf_)
2311 {
2312 __f_ = (__base*)&__buf_;
2313 __f.__f_->__clone(__f_);
2314 }
2315 else
2316 __f_ = __f.__f_->__clone();
2317}
2318
2319template<class _Rp, class _A0, class _A1>
2320template <class _Fp>
2321function<_Rp(_A0, _A1)>::function(_Fp __f,
2322 typename enable_if<!is_integral<_Fp>::value>::type*)
2323 : __f_(0)
2324{
2325 if (__function::__not_null(__f))
2326 {
2327 typedef __function::__func<_Fp, allocator<_Fp>, _Rp(_A0, _A1)> _FF;
2328 if (sizeof(_FF) <= sizeof(__buf_))
2329 {
2330 __f_ = (__base*)&__buf_;
2331 ::new ((void*)__f_) _FF(__f);
2332 }
2333 else
2334 {
2335 typedef allocator<_FF> _Ap;
2336 _Ap __a;
2337 typedef __allocator_destructor<_Ap> _Dp;
2338 unique_ptr<__base, _Dp> __hold(__a.allocate(1), _Dp(__a, 1));
2339 ::new ((void*)__hold.get()) _FF(__f, allocator<_Fp>(__a));
2340 __f_ = __hold.release();
2341 }
2342 }
2343}
2344
2345template<class _Rp, class _A0, class _A1>
2346template <class _Fp, class _Alloc>
2347function<_Rp(_A0, _A1)>::function(allocator_arg_t, const _Alloc& __a0, _Fp __f,
2348 typename enable_if<!is_integral<_Fp>::value>::type*)
2349 : __f_(0)
2350{
2351 typedef allocator_traits<_Alloc> __alloc_traits;
2352 if (__function::__not_null(__f))
2353 {
2354 typedef __function::__func<_Fp, _Alloc, _Rp(_A0, _A1)> _FF;
2355 if (sizeof(_FF) <= sizeof(__buf_))
2356 {
2357 __f_ = (__base*)&__buf_;
2358 ::new ((void*)__f_) _FF(__f, __a0);
2359 }
2360 else
2361 {
2362 typedef typename __rebind_alloc_helper<__alloc_traits, _FF>::type _Ap;
2363 _Ap __a(__a0);
2364 typedef __allocator_destructor<_Ap> _Dp;
2365 unique_ptr<__base, _Dp> __hold(__a.allocate(1), _Dp(__a, 1));
2366 ::new ((void*)__hold.get()) _FF(__f, _Alloc(__a));
2367 __f_ = __hold.release();
2368 }
2369 }
2370}
2371
2372template<class _Rp, class _A0, class _A1>
2373function<_Rp(_A0, _A1)>&
2374function<_Rp(_A0, _A1)>::operator=(const function& __f)
2375{
2376 if (__f)
2377 function(__f).swap(*this);
2378 else
2379 *this = nullptr;
2380 return *this;
2381}
2382
2383template<class _Rp, class _A0, class _A1>
2384function<_Rp(_A0, _A1)>&
2385function<_Rp(_A0, _A1)>::operator=(nullptr_t)
2386{
2387 __base* __t = __f_;
2388 __f_ = 0;
2389 if (__t == (__base*)&__buf_)
2390 __t->destroy();
2391 else if (__t)
2392 __t->destroy_deallocate();
2393 return *this;
2394}
2395
2396template<class _Rp, class _A0, class _A1>
2397template <class _Fp>
2398typename enable_if
2399<
2400 !is_integral<_Fp>::value,
2401 function<_Rp(_A0, _A1)>&
2402>::type
2403function<_Rp(_A0, _A1)>::operator=(_Fp __f)
2404{
2405 function(_VSTDstd::__1::move(__f)).swap(*this);
2406 return *this;
2407}
2408
2409template<class _Rp, class _A0, class _A1>
2410function<_Rp(_A0, _A1)>::~function()
2411{
2412 if (__f_ == (__base*)&__buf_)
2413 __f_->destroy();
2414 else if (__f_)
2415 __f_->destroy_deallocate();
2416}
2417
2418template<class _Rp, class _A0, class _A1>
2419void
2420function<_Rp(_A0, _A1)>::swap(function& __f)
2421{
2422 if (_VSTDstd::__1::addressof(__f) == this)
2423 return;
2424 if (__f_ == (__base*)&__buf_ && __f.__f_ == (__base*)&__f.__buf_)
2425 {
2426 typename aligned_storage<sizeof(__buf_)>::type __tempbuf;
2427 __base* __t = (__base*)&__tempbuf;
2428 __f_->__clone(__t);
2429 __f_->destroy();
2430 __f_ = 0;
2431 __f.__f_->__clone((__base*)&__buf_);
2432 __f.__f_->destroy();
2433 __f.__f_ = 0;
2434 __f_ = (__base*)&__buf_;
2435 __t->__clone((__base*)&__f.__buf_);
2436 __t->destroy();
2437 __f.__f_ = (__base*)&__f.__buf_;
2438 }
2439 else if (__f_ == (__base*)&__buf_)
2440 {
2441 __f_->__clone((__base*)&__f.__buf_);
2442 __f_->destroy();
2443 __f_ = __f.__f_;
2444 __f.__f_ = (__base*)&__f.__buf_;
2445 }
2446 else if (__f.__f_ == (__base*)&__f.__buf_)
2447 {
2448 __f.__f_->__clone((__base*)&__buf_);
2449 __f.__f_->destroy();
2450 __f.__f_ = __f_;
2451 __f_ = (__base*)&__buf_;
2452 }
2453 else
2454 _VSTDstd::__1::swap(__f_, __f.__f_);
2455}
2456
2457template<class _Rp, class _A0, class _A1>
2458_Rp
2459function<_Rp(_A0, _A1)>::operator()(_A0 __a0, _A1 __a1) const
2460{
2461 if (__f_ == 0)
2462 __throw_bad_function_call();
2463 return (*__f_)(__a0, __a1);
2464}
2465
2466#ifndef _LIBCPP_NO_RTTI
2467
2468template<class _Rp, class _A0, class _A1>
2469const std::type_info&
2470function<_Rp(_A0, _A1)>::target_type() const
2471{
2472 if (__f_ == 0)
2473 return typeid(void);
2474 return __f_->target_type();
2475}
2476
2477template<class _Rp, class _A0, class _A1>
2478template <typename _Tp>
2479_Tp*
2480function<_Rp(_A0, _A1)>::target()
2481{
2482 if (__f_ == 0)
2483 return (_Tp*)0;
2484 return (_Tp*) const_cast<void *>(__f_->target(typeid(_Tp)));
2485}
2486
2487template<class _Rp, class _A0, class _A1>
2488template <typename _Tp>
2489const _Tp*
2490function<_Rp(_A0, _A1)>::target() const
2491{
2492 if (__f_ == 0)
2493 return (const _Tp*)0;
2494 return (const _Tp*)__f_->target(typeid(_Tp));
2495}
2496
2497#endif // _LIBCPP_NO_RTTI
2498
2499template<class _Rp, class _A0, class _A1, class _A2>
2500class _LIBCPP_TEMPLATE_VIS__attribute__ ((__type_visibility__("default"))) function<_Rp(_A0, _A1, _A2)>
2501{
2502 typedef __function::__base<_Rp(_A0, _A1, _A2)> __base;
2503 aligned_storage<3*sizeof(void*)>::type __buf_;
2504 __base* __f_;
2505
2506public:
2507 typedef _Rp result_type;
2508
2509 // 20.7.16.2.1, construct/copy/destroy:
2510 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
explicit function() : __f_(0) {}
2511 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
function(nullptr_t) : __f_(0) {}
2512 function(const function&);
2513 template<class _Fp>
2514 function(_Fp,
2515 typename enable_if<!is_integral<_Fp>::value>::type* = 0);
2516
2517 template<class _Alloc>
2518 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
2519 function(allocator_arg_t, const _Alloc&) : __f_(0) {}
2520 template<class _Alloc>
2521 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
2522 function(allocator_arg_t, const _Alloc&, nullptr_t) : __f_(0) {}
2523 template<class _Alloc>
2524 function(allocator_arg_t, const _Alloc&, const function&);
2525 template<class _Fp, class _Alloc>
2526 function(allocator_arg_t, const _Alloc& __a, _Fp __f,
2527 typename enable_if<!is_integral<_Fp>::value>::type* = 0);
2528
2529 function& operator=(const function&);
2530 function& operator=(nullptr_t);
2531 template<class _Fp>
2532 typename enable_if
2533 <
2534 !is_integral<_Fp>::value,
2535 function&
2536 >::type
2537 operator=(_Fp);
2538
2539 ~function();
2540
2541 // 20.7.16.2.2, function modifiers:
2542 void swap(function&);
2543 template<class _Fp, class _Alloc>
2544 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
2545 void assign(_Fp __f, const _Alloc& __a)
2546 {function(allocator_arg, __a, __f).swap(*this);}
2547
2548 // 20.7.16.2.3, function capacity:
2549 _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
explicit operator bool() const {return __f_;}
2550
2551private:
2552 // deleted overloads close possible hole in the type system
2553 template<class _R2, class _B0, class _B1, class _B2>
2554 bool operator==(const function<_R2(_B0, _B1, _B2)>&) const;// = delete;
2555 template<class _R2, class _B0, class _B1, class _B2>
2556 bool operator!=(const function<_R2(_B0, _B1, _B2)>&) const;// = delete;
2557public:
2558 // 20.7.16.2.4, function invocation:
2559 _Rp operator()(_A0, _A1, _A2) const;
2560
2561#ifndef _LIBCPP_NO_RTTI
2562 // 20.7.16.2.5, function target access:
2563 const std::type_info& target_type() const;
2564 template <typename _Tp> _Tp* target();
2565 template <typename _Tp> const _Tp* target() const;
2566#endif // _LIBCPP_NO_RTTI
2567};
2568
2569template<class _Rp, class _A0, class _A1, class _A2>
2570function<_Rp(_A0, _A1, _A2)>::function(const function& __f)
2571{
2572 if (__f.__f_ == 0)
2573 __f_ = 0;
2574 else if (__f.__f_ == (const __base*)&__f.__buf_)
2575 {
2576 __f_ = (__base*)&__buf_;
2577 __f.__f_->__clone(__f_);
2578 }
2579 else
2580 __f_ = __f.__f_->__clone();
2581}
2582
2583template<class _Rp, class _A0, class _A1, class _A2>
2584template<class _Alloc>
2585function<_Rp(_A0, _A1, _A2)>::function(allocator_arg_t, const _Alloc&,
2586 const function& __f)
2587{
2588 if (__f.__f_ == 0)
2589 __f_ = 0;
2590 else if (__f.__f_ == (const __base*)&__f.__buf_)
2591 {
2592 __f_ = (__base*)&__buf_;
2593 __f.__f_->__clone(__f_);
2594 }
2595 else
2596 __f_ = __f.__f_->__clone();
2597}
2598
2599template<class _Rp, class _A0, class _A1, class _A2>
2600template <class _Fp>
2601function<_Rp(_A0, _A1, _A2)>::function(_Fp __f,
2602 typename enable_if<!is_integral<_Fp>::value>::type*)
2603 : __f_(0)
2604{
2605 if (__function::__not_null(__f))
2606 {
2607 typedef __function::__func<_Fp, allocator<_Fp>, _Rp(_A0, _A1, _A2)> _FF;
2608 if (sizeof(_FF) <= sizeof(__buf_))
2609 {
2610 __f_ = (__base*)&__buf_;
2611 ::new ((void*)__f_) _FF(__f);
2612 }
2613 else
2614 {
2615 typedef allocator<_FF> _Ap;
2616 _Ap __a;
2617 typedef __allocator_destructor<_Ap> _Dp;
2618 unique_ptr<__base, _Dp> __hold(__a.allocate(1), _Dp(__a, 1));
2619 ::new ((void*)__hold.get()) _FF(__f, allocator<_Fp>(__a));
2620 __f_ = __hold.release();
2621 }
2622 }
2623}
2624
2625template<class _Rp, class _A0, class _A1, class _A2>
2626template <class _Fp, class _Alloc>
2627function<_Rp(_A0, _A1, _A2)>::function(allocator_arg_t, const _Alloc& __a0, _Fp __f,
2628 typename enable_if<!is_integral<_Fp>::value>::type*)
2629 : __f_(0)
2630{
2631 typedef allocator_traits<_Alloc> __alloc_traits;
2632 if (__function::__not_null(__f))
2633 {
2634 typedef __function::__func<_Fp, _Alloc, _Rp(_A0, _A1, _A2)> _FF;
2635 if (sizeof(_FF) <= sizeof(__buf_))
2636 {
2637 __f_ = (__base*)&__buf_;
2638 ::new ((void*)__f_) _FF(__f, __a0);
2639 }
2640 else
2641 {
2642 typedef typename __rebind_alloc_helper<__alloc_traits, _FF>::type _Ap;
2643 _Ap __a(__a0);
2644 typedef __allocator_destructor<_Ap> _Dp;
2645 unique_ptr<__base, _Dp> __hold(__a.allocate(1), _Dp(__a, 1));
2646 ::new ((void*)__hold.get()) _FF(__f, _Alloc(__a));
2647 __f_ = __hold.release();
2648 }
2649 }
2650}
2651
2652template<class _Rp, class _A0, class _A1, class _A2>
2653function<_Rp(_A0, _A1, _A2)>&
2654function<_Rp(_A0, _A1, _A2)>::operator=(const function& __f)
2655{
2656 if (__f)
2657 function(__f).swap(*this);
2658 else
2659 *this = nullptr;
2660 return *this;
2661}
2662
2663template<class _Rp, class _A0, class _A1, class _A2>
2664function<_Rp(_A0, _A1, _A2)>&
2665function<_Rp(_A0, _A1, _A2)>::operator=(nullptr_t)
2666{
2667 __base* __t = __f_;
2668 __f_ = 0;
2669 if (__t == (__base*)&__buf_)
2670 __t->destroy();
2671 else if (__t)
2672 __t->destroy_deallocate();
2673 return *this;
2674}
2675
2676template<class _Rp, class _A0, class _A1, class _A2>
2677template <class _Fp>
2678typename enable_if
2679<
2680 !is_integral<_Fp>::value,
2681 function<_Rp(_A0, _A1, _A2)>&
2682>::type
2683function<_Rp(_A0, _A1, _A2)>::operator=(_Fp __f)
2684{
2685 function(_VSTDstd::__1::move(__f)).swap(*this);
2686 return *this;
2687}
2688
2689template<class _Rp, class _A0, class _A1, class _A2>
2690function<_Rp(_A0, _A1, _A2)>::~function()
2691{
2692 if (__f_ == (__base*)&__buf_)
2693 __f_->destroy();
2694 else if (__f_)
2695 __f_->destroy_deallocate();
2696}
2697
2698template<class _Rp, class _A0, class _A1, class _A2>
2699void
2700function<_Rp(_A0, _A1, _A2)>::swap(function& __f)
2701{
2702 if (_VSTDstd::__1::addressof(__f) == this)
2703 return;
2704 if (__f_ == (__base*)&__buf_ && __f.__f_ == (__base*)&__f.__buf_)
2705 {
2706 typename aligned_storage<sizeof(__buf_)>::type __tempbuf;
2707 __base* __t = (__base*)&__tempbuf;
2708 __f_->__clone(__t);
2709 __f_->destroy();
2710 __f_ = 0;
2711 __f.__f_->__clone((__base*)&__buf_);
2712 __f.__f_->destroy();
2713 __f.__f_ = 0;
2714 __f_ = (__base*)&__buf_;
2715 __t->__clone((__base*)&__f.__buf_);
2716 __t->destroy();
2717 __f.__f_ = (__base*)&__f.__buf_;
2718 }
2719 else if (__f_ == (__base*)&__buf_)
2720 {
2721 __f_->__clone((__base*)&__f.__buf_);
2722 __f_->destroy();
2723 __f_ = __f.__f_;
2724 __f.__f_ = (__base*)&__f.__buf_;
2725 }
2726 else if (__f.__f_ == (__base*)&__f.__buf_)
2727 {
2728 __f.__f_->__clone((__base*)&__buf_);
2729 __f.__f_->destroy();
2730 __f.__f_ = __f_;
2731 __f_ = (__base*)&__buf_;
2732 }
2733 else
2734 _VSTDstd::__1::swap(__f_, __f.__f_);
2735}
2736
2737template<class _Rp, class _A0, class _A1, class _A2>
2738_Rp
2739function<_Rp(_A0, _A1, _A2)>::operator()(_A0 __a0, _A1 __a1, _A2 __a2) const
2740{
2741 if (__f_ == 0)
2742 __throw_bad_function_call();
2743 return (*__f_)(__a0, __a1, __a2);
2744}
2745
2746#ifndef _LIBCPP_NO_RTTI
2747
2748template<class _Rp, class _A0, class _A1, class _A2>
2749const std::type_info&
2750function<_Rp(_A0, _A1, _A2)>::target_type() const
2751{
2752 if (__f_ == 0)
2753 return typeid(void);
2754 return __f_->target_type();
2755}
2756
2757template<class _Rp, class _A0, class _A1, class _A2>
2758template <typename _Tp>
2759_Tp*
2760function<_Rp(_A0, _A1, _A2)>::target()
2761{
2762 if (__f_ == 0)
2763 return (_Tp*)0;
2764 return (_Tp*) const_cast<void *>(__f_->target(typeid(_Tp)));
2765}
2766
2767template<class _Rp, class _A0, class _A1, class _A2>
2768template <typename _Tp>
2769const _Tp*
2770function<_Rp(_A0, _A1, _A2)>::target() const
2771{
2772 if (__f_ == 0)
2773 return (const _Tp*)0;
2774 return (const _Tp*)__f_->target(typeid(_Tp));
2775}
2776
2777#endif // _LIBCPP_NO_RTTI
2778
2779template <class _Fp>
2780inline _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
2781bool
2782operator==(const function<_Fp>& __f, nullptr_t) {return !__f;}
2783
2784template <class _Fp>
2785inline _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
2786bool
2787operator==(nullptr_t, const function<_Fp>& __f) {return !__f;}
2788
2789template <class _Fp>
2790inline _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
2791bool
2792operator!=(const function<_Fp>& __f, nullptr_t) {return (bool)__f;}
2793
2794template <class _Fp>
2795inline _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
2796bool
2797operator!=(nullptr_t, const function<_Fp>& __f) {return (bool)__f;}
2798
2799template <class _Fp>
2800inline _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__
))
2801void
2802swap(function<_Fp>& __x, function<_Fp>& __y)
2803{return __x.swap(__y);}
2804
2805#endif
2806
2807_LIBCPP_END_NAMESPACE_STD} }
2808
2809#endif // _LIBCPP___FUNCTIONAL_FUNCTION_H