[C++11] Sink the iterator over a Value's users into the Value type

itself and teach it to convert between the non-const and const variants.
De-templatetize its usage in APIs to just use the const variant which
always works for those use cases. Also, rename its implementation to
reflect that it is an iterator over *users* not over *uses*.

This is a step toward providing both iterator and range support for
walking the *uses* distinct from the *users*. In a subsequent patch this
will get renamed to make it clear that this is an adaptor over the
fundamental use iterator.

llvm-svn: 202923
This commit is contained in:
Chandler Carruth 2014-03-05 01:50:35 +00:00
parent 01c7d98043
commit 1a534ebef0
4 changed files with 60 additions and 59 deletions

View File

@ -104,7 +104,7 @@ public:
/// isCallee - Determine whether the passed iterator points to the
/// callee operand's Use.
///
bool isCallee(value_use_iterator<UserTy> UI) const {
bool isCallee(Value::const_use_iterator UI) const {
return getCallee() == &UI.getUse();
}
@ -121,7 +121,7 @@ public:
/// Given a value use iterator, returns the argument that corresponds to it.
/// Iterator must actually correspond to an argument.
unsigned getArgumentNo(value_use_iterator<UserTy> I) const {
unsigned getArgumentNo(Value::const_use_iterator I) const {
assert(getInstruction() && "Not a call or invoke instruction!");
assert(arg_begin() <= &I.getUse() && &I.getUse() < arg_end()
&& "Argument # out of range!");

View File

@ -2100,8 +2100,7 @@ public:
/// getIncomingBlock - Return incoming basic block corresponding
/// to value use iterator.
///
template <typename U>
BasicBlock *getIncomingBlock(value_use_iterator<U> I) const {
BasicBlock *getIncomingBlock(Value::const_use_iterator I) const {
return getIncomingBlock(I.getUse());
}

View File

@ -165,56 +165,6 @@ template <> struct simplify_type<const Use> {
static SimpleType getSimplifiedValue(const Use &Val) { return Val.get(); }
};
template<typename UserTy> // UserTy == 'User' or 'const User'
class value_use_iterator : public std::iterator<std::forward_iterator_tag,
UserTy*, ptrdiff_t> {
typedef std::iterator<std::forward_iterator_tag, UserTy*, ptrdiff_t> super;
typedef value_use_iterator<UserTy> _Self;
Use *U;
explicit value_use_iterator(Use *u) : U(u) {}
friend class Value;
public:
typedef typename super::reference reference;
typedef typename super::pointer pointer;
value_use_iterator() {}
bool operator==(const _Self &x) const {
return U == x.U;
}
bool operator!=(const _Self &x) const {
return !operator==(x);
}
/// \brief Returns true if this iterator is equal to use_end() on the value.
bool atEnd() const { return U == 0; }
// Iterator traversal: forward iteration only
_Self &operator++() { // Preincrement
assert(U && "Cannot increment end iterator!");
U = U->getNext();
return *this;
}
_Self operator++(int) { // Postincrement
_Self tmp = *this; ++*this; return tmp;
}
// Retrieve a pointer to the current User.
UserTy *operator*() const {
assert(U && "Cannot dereference end iterator!");
return U->getUser();
}
UserTy *operator->() const { return operator*(); }
Use &getUse() const { return *U; }
/// \brief Return the operand # of this use in its User.
/// FIXME: Replace all callers with a direct call to Use::getOperandNo.
unsigned getOperandNo() const { return U->getOperandNo(); }
};
// Create wrappers for C Binding types (see CBindingWrapping.h).
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(Use, LLVMUseRef)

View File

@ -75,6 +75,58 @@ protected:
unsigned char SubclassOptionalData : 7;
private:
template <typename UserTy> // UserTy == 'User' or 'const User'
class user_iterator_impl
: public std::iterator<std::forward_iterator_tag, UserTy *, ptrdiff_t> {
typedef std::iterator<std::forward_iterator_tag, UserTy *, ptrdiff_t> super;
Use *U;
explicit user_iterator_impl(Use *u) : U(u) {}
friend class Value;
public:
typedef typename super::reference reference;
typedef typename super::pointer pointer;
user_iterator_impl() {}
bool operator==(const user_iterator_impl &x) const { return U == x.U; }
bool operator!=(const user_iterator_impl &x) const { return !operator==(x); }
/// \brief Returns true if this iterator is equal to use_end() on the value.
bool atEnd() const { return U == 0; }
// Iterator traversal: forward iteration only
user_iterator_impl &operator++() { // Preincrement
assert(U && "Cannot increment end iterator!");
U = U->getNext();
return *this;
}
user_iterator_impl operator++(int) { // Postincrement
auto tmp = *this;
++*this;
return tmp;
}
// Retrieve a pointer to the current User.
UserTy *operator*() const {
assert(U && "Cannot dereference end iterator!");
return U->getUser();
}
UserTy *operator->() const { return operator*(); }
operator user_iterator_impl<const UserTy>() const {
return user_iterator_impl<const UserTy>(U);
}
Use &getUse() const { return *U; }
/// \brief Return the operand # of this use in its User.
/// FIXME: Replace all callers with a direct call to Use::getOperandNo.
unsigned getOperandNo() const { return U->getOperandNo(); }
};
/// SubclassData - This member is defined by this class, but is not used for
/// anything. Subclasses can use it to hold whatever state they find useful.
/// This field is initialized to zero by the ctor.
@ -151,16 +203,16 @@ public:
//----------------------------------------------------------------------
// Methods for handling the chain of uses of this Value.
//
typedef value_use_iterator<User> use_iterator;
typedef value_use_iterator<const User> const_use_iterator;
bool use_empty() const { return UseList == 0; }
typedef user_iterator_impl<User> use_iterator;
typedef user_iterator_impl<const User> const_use_iterator;
use_iterator use_begin() { return use_iterator(UseList); }
const_use_iterator use_begin() const { return const_use_iterator(UseList); }
use_iterator use_end() { return use_iterator(0); }
const_use_iterator use_end() const { return const_use_iterator(0); }
User *use_back() { return *use_begin(); }
const User *use_back() const { return *use_begin(); }
User *use_back() { return *use_begin(); }
const User *use_back() const { return *use_begin(); }
/// hasOneUse - Return true if there is exactly one user of this value. This
/// is specialized because it is a common request and does not require