OSDN Git Service

[ADT] Defend against getting slightly wrong template arguments passed
authorChandler Carruth <chandlerc@gmail.com>
Tue, 7 Feb 2017 03:15:12 +0000 (03:15 +0000)
committerChandler Carruth <chandlerc@gmail.com>
Tue, 7 Feb 2017 03:15:12 +0000 (03:15 +0000)
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

include/llvm/ADT/DenseMap.h
include/llvm/ADT/iterator.h

index 0b4b09d..a689bcb 100644 (file)
@@ -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() {
index 6470e09..9a134e1 100644 (file)
@@ -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; }