diff options
| author | Chandler Carruth <chandlerc@gmail.com> | 2017-02-07 03:15:12 +0000 |
|---|---|---|
| committer | Chandler Carruth <chandlerc@gmail.com> | 2017-02-07 03:15:12 +0000 |
| commit | 0aecae34529b70f6ac4b758651bf579f0a464257 (patch) | |
| tree | d6db150126d79158690fa2716cc941e40cf97e10 /llvm | |
| parent | 833cf8bdb6e6050337e878b9946c0752d4550ac0 (diff) | |
| download | bcm5719-llvm-0aecae34529b70f6ac4b758651bf579f0a464257.tar.gz bcm5719-llvm-0aecae34529b70f6ac4b758651bf579f0a464257.zip | |
[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.
llvm-svn: 294271
Diffstat (limited to 'llvm')
| -rw-r--r-- | llvm/include/llvm/ADT/DenseMap.h | 2 | ||||
| -rw-r--r-- | llvm/include/llvm/ADT/iterator.h | 9 |
2 files changed, 10 insertions, 1 deletions
diff --git a/llvm/include/llvm/ADT/DenseMap.h b/llvm/include/llvm/ADT/DenseMap.h index 0b4b09d4b73..a689bcbf151 100644 --- a/llvm/include/llvm/ADT/DenseMap.h +++ b/llvm/include/llvm/ADT/DenseMap.h @@ -389,6 +389,8 @@ protected: return KeyInfoT::getHashValue(Val); } static const KeyT getEmptyKey() { + static_assert(std::is_base_of<DenseMapBase, DerivedT>::value, + "Must pass the derived type to this template!"); return KeyInfoT::getEmptyKey(); } static const KeyT getTombstoneKey() { diff --git a/llvm/include/llvm/ADT/iterator.h b/llvm/include/llvm/ADT/iterator.h index 6470e09db86..9a134e1557b 100644 --- a/llvm/include/llvm/ADT/iterator.h +++ b/llvm/include/llvm/ADT/iterator.h @@ -91,6 +91,8 @@ protected: public: DerivedT operator+(DifferenceTypeT n) const { + static_assert(std::is_base_of<iterator_facade_base, DerivedT>::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<iterator_facade_base, DerivedT>::value, + "Must pass the derived type to this template!"); return static_cast<DerivedT *>(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<iterator_adaptor_base, DerivedT>::value, + "Must pass the derived type to this template!"); + } const WrappedIteratorT &wrapped() const { return I; } |

