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>
71
72 template <typename U> static double test(...);
73
74 static bool const value =
75 (sizeof(test<llvm::format_provider<Decayed>>(nullptr)) == 1);
76};
77
78// Test if raw_ostream& << T -> raw_ostream& is findable via ADL.
79template <class T> class has_StreamOperator {
80public:
81 using ConstRefT = const std::decay_t<T> &;
82
83 template <typename U>
84 static char test(std::enable_if_t<
85 std::is_same_v<decltype(std::declval<llvm::raw_ostream &>()
86 << std::declval<U>()),
88 int *>);
89
90 template <typename U> static double test(...);
91
92 static bool const value = (sizeof(test<ConstRefT>(nullptr)) == 1);
93};
94
95// Simple template that decides whether a type T should use the member-function
96// based format() invocation.
97template <typename T>
99 : public std::integral_constant<
100 bool, std::is_base_of_v<format_adapter, std::remove_reference_t<T>>> {
101};
102
103// Simple template that decides whether a type T should use the format_provider
104// based format() invocation. The member function takes priority, so this test
105// will only be true if there is not ALSO a format member.
106template <typename T>
108 : public std::integral_constant<
109 bool, !uses_format_member<T>::value && has_FormatProvider<T>::value> {
110};
111
112// Simple template that decides whether a type T should use the operator<<
113// based format() invocation. This takes last priority.
114template <typename T>
116 : public std::integral_constant<bool, !uses_format_member<T>::value &&
117 !uses_format_provider<T>::value &&
118 has_StreamOperator<T>::value> {};
119
120// Simple template that decides whether a type T has neither a member-function
121// nor format_provider based implementation that it can use. Mostly used so
122// that the compiler spits out a nice diagnostic when a type with no format
123// implementation can be located.
124template <typename T>
126 : public std::integral_constant<bool, !uses_format_member<T>::value &&
127 !uses_format_provider<T>::value &&
128 !uses_stream_operator<T>::value> {
129};
130
131template <typename T>
132std::enable_if_t<uses_format_member<T>::value, T>
134 return std::forward<T>(Item);
135}
136
137template <typename T>
138std::enable_if_t<uses_format_provider<T>::value, provider_format_adapter<T>>
140 return provider_format_adapter<T>(std::forward<T>(Item));
141}
142
143template <typename T>
144std::enable_if_t<uses_stream_operator<T>::value,
145 stream_operator_format_adapter<T>>
147 // If the caller passed an Error by value, then stream_operator_format_adapter
148 // would be responsible for consuming it.
149 // Make the caller opt into this by calling fmt_consume().
150 static_assert(
151 !std::is_same_v<llvm::Error, std::remove_cv_t<T>>,
152 "llvm::Error-by-value must be wrapped in fmt_consume() for formatv");
153 return stream_operator_format_adapter<T>(std::forward<T>(Item));
154}
155
156template <typename T>
157std::enable_if_t<uses_missing_provider<T>::value, missing_format_adapter<T>>
161} // namespace detail
162} // namespace support
163} // namespace llvm
164
165#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)
static char test(SameType< Signature_format, &U::format > *)
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.
Implement std::hash so that hash_code can be used in STL containers.
Definition BitVector.h:851