[ref-counted] Use down_cast for additional safety checks (#35579)

Closes #35579

COPYBARA_INTEGRATE_REVIEW=https://github.com/grpc/grpc/pull/35579 from ctiller:use-downcast 6f11268751
PiperOrigin-RevId: 622981017
pull/36292/head
Craig Tiller 12 months ago committed by Copybara-Service
parent 70839a9b19
commit c7b81ad925
  1. 2
      BUILD
  2. 3
      CMakeLists.txt
  3. 6
      build_autogenerated.yaml
  4. 2
      src/core/BUILD
  5. 8
      src/core/lib/gprpp/down_cast.h
  6. 13
      src/core/lib/gprpp/dual_ref_counted.h
  7. 7
      src/core/lib/gprpp/orphanable.h
  8. 7
      src/core/lib/gprpp/ref_counted.h
  9. 3
      src/core/lib/gprpp/ref_counted_ptr.h
  10. 4
      src/core/lib/promise/context.h
  11. 4
      test/core/gprpp/down_cast_test.cc

@ -3031,6 +3031,7 @@ grpc_cc_library(
"debug_location",
"gpr_platform",
"ref_counted_ptr",
"//src/core:down_cast",
"//src/core:ref_counted",
],
)
@ -3063,6 +3064,7 @@ grpc_cc_library(
deps = [
"debug_location",
"gpr_platform",
"//src/core:down_cast",
],
)

3
CMakeLists.txt generated

@ -7345,6 +7345,7 @@ target_include_directories(avl_test
target_link_libraries(avl_test
${_gRPC_ALLTARGETS_LIBRARIES}
gtest
absl::config
absl::hash
gpr
)
@ -12812,6 +12813,7 @@ target_include_directories(endpoint_config_test
target_link_libraries(endpoint_config_test
${_gRPC_ALLTARGETS_LIBRARIES}
gtest
absl::config
absl::hash
absl::type_traits
absl::statusor
@ -30509,6 +30511,7 @@ target_include_directories(thread_quota_test
target_link_libraries(thread_quota_test
${_gRPC_ALLTARGETS_LIBRARIES}
gtest
absl::config
absl::hash
gpr
)

@ -5742,12 +5742,14 @@ targets:
headers:
- src/core/lib/avl/avl.h
- src/core/lib/gprpp/atomic_utils.h
- src/core/lib/gprpp/down_cast.h
- src/core/lib/gprpp/ref_counted.h
- src/core/lib/gprpp/ref_counted_ptr.h
src:
- test/core/avl/avl_test.cc
deps:
- gtest
- absl/base:config
- absl/hash:hash
- gpr
uses_polling: false
@ -8944,6 +8946,7 @@ targets:
- src/core/lib/channel/channel_args.h
- src/core/lib/event_engine/channel_args_endpoint_config.h
- src/core/lib/gprpp/atomic_utils.h
- src/core/lib/gprpp/down_cast.h
- src/core/lib/gprpp/dual_ref_counted.h
- src/core/lib/gprpp/orphanable.h
- src/core/lib/gprpp/ref_counted.h
@ -8960,6 +8963,7 @@ targets:
- test/core/event_engine/endpoint_config_test.cc
deps:
- gtest
- absl/base:config
- absl/hash:hash
- absl/meta:type_traits
- absl/status:statusor
@ -19159,6 +19163,7 @@ targets:
language: c++
headers:
- src/core/lib/gprpp/atomic_utils.h
- src/core/lib/gprpp/down_cast.h
- src/core/lib/gprpp/ref_counted.h
- src/core/lib/gprpp/ref_counted_ptr.h
- src/core/lib/resource_quota/thread_quota.h
@ -19167,6 +19172,7 @@ targets:
- test/core/resource_quota/thread_quota_test.cc
deps:
- gtest
- absl/base:config
- absl/hash:hash
- gpr
uses_polling: false

@ -1157,6 +1157,7 @@ grpc_cc_library(
public_hdrs = ["lib/gprpp/ref_counted.h"],
deps = [
"atomic_utils",
"down_cast",
"//:debug_location",
"//:gpr",
"//:ref_counted_ptr",
@ -1168,6 +1169,7 @@ grpc_cc_library(
language = "c++",
public_hdrs = ["lib/gprpp/dual_ref_counted.h"],
deps = [
"down_cast",
"//:debug_location",
"//:gpr",
"//:orphanable",

@ -26,10 +26,10 @@
namespace grpc_core {
template <typename To, typename From>
inline To down_cast(From* f) {
inline To DownCast(From* f) {
static_assert(
std::is_base_of<From, typename std::remove_pointer<To>::type>::value,
"down_cast requires a base-to-derived relationship");
"DownCast requires a base-to-derived relationship");
// If we have RTTI & we're in debug, assert that the cast is legal.
#if ABSL_INTERNAL_HAS_RTTI
#ifndef NDEBUG
@ -40,8 +40,8 @@ inline To down_cast(From* f) {
}
template <typename To, typename From>
inline To down_cast(From& f) {
return *down_cast<typename std::remove_reference<To>::type*>(&f);
inline To DownCast(From& f) {
return *DownCast<typename std::remove_reference<To>::type*>(&f);
}
} // namespace grpc_core

@ -25,6 +25,7 @@
#include <grpc/support/log.h>
#include "src/core/lib/gprpp/debug_location.h"
#include "src/core/lib/gprpp/down_cast.h"
#include "src/core/lib/gprpp/orphanable.h"
#include "src/core/lib/gprpp/ref_counted_ptr.h"
@ -68,7 +69,8 @@ class DualRefCounted {
std::enable_if_t<std::is_base_of<Child, Subclass>::value, bool> = true>
RefCountedPtr<Subclass> RefAsSubclass() {
IncrementRefCount();
return RefCountedPtr<Subclass>(static_cast<Subclass*>(this));
return RefCountedPtr<Subclass>(
DownCast<Subclass*>(static_cast<Child*>(this)));
}
template <
typename Subclass,
@ -76,7 +78,8 @@ class DualRefCounted {
RefCountedPtr<Subclass> RefAsSubclass(const DebugLocation& location,
const char* reason) {
IncrementRefCount(location, reason);
return RefCountedPtr<Subclass>(static_cast<Subclass*>(this));
return RefCountedPtr<Subclass>(
DownCast<Subclass*>(static_cast<Child*>(this)));
}
void Unref() {
@ -179,7 +182,8 @@ class DualRefCounted {
std::enable_if_t<std::is_base_of<Child, Subclass>::value, bool> = true>
WeakRefCountedPtr<Subclass> WeakRefAsSubclass() {
IncrementWeakRefCount();
return WeakRefCountedPtr<Subclass>(static_cast<Subclass*>(this));
return WeakRefCountedPtr<Subclass>(
DownCast<Subclass*>(static_cast<Child*>(this)));
}
template <
typename Subclass,
@ -187,7 +191,8 @@ class DualRefCounted {
WeakRefCountedPtr<Subclass> WeakRefAsSubclass(const DebugLocation& location,
const char* reason) {
IncrementWeakRefCount(location, reason);
return WeakRefCountedPtr<Subclass>(static_cast<Subclass*>(this));
return WeakRefCountedPtr<Subclass>(
DownCast<Subclass*>(static_cast<Child*>(this)));
}
void WeakUnref() {

@ -26,6 +26,7 @@
#include <utility>
#include "src/core/lib/gprpp/debug_location.h"
#include "src/core/lib/gprpp/down_cast.h"
#include "src/core/lib/gprpp/ref_counted.h"
#include "src/core/lib/gprpp/ref_counted_ptr.h"
@ -102,7 +103,8 @@ class InternallyRefCounted : public Orphanable {
std::enable_if_t<std::is_base_of<Child, Subclass>::value, bool> = true>
RefCountedPtr<Subclass> RefAsSubclass() {
IncrementRefCount();
return RefCountedPtr<Subclass>(static_cast<Subclass*>(this));
return RefCountedPtr<Subclass>(
DownCast<Subclass*>(static_cast<Child*>(this)));
}
template <
typename Subclass,
@ -110,7 +112,8 @@ class InternallyRefCounted : public Orphanable {
RefCountedPtr<Subclass> RefAsSubclass(const DebugLocation& location,
const char* reason) {
IncrementRefCount(location, reason);
return RefCountedPtr<Subclass>(static_cast<Subclass*>(this));
return RefCountedPtr<Subclass>(
DownCast<Subclass*>(static_cast<Child*>(this)));
}
GRPC_MUST_USE_RESULT RefCountedPtr<Child> RefIfNonZero() {

@ -29,6 +29,7 @@
#include "src/core/lib/gprpp/atomic_utils.h"
#include "src/core/lib/gprpp/debug_location.h"
#include "src/core/lib/gprpp/down_cast.h"
#include "src/core/lib/gprpp/ref_counted_ptr.h"
namespace grpc_core {
@ -310,7 +311,8 @@ class RefCounted : public Impl {
std::enable_if_t<std::is_base_of<Child, Subclass>::value, bool> = true>
RefCountedPtr<Subclass> RefAsSubclass() {
IncrementRefCount();
return RefCountedPtr<Subclass>(static_cast<Subclass*>(this));
return RefCountedPtr<Subclass>(
DownCast<Subclass*>(static_cast<Child*>(this)));
}
template <
typename Subclass,
@ -318,7 +320,8 @@ class RefCounted : public Impl {
RefCountedPtr<Subclass> RefAsSubclass(const DebugLocation& location,
const char* reason) {
IncrementRefCount(location, reason);
return RefCountedPtr<Subclass>(static_cast<Subclass*>(this));
return RefCountedPtr<Subclass>(
DownCast<Subclass*>(static_cast<Child*>(this)));
}
// RefIfNonZero() for mutable types.

@ -30,6 +30,7 @@
#include "absl/hash/hash.h"
#include "src/core/lib/gprpp/debug_location.h"
#include "src/core/lib/gprpp/down_cast.h"
namespace grpc_core {
@ -159,7 +160,7 @@ class RefCountedPtr {
template <typename Y,
std::enable_if_t<std::is_base_of<T, Y>::value, bool> = true>
RefCountedPtr<Y> TakeAsSubclass() {
return RefCountedPtr<Y>(static_cast<Y*>(release()));
return RefCountedPtr<Y>(DownCast<Y*>(release()));
}
template <typename Y,

@ -36,7 +36,7 @@ struct ContextType;
// Some contexts can be subclassed. If the subclass is set as that context
// then GetContext<Base>() will return the base, and GetContext<Derived>() will
// down_cast to the derived type.
// DownCast to the derived type.
// Specializations of this type should be created for each derived type, and
// should have a single using statement Base pointing to the derived base class.
// Example:
@ -84,7 +84,7 @@ class Context<T, absl::void_t<typename ContextSubclass<T>::Base>>
public:
using Context<typename ContextSubclass<T>::Base>::Context;
static T* get() {
return down_cast<T*>(Context<typename ContextSubclass<T>::Base>::get());
return DownCast<T*>(Context<typename ContextSubclass<T>::Base>::get());
}
};

@ -32,8 +32,8 @@ class Derived : public Base {
TEST(DownCastTest, DownCast) {
Derived d;
Base* b = &d;
EXPECT_EQ(down_cast<Derived*>(b)->i, 3);
EXPECT_EQ(down_cast<Derived&>(*b).i, 3);
EXPECT_EQ(DownCast<Derived*>(b)->i, 3);
EXPECT_EQ(DownCast<Derived&>(*b).i, 3);
}
} // namespace

Loading…
Cancel
Save