[llvm] r294271 - [ADT] Defend against getting slightly wrong template arguments passed

Chandler Carruth via llvm-commits llvm-commits at lists.llvm.org
Mon Feb 6 19:15:12 PST 2017


Author: chandlerc
Date: Mon Feb  6 21:15:12 2017
New Revision: 294271

URL: http://llvm.org/viewvc/llvm-project?rev=294271&view=rev
Log:
[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.

Modified:
    llvm/trunk/include/llvm/ADT/DenseMap.h
    llvm/trunk/include/llvm/ADT/iterator.h

Modified: llvm/trunk/include/llvm/ADT/DenseMap.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ADT/DenseMap.h?rev=294271&r1=294270&r2=294271&view=diff
==============================================================================
--- llvm/trunk/include/llvm/ADT/DenseMap.h (original)
+++ llvm/trunk/include/llvm/ADT/DenseMap.h Mon Feb  6 21:15:12 2017
@@ -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() {

Modified: llvm/trunk/include/llvm/ADT/iterator.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ADT/iterator.h?rev=294271&r1=294270&r2=294271&view=diff
==============================================================================
--- llvm/trunk/include/llvm/ADT/iterator.h (original)
+++ llvm/trunk/include/llvm/ADT/iterator.h Mon Feb  6 21:15:12 2017
@@ -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; }
 




More information about the llvm-commits mailing list