LLVM 22.0.0git
FormatVariadicDetails.h
Go to the documentation of this file.
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/STLExtras.h"
13#include "llvm/ADT/StringRef.h"
16
17#include <type_traits>
18
19namespace llvm {
20template <typename T, typename Enable = void> struct format_provider {};
21class Error;
22
23namespace support {
24namespace detail {
26 virtual void anchor();
27
28protected:
29 virtual ~format_adapter() = default;
30
31public:
32 virtual void format(raw_ostream &S, StringRef Options) = 0;
33};
34
35template <typename T> class provider_format_adapter : public format_adapter {
36 T Item;
37
38public:
39 explicit provider_format_adapter(T &&Item) : Item(std::forward<T>(Item)) {}
40
44};
45
46template <typename T>
48 T Item;
49
50public:
52 : Item(std::forward<T>(Item)) {}
53
54 void format(llvm::raw_ostream &S, StringRef) override { S << Item; }
55};
56
57template <typename T> class missing_format_adapter;
58
59// Test if format_provider<T> is defined on T and contains a member function
60// with the signature:
61// static void format(const T&, raw_stream &, StringRef);
62//
63template <class T> class has_FormatProvider {
64public:
65 using Decayed = std::decay_t<T>;
66 typedef void (*Signature_format)(const Decayed &, llvm::raw_ostream &,
67 StringRef);
68
69 template <typename U> using check = SameType<Signature_format, &U::format>;
70
71 static constexpr bool value =
73};
74
75// Test if raw_ostream& << T -> raw_ostream& is findable via ADL.
76template <class T> class has_StreamOperator {
77public:
78 using ConstRefT = const std::decay_t<T> &;
79
80 template <typename U>
81 static auto test(int)
82 -> std::is_same<decltype(std::declval<llvm::raw_ostream &>()
83 << std::declval<U>()),
85
86 template <typename U> static auto test(...) -> std::false_type;
87
88 static constexpr bool value = decltype(test<ConstRefT>(0))::value;
89};
90
91// Simple template that decides whether a type T should use the member-function
92// based format() invocation.
93template <typename T>
95 : public std::bool_constant<
96 std::is_base_of_v<format_adapter, std::remove_reference_t<T>>> {};
97
98// Simple template that decides whether a type T should use the format_provider
99// based format() invocation. The member function takes priority, so this test
100// will only be true if there is not ALSO a format member.
101template <typename T>
103 : public std::bool_constant<!uses_format_member<T>::value &&
104 has_FormatProvider<T>::value> {};
105
106// Simple template that decides whether a type T should use the operator<<
107// based format() invocation. This takes last priority.
108template <typename T>
110 : public std::bool_constant<!uses_format_member<T>::value &&
111 !uses_format_provider<T>::value &&
112 has_StreamOperator<T>::value> {};
113
114// Simple template that decides whether a type T has neither a member-function
115// nor format_provider based implementation that it can use. Mostly used so
116// that the compiler spits out a nice diagnostic when a type with no format
117// implementation can be located.
118template <typename T>
120 : public std::bool_constant<!uses_format_member<T>::value &&
121 !uses_format_provider<T>::value &&
122 !uses_stream_operator<T>::value> {};
123
124template <typename T>
125std::enable_if_t<uses_format_member<T>::value, T>
127 return std::forward<T>(Item);
128}
129
130template <typename T>
131std::enable_if_t<uses_format_provider<T>::value, provider_format_adapter<T>>
133 return provider_format_adapter<T>(std::forward<T>(Item));
134}
135
136template <typename T>
137std::enable_if_t<uses_stream_operator<T>::value,
138 stream_operator_format_adapter<T>>
140 // If the caller passed an Error by value, then stream_operator_format_adapter
141 // would be responsible for consuming it.
142 // Make the caller opt into this by calling fmt_consume().
143 static_assert(
144 !std::is_same_v<llvm::Error, std::remove_cv_t<T>>,
145 "llvm::Error-by-value must be wrapped in fmt_consume() for formatv");
146 return stream_operator_format_adapter<T>(std::forward<T>(Item));
147}
148
149template <typename T>
150std::enable_if_t<uses_missing_provider<T>::value, missing_format_adapter<T>>
154} // namespace detail
155} // namespace support
156} // namespace llvm
157
158#endif
#define LLVM_ABI
Definition Compiler.h:213
static LVOptions Options
Definition LVOptions.cpp:25
#define T
modulo schedule test
This file contains some templates that are useful if you are working with the STL at all.
Lightweight error class with error context and mandatory checking.
Definition Error.h:159
StringRef - Represent a constant reference to a string, i.e.
Definition StringRef.h:55
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition raw_ostream.h:53
virtual void format(raw_ostream &S, StringRef Options)=0
void(* Signature_format)(const Decayed &, llvm::raw_ostream &, StringRef)
SameType< Signature_format, &U::format > check
static auto test(int) -> std::is_same< decltype(std::declval< llvm::raw_ostream & >()<< std::declval< U >()), llvm::raw_ostream & >
static auto test(...) -> std::false_type
void format(llvm::raw_ostream &S, StringRef Options) override
void format(llvm::raw_ostream &S, StringRef) override
std::enable_if_t< uses_format_member< T >::value, T > build_format_adapter(T &&Item)
This is an optimization pass for GlobalISel generic memory operations.
typename detail::detector< void, Op, Args... >::value_t is_detected
Detects if a given trait holds for some set of arguments 'Args'.
Implement std::hash so that hash_code can be used in STL containers.
Definition BitVector.h:851