diff --git a/Makefile b/Makefile
index fb283e0c902937fd69d1c91a3b06aadae002dfbe..6685799a1e43dfc0fd8c4d71ecc76dc14f59d818 100644
--- a/Makefile
+++ b/Makefile
@@ -355,7 +355,7 @@ LDFLAGS += -framework CoreFoundation
 endif
 CFLAGS += -g
 CPPFLAGS += -g -Wall -Wextra -DOSATOMIC_USE_INLINED=1 -Ithird_party/upb -Isrc/core/ext/upb-generated
-COREFLAGS += -fno-rtti -fno-exceptions
+COREFLAGS += -fno-exceptions
 LDFLAGS += -g
 
 CPPFLAGS += $(CPPFLAGS_$(CONFIG))
@@ -7925,7 +7925,7 @@ PUBLIC_HEADERS_C += \
 LIBBORINGSSL_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBBORINGSSL_SRC))))
 
 $(LIBBORINGSSL_OBJS): CPPFLAGS += -Ithird_party/boringssl/include -fvisibility=hidden -DOPENSSL_NO_ASM -D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN -D_HAS_EXCEPTIONS=0 -DNOMINMAX
-$(LIBBORINGSSL_OBJS): CXXFLAGS += -fno-rtti -fno-exceptions
+$(LIBBORINGSSL_OBJS): CXXFLAGS += -fno-exceptions
 $(LIBBORINGSSL_OBJS): CFLAGS += -g
 
 $(LIBDIR)/$(CONFIG)/libboringssl.a: $(ZLIB_DEP) $(CARES_DEP) $(ADDRESS_SORTING_DEP)  $(LIBBORINGSSL_OBJS) 
@@ -7955,7 +7955,7 @@ PUBLIC_HEADERS_CXX += \
 LIBBORINGSSL_TEST_UTIL_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBBORINGSSL_TEST_UTIL_SRC))))
 
 $(LIBBORINGSSL_TEST_UTIL_OBJS): CPPFLAGS += -Ithird_party/boringssl/include -fvisibility=hidden -DOPENSSL_NO_ASM -D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN -D_HAS_EXCEPTIONS=0 -DNOMINMAX
-$(LIBBORINGSSL_TEST_UTIL_OBJS): CXXFLAGS += -fno-rtti -fno-exceptions
+$(LIBBORINGSSL_TEST_UTIL_OBJS): CXXFLAGS += -fno-exceptions
 $(LIBBORINGSSL_TEST_UTIL_OBJS): CFLAGS += -g
 
 ifeq ($(NO_PROTOBUF),true)
@@ -20118,7 +20118,7 @@ $(BINDIR)/$(CONFIG)/boringssl_ssl_test: $(PROTOBUF_DEP) $(BORINGSSL_SSL_TEST_OBJ
 endif
 
 $(BORINGSSL_SSL_TEST_OBJS): CPPFLAGS += -Ithird_party/boringssl/include -fvisibility=hidden -DOPENSSL_NO_ASM -D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN -D_HAS_EXCEPTIONS=0 -DNOMINMAX
-$(BORINGSSL_SSL_TEST_OBJS): CXXFLAGS += -fno-rtti -fno-exceptions
+$(BORINGSSL_SSL_TEST_OBJS): CXXFLAGS += -fno-exceptions
 $(BORINGSSL_SSL_TEST_OBJS): CFLAGS += -g
 $(OBJDIR)/$(CONFIG)/third_party/boringssl/crypto/test/gtest_main.o:  $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a $(LIBDIR)/$(CONFIG)/libboringssl.a
 
@@ -20210,7 +20210,7 @@ $(BINDIR)/$(CONFIG)/boringssl_crypto_test: $(PROTOBUF_DEP) $(BORINGSSL_CRYPTO_TE
 endif
 
 $(BORINGSSL_CRYPTO_TEST_OBJS): CPPFLAGS += -Ithird_party/boringssl/include -fvisibility=hidden -DOPENSSL_NO_ASM -D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN -D_HAS_EXCEPTIONS=0 -DNOMINMAX
-$(BORINGSSL_CRYPTO_TEST_OBJS): CXXFLAGS += -fno-rtti -fno-exceptions
+$(BORINGSSL_CRYPTO_TEST_OBJS): CXXFLAGS += -fno-exceptions
 $(BORINGSSL_CRYPTO_TEST_OBJS): CFLAGS += -g
 $(OBJDIR)/$(CONFIG)/src/boringssl/crypto_test_data.o:  $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a $(LIBDIR)/$(CONFIG)/libboringssl.a
 
diff --git a/build.yaml b/build.yaml
index 615ed4f793576a0583ece1d4324b4140a29980e5..302b61ec394e4e7cb42afd2f9fbdedb597431800 100644
--- a/build.yaml
+++ b/build.yaml
@@ -6165,10 +6165,10 @@ defaults:
     CFLAGS: -g
     CPPFLAGS: -Ithird_party/boringssl/include -fvisibility=hidden -DOPENSSL_NO_ASM
       -D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN -D_HAS_EXCEPTIONS=0 -DNOMINMAX
-    CXXFLAGS: -fno-rtti -fno-exceptions
+    CXXFLAGS: -fno-exceptions
   global:
     CFLAGS: -g
-    COREFLAGS: -fno-rtti -fno-exceptions
+    COREFLAGS: -fno-exceptions
     CPPFLAGS: -g -Wall -Wextra -DOSATOMIC_USE_INLINED=1 -Ithird_party/upb -Isrc/core/ext/upb-generated
     LDFLAGS: -g
   zlib:
diff --git a/src/core/lib/gprpp/memory.h b/src/core/lib/gprpp/memory.h
index 26917ef1c8490b484497801efe7c2da71e1e596d..e101ed376c216f3f75e1f407a6da49c5ee58d917 100644
--- a/src/core/lib/gprpp/memory.h
+++ b/src/core/lib/gprpp/memory.h
@@ -48,19 +48,32 @@
 
 namespace grpc_core {
 
-// Alternative to new, since we cannot use it (for fear of libstdc++)
+// Alternative to new, to ensure memory allocation being wrapped to gpr_malloc
 template <typename T, typename... Args>
 inline T* New(Args&&... args) {
   void* p = gpr_malloc(sizeof(T));
   return new (p) T(std::forward<Args>(args)...);
 }
 
-// Alternative to delete, since we cannot use it (for fear of libstdc++)
+// Gets the base pointer of any class, in case of multiple inheritence.
+// Used by Delete and friends.
+template <typename T, bool isPolymorphic>
+struct BasePointerGetter {
+  static void* get(T* p) { return p; }
+};
+
+template <typename T>
+struct BasePointerGetter<T, true> {
+  static void* get(T* p) { return dynamic_cast<void*>(p); }
+};
+
+// Alternative to delete, to ensure memory allocation being wrapped to gpr_free
 template <typename T>
 inline void Delete(T* p) {
   if (p == nullptr) return;
+  void* basePtr = BasePointerGetter<T, std::is_polymorphic<T>::value>::get(p);
   p->~T();
-  gpr_free(p);
+  gpr_free(basePtr);
 }
 
 class DefaultDelete {
@@ -68,12 +81,13 @@ class DefaultDelete {
   template <typename T>
   void operator()(T* p) {
     // Delete() checks whether the value is null, but std::unique_ptr<> is
-    // gauranteed not to call the deleter if the pointer is nullptr
+    // guaranteed not to call the deleter if the pointer is nullptr
     // (i.e., it already does this check for us), and we don't want to
     // do the check twice.  So, instead of calling Delete() here, we
     // manually call the object's dtor and free it.
+    void* basePtr = BasePointerGetter<T, std::is_polymorphic<T>::value>::get(p);
     p->~T();
-    gpr_free(p);
+    gpr_free(basePtr);
   }
 };
 
diff --git a/test/core/gprpp/memory_test.cc b/test/core/gprpp/memory_test.cc
index bb6a219a848dec28b046899a4250640d9969efe0..b148d7dfccba3137423cf4f9c8698587614e735c 100644
--- a/test/core/gprpp/memory_test.cc
+++ b/test/core/gprpp/memory_test.cc
@@ -29,6 +29,21 @@ struct Foo {
   int b;
 };
 
+struct Base1 {
+  int a;
+  virtual ~Base1() {}
+};
+
+struct Base2 {
+  int b;
+  virtual ~Base2() {}
+};
+
+struct Compound : public Base1, Base2 {
+  int c;
+  virtual ~Compound() {}
+};
+
 TEST(MemoryTest, NewDeleteTest) { Delete(New<int>()); }
 
 TEST(MemoryTest, NewDeleteWithArgTest) {
@@ -64,6 +79,12 @@ TEST(MemoryTest, UniquePtrWithCustomDeleter) {
   EXPECT_EQ(1, n);
 }
 
+TEST(MemoryTest, MultipleInheritence) {
+  Base2* p = New<Compound>();
+  EXPECT_NE(p, dynamic_cast<void*>(p));
+  Delete(p);
+}
+
 }  // namespace testing
 }  // namespace grpc_core