[llvm] b39f6a7 - [ADT] Extend EnableIfCallable for callables with incomplete returns

Daniil Suchkov via llvm-commits llvm-commits at lists.llvm.org
Mon Sep 13 12:17:08 PDT 2021


Author: Fehr Mathieu
Date: 2021-09-13T19:16:16Z
New Revision: b39f6a79ee88ea0c626a467ade032f052c9ce139

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

LOG: [ADT] Extend EnableIfCallable for callables with incomplete returns

std::is_convertible has no defined behavior when its arguments
are incomplete, even if they are equal. In practice, it returns false.
Adding std::is_same allows us to use the constructor using a callable,
even if the return value is incomplete. We also check the case where
we convert a T into a const T.

Reviewed By: DaniilSuchkov

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

Committer: Daniil Suchkov <dsuchkov at azul.com>

Added: 
    

Modified: 
    llvm/include/llvm/ADT/FunctionExtras.h
    llvm/unittests/ADT/FunctionExtrasTest.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/ADT/FunctionExtras.h b/llvm/include/llvm/ADT/FunctionExtras.h
index e67ef7377c88..43e98de1676f 100644
--- a/llvm/include/llvm/ADT/FunctionExtras.h
+++ b/llvm/include/llvm/ADT/FunctionExtras.h
@@ -64,11 +64,16 @@ template <typename CallableT, typename ThisT>
 using EnableUnlessSameType =
     std::enable_if_t<!std::is_same<remove_cvref_t<CallableT>, ThisT>::value>;
 template <typename CallableT, typename Ret, typename... Params>
-using EnableIfCallable =
-    std::enable_if_t<std::is_void<Ret>::value ||
-                     std::is_convertible<decltype(std::declval<CallableT>()(
-                                             std::declval<Params>()...)),
-                                         Ret>::value>;
+using EnableIfCallable = std::enable_if_t<llvm::disjunction<
+    std::is_void<Ret>,
+    std::is_same<decltype(std::declval<CallableT>()(std::declval<Params>()...)),
+                 Ret>,
+    std::is_same<const decltype(std::declval<CallableT>()(
+                     std::declval<Params>()...)),
+                 Ret>,
+    std::is_convertible<decltype(std::declval<CallableT>()(
+                            std::declval<Params>()...)),
+                        Ret>>::value>;
 
 template <typename ReturnT, typename... ParamTs> class UniqueFunctionBase {
 protected:

diff  --git a/llvm/unittests/ADT/FunctionExtrasTest.cpp b/llvm/unittests/ADT/FunctionExtrasTest.cpp
index 3c6f179c190f..fc856a976946 100644
--- a/llvm/unittests/ADT/FunctionExtrasTest.cpp
+++ b/llvm/unittests/ADT/FunctionExtrasTest.cpp
@@ -291,4 +291,23 @@ TEST(UniqueFunctionTest, IncompleteTypes) {
   unique_function<Templated<Incomplete> *()> IncompleteResultPointer;
 }
 
+// Incomplete function returning an incomplete type
+Incomplete incompleteFunction();
+const Incomplete incompleteFunctionConst();
+
+// Check that we can assign a callable to a unique_function when the
+// callable return value is incomplete.
+TEST(UniqueFunctionTest, IncompleteCallableType) {
+  unique_function<Incomplete()> IncompleteReturnInCallable{incompleteFunction};
+  unique_function<const Incomplete()> IncompleteReturnInCallableConst{
+      incompleteFunctionConst};
+  unique_function<const Incomplete()> IncompleteReturnInCallableConstConversion{
+      incompleteFunction};
+}
+
+// Define the incomplete function
+class Incomplete {};
+Incomplete incompleteFunction() { return {}; }
+const Incomplete incompleteFunctionConst() { return {}; }
+
 } // anonymous namespace


        


More information about the llvm-commits mailing list