LLVM 23.0.0git
ValueHandle.h
Go to the documentation of this file.
1//===- ValueHandle.h - Value Smart Pointer classes --------------*- C++ -*-===//
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 declares the ValueHandle class and its sub-classes.
10//
11//===----------------------------------------------------------------------===//
12
13#ifndef LLVM_IR_VALUEHANDLE_H
14#define LLVM_IR_VALUEHANDLE_H
15
18#include "llvm/IR/Value.h"
21#include <cassert>
22
23namespace llvm {
24
25/// This is the common base class of value handles.
26///
27/// ValueHandle's are smart pointers to Value's that have special behavior when
28/// the value is deleted or ReplaceAllUsesWith'd. See the specific handles
29/// below for details.
31 friend class Value;
32
33protected:
34 /// This indicates what sub class the handle actually is.
35 ///
36 /// This is to avoid having a vtable for the light-weight handle pointers. The
37 /// fully general Callback version does have a vtable.
39
41 : ValueHandleBase(RHS.PrevPair.getInt(), RHS) {}
42
44 : PrevPair(nullptr, Kind), Val(RHS.getValPtr()) {
45 if (isValid(getValPtr()))
46 AddToExistingUseList(RHS.getPrevPtr());
47 }
48
50 : PrevPair(nullptr, Kind), Val(RHS.getValPtr()) {
51 if (isValid(getValPtr())) {
52 AddToExistingUseList(RHS.getPrevPtr());
53 RHS.RemoveFromUseList();
54 RHS.clearValPtr();
55 }
56 }
57
58private:
60 ValueHandleBase *Next = nullptr;
61 Value *Val = nullptr;
62
63 void setValPtr(Value *V) { Val = V; }
64
65public:
67 : PrevPair(nullptr, Kind) {}
69 : PrevPair(nullptr, Kind), Val(V) {
70 if (isValid(getValPtr()))
71 AddToUseList();
72 }
73
78
80 if (getValPtr() == RHS)
81 return RHS;
82 if (isValid(getValPtr()))
84 setValPtr(RHS);
85 if (isValid(getValPtr()))
86 AddToUseList();
87 return RHS;
88 }
89
91 if (getValPtr() == RHS.getValPtr())
92 return RHS.getValPtr();
93 if (isValid(getValPtr()))
95 setValPtr(RHS.getValPtr());
96 if (isValid(getValPtr()))
97 AddToExistingUseList(RHS.getPrevPtr());
98 return getValPtr();
99 }
100
102 if (getValPtr() == RHS.getValPtr()) {
103 if (this != &RHS) {
104 if (isValid(RHS.getValPtr()))
105 RHS.RemoveFromUseList();
106 RHS.clearValPtr();
107 }
108 return getValPtr();
109 }
110 if (isValid(getValPtr()))
112 setValPtr(RHS.getValPtr());
113 if (isValid(getValPtr())) {
114 AddToExistingUseList(RHS.getPrevPtr());
115 RHS.RemoveFromUseList();
116 RHS.clearValPtr();
117 }
118 return getValPtr();
119 }
120
121 Value *operator->() const { return getValPtr(); }
122 Value &operator*() const {
123 Value *V = getValPtr();
124 assert(V && "Dereferencing deleted ValueHandle");
125 return *V;
126 }
127
128protected:
129 Value *getValPtr() const { return Val; }
130
131 static bool isValid(Value *V) {
132 return V &&
135 }
136
137 /// Remove this ValueHandle from its current use list.
139
140 /// Clear the underlying pointer without clearing the use list.
141 ///
142 /// This should only be used if a derived class has manually removed the
143 /// handle from the use list.
144 void clearValPtr() { setValPtr(nullptr); }
145
146public:
147 // Callbacks made from Value.
148 LLVM_ABI static void ValueIsDeleted(Value *V);
149 LLVM_ABI static void ValueIsRAUWd(Value *Old, Value *New);
150
151private:
152 // Internal implementation details.
153 ValueHandleBase **getPrevPtr() const { return PrevPair.getPointer(); }
154 HandleBaseKind getKind() const { return PrevPair.getInt(); }
155 void setPrevPtr(ValueHandleBase **Ptr) { PrevPair.setPointer(Ptr); }
156
157 /// Add this ValueHandle to the use list for V.
158 ///
159 /// List is the address of either the head of the list or a Next node within
160 /// the existing use list.
161 LLVM_ABI void AddToExistingUseList(ValueHandleBase **List);
162
163 /// Add this ValueHandle to the use list after Node.
164 void AddToExistingUseListAfter(ValueHandleBase *Node);
165
166 /// Add this ValueHandle to the use list for V.
167 LLVM_ABI void AddToUseList();
168};
169
170/// A nullable Value handle that is nullable.
171///
172/// This is a value handle that points to a value, and nulls itself
173/// out if that value is deleted.
174class WeakVH : public ValueHandleBase {
175public:
180
181 WeakVH &operator=(const WeakVH &RHS) = default;
182
189
190 operator Value*() const {
191 return getValPtr();
192 }
193};
194
195// Specialize simplify_type to allow WeakVH to participate in
196// dyn_cast, isa, etc.
197template <> struct simplify_type<WeakVH> {
198 using SimpleType = Value *;
199
200 static SimpleType getSimplifiedValue(WeakVH &WVH) { return WVH; }
201};
202template <> struct simplify_type<const WeakVH> {
203 using SimpleType = Value *;
204
205 static SimpleType getSimplifiedValue(const WeakVH &WVH) { return WVH; }
206};
207
208// Specialize DenseMapInfo to allow WeakVH to participate in DenseMap.
209template <> struct DenseMapInfo<WeakVH> {
210 static inline WeakVH getEmptyKey() {
212 }
213
217
218 static unsigned getHashValue(const WeakVH &Val) {
220 }
221
222 static bool isEqual(const WeakVH &LHS, const WeakVH &RHS) {
224 }
225};
226
227/// Value handle that is nullable, but tries to track the Value.
228///
229/// This is a value handle that tries hard to point to a Value, even across
230/// RAUW operations, but will null itself out if the value is destroyed. this
231/// is useful for advisory sorts of information, but should not be used as the
232/// key of a map (since the map would have to rearrange itself when the pointer
233/// changes).
258
259// Specialize simplify_type to allow WeakTrackingVH to participate in
260// dyn_cast, isa, etc.
261template <> struct simplify_type<WeakTrackingVH> {
262 using SimpleType = Value *;
263
264 static SimpleType getSimplifiedValue(WeakTrackingVH &WVH) { return WVH; }
265};
266template <> struct simplify_type<const WeakTrackingVH> {
267 using SimpleType = Value *;
268
270 return WVH;
271 }
272};
273
274/// Value handle that asserts if the Value is deleted.
275///
276/// This is a Value Handle that points to a value and asserts out if the value
277/// is destroyed while the handle is still live. This is very useful for
278/// catching dangling pointer bugs and other things which can be non-obvious.
279/// One particularly useful place to use this is as the Key of a map. Dangling
280/// pointer bugs often lead to really subtle bugs that only occur if another
281/// object happens to get allocated to the same address as the old one. Using
282/// an AssertingVH ensures that an assert is triggered as soon as the bad
283/// delete occurs.
284///
285/// Note that an AssertingVH handle does *not* follow values across RAUW
286/// operations. This means that RAUW's need to explicitly update the
287/// AssertingVH's as it moves. This is required because in non-assert mode this
288/// class turns into a trivial wrapper around a pointer.
289template <typename ValueTy>
291#if LLVM_ENABLE_ABI_BREAKING_CHECKS
292 : public ValueHandleBase
293#endif
294{
295 friend struct DenseMapInfo<AssertingVH<ValueTy>>;
296
297#if LLVM_ENABLE_ABI_BREAKING_CHECKS
298 Value *getRawValPtr() const { return ValueHandleBase::getValPtr(); }
299 void setRawValPtr(Value *P) { ValueHandleBase::operator=(P); }
300#else
301 Value *ThePtr;
302 Value *getRawValPtr() const { return ThePtr; }
303 void setRawValPtr(Value *P) { ThePtr = P; }
304#endif
305 // Convert a ValueTy*, which may be const, to the raw Value*.
306 static Value *GetAsValue(Value *V) { return V; }
307 static Value *GetAsValue(const Value *V) { return const_cast<Value*>(V); }
308
309 ValueTy *getValPtr() const { return static_cast<ValueTy *>(getRawValPtr()); }
310 void setValPtr(ValueTy *P) { setRawValPtr(GetAsValue(P)); }
311
312public:
313#if LLVM_ENABLE_ABI_BREAKING_CHECKS
314 AssertingVH() : ValueHandleBase(Assert) {}
315 AssertingVH(ValueTy *P) : ValueHandleBase(Assert, GetAsValue(P)) {}
316 AssertingVH(const AssertingVH &RHS) : ValueHandleBase(Assert, RHS) {}
317 AssertingVH(AssertingVH &&RHS) : ValueHandleBase(Assert, std::move(RHS)) {}
318#else
319 AssertingVH() : ThePtr(nullptr) {}
320 AssertingVH(ValueTy *P) : ThePtr(GetAsValue(P)) {}
321 AssertingVH(const AssertingVH &) = default;
322 AssertingVH(AssertingVH &&RHS) : ThePtr(std::exchange(RHS.ThePtr, nullptr)) {}
323#endif
324
325 operator ValueTy*() const {
326 return getValPtr();
327 }
328
329 ValueTy *operator=(ValueTy *RHS) {
330 setValPtr(RHS);
331 return getValPtr();
332 }
334 setValPtr(RHS.getValPtr());
335 return getValPtr();
336 }
337#if LLVM_ENABLE_ABI_BREAKING_CHECKS
340 return getValPtr();
341 }
342#else
344 ThePtr = std::exchange(RHS.ThePtr, nullptr);
345 return getValPtr();
346 }
347#endif
348
349 ValueTy *operator->() const { return getValPtr(); }
350 ValueTy &operator*() const { return *getValPtr(); }
351};
352
353// Treat AssertingVH<T> like T* inside maps. This also allows using find_as()
354// to look up a value without constructing a value handle.
355template<typename T>
357
358/// Value handle that tracks a Value across RAUW.
359///
360/// TrackingVH is designed for situations where a client needs to hold a handle
361/// to a Value (or subclass) across some operations which may move that value,
362/// but should never destroy it or replace it with some unacceptable type.
363///
364/// It is an error to attempt to replace a value with one of a type which is
365/// incompatible with any of its outstanding TrackingVHs.
366///
367/// It is an error to read from a TrackingVH that does not point to a valid
368/// value. A TrackingVH is said to not point to a valid value if either it
369/// hasn't yet been assigned a value yet or because the value it was tracking
370/// has since been deleted.
371///
372/// Assigning a value to a TrackingVH is always allowed, even if said TrackingVH
373/// no longer points to a valid value.
374template <typename ValueTy> class TrackingVH {
375 WeakTrackingVH InnerHandle;
376
377public:
378 ValueTy *getValPtr() const {
379 assert(InnerHandle.pointsToAliveValue() &&
380 "TrackingVH must be non-null and valid on dereference!");
381
382 // Check that the value is a member of the correct subclass. We would like
383 // to check this property on assignment for better debugging, but we don't
384 // want to require a virtual interface on this VH. Instead we allow RAUW to
385 // replace this value with a value of an invalid type, and check it here.
386 assert(isa<ValueTy>(InnerHandle) &&
387 "Tracked Value was replaced by one with an invalid type!");
388 return cast<ValueTy>(InnerHandle);
389 }
390
391 void setValPtr(ValueTy *P) {
392 // Assigning to non-valid TrackingVH's are fine so we just unconditionally
393 // assign here.
394 InnerHandle = GetAsValue(P);
395 }
396
397 // Convert a ValueTy*, which may be const, to the type the base
398 // class expects.
399 static Value *GetAsValue(Value *V) { return V; }
400 static Value *GetAsValue(const Value *V) { return const_cast<Value*>(V); }
401
402public:
403 TrackingVH() = default;
404 TrackingVH(ValueTy *P) { setValPtr(P); }
405
406 operator ValueTy*() const {
407 return getValPtr();
408 }
409
410 ValueTy *operator=(ValueTy *RHS) {
411 setValPtr(RHS);
412 return getValPtr();
413 }
414
415 ValueTy *operator->() const { return getValPtr(); }
416 ValueTy &operator*() const { return *getValPtr(); }
417};
418
419/// Value handle with callbacks on RAUW and destruction.
420///
421/// This is a value handle that allows subclasses to define callbacks that run
422/// when the underlying Value has RAUW called on it or is destroyed. This
423/// class can be used as the key of a map, as long as the user takes it out of
424/// the map before calling setValPtr() (since the map has to rearrange itself
425/// when the pointer changes). Unlike ValueHandleBase, this class has a vtable.
427 virtual void anchor();
428protected:
429 ~CallbackVH() = default;
430 CallbackVH(const CallbackVH &) = default;
431 CallbackVH &operator=(const CallbackVH &) = default;
432
436
437public:
440 CallbackVH(const Value *P) : CallbackVH(const_cast<Value *>(P)) {}
441
442 operator Value*() const {
443 return getValPtr();
444 }
445
446 /// Callback for Value destruction.
447 ///
448 /// Called when this->getValPtr() is destroyed, inside ~Value(), so you
449 /// may call any non-virtual Value method on getValPtr(), but no subclass
450 /// methods. If WeakTrackingVH were implemented as a CallbackVH, it would use
451 /// this
452 /// method to call setValPtr(NULL). AssertingVH would use this method to
453 /// cause an assertion failure.
454 ///
455 /// All implementations must remove the reference from this object to the
456 /// Value that's being destroyed.
457 virtual void deleted() { setValPtr(nullptr); }
458
459 /// Callback for Value RAUW.
460 ///
461 /// Called when this->getValPtr()->replaceAllUsesWith(new_value) is called,
462 /// _before_ any of the uses have actually been replaced. If WeakTrackingVH
463 /// were
464 /// implemented as a CallbackVH, it would use this method to call
465 /// setValPtr(new_value). AssertingVH would do nothing in this method.
466 virtual void allUsesReplacedWith(Value *) {}
467};
468
469/// Value handle that poisons itself if the Value is deleted.
470///
471/// This is a Value Handle that points to a value and poisons itself if the
472/// value is destroyed while the handle is still live. This is very useful for
473/// catching dangling pointer bugs where an \c AssertingVH cannot be used
474/// because the dangling handle needs to outlive the value without ever being
475/// used.
476///
477/// One particularly useful place to use this is as the Key of a map. Dangling
478/// pointer bugs often lead to really subtle bugs that only occur if another
479/// object happens to get allocated to the same address as the old one. Using
480/// a PoisoningVH ensures that an assert is triggered if looking up a new value
481/// in the map finds a handle from the old value.
482///
483/// Note that a PoisoningVH handle does *not* follow values across RAUW
484/// operations. This means that RAUW's need to explicitly update the
485/// PoisoningVH's as it moves. This is required because in non-assert mode this
486/// class turns into a trivial wrapper around a pointer.
487template <typename ValueTy>
488class PoisoningVH final
489#if LLVM_ENABLE_ABI_BREAKING_CHECKS
490 : public CallbackVH
491#endif
492{
493 friend struct DenseMapInfo<PoisoningVH<ValueTy>>;
494
495 // Convert a ValueTy*, which may be const, to the raw Value*.
496 static Value *GetAsValue(Value *V) { return V; }
497 static Value *GetAsValue(const Value *V) { return const_cast<Value *>(V); }
498
499#if LLVM_ENABLE_ABI_BREAKING_CHECKS
500 /// A flag tracking whether this value has been poisoned.
501 ///
502 /// On delete and RAUW, we leave the value pointer alone so that as a raw
503 /// pointer it produces the same value (and we fit into the same key of
504 /// a hash table, etc), but we poison the handle so that any top-level usage
505 /// will fail.
506 bool Poisoned = false;
507
508 Value *getRawValPtr() const { return ValueHandleBase::getValPtr(); }
509 void setRawValPtr(Value *P) { ValueHandleBase::operator=(P); }
510
511 /// Handle deletion by poisoning the handle.
512 void deleted() override {
513 assert(!Poisoned && "Tried to delete an already poisoned handle!");
514 Poisoned = true;
515 RemoveFromUseList();
516 }
517
518 /// Handle RAUW by poisoning the handle.
519 void allUsesReplacedWith(Value *) override {
520 assert(!Poisoned && "Tried to RAUW an already poisoned handle!");
521 Poisoned = true;
522 RemoveFromUseList();
523 }
524#else // LLVM_ENABLE_ABI_BREAKING_CHECKS
525 Value *ThePtr = nullptr;
526
527 Value *getRawValPtr() const { return ThePtr; }
528 void setRawValPtr(Value *P) { ThePtr = P; }
529#endif
530
531 ValueTy *getValPtr() const {
532#if LLVM_ENABLE_ABI_BREAKING_CHECKS
533 assert(!Poisoned && "Accessed a poisoned value handle!");
534#endif
535 return static_cast<ValueTy *>(getRawValPtr());
536 }
537 void setValPtr(ValueTy *P) { setRawValPtr(GetAsValue(P)); }
538
539public:
540 PoisoningVH() = default;
541#if LLVM_ENABLE_ABI_BREAKING_CHECKS
542 PoisoningVH(ValueTy *P) : CallbackVH(GetAsValue(P)) {}
544 : CallbackVH(RHS), Poisoned(RHS.Poisoned) {}
545
546 ~PoisoningVH() {
547 if (Poisoned)
548 clearValPtr();
549 }
550
551 PoisoningVH &operator=(const PoisoningVH &RHS) {
552 if (Poisoned)
553 clearValPtr();
555 Poisoned = RHS.Poisoned;
556 return *this;
557 }
558#else
559 PoisoningVH(ValueTy *P) : ThePtr(GetAsValue(P)) {}
560#endif
561
562 operator ValueTy *() const { return getValPtr(); }
563
564 ValueTy *operator->() const { return getValPtr(); }
565 ValueTy &operator*() const { return *getValPtr(); }
566};
567
568// Specialize DenseMapInfo to allow PoisoningVH to participate in DenseMap.
569template <typename T> struct DenseMapInfo<PoisoningVH<T>> {
570 static inline PoisoningVH<T> getEmptyKey() {
571 PoisoningVH<T> Res;
572 Res.setRawValPtr(DenseMapInfo<Value *>::getEmptyKey());
573 return Res;
574 }
575
577 PoisoningVH<T> Res;
578 Res.setRawValPtr(DenseMapInfo<Value *>::getTombstoneKey());
579 return Res;
580 }
581
582 static unsigned getHashValue(const PoisoningVH<T> &Val) {
583 return DenseMapInfo<Value *>::getHashValue(Val.getRawValPtr());
584 }
585
586 static bool isEqual(const PoisoningVH<T> &LHS, const PoisoningVH<T> &RHS) {
587 return DenseMapInfo<Value *>::isEqual(LHS.getRawValPtr(),
588 RHS.getRawValPtr());
589 }
590
591 // Allow lookup by T* via find_as(), without constructing a temporary
592 // value handle.
593
594 static unsigned getHashValue(const T *Val) {
596 }
597
598 static bool isEqual(const T *LHS, const PoisoningVH<T> &RHS) {
599 return DenseMapInfo<Value *>::isEqual(LHS, RHS.getRawValPtr());
600 }
601};
602
603} // end namespace llvm
604
605#endif // LLVM_IR_VALUEHANDLE_H
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
aarch64 promote const
#define LLVM_ABI
Definition Compiler.h:213
This file defines DenseMapInfo traits for DenseMap.
#define T
#define P(N)
if(PassOpts->AAPipeline)
This file defines the PointerIntPair class.
Value * RHS
Value * LHS
Value handle that asserts if the Value is deleted.
ValueTy * operator=(ValueTy *RHS)
ValueTy & operator*() const
ValueTy * operator=(const AssertingVH< ValueTy > &RHS)
ValueTy * operator->() const
AssertingVH(ValueTy *P)
AssertingVH(const AssertingVH &)=default
ValueTy * operator=(AssertingVH< ValueTy > &&RHS)
AssertingVH(AssertingVH &&RHS)
Value handle with callbacks on RAUW and destruction.
virtual void allUsesReplacedWith(Value *)
Callback for Value RAUW.
CallbackVH(const Value *P)
CallbackVH & operator=(const CallbackVH &)=default
CallbackVH(Value *P)
CallbackVH(const CallbackVH &)=default
virtual void deleted()
Callback for Value destruction.
void setValPtr(Value *P)
~CallbackVH()=default
PointerIntPair - This class implements a pair of a pointer and small integer.
IntType getInt() const
PointerTy getPointer() const
Value handle that poisons itself if the Value is deleted.
ValueTy & operator*() const
PoisoningVH()=default
ValueTy * operator->() const
PoisoningVH(ValueTy *P)
ValueTy * operator->() const
ValueTy * getValPtr() const
static Value * GetAsValue(const Value *V)
static Value * GetAsValue(Value *V)
ValueTy & operator*() const
void setValPtr(ValueTy *P)
ValueTy * operator=(ValueTy *RHS)
TrackingVH(ValueTy *P)
TrackingVH()=default
This is the common base class of value handles.
Definition ValueHandle.h:30
Value & operator*() const
ValueHandleBase(HandleBaseKind Kind, Value *V)
Definition ValueHandle.h:68
static bool isValid(Value *V)
LLVM_ABI void RemoveFromUseList()
Remove this ValueHandle from its current use list.
Definition Value.cpp:1206
ValueHandleBase(HandleBaseKind Kind, ValueHandleBase &&RHS)
Definition ValueHandle.h:49
Value * operator->() const
Value * operator=(Value *RHS)
Definition ValueHandle.h:79
Value * operator=(const ValueHandleBase &RHS)
Definition ValueHandle.h:90
Value * getValPtr() const
Value * operator=(ValueHandleBase &&RHS)
static LLVM_ABI void ValueIsDeleted(Value *V)
Definition Value.cpp:1232
void clearValPtr()
Clear the underlying pointer without clearing the use list.
ValueHandleBase(HandleBaseKind Kind)
Definition ValueHandle.h:66
static LLVM_ABI void ValueIsRAUWd(Value *Old, Value *New)
Definition Value.cpp:1285
HandleBaseKind
This indicates what sub class the handle actually is.
Definition ValueHandle.h:38
ValueHandleBase(HandleBaseKind Kind, const ValueHandleBase &RHS)
Definition ValueHandle.h:43
ValueHandleBase(const ValueHandleBase &RHS)
Definition ValueHandle.h:40
LLVM Value Representation.
Definition Value.h:75
Value handle that is nullable, but tries to track the Value.
WeakTrackingVH(const WeakTrackingVH &RHS)
Value * operator=(const ValueHandleBase &RHS)
Value * operator=(Value *RHS)
WeakTrackingVH & operator=(const WeakTrackingVH &RHS)=default
bool pointsToAliveValue() const
A nullable Value handle that is nullable.
WeakVH(Value *P)
WeakVH(const WeakVH &RHS)
WeakVH & operator=(const WeakVH &RHS)=default
Value * operator=(const ValueHandleBase &RHS)
Value * operator=(Value *RHS)
This is an optimization pass for GlobalISel generic memory operations.
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
Definition Casting.h:547
FunctionAddr VTableAddr Next
Definition InstrProf.h:141
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
Implement std::hash so that hash_code can be used in STL containers.
Definition BitVector.h:870
static bool isEqual(const T *LHS, const PoisoningVH< T > &RHS)
static PoisoningVH< T > getTombstoneKey()
static unsigned getHashValue(const T *Val)
static unsigned getHashValue(const PoisoningVH< T > &Val)
static bool isEqual(const PoisoningVH< T > &LHS, const PoisoningVH< T > &RHS)
static PoisoningVH< T > getEmptyKey()
static bool isEqual(const WeakVH &LHS, const WeakVH &RHS)
static unsigned getHashValue(const WeakVH &Val)
static WeakVH getTombstoneKey()
An information struct used to provide DenseMap with the various necessary components for a given valu...
static SimpleType getSimplifiedValue(WeakTrackingVH &WVH)
static SimpleType getSimplifiedValue(WeakVH &WVH)
static SimpleType getSimplifiedValue(const WeakVH &WVH)
Define a template that can be specialized by smart pointers to reflect the fact that they are automat...
Definition Casting.h:34
static SimpleType & getSimplifiedValue(From &Val)
Definition Casting.h:38