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 char test(std::enable_if_t<
82 std::is_same_v<decltype(std::declval<llvm::raw_ostream &>()
83 << std::declval<U>()),
85 int *>);
86
87 template <typename U> static double test(...);
88
89 static bool const value = (sizeof(test<ConstRefT>(nullptr)) == 1);
90};
91
92// Simple template that decides whether a type T should use the member-function
93// based format() invocation.
94template <typename T>
96 : public std::bool_constant<
97 std::is_base_of_v<format_adapter, std::remove_reference_t<T>>> {};
98
99// Simple template that decides whether a type T should use the format_provider
100// based format() invocation. The member function takes priority, so this test
101// will only be true if there is not ALSO a format member.
102template <typename T>
104 : public std::bool_constant<!uses_format_member<T>::value &&
105 has_FormatProvider<T>::value> {};
106
107// Simple template that decides whether a type T should use the operator<<
108// based format() invocation. This takes last priority.
109template <typename T>
111 : public std::bool_constant<!uses_format_member<T>::value &&
112 !uses_format_provider<T>::value &&
113 has_StreamOperator<T>::value> {};
114
115// Simple template that decides whether a type T has neither a member-function
116// nor format_provider based implementation that it can use. Mostly used so
117// that the compiler spits out a nice diagnostic when a type with no format
118// implementation can be located.
119template <typename T>
121 : public std::bool_constant<!uses_format_member<T>::value &&
122 !uses_format_provider<T>::value &&
123 !uses_stream_operator<T>::value> {};
124
125template <typename T>
126std::enable_if_t<uses_format_member<T>::value, T>
128 return std::forward<T>(Item);
129}
130
131template <typename T>
132std::enable_if_t<uses_format_provider<T>::value, provider_format_adapter<T>>
134 return provider_format_adapter<T>(std::forward<T>(Item));
135}
136
137template <typename T>
138std::enable_if_t<uses_stream_operator<T>::value,
139 stream_operator_format_adapter<T>>
141 // If the caller passed an Error by value, then stream_operator_format_adapter
142 // would be responsible for consuming it.
143 // Make the caller opt into this by calling fmt_consume().
144 static_assert(
145 !std::is_same_v<llvm::Error, std::remove_cv_t<T>>,
146 "llvm::Error-by-value must be wrapped in fmt_consume() for formatv");
147 return stream_operator_format_adapter<T>(std::forward<T>(Item));
148}
149
150template <typename T>
151std::enable_if_t<uses_missing_provider<T>::value, missing_format_adapter<T>>
155} // namespace detail
156} // namespace support
157} // namespace llvm
158
159#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 char test(std::enable_if_t< std::is_same_v< decltype(std::declval< llvm::raw_ostream & >()<< std::declval< U >()), llvm::raw_ostream & >, int * >)
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