coroutine_handle<void>
     {
     public:
-      // 17.12.3.1, construct/reset
+      // [coroutine.handle.con], construct/reset
       constexpr coroutine_handle() noexcept : _M_fr_ptr(0) {}
 
       constexpr coroutine_handle(std::nullptr_t __h) noexcept
       }
 
     public:
-      // 17.12.3.2, export/import
+      // [coroutine.handle.export.import], export/import
       constexpr void* address() const noexcept { return _M_fr_ptr; }
 
       constexpr static coroutine_handle from_address(void* __a) noexcept
       }
 
     public:
-      // 17.12.3.3, observers
+      // [coroutine.handle.observers], observers
       constexpr explicit operator bool() const noexcept
       {
        return bool(_M_fr_ptr);
 
       bool done() const noexcept { return __builtin_coro_done(_M_fr_ptr); }
 
-      // 17.12.3.4, resumption
+      // [coroutine.handle.resumption], resumption
       void operator()() const { resume(); }
 
       void resume() const { __builtin_coro_resume(_M_fr_ptr); }
       void* _M_fr_ptr;
   };
 
-  // 17.12.3.6 Comparison operators
-  /// [coroutine.handle.compare]
-  constexpr bool operator==(coroutine_handle<> __a,
-                           coroutine_handle<> __b) noexcept
+  // [coroutine.handle.compare], comparison operators
+
+  constexpr bool
+  operator==(coroutine_handle<> __a, coroutine_handle<> __b) noexcept
   {
     return __a.address() == __b.address();
   }
 #if _COROUTINES_USE_SPACESHIP
   constexpr strong_ordering
   operator<=>(coroutine_handle<> __a, coroutine_handle<> __b) noexcept
-  { return std::compare_three_way()(__a.address(), __b.address()); }
+  {
+    return std::compare_three_way()(__a.address(), __b.address());
+  }
 #else
   // These are to enable operation with std=c++14,17.
-  constexpr bool operator!=(coroutine_handle<> __a,
-                           coroutine_handle<> __b) noexcept
+  constexpr bool
+  operator!=(coroutine_handle<> __a, coroutine_handle<> __b) noexcept
   {
     return !(__a == __b);
   }
 
-  constexpr bool operator<(coroutine_handle<> __a,
-                          coroutine_handle<> __b) noexcept
+  constexpr bool
+  operator<(coroutine_handle<> __a, coroutine_handle<> __b) noexcept
   {
     return less<void*>()(__a.address(), __b.address());
   }
 
-  constexpr bool operator>(coroutine_handle<> __a,
-                          coroutine_handle<> __b) noexcept
+  constexpr bool
+  operator>(coroutine_handle<> __a, coroutine_handle<> __b) noexcept
   {
     return __b < __a;
   }
 
-  constexpr bool operator<=(coroutine_handle<> __a,
-                           coroutine_handle<> __b) noexcept
+  constexpr bool
+  operator<=(coroutine_handle<> __a, coroutine_handle<> __b) noexcept
   {
     return !(__a > __b);
   }
 
-  constexpr bool operator>=(coroutine_handle<> __a,
-                           coroutine_handle<> __b) noexcept
+  constexpr bool
+  operator>=(coroutine_handle<> __a, coroutine_handle<> __b) noexcept
   {
     return !(__a < __b);
   }
 #endif
 
   template <typename _Promise>
-    struct coroutine_handle : coroutine_handle<>
+    struct coroutine_handle
     {
-      // 17.12.3.1, construct/reset
-      using coroutine_handle<>::coroutine_handle;
+      // [coroutine.handle.con], construct/reset
 
-      static coroutine_handle from_promise(_Promise& p)
+      constexpr coroutine_handle() noexcept { }
+
+      constexpr coroutine_handle(nullptr_t) noexcept { }
+
+      static coroutine_handle
+      from_promise(_Promise& __p)
       {
        coroutine_handle __self;
        __self._M_fr_ptr
-         = __builtin_coro_promise((char*) &p, __alignof(_Promise), true);
+         = __builtin_coro_promise((char*) &__p, __alignof(_Promise), true);
        return __self;
       }
 
-      coroutine_handle& operator=(std::nullptr_t) noexcept
+      coroutine_handle& operator=(nullptr_t) noexcept
       {
-       coroutine_handle<>::operator=(nullptr);
+       _M_fr_ptr = nullptr;
        return *this;
       }
 
-    // 17.12.3.2, export/import
-    constexpr static coroutine_handle from_address(void* __a)
-    {
-      coroutine_handle __self;
-      __self._M_fr_ptr = __a;
-      return __self;
-    }
+      // [coroutine.handle.export.import], export/import
 
-    // 17.12.3.5, promise accesss
-    _Promise& promise() const
-    {
-      void* __t
-       = __builtin_coro_promise (this->_M_fr_ptr, __alignof(_Promise), false);
-      return *static_cast<_Promise*>(__t);
-    }
-  };
+      constexpr void* address() const noexcept { return _M_fr_ptr; }
+
+      constexpr static coroutine_handle from_address(void* __a)
+      {
+       coroutine_handle __self;
+       __self._M_fr_ptr = __a;
+       return __self;
+      }
+
+      // [coroutine.handle.conv], conversion
+      constexpr operator coroutine_handle<>() const noexcept
+      { return coroutine_handle<>::from_address(address()); }
+
+      // [coroutine.handle.observers], observers
+      constexpr explicit operator bool() const noexcept
+      {
+       return bool(_M_fr_ptr);
+      }
+
+      bool done() const noexcept { return __builtin_coro_done(_M_fr_ptr); }
+
+      // [coroutine.handle.resumption], resumption
+      void operator()() const { resume(); }
+
+      void resume() const { __builtin_coro_resume(_M_fr_ptr); }
+
+      void destroy() const { __builtin_coro_destroy(_M_fr_ptr); }
+
+      // [coroutine.handle.promise], promise access
+      _Promise& promise() const
+      {
+       void* __t
+         = __builtin_coro_promise (_M_fr_ptr, __alignof(_Promise), false);
+       return *static_cast<_Promise*>(__t);
+      }
+
+    private:
+      void* _M_fr_ptr = nullptr;
+    };
 
   /// [coroutine.noop]
   struct noop_coroutine_promise
   // 17.12.4.1 Class noop_coroutine_promise
   /// [coroutine.promise.noop]
   template <>
-    struct coroutine_handle<noop_coroutine_promise> : public coroutine_handle<>
+    struct coroutine_handle<noop_coroutine_promise>
     {
-      using _Promise = noop_coroutine_promise;
+      // _GLIBCXX_RESOLVE_LIB_DEFECTS
+      // 3460. Unimplementable noop_coroutine_handle guarantees
+      // [coroutine.handle.noop.conv], conversion
+      constexpr operator coroutine_handle<>() const noexcept
+      { return coroutine_handle<>::from_address(address()); }
 
-    public:
-      // 17.12.4.2.1, observers
+      // [coroutine.handle.noop.observers], observers
       constexpr explicit operator bool() const noexcept { return true; }
 
       constexpr bool done() const noexcept { return false; }
 
-      // 17.12.4.2.2, resumption
+      // [coroutine.handle.noop.resumption], resumption
       void operator()() const noexcept {}
 
       void resume() const noexcept {}
 
       void destroy() const noexcept {}
 
-      // 17.12.4.2.3, promise access
-      _Promise& promise() const
-      {
-       return *static_cast<_Promise*>(
-         __builtin_coro_promise(this->_M_fr_ptr, __alignof(_Promise), false));
-      }
+      // [coroutine.handle.noop.promise], promise access
+      noop_coroutine_promise& promise() const noexcept
+      { return __noop_coro_fr.__p; }
+
+      // [coroutine.handle.noop.address], address
+      constexpr void* address() const noexcept { return _M_fr_ptr; }
 
-      // 17.12.4.2.4, address
     private:
-      friend coroutine_handle<noop_coroutine_promise> noop_coroutine() noexcept;
+      friend coroutine_handle noop_coroutine() noexcept;
+
+      coroutine_handle() = default;
 
-      coroutine_handle() noexcept { this->_M_fr_ptr = (void*) &__noop_coro_fr; }
+      void* _M_fr_ptr = (void*) &__noop_coro_fr;
     };
 
   using noop_coroutine_handle = coroutine_handle<noop_coroutine_promise>;
 
--- /dev/null
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do compile { target c++2a } }
+
+#include <coroutine>
+
+void
+test01()
+{
+  // LWG 3460. Unimplementable noop_coroutine_handle guarantees
+
+  static_assert( std::is_convertible_v<std::noop_coroutine_handle&,
+                                      std::coroutine_handle<>> );
+  static_assert( ! std::is_convertible_v<std::noop_coroutine_handle&,
+                                        std::coroutine_handle<>&> );
+  static_assert( ! std::is_assignable_v<std::noop_coroutine_handle&,
+                                       std::coroutine_handle<>> );
+
+  std::noop_coroutine_handle h = std::noop_coroutine();
+  std::coroutine_handle<> h2 = h;
+  h2();                // no-op
+  h2.resume(); // no-op
+  h2.destroy();        // no-op
+}
+
+void
+test02()
+{
+  // LWG 3469. Precondition of coroutine_handle::promise may be insufficient
+
+  struct P1 { };
+  struct P2 { };
+
+  static_assert( ! std::is_assignable_v<std::coroutine_handle<P1>&,
+                                       std::coroutine_handle<>> );
+  static_assert( ! std::is_assignable_v<std::coroutine_handle<P1>&,
+                                       std::coroutine_handle<P2>> );
+}