Change Ref() methods to return a RefCountedPtr<>.
diff --git a/src/core/ext/filters/client_channel/subchannel.cc b/src/core/ext/filters/client_channel/subchannel.cc
index dc1beee..6bf710c 100644
--- a/src/core/ext/filters/client_channel/subchannel.cc
+++ b/src/core/ext/filters/client_channel/subchannel.cc
@@ -738,8 +738,9 @@
 }
 
 namespace grpc_core {
+
 ConnectedSubchannel::ConnectedSubchannel(grpc_channel_stack* channel_stack)
-    : grpc_core::RefCountedWithTracing(&grpc_trace_stream_refcount),
+    : RefCountedWithTracing<ConnectedSubchannel>(&grpc_trace_stream_refcount),
       channel_stack_(channel_stack) {}
 
 ConnectedSubchannel::~ConnectedSubchannel() {
@@ -774,7 +775,9 @@
       args.arena,
       sizeof(grpc_subchannel_call) + channel_stack_->call_stack_size);
   grpc_call_stack* callstk = SUBCHANNEL_CALL_TO_CALL_STACK(*call);
-  Ref(DEBUG_LOCATION, "subchannel_call");
+  RefCountedPtr<ConnectedSubchannel> connection =
+      Ref(DEBUG_LOCATION, "subchannel_call");
+  connection.release();  // Ref is passed to the grpc_subchannel_call object.
   (*call)->connection = this;
   const grpc_call_element_args call_args = {
       callstk,           /* call_stack */
@@ -796,4 +799,5 @@
   grpc_call_stack_set_pollset_or_pollset_set(callstk, args.pollent);
   return GRPC_ERROR_NONE;
 }
+
 }  // namespace grpc_core
diff --git a/src/core/ext/filters/client_channel/subchannel.h b/src/core/ext/filters/client_channel/subchannel.h
index b7593ec..d2b45ae 100644
--- a/src/core/ext/filters/client_channel/subchannel.h
+++ b/src/core/ext/filters/client_channel/subchannel.h
@@ -68,7 +68,8 @@
 #endif
 
 namespace grpc_core {
-class ConnectedSubchannel : public grpc_core::RefCountedWithTracing {
+
+class ConnectedSubchannel : public RefCountedWithTracing<ConnectedSubchannel> {
  public:
   struct CallArgs {
     grpc_polling_entity* pollent;
@@ -93,6 +94,7 @@
  private:
   grpc_channel_stack* channel_stack_;
 };
+
 }  // namespace grpc_core
 
 grpc_subchannel* grpc_subchannel_ref(
diff --git a/src/core/lib/gprpp/orphanable.h b/src/core/lib/gprpp/orphanable.h
index 5019973..6e127c2 100644
--- a/src/core/lib/gprpp/orphanable.h
+++ b/src/core/lib/gprpp/orphanable.h
@@ -28,6 +28,7 @@
 #include "src/core/lib/gprpp/abstract.h"
 #include "src/core/lib/gprpp/debug_location.h"
 #include "src/core/lib/gprpp/memory.h"
+#include "src/core/lib/gprpp/ref_counted_ptr.h"
 
 namespace grpc_core {
 
@@ -69,6 +70,7 @@
 }
 
 // A type of Orphanable with internal ref-counting.
+template <typename Child>
 class InternallyRefCounted : public Orphanable {
  public:
   // Not copyable nor movable.
@@ -78,10 +80,20 @@
   GRPC_ABSTRACT_BASE_CLASS
 
  protected:
+  // Allow Delete() to access destructor.
+  template <typename T>
+  friend void Delete(T*);
+
+  // Allow RefCountedPtr<> to access Unref() and IncrementRefCount().
+  friend class RefCountedPtr<Child>;
+
   InternallyRefCounted() { gpr_ref_init(&refs_, 1); }
   virtual ~InternallyRefCounted() {}
 
-  void Ref() { gpr_ref(&refs_); }
+  RefCountedPtr<Child> Ref() GRPC_MUST_USE_RESULT {
+    IncrementRefCount();
+    return RefCountedPtr<Child>(reinterpret_cast<Child*>(this));
+  }
 
   void Unref() {
     if (gpr_unref(&refs_)) {
@@ -89,11 +101,9 @@
     }
   }
 
-  // Allow Delete() to access destructor.
-  template <typename T>
-  friend void Delete(T*);
-
  private:
+  void IncrementRefCount() { gpr_ref(&refs_); }
+
   gpr_refcount refs_;
 };
 
@@ -103,6 +113,7 @@
 // pointers and legacy code that is manually calling Ref() and Unref().
 // Once all of our code is converted to idiomatic C++, we may be able to
 // eliminate this class.
+template <typename Child>
 class InternallyRefCountedWithTracing : public Orphanable {
  public:
   // Not copyable nor movable.
@@ -118,6 +129,9 @@
   template <typename T>
   friend void Delete(T*);
 
+  // Allow RefCountedPtr<> to access Unref() and IncrementRefCount().
+  friend class RefCountedPtr<Child>;
+
   InternallyRefCountedWithTracing()
       : InternallyRefCountedWithTracing(static_cast<TraceFlag*>(nullptr)) {}
 
@@ -133,18 +147,27 @@
 
   virtual ~InternallyRefCountedWithTracing() {}
 
-  void Ref() { gpr_ref(&refs_); }
+  RefCountedPtr<Child> Ref() GRPC_MUST_USE_RESULT {
+    IncrementRefCount();
+    return RefCountedPtr<Child>(reinterpret_cast<Child*>(this));
+  }
 
-  void Ref(const DebugLocation& location, const char* reason) {
+  RefCountedPtr<Child> Ref(const DebugLocation& location,
+                           const char* reason) GRPC_MUST_USE_RESULT {
     if (location.Log() && trace_flag_ != nullptr && trace_flag_->enabled()) {
       gpr_atm old_refs = gpr_atm_no_barrier_load(&refs_.count);
       gpr_log(GPR_DEBUG, "%s:%p %s:%d ref %" PRIdPTR " -> %" PRIdPTR " %s",
               trace_flag_->name(), this, location.file(), location.line(),
               old_refs, old_refs + 1, reason);
     }
-    Ref();
+    return Ref();
   }
 
+  // TODO(roth): Once all of our code is converted to C++ and can use
+  // RefCountedPtr<> instead of manual ref-counting, make the Unref() methods
+  // private, since they will only be used by RefCountedPtr<>, which is a
+  // friend of this class.
+
   void Unref() {
     if (gpr_unref(&refs_)) {
       Delete(this);
@@ -162,6 +185,8 @@
   }
 
  private:
+  void IncrementRefCount() { gpr_ref(&refs_); }
+
   TraceFlag* trace_flag_ = nullptr;
   gpr_refcount refs_;
 };
diff --git a/src/core/lib/gprpp/ref_counted.h b/src/core/lib/gprpp/ref_counted.h
index c68118a..16c7912 100644
--- a/src/core/lib/gprpp/ref_counted.h
+++ b/src/core/lib/gprpp/ref_counted.h
@@ -26,16 +26,28 @@
 #include "src/core/lib/gprpp/abstract.h"
 #include "src/core/lib/gprpp/debug_location.h"
 #include "src/core/lib/gprpp/memory.h"
+#include "src/core/lib/gprpp/ref_counted_ptr.h"
 
 namespace grpc_core {
 
 // A base class for reference-counted objects.
 // New objects should be created via New() and start with a refcount of 1.
 // When the refcount reaches 0, the object will be deleted via Delete().
+//
+// This will commonly be used by CRTP (curiously-recurring template pattern)
+// e.g., class MyClass : public RefCounted<MyClass>
+template <typename Child>
 class RefCounted {
  public:
-  void Ref() { gpr_ref(&refs_); }
+  RefCountedPtr<Child> Ref() GRPC_MUST_USE_RESULT {
+    IncrementRefCount();
+    return RefCountedPtr<Child>(reinterpret_cast<Child*>(this));
+  }
 
+  // TODO(roth): Once all of our code is converted to C++ and can use
+  // RefCountedPtr<> instead of manual ref-counting, make this method
+  // private, since it will only be used by RefCountedPtr<>, which is a
+  // friend of this class.
   void Unref() {
     if (gpr_unref(&refs_)) {
       Delete(this);
@@ -58,6 +70,11 @@
   virtual ~RefCounted() {}
 
  private:
+  // Allow RefCountedPtr<> to access IncrementRefCount().
+  friend class RefCountedPtr<Child>;
+
+  void IncrementRefCount() { gpr_ref(&refs_); }
+
   gpr_refcount refs_;
 };
 
@@ -67,20 +84,30 @@
 // pointers and legacy code that is manually calling Ref() and Unref().
 // Once all of our code is converted to idiomatic C++, we may be able to
 // eliminate this class.
+template <typename Child>
 class RefCountedWithTracing {
  public:
-  void Ref() { gpr_ref(&refs_); }
+  RefCountedPtr<Child> Ref() GRPC_MUST_USE_RESULT {
+    IncrementRefCount();
+    return RefCountedPtr<Child>(reinterpret_cast<Child*>(this));
+  }
 
-  void Ref(const DebugLocation& location, const char* reason) {
+  RefCountedPtr<Child> Ref(const DebugLocation& location,
+                           const char* reason) GRPC_MUST_USE_RESULT {
     if (location.Log() && trace_flag_ != nullptr && trace_flag_->enabled()) {
       gpr_atm old_refs = gpr_atm_no_barrier_load(&refs_.count);
       gpr_log(GPR_DEBUG, "%s:%p %s:%d ref %" PRIdPTR " -> %" PRIdPTR " %s",
               trace_flag_->name(), this, location.file(), location.line(),
               old_refs, old_refs + 1, reason);
     }
-    Ref();
+    return Ref();
   }
 
+  // TODO(roth): Once all of our code is converted to C++ and can use
+  // RefCountedPtr<> instead of manual ref-counting, make the Unref() methods
+  // private, since they will only be used by RefCountedPtr<>, which is a
+  // friend of this class.
+
   void Unref() {
     if (gpr_unref(&refs_)) {
       Delete(this);
@@ -124,6 +151,11 @@
   virtual ~RefCountedWithTracing() {}
 
  private:
+  // Allow RefCountedPtr<> to access IncrementRefCount().
+  friend class RefCountedPtr<Child>;
+
+  void IncrementRefCount() { gpr_ref(&refs_); }
+
   TraceFlag* trace_flag_ = nullptr;
   gpr_refcount refs_;
 };
diff --git a/src/core/lib/gprpp/ref_counted_ptr.h b/src/core/lib/gprpp/ref_counted_ptr.h
index dda0f00..f82ba50 100644
--- a/src/core/lib/gprpp/ref_counted_ptr.h
+++ b/src/core/lib/gprpp/ref_counted_ptr.h
@@ -25,8 +25,8 @@
 
 namespace grpc_core {
 
-// A smart pointer class for objects that provide Ref() and Unref() methods,
-// such as those provided by the RefCounted base class.
+// A smart pointer class for objects that provide IncrementRefCount() and
+// Unref() methods, such as those provided by the RefCounted base class.
 template <typename T>
 class RefCountedPtr {
  public:
@@ -49,13 +49,13 @@
 
   // Copy support.
   RefCountedPtr(const RefCountedPtr& other) {
-    if (other.value_ != nullptr) other.value_->Ref();
+    if (other.value_ != nullptr) other.value_->IncrementRefCount();
     value_ = other.value_;
   }
   RefCountedPtr& operator=(const RefCountedPtr& other) {
     // Note: Order of reffing and unreffing is important here in case value_
     // and other.value_ are the same object.
-    if (other.value_ != nullptr) other.value_->Ref();
+    if (other.value_ != nullptr) other.value_->IncrementRefCount();
     if (value_ != nullptr) value_->Unref();
     value_ = other.value_;
     return *this;
@@ -71,6 +71,16 @@
     value_ = value;
   }
 
+  // TODO(roth): This method exists solely as a transition mechanism to allow
+  // us to pass a ref to idiomatic C code that does not use RefCountedPtr<>.
+  // Once all of our code has been converted to idiomatic C++, this
+  // method should go away.
+  T* release() {
+    T* value = value_;
+    value_ = nullptr;
+    return value;
+  }
+
   T* get() const { return value_; }
 
   T& operator*() const { return *value_; }