Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Blame | Last modification | View Log | Download | RSS feed

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