LCOV - code coverage report
Current view: top level - clang/tools/extra/clangd - Function.h (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 0 10 0.0 %
Date: 2018-05-20 00:06:23 Functions: 0 85 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //===--- Function.h - Utility callable wrappers  -----------------*- C++-*-===//
       2             : //
       3             : //                     The LLVM Compiler Infrastructure
       4             : //
       5             : // This file is distributed under the University of Illinois Open Source
       6             : // License. See LICENSE.TXT for details.
       7             : //
       8             : //===----------------------------------------------------------------------===//
       9             : //
      10             : // This file provides an analogue to std::function that supports move semantics.
      11             : //
      12             : //===----------------------------------------------------------------------===//
      13             : 
      14             : #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_FUNCTION_H
      15             : #define LLVM_CLANG_TOOLS_EXTRA_CLANGD_FUNCTION_H
      16             : 
      17             : #include "llvm/ADT/STLExtras.h"
      18             : #include "llvm/Support/Error.h"
      19             : #include <cassert>
      20             : #include <memory>
      21             : #include <tuple>
      22             : #include <type_traits>
      23             : #include <utility>
      24             : 
      25             : namespace clang {
      26             : namespace clangd {
      27             : 
      28             : /// A move-only type-erasing function wrapper. Similar to `std::function`, but
      29             : /// allows to store move-only callables.
      30             : template <class> class UniqueFunction;
      31             : /// A Callback<T> is a void function that accepts Expected<T>.
      32             : /// This is accepted by ClangdServer functions that logically return T.
      33             : template <typename T> using Callback = UniqueFunction<void(llvm::Expected<T>)>;
      34             : 
      35             : template <class Ret, class... Args> class UniqueFunction<Ret(Args...)> {
      36             : public:
      37             :   UniqueFunction() = default;
      38             :   UniqueFunction(std::nullptr_t) : UniqueFunction(){};
      39             : 
      40             :   UniqueFunction(UniqueFunction const &) = delete;
      41             :   UniqueFunction &operator=(UniqueFunction const &) = delete;
      42             : 
      43             :   UniqueFunction(UniqueFunction &&) noexcept = default;
      44             :   UniqueFunction &operator=(UniqueFunction &&) noexcept = default;
      45             : 
      46             :   template <class Callable,
      47             :             /// A sfinae-check that Callable can be called with Args... and
      48             :             class = typename std::enable_if<std::is_convertible<
      49             :                 decltype(std::declval<Callable>()(std::declval<Args>()...)),
      50             :                 Ret>::value>::type>
      51           0 :   UniqueFunction(Callable &&Func)
      52             :       : CallablePtr(llvm::make_unique<
      53             :                     FunctionCallImpl<typename std::decay<Callable>::type>>(
      54           0 :             std::forward<Callable>(Func))) {}
      55             : 
      56             :   explicit operator bool() { return bool(CallablePtr); }
      57             : 
      58             :   Ret operator()(Args... As) {
      59             :     assert(CallablePtr);
      60             :     return CallablePtr->Call(std::forward<Args>(As)...);
      61             :   }
      62             : 
      63             : private:
      64             :   class FunctionCallBase {
      65             :   public:
      66             :     virtual ~FunctionCallBase() = default;
      67             :     virtual Ret Call(Args... As) = 0;
      68             :   };
      69             : 
      70             :   template <class Callable>
      71           0 :   class FunctionCallImpl final : public FunctionCallBase {
      72             :     static_assert(
      73             :         std::is_same<Callable, typename std::decay<Callable>::type>::value,
      74             :         "FunctionCallImpl must be instanstiated with std::decay'ed types");
      75             : 
      76             :   public:
      77           0 :     FunctionCallImpl(Callable Func) : Func(std::move(Func)) {}
      78             : 
      79           0 :     Ret Call(Args... As) override { return Func(std::forward<Args>(As)...); }
      80             : 
      81             :   private:
      82             :     Callable Func;
      83             :   };
      84             : 
      85             :   std::unique_ptr<FunctionCallBase> CallablePtr;
      86             : };
      87             : 
      88             : /// Stores a callable object (Func) and arguments (Args) and allows to call the
      89             : /// callable with provided arguments later using `operator ()`. The arguments
      90             : /// are std::forward'ed into the callable in the body of `operator()`. Therefore
      91             : /// `operator()` can only be called once, as some of the arguments could be
      92             : /// std::move'ed into the callable on first call.
      93             : template <class Func, class... Args> struct ForwardBinder {
      94             :   using Tuple = std::tuple<typename std::decay<Func>::type,
      95             :                            typename std::decay<Args>::type...>;
      96             :   Tuple FuncWithArguments;
      97             : #ifndef NDEBUG
      98             :   bool WasCalled = false;
      99             : #endif
     100             : 
     101             : public:
     102             :   ForwardBinder(Tuple FuncWithArguments)
     103             :       : FuncWithArguments(std::move(FuncWithArguments)) {}
     104             : 
     105             : private:
     106             :   template <std::size_t... Indexes, class... RestArgs>
     107           0 :   auto CallImpl(llvm::integer_sequence<std::size_t, Indexes...> Seq,
     108             :                 RestArgs &&... Rest)
     109             :       -> decltype(std::get<0>(this->FuncWithArguments)(
     110             :           std::forward<Args>(std::get<Indexes + 1>(this->FuncWithArguments))...,
     111             :           std::forward<RestArgs>(Rest)...)) {
     112           0 :     return std::get<0>(this->FuncWithArguments)(
     113             :         std::forward<Args>(std::get<Indexes + 1>(this->FuncWithArguments))...,
     114           0 :         std::forward<RestArgs>(Rest)...);
     115             :   }
     116             : 
     117             : public:
     118             :   template <class... RestArgs>
     119             :   auto operator()(RestArgs &&... Rest)
     120             :       -> decltype(this->CallImpl(llvm::index_sequence_for<Args...>(),
     121             :                                  std::forward<RestArgs>(Rest)...)) {
     122             : 
     123             : #ifndef NDEBUG
     124             :     assert(!WasCalled && "Can only call result of Bind once.");
     125             :     WasCalled = true;
     126             : #endif
     127           0 :     return CallImpl(llvm::index_sequence_for<Args...>(),
     128             :                     std::forward<RestArgs>(Rest)...);
     129             :   }
     130             : };
     131             : 
     132             : /// Creates an object that stores a callable (\p F) and first arguments to the
     133             : /// callable (\p As) and allows to call \p F with \Args at a later point.
     134             : /// Similar to std::bind, but also works with move-only \p F and \p As.
     135             : ///
     136             : /// The returned object must be called no more than once, as \p As are
     137             : /// std::forwarded'ed (therefore can be moved) into \p F during the call.
     138             : template <class Func, class... Args>
     139             : ForwardBinder<Func, Args...> Bind(Func F, Args &&... As) {
     140             :   return ForwardBinder<Func, Args...>(
     141           0 :       std::make_tuple(std::forward<Func>(F), std::forward<Args>(As)...));
     142             : }
     143             : 
     144             : } // namespace clangd
     145             : } // namespace clang
     146             : 
     147             : #endif

Generated by: LCOV version 1.13