diff options
Diffstat (limited to 'include/llvm/ADT/ArrayRef.h')
-rw-r--r-- | include/llvm/ADT/ArrayRef.h | 71 |
1 files changed, 70 insertions, 1 deletions
diff --git a/include/llvm/ADT/ArrayRef.h b/include/llvm/ADT/ArrayRef.h index 0fff505..8c14a42 100644 --- a/include/llvm/ADT/ArrayRef.h +++ b/include/llvm/ADT/ArrayRef.h @@ -11,6 +11,7 @@ #define LLVM_ADT_ARRAYREF_H #include "llvm/ADT/None.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallVector.h" #include <vector> @@ -43,6 +44,19 @@ namespace llvm { /// The number of elements. size_type Length; + /// \brief A dummy "optional" type that is only created by implicit + /// conversion from a reference to T. + /// + /// This type must *only* be used in a function argument or as a copy of + /// a function argument, as otherwise it will hold a pointer to a temporary + /// past that temporaries' lifetime. + struct TRefOrNothing { + const T *TPtr; + + TRefOrNothing() : TPtr(nullptr) {} + TRefOrNothing(const T &TRef) : TPtr(&TRef) {} + }; + public: /// @name Constructors /// @{ @@ -90,6 +104,14 @@ namespace llvm { Length(Vec.size()) {} #endif + /// Construct an ArrayRef<const T*> from ArrayRef<T*>. This uses SFINAE to + /// ensure that only ArrayRefs of pointers can be converted. + template <typename U> + ArrayRef(const ArrayRef<U *> &A, + typename std::enable_if< + std::is_convertible<U *const *, T const *>::value>::type* = 0) + : Data(A.data()), Length(A.size()) {} + /// @} /// @name Simple Operations /// @{ @@ -131,7 +153,13 @@ namespace llvm { bool equals(ArrayRef RHS) const { if (Length != RHS.Length) return false; - return std::equal(begin(), end(), RHS.begin()); + // Don't use std::equal(), since it asserts in MSVC on nullptr iterators. + for (auto L = begin(), LE = end(), R = RHS.begin(); L != LE; ++L, ++R) + // Match std::equal() in using == (instead of !=) to minimize API + // requirements of ArrayRef'ed types. + if (!(*L == *R)) + return false; + return true; } /// slice(n) - Chop off the first N elements of the array. @@ -176,6 +204,47 @@ namespace llvm { } /// @} + /// @{ + /// @name Convenience methods + + /// @brief Predicate for testing that the array equals the exact sequence of + /// arguments. + /// + /// Will return false if the size is not equal to the exact number of + /// arguments given or if the array elements don't equal the argument + /// elements in order. Currently supports up to 16 arguments, but can + /// easily be extended. + bool equals(TRefOrNothing Arg0 = TRefOrNothing(), + TRefOrNothing Arg1 = TRefOrNothing(), + TRefOrNothing Arg2 = TRefOrNothing(), + TRefOrNothing Arg3 = TRefOrNothing(), + TRefOrNothing Arg4 = TRefOrNothing(), + TRefOrNothing Arg5 = TRefOrNothing(), + TRefOrNothing Arg6 = TRefOrNothing(), + TRefOrNothing Arg7 = TRefOrNothing(), + TRefOrNothing Arg8 = TRefOrNothing(), + TRefOrNothing Arg9 = TRefOrNothing(), + TRefOrNothing Arg10 = TRefOrNothing(), + TRefOrNothing Arg11 = TRefOrNothing(), + TRefOrNothing Arg12 = TRefOrNothing(), + TRefOrNothing Arg13 = TRefOrNothing(), + TRefOrNothing Arg14 = TRefOrNothing(), + TRefOrNothing Arg15 = TRefOrNothing()) { + TRefOrNothing Args[] = {Arg0, Arg1, Arg2, Arg3, Arg4, Arg5, + Arg6, Arg7, Arg8, Arg9, Arg10, Arg11, + Arg12, Arg13, Arg14, Arg15}; + if (size() > array_lengthof(Args)) + return false; + + for (unsigned i = 0, e = size(); i != e; ++i) + if (Args[i].TPtr == nullptr || (*this)[i] != *Args[i].TPtr) + return false; + + // Either the size is exactly as many args, or the next arg must be null. + return size() == array_lengthof(Args) || Args[size()].TPtr == nullptr; + } + + /// @} }; /// MutableArrayRef - Represent a mutable reference to an array (0 or more |