[llvm] 0be41ed - [LLVM][Casting.h] Don't create a temporary while casting.

via llvm-commits llvm-commits at lists.llvm.org
Thu May 12 20:11:07 PDT 2022


Author: bzcheeseman
Date: 2022-05-12T23:11:02-04:00
New Revision: 0be41ed5bb57aded4e8ca1c6a8d22b7830c8f2fc

URL: https://github.com/llvm/llvm-project/commit/0be41ed5bb57aded4e8ca1c6a8d22b7830c8f2fc
DIFF: https://github.com/llvm/llvm-project/commit/0be41ed5bb57aded4e8ca1c6a8d22b7830c8f2fc.diff

LOG: [LLVM][Casting.h] Don't create a temporary while casting.

C-style casting can create a temporary when compiled by a C++ compiler, which was emitting a warning casting a reference to another reference. We can't use C++-style casting directly because it doesn't always work with incomplete types. In order to support the current use-cases, for references we switch to pointer space to perform the cast.

Reviewed By: qiongsiwu1

Differential Revision: https://reviews.llvm.org/D125482

Added: 
    

Modified: 
    llvm/include/llvm/Support/Casting.h
    llvm/unittests/Support/Casting.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/Support/Casting.h b/llvm/include/llvm/Support/Casting.h
index 8c07bf074c6db..5e87495135d1b 100644
--- a/llvm/include/llvm/Support/Casting.h
+++ b/llvm/include/llvm/Support/Casting.h
@@ -209,11 +209,19 @@ template <class To, class From, class SimpleFrom> struct cast_convert_val {
 };
 
 template <class To, class FromTy> struct cast_convert_val<To, FromTy, FromTy> {
-  // This _is_ a simple type, just cast it.
+  // If it's a reference, switch to a pointer to do the cast and then deref it.
   static typename cast_retty<To, FromTy>::ret_type doit(const FromTy &Val) {
-    typename cast_retty<To, FromTy>::ret_type Res2 =
-        (typename cast_retty<To, FromTy>::ret_type) const_cast<FromTy &>(Val);
-    return Res2;
+    return *(std::remove_reference_t<typename cast_retty<To, FromTy>::ret_type>
+                 *)&const_cast<FromTy &>(Val);
+  }
+};
+
+template <class To, class FromTy>
+struct cast_convert_val<To, FromTy *, FromTy *> {
+  // If it's a pointer, we can use c-style casting directly.
+  static typename cast_retty<To, FromTy *>::ret_type doit(const FromTy *Val) {
+    return (typename cast_retty<To, FromTy *>::ret_type) const_cast<FromTy *>(
+        Val);
   }
 };
 

diff  --git a/llvm/unittests/Support/Casting.cpp b/llvm/unittests/Support/Casting.cpp
index 56edf155511fb..086548f1e2128 100644
--- a/llvm/unittests/Support/Casting.cpp
+++ b/llvm/unittests/Support/Casting.cpp
@@ -298,11 +298,9 @@ TEST(CastingTest, unique_dyn_cast) {
   ASSERT_EQ(OrigD, D.get());
   ASSERT_EQ(nullptr, NewB);
 
-  // Converting between unrelated types should fail.  The original value should
-  // remain unchanged and it should return nullptr.
-  //
-  // Note that this is a very contrived test - most of the time we want a cast
-  // like this to emit a compiler error.
+  // This is a very contrived test, casting between completely unrelated types
+  // should generally fail to compile. See the classof shenanigans we have in
+  // the definition of `foo` above.
   auto F = unique_dyn_cast<foo>(D);
   ASSERT_EQ(nullptr, F);
   ASSERT_EQ(OrigD, D.get());
@@ -317,6 +315,9 @@ TEST(CastingTest, unique_dyn_cast) {
   auto B3 = unique_dyn_cast<base>(newb());
   EXPECT_NE(nullptr, B3);
 
+  // This is a very contrived test, casting between completely unrelated types
+  // should generally fail to compile. See the classof shenanigans we have in
+  // the definition of `foo` above.
   auto F2 = unique_dyn_cast<foo>(newb());
   EXPECT_EQ(nullptr, F2);
 }


        


More information about the llvm-commits mailing list