Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:44:30

0001 //===- FormatVariadicDetails.h - Helpers for FormatVariadic.h ----*- C++-*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 
0009 #ifndef LLVM_SUPPORT_FORMATVARIADICDETAILS_H
0010 #define LLVM_SUPPORT_FORMATVARIADICDETAILS_H
0011 
0012 #include "llvm/ADT/StringRef.h"
0013 #include "llvm/ADT/STLExtras.h"
0014 #include "llvm/Support/raw_ostream.h"
0015 
0016 #include <type_traits>
0017 
0018 namespace llvm {
0019 template <typename T, typename Enable = void> struct format_provider {};
0020 class Error;
0021 
0022 namespace support {
0023 namespace detail {
0024 class format_adapter {
0025   virtual void anchor();
0026 
0027 protected:
0028   virtual ~format_adapter() = default;
0029 
0030 public:
0031   virtual void format(raw_ostream &S, StringRef Options) = 0;
0032 };
0033 
0034 template <typename T> class provider_format_adapter : public format_adapter {
0035   T Item;
0036 
0037 public:
0038   explicit provider_format_adapter(T &&Item) : Item(std::forward<T>(Item)) {}
0039 
0040   void format(llvm::raw_ostream &S, StringRef Options) override {
0041     format_provider<std::decay_t<T>>::format(Item, S, Options);
0042   }
0043 };
0044 
0045 template <typename T>
0046 class stream_operator_format_adapter : public format_adapter {
0047   T Item;
0048 
0049 public:
0050   explicit stream_operator_format_adapter(T &&Item)
0051       : Item(std::forward<T>(Item)) {}
0052 
0053   void format(llvm::raw_ostream &S, StringRef) override { S << Item; }
0054 };
0055 
0056 template <typename T> class missing_format_adapter;
0057 
0058 // Test if format_provider<T> is defined on T and contains a member function
0059 // with the signature:
0060 //   static void format(const T&, raw_stream &, StringRef);
0061 //
0062 template <class T> class has_FormatProvider {
0063 public:
0064   using Decayed = std::decay_t<T>;
0065   typedef void (*Signature_format)(const Decayed &, llvm::raw_ostream &,
0066                                    StringRef);
0067 
0068   template <typename U>
0069   static char test(SameType<Signature_format, &U::format> *);
0070 
0071   template <typename U> static double test(...);
0072 
0073   static bool const value =
0074       (sizeof(test<llvm::format_provider<Decayed>>(nullptr)) == 1);
0075 };
0076 
0077 // Test if raw_ostream& << T -> raw_ostream& is findable via ADL.
0078 template <class T> class has_StreamOperator {
0079 public:
0080   using ConstRefT = const std::decay_t<T> &;
0081 
0082   template <typename U>
0083   static char test(std::enable_if_t<
0084                    std::is_same_v<decltype(std::declval<llvm::raw_ostream &>()
0085                                            << std::declval<U>()),
0086                                   llvm::raw_ostream &>,
0087                    int *>);
0088 
0089   template <typename U> static double test(...);
0090 
0091   static bool const value = (sizeof(test<ConstRefT>(nullptr)) == 1);
0092 };
0093 
0094 // Simple template that decides whether a type T should use the member-function
0095 // based format() invocation.
0096 template <typename T>
0097 struct uses_format_member
0098     : public std::integral_constant<
0099           bool, std::is_base_of_v<format_adapter, std::remove_reference_t<T>>> {
0100 };
0101 
0102 // Simple template that decides whether a type T should use the format_provider
0103 // based format() invocation.  The member function takes priority, so this test
0104 // will only be true if there is not ALSO a format member.
0105 template <typename T>
0106 struct uses_format_provider
0107     : public std::integral_constant<
0108           bool, !uses_format_member<T>::value && has_FormatProvider<T>::value> {
0109 };
0110 
0111 // Simple template that decides whether a type T should use the operator<<
0112 // based format() invocation.  This takes last priority.
0113 template <typename T>
0114 struct uses_stream_operator
0115     : public std::integral_constant<bool, !uses_format_member<T>::value &&
0116                                               !uses_format_provider<T>::value &&
0117                                               has_StreamOperator<T>::value> {};
0118 
0119 // Simple template that decides whether a type T has neither a member-function
0120 // nor format_provider based implementation that it can use.  Mostly used so
0121 // that the compiler spits out a nice diagnostic when a type with no format
0122 // implementation can be located.
0123 template <typename T>
0124 struct uses_missing_provider
0125     : public std::integral_constant<bool, !uses_format_member<T>::value &&
0126                                               !uses_format_provider<T>::value &&
0127                                               !uses_stream_operator<T>::value> {
0128 };
0129 
0130 template <typename T>
0131 std::enable_if_t<uses_format_member<T>::value, T>
0132 build_format_adapter(T &&Item) {
0133   return std::forward<T>(Item);
0134 }
0135 
0136 template <typename T>
0137 std::enable_if_t<uses_format_provider<T>::value, provider_format_adapter<T>>
0138 build_format_adapter(T &&Item) {
0139   return provider_format_adapter<T>(std::forward<T>(Item));
0140 }
0141 
0142 template <typename T>
0143 std::enable_if_t<uses_stream_operator<T>::value,
0144                  stream_operator_format_adapter<T>>
0145 build_format_adapter(T &&Item) {
0146   // If the caller passed an Error by value, then stream_operator_format_adapter
0147   // would be responsible for consuming it.
0148   // Make the caller opt into this by calling fmt_consume().
0149   static_assert(
0150       !std::is_same_v<llvm::Error, std::remove_cv_t<T>>,
0151       "llvm::Error-by-value must be wrapped in fmt_consume() for formatv");
0152   return stream_operator_format_adapter<T>(std::forward<T>(Item));
0153 }
0154 
0155 template <typename T>
0156 std::enable_if_t<uses_missing_provider<T>::value, missing_format_adapter<T>>
0157 build_format_adapter(T &&) {
0158   return missing_format_adapter<T>();
0159 }
0160 } // namespace detail
0161 } // namespace support
0162 } // namespace llvm
0163 
0164 #endif