LCOV - code coverage report
Current view: top level - include/llvm/Support - FormatVariadicDetails.h (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 114 137 83.2 %
Date: 2018-10-20 13:21:21 Functions: 95 116 81.9 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //===- FormatVariadicDetails.h - Helpers for FormatVariadic.h ----*- 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             : #ifndef LLVM_SUPPORT_FORMATVARIADIC_DETAILS_H
      11             : #define LLVM_SUPPORT_FORMATVARIADIC_DETAILS_H
      12             : 
      13             : #include "llvm/ADT/StringRef.h"
      14             : #include "llvm/Support/raw_ostream.h"
      15             : 
      16             : #include <type_traits>
      17             : 
      18             : namespace llvm {
      19             : template <typename T, typename Enable = void> struct format_provider {};
      20             : class Error;
      21             : 
      22             : namespace detail {
      23       89172 : class format_adapter {
      24             : protected:
      25           0 :   virtual ~format_adapter() {}
      26             : 
      27             : public:
      28             :   virtual void format(raw_ostream &S, StringRef Options) = 0;
      29             : };
      30             : 
      31      182220 : template <typename T> class provider_format_adapter : public format_adapter {
      32             :   T Item;
      33             : 
      34             : public:
      35        8662 :   explicit provider_format_adapter(T &&Item) : Item(std::forward<T>(Item)) {}
      36             : 
      37      114063 :   void format(llvm::raw_ostream &S, StringRef Options) override {
      38      124724 :     format_provider<typename std::decay<T>::type>::format(Item, S, Options);
      39      114063 :   }
      40       40162 : };
      41       40162 : 
      42       40162 : template <typename T>
      43       29448 : class stream_operator_format_adapter : public format_adapter {
      44       29448 :   T Item;
      45       29448 : 
      46       11331 : public:
      47       11331 :   explicit stream_operator_format_adapter(T &&Item)
      48       11331 :       : Item(std::forward<T>(Item)) {}
      49        8807 : 
      50        8121 :   void format(llvm::raw_ostream &S, StringRef Options) override { S << Item; }
      51        8121 : };
      52        8975 : 
      53        8975 : template <typename T> class missing_format_adapter;
      54        8975 : 
      55        8348 : // Test if format_provider<T> is defined on T and contains a member function
      56        9034 : // with the signature:
      57        8348 : //   static void format(const T&, raw_stream &, StringRef);
      58         401 : //
      59         401 : template <class T> class has_FormatProvider {
      60         401 : public:
      61         148 :   using Decayed = typename std::decay<T>::type;
      62         148 :   typedef void (*Signature_format)(const Decayed &, llvm::raw_ostream &,
      63         148 :                                    StringRef);
      64         672 : 
      65         672 :   template <typename U>
      66         672 :   static char test(SameType<Signature_format, &U::format> *);
      67         100 : 
      68          58 :   template <typename U> static double test(...);
      69          58 : 
      70         854 :   static bool const value =
      71         854 :       (sizeof(test<llvm::format_provider<Decayed>>(nullptr)) == 1);
      72         854 : };
      73          35 : 
      74          56 : // Test if raw_ostream& << T -> raw_ostream& is findable via ADL.
      75          35 : template <class T> class has_StreamOperator {
      76          10 : public:
      77          10 :   using ConstRefT = const typename std::decay<T>::type &;
      78          10 : 
      79          14 :   template <typename U>
      80          14 :   static char test(typename std::enable_if<
      81          14 :                    std::is_same<decltype(std::declval<llvm::raw_ostream &>()
      82          17 :                                          << std::declval<U>()),
      83          17 :                                 llvm::raw_ostream &>::value,
      84          17 :                    int *>::type);
      85          17 : 
      86          17 :   template <typename U> static double test(...);
      87          17 : 
      88           2 :   static bool const value = (sizeof(test<ConstRefT>(nullptr)) == 1);
      89           2 : };
      90           2 : 
      91           9 : // Simple template that decides whether a type T should use the member-function
      92           9 : // based format() invocation.
      93           9 : template <typename T>
      94           6 : struct uses_format_member
      95           6 :     : public std::integral_constant<
      96           6 :           bool,
      97           5 :           std::is_base_of<format_adapter,
      98           5 :                           typename std::remove_reference<T>::type>::value> {};
      99           5 : 
     100          14 : // Simple template that decides whether a type T should use the format_provider
     101          14 : // based format() invocation.  The member function takes priority, so this test
     102          14 : // will only be true if there is not ALSO a format member.
     103         963 : template <typename T>
     104         963 : struct uses_format_provider
     105         963 :     : public std::integral_constant<
     106          26 :           bool, !uses_format_member<T>::value && has_FormatProvider<T>::value> {
     107          26 : };
     108          26 : 
     109         135 : // Simple template that decides whether a type T should use the operator<<
     110         135 : // based format() invocation.  This takes last priority.
     111         135 : template <typename T>
     112          18 : struct uses_stream_operator
     113          18 :     : public std::integral_constant<bool, !uses_format_member<T>::value &&
     114          18 :                                               !uses_format_provider<T>::value &&
     115           1 :                                               has_StreamOperator<T>::value> {};
     116           1 : 
     117           1 : // Simple template that decides whether a type T has neither a member-function
     118         172 : // nor format_provider based implementation that it can use.  Mostly used so
     119         172 : // that the compiler spits out a nice diagnostic when a type with no format
     120         172 : // implementation can be located.
     121          54 : template <typename T>
     122          54 : struct uses_missing_provider
     123          54 :     : public std::integral_constant<bool, !uses_format_member<T>::value &&
     124           5 :                                               !uses_format_provider<T>::value &&
     125           5 :                                               !uses_stream_operator<T>::value> {
     126           5 : };
     127           5 : 
     128           5 : template <typename T>
     129           5 : typename std::enable_if<uses_format_member<T>::value, T>::type
     130           1 : build_format_adapter(T &&Item) {
     131           1 :   return std::forward<T>(Item);
     132           1 : }
     133           5 : 
     134           5 : template <typename T>
     135           5 : typename std::enable_if<uses_format_provider<T>::value,
     136          16 :                         provider_format_adapter<T>>::type
     137          16 : build_format_adapter(T &&Item) {
     138          16 :   return provider_format_adapter<T>(std::forward<T>(Item));
     139          24 : }
     140          24 : 
     141          24 : template <typename T>
     142           1 : typename std::enable_if<uses_stream_operator<T>::value,
     143           1 :                         stream_operator_format_adapter<T>>::type
     144           1 : build_format_adapter(T &&Item) {
     145             :   // If the caller passed an Error by value, then stream_operator_format_adapter
     146           0 :   // would be responsible for consuming it.
     147           0 :   // Make the caller opt into this by calling fmt_consume().
     148          12 :   static_assert(
     149           0 :       !std::is_same<llvm::Error, typename std::remove_cv<T>::type>::value,
     150           0 :       "llvm::Error-by-value must be wrapped in fmt_consume() for formatv");
     151             :   return stream_operator_format_adapter<T>(std::forward<T>(Item));
     152           0 : }
     153           2 : 
     154             : template <typename T>
     155           4 : typename std::enable_if<uses_missing_provider<T>::value,
     156           0 :                         missing_format_adapter<T>>::type
     157             : build_format_adapter(T &&Item) {
     158             :   return missing_format_adapter<T>();
     159             : }
     160             : }
     161           0 : }
     162           0 : 
     163             : #endif

Generated by: LCOV version 1.13