diff --git a/libcxx/docs/Status/Cxx17.rst b/libcxx/docs/Status/Cxx17.rst
--- a/libcxx/docs/Status/Cxx17.rst
+++ b/libcxx/docs/Status/Cxx17.rst
@@ -40,7 +40,6 @@
 
 .. note::
 
-   .. [#note-P0433] P0433: The only part not fully implemented is the requirement that certain deduction guides should not participate in overload resolution when given incorrect template arguments.
    .. [#note-P0607] P0607: The parts of P0607 that are not done are the ``<regex>`` bits.
 
 
diff --git a/libcxx/docs/Status/Cxx17Papers.csv b/libcxx/docs/Status/Cxx17Papers.csv
--- a/libcxx/docs/Status/Cxx17Papers.csv
+++ b/libcxx/docs/Status/Cxx17Papers.csv
@@ -94,7 +94,7 @@
 "`P0298R3 <https://wg21.link/P0298R3>`__","CWG","A byte type definition","Kona","|Complete|","5.0"
 "`P0317R1 <https://wg21.link/P0317R1>`__","LWG","Directory Entry Caching for Filesystem","Kona","|Complete|","7.0"
 "`P0430R2 <https://wg21.link/P0430R2>`__","LWG","File system library on non-POSIX-like operating systems","Kona","|Complete|","7.0"
-"`P0433R2 <https://wg21.link/P0433R2>`__","LWG","Toward a resolution of US7 and US14: Integrating template deduction for class templates into the standard library","Kona","|In Progress| [#note-P0433]_","7.0"
+"`P0433R2 <https://wg21.link/P0433R2>`__","LWG","Toward a resolution of US7 and US14: Integrating template deduction for class templates into the standard library","Kona","|Complete|","13.0"
 "`P0452R1 <https://wg21.link/P0452R1>`__","LWG","Unifying <numeric> Parallel Algorithms","Kona","",""
 "`P0467R2 <https://wg21.link/P0467R2>`__","LWG","Iterator Concerns for Parallel Algorithms","Kona","",""
 "`P0492R2 <https://wg21.link/P0492R2>`__","LWG","Proposed Resolution of C++17 National Body Comments for Filesystems","Kona","|Complete|","7.0"
diff --git a/libcxx/include/__memory/allocator_traits.h b/libcxx/include/__memory/allocator_traits.h
--- a/libcxx/include/__memory/allocator_traits.h
+++ b/libcxx/include/__memory/allocator_traits.h
@@ -349,6 +349,12 @@
     }
 };
 
+// A version of `allocator_traits` for internal usage that SFINAEs away if the
+// given allocator doesn't have a nested `value_type`. This helps avoid bad
+// instantiations in containers.
+template <class _Alloc, class _ValueType = typename _Alloc::value_type>
+struct _LIBCPP_TEMPLATE_VIS __allocator_traits : allocator_traits<_Alloc> {};
+
 template <class _Traits, class _Tp>
 struct __rebind_alloc_helper {
 #ifndef _LIBCPP_CXX03_LANG
diff --git a/libcxx/include/deque b/libcxx/include/deque
--- a/libcxx/include/deque
+++ b/libcxx/include/deque
@@ -162,6 +162,7 @@
 
 #include <__config>
 #include <__debug>
+#include <__iterator/iterator_traits.h>
 #include <__split_buffer>
 #include <__utility/forward.h>
 #include <algorithm>
@@ -1258,20 +1259,20 @@
     static_assert((is_same<typename allocator_type::value_type, value_type>::value),
                   "Allocator::value_type must be same type as value_type");
 
-    typedef __deque_base<value_type, allocator_type> __base;
+    typedef __deque_base<value_type, allocator_type>                 __base;
 
-    typedef typename __base::__alloc_traits        __alloc_traits;
-    typedef typename __base::reference             reference;
-    typedef typename __base::const_reference       const_reference;
-    typedef typename __base::iterator              iterator;
-    typedef typename __base::const_iterator        const_iterator;
-    typedef typename __base::size_type             size_type;
-    typedef typename __base::difference_type       difference_type;
+    typedef typename __base::__alloc_traits                          __alloc_traits;
+    typedef typename __base::reference                               reference;
+    typedef typename __base::const_reference                         const_reference;
+    typedef typename __base::iterator                                iterator;
+    typedef typename __base::const_iterator                          const_iterator;
+    typedef typename __allocator_traits<allocator_type>::size_type   size_type;
+    typedef typename __base::difference_type                         difference_type;
 
-    typedef typename __base::pointer               pointer;
-    typedef typename __base::const_pointer         const_pointer;
-    typedef _VSTD::reverse_iterator<iterator>       reverse_iterator;
-    typedef _VSTD::reverse_iterator<const_iterator> const_reverse_iterator;
+    typedef typename __base::pointer                                 pointer;
+    typedef typename __base::const_pointer                           const_pointer;
+    typedef _VSTD::reverse_iterator<iterator>                        reverse_iterator;
+    typedef _VSTD::reverse_iterator<const_iterator>                  const_reverse_iterator;
 
     using typename __base::__deque_range;
     using typename __base::__deque_block_range;
@@ -1568,6 +1569,7 @@
 #if _LIBCPP_STD_VER >= 17
 template<class _InputIterator,
          class _Alloc = allocator<__iter_value_type<_InputIterator>>,
+         class = enable_if_t<__is_cpp17_input_iterator<_InputIterator>::value>,
          class = enable_if_t<__is_allocator<_Alloc>::value>
          >
 deque(_InputIterator, _InputIterator)
@@ -1575,13 +1577,13 @@
 
 template<class _InputIterator,
          class _Alloc,
+         class = enable_if_t<__is_cpp17_input_iterator<_InputIterator>::value>,
          class = enable_if_t<__is_allocator<_Alloc>::value>
          >
 deque(_InputIterator, _InputIterator, _Alloc)
   -> deque<__iter_value_type<_InputIterator>, _Alloc>;
 #endif
 
-
 template <class _Tp, class _Allocator>
 deque<_Tp, _Allocator>::deque(size_type __n)
 {
diff --git a/libcxx/include/forward_list b/libcxx/include/forward_list
--- a/libcxx/include/forward_list
+++ b/libcxx/include/forward_list
@@ -647,7 +647,7 @@
     typedef const value_type&                                          const_reference;
     typedef typename allocator_traits<allocator_type>::pointer         pointer;
     typedef typename allocator_traits<allocator_type>::const_pointer   const_pointer;
-    typedef typename allocator_traits<allocator_type>::size_type       size_type;
+    typedef typename __allocator_traits<allocator_type>::size_type     size_type;
     typedef typename allocator_traits<allocator_type>::difference_type difference_type;
 
     typedef typename base::iterator       iterator;
@@ -873,6 +873,7 @@
 #if _LIBCPP_STD_VER >= 17
 template<class _InputIterator,
          class _Alloc = allocator<__iter_value_type<_InputIterator>>,
+         class = enable_if_t<__is_cpp17_input_iterator<_InputIterator>::value>,
          class = enable_if_t<__is_allocator<_Alloc>::value>
          >
 forward_list(_InputIterator, _InputIterator)
@@ -880,6 +881,7 @@
 
 template<class _InputIterator,
          class _Alloc,
+         class = enable_if_t<__is_cpp17_input_iterator<_InputIterator>::value>,
          class = enable_if_t<__is_allocator<_Alloc>::value>
          >
 forward_list(_InputIterator, _InputIterator, _Alloc)
diff --git a/libcxx/include/list b/libcxx/include/list
--- a/libcxx/include/list
+++ b/libcxx/include/list
@@ -845,24 +845,24 @@
     typedef typename base::__link_pointer __link_pointer;
 
 public:
-    typedef _Tp                                      value_type;
-    typedef _Alloc                                   allocator_type;
+    typedef _Tp                                                      value_type;
+    typedef _Alloc                                                   allocator_type;
     static_assert((is_same<value_type, typename allocator_type::value_type>::value),
                   "Invalid allocator::value_type");
-    typedef value_type&                              reference;
-    typedef const value_type&                        const_reference;
-    typedef typename base::pointer                   pointer;
-    typedef typename base::const_pointer             const_pointer;
-    typedef typename base::size_type                 size_type;
-    typedef typename base::difference_type           difference_type;
-    typedef typename base::iterator                  iterator;
-    typedef typename base::const_iterator            const_iterator;
-    typedef _VSTD::reverse_iterator<iterator>         reverse_iterator;
-    typedef _VSTD::reverse_iterator<const_iterator>   const_reverse_iterator;
+    typedef value_type&                                              reference;
+    typedef const value_type&                                        const_reference;
+    typedef typename base::pointer                                   pointer;
+    typedef typename base::const_pointer                             const_pointer;
+    typedef typename __allocator_traits<allocator_type>::size_type   size_type;
+    typedef typename base::difference_type                           difference_type;
+    typedef typename base::iterator                                  iterator;
+    typedef typename base::const_iterator                            const_iterator;
+    typedef _VSTD::reverse_iterator<iterator>                        reverse_iterator;
+    typedef _VSTD::reverse_iterator<const_iterator>                  const_reverse_iterator;
 #if _LIBCPP_STD_VER > 17
-    typedef size_type                                __remove_return_type;
+    typedef size_type                                                __remove_return_type;
 #else
-    typedef void                                     __remove_return_type;
+    typedef void                                                     __remove_return_type;
 #endif
 
     _LIBCPP_INLINE_VISIBILITY
@@ -1144,6 +1144,7 @@
 #if _LIBCPP_STD_VER >= 17
 template<class _InputIterator,
          class _Alloc = allocator<__iter_value_type<_InputIterator>>,
+         class = enable_if_t<__is_cpp17_input_iterator<_InputIterator>::value>,
          class = enable_if_t<__is_allocator<_Alloc>::value>
          >
 list(_InputIterator, _InputIterator)
@@ -1151,6 +1152,7 @@
 
 template<class _InputIterator,
          class _Alloc,
+         class = enable_if_t<__is_cpp17_input_iterator<_InputIterator>::value>,
          class = enable_if_t<__is_allocator<_Alloc>::value>
          >
 list(_InputIterator, _InputIterator, _Alloc)
diff --git a/libcxx/include/map b/libcxx/include/map
--- a/libcxx/include/map
+++ b/libcxx/include/map
@@ -223,6 +223,23 @@
         pair<const_iterator,const_iterator> equal_range(const K& x) const;  // C++14
 };
 
+template <class InputIterator,
+      class Compare = less<iter_key_t<InputIterator>>,
+      class Allocator = allocator<iter_to_alloc_t<InputIterator>>>
+map(InputIterator, InputIterator, Compare = Compare(), Allocator = Allocator())
+  -> map<iter_key_t<InputIterator>, iter_val_t<InputIterator>, Compare, Allocator>;
+
+template<class Key, class T, class Compare = less<Key>, class Allocator = allocator<pair<const Key, T>>>
+map(initializer_list<pair<const Key, T>>, Compare = Compare(), Allocator = Allocator())
+  -> map<Key, T, Compare, Allocator>;
+
+template <class InputIterator, class Allocator>
+map(InputIterator, InputIterator, Allocator)
+  -> map<iter_key_t<InputIterator>, iter_val_t<InputIterator>, less<iter_key_t<InputIterator>>, Allocator>;
+
+template<class Key, class T, class Allocator>
+map(initializer_list<pair<const Key, T>>, Allocator) -> map<Key, T, less<Key>, Allocator>;
+
 template <class Key, class T, class Compare, class Allocator>
 bool
 operator==(const map<Key, T, Compare, Allocator>& x,
@@ -444,6 +461,23 @@
         pair<const_iterator,const_iterator> equal_range(const K& x) const;  // C++14
 };
 
+template <class InputIterator,
+      class Compare = less<iter_key_t<InputIterator>>,
+      class Allocator = allocator<iter_to_alloc_t<InputIterator>>>
+multimap(InputIterator, InputIterator, Compare = Compare(), Allocator = Allocator())
+  -> multimap<iter_key_t<InputIterator>, iter_val_t<InputIterator>, Compare, Allocator>;
+
+template<class Key, class T, class Compare = less<Key>, class Allocator = allocator<pair<const Key, T>>>
+multimap(initializer_list<pair<const Key, T>>, Compare = Compare(), Allocator = Allocator())
+  -> multimap<Key, T, Compare, Allocator>;
+
+template <class InputIterator, class Allocator>
+multimap(InputIterator, InputIterator, Allocator)
+  -> multimap<iter_key_t<InputIterator>, iter_val_t<InputIterator>, less<iter_key_t<InputIterator>>, Allocator>;
+
+template<class Key, class T, class Allocator>
+multimap(initializer_list<pair<const Key, T>>, Allocator) -> multimap<Key, T, less<Key>, Allocator>;
+
 template <class Key, class T, class Compare, class Allocator>
 bool
 operator==(const multimap<Key, T, Compare, Allocator>& x,
@@ -492,6 +526,7 @@
 #include <__config>
 #include <__debug>
 #include <__functional/is_transparent.h>
+#include <__iterator/iterator_traits.h>
 #include <__node_handle>
 #include <__tree>
 #include <__utility/forward.h>
@@ -1501,6 +1536,7 @@
 #if _LIBCPP_STD_VER >= 17
 template<class _InputIterator, class _Compare = less<__iter_key_type<_InputIterator>>,
          class _Allocator = allocator<__iter_to_alloc_type<_InputIterator>>,
+         class = enable_if_t<__is_cpp17_input_iterator<_InputIterator>::value, void>,
          class = enable_if_t<!__is_allocator<_Compare>::value, void>,
          class = enable_if_t<__is_allocator<_Allocator>::value, void>>
 map(_InputIterator, _InputIterator, _Compare = _Compare(), _Allocator = _Allocator())
@@ -1514,6 +1550,7 @@
   -> map<remove_const_t<_Key>, _Tp, _Compare, _Allocator>;
 
 template<class _InputIterator, class _Allocator,
+         class = enable_if_t<__is_cpp17_input_iterator<_InputIterator>::value, void>,
          class = enable_if_t<__is_allocator<_Allocator>::value, void>>
 map(_InputIterator, _InputIterator, _Allocator)
   -> map<__iter_key_type<_InputIterator>, __iter_mapped_type<_InputIterator>,
@@ -2174,6 +2211,7 @@
 #if _LIBCPP_STD_VER >= 17
 template<class _InputIterator, class _Compare = less<__iter_key_type<_InputIterator>>,
          class _Allocator = allocator<__iter_to_alloc_type<_InputIterator>>,
+         class = enable_if_t<__is_cpp17_input_iterator<_InputIterator>::value, void>,
          class = enable_if_t<!__is_allocator<_Compare>::value, void>,
          class = enable_if_t<__is_allocator<_Allocator>::value, void>>
 multimap(_InputIterator, _InputIterator, _Compare = _Compare(), _Allocator = _Allocator())
@@ -2187,6 +2225,7 @@
   -> multimap<remove_const_t<_Key>, _Tp, _Compare, _Allocator>;
 
 template<class _InputIterator, class _Allocator,
+         class = enable_if_t<__is_cpp17_input_iterator<_InputIterator>::value, void>,
          class = enable_if_t<__is_allocator<_Allocator>::value, void>>
 multimap(_InputIterator, _InputIterator, _Allocator)
   -> multimap<__iter_key_type<_InputIterator>, __iter_mapped_type<_InputIterator>,
diff --git a/libcxx/include/set b/libcxx/include/set
--- a/libcxx/include/set
+++ b/libcxx/include/set
@@ -183,6 +183,25 @@
         pair<const_iterator,const_iterator> equal_range(const K& x) const;  // C++14
 };
 
+template <class InputIterator,
+      class Compare = less<typename iterator_traits<InputIterator>::value_type>,
+      class Allocator = allocator<typename iterator_traits<InputIterator>::value_type>>
+set(InputIterator, InputIterator,
+    Compare = Compare(), Allocator = Allocator())
+  -> set<typename iterator_traits<InputIterator>::value_type, Compare, Allocator>;
+
+template<class Key, class Compare = less<Key>, class Allocator = allocator<Key>>
+set(initializer_list<Key>, Compare = Compare(), Allocator = Allocator())
+  -> set<Key, Compare, Allocator>;
+
+template<class InputIterator, class Allocator>
+set(InputIterator, InputIterator, Allocator)
+  -> set<typename iterator_traits<InputIterator>::value_type,
+          less<typename iterator_traits<InputIterator>::value_type>, Allocator>;
+
+template<class Key, class Allocator>
+set(initializer_list<Key>, Allocator) -> set<Key, less<Key>, Allocator>;
+
 template <class Key, class Compare, class Allocator>
 bool
 operator==(const set<Key, Compare, Allocator>& x,
@@ -389,6 +408,25 @@
         pair<const_iterator,const_iterator> equal_range(const K& x) const;  // C++14
 };
 
+template <class InputIterator,
+      class Compare = less<typename iterator_traits<InputIterator>::value_type>,
+      class Allocator = allocator<typename iterator_traits<InputIterator>::value_type>>
+multiset(InputIterator, InputIterator,
+    Compare = Compare(), Allocator = Allocator())
+  -> multiset<typename iterator_traits<InputIterator>::value_type, Compare, Allocator>;
+
+template<class Key, class Compare = less<Key>, class Allocator = allocator<Key>>
+multiset(initializer_list<Key>, Compare = Compare(), Allocator = Allocator())
+  -> multiset<Key, Compare, Allocator>;
+
+template<class InputIterator, class Allocator>
+multiset(InputIterator, InputIterator, Allocator)
+  -> multiset<typename iterator_traits<InputIterator>::value_type,
+          less<typename iterator_traits<InputIterator>::value_type>, Allocator>;
+
+template<class Key, class Allocator>
+multiset(initializer_list<Key>, Allocator) -> multiset<Key, less<Key>, Allocator>;
+
 template <class Key, class Compare, class Allocator>
 bool
 operator==(const multiset<Key, Compare, Allocator>& x,
@@ -436,6 +474,7 @@
 #include <__config>
 #include <__debug>
 #include <__functional/is_transparent.h>
+#include <__iterator/iterator_traits.h>
 #include <__node_handle>
 #include <__tree>
 #include <__utility/forward.h>
@@ -462,7 +501,7 @@
     // types:
     typedef _Key                                     key_type;
     typedef key_type                                 value_type;
-    typedef _Compare                                 key_compare;
+    typedef __identity_t<_Compare>                   key_compare;
     typedef key_compare                              value_compare;
     typedef __identity_t<_Allocator>                 allocator_type;
     typedef value_type&                              reference;
@@ -474,7 +513,6 @@
 private:
     typedef __tree<value_type, value_compare, allocator_type> __base;
     typedef allocator_traits<allocator_type>                  __alloc_traits;
-    typedef typename __base::__node_holder                    __node_holder;
 
     __base __tree_;
 
@@ -872,6 +910,7 @@
 template<class _InputIterator,
          class _Compare = less<__iter_value_type<_InputIterator>>,
          class _Allocator = allocator<__iter_value_type<_InputIterator>>,
+         class = enable_if_t<__is_cpp17_input_iterator<_InputIterator>::value, void>,
          class = enable_if_t<__is_allocator<_Allocator>::value, void>,
          class = enable_if_t<!__is_allocator<_Compare>::value, void>>
 set(_InputIterator, _InputIterator, _Compare = _Compare(), _Allocator = _Allocator())
@@ -879,12 +918,13 @@
 
 template<class _Key, class _Compare = less<_Key>,
          class _Allocator = allocator<_Key>,
-         class = enable_if_t<__is_allocator<_Allocator>::value, void>,
-         class = enable_if_t<!__is_allocator<_Compare>::value, void>>
+         class = enable_if_t<!__is_allocator<_Compare>::value, void>,
+         class = enable_if_t<__is_allocator<_Allocator>::value, void>>
 set(initializer_list<_Key>, _Compare = _Compare(), _Allocator = _Allocator())
   -> set<_Key, _Compare, _Allocator>;
 
 template<class _InputIterator, class _Allocator,
+         class = enable_if_t<__is_cpp17_input_iterator<_InputIterator>::value, void>,
          class = enable_if_t<__is_allocator<_Allocator>::value, void>>
 set(_InputIterator, _InputIterator, _Allocator)
   -> set<__iter_value_type<_InputIterator>,
@@ -994,7 +1034,7 @@
     // types:
     typedef _Key                                     key_type;
     typedef key_type                                 value_type;
-    typedef _Compare                                 key_compare;
+    typedef __identity_t<_Compare>                   key_compare;
     typedef key_compare                              value_compare;
     typedef __identity_t<_Allocator>                 allocator_type;
     typedef value_type&                              reference;
@@ -1006,7 +1046,6 @@
 private:
     typedef __tree<value_type, value_compare, allocator_type> __base;
     typedef allocator_traits<allocator_type>                  __alloc_traits;
-    typedef typename __base::__node_holder                    __node_holder;
 
     __base __tree_;
 
@@ -1403,6 +1442,7 @@
 template<class _InputIterator,
          class _Compare = less<__iter_value_type<_InputIterator>>,
          class _Allocator = allocator<__iter_value_type<_InputIterator>>,
+         class = enable_if_t<__is_cpp17_input_iterator<_InputIterator>::value, void>,
          class = enable_if_t<__is_allocator<_Allocator>::value, void>,
          class = enable_if_t<!__is_allocator<_Compare>::value, void>>
 multiset(_InputIterator, _InputIterator, _Compare = _Compare(), _Allocator = _Allocator())
@@ -1416,6 +1456,7 @@
   -> multiset<_Key, _Compare, _Allocator>;
 
 template<class _InputIterator, class _Allocator,
+         class = enable_if_t<__is_cpp17_input_iterator<_InputIterator>::value, void>,
          class = enable_if_t<__is_allocator<_Allocator>::value, void>>
 multiset(_InputIterator, _InputIterator, _Allocator)
   -> multiset<__iter_value_type<_InputIterator>,
diff --git a/libcxx/include/unordered_map b/libcxx/include/unordered_map
--- a/libcxx/include/unordered_map
+++ b/libcxx/include/unordered_map
@@ -216,6 +216,46 @@
     void reserve(size_type n);
 };
 
+template<class InputIterator,
+    class Hash = hash<iter_key_t<InputIterator>>, class Pred = equal_to<iter_key_t<InputIterator>>,
+    class Allocator = allocator<iter_to_alloc_t<InputIterator>>>
+unordered_map(InputIterator, InputIterator, typename see below::size_type = see below,
+    Hash = Hash(), Pred = Pred(), Allocator = Allocator())
+    -> unordered_map<iter_key_t<InputIterator>, iter_value_t<InputIterator>, Hash, Pred, Allocator>;
+
+template<class Key, class T, class Hash = hash<Key>,
+    class Pred = equal_to<Key>, class Allocator = allocator<pair<const Key, T>>>
+unordered_map(initializer_list<pair<const Key, T>>, typename see below::size_type = see below,
+    Hash = Hash(), Pred = Pred(), Allocator = Allocator())
+  -> unordered_map<Key, T, Hash, Pred, Allocator>;
+
+template<class InputIterator, class Allocator>
+unordered_map(InputIterator, InputIterator, typename see below::size_type, Allocator)
+    -> unordered_map<iter_key_t<InputIterator>, iter_val_t<InputIterator>,
+          hash<iter_key_t<InputIterator>>, equal_to<iter_key_t<InputIterator>>, Allocator>;
+
+template<class InputIterator, class Allocator>
+unordered_map(InputIterator, InputIterator, Allocator)
+    -> unordered_map<iter_key_t<InputIterator>, iter_val_t<InputIterator>,
+          hash<iter_key_t<InputIterator>>, equal_to<iter_key_t<InputIterator>>, Allocator>;
+
+template<class InputIterator, class Hash, class Allocator>
+unordered_map(InputIterator, InputIterator, typename see below::size_type, Hash, Allocator)
+    -> unordered_map<iter_key_t<InputIterator>, iter_val_t<InputIterator>, Hash,
+            equal_to<iter_key_t<InputIterator>>, Allocator>;
+
+template<class Key, class T, typename Allocator>
+unordered_map(initializer_list<pair<const Key, T>>, typename see below::size_type, Allocator)
+      -> unordered_map<Key, T, hash<Key>, equal_to<Key>, Allocator>;
+
+template<class Key, class T, typename Allocator>
+unordered_map(initializer_list<pair<const Key, T>>, Allocator)
+      -> unordered_map<Key, T, hash<Key>, equal_to<Key>, Allocator>;
+
+template<class Key, class T, class Hash, class Allocator>
+unordered_map(initializer_list<pair<const Key, T>>, typename see below::size_type, Hash, Allocator)
+  -> unordered_map<Key, T, Hash, equal_to<Key>, Allocator>;
+
 template <class Key, class T, class Hash, class Pred, class Alloc>
     void swap(unordered_map<Key, T, Hash, Pred, Alloc>& x,
               unordered_map<Key, T, Hash, Pred, Alloc>& y)
@@ -404,6 +444,46 @@
     void reserve(size_type n);
 };
 
+template<class InputIterator,
+    class Hash = hash<iter_key_t<InputIterator>>, class Pred = equal_to<iter_key_t<InputIterator>>,
+    class Allocator = allocator<iter_to_alloc_t<InputIterator>>>
+unordered_multimap(InputIterator, InputIterator, typename see below::size_type = see below,
+    Hash = Hash(), Pred = Pred(), Allocator = Allocator())
+    -> unordered_multimap<iter_key_t<InputIterator>, iter_value_t<InputIterator>, Hash, Pred, Allocator>;
+
+template<class Key, class T, class Hash = hash<Key>,
+    class Pred = equal_to<Key>, class Allocator = allocator<pair<const Key, T>>>
+unordered_multimap(initializer_list<pair<const Key, T>>, typename see below::size_type = see below,
+    Hash = Hash(), Pred = Pred(), Allocator = Allocator())
+  -> unordered_multimap<Key, T, Hash, Pred, Allocator>;
+
+template<class InputIterator, class Allocator>
+unordered_multimap(InputIterator, InputIterator, typename see below::size_type, Allocator)
+    -> unordered_multimap<iter_key_t<InputIterator>, iter_val_t<InputIterator>,
+          hash<iter_key_t<InputIterator>>, equal_to<iter_key_t<InputIterator>>, Allocator>;
+
+template<class InputIterator, class Allocator>
+unordered_multimap(InputIterator, InputIterator, Allocator)
+    -> unordered_multimap<iter_key_t<InputIterator>, iter_val_t<InputIterator>,
+          hash<iter_key_t<InputIterator>>, equal_to<iter_key_t<InputIterator>>, Allocator>;
+
+template<class InputIterator, class Hash, class Allocator>
+unordered_multimap(InputIterator, InputIterator, typename see below::size_type, Hash, Allocator)
+    -> unordered_multimap<iter_key_t<InputIterator>, iter_val_t<InputIterator>, Hash,
+            equal_to<iter_key_t<InputIterator>>, Allocator>;
+
+template<class Key, class T, typename Allocator>
+unordered_multimap(initializer_list<pair<const Key, T>>, typename see below::size_type, Allocator)
+      -> unordered_multimap<Key, T, hash<Key>, equal_to<Key>, Allocator>;
+
+template<class Key, class T, typename Allocator>
+unordered_multimap(initializer_list<pair<const Key, T>>, Allocator)
+      -> unordered_multimap<Key, T, hash<Key>, equal_to<Key>, Allocator>;
+
+template<class Key, class T, class Hash, class Allocator>
+unordered_multimap(initializer_list<pair<const Key, T>>, typename see below::size_type, Hash, Allocator)
+  -> unordered_multimap<Key, T, Hash, equal_to<Key>, Allocator>;
+
 template <class Key, class T, class Hash, class Pred, class Alloc>
     void swap(unordered_multimap<Key, T, Hash, Pred, Alloc>& x,
               unordered_multimap<Key, T, Hash, Pred, Alloc>& y)
@@ -434,6 +514,7 @@
 #include <__config>
 #include <__debug>
 #include <__functional/is_transparent.h>
+#include <__iterator/iterator_traits.h>
 #include <__hash_table>
 #include <__node_handle>
 #include <__utility/forward.h>
@@ -1470,6 +1551,7 @@
          class _Hash = hash<__iter_key_type<_InputIterator>>,
          class _Pred = equal_to<__iter_key_type<_InputIterator>>,
          class _Allocator = allocator<__iter_to_alloc_type<_InputIterator>>,
+         class = enable_if_t<__is_cpp17_input_iterator<_InputIterator>::value>,
          class = enable_if_t<!__is_allocator<_Hash>::value>,
          class = enable_if_t<!is_integral<_Hash>::value>,
          class = enable_if_t<!__is_allocator<_Pred>::value>,
@@ -1490,18 +1572,21 @@
   -> unordered_map<remove_const_t<_Key>, _Tp, _Hash, _Pred, _Allocator>;
 
 template<class _InputIterator, class _Allocator,
+         class = enable_if_t<__is_cpp17_input_iterator<_InputIterator>::value>,
          class = enable_if_t<__is_allocator<_Allocator>::value>>
 unordered_map(_InputIterator, _InputIterator, typename allocator_traits<_Allocator>::size_type, _Allocator)
   -> unordered_map<__iter_key_type<_InputIterator>, __iter_mapped_type<_InputIterator>,
                    hash<__iter_key_type<_InputIterator>>, equal_to<__iter_key_type<_InputIterator>>, _Allocator>;
 
 template<class _InputIterator, class _Allocator,
+         class = enable_if_t<__is_cpp17_input_iterator<_InputIterator>::value>,
          class = enable_if_t<__is_allocator<_Allocator>::value>>
 unordered_map(_InputIterator, _InputIterator, _Allocator)
   -> unordered_map<__iter_key_type<_InputIterator>, __iter_mapped_type<_InputIterator>,
                    hash<__iter_key_type<_InputIterator>>, equal_to<__iter_key_type<_InputIterator>>, _Allocator>;
 
 template<class _InputIterator, class _Hash, class _Allocator,
+         class = enable_if_t<__is_cpp17_input_iterator<_InputIterator>::value>,
          class = enable_if_t<!__is_allocator<_Hash>::value>,
          class = enable_if_t<!is_integral<_Hash>::value>,
          class = enable_if_t<__is_allocator<_Allocator>::value>>
@@ -2268,6 +2353,7 @@
          class _Hash = hash<__iter_key_type<_InputIterator>>,
          class _Pred = equal_to<__iter_key_type<_InputIterator>>,
          class _Allocator = allocator<__iter_to_alloc_type<_InputIterator>>,
+         class = enable_if_t<__is_cpp17_input_iterator<_InputIterator>::value>,
          class = enable_if_t<!__is_allocator<_Hash>::value>,
          class = enable_if_t<!is_integral<_Hash>::value>,
          class = enable_if_t<!__is_allocator<_Pred>::value>,
@@ -2288,18 +2374,21 @@
   -> unordered_multimap<remove_const_t<_Key>, _Tp, _Hash, _Pred, _Allocator>;
 
 template<class _InputIterator, class _Allocator,
+         class = enable_if_t<__is_cpp17_input_iterator<_InputIterator>::value>,
          class = enable_if_t<__is_allocator<_Allocator>::value>>
 unordered_multimap(_InputIterator, _InputIterator, typename allocator_traits<_Allocator>::size_type, _Allocator)
   -> unordered_multimap<__iter_key_type<_InputIterator>, __iter_mapped_type<_InputIterator>,
                         hash<__iter_key_type<_InputIterator>>, equal_to<__iter_key_type<_InputIterator>>, _Allocator>;
 
 template<class _InputIterator, class _Allocator,
+         class = enable_if_t<__is_cpp17_input_iterator<_InputIterator>::value>,
          class = enable_if_t<__is_allocator<_Allocator>::value>>
 unordered_multimap(_InputIterator, _InputIterator, _Allocator)
   -> unordered_multimap<__iter_key_type<_InputIterator>, __iter_mapped_type<_InputIterator>,
                         hash<__iter_key_type<_InputIterator>>, equal_to<__iter_key_type<_InputIterator>>, _Allocator>;
 
 template<class _InputIterator, class _Hash, class _Allocator,
+         class = enable_if_t<__is_cpp17_input_iterator<_InputIterator>::value>,
          class = enable_if_t<!__is_allocator<_Hash>::value>,
          class = enable_if_t<!is_integral<_Hash>::value>,
          class = enable_if_t<__is_allocator<_Allocator>::value>>
diff --git a/libcxx/include/unordered_set b/libcxx/include/unordered_set
--- a/libcxx/include/unordered_set
+++ b/libcxx/include/unordered_set
@@ -182,6 +182,43 @@
     void reserve(size_type n);
 };
 
+template<class InputIterator,
+    class Hash = hash<typename iterator_traits<InputIterator>::value_type>,
+    class Pred = equal_to<typename iterator_traits<InputIterator>::value_type>,
+    class Allocator = allocator<typename iterator_traits<InputIterator>::value_type>>
+unordered_set(InputIterator, InputIterator, typename see below::size_type = see below,
+    Hash = Hash(), Pred = Pred(), Allocator = Allocator())
+  -> unordered_set<typename iterator_traits<InputIterator>::value_type,
+        Hash, Pred, Allocator>;
+
+template<class T, class Hash = hash<T>,
+          class Pred = equal_to<T>, class Allocator = allocator<T>>
+unordered_set(initializer_list<T>, typename see below::size_type = see below,
+    Hash = Hash(), Pred = Pred(), Allocator = Allocator())
+  -> unordered_set<T, Hash, Pred, Allocator>;
+
+template<class InputIterator,  class Allocator>
+unordered_set(InputIterator, InputIterator, typename see below::size_type, Allocator)
+  -> unordered_set<typename iterator_traits<InputIterator>::value_type,
+        hash<typename iterator_traits<InputIterator>::value_type>,
+        equal_to<typename iterator_traits<InputIterator>::value_type>,
+        Allocator>;
+
+template<class InputIterator, class Hash, class Allocator>
+unordered_set(InputIterator, InputIterator, typename see below::size_type,
+    Hash, Allocator)
+  -> unordered_set<typename iterator_traits<InputIterator>::value_type, Hash,
+        equal_to<typename iterator_traits<InputIterator>::value_type>,
+        Allocator>;
+
+template<class T, class Allocator>
+unordered_set(initializer_list<T>, typename see below::size_type, Allocator)
+  -> unordered_set<T, hash<T>, equal_to<T>, Allocator>;
+
+template<class T, class Hash, class Allocator>
+unordered_set(initializer_list<T>, typename see below::size_type, Hash, Allocator)
+  -> unordered_set<T, Hash, equal_to<T>, Allocator>;
+
 template <class Value, class Hash, class Pred, class Alloc>
     void swap(unordered_set<Value, Hash, Pred, Alloc>& x,
               unordered_set<Value, Hash, Pred, Alloc>& y)
@@ -359,6 +396,42 @@
     void reserve(size_type n);
 };
 
+template<class InputIterator,
+    class Hash = hash<typename iterator_traits<InputIterator>::value_type>,
+    class Pred = equal_to<typename iterator_traits<InputIterator>::value_type>,
+    class Allocator = allocator<typename iterator_traits<InputIterator>::value_type>>
+unordered_multiset(InputIterator, InputIterator, see below::size_type = see below,
+    Hash = Hash(), Pred = Pred(), Allocator = Allocator())
+  -> unordered_multiset<typename iterator_traits<InputIterator>::value_type,
+        Hash, Pred, Allocator>;
+
+template<class T, class Hash = hash<T>,
+          class Pred = equal_to<T>, class Allocator = allocator<T>>
+unordered_multiset(initializer_list<T>, typename see below::size_type = see below,
+    Hash = Hash(), Pred = Pred(), Allocator = Allocator())
+  -> unordered_multiset<T, Hash, Pred, Allocator>;
+
+template<class InputIterator,  class Allocator>
+unordered_multiset(InputIterator, InputIterator, typename see below::size_type, Allocator)
+  -> unordered_multiset<typename iterator_traits<InputIterator>::value_type,
+        hash<typename iterator_traits<InputIterator>::value_type>,
+        equal_to<typename iterator_traits<InputIterator>::value_type>,
+        Allocator>;
+
+template<class InputIterator,  class Hash, class Allocator>
+unordered_multiset(InputIterator, InputIterator, typename see below::size_type,
+    Hash, Allocator)
+  -> unordered_multiset<typename iterator_traits<InputIterator>::value_type, Hash,
+        equal_to<typename iterator_traits<InputIterator>::value_type>, Allocator>;
+
+template<class T, class Allocator>
+unordered_multiset(initializer_list<T>, typename see below::size_type, Allocator)
+  -> unordered_multiset<T, hash<T>, equal_to<T>, Allocator>;
+
+template<class T, class Hash, class Allocator>
+unordered_multiset(initializer_list<T>, typename see below::size_type, Hash, Allocator)
+  -> unordered_multiset<T, Hash, equal_to<T>, Allocator>;
+
 template <class Value, class Hash, class Pred, class Alloc>
     void swap(unordered_multiset<Value, Hash, Pred, Alloc>& x,
               unordered_multiset<Value, Hash, Pred, Alloc>& y)
diff --git a/libcxx/include/vector b/libcxx/include/vector
--- a/libcxx/include/vector
+++ b/libcxx/include/vector
@@ -275,6 +275,7 @@
 #include <__bit_reference>
 #include <__debug>
 #include <__functional_base>
+#include <__iterator/iterator_traits.h>
 #include <__iterator/wrap_iter.h>
 #include <__split_buffer>
 #include <__utility/forward.h>
@@ -479,23 +480,23 @@
     : private __vector_base<_Tp, _Allocator>
 {
 private:
-    typedef __vector_base<_Tp, _Allocator>           __base;
-    typedef allocator<_Tp>                           __default_allocator_type;
+    typedef __vector_base<_Tp, _Allocator>                           __base;
+    typedef allocator<_Tp>                                           __default_allocator_type;
 public:
-    typedef vector                                   __self;
-    typedef _Tp                                      value_type;
-    typedef _Allocator                               allocator_type;
-    typedef typename __base::__alloc_traits          __alloc_traits;
-    typedef typename __base::reference               reference;
-    typedef typename __base::const_reference         const_reference;
-    typedef typename __base::size_type               size_type;
-    typedef typename __base::difference_type         difference_type;
-    typedef typename __base::pointer                 pointer;
-    typedef typename __base::const_pointer           const_pointer;
-    typedef __wrap_iter<pointer>                     iterator;
-    typedef __wrap_iter<const_pointer>               const_iterator;
-    typedef _VSTD::reverse_iterator<iterator>         reverse_iterator;
-    typedef _VSTD::reverse_iterator<const_iterator>   const_reverse_iterator;
+    typedef vector                                                   __self;
+    typedef _Tp                                                      value_type;
+    typedef _Allocator                                               allocator_type;
+    typedef typename __base::__alloc_traits                          __alloc_traits;
+    typedef typename __base::reference                               reference;
+    typedef typename __base::const_reference                         const_reference;
+    typedef typename __allocator_traits<allocator_type>::size_type   size_type;
+    typedef typename __base::difference_type                         difference_type;
+    typedef typename __base::pointer                                 pointer;
+    typedef typename __base::const_pointer                           const_pointer;
+    typedef __wrap_iter<pointer>                                     iterator;
+    typedef __wrap_iter<const_pointer>                               const_iterator;
+    typedef _VSTD::reverse_iterator<iterator>                        reverse_iterator;
+    typedef _VSTD::reverse_iterator<const_iterator>                  const_reverse_iterator;
 
     static_assert((is_same<typename allocator_type::value_type, value_type>::value),
                   "Allocator::value_type must be same type as value_type");
@@ -939,6 +940,7 @@
 #if _LIBCPP_STD_VER >= 17
 template<class _InputIterator,
          class _Alloc = allocator<__iter_value_type<_InputIterator>>,
+         class = enable_if_t<__is_cpp17_input_iterator<_InputIterator>::value>,
          class = enable_if_t<__is_allocator<_Alloc>::value>
          >
 vector(_InputIterator, _InputIterator)
@@ -946,6 +948,7 @@
 
 template<class _InputIterator,
          class _Alloc,
+         class = enable_if_t<__is_cpp17_input_iterator<_InputIterator>::value>,
          class = enable_if_t<__is_allocator<_Alloc>::value>
          >
 vector(_InputIterator, _InputIterator, _Alloc)
diff --git a/libcxx/test/std/containers/associative/map/map.cons/deduct.pass.cpp b/libcxx/test/std/containers/associative/map/map.cons/deduct.pass.cpp
--- a/libcxx/test/std/containers/associative/map/map.cons/deduct.pass.cpp
+++ b/libcxx/test/std/containers/associative/map/map.cons/deduct.pass.cpp
@@ -32,6 +32,7 @@
 #include <map>
 #include <type_traits>
 
+#include "deduction_guides_sfinae_checks.h"
 #include "test_allocator.h"
 
 using P = std::pair<int, long>;
@@ -151,5 +152,7 @@
     ASSERT_SAME_TYPE(decltype(m2), std::map<int, int>);
     }
 
+    AssociativeContainerDeductionGuidesSfinaeAway<std::map, PC>();
+
     return 0;
 }
diff --git a/libcxx/test/std/containers/associative/multimap/multimap.cons/deduct.pass.cpp b/libcxx/test/std/containers/associative/multimap/multimap.cons/deduct.pass.cpp
--- a/libcxx/test/std/containers/associative/multimap/multimap.cons/deduct.pass.cpp
+++ b/libcxx/test/std/containers/associative/multimap/multimap.cons/deduct.pass.cpp
@@ -32,6 +32,7 @@
 #include <map>
 #include <type_traits>
 
+#include "deduction_guides_sfinae_checks.h"
 #include "test_allocator.h"
 
 using P = std::pair<int, long>;
@@ -151,5 +152,7 @@
     ASSERT_SAME_TYPE(decltype(m2), std::multimap<int, int>);
     }
 
+    AssociativeContainerDeductionGuidesSfinaeAway<std::multimap, PC>();
+
     return 0;
 }
diff --git a/libcxx/test/std/containers/associative/multiset/multiset.cons/deduct.pass.cpp b/libcxx/test/std/containers/associative/multiset/multiset.cons/deduct.pass.cpp
--- a/libcxx/test/std/containers/associative/multiset/multiset.cons/deduct.pass.cpp
+++ b/libcxx/test/std/containers/associative/multiset/multiset.cons/deduct.pass.cpp
@@ -35,6 +35,7 @@
 #include <set>
 #include <type_traits>
 
+#include "deduction_guides_sfinae_checks.h"
 #include "test_allocator.h"
 
 struct NotAnAllocator {
@@ -186,5 +187,7 @@
     assert(s.size() == 2);
   }
 
+  AssociativeContainerDeductionGuidesSfinaeAway<std::multiset, int>();
+
   return 0;
 }
diff --git a/libcxx/test/std/containers/associative/set/set.cons/deduct.pass.cpp b/libcxx/test/std/containers/associative/set/set.cons/deduct.pass.cpp
--- a/libcxx/test/std/containers/associative/set/set.cons/deduct.pass.cpp
+++ b/libcxx/test/std/containers/associative/set/set.cons/deduct.pass.cpp
@@ -35,6 +35,7 @@
 #include <set>
 #include <type_traits>
 
+#include "deduction_guides_sfinae_checks.h"
 #include "test_allocator.h"
 
 struct NotAnAllocator {
@@ -184,5 +185,7 @@
     assert(s.size() == 2);
   }
 
-  return 0;
+    AssociativeContainerDeductionGuidesSfinaeAway<std::set, int>();
+
+    return 0;
 }
diff --git a/libcxx/test/std/containers/container.adaptors/priority.queue/priqueue.cons/deduct.pass.cpp b/libcxx/test/std/containers/container.adaptors/priority.queue/priqueue.cons/deduct.pass.cpp
--- a/libcxx/test/std/containers/container.adaptors/priority.queue/priqueue.cons/deduct.pass.cpp
+++ b/libcxx/test/std/containers/container.adaptors/priority.queue/priqueue.cons/deduct.pass.cpp
@@ -31,6 +31,7 @@
 #include <cstddef>
 #include <climits> // INT_MAX
 
+#include "sfinaes_away.h"
 #include "test_macros.h"
 #include "test_iterators.h"
 #include "test_allocator.h"
@@ -239,5 +240,105 @@
         }
     }
 
+    // Deduction guides should be SFINAE'd away when given:
+    // - "bad" input iterators (that is, a type not qualifying as an input
+    //   iterator);
+    // - a bad allocator;
+    // - an allocator instead of a comparator;
+    // - an allocator instead of a container;
+    // - an allocator and a container that uses a different allocator.
+
+    // (iter, iter)
+    // (iter, iter, comp)
+    // (iter, iter, comp, cont)
+    //
+    // (iter, iter, alloc)
+    //
+    // (iter, iter, comp, alloc)
+    //
+    // (iter, iter, comp, cont, alloc)
+    //
+    // (comp, cont)
+    //
+    // (comp, cont, alloc)
+    {
+        using Comp = std::less<int>;
+        using Cont = std::vector<int>;
+        using Alloc = std::allocator<int>;
+        using Iter = int*;
+
+        struct BadAlloc {};
+        struct BadIter {};
+        using AllocAsComp = Alloc;
+        using AllocAsCont = Alloc;
+        using DiffAlloc = test_allocator<int>;
+
+        // (iter, iter)
+        //
+        // Cannot deduce from (BAD_iter, BAD_iter)
+        static_assert(SFINAEs_away<std::priority_queue, BadIter, BadIter>);
+
+        // (iter, iter, comp)
+        //
+        // Cannot deduce from (BAD_iter, BAD_iter, comp)
+        static_assert(SFINAEs_away<std::priority_queue, BadIter, BadIter, Comp>);
+        // Note: (iter, iter, ALLOC_as_comp) is allowed -- it just calls (iter, iter, alloc).
+
+        // (iter, iter, comp, cont)
+        //
+        // Cannot deduce from (BAD_iter, BAD_iter, comp, cont)
+        static_assert(SFINAEs_away<std::priority_queue, BadIter, BadIter, Comp, Cont>);
+        // Cannot deduce from (iter, iter, ALLOC_as_comp, cont)
+        static_assert(SFINAEs_away<std::priority_queue, Iter, Iter, AllocAsComp, Cont>);
+        // Note: (iter, iter, comp, ALLOC_as_cont) is allowed -- it just calls (iter, iter, comp,
+        // alloc).
+
+        // (iter, iter, alloc)
+        //
+        // Cannot deduce from (BAD_iter, BAD_iter, alloc)
+        static_assert(SFINAEs_away<std::priority_queue, BadIter, BadIter, Alloc>);
+        // Note: (iter, iter, BAD_alloc) is interpreted as (iter, iter, comp) instead and fails upon
+        // instantiation. There is no requirement to SFINAE away bad comparators.
+
+        // (iter, iter, comp, alloc)
+        //
+        // Cannot deduce from (iter, iter, ALLOC_as_comp, alloc)
+        static_assert(SFINAEs_away<std::priority_queue, Iter, Iter, AllocAsComp, Alloc>);
+        // Note: (iter, iter, comp, BAD_alloc) is interpreted as (iter, iter, comp, cont) instead
+        // and fails upon instantiation. There is no requirement to SFINAE away bad containers.
+
+        // (iter, iter, comp, cont, alloc)
+        //
+        // Cannot deduce from (BAD_iter, BAD_iter, comp, cont, alloc)
+        static_assert(SFINAEs_away<std::priority_queue, BadIter, BadIter, Comp, Cont, Alloc>);
+        // Cannot deduce from (iter, iter, ALLOC_as_comp, cont, alloc)
+        static_assert(SFINAEs_away<std::priority_queue, Iter, Iter, AllocAsComp, Cont, Alloc>);
+        // Cannot deduce from (iter, iter, comp, cont, BAD_alloc)
+        static_assert(SFINAEs_away<std::priority_queue, Iter, Iter, Comp, Cont, BadAlloc>);
+        // Cannot deduce from (iter, iter, comp, cont, DIFFERENT_alloc)
+        static_assert(SFINAEs_away<std::priority_queue, Iter, Iter, Comp, Cont, DiffAlloc>);
+
+        // (comp, alloc)
+        //
+        // Cannot deduce from (ALLOC_as_comp, alloc)
+        static_assert(SFINAEs_away<std::priority_queue, AllocAsComp, Alloc>);
+        // Cannot deduce from (comp, BAD_alloc)
+        static_assert(SFINAEs_away<std::priority_queue, Comp, BadAlloc>);
+
+        // (comp, cont, alloc)
+        //
+        // Cannot deduce from (ALLOC_as_comp, cont, alloc)
+        static_assert(SFINAEs_away<std::priority_queue, AllocAsComp, Cont, Alloc>);
+        // Cannot deduce from (comp, cont, BAD_alloc)
+        static_assert(SFINAEs_away<std::priority_queue, Comp, Cont, BadAlloc>);
+        // Cannot deduce from (comp, cont, DIFFERENT_alloc)
+        static_assert(SFINAEs_away<std::priority_queue, Comp, Cont, DiffAlloc>);
+
+        // (comp, cont)
+        //
+        // Cannot deduce from (ALLOC_as_comp, cont)
+        static_assert(SFINAEs_away<std::priority_queue, AllocAsComp, Cont>);
+    }
+
     return 0;
 }
diff --git a/libcxx/test/std/containers/container.adaptors/queue/queue.cons/deduct.pass.cpp b/libcxx/test/std/containers/container.adaptors/queue/queue.cons/deduct.pass.cpp
--- a/libcxx/test/std/containers/container.adaptors/queue/queue.cons/deduct.pass.cpp
+++ b/libcxx/test/std/containers/container.adaptors/queue/queue.cons/deduct.pass.cpp
@@ -21,8 +21,8 @@
 #include <iterator>
 #include <cassert>
 #include <cstddef>
-#include <climits> // INT_MAX
 
+#include "sfinaes_away.h"
 #include "test_macros.h"
 #include "test_iterators.h"
 #include "test_allocator.h"
@@ -133,5 +133,27 @@
         }
     }
 
+    // Deduction guides should be SFINAE'd away when given:
+    // - a "bad" allocator (that is, a type not qualifying as an allocator);
+    // - an allocator instead of a container;
+    // - an allocator and a container that uses a different allocator.
+    {
+        using Cont = std::list<int>;
+        using Alloc = std::allocator<int>;
+        using DiffAlloc = test_allocator<int>;
+
+        struct BadAlloc {};
+        using AllocAsCont = Alloc;
+
+        // (cont, alloc)
+        //
+        // Cannot deduce from (ALLOC_as_cont, alloc)
+        static_assert(SFINAEs_away<std::queue, AllocAsCont, BadAlloc>);
+        // Cannot deduce from (cont, BAD_alloc)
+        static_assert(SFINAEs_away<std::queue, Cont, BadAlloc>);
+        // Cannot deduce from (cont, DIFFERENT_alloc)
+        static_assert(SFINAEs_away<std::queue, Cont, DiffAlloc>);
+    }
+
     return 0;
 }
diff --git a/libcxx/test/std/containers/container.adaptors/stack/stack.cons/deduct.pass.cpp b/libcxx/test/std/containers/container.adaptors/stack/stack.cons/deduct.pass.cpp
--- a/libcxx/test/std/containers/container.adaptors/stack/stack.cons/deduct.pass.cpp
+++ b/libcxx/test/std/containers/container.adaptors/stack/stack.cons/deduct.pass.cpp
@@ -25,6 +25,7 @@
 #include <cstddef>
 #include <climits> // INT_MAX
 
+#include "sfinaes_away.h"
 #include "test_macros.h"
 #include "test_iterators.h"
 #include "test_allocator.h"
@@ -136,5 +137,27 @@
         }
     }
 
+    // Deduction guides should be SFINAE'd away when given:
+    // - a "bad" allocator (that is, a type not qualifying as an allocator);
+    // - an allocator instead of a container;
+    // - an allocator and a container that uses a different allocator.
+    {
+        using Cont = std::list<int>;
+        using Alloc = std::allocator<int>;
+        using DiffAlloc = test_allocator<int>;
+
+        struct BadAlloc {};
+        using AllocAsCont = Alloc;
+
+        // (cont, alloc)
+        //
+        // Cannot deduce from (ALLOC_as_cont, alloc)
+        static_assert(SFINAEs_away<std::stack, AllocAsCont, Alloc>);
+        // Cannot deduce from (cont, BAD_alloc)
+        static_assert(SFINAEs_away<std::stack, Cont, BadAlloc>);
+        // Cannot deduce from (cont, DIFFERENT_alloc)
+        static_assert(SFINAEs_away<std::stack, Cont, DiffAlloc>);
+    }
+
     return 0;
 }
diff --git a/libcxx/test/std/containers/sequences/deque/deque.cons/deduct.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.cons/deduct.pass.cpp
--- a/libcxx/test/std/containers/sequences/deque/deque.cons/deduct.pass.cpp
+++ b/libcxx/test/std/containers/sequences/deque/deque.cons/deduct.pass.cpp
@@ -20,6 +20,7 @@
 #include <cstddef>
 #include <climits> // INT_MAX
 
+#include "deduction_guides_sfinae_checks.h"
 #include "test_macros.h"
 #include "test_iterators.h"
 #include "test_allocator.h"
@@ -121,5 +122,7 @@
         }
     }
 
+    SequenceContainerDeductionGuidesSfinaeAway<std::deque>();
+
     return 0;
 }
diff --git a/libcxx/test/std/containers/sequences/forwardlist/forwardlist.cons/deduct.pass.cpp b/libcxx/test/std/containers/sequences/forwardlist/forwardlist.cons/deduct.pass.cpp
--- a/libcxx/test/std/containers/sequences/forwardlist/forwardlist.cons/deduct.pass.cpp
+++ b/libcxx/test/std/containers/sequences/forwardlist/forwardlist.cons/deduct.pass.cpp
@@ -20,6 +20,7 @@
 #include <cstddef>
 #include <climits> // INT_MAX
 
+#include "deduction_guides_sfinae_checks.h"
 #include "test_macros.h"
 #include "test_iterators.h"
 #include "test_allocator.h"
@@ -126,5 +127,7 @@
         }
     }
 
+    SequenceContainerDeductionGuidesSfinaeAway<std::forward_list>();
+
     return 0;
 }
diff --git a/libcxx/test/std/containers/sequences/list/list.cons/deduct.pass.cpp b/libcxx/test/std/containers/sequences/list/list.cons/deduct.pass.cpp
--- a/libcxx/test/std/containers/sequences/list/list.cons/deduct.pass.cpp
+++ b/libcxx/test/std/containers/sequences/list/list.cons/deduct.pass.cpp
@@ -20,6 +20,7 @@
 #include <cstddef>
 #include <climits> // INT_MAX
 
+#include "deduction_guides_sfinae_checks.h"
 #include "test_macros.h"
 #include "test_iterators.h"
 #include "test_allocator.h"
@@ -126,5 +127,7 @@
         }
     }
 
+    SequenceContainerDeductionGuidesSfinaeAway<std::list>();
+
     return 0;
 }
diff --git a/libcxx/test/std/containers/sequences/vector/vector.cons/deduct.pass.cpp b/libcxx/test/std/containers/sequences/vector/vector.cons/deduct.pass.cpp
--- a/libcxx/test/std/containers/sequences/vector/vector.cons/deduct.pass.cpp
+++ b/libcxx/test/std/containers/sequences/vector/vector.cons/deduct.pass.cpp
@@ -15,11 +15,13 @@
 //
 
 #include <vector>
-#include <iterator>
 #include <cassert>
 #include <cstddef>
 #include <climits> // INT_MAX
+#include <iterator>
+#include <type_traits>
 
+#include "deduction_guides_sfinae_checks.h"
 #include "test_macros.h"
 #include "test_iterators.h"
 #include "test_allocator.h"
@@ -139,5 +141,7 @@
         }
     }
 
+    SequenceContainerDeductionGuidesSfinaeAway<std::vector>();
+
     return 0;
 }
diff --git a/libcxx/test/std/containers/unord/unord.map/unord.map.cnstr/deduct.pass.cpp b/libcxx/test/std/containers/unord/unord.map/unord.map.cnstr/deduct.pass.cpp
--- a/libcxx/test/std/containers/unord/unord.map/unord.map.cnstr/deduct.pass.cpp
+++ b/libcxx/test/std/containers/unord/unord.map/unord.map.cnstr/deduct.pass.cpp
@@ -61,6 +61,7 @@
 #include <type_traits>
 #include <unordered_map>
 
+#include "deduction_guides_sfinae_checks.h"
 #include "test_allocator.h"
 
 using P = std::pair<int, long>;
@@ -218,5 +219,7 @@
     ASSERT_SAME_TYPE(decltype(m2), std::unordered_map<int, int>);
     }
 
+    UnorderedContainerDeductionGuidesSfinaeAway<std::unordered_map, PC>();
+
     return 0;
 }
diff --git a/libcxx/test/std/containers/unord/unord.multimap/unord.multimap.cnstr/deduct.pass.cpp b/libcxx/test/std/containers/unord/unord.multimap/unord.multimap.cnstr/deduct.pass.cpp
--- a/libcxx/test/std/containers/unord/unord.multimap/unord.multimap.cnstr/deduct.pass.cpp
+++ b/libcxx/test/std/containers/unord/unord.multimap/unord.multimap.cnstr/deduct.pass.cpp
@@ -61,6 +61,7 @@
 #include <type_traits>
 #include <unordered_map>
 
+#include "deduction_guides_sfinae_checks.h"
 #include "test_allocator.h"
 
 using P = std::pair<int, long>;
@@ -218,5 +219,7 @@
     ASSERT_SAME_TYPE(decltype(m2), std::unordered_multimap<int, int>);
     }
 
+    UnorderedContainerDeductionGuidesSfinaeAway<std::unordered_multimap, PC>();
+
     return 0;
 }
diff --git a/libcxx/test/std/containers/unord/unord.multiset/unord.multiset.cnstr/deduct.pass.cpp b/libcxx/test/std/containers/unord/unord.multiset/unord.multiset.cnstr/deduct.pass.cpp
--- a/libcxx/test/std/containers/unord/unord.multiset/unord.multiset.cnstr/deduct.pass.cpp
+++ b/libcxx/test/std/containers/unord/unord.multiset/unord.multiset.cnstr/deduct.pass.cpp
@@ -53,6 +53,7 @@
 #include <type_traits>
 #include <unordered_set>
 
+#include "deduction_guides_sfinae_checks.h"
 #include "test_allocator.h"
 
 int main(int, char**)
@@ -192,5 +193,7 @@
     assert(s.get_allocator().get_id() == 42);
     }
 
+    UnorderedContainerDeductionGuidesSfinaeAway<std::unordered_multiset, int>();
+
     return 0;
 }
diff --git a/libcxx/test/std/containers/unord/unord.set/unord.set.cnstr/deduct.pass.cpp b/libcxx/test/std/containers/unord/unord.set/unord.set.cnstr/deduct.pass.cpp
--- a/libcxx/test/std/containers/unord/unord.set/unord.set.cnstr/deduct.pass.cpp
+++ b/libcxx/test/std/containers/unord/unord.set/unord.set.cnstr/deduct.pass.cpp
@@ -53,6 +53,7 @@
 #include <type_traits>
 #include <unordered_set>
 
+#include "deduction_guides_sfinae_checks.h"
 #include "test_allocator.h"
 
 int main(int, char**)
@@ -192,5 +193,7 @@
     assert(s.get_allocator().get_id() == 42);
     }
 
+    UnorderedContainerDeductionGuidesSfinaeAway<std::unordered_set, int>();
+
     return 0;
 }
diff --git a/libcxx/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.ctor/deduct.fail.cpp b/libcxx/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.ctor/deduct.fail.cpp
new file mode 100644
--- /dev/null
+++ b/libcxx/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.ctor/deduct.fail.cpp
@@ -0,0 +1,74 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14
+
+// <memory>
+
+// unique_ptr
+
+// The following constructors should not be selected by class template argument
+// deduction:
+//
+// explicit unique_ptr(pointer p)
+// unique_ptr(pointer p, const D& d) noexcept
+// unique_ptr(pointer p, remove_reference_t<D>&& d) noexcept
+
+#include <memory>
+
+struct Deleter {
+  void operator()(int* p) const { delete p; }
+};
+
+int main(int, char**) {
+  // Cannot deduce from a raw pointer.
+  {
+    int* p = nullptr;
+    std::unique_ptr u(p);
+    // expected-error@-1 {{no viable constructor or deduction guide for deduction of template arguments of 'unique_ptr'}}
+  }
+
+  // Cannot deduce from a built-in array.
+  {
+    int p[] = {};
+    std::unique_ptr u(p);
+    // expected-error@-1 {{no viable constructor or deduction guide for deduction of template arguments of 'unique_ptr'}}
+  }
+
+  // Cannot deduce from a raw pointer and a Deleter&&.
+  {
+    int* p = nullptr;
+    std::unique_ptr u(p, Deleter{});
+    // expected-error@-1 {{no viable constructor or deduction guide for deduction of template arguments of 'unique_ptr'}}
+  }
+
+  // Cannot deduce from a built-in array and a Deleter&&.
+  {
+    int p[] = {};
+    std::unique_ptr u(p, Deleter{});
+    // expected-error@-1 {{no viable constructor or deduction guide for deduction of template arguments of 'unique_ptr'}}
+  }
+
+  // Cannot deduce from a raw pointer and a const Deleter&.
+  {
+    int* p = nullptr;
+    const Deleter d;
+    std::unique_ptr u(p, d);
+    // expected-error@-1 {{no viable constructor or deduction guide for deduction of template arguments of 'unique_ptr'}}
+  }
+
+  // Cannot deduce from a built-in array and a const Deleter&.
+  {
+    int p[] = {};
+    const Deleter d;
+    std::unique_ptr u(p, d);
+    // expected-error@-1 {{no viable constructor or deduction guide for deduction of template arguments of 'unique_ptr'}}
+  }
+
+  return 0;
+}
diff --git a/libcxx/test/support/deduction_guides_sfinae_checks.h b/libcxx/test/support/deduction_guides_sfinae_checks.h
new file mode 100644
--- /dev/null
+++ b/libcxx/test/support/deduction_guides_sfinae_checks.h
@@ -0,0 +1,292 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef TEST_SUPPORT_DEDUCTION_GUIDES_SFINAE_CHECKS_H
+#define TEST_SUPPORT_DEDUCTION_GUIDES_SFINAE_CHECKS_H
+
+#include <memory>
+
+#include "sfinaes_away.h"
+
+// For sequence containers the deduction guides should be SFINAE'd away when
+// given:
+// - "bad" input iterators (that is, a type not qualifying as an input
+//   iterator);
+// - a bad allocator.
+template<template<typename ...> class Container>
+constexpr void SequenceContainerDeductionGuidesSfinaeAway() {
+  using Alloc = std::allocator<int>;
+  using Iter = int*;
+
+  struct BadAlloc {};
+  struct BadIter {};
+
+  // (iter, iter)
+  //
+  // Cannot deduce from (BAD_iter, BAD_iter)
+  static_assert(SFINAEs_away<Container, BadIter, BadIter>);
+
+  // (iter, iter, alloc)
+  //
+  // Cannot deduce from (BAD_iter, BAD_iter, alloc)
+  static_assert(SFINAEs_away<Container, BadIter, BadIter, Alloc>);
+  // Cannot deduce from (iter, iter, BAD_alloc)
+  static_assert(SFINAEs_away<Container, Iter, Iter, BadAlloc>);
+
+  // (alloc)
+  //
+  // Cannot deduce from (alloc)
+  static_assert(SFINAEs_away<Container, Alloc>);
+}
+
+// For associative containers the deduction guides should be SFINAE'd away when
+// given:
+// - "bad" input iterators (that is, a type not qualifying as an input
+//   iterator);
+// - a bad allocator;
+// - an allocator in place of a comparator.
+
+template<template<typename ...> class Container, typename ValueType>
+constexpr void AssociativeContainerDeductionGuidesSfinaeAway() {
+  using Comp = std::less<int>;
+  using Alloc = std::allocator<ValueType>;
+  using Iter = ValueType*;
+  using InitList = std::initializer_list<ValueType>;
+
+  struct BadAlloc {};
+  struct BadIter {};
+  using AllocAsComp = Alloc;
+
+  // Possible deduction guides invocations:
+  //
+  // (iter, iter)
+  // (iter, iter, comp)
+  // (iter, iter, comp, alloc)
+  //
+  // (iter, iter, alloc)
+  //
+  // (init_list, comp)
+  // (init_list, comp, alloc)
+  //
+  // (init_list, alloc)
+
+  // (iter, iter)
+  //
+  // Cannot deduce from (BAD_iter, BAD_iter)
+  static_assert(SFINAEs_away<Container, BadIter, BadIter>);
+
+  // (iter, iter, comp)
+  //
+  // Cannot deduce from (BAD_iter, BAD_iter, comp)
+  static_assert(SFINAEs_away<Container, BadIter, BadIter, Comp>);
+
+  // (iter, iter, comp, alloc)
+  //
+  // Cannot deduce from (BAD_iter, BAD_iter, comp, alloc)
+  static_assert(SFINAEs_away<Container, BadIter, BadIter, Comp, Alloc>);
+  // Cannot deduce from (iter, iter, ALLOC_as_comp, alloc)
+  static_assert(SFINAEs_away<Container, Iter, Iter, AllocAsComp, Alloc>);
+  // Cannot deduce from (iter, iter, comp, BAD_alloc)
+  static_assert(SFINAEs_away<Container, Iter, Iter, Comp, BadAlloc>);
+
+  // (iter, iter, alloc)
+  //
+  // Cannot deduce from (BAD_iter, BAD_iter, alloc)
+  static_assert(SFINAEs_away<Container, BadIter, BadIter, Alloc>);
+  // Note: (iter, iter, BAD_alloc) is interpreted as (iter, iter, comp)
+  // instead and fails upon instantiation. There is no requirement to SFINAE
+  // away bad comparators.
+
+  // (init_list, comp, alloc)
+  //
+  // Cannot deduce from (init_list, ALLOC_as_comp, alloc)
+  // FIXME(varconst)
+  //static_assert(SFINAEs_away<Container, InitList, AllocAsComp, Alloc>);
+  // Cannot deduce from (init_list, comp, BAD_alloc)
+  static_assert(SFINAEs_away<Container, InitList, Comp, BadAlloc>);
+
+  // (init_list, alloc)
+  //
+  // Note: (init_list, BAD_alloc) is interpreted as (init_list, comp) instead
+  // and fails upon instantiation. There is no requirement to SFINAE away bad
+  // comparators.
+}
+
+// For unordered containers the deduction guides should be SFINAE'd away when
+// given:
+// - "bad" input iterators (that is, a type not qualifying as an input
+//   iterator);
+// - a bad allocator;
+// - a bad hash functor (an integral type in place of a hash);
+// - an allocator in place of a hash functor;
+// - an allocator in place of a predicate.
+template<template<typename ...> class Container, typename ValueType>
+constexpr void UnorderedContainerDeductionGuidesSfinaeAway() {
+  using Pred = std::equal_to<int>;
+  using Hash = std::hash<int>;
+  using Alloc = std::allocator<ValueType>;
+  using Iter = ValueType*;
+  using InitList = std::initializer_list<ValueType>;
+
+  using BadHash = int;
+  struct BadAlloc {};
+  struct BadIter {};
+  using AllocAsHash = Alloc;
+  using AllocAsPred = Alloc;
+
+  // Possible deduction guides invocations:
+  //
+  // (iter, iter)
+  // (iter, iter, buckets)
+  // (iter, iter, buckets, hash)
+  // (iter, iter, buckets, hash, pred)
+  // (iter, iter, buckets, hash, pred, alloc)
+  //
+  // (iter, iter, buckets, alloc)
+  //
+  // (iter, iter, alloc)
+  //
+  // (iter, iter, buckets, hash, alloc)
+  //
+  // (init_list, buckets, hash)
+  // (init_list, buckets, hash, pred)
+  // (init_list, buckets, hash, pred, alloc)
+  //
+  // (init_list, buckets, alloc)
+  //
+  // (init_list, buckets, hash, alloc)
+  //
+  // (init_list, alloc)
+
+  // (iter, iter)
+  //
+  // Cannot deduce from (BAD_iter, BAD_iter)
+  static_assert(SFINAEs_away<Container, BadIter, BadIter>);
+
+  // (iter, iter, buckets)
+  //
+  // Cannot deduce from (BAD_iter, BAD_iter, buckets)
+  static_assert(SFINAEs_away<Container, BadIter, BadIter, size_t>);
+
+  // (iter, iter, buckets, hash)
+  //
+  // Cannot deduce from (BAD_iter, BAD_iter, buckets, hash)
+  static_assert(SFINAEs_away<Container, BadIter, BadIter, size_t, Hash>);
+  // Cannot deduce from (iter, iter, buckets, BAD_hash)
+  static_assert(SFINAEs_away<Container, Iter, Iter, size_t, BadHash>);
+  // Note: (iter, iter, buckets, ALLOC_as_hash) is allowed -- it just calls
+  // (iter, iter, buckets, alloc)
+
+  // (iter, iter, buckets, hash, pred)
+  //
+  // Cannot deduce from (BAD_iter, BAD_iter, buckets, hash, pred)
+  static_assert(SFINAEs_away<Container, BadIter, BadIter, size_t, Hash, Pred>);
+  // Cannot deduce from (iter, iter, buckets, BAD_hash, pred)
+  static_assert(SFINAEs_away<Container, Iter, Iter, size_t, BadHash, Pred>);
+  // Cannot deduce from (iter, iter, buckets, ALLOC_as_hash, pred)
+  static_assert(SFINAEs_away<Container, Iter, Iter, size_t, AllocAsHash, Pred>);
+  // Note: (iter, iter, buckets, hash, ALLOC_as_pred) is allowed -- it just
+  // calls (iter, iter, buckets, hash, alloc)
+
+  // (iter, iter, buckets, hash, pred, alloc)
+  //
+  // Cannot deduce from (BAD_iter, BAD_iter, buckets, hash, pred, alloc)
+  static_assert(
+      SFINAEs_away<Container, BadIter, BadIter, size_t, Hash, Pred, Alloc>);
+  // Cannot deduce from (iter, iter, buckets, BAD_hash, pred, alloc)
+  static_assert(
+      SFINAEs_away<Container, Iter, Iter, size_t, BadHash, Pred, Alloc>);
+  // Cannot deduce from (iter, iter, buckets, ALLOC_as_hash, pred, alloc)
+  static_assert(
+      SFINAEs_away<Container, Iter, Iter, size_t, AllocAsHash, Pred, Alloc>);
+  // Cannot deduce from (iter, iter, buckets, hash, ALLOC_as_pred, alloc)
+  static_assert(
+      SFINAEs_away<Container, Iter, Iter, size_t, Hash, AllocAsPred, Alloc>);
+  // Cannot deduce from (iter, iter, buckets, hash, pred, BAD_alloc)
+  static_assert(
+      SFINAEs_away<Container, Iter, Iter, size_t, Hash, Pred, BadAlloc>);
+
+  // (iter, iter, buckets, alloc)
+  //
+  // Cannot deduce from (BAD_iter, BAD_iter, buckets, alloc)
+  static_assert(SFINAEs_away<Container, BadIter, BadIter, size_t, Alloc>);
+  // Note: (iter, iter, buckets, BAD_alloc) is interpreted as (iter, iter,
+  // buckets, hash), which is valid because the only requirement for the hash
+  // parameter is that it's not integral.
+
+  // (iter, iter, alloc)
+  //
+  // Cannot deduce from (BAD_iter, BAD_iter, alloc)
+  static_assert(SFINAEs_away<Container, BadIter, BadIter, Alloc>);
+  // Cannot deduce from (iter, iter, BAD_alloc)
+  static_assert(SFINAEs_away<Container, Iter, Iter, BadAlloc>);
+
+  // (iter, iter, buckets, hash, alloc)
+  //
+  // Cannot deduce from (BAD_iter, BAD_iter, buckets, hash, alloc)
+  static_assert(SFINAEs_away<Container, BadIter, BadIter, size_t, Hash, Alloc>);
+  // Cannot deduce from (iter, iter, buckets, BAD_hash, alloc)
+  static_assert(SFINAEs_away<Container, Iter, Iter, size_t, BadHash, Alloc>);
+  // Cannot deduce from (iter, iter, buckets, ALLOC_as_hash, alloc)
+  static_assert(
+      SFINAEs_away<Container, Iter, Iter, size_t, AllocAsHash, Alloc>);
+  // Note: (iter, iter, buckets, hash, BAD_alloc) is interpreted as (iter, iter,
+  // buckets, hash, pred), which is valid because there are no requirements for
+  // the predicate.
+
+  // (init_list, buckets, hash)
+  //
+  // Cannot deduce from (init_list, buckets, BAD_hash)
+  static_assert(SFINAEs_away<Container, InitList, size_t, BadHash>);
+  // Note: (init_list, buckets, ALLOC_as_hash) is interpreted as (init_list,
+  // buckets, alloc), which is valid.
+
+  // (init_list, buckets, hash, pred)
+  //
+  // Cannot deduce from (init_list, buckets, BAD_hash, pred)
+  static_assert(SFINAEs_away<Container, InitList, size_t, BadHash, Pred>);
+  // Cannot deduce from (init_list, buckets, ALLOC_as_hash, pred)
+  static_assert(SFINAEs_away<Container, InitList, size_t, AllocAsHash, Pred>);
+  // Note: (init_list, buckets, hash, ALLOC_as_pred) is interpreted as
+  // (init_list, buckets, hash, alloc), which is valid.
+
+  // (init_list, buckets, hash, pred, alloc)
+  //
+  // Cannot deduce from (init_list, buckets, BAD_hash, pred, alloc)
+  static_assert(
+      SFINAEs_away<Container, InitList, size_t, BadHash, Pred, Alloc>);
+  // Cannot deduce from (init_list, buckets, ALLOC_as_hash, pred, alloc)
+  static_assert(
+      SFINAEs_away<Container, InitList, size_t, AllocAsHash, Pred, Alloc>);
+  // Cannot deduce from (init_list, buckets, hash, ALLOC_as_pred, alloc)
+  static_assert(
+      SFINAEs_away<Container, InitList, size_t, Hash, AllocAsPred, Alloc>);
+  // Cannot deduce from (init_list, buckets, hash, pred, BAD_alloc)
+  static_assert(
+      SFINAEs_away<Container, InitList, size_t, Hash, Pred, BadAlloc>);
+
+  // (init_list, buckets, alloc)
+  //
+  // Note: (init_list, buckets, BAD_alloc) is interpreted as (init_list,
+  // buckets, hash), which is valid because the only requirement for the hash
+  // parameter is that it's not integral.
+
+  // (init_list, buckets, hash, alloc)
+  //
+  // Cannot deduce from (init_list, buckets, BAD_hash, alloc)
+  static_assert(SFINAEs_away<Container, InitList, size_t, BadHash, Alloc>);
+  // Cannot deduce from (init_list, buckets, ALLOC_as_hash, alloc)
+  static_assert(SFINAEs_away<Container, InitList, size_t, AllocAsHash, Alloc>);
+
+  // (init_list, alloc)
+  //
+  // Cannot deduce from (init_list, BAD_alloc)
+  static_assert(SFINAEs_away<Container, InitList, BadAlloc>);
+}
+
+#endif // TEST_SUPPORT_DEDUCTION_GUIDES_SFINAE_CHECKS_H
diff --git a/libcxx/test/support/sfinaes_away.h b/libcxx/test/support/sfinaes_away.h
new file mode 100644
--- /dev/null
+++ b/libcxx/test/support/sfinaes_away.h
@@ -0,0 +1,30 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef TEST_SUPPORT_SFINAES_AWAY_H
+#define TEST_SUPPORT_SFINAES_AWAY_H
+
+#include <type_traits>
+#include <utility>
+
+// `SFINAEs_away` template variable checks whether the template arguments for
+// a given template class `Instantiated` can be deduced from the given
+// constructor parameter types `CtrArgs` using CTAD.
+
+template<template<typename ...> class Instantiated, class ...CtrArgs,
+    class = decltype(Instantiated(std::declval<CtrArgs>()...))>
+std::false_type SFINAEs_away_impl(int);
+
+template<template<typename ...> class Instantiated, class ...CtrArgs>
+std::true_type SFINAEs_away_impl(...);
+
+template<template<typename ...> class Instantiated, class ...CtrArgs>
+constexpr bool SFINAEs_away =
+    decltype(SFINAEs_away_impl<Instantiated, CtrArgs...>(0))::value;
+
+#endif // TEST_SUPPORT_SFINAES_AWAY_H