//===- FormatVariadicDetails.h - Helpers for FormatVariadic.h ----*- C++-*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #ifndef LLVM_SUPPORT_FORMATVARIADIC_DETAILS_H #define LLVM_SUPPORT_FORMATVARIADIC_DETAILS_H #include "llvm/ADT/StringRef.h" #include "llvm/Support/raw_ostream.h" #include namespace llvm { template struct format_provider {}; class Error; namespace detail { class format_adapter { virtual void anchor(); protected: virtual ~format_adapter() {} public: virtual void format(raw_ostream &S, StringRef Options) = 0; }; template class provider_format_adapter : public format_adapter { T Item; public: explicit provider_format_adapter(T &&Item) : Item(std::forward(Item)) {} void format(llvm::raw_ostream &S, StringRef Options) override { format_provider::type>::format(Item, S, Options); } }; template class stream_operator_format_adapter : public format_adapter { T Item; public: explicit stream_operator_format_adapter(T &&Item) : Item(std::forward(Item)) {} void format(llvm::raw_ostream &S, StringRef Options) override { S << Item; } }; template class missing_format_adapter; // Test if format_provider is defined on T and contains a member function // with the signature: // static void format(const T&, raw_stream &, StringRef); // template class has_FormatProvider { public: using Decayed = typename std::decay::type; typedef void (*Signature_format)(const Decayed &, llvm::raw_ostream &, StringRef); template static char test(SameType *); template static double test(...); static bool const value = (sizeof(test>(nullptr)) == 1); }; // Test if raw_ostream& << T -> raw_ostream& is findable via ADL. template class has_StreamOperator { public: using ConstRefT = const typename std::decay::type &; template static char test(typename std::enable_if< std::is_same() << std::declval()), llvm::raw_ostream &>::value, int *>::type); template static double test(...); static bool const value = (sizeof(test(nullptr)) == 1); }; // Simple template that decides whether a type T should use the member-function // based format() invocation. template struct uses_format_member : public std::integral_constant< bool, std::is_base_of::type>::value> {}; // Simple template that decides whether a type T should use the format_provider // based format() invocation. The member function takes priority, so this test // will only be true if there is not ALSO a format member. template struct uses_format_provider : public std::integral_constant< bool, !uses_format_member::value && has_FormatProvider::value> { }; // Simple template that decides whether a type T should use the operator<< // based format() invocation. This takes last priority. template struct uses_stream_operator : public std::integral_constant::value && !uses_format_provider::value && has_StreamOperator::value> {}; // Simple template that decides whether a type T has neither a member-function // nor format_provider based implementation that it can use. Mostly used so // that the compiler spits out a nice diagnostic when a type with no format // implementation can be located. template struct uses_missing_provider : public std::integral_constant::value && !uses_format_provider::value && !uses_stream_operator::value> { }; template typename std::enable_if::value, T>::type build_format_adapter(T &&Item) { return std::forward(Item); } template typename std::enable_if::value, provider_format_adapter>::type build_format_adapter(T &&Item) { return provider_format_adapter(std::forward(Item)); } template typename std::enable_if::value, stream_operator_format_adapter>::type build_format_adapter(T &&Item) { // If the caller passed an Error by value, then stream_operator_format_adapter // would be responsible for consuming it. // Make the caller opt into this by calling fmt_consume(). static_assert( !std::is_same::type>::value, "llvm::Error-by-value must be wrapped in fmt_consume() for formatv"); return stream_operator_format_adapter(std::forward(Item)); } template typename std::enable_if::value, missing_format_adapter>::type build_format_adapter(T &&Item) { return missing_format_adapter(); } } } #endif