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::is_base_of<format_adapter, std::remove_reference_t<T>> {};
96
97// Simple template that decides whether a type T should use the format_provider
98// based format() invocation. The member function takes priority, so this test
99// will only be true if there is not ALSO a format member.
100template <typename T>
102 : public std::bool_constant<!uses_format_member<T>::value &&
103 has_FormatProvider<T>::value> {};
104
105// Simple template that decides whether a type T should use the operator<<
106// based format() invocation. This takes last priority.
107template <typename T>
109 : public std::bool_constant<!uses_format_member<T>::value &&
110 !uses_format_provider<T>::value &&
111 has_StreamOperator<T>::value> {};
112
113// Simple template that decides whether a type T has neither a member-function
114// nor format_provider based implementation that it can use. Mostly used so
115// that the compiler spits out a nice diagnostic when a type with no format
116// implementation can be located.
117template <typename T>
119 : public std::bool_constant<!uses_format_member<T>::value &&
120 !uses_format_provider<T>::value &&
121 !uses_stream_operator<T>::value> {};
122
123template <typename T>
124std::enable_if_t<uses_format_member<T>::value, T>
126 return std::forward<T>(Item);
127}
128
129template <typename T>
130std::enable_if_t<uses_format_provider<T>::value, provider_format_adapter<T>>
132 return provider_format_adapter<T>(std::forward<T>(Item));
133}
134
135template <typename T>
136std::enable_if_t<uses_stream_operator<T>::value,
137 stream_operator_format_adapter<T>>
139 // If the caller passed an Error by value, then stream_operator_format_adapter
140 // would be responsible for consuming it.
141 // Make the caller opt into this by calling fmt_consume().
142 static_assert(
143 !std::is_same_v<llvm::Error, std::remove_cv_t<T>>,
144 "llvm::Error-by-value must be wrapped in fmt_consume() for formatv");
145 return stream_operator_format_adapter<T>(std::forward<T>(Item));
146}
147
148template <typename T>
149std::enable_if_t<uses_missing_provider<T>::value, missing_format_adapter<T>>
153} // namespace detail
154} // namespace support
155} // namespace llvm
156
157#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:870