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 |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
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 | |||||
65 | using namespace llvm; | ||||
66 | |||||
67 | #define DEBUG_TYPE"guard-widening" "guard-widening" | ||||
68 | |||||
69 | STATISTIC(GuardsEliminated, "Number of eliminated guards")static llvm::Statistic GuardsEliminated = {"guard-widening", "GuardsEliminated" , "Number of eliminated guards"}; | ||||
70 | STATISTIC(CondBranchEliminated, "Number of eliminated conditional branches")static llvm::Statistic CondBranchEliminated = {"guard-widening" , "CondBranchEliminated", "Number of eliminated conditional branches" }; | ||||
71 | |||||
72 | static 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 | |||||
78 | namespace { | ||||
79 | |||||
80 | // Get the condition of \p I. It can either be a guard or a conditional branch. | ||||
81 | static 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. | ||||
97 | static 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. | ||||
108 | static void eliminateGuard(Instruction *GuardInst) { | ||||
109 | GuardInst->eraseFromParent(); | ||||
110 | ++GuardsEliminated; | ||||
111 | } | ||||
112 | |||||
113 | class 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; | ||||
261 | |||||
262 | widenCondCommon(getCondition(ToWiden), NewCondition, ToWiden, Result, | ||||
263 | InvertCondition); | ||||
264 | if (isGuardAsWidenableBranch(ToWiden)) { | ||||
265 | setWidenableBranchCond(cast<BranchInst>(ToWiden), Result); | ||||
266 | return; | ||||
267 | } | ||||
268 | setCondition(ToWiden, Result); | ||||
269 | } | ||||
270 | |||||
271 | public: | ||||
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 | |||||
284 | static 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 | |||||
292 | bool GuardWideningImpl::run() { | ||||
293 | DenseMap<BasicBlock *, SmallVector<Instruction *, 8>> GuardsInBlock; | ||||
294 | bool Changed = false; | ||||
295 | for (auto DFI = df_begin(Root), DFE = df_end(Root); | ||||
296 | DFI != DFE; ++DFI) { | ||||
297 | auto *BB = (*DFI)->getBlock(); | ||||
298 | if (!BlockFilter(BB)) | ||||
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) | ||||
308 | Changed |= eliminateInstrViaWidening(II, DFI, GuardsInBlock); | ||||
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 | |||||
327 | bool 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))) | ||||
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) { | ||||
343 | auto *CurBB = DFSI.getPath(i)->getBlock(); | ||||
344 | if (!BlockFilter(CurBB)) | ||||
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) | ||||
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)) { | ||||
370 | auto Score = computeWideningScore(Instr, Candidate, InvertCondition); | ||||
371 | LLVM_DEBUG(dbgs() << "Score between " << *getCondition(Instr)do { } while (false) | ||||
372 | << " and " << *getCondition(Candidate) << " is "do { } while (false) | ||||
373 | << scoreTypeToString(Score) << "\n")do { } while (false); | ||||
374 | if (Score
| ||||
375 | BestScoreSoFar = Score; | ||||
376 | BestSoFar = Candidate; | ||||
377 | } | ||||
378 | } | ||||
379 | } | ||||
380 | |||||
381 | if (BestScoreSoFar
| ||||
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) | ||||
390 | << " with score " << scoreTypeToString(BestScoreSoFar)do { } while (false) | ||||
391 | << "\n")do { } while (false); | ||||
392 | widenGuard(BestSoFar, getCondition(Instr), InvertCondition); | ||||
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 | |||||
402 | GuardWideningImpl::WideningScore | ||||
403 | GuardWideningImpl::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 | |||||
461 | bool 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 | |||||
483 | void 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 | |||||
497 | bool 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))) && | ||||
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
| ||||
546 | parseRangeChecks(Cond0, Checks) && parseRangeChecks(Cond1, Checks) && | ||||
547 | combineRangeChecks(Checks, CombinedChecks)) { | ||||
548 | if (InsertPt
| ||||
549 | Result = nullptr; | ||||
550 | for (auto &RC : CombinedChecks) { | ||||
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"); | ||||
| |||||
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 | |||||
579 | bool 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 | |||||
651 | bool 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 | ||||
748 | StringRef 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 | |||||
764 | PreservedAnalyses 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 | |||||
778 | PreservedAnalyses 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 | |||||
794 | namespace { | ||||
795 | struct 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 | ||||
822 | struct 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)) | ||||
| |||||
831 | return false; | ||||
832 | auto &DT = getAnalysis<DominatorTreeWrapperPass>().getDomTree(); | ||||
833 | auto &LI = getAnalysis<LoopInfoWrapperPass>().getLoopInfo(); | ||||
834 | auto *PDTWP = getAnalysisIfAvailable<PostDominatorTreeWrapperPass>(); | ||||
835 | auto *PDT = PDTWP
| ||||
836 | BasicBlock *RootBB = L->getLoopPredecessor(); | ||||
837 | if (!RootBB) | ||||
838 | RootBB = L->getHeader(); | ||||
839 | auto BlockFilter = [&](BasicBlock *BB) { | ||||
840 | return BB == RootBB || L->contains(BB); | ||||
841 | }; | ||||
842 | return GuardWideningImpl(DT, PDT, LI, | ||||
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 | |||||
854 | char GuardWideningLegacyPass::ID = 0; | ||||
855 | char LoopGuardWideningLegacyPass::ID = 0; | ||||
856 | |||||
857 | INITIALIZE_PASS_BEGIN(GuardWideningLegacyPass, "guard-widening", "Widen guards",static void *initializeGuardWideningLegacyPassPassOnce(PassRegistry &Registry) { | ||||
858 | false, false)static void *initializeGuardWideningLegacyPassPassOnce(PassRegistry &Registry) { | ||||
859 | INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)initializeDominatorTreeWrapperPassPass(Registry); | ||||
860 | INITIALIZE_PASS_DEPENDENCY(PostDominatorTreeWrapperPass)initializePostDominatorTreeWrapperPassPass(Registry); | ||||
861 | INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass)initializeLoopInfoWrapperPassPass(Registry); | ||||
862 | INITIALIZE_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 | |||||
865 | INITIALIZE_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) { | ||||
868 | INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)initializeDominatorTreeWrapperPassPass(Registry); | ||||
869 | INITIALIZE_PASS_DEPENDENCY(PostDominatorTreeWrapperPass)initializePostDominatorTreeWrapperPassPass(Registry); | ||||
870 | INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass)initializeLoopInfoWrapperPassPass(Registry); | ||||
871 | INITIALIZE_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 | |||||
875 | FunctionPass *llvm::createGuardWideningPass() { | ||||
876 | return new GuardWideningLegacyPass(); | ||||
877 | } | ||||
878 | |||||
879 | Pass *llvm::createLoopGuardWideningPass() { | ||||
880 | return new LoopGuardWideningLegacyPass(); | ||||
881 | } |
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 | |
34 | class _LIBCPP_EXCEPTION_ABI__attribute__ ((__visibility__("default"))) bad_function_call |
35 | : public exception |
36 | { |
37 | #ifdef _LIBCPP_ABI_BAD_FUNCTION_CALL_KEY_FUNCTION |
38 | public: |
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__ )) |
46 | void __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 | |
62 | template<class _Fp> class _LIBCPP_DEPRECATED_CXX03_FUNCTION _LIBCPP_TEMPLATE_VIS__attribute__ ((__type_visibility__("default"))) function; // undefined |
63 | |
64 | namespace __function |
65 | { |
66 | |
67 | template<class _Rp> |
68 | struct __maybe_derive_from_unary_function |
69 | { |
70 | }; |
71 | |
72 | template<class _Rp, class _A1> |
73 | struct __maybe_derive_from_unary_function<_Rp(_A1)> |
74 | : public unary_function<_A1, _Rp> |
75 | { |
76 | }; |
77 | |
78 | template<class _Rp> |
79 | struct __maybe_derive_from_binary_function |
80 | { |
81 | }; |
82 | |
83 | template<class _Rp, class _A1, class _A2> |
84 | struct __maybe_derive_from_binary_function<_Rp(_A1, _A2)> |
85 | : public binary_function<_A1, _A2, _Rp> |
86 | { |
87 | }; |
88 | |
89 | template <class _Fp> |
90 | _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
91 | bool __not_null(_Fp const&) { return true; } |
92 | |
93 | template <class _Fp> |
94 | _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
95 | bool __not_null(_Fp* __ptr) { return __ptr; } |
96 | |
97 | template <class _Ret, class _Class> |
98 | _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
99 | bool __not_null(_Ret _Class::*__ptr) { return __ptr; } |
100 | |
101 | template <class _Fp> |
102 | _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
103 | bool __not_null(function<_Fp> const& __f) { return !!__f; } |
104 | |
105 | #ifdef _LIBCPP_HAS_EXTENSION_BLOCKS |
106 | template <class _Rp, class ..._Args> |
107 | _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
108 | bool __not_null(_Rp (^__p)(_Args...)) { return __p; } |
109 | #endif |
110 | |
111 | } // namespace __function |
112 | |
113 | #ifndef _LIBCPP_CXX03_LANG |
114 | |
115 | namespace __function { |
116 | |
117 | // __alloc_func holds a functor and an allocator. |
118 | |
119 | template <class _Fp, class _Ap, class _FB> class __alloc_func; |
120 | template <class _Fp, class _FB> |
121 | class __default_alloc_func; |
122 | |
123 | template <class _Fp, class _Ap, class _Rp, class... _ArgTypes> |
124 | class __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 | |
202 | template <class _Fp, class _Rp, class... _ArgTypes> |
203 | class __default_alloc_func<_Fp, _Rp(_ArgTypes...)> { |
204 | _Fp __f_; |
205 | |
206 | public: |
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 | |
245 | template<class _Fp> class _LIBCPP_TEMPLATE_VIS__attribute__ ((__type_visibility__("default"))) __base; |
246 | |
247 | template<class _Rp, class ..._ArgTypes> |
248 | class __base<_Rp(_ArgTypes...)> |
249 | { |
250 | __base(const __base&); |
251 | __base& operator=(const __base&); |
252 | public: |
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 | |
268 | template<class _FD, class _Alloc, class _FB> class __func; |
269 | |
270 | template<class _Fp, class _Alloc, class _Rp, class ..._ArgTypes> |
271 | class __func<_Fp, _Alloc, _Rp(_ArgTypes...)> |
272 | : public __base<_Rp(_ArgTypes...)> |
273 | { |
274 | __alloc_func<_Fp, _Alloc, _Rp(_ArgTypes...)> __f_; |
275 | public: |
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 | |
303 | template<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 | |
316 | template<class _Fp, class _Alloc, class _Rp, class ..._ArgTypes> |
317 | void |
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 | |
323 | template<class _Fp, class _Alloc, class _Rp, class ..._ArgTypes> |
324 | void |
325 | __func<_Fp, _Alloc, _Rp(_ArgTypes...)>::destroy() _NOEXCEPTnoexcept |
326 | { |
327 | __f_.destroy(); |
328 | } |
329 | |
330 | template<class _Fp, class _Alloc, class _Rp, class ..._ArgTypes> |
331 | void |
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 | |
341 | template<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 | |
350 | template<class _Fp, class _Alloc, class _Rp, class ..._ArgTypes> |
351 | const 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 | |
359 | template<class _Fp, class _Alloc, class _Rp, class ..._ArgTypes> |
360 | const 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 | |
370 | template <class _Fp> class __value_func; |
371 | |
372 | template <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) |
497 | __throw_bad_function_call(); |
498 | return (*__f_)(_VSTDstd::__1::forward<_ArgTypes>(__args)...); |
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. |
563 | union __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. |
570 | template <typename _Fun> |
571 | struct __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. |
580 | struct __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. |
658 | template <typename _Tp> |
659 | using __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 | |
664 | template <class _Fp> struct __policy_invoker; |
665 | |
666 | template <class _Rp, class... _ArgTypes> |
667 | struct __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 | |
709 | template <class _Fp> class __policy_func; |
710 | |
711 | template <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 | |
874 | extern "C" void *_Block_copy(const void *); |
875 | extern "C" void _Block_release(const void *); |
876 | |
877 | template<class _Rp1, class ..._ArgTypes1, class _Alloc, class _Rp, class ..._ArgTypes> |
878 | class __func<_Rp1(^)(_ArgTypes1...), _Alloc, _Rp(_ArgTypes...)> |
879 | : public __base<_Rp(_ArgTypes...)> |
880 | { |
881 | typedef _Rp1(^__block_type)(_ArgTypes1...); |
882 | __block_type __f_; |
883 | |
884 | public: |
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 | |
943 | template<class _Rp, class ..._ArgTypes> |
944 | class _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; |
978 | public: |
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; |
1035 | public: |
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 |
1048 | template<class _Rp, class ..._Ap> |
1049 | function(_Rp(*)(_Ap...)) -> function<_Rp(_Ap...)>; |
1050 | |
1051 | template<class _Fp> |
1052 | struct __strip_signature; |
1053 | |
1054 | template<class _Rp, class _Gp, class ..._Ap> |
1055 | struct __strip_signature<_Rp (_Gp::*) (_Ap...)> { using type = _Rp(_Ap...); }; |
1056 | template<class _Rp, class _Gp, class ..._Ap> |
1057 | struct __strip_signature<_Rp (_Gp::*) (_Ap...) const> { using type = _Rp(_Ap...); }; |
1058 | template<class _Rp, class _Gp, class ..._Ap> |
1059 | struct __strip_signature<_Rp (_Gp::*) (_Ap...) volatile> { using type = _Rp(_Ap...); }; |
1060 | template<class _Rp, class _Gp, class ..._Ap> |
1061 | struct __strip_signature<_Rp (_Gp::*) (_Ap...) const volatile> { using type = _Rp(_Ap...); }; |
1062 | |
1063 | template<class _Rp, class _Gp, class ..._Ap> |
1064 | struct __strip_signature<_Rp (_Gp::*) (_Ap...) &> { using type = _Rp(_Ap...); }; |
1065 | template<class _Rp, class _Gp, class ..._Ap> |
1066 | struct __strip_signature<_Rp (_Gp::*) (_Ap...) const &> { using type = _Rp(_Ap...); }; |
1067 | template<class _Rp, class _Gp, class ..._Ap> |
1068 | struct __strip_signature<_Rp (_Gp::*) (_Ap...) volatile &> { using type = _Rp(_Ap...); }; |
1069 | template<class _Rp, class _Gp, class ..._Ap> |
1070 | struct __strip_signature<_Rp (_Gp::*) (_Ap...) const volatile &> { using type = _Rp(_Ap...); }; |
1071 | |
1072 | template<class _Rp, class _Gp, class ..._Ap> |
1073 | struct __strip_signature<_Rp (_Gp::*) (_Ap...) noexcept> { using type = _Rp(_Ap...); }; |
1074 | template<class _Rp, class _Gp, class ..._Ap> |
1075 | struct __strip_signature<_Rp (_Gp::*) (_Ap...) const noexcept> { using type = _Rp(_Ap...); }; |
1076 | template<class _Rp, class _Gp, class ..._Ap> |
1077 | struct __strip_signature<_Rp (_Gp::*) (_Ap...) volatile noexcept> { using type = _Rp(_Ap...); }; |
1078 | template<class _Rp, class _Gp, class ..._Ap> |
1079 | struct __strip_signature<_Rp (_Gp::*) (_Ap...) const volatile noexcept> { using type = _Rp(_Ap...); }; |
1080 | |
1081 | template<class _Rp, class _Gp, class ..._Ap> |
1082 | struct __strip_signature<_Rp (_Gp::*) (_Ap...) & noexcept> { using type = _Rp(_Ap...); }; |
1083 | template<class _Rp, class _Gp, class ..._Ap> |
1084 | struct __strip_signature<_Rp (_Gp::*) (_Ap...) const & noexcept> { using type = _Rp(_Ap...); }; |
1085 | template<class _Rp, class _Gp, class ..._Ap> |
1086 | struct __strip_signature<_Rp (_Gp::*) (_Ap...) volatile & noexcept> { using type = _Rp(_Ap...); }; |
1087 | template<class _Rp, class _Gp, class ..._Ap> |
1088 | struct __strip_signature<_Rp (_Gp::*) (_Ap...) const volatile & noexcept> { using type = _Rp(_Ap...); }; |
1089 | |
1090 | template<class _Fp, class _Stripped = typename __strip_signature<decltype(&_Fp::operator())>::type> |
1091 | function(_Fp) -> function<_Stripped>; |
1092 | #endif // !_LIBCPP_HAS_NO_DEDUCTION_GUIDES |
1093 | |
1094 | template<class _Rp, class ..._ArgTypes> |
1095 | function<_Rp(_ArgTypes...)>::function(const function& __f) : __f_(__f.__f_) {} |
1096 | |
1097 | #if _LIBCPP_STD_VER14 <= 14 |
1098 | template<class _Rp, class ..._ArgTypes> |
1099 | template <class _Alloc> |
1100 | function<_Rp(_ArgTypes...)>::function(allocator_arg_t, const _Alloc&, |
1101 | const function& __f) : __f_(__f.__f_) {} |
1102 | #endif |
1103 | |
1104 | template <class _Rp, class... _ArgTypes> |
1105 | function<_Rp(_ArgTypes...)>::function(function&& __f) _NOEXCEPTnoexcept |
1106 | : __f_(_VSTDstd::__1::move(__f.__f_)) {} |
1107 | |
1108 | #if _LIBCPP_STD_VER14 <= 14 |
1109 | template<class _Rp, class ..._ArgTypes> |
1110 | template <class _Alloc> |
1111 | function<_Rp(_ArgTypes...)>::function(allocator_arg_t, const _Alloc&, |
1112 | function&& __f) |
1113 | : __f_(_VSTDstd::__1::move(__f.__f_)) {} |
1114 | #endif |
1115 | |
1116 | template <class _Rp, class... _ArgTypes> |
1117 | template <class _Fp, class> |
1118 | function<_Rp(_ArgTypes...)>::function(_Fp __f) : __f_(_VSTDstd::__1::move(__f)) {} |
1119 | |
1120 | #if _LIBCPP_STD_VER14 <= 14 |
1121 | template <class _Rp, class... _ArgTypes> |
1122 | template <class _Fp, class _Alloc, class> |
1123 | function<_Rp(_ArgTypes...)>::function(allocator_arg_t, const _Alloc& __a, |
1124 | _Fp __f) |
1125 | : __f_(_VSTDstd::__1::move(__f), __a) {} |
1126 | #endif |
1127 | |
1128 | template<class _Rp, class ..._ArgTypes> |
1129 | function<_Rp(_ArgTypes...)>& |
1130 | function<_Rp(_ArgTypes...)>::operator=(const function& __f) |
1131 | { |
1132 | function(__f).swap(*this); |
1133 | return *this; |
1134 | } |
1135 | |
1136 | template<class _Rp, class ..._ArgTypes> |
1137 | function<_Rp(_ArgTypes...)>& |
1138 | function<_Rp(_ArgTypes...)>::operator=(function&& __f) _NOEXCEPTnoexcept |
1139 | { |
1140 | __f_ = _VSTDstd::__1::move(__f.__f_); |
1141 | return *this; |
1142 | } |
1143 | |
1144 | template<class _Rp, class ..._ArgTypes> |
1145 | function<_Rp(_ArgTypes...)>& |
1146 | function<_Rp(_ArgTypes...)>::operator=(nullptr_t) _NOEXCEPTnoexcept |
1147 | { |
1148 | __f_ = nullptr; |
1149 | return *this; |
1150 | } |
1151 | |
1152 | template<class _Rp, class ..._ArgTypes> |
1153 | template <class _Fp, class> |
1154 | function<_Rp(_ArgTypes...)>& |
1155 | function<_Rp(_ArgTypes...)>::operator=(_Fp&& __f) |
1156 | { |
1157 | function(_VSTDstd::__1::forward<_Fp>(__f)).swap(*this); |
1158 | return *this; |
1159 | } |
1160 | |
1161 | template<class _Rp, class ..._ArgTypes> |
1162 | function<_Rp(_ArgTypes...)>::~function() {} |
1163 | |
1164 | template<class _Rp, class ..._ArgTypes> |
1165 | void |
1166 | function<_Rp(_ArgTypes...)>::swap(function& __f) _NOEXCEPTnoexcept |
1167 | { |
1168 | __f_.swap(__f.__f_); |
1169 | } |
1170 | |
1171 | template<class _Rp, class ..._ArgTypes> |
1172 | _Rp |
1173 | function<_Rp(_ArgTypes...)>::operator()(_ArgTypes... __arg) const |
1174 | { |
1175 | return __f_(_VSTDstd::__1::forward<_ArgTypes>(__arg)...); |
1176 | } |
1177 | |
1178 | #ifndef _LIBCPP_NO_RTTI |
1179 | |
1180 | template<class _Rp, class ..._ArgTypes> |
1181 | const std::type_info& |
1182 | function<_Rp(_ArgTypes...)>::target_type() const _NOEXCEPTnoexcept |
1183 | { |
1184 | return __f_.target_type(); |
1185 | } |
1186 | |
1187 | template<class _Rp, class ..._ArgTypes> |
1188 | template <typename _Tp> |
1189 | _Tp* |
1190 | function<_Rp(_ArgTypes...)>::target() _NOEXCEPTnoexcept |
1191 | { |
1192 | return (_Tp*)(__f_.template target<_Tp>()); |
1193 | } |
1194 | |
1195 | template<class _Rp, class ..._ArgTypes> |
1196 | template <typename _Tp> |
1197 | const _Tp* |
1198 | function<_Rp(_ArgTypes...)>::target() const _NOEXCEPTnoexcept |
1199 | { |
1200 | return __f_.template target<_Tp>(); |
1201 | } |
1202 | |
1203 | #endif // _LIBCPP_NO_RTTI |
1204 | |
1205 | template <class _Rp, class... _ArgTypes> |
1206 | inline _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
1207 | bool |
1208 | operator==(const function<_Rp(_ArgTypes...)>& __f, nullptr_t) _NOEXCEPTnoexcept {return !__f;} |
1209 | |
1210 | template <class _Rp, class... _ArgTypes> |
1211 | inline _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
1212 | bool |
1213 | operator==(nullptr_t, const function<_Rp(_ArgTypes...)>& __f) _NOEXCEPTnoexcept {return !__f;} |
1214 | |
1215 | template <class _Rp, class... _ArgTypes> |
1216 | inline _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
1217 | bool |
1218 | operator!=(const function<_Rp(_ArgTypes...)>& __f, nullptr_t) _NOEXCEPTnoexcept {return (bool)__f;} |
1219 | |
1220 | template <class _Rp, class... _ArgTypes> |
1221 | inline _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
1222 | bool |
1223 | operator!=(nullptr_t, const function<_Rp(_ArgTypes...)>& __f) _NOEXCEPTnoexcept {return (bool)__f;} |
1224 | |
1225 | template <class _Rp, class... _ArgTypes> |
1226 | inline _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
1227 | void |
1228 | swap(function<_Rp(_ArgTypes...)>& __x, function<_Rp(_ArgTypes...)>& __y) _NOEXCEPTnoexcept |
1229 | {return __x.swap(__y);} |
1230 | |
1231 | #else // _LIBCPP_CXX03_LANG |
1232 | |
1233 | namespace __function { |
1234 | |
1235 | template<class _Fp> class __base; |
1236 | |
1237 | template<class _Rp> |
1238 | class __base<_Rp()> |
1239 | { |
1240 | __base(const __base&); |
1241 | __base& operator=(const __base&); |
1242 | public: |
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 | |
1256 | template<class _Rp, class _A0> |
1257 | class __base<_Rp(_A0)> |
1258 | { |
1259 | __base(const __base&); |
1260 | __base& operator=(const __base&); |
1261 | public: |
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 | |
1275 | template<class _Rp, class _A0, class _A1> |
1276 | class __base<_Rp(_A0, _A1)> |
1277 | { |
1278 | __base(const __base&); |
1279 | __base& operator=(const __base&); |
1280 | public: |
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 | |
1294 | template<class _Rp, class _A0, class _A1, class _A2> |
1295 | class __base<_Rp(_A0, _A1, _A2)> |
1296 | { |
1297 | __base(const __base&); |
1298 | __base& operator=(const __base&); |
1299 | public: |
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 | |
1313 | template<class _FD, class _Alloc, class _FB> class __func; |
1314 | |
1315 | template<class _Fp, class _Alloc, class _Rp> |
1316 | class __func<_Fp, _Alloc, _Rp()> |
1317 | : public __base<_Rp()> |
1318 | { |
1319 | __compressed_pair<_Fp, _Alloc> __f_; |
1320 | public: |
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 | |
1334 | template<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 | |
1347 | template<class _Fp, class _Alloc, class _Rp> |
1348 | void |
1349 | __func<_Fp, _Alloc, _Rp()>::__clone(__base<_Rp()>* __p) const |
1350 | { |
1351 | ::new ((void*)__p) __func(__f_.first(), __f_.second()); |
1352 | } |
1353 | |
1354 | template<class _Fp, class _Alloc, class _Rp> |
1355 | void |
1356 | __func<_Fp, _Alloc, _Rp()>::destroy() |
1357 | { |
1358 | __f_.~__compressed_pair<_Fp, _Alloc>(); |
1359 | } |
1360 | |
1361 | template<class _Fp, class _Alloc, class _Rp> |
1362 | void |
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 | |
1372 | template<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 | |
1382 | template<class _Fp, class _Alloc, class _Rp> |
1383 | const 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 | |
1391 | template<class _Fp, class _Alloc, class _Rp> |
1392 | const std::type_info& |
1393 | __func<_Fp, _Alloc, _Rp()>::target_type() const |
1394 | { |
1395 | return typeid(_Fp); |
1396 | } |
1397 | |
1398 | #endif // _LIBCPP_NO_RTTI |
1399 | |
1400 | template<class _Fp, class _Alloc, class _Rp, class _A0> |
1401 | class __func<_Fp, _Alloc, _Rp(_A0)> |
1402 | : public __base<_Rp(_A0)> |
1403 | { |
1404 | __compressed_pair<_Fp, _Alloc> __f_; |
1405 | public: |
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 | |
1420 | template<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 | |
1433 | template<class _Fp, class _Alloc, class _Rp, class _A0> |
1434 | void |
1435 | __func<_Fp, _Alloc, _Rp(_A0)>::__clone(__base<_Rp(_A0)>* __p) const |
1436 | { |
1437 | ::new ((void*)__p) __func(__f_.first(), __f_.second()); |
1438 | } |
1439 | |
1440 | template<class _Fp, class _Alloc, class _Rp, class _A0> |
1441 | void |
1442 | __func<_Fp, _Alloc, _Rp(_A0)>::destroy() |
1443 | { |
1444 | __f_.~__compressed_pair<_Fp, _Alloc>(); |
1445 | } |
1446 | |
1447 | template<class _Fp, class _Alloc, class _Rp, class _A0> |
1448 | void |
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 | |
1458 | template<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 | |
1468 | template<class _Fp, class _Alloc, class _Rp, class _A0> |
1469 | const 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 | |
1477 | template<class _Fp, class _Alloc, class _Rp, class _A0> |
1478 | const 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 | |
1486 | template<class _Fp, class _Alloc, class _Rp, class _A0, class _A1> |
1487 | class __func<_Fp, _Alloc, _Rp(_A0, _A1)> |
1488 | : public __base<_Rp(_A0, _A1)> |
1489 | { |
1490 | __compressed_pair<_Fp, _Alloc> __f_; |
1491 | public: |
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 | |
1506 | template<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 | |
1519 | template<class _Fp, class _Alloc, class _Rp, class _A0, class _A1> |
1520 | void |
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 | |
1526 | template<class _Fp, class _Alloc, class _Rp, class _A0, class _A1> |
1527 | void |
1528 | __func<_Fp, _Alloc, _Rp(_A0, _A1)>::destroy() |
1529 | { |
1530 | __f_.~__compressed_pair<_Fp, _Alloc>(); |
1531 | } |
1532 | |
1533 | template<class _Fp, class _Alloc, class _Rp, class _A0, class _A1> |
1534 | void |
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 | |
1544 | template<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 | |
1554 | template<class _Fp, class _Alloc, class _Rp, class _A0, class _A1> |
1555 | const 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 | |
1563 | template<class _Fp, class _Alloc, class _Rp, class _A0, class _A1> |
1564 | const 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 | |
1572 | template<class _Fp, class _Alloc, class _Rp, class _A0, class _A1, class _A2> |
1573 | class __func<_Fp, _Alloc, _Rp(_A0, _A1, _A2)> |
1574 | : public __base<_Rp(_A0, _A1, _A2)> |
1575 | { |
1576 | __compressed_pair<_Fp, _Alloc> __f_; |
1577 | public: |
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 | |
1592 | template<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 | |
1605 | template<class _Fp, class _Alloc, class _Rp, class _A0, class _A1, class _A2> |
1606 | void |
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 | |
1612 | template<class _Fp, class _Alloc, class _Rp, class _A0, class _A1, class _A2> |
1613 | void |
1614 | __func<_Fp, _Alloc, _Rp(_A0, _A1, _A2)>::destroy() |
1615 | { |
1616 | __f_.~__compressed_pair<_Fp, _Alloc>(); |
1617 | } |
1618 | |
1619 | template<class _Fp, class _Alloc, class _Rp, class _A0, class _A1, class _A2> |
1620 | void |
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 | |
1630 | template<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 | |
1640 | template<class _Fp, class _Alloc, class _Rp, class _A0, class _A1, class _A2> |
1641 | const 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 | |
1649 | template<class _Fp, class _Alloc, class _Rp, class _A0, class _A1, class _A2> |
1650 | const 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 | |
1660 | template<class _Rp> |
1661 | class _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 | |
1667 | public: |
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 | |
1712 | private: |
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; |
1718 | public: |
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 | |
1730 | template<class _Rp> |
1731 | function<_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 | |
1744 | template<class _Rp> |
1745 | template<class _Alloc> |
1746 | function<_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 | |
1759 | template<class _Rp> |
1760 | template <class _Fp> |
1761 | function<_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 | |
1785 | template<class _Rp> |
1786 | template <class _Fp, class _Alloc> |
1787 | function<_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 | |
1812 | template<class _Rp> |
1813 | function<_Rp()>& |
1814 | function<_Rp()>::operator=(const function& __f) |
1815 | { |
1816 | if (__f) |
1817 | function(__f).swap(*this); |
1818 | else |
1819 | *this = nullptr; |
1820 | return *this; |
1821 | } |
1822 | |
1823 | template<class _Rp> |
1824 | function<_Rp()>& |
1825 | function<_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 | |
1836 | template<class _Rp> |
1837 | template <class _Fp> |
1838 | typename enable_if |
1839 | < |
1840 | !is_integral<_Fp>::value, |
1841 | function<_Rp()>& |
1842 | >::type |
1843 | function<_Rp()>::operator=(_Fp __f) |
1844 | { |
1845 | function(_VSTDstd::__1::move(__f)).swap(*this); |
1846 | return *this; |
1847 | } |
1848 | |
1849 | template<class _Rp> |
1850 | function<_Rp()>::~function() |
1851 | { |
1852 | if (__f_ == (__base*)&__buf_) |
1853 | __f_->destroy(); |
1854 | else if (__f_) |
1855 | __f_->destroy_deallocate(); |
1856 | } |
1857 | |
1858 | template<class _Rp> |
1859 | void |
1860 | function<_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 | |
1897 | template<class _Rp> |
1898 | _Rp |
1899 | function<_Rp()>::operator()() const |
1900 | { |
1901 | if (__f_ == 0) |
1902 | __throw_bad_function_call(); |
1903 | return (*__f_)(); |
1904 | } |
1905 | |
1906 | #ifndef _LIBCPP_NO_RTTI |
1907 | |
1908 | template<class _Rp> |
1909 | const std::type_info& |
1910 | function<_Rp()>::target_type() const |
1911 | { |
1912 | if (__f_ == 0) |
1913 | return typeid(void); |
1914 | return __f_->target_type(); |
1915 | } |
1916 | |
1917 | template<class _Rp> |
1918 | template <typename _Tp> |
1919 | _Tp* |
1920 | function<_Rp()>::target() |
1921 | { |
1922 | if (__f_ == 0) |
1923 | return (_Tp*)0; |
1924 | return (_Tp*) const_cast<void *>(__f_->target(typeid(_Tp))); |
1925 | } |
1926 | |
1927 | template<class _Rp> |
1928 | template <typename _Tp> |
1929 | const _Tp* |
1930 | function<_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 | |
1939 | template<class _Rp, class _A0> |
1940 | class _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 | |
1947 | public: |
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 | |
1992 | private: |
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; |
1998 | public: |
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 | |
2010 | template<class _Rp, class _A0> |
2011 | function<_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 | |
2024 | template<class _Rp, class _A0> |
2025 | template<class _Alloc> |
2026 | function<_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 | |
2039 | template<class _Rp, class _A0> |
2040 | template <class _Fp> |
2041 | function<_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 | |
2065 | template<class _Rp, class _A0> |
2066 | template <class _Fp, class _Alloc> |
2067 | function<_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 | |
2092 | template<class _Rp, class _A0> |
2093 | function<_Rp(_A0)>& |
2094 | function<_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 | |
2103 | template<class _Rp, class _A0> |
2104 | function<_Rp(_A0)>& |
2105 | function<_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 | |
2116 | template<class _Rp, class _A0> |
2117 | template <class _Fp> |
2118 | typename enable_if |
2119 | < |
2120 | !is_integral<_Fp>::value, |
2121 | function<_Rp(_A0)>& |
2122 | >::type |
2123 | function<_Rp(_A0)>::operator=(_Fp __f) |
2124 | { |
2125 | function(_VSTDstd::__1::move(__f)).swap(*this); |
2126 | return *this; |
2127 | } |
2128 | |
2129 | template<class _Rp, class _A0> |
2130 | function<_Rp(_A0)>::~function() |
2131 | { |
2132 | if (__f_ == (__base*)&__buf_) |
2133 | __f_->destroy(); |
2134 | else if (__f_) |
2135 | __f_->destroy_deallocate(); |
2136 | } |
2137 | |
2138 | template<class _Rp, class _A0> |
2139 | void |
2140 | function<_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 | |
2177 | template<class _Rp, class _A0> |
2178 | _Rp |
2179 | function<_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 | |
2188 | template<class _Rp, class _A0> |
2189 | const std::type_info& |
2190 | function<_Rp(_A0)>::target_type() const |
2191 | { |
2192 | if (__f_ == 0) |
2193 | return typeid(void); |
2194 | return __f_->target_type(); |
2195 | } |
2196 | |
2197 | template<class _Rp, class _A0> |
2198 | template <typename _Tp> |
2199 | _Tp* |
2200 | function<_Rp(_A0)>::target() |
2201 | { |
2202 | if (__f_ == 0) |
2203 | return (_Tp*)0; |
2204 | return (_Tp*) const_cast<void *>(__f_->target(typeid(_Tp))); |
2205 | } |
2206 | |
2207 | template<class _Rp, class _A0> |
2208 | template <typename _Tp> |
2209 | const _Tp* |
2210 | function<_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 | |
2219 | template<class _Rp, class _A0, class _A1> |
2220 | class _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 | |
2227 | public: |
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 | |
2272 | private: |
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; |
2278 | public: |
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 | |
2290 | template<class _Rp, class _A0, class _A1> |
2291 | function<_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 | |
2304 | template<class _Rp, class _A0, class _A1> |
2305 | template<class _Alloc> |
2306 | function<_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 | |
2319 | template<class _Rp, class _A0, class _A1> |
2320 | template <class _Fp> |
2321 | function<_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 | |
2345 | template<class _Rp, class _A0, class _A1> |
2346 | template <class _Fp, class _Alloc> |
2347 | function<_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 | |
2372 | template<class _Rp, class _A0, class _A1> |
2373 | function<_Rp(_A0, _A1)>& |
2374 | function<_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 | |
2383 | template<class _Rp, class _A0, class _A1> |
2384 | function<_Rp(_A0, _A1)>& |
2385 | function<_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 | |
2396 | template<class _Rp, class _A0, class _A1> |
2397 | template <class _Fp> |
2398 | typename enable_if |
2399 | < |
2400 | !is_integral<_Fp>::value, |
2401 | function<_Rp(_A0, _A1)>& |
2402 | >::type |
2403 | function<_Rp(_A0, _A1)>::operator=(_Fp __f) |
2404 | { |
2405 | function(_VSTDstd::__1::move(__f)).swap(*this); |
2406 | return *this; |
2407 | } |
2408 | |
2409 | template<class _Rp, class _A0, class _A1> |
2410 | function<_Rp(_A0, _A1)>::~function() |
2411 | { |
2412 | if (__f_ == (__base*)&__buf_) |
2413 | __f_->destroy(); |
2414 | else if (__f_) |
2415 | __f_->destroy_deallocate(); |
2416 | } |
2417 | |
2418 | template<class _Rp, class _A0, class _A1> |
2419 | void |
2420 | function<_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 | |
2457 | template<class _Rp, class _A0, class _A1> |
2458 | _Rp |
2459 | function<_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 | |
2468 | template<class _Rp, class _A0, class _A1> |
2469 | const std::type_info& |
2470 | function<_Rp(_A0, _A1)>::target_type() const |
2471 | { |
2472 | if (__f_ == 0) |
2473 | return typeid(void); |
2474 | return __f_->target_type(); |
2475 | } |
2476 | |
2477 | template<class _Rp, class _A0, class _A1> |
2478 | template <typename _Tp> |
2479 | _Tp* |
2480 | function<_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 | |
2487 | template<class _Rp, class _A0, class _A1> |
2488 | template <typename _Tp> |
2489 | const _Tp* |
2490 | function<_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 | |
2499 | template<class _Rp, class _A0, class _A1, class _A2> |
2500 | class _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 | |
2506 | public: |
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 | |
2551 | private: |
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; |
2557 | public: |
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 | |
2569 | template<class _Rp, class _A0, class _A1, class _A2> |
2570 | function<_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 | |
2583 | template<class _Rp, class _A0, class _A1, class _A2> |
2584 | template<class _Alloc> |
2585 | function<_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 | |
2599 | template<class _Rp, class _A0, class _A1, class _A2> |
2600 | template <class _Fp> |
2601 | function<_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 | |
2625 | template<class _Rp, class _A0, class _A1, class _A2> |
2626 | template <class _Fp, class _Alloc> |
2627 | function<_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 | |
2652 | template<class _Rp, class _A0, class _A1, class _A2> |
2653 | function<_Rp(_A0, _A1, _A2)>& |
2654 | function<_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 | |
2663 | template<class _Rp, class _A0, class _A1, class _A2> |
2664 | function<_Rp(_A0, _A1, _A2)>& |
2665 | function<_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 | |
2676 | template<class _Rp, class _A0, class _A1, class _A2> |
2677 | template <class _Fp> |
2678 | typename enable_if |
2679 | < |
2680 | !is_integral<_Fp>::value, |
2681 | function<_Rp(_A0, _A1, _A2)>& |
2682 | >::type |
2683 | function<_Rp(_A0, _A1, _A2)>::operator=(_Fp __f) |
2684 | { |
2685 | function(_VSTDstd::__1::move(__f)).swap(*this); |
2686 | return *this; |
2687 | } |
2688 | |
2689 | template<class _Rp, class _A0, class _A1, class _A2> |
2690 | function<_Rp(_A0, _A1, _A2)>::~function() |
2691 | { |
2692 | if (__f_ == (__base*)&__buf_) |
2693 | __f_->destroy(); |
2694 | else if (__f_) |
2695 | __f_->destroy_deallocate(); |
2696 | } |
2697 | |
2698 | template<class _Rp, class _A0, class _A1, class _A2> |
2699 | void |
2700 | function<_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 | |
2737 | template<class _Rp, class _A0, class _A1, class _A2> |
2738 | _Rp |
2739 | function<_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 | |
2748 | template<class _Rp, class _A0, class _A1, class _A2> |
2749 | const std::type_info& |
2750 | function<_Rp(_A0, _A1, _A2)>::target_type() const |
2751 | { |
2752 | if (__f_ == 0) |
2753 | return typeid(void); |
2754 | return __f_->target_type(); |
2755 | } |
2756 | |
2757 | template<class _Rp, class _A0, class _A1, class _A2> |
2758 | template <typename _Tp> |
2759 | _Tp* |
2760 | function<_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 | |
2767 | template<class _Rp, class _A0, class _A1, class _A2> |
2768 | template <typename _Tp> |
2769 | const _Tp* |
2770 | function<_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 | |
2779 | template <class _Fp> |
2780 | inline _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
2781 | bool |
2782 | operator==(const function<_Fp>& __f, nullptr_t) {return !__f;} |
2783 | |
2784 | template <class _Fp> |
2785 | inline _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
2786 | bool |
2787 | operator==(nullptr_t, const function<_Fp>& __f) {return !__f;} |
2788 | |
2789 | template <class _Fp> |
2790 | inline _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
2791 | bool |
2792 | operator!=(const function<_Fp>& __f, nullptr_t) {return (bool)__f;} |
2793 | |
2794 | template <class _Fp> |
2795 | inline _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
2796 | bool |
2797 | operator!=(nullptr_t, const function<_Fp>& __f) {return (bool)__f;} |
2798 | |
2799 | template <class _Fp> |
2800 | inline _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
2801 | void |
2802 | swap(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 |