From: Chandler Carruth Date: Tue, 7 Feb 2017 03:15:12 +0000 (+0000) Subject: [ADT] Defend against getting slightly wrong template arguments passed X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=167cdd001ac7b5c7481fcd40912de7cf9b4fef1e;p=llvm [ADT] Defend against getting slightly wrong template arguments passed into CRTP base classes. This can sometimes happen and not cause an immediate failure when the derived class is, itself, a template. You can end up essentially calling methods on the wrong derived type but a type where many things will appear to "work". To fail fast and with a clear error message we can use a static_assert, but we have to stash that static_assert inside a method body or nested type that won't need to be completed while building the base class. I've tried to pick a reasonably small number of places that seemed like reliably places for this to be instantiated. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@294271 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/llvm/ADT/DenseMap.h b/include/llvm/ADT/DenseMap.h index 0b4b09d4b73..a689bcbf151 100644 --- a/include/llvm/ADT/DenseMap.h +++ b/include/llvm/ADT/DenseMap.h @@ -389,6 +389,8 @@ protected: return KeyInfoT::getHashValue(Val); } static const KeyT getEmptyKey() { + static_assert(std::is_base_of::value, + "Must pass the derived type to this template!"); return KeyInfoT::getEmptyKey(); } static const KeyT getTombstoneKey() { diff --git a/include/llvm/ADT/iterator.h b/include/llvm/ADT/iterator.h index 6470e09db86..9a134e1557b 100644 --- a/include/llvm/ADT/iterator.h +++ b/include/llvm/ADT/iterator.h @@ -91,6 +91,8 @@ protected: public: DerivedT operator+(DifferenceTypeT n) const { + static_assert(std::is_base_of::value, + "Must pass the derived type to this template!"); static_assert( IsRandomAccess, "The '+' operator is only defined for random access iterators."); @@ -114,6 +116,8 @@ public: } DerivedT &operator++() { + static_assert(std::is_base_of::value, + "Must pass the derived type to this template!"); return static_cast(this)->operator+=(1); } DerivedT operator++(int) { @@ -202,7 +206,10 @@ protected: iterator_adaptor_base() = default; - explicit iterator_adaptor_base(WrappedIteratorT u) : I(std::move(u)) {} + explicit iterator_adaptor_base(WrappedIteratorT u) : I(std::move(u)) { + static_assert(std::is_base_of::value, + "Must pass the derived type to this template!"); + } const WrappedIteratorT &wrapped() const { return I; }