[gprpp] Implement down_cast - a debug-time checked down cast (#35548)

Closes #35548

COPYBARA_INTEGRATE_REVIEW=https://github.com/grpc/grpc/pull/35548 from ctiller:down_cast cd7501dadd
PiperOrigin-RevId: 599176414
pull/35580/head
Craig Tiller 1 year ago committed by Copybara-Service
parent e36025d3d2
commit c77ba326e9
  1. 35
      CMakeLists.txt
  2. 13
      build_autogenerated.yaml
  3. 7
      src/core/BUILD
  4. 49
      src/core/lib/gprpp/down_cast.h
  5. 12
      test/core/gprpp/BUILD
  6. 45
      test/core/gprpp/down_cast_test.cc
  7. 1
      tools/distrib/fix_build_deps.py
  8. 24
      tools/run_tests/generated/tests.json

35
CMakeLists.txt generated

@ -1009,6 +1009,7 @@ if(gRPC_BUILD_TESTS)
add_dependencies(buildtests_cxx disappearing_server_test)
add_dependencies(buildtests_cxx dns_resolver_cooldown_test)
add_dependencies(buildtests_cxx dns_resolver_test)
add_dependencies(buildtests_cxx down_cast_test)
add_dependencies(buildtests_cxx dual_ref_counted_test)
if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
add_dependencies(buildtests_cxx dualstack_socket_test)
@ -11917,6 +11918,40 @@ target_link_libraries(dns_resolver_test
)
endif()
if(gRPC_BUILD_TESTS)
add_executable(down_cast_test
test/core/gprpp/down_cast_test.cc
)
target_compile_features(down_cast_test PUBLIC cxx_std_14)
target_include_directories(down_cast_test
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/include
${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
${_gRPC_RE2_INCLUDE_DIR}
${_gRPC_SSL_INCLUDE_DIR}
${_gRPC_UPB_GENERATED_DIR}
${_gRPC_UPB_GRPC_GENERATED_DIR}
${_gRPC_UPB_INCLUDE_DIR}
${_gRPC_XXHASH_INCLUDE_DIR}
${_gRPC_ZLIB_INCLUDE_DIR}
third_party/googletest/googletest/include
third_party/googletest/googletest
third_party/googletest/googlemock/include
third_party/googletest/googlemock
${_gRPC_PROTO_GENS_DIR}
)
target_link_libraries(down_cast_test
${_gRPC_ALLTARGETS_LIBRARIES}
gtest
absl::config
gpr
)
endif()
if(gRPC_BUILD_TESTS)

@ -7990,6 +7990,19 @@ targets:
deps:
- gtest
- grpc_test_util
- name: down_cast_test
gtest: true
build: test
language: c++
headers:
- src/core/lib/gprpp/down_cast.h
src:
- test/core/gprpp/down_cast_test.cc
deps:
- gtest
- absl/base:config
- gpr
uses_polling: false
- name: dual_ref_counted_test
gtest: true
build: test

@ -5085,6 +5085,13 @@ grpc_cc_library(
],
)
grpc_cc_library(
name = "down_cast",
hdrs = ["lib/gprpp/down_cast.h"],
external_deps = ["absl/base:config"],
deps = ["//:gpr"],
)
grpc_cc_library(
name = "status_conversion",
srcs = ["lib/transport/status_conversion.cc"],

@ -0,0 +1,49 @@
// Copyright 2024 gRPC authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef GRPC_SRC_CORE_LIB_GPRPP_DOWN_CAST_H
#define GRPC_SRC_CORE_LIB_GPRPP_DOWN_CAST_H
#include <grpc/support/port_platform.h>
#include <type_traits>
#include "absl/base/config.h"
#include <grpc/support/log.h>
namespace grpc_core {
template <typename To, typename From>
inline To down_cast(From* f) {
static_assert(
std::is_base_of<From, typename std::remove_pointer<To>::type>::value,
"down_cast 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
if (f != nullptr) GPR_ASSERT(dynamic_cast<To>(f) != nullptr);
#endif
#endif
return static_cast<To>(f);
}
template <typename To, typename From>
inline To down_cast(From& f) {
return *down_cast<typename std::remove_reference<To>::type*>(&f);
}
} // namespace grpc_core
#endif // GRPC_SRC_CORE_LIB_GPRPP_DOWN_CAST_H

@ -135,6 +135,18 @@ grpc_cc_test(
],
)
grpc_cc_test(
name = "down_cast_test",
srcs = ["down_cast_test.cc"],
external_deps = ["gtest"],
language = "C++",
uses_event_engine = False,
uses_polling = False,
deps = [
"//src/core:down_cast",
],
)
grpc_cc_test(
name = "table_test",
srcs = ["table_test.cc"],

@ -0,0 +1,45 @@
// Copyright 2024 gRPC authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "src/core/lib/gprpp/down_cast.h"
#include "gtest/gtest.h"
namespace grpc_core {
namespace {
class Base {
public:
virtual ~Base() = default;
};
class Derived : public Base {
public:
int i = 3;
};
TEST(DownCastTest, DownCast) {
Derived d;
Base* b = &d;
EXPECT_EQ(down_cast<Derived*>(b)->i, 3);
EXPECT_EQ(down_cast<Derived&>(*b).i, 3);
}
} // namespace
} // namespace grpc_core
int main(int argc, char** argv) {
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}

@ -44,6 +44,7 @@ EXTERNAL_DEPS = {
"absl/algorithm/container.h": "absl/algorithm:container",
"absl/base/attributes.h": "absl/base:core_headers",
"absl/base/call_once.h": "absl/base",
"absl/base/config.h": "absl/base:config",
# TODO(ctiller) remove this
"absl/base/internal/endian.h": "absl/base:endian",
"absl/base/thread_annotations.h": "absl/base:core_headers",

@ -2899,6 +2899,30 @@
],
"uses_polling": true
},
{
"args": [],
"benchmark": false,
"ci_platforms": [
"linux",
"mac",
"posix",
"windows"
],
"cpu_cost": 1.0,
"exclude_configs": [],
"exclude_iomgrs": [],
"flaky": false,
"gtest": true,
"language": "c++",
"name": "down_cast_test",
"platforms": [
"linux",
"mac",
"posix",
"windows"
],
"uses_polling": false
},
{
"args": [],
"benchmark": false,

Loading…
Cancel
Save