tvl-depot/absl/strings/internal/str_format/arg.h

429 lines
16 KiB
C
Raw Normal View History

#ifndef ABSL_STRINGS_INTERNAL_STR_FORMAT_ARG_H_
#define ABSL_STRINGS_INTERNAL_STR_FORMAT_ARG_H_
#include <string.h>
#include <wchar.h>
#include <cstdio>
#include <iomanip>
#include <limits>
#include <memory>
#include <sstream>
#include <string>
#include <type_traits>
#include "absl/base/port.h"
#include "absl/meta/type_traits.h"
#include "absl/numeric/int128.h"
#include "absl/strings/internal/str_format/extension.h"
#include "absl/strings/string_view.h"
class CordReader;
namespace absl {
class Cord;
class FormatCountCapture;
class FormatSink;
namespace str_format_internal {
template <typename T, typename = void>
struct HasUserDefinedConvert : std::false_type {};
template <typename T>
struct HasUserDefinedConvert<
T, void_t<decltype(AbslFormatConvert(
std::declval<const T&>(), std::declval<ConversionSpec>(),
std::declval<FormatSink*>()))>> : std::true_type {};
Export of internal Abseil changes. -- bdce7e57e9e886eff1114d0266781b443f7ec639 by Derek Mauro <dmauro@google.com>: Change {Get|Set}EnvironmentVariable to {Get|Set}EnvironmentVariableA for compatibility with /DUNICODE. PiperOrigin-RevId: 239229514 -- 2276ed502326a044a84060d34eb19d499e3a3be2 by Derek Mauro <dmauro@google.com>: Import of CCTZ from GitHub. PiperOrigin-RevId: 239228622 -- a462efb970ff43b08a362ef2343fb75ac1295a50 by Derek Mauro <dmauro@google.com>: Adding linking of CoreFoundation to CMakeLists in absl/time. Import https://github.com/abseil/abseil-cpp/pull/280. Fix #283 PiperOrigin-RevId: 239220785 -- fc23327b97f940c682aae1956cf7a1bf87f88c06 by Derek Mauro <dmauro@google.com>: Add hermetic test script that uses Docker to build with a very recent version of gcc (8.3.0 today) with libstdc++ and bazel. PiperOrigin-RevId: 239220448 -- 418c08a8f6a53e63b84e39473035774417ca3aa7 by Derek Mauro <dmauro@google.com>: Disable part of the variant exeception safety test on move assignment when using versions of libstd++ that contain a bug. https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87431#c7 PiperOrigin-RevId: 239062455 -- 799722217aeda79679577843c91d5be62cbcbb42 by Matt Calabrese <calabrese@google.com>: Add internal-only IsSwappable traits corresponding to std::is_swappable and std::is_nothrow_swappable, which are used with the swap implementations of optional and variant. PiperOrigin-RevId: 239049448 -- aa46a036038a3de5c68ac5e5d3b4bf76f818d2ea by CJ Johnson <johnsoncj@google.com>: Make InlinedVectorStorage constructor explicit PiperOrigin-RevId: 239044361 -- 17949715b3aa21c794701f69f2154e91b6acabc3 by CJ Johnson <johnsoncj@google.com>: Add absl namesapce to internal/inlined_vector.h PiperOrigin-RevId: 239030789 -- 834628325953078cc08ed10d23bb8890e5bec897 by Derek Mauro <dmauro@google.com>: Add test script that uses Docker to build Abseil with gcc-4.8, libstdc++, and cmake. PiperOrigin-RevId: 239028433 -- 80fe24149ed73ed2ced995ad1e372fb060c60427 by CJ Johnson <johnsoncj@google.com>: Factors data members of InlinedVector into an impl type called InlinedVectorStorage so that (in future changes) the contents of a vector can be grouped together with a single pointer. PiperOrigin-RevId: 239021086 -- 585331436d5d4d79f845e45dcf79d918a0dc6169 by Derek Mauro <dmauro@google.com>: Add -Wno-missing-field-initializers to gcc compiler flags. gcc-4.x has spurious missing field initializer warnings. https://gcc.gnu.org/bugzilla/show_bug.cgi?id=36750 PiperOrigin-RevId: 239017217 -- 94602fe4e33ee3a552a7f2939c0f57a992f55075 by Abseil Team <absl-team@google.com>: Formatting fixes. PiperOrigin-RevId: 238983038 -- a1c1b63c08505574e0a8c491561840cecb2bb93e by Derek Mauro <dmauro@google.com>: Add hermetic test script that uses Docker to build with a very recent version of clang with libc++ and bazel. PiperOrigin-RevId: 238669118 -- e525f8d20bc2f79a0d69336b902f63858f3bff9d by Derek Mauro <dmauro@google.com>: Disable the test optionalTest.InPlaceTSFINAEBug until libc++ is updated. PiperOrigin-RevId: 238661703 -- f99a2a0b5ec424a059678f7f226600f137b4c74e by Derek Mauro <dmauro@google.com>: Correct the check for the FlatHashMap-Any test bug (list conditions instead of platforms when possible) PiperOrigin-RevId: 238653344 -- 777928035dbcbf39f361eb7d10dc3696822f692f by Jon Cohen <cohenjon@google.com>: Add install rules for Abseil CMake. These are attempted to be limited to in-project installation. This serves two purposes -- first it's morally the same as using Abseil in-source, except you don't have to rebuild us every time. Second, the presence of an install rule makes life massively simpler for package manager maintainers. Currently this doesn't install absl tests or testonly libraries. This can be added in a follow-up patch. Fixes #38, Fixes #80, Closes #182 PiperOrigin-RevId: 238645836 -- ded1c6ce697c191b7a6ff14572b3e6d183117b2c by Derek Mauro <dmauro@google.com>: Add hermetic test script that uses Docker to build with a very recent version of clang with libstdc++ and bazel. PiperOrigin-RevId: 238517815 GitOrigin-RevId: bdce7e57e9e886eff1114d0266781b443f7ec639 Change-Id: I6f745869cb8ef63851891ccac05ae9a7dd241c4f
2019-03-19 19:14:01 +01:00
template <typename T>
class StreamedWrapper;
// If 'v' can be converted (in the printf sense) according to 'conv',
// then convert it, appending to `sink` and return `true`.
// Otherwise fail and return `false`.
Export of internal Abseil changes. -- bdce7e57e9e886eff1114d0266781b443f7ec639 by Derek Mauro <dmauro@google.com>: Change {Get|Set}EnvironmentVariable to {Get|Set}EnvironmentVariableA for compatibility with /DUNICODE. PiperOrigin-RevId: 239229514 -- 2276ed502326a044a84060d34eb19d499e3a3be2 by Derek Mauro <dmauro@google.com>: Import of CCTZ from GitHub. PiperOrigin-RevId: 239228622 -- a462efb970ff43b08a362ef2343fb75ac1295a50 by Derek Mauro <dmauro@google.com>: Adding linking of CoreFoundation to CMakeLists in absl/time. Import https://github.com/abseil/abseil-cpp/pull/280. Fix #283 PiperOrigin-RevId: 239220785 -- fc23327b97f940c682aae1956cf7a1bf87f88c06 by Derek Mauro <dmauro@google.com>: Add hermetic test script that uses Docker to build with a very recent version of gcc (8.3.0 today) with libstdc++ and bazel. PiperOrigin-RevId: 239220448 -- 418c08a8f6a53e63b84e39473035774417ca3aa7 by Derek Mauro <dmauro@google.com>: Disable part of the variant exeception safety test on move assignment when using versions of libstd++ that contain a bug. https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87431#c7 PiperOrigin-RevId: 239062455 -- 799722217aeda79679577843c91d5be62cbcbb42 by Matt Calabrese <calabrese@google.com>: Add internal-only IsSwappable traits corresponding to std::is_swappable and std::is_nothrow_swappable, which are used with the swap implementations of optional and variant. PiperOrigin-RevId: 239049448 -- aa46a036038a3de5c68ac5e5d3b4bf76f818d2ea by CJ Johnson <johnsoncj@google.com>: Make InlinedVectorStorage constructor explicit PiperOrigin-RevId: 239044361 -- 17949715b3aa21c794701f69f2154e91b6acabc3 by CJ Johnson <johnsoncj@google.com>: Add absl namesapce to internal/inlined_vector.h PiperOrigin-RevId: 239030789 -- 834628325953078cc08ed10d23bb8890e5bec897 by Derek Mauro <dmauro@google.com>: Add test script that uses Docker to build Abseil with gcc-4.8, libstdc++, and cmake. PiperOrigin-RevId: 239028433 -- 80fe24149ed73ed2ced995ad1e372fb060c60427 by CJ Johnson <johnsoncj@google.com>: Factors data members of InlinedVector into an impl type called InlinedVectorStorage so that (in future changes) the contents of a vector can be grouped together with a single pointer. PiperOrigin-RevId: 239021086 -- 585331436d5d4d79f845e45dcf79d918a0dc6169 by Derek Mauro <dmauro@google.com>: Add -Wno-missing-field-initializers to gcc compiler flags. gcc-4.x has spurious missing field initializer warnings. https://gcc.gnu.org/bugzilla/show_bug.cgi?id=36750 PiperOrigin-RevId: 239017217 -- 94602fe4e33ee3a552a7f2939c0f57a992f55075 by Abseil Team <absl-team@google.com>: Formatting fixes. PiperOrigin-RevId: 238983038 -- a1c1b63c08505574e0a8c491561840cecb2bb93e by Derek Mauro <dmauro@google.com>: Add hermetic test script that uses Docker to build with a very recent version of clang with libc++ and bazel. PiperOrigin-RevId: 238669118 -- e525f8d20bc2f79a0d69336b902f63858f3bff9d by Derek Mauro <dmauro@google.com>: Disable the test optionalTest.InPlaceTSFINAEBug until libc++ is updated. PiperOrigin-RevId: 238661703 -- f99a2a0b5ec424a059678f7f226600f137b4c74e by Derek Mauro <dmauro@google.com>: Correct the check for the FlatHashMap-Any test bug (list conditions instead of platforms when possible) PiperOrigin-RevId: 238653344 -- 777928035dbcbf39f361eb7d10dc3696822f692f by Jon Cohen <cohenjon@google.com>: Add install rules for Abseil CMake. These are attempted to be limited to in-project installation. This serves two purposes -- first it's morally the same as using Abseil in-source, except you don't have to rebuild us every time. Second, the presence of an install rule makes life massively simpler for package manager maintainers. Currently this doesn't install absl tests or testonly libraries. This can be added in a follow-up patch. Fixes #38, Fixes #80, Closes #182 PiperOrigin-RevId: 238645836 -- ded1c6ce697c191b7a6ff14572b3e6d183117b2c by Derek Mauro <dmauro@google.com>: Add hermetic test script that uses Docker to build with a very recent version of clang with libstdc++ and bazel. PiperOrigin-RevId: 238517815 GitOrigin-RevId: bdce7e57e9e886eff1114d0266781b443f7ec639 Change-Id: I6f745869cb8ef63851891ccac05ae9a7dd241c4f
2019-03-19 19:14:01 +01:00
// Raw pointers.
struct VoidPtr {
VoidPtr() = default;
template <typename T,
decltype(reinterpret_cast<uintptr_t>(std::declval<T*>())) = 0>
VoidPtr(T* ptr) // NOLINT
: value(ptr ? reinterpret_cast<uintptr_t>(ptr) : 0) {}
uintptr_t value;
};
ConvertResult<Conv::p> FormatConvertImpl(VoidPtr v, ConversionSpec conv,
FormatSinkImpl* sink);
// Strings.
ConvertResult<Conv::s> FormatConvertImpl(const std::string& v,
ConversionSpec conv,
FormatSinkImpl* sink);
ConvertResult<Conv::s> FormatConvertImpl(string_view v, ConversionSpec conv,
FormatSinkImpl* sink);
ConvertResult<Conv::s | Conv::p> FormatConvertImpl(const char* v,
ConversionSpec conv,
FormatSinkImpl* sink);
template <class AbslCord,
typename std::enable_if<
std::is_same<AbslCord, absl::Cord>::value>::type* = nullptr,
class AbslCordReader = ::CordReader>
ConvertResult<Conv::s> FormatConvertImpl(const AbslCord& value,
ConversionSpec conv,
FormatSinkImpl* sink) {
if (conv.conv().id() != ConversionChar::s) return {false};
bool is_left = conv.flags().left;
size_t space_remaining = 0;
int width = conv.width();
if (width >= 0) space_remaining = width;
size_t to_write = value.size();
int precision = conv.precision();
if (precision >= 0)
Export of internal Abseil changes. -- 22fa219d17b2281c0695642830c4300711bd65ea by CJ Johnson <johnsoncj@google.com>: Rearrange the private method declarations in InlinedVector PiperOrigin-RevId: 224202447 -- eed3c9f488f23b521bee41d3683eb6cc22517ded by Derek Mauro <dmauro@google.com>: Fix leak_check target (it was always a no-op when LSAN isn't available). Fixes https://github.com/abseil/abseil-cpp/issues/232 PiperOrigin-RevId: 224201634 -- fc08039e175204b14a9561f618fcfc0234586801 by Greg Falcon <gfalcon@google.com>: Add parens around more invocations of min() and max() missed in my prior CL. PiperOrigin-RevId: 224162430 -- 0ec5476a8293c7796cd84928a1a558b14f14f222 by Abseil Team <absl-team@google.com>: Update absl/numeric/CMakeLists.txt to use new functions i.e. absl_cc_(library|test) PiperOrigin-RevId: 224139165 -- 2b46aa6fabb20c589661f8bbc84030ecf39ce394 by Abseil Team <absl-team@google.com>: Update absl/meta/CMakeLists.txt to use new functions i.e. absl_cc_(library|test) PiperOrigin-RevId: 224117258 -- 6c951c798f8c6903bd8793a8a4b5f69244be8aa9 by Abseil Team <absl-team@google.com>: Fix 2 Unused C++ BUILD Dependencies PiperOrigin-RevId: 224070093 -- 0ee7bd191708708f91fc5209c197fd93f6e4a8b3 by Greg Falcon <gfalcon@google.com>: Inside Abseil headers, wrap most invocations of methods and functions named `min` and `max` in parentheses, for better interoperability with Windows toolchains. CCTZ fixes will appear in a follow-up CL. PiperOrigin-RevId: 224051960 -- f562f56577b84a8bc07e5873775c01d068531bca by Jon Cohen <cohenjon@google.com>: Generate Abseil compile options. The single source of truth is now absl/copts/copts.py The way this works goes something like this: copts.py acts as the configuration file. We use python because unlike JSON it allows comments. It has two maps in it: one from names to external flags, and one from names to internal flags. generate_copts.py imports the maps and loops through them to write GENERATED_copts.bzl and GENERATED_AbseilCopts.cmake AbseilConfigureCopts.cmake and configure_copts.bzl import their respective copts args and set the platform-appropriate copts into ABSL_DEFAULT_COPTS, ABSL_TEST_COPTS, ABSL_EXCEPTIONS_FLAG, and ABSL_EXCEPTIONS_LINKOPTS For Bazel, each BUILD file load()s configure_copts.bzl For CMake, AbseilHelpers.cmake include()s AbseilConfigureCopts.cmake to get the final copts and both inserts them as needed into legacy target rules and also makes them available to the rest of our CMakeLists.txt file. We may instead want to include() AbseilConfigureCopts.cmake directly into each CMakeLists.txt file for consistency, but I'm not sure what the deal is with cmake and include guards, or if they are even needed. That's also not as idiomatic -- CMake tends to use directory scope where globals set at a higher level CMakeLists.txt file are used in the subdirectory CMakeLists.txt files. PiperOrigin-RevId: 224039419 -- f7402f6bb65037e668a7355f0a003f5c05a3b6a7 by Abseil Team <absl-team@google.com>: Import of CCTZ from GitHub. PiperOrigin-RevId: 224036622 GitOrigin-RevId: 22fa219d17b2281c0695642830c4300711bd65ea Change-Id: I6b505360539ff2aef8aa30c51a5f7d55db1c75cf
2018-12-05 21:37:41 +01:00
to_write = (std::min)(to_write, static_cast<size_t>(precision));
space_remaining = Excess(to_write, space_remaining);
if (space_remaining > 0 && !is_left) sink->Append(space_remaining, ' ');
string_view piece;
for (AbslCordReader reader(value);
to_write > 0 && reader.ReadFragment(&piece); to_write -= piece.size()) {
if (piece.size() > to_write) piece.remove_suffix(piece.size() - to_write);
sink->Append(piece);
}
if (space_remaining > 0 && is_left) sink->Append(space_remaining, ' ');
return {true};
}
using IntegralConvertResult =
ConvertResult<Conv::c | Conv::numeric | Conv::star>;
using FloatingConvertResult = ConvertResult<Conv::floating>;
// Floats.
FloatingConvertResult FormatConvertImpl(float v, ConversionSpec conv,
FormatSinkImpl* sink);
FloatingConvertResult FormatConvertImpl(double v, ConversionSpec conv,
FormatSinkImpl* sink);
FloatingConvertResult FormatConvertImpl(long double v, ConversionSpec conv,
FormatSinkImpl* sink);
// Chars.
IntegralConvertResult FormatConvertImpl(char v, ConversionSpec conv,
FormatSinkImpl* sink);
IntegralConvertResult FormatConvertImpl(signed char v, ConversionSpec conv,
FormatSinkImpl* sink);
IntegralConvertResult FormatConvertImpl(unsigned char v, ConversionSpec conv,
FormatSinkImpl* sink);
// Ints.
IntegralConvertResult FormatConvertImpl(short v, // NOLINT
ConversionSpec conv,
FormatSinkImpl* sink);
IntegralConvertResult FormatConvertImpl(unsigned short v, // NOLINT
ConversionSpec conv,
FormatSinkImpl* sink);
IntegralConvertResult FormatConvertImpl(int v, ConversionSpec conv,
FormatSinkImpl* sink);
IntegralConvertResult FormatConvertImpl(unsigned v, ConversionSpec conv,
FormatSinkImpl* sink);
IntegralConvertResult FormatConvertImpl(long v, // NOLINT
ConversionSpec conv,
FormatSinkImpl* sink);
IntegralConvertResult FormatConvertImpl(unsigned long v, // NOLINT
ConversionSpec conv,
FormatSinkImpl* sink);
IntegralConvertResult FormatConvertImpl(long long v, // NOLINT
ConversionSpec conv,
FormatSinkImpl* sink);
IntegralConvertResult FormatConvertImpl(unsigned long long v, // NOLINT
ConversionSpec conv,
FormatSinkImpl* sink);
IntegralConvertResult FormatConvertImpl(int128 v, ConversionSpec conv,
FormatSinkImpl* sink);
IntegralConvertResult FormatConvertImpl(uint128 v, ConversionSpec conv,
FormatSinkImpl* sink);
template <typename T, enable_if_t<std::is_same<T, bool>::value, int> = 0>
IntegralConvertResult FormatConvertImpl(T v, ConversionSpec conv,
FormatSinkImpl* sink) {
return FormatConvertImpl(static_cast<int>(v), conv, sink);
}
// We provide this function to help the checker, but it is never defined.
// FormatArgImpl will use the underlying Convert functions instead.
template <typename T>
typename std::enable_if<std::is_enum<T>::value &&
!HasUserDefinedConvert<T>::value,
IntegralConvertResult>::type
FormatConvertImpl(T v, ConversionSpec conv, FormatSinkImpl* sink);
template <typename T>
ConvertResult<Conv::s> FormatConvertImpl(const StreamedWrapper<T>& v,
ConversionSpec conv,
FormatSinkImpl* out) {
std::ostringstream oss;
oss << v.v_;
if (!oss) return {false};
return str_format_internal::FormatConvertImpl(oss.str(), conv, out);
}
// Use templates and dependent types to delay evaluation of the function
// until after FormatCountCapture is fully defined.
struct FormatCountCaptureHelper {
template <class T = int>
static ConvertResult<Conv::n> ConvertHelper(const FormatCountCapture& v,
ConversionSpec conv,
FormatSinkImpl* sink) {
const absl::enable_if_t<sizeof(T) != 0, FormatCountCapture>& v2 = v;
if (conv.conv().id() != str_format_internal::ConversionChar::n)
return {false};
*v2.p_ = static_cast<int>(sink->size());
return {true};
}
};
template <class T = int>
ConvertResult<Conv::n> FormatConvertImpl(const FormatCountCapture& v,
ConversionSpec conv,
FormatSinkImpl* sink) {
return FormatCountCaptureHelper::ConvertHelper(v, conv, sink);
}
// Helper friend struct to hide implementation details from the public API of
// FormatArgImpl.
struct FormatArgImplFriend {
template <typename Arg>
static bool ToInt(Arg arg, int* out) {
// A value initialized ConversionSpec has a `none` conv, which tells the
// dispatcher to run the `int` conversion.
return arg.dispatcher_(arg.data_, {}, out);
}
template <typename Arg>
static bool Convert(Arg arg, str_format_internal::ConversionSpec conv,
FormatSinkImpl* out) {
return arg.dispatcher_(arg.data_, conv, out);
}
template <typename Arg>
static typename Arg::Dispatcher GetVTablePtrForTest(Arg arg) {
return arg.dispatcher_;
}
};
// A type-erased handle to a format argument.
class FormatArgImpl {
private:
enum { kInlinedSpace = 8 };
using VoidPtr = str_format_internal::VoidPtr;
union Data {
const void* ptr;
const volatile void* volatile_ptr;
char buf[kInlinedSpace];
};
using Dispatcher = bool (*)(Data, ConversionSpec, void* out);
template <typename T>
struct store_by_value
: std::integral_constant<bool, (sizeof(T) <= kInlinedSpace) &&
(std::is_integral<T>::value ||
std::is_floating_point<T>::value ||
std::is_pointer<T>::value ||
std::is_same<VoidPtr, T>::value)> {};
enum StoragePolicy { ByPointer, ByVolatilePointer, ByValue };
template <typename T>
struct storage_policy
: std::integral_constant<StoragePolicy,
(std::is_volatile<T>::value
? ByVolatilePointer
: (store_by_value<T>::value ? ByValue
: ByPointer))> {
};
// To reduce the number of vtables we will decay values before hand.
// Anything with a user-defined Convert will get its own vtable.
// For everything else:
// - Decay char* and char arrays into `const char*`
// - Decay any other pointer to `const void*`
// - Decay all enums to their underlying type.
// - Decay function pointers to void*.
template <typename T, typename = void>
struct DecayType {
static constexpr bool kHasUserDefined =
str_format_internal::HasUserDefinedConvert<T>::value;
using type = typename std::conditional<
!kHasUserDefined && std::is_convertible<T, const char*>::value,
const char*,
typename std::conditional<!kHasUserDefined &&
std::is_convertible<T, VoidPtr>::value,
VoidPtr, const T&>::type>::type;
};
template <typename T>
struct DecayType<T,
typename std::enable_if<
!str_format_internal::HasUserDefinedConvert<T>::value &&
std::is_enum<T>::value>::type> {
using type = typename std::underlying_type<T>::type;
};
public:
template <typename T>
explicit FormatArgImpl(const T& value) {
using D = typename DecayType<T>::type;
static_assert(
std::is_same<D, const T&>::value || storage_policy<D>::value == ByValue,
"Decayed types must be stored by value");
Init(static_cast<D>(value));
}
private:
friend struct str_format_internal::FormatArgImplFriend;
template <typename T, StoragePolicy = storage_policy<T>::value>
struct Manager;
template <typename T>
struct Manager<T, ByPointer> {
static Data SetValue(const T& value) {
Data data;
data.ptr = std::addressof(value);
return data;
}
static const T& Value(Data arg) { return *static_cast<const T*>(arg.ptr); }
};
template <typename T>
struct Manager<T, ByVolatilePointer> {
static Data SetValue(const T& value) {
Data data;
data.volatile_ptr = &value;
return data;
}
static const T& Value(Data arg) {
return *static_cast<const T*>(arg.volatile_ptr);
}
};
template <typename T>
struct Manager<T, ByValue> {
static Data SetValue(const T& value) {
Data data;
memcpy(data.buf, &value, sizeof(value));
return data;
}
static T Value(Data arg) {
T value;
memcpy(&value, arg.buf, sizeof(T));
return value;
}
};
template <typename T>
void Init(const T& value) {
data_ = Manager<T>::SetValue(value);
dispatcher_ = &Dispatch<T>;
}
template <typename T>
static int ToIntVal(const T& val) {
using CommonType = typename std::conditional<std::is_signed<T>::value,
int64_t, uint64_t>::type;
if (static_cast<CommonType>(val) >
Export of internal Abseil changes. -- ba4dd47492748bd630462eb68b7959037fc6a11a by Abseil Team <absl-team@google.com>: Work around nvcc 9.0 compiler bug for open-source Tensorflow build. With the current implementation, when I (unintentionally and transitively) include absl/types/optional.h in a CUDA compilation unit, I get the following nvcc error message: INFO: From Compiling tensorflow/core/kernels/crop_and_resize_op_gpu.cu.cc: external/com_google_absl/absl/types/optional.h: In member function 'void absl::optional_internal::optional_data_dtor_base<T, <anonymous> >::destruct()': external/com_google_absl/absl/types/optional.h:185:50: error: '__T0' was not declared in this scope data_.~T(); I've also seen similar compilation failures online, for flat_hash_map: https://devtalk.nvidia.com/default/topic/1042599/nvcc-preprocessor-bug-causes-compilation-failure/ The bug is always around unnamed template parameters. Therefore, the workaround is to make them named. PiperOrigin-RevId: 219208288 -- dad2f40cb2e8d5017660985ef6fb57f3c3cdcc80 by CJ Johnson <johnsoncj@google.com>: Adds internal macros for catching and throwing unknown exception types PiperOrigin-RevId: 219207362 -- 0a9840328d2d86e8420b853435fdbf1f7a19d931 by Abseil Team <absl-team@google.com>: Fix typo in mutex.h comments. PiperOrigin-RevId: 219199397 -- 0d576dc7597564210bfdf91518075064756f0bf4 by Matt Calabrese <calabrese@google.com>: Internal change. PiperOrigin-RevId: 219185475 -- 66be156095571959fb19a76da8ad0b53ec37658e by Abseil Team <absl-team@google.com>: Fix alignment conformance for VS 2017 >= 15.8 (fix #193) PiperOrigin-RevId: 219129894 -- a6e1825a12587945f8194677ccfdcaba6f7aad1d by Abseil Team <absl-team@google.com>: Reapply PR #173 PiperOrigin-RevId: 219129361 -- cf72ade4881b25acc6ccaea468f69793a0fdce32 by Abseil Team <absl-team@google.com>: Update .gitignore PiperOrigin-RevId: 219127495 -- 0537490c6348a2cb489abe15638928ac5aa6982a by Jon Cohen <cohenjon@google.com>: Small refactor and reformat of error messages from the exception safety test framework. PiperOrigin-RevId: 218927773 -- 4c556ca45fa25698ad12002a00c713aeceefab73 by CJ Johnson <johnsoncj@google.com>: Updates the inlined vector swap tests to check for number of moves that took place if available PiperOrigin-RevId: 218900777 -- dcbfda0021a1e6dfa9586986b1269c06ec394053 by Mark Barolak <mbar@google.com>: Add parens around calls to std::numeric_limits<>::min and std::numeric_limits<>::max to prevent compilation errors on Windows platforms where min and max are defined as macros. PiperOrigin-RevId: 218888700 GitOrigin-RevId: ba4dd47492748bd630462eb68b7959037fc6a11a Change-Id: I0e393958eb8cb501b85f6114979f6d4d86ed996c
2018-10-29 23:53:34 +01:00
static_cast<CommonType>((std::numeric_limits<int>::max)())) {
return (std::numeric_limits<int>::max)();
} else if (std::is_signed<T>::value &&
static_cast<CommonType>(val) <
Export of internal Abseil changes. -- ba4dd47492748bd630462eb68b7959037fc6a11a by Abseil Team <absl-team@google.com>: Work around nvcc 9.0 compiler bug for open-source Tensorflow build. With the current implementation, when I (unintentionally and transitively) include absl/types/optional.h in a CUDA compilation unit, I get the following nvcc error message: INFO: From Compiling tensorflow/core/kernels/crop_and_resize_op_gpu.cu.cc: external/com_google_absl/absl/types/optional.h: In member function 'void absl::optional_internal::optional_data_dtor_base<T, <anonymous> >::destruct()': external/com_google_absl/absl/types/optional.h:185:50: error: '__T0' was not declared in this scope data_.~T(); I've also seen similar compilation failures online, for flat_hash_map: https://devtalk.nvidia.com/default/topic/1042599/nvcc-preprocessor-bug-causes-compilation-failure/ The bug is always around unnamed template parameters. Therefore, the workaround is to make them named. PiperOrigin-RevId: 219208288 -- dad2f40cb2e8d5017660985ef6fb57f3c3cdcc80 by CJ Johnson <johnsoncj@google.com>: Adds internal macros for catching and throwing unknown exception types PiperOrigin-RevId: 219207362 -- 0a9840328d2d86e8420b853435fdbf1f7a19d931 by Abseil Team <absl-team@google.com>: Fix typo in mutex.h comments. PiperOrigin-RevId: 219199397 -- 0d576dc7597564210bfdf91518075064756f0bf4 by Matt Calabrese <calabrese@google.com>: Internal change. PiperOrigin-RevId: 219185475 -- 66be156095571959fb19a76da8ad0b53ec37658e by Abseil Team <absl-team@google.com>: Fix alignment conformance for VS 2017 >= 15.8 (fix #193) PiperOrigin-RevId: 219129894 -- a6e1825a12587945f8194677ccfdcaba6f7aad1d by Abseil Team <absl-team@google.com>: Reapply PR #173 PiperOrigin-RevId: 219129361 -- cf72ade4881b25acc6ccaea468f69793a0fdce32 by Abseil Team <absl-team@google.com>: Update .gitignore PiperOrigin-RevId: 219127495 -- 0537490c6348a2cb489abe15638928ac5aa6982a by Jon Cohen <cohenjon@google.com>: Small refactor and reformat of error messages from the exception safety test framework. PiperOrigin-RevId: 218927773 -- 4c556ca45fa25698ad12002a00c713aeceefab73 by CJ Johnson <johnsoncj@google.com>: Updates the inlined vector swap tests to check for number of moves that took place if available PiperOrigin-RevId: 218900777 -- dcbfda0021a1e6dfa9586986b1269c06ec394053 by Mark Barolak <mbar@google.com>: Add parens around calls to std::numeric_limits<>::min and std::numeric_limits<>::max to prevent compilation errors on Windows platforms where min and max are defined as macros. PiperOrigin-RevId: 218888700 GitOrigin-RevId: ba4dd47492748bd630462eb68b7959037fc6a11a Change-Id: I0e393958eb8cb501b85f6114979f6d4d86ed996c
2018-10-29 23:53:34 +01:00
static_cast<CommonType>((std::numeric_limits<int>::min)())) {
return (std::numeric_limits<int>::min)();
}
return static_cast<int>(val);
}
template <typename T>
static bool ToInt(Data arg, int* out, std::true_type /* is_integral */,
std::false_type) {
*out = ToIntVal(Manager<T>::Value(arg));
return true;
}
template <typename T>
static bool ToInt(Data arg, int* out, std::false_type,
std::true_type /* is_enum */) {
*out = ToIntVal(static_cast<typename std::underlying_type<T>::type>(
Manager<T>::Value(arg)));
return true;
}
template <typename T>
static bool ToInt(Data, int*, std::false_type, std::false_type) {
return false;
}
template <typename T>
static bool Dispatch(Data arg, ConversionSpec spec, void* out) {
// A `none` conv indicates that we want the `int` conversion.
if (ABSL_PREDICT_FALSE(spec.conv().id() == ConversionChar::none)) {
return ToInt<T>(arg, static_cast<int*>(out), std::is_integral<T>(),
std::is_enum<T>());
}
return str_format_internal::FormatConvertImpl(
Manager<T>::Value(arg), spec, static_cast<FormatSinkImpl*>(out))
.value;
}
Data data_;
Dispatcher dispatcher_;
};
#define ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(T, E) \
E template bool FormatArgImpl::Dispatch<T>(Data, ConversionSpec, void*)
#define ABSL_INTERNAL_FORMAT_DISPATCH_OVERLOADS_EXPAND_(...) \
ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(str_format_internal::VoidPtr, \
__VA_ARGS__); \
ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(bool, __VA_ARGS__); \
ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(char, __VA_ARGS__); \
ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(signed char, __VA_ARGS__); \
ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(unsigned char, __VA_ARGS__); \
ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(short, __VA_ARGS__); /* NOLINT */ \
ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(unsigned short, /* NOLINT */ \
__VA_ARGS__); \
ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(int, __VA_ARGS__); \
ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(unsigned int, __VA_ARGS__); \
ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(long, __VA_ARGS__); /* NOLINT */ \
ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(unsigned long, /* NOLINT */ \
__VA_ARGS__); \
ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(long long, /* NOLINT */ \
__VA_ARGS__); \
ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(unsigned long long, /* NOLINT */ \
__VA_ARGS__); \
ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(int128, __VA_ARGS__); \
ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(uint128, __VA_ARGS__); \
ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(float, __VA_ARGS__); \
ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(double, __VA_ARGS__); \
ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(long double, __VA_ARGS__); \
ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(const char*, __VA_ARGS__); \
ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(std::string, __VA_ARGS__); \
ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(string_view, __VA_ARGS__)
ABSL_INTERNAL_FORMAT_DISPATCH_OVERLOADS_EXPAND_(extern);
} // namespace str_format_internal
} // namespace absl
#endif // ABSL_STRINGS_INTERNAL_STR_FORMAT_ARG_H_