Gabriel B. has submitted this change. ( https://gem5-review.googlesource.com/c/public/gem5/+/67453?usp=email )

Change subject: base: Strengthen safe_cast and make it work for reference types
......................................................................

base: Strengthen safe_cast and make it work for reference types

safe_cast now supports the exact same types as dynamic_cast would. In
particular, it now supports l-value references and rejects r-value
references.

The non-debug version has also been updated to make it build only in
the same cases as the debug version of safe_cast would.

Change-Id: I86692561c169b1ad063000c990a52ea80c6637ca
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/67453
Reviewed-by: Giacomo Travaglini <giacomo.travagl...@arm.com>
Maintainer: Giacomo Travaglini <giacomo.travagl...@arm.com>
Tested-by: kokoro <noreply+kok...@google.com>
---
M src/base/cast.hh
1 file changed, 47 insertions(+), 5 deletions(-)

Approvals:
  Giacomo Travaglini: Looks good to me, approved; Looks good to me, approved
  kokoro: Regressions pass




diff --git a/src/base/cast.hh b/src/base/cast.hh
index cdc3c62..01464d9 100644
--- a/src/base/cast.hh
+++ b/src/base/cast.hh
@@ -30,6 +30,8 @@
 #define __BASE_CAST_HH__

 #include <cassert>
+#include <type_traits>
+#include "base/logging.hh"

 namespace gem5
 {
@@ -44,10 +46,20 @@

 template <class T, class U>
 inline T
-safe_cast(U ptr)
+safe_cast(U&& ref_or_ptr)
 {
-    T ret = dynamic_cast<T>(ptr);
-    assert(ret);
+    /*
+ * srd::forward used in conjunction with forwarding references (template T + * + T&&) ensures that dynamic_cast will see the exact same type that was
+     * passed to safe_cast (a.k.a., perfect forwarding).
+     *
+ * Not using std::forward would make safe_cast compile with references to
+     * temporary objects and thus return a dangling reference.
+     */
+    T ret = dynamic_cast<T>(std::forward<U>(ref_or_ptr));
+    if constexpr (std::is_pointer_v<T>) {
+        gem5_assert(ret);
+    }
     return ret;
 }

@@ -59,9 +71,19 @@

 template <class T, class U>
 inline T
-safe_cast(U ptr)
+safe_cast(U&& ref_or_ptr)
 {
-    return static_cast<T>(ptr);
+    /*
+ * safe_cast should be reserved to polymorphic types while static_cast is + * also allowed for non-polymorphic types. It could make safe_cast able to
+     * compile in a non-debug build and fail in a debug build.
+     */
+    static_assert(std::is_polymorphic_v<
+        std::remove_pointer_t<
+        std::remove_reference_t<
+        U>>
+    >);
+    return static_cast<T>(std::forward<U>(ref_or_ptr));
 }

 #endif

--
To view, visit https://gem5-review.googlesource.com/c/public/gem5/+/67453?usp=email To unsubscribe, or for help writing mail filters, visit https://gem5-review.googlesource.com/settings

Gerrit-Project: public/gem5
Gerrit-Branch: develop
Gerrit-Change-Id: I86692561c169b1ad063000c990a52ea80c6637ca
Gerrit-Change-Number: 67453
Gerrit-PatchSet: 4
Gerrit-Owner: Gabriel B. <gabriel.bus...@arteris.com>
Gerrit-Reviewer: Bobby Bruce <bbr...@ucdavis.edu>
Gerrit-Reviewer: Daniel Carvalho <oda...@yahoo.com.br>
Gerrit-Reviewer: Gabriel B. <gabriel.bus...@arteris.com>
Gerrit-Reviewer: Giacomo Travaglini <giacomo.travagl...@arm.com>
Gerrit-Reviewer: kokoro <noreply+kok...@google.com>
Gerrit-MessageType: merged
_______________________________________________
gem5-dev mailing list -- gem5-dev@gem5.org
To unsubscribe send an email to gem5-dev-le...@gem5.org

Reply via email to