Export of internal Abseil changes

--
7a9e8d95f795be037aa2dce4e44809ad0166aaec by Samuel Benzaquen <sbenza@google.com>:

Make end() iterator be nullptr.
This makes the creation of and comparison with end() smaller and faster. `find()!=end()` becomes leaner.

PiperOrigin-RevId: 304681605

--
8f3024979446b391b79b1b60ada7d00a504d6aa6 by Derek Mauro <dmauro@google.com>:

Fix Bazel's distdir detection and prefer double brackets (bash recommendation)

PiperOrigin-RevId: 304615725

--
f1d709cb4b2b3743d548b814dd19602fb057a5e6 by Abseil Team <absl-team@google.com>:

Internal change

PiperOrigin-RevId: 304570545

--
2bbfa5bda52057e1938a96c286ad33ff64e535e0 by Gennadiy Rozental <rogeeff@google.com>:

Implement general storage case as aligned buffer.

Aside from eliminating dynamic memory allocation for flag storage, we also saving 11 bytes per int flag, 15 bytes per double and string flag.

PiperOrigin-RevId: 304511965

--
9e1aed2a95d7d060f8b906fe8c67fc3ba537b521 by Derek Mauro <dmauro@google.com>:

Use reserve to make a bad_alloc less likely in endian_test

This happened once and shouldn't have happened, so it was probably
just a flake, but might as well make this change.

PiperOrigin-RevId: 304505572

--
c2faf22ba2d4d66753390e6959494214895581f0 by Gennadiy Rozental <rogeeff@google.com>:

Use anonymous bit fields to enforce separation between const and mutable bit fields.

We also move init_control field (which is now safe) to save 8 bytes per flag (based on size_tester output)

PiperOrigin-RevId: 304505215

--
7ec51250a84bb03e826b3caad64431e91748186a by Krzysztof Kosiński <krzysio@google.com>:

Change the buffer size in AppendNumberUnit to constexpr.

PiperOrigin-RevId: 304492779

--
a6c8db1be4f421ea7b7c02f7a01b4f48bad61883 by Gennadiy Rozental <rogeeff@google.com>:

Add test cases for two word storage.

Some additional tests were added for other storage kinds as well. These came about after I started to look into a coverage output and noticed that some cases (like reading flag values via reflection) were not covered by this test at all. It does not make sense to just add tests for two word values, so I've covered other storage kinds as well.

PiperOrigin-RevId: 304432511

--
2644ecc32e1215cd6451efcb2f1054fd77e7c812 by Abseil Team <absl-team@google.com>:

Internal change

PiperOrigin-RevId: 304254681

--
4949a6b20c2bb4b9b2c811f439ccb893abc08df5 by Abseil Team <absl-team@google.com>:

Internal change

PiperOrigin-RevId: 304250274
GitOrigin-RevId: 7a9e8d95f795be037aa2dce4e44809ad0166aaec
Change-Id: I01623de87355bec5cf87cc5932a1ca44cade9aae
This commit is contained in:
Abseil Team 2020-04-03 13:24:29 -07:00 committed by Andy Getz
parent 62f05b1f57
commit d43b7997c0
25 changed files with 362 additions and 184 deletions

View file

@ -31,7 +31,9 @@ cc_library(
hdrs = ["algorithm.h"], hdrs = ["algorithm.h"],
copts = ABSL_DEFAULT_COPTS, copts = ABSL_DEFAULT_COPTS,
linkopts = ABSL_DEFAULT_LINKOPTS, linkopts = ABSL_DEFAULT_LINKOPTS,
deps = ["//absl/base:config"], deps = [
"//absl/base:config",
],
) )
cc_test( cc_test(

View file

@ -57,6 +57,7 @@ const uint16_t k16ValueBE{0x2301};
template<typename T> template<typename T>
std::vector<T> GenerateAllValuesForType() { std::vector<T> GenerateAllValuesForType() {
std::vector<T> result; std::vector<T> result;
result.reserve(size_t{1} << (sizeof(T) * 8));
T next = std::numeric_limits<T>::min(); T next = std::numeric_limits<T>::min();
while (true) { while (true) {
result.push_back(next); result.push_back(next);
@ -68,10 +69,11 @@ std::vector<T> GenerateAllValuesForType() {
} }
template<typename T> template<typename T>
std::vector<T> GenerateRandomIntegers(size_t numValuesToTest) { std::vector<T> GenerateRandomIntegers(size_t num_values_to_test) {
std::vector<T> result; std::vector<T> result;
result.reserve(num_values_to_test);
std::mt19937_64 rng(kRandomSeed); std::mt19937_64 rng(kRandomSeed);
for (size_t i = 0; i < numValuesToTest; ++i) { for (size_t i = 0; i < num_values_to_test; ++i) {
result.push_back(rng()); result.push_back(rng());
} }
return result; return result;

View file

@ -178,4 +178,38 @@
#define ABSL_PREDICT_TRUE(x) (x) #define ABSL_PREDICT_TRUE(x) (x)
#endif #endif
// ABSL_INTERNAL_ASSUME(cond)
// Informs the compiler than a condition is always true and that it can assume
// it to be true for optimization purposes. The call has undefined behavior if
// the condition is false.
// In !NDEBUG mode, the condition is checked with an assert().
// NOTE: The expression must not have side effects, as it will only be evaluated
// in some compilation modes and not others.
//
// Example:
//
// int x = ...;
// ABSL_INTERNAL_ASSUME(x >= 0);
// // The compiler can optimize the division to a simple right shift using the
// // assumption specified above.
// int y = x / 16;
//
#if !defined(NDEBUG)
#define ABSL_INTERNAL_ASSUME(cond) assert(cond)
#elif ABSL_HAVE_BUILTIN(__builtin_assume)
#define ABSL_INTERNAL_ASSUME(cond) __builtin_assume(cond)
#elif defined(__GNUC__) || ABSL_HAVE_BUILTIN(__builtin_unreachable)
#define ABSL_INTERNAL_ASSUME(cond) \
do { \
if (!(cond)) __builtin_unreachable(); \
} while (0)
#elif defined(_MSC_VER)
#define ABSL_INTERNAL_ASSUME(cond) __assume(cond)
#else
#define ABSL_INTERNAL_ASSUME(cond) \
do { \
static_cast<void>(false && (cond)); \
} while (0)
#endif
#endif // ABSL_BASE_OPTIMIZATION_H_ #endif // ABSL_BASE_OPTIMIZATION_H_

View file

@ -104,7 +104,7 @@
#include "absl/base/internal/bits.h" #include "absl/base/internal/bits.h"
#include "absl/base/internal/endian.h" #include "absl/base/internal/endian.h"
#include "absl/base/macros.h" #include "absl/base/optimization.h"
#include "absl/base/port.h" #include "absl/base/port.h"
#include "absl/container/internal/common.h" #include "absl/container/internal/common.h"
#include "absl/container/internal/compressed_tuple.h" #include "absl/container/internal/compressed_tuple.h"
@ -649,24 +649,26 @@ class raw_hash_set {
} }
private: private:
iterator(ctrl_t* ctrl) : ctrl_(ctrl) {} // for end() iterator(ctrl_t* ctrl, slot_type* slot) : ctrl_(ctrl), slot_(slot) {
iterator(ctrl_t* ctrl, slot_type* slot) : ctrl_(ctrl), slot_(slot) {} // This assumption helps the compiler know that any non-end iterator is
// not equal to any end iterator.
ABSL_INTERNAL_ASSUME(ctrl != nullptr);
}
void assert_is_full() const { ABSL_HARDENING_ASSERT(IsFull(*ctrl_)); } void assert_is_full() const {
ABSL_HARDENING_ASSERT(ctrl_ != nullptr && IsFull(*ctrl_));
}
void assert_is_valid() const { void assert_is_valid() const {
ABSL_HARDENING_ASSERT(!ctrl_ || IsFull(*ctrl_) || *ctrl_ == kSentinel); ABSL_HARDENING_ASSERT(ctrl_ == nullptr || IsFull(*ctrl_));
} }
void skip_empty_or_deleted() { void skip_empty_or_deleted() {
while (IsEmptyOrDeleted(*ctrl_)) { while (IsEmptyOrDeleted(*ctrl_)) {
// ctrl is not necessarily aligned to Group::kWidth. It is also likely
// to read past the space for ctrl bytes and into slots. This is ok
// because ctrl has sizeof() == 1 and slot has sizeof() >= 1 so there
// is no way to read outside the combined slot array.
uint32_t shift = Group{ctrl_}.CountLeadingEmptyOrDeleted(); uint32_t shift = Group{ctrl_}.CountLeadingEmptyOrDeleted();
ctrl_ += shift; ctrl_ += shift;
slot_ += shift; slot_ += shift;
} }
if (ABSL_PREDICT_FALSE(*ctrl_ == kSentinel)) ctrl_ = nullptr;
} }
ctrl_t* ctrl_ = nullptr; ctrl_t* ctrl_ = nullptr;
@ -908,12 +910,12 @@ class raw_hash_set {
it.skip_empty_or_deleted(); it.skip_empty_or_deleted();
return it; return it;
} }
iterator end() { return {ctrl_ + capacity_}; } iterator end() { return {}; }
const_iterator begin() const { const_iterator begin() const {
return const_cast<raw_hash_set*>(this)->begin(); return const_cast<raw_hash_set*>(this)->begin();
} }
const_iterator end() const { return const_cast<raw_hash_set*>(this)->end(); } const_iterator end() const { return {}; }
const_iterator cbegin() const { return begin(); } const_iterator cbegin() const { return begin(); }
const_iterator cend() const { return end(); } const_iterator cend() const { return end(); }

View file

@ -326,7 +326,9 @@ cc_test(
":handle", ":handle",
":registry", ":registry",
"//absl/base:core_headers", "//absl/base:core_headers",
"//absl/base:malloc_internal",
"//absl/strings", "//absl/strings",
"//absl/time",
"@com_google_googletest//:gtest_main", "@com_google_googletest//:gtest_main",
], ],
) )

View file

@ -304,6 +304,7 @@ absl_cc_test(
absl::flags_internal absl::flags_internal
absl::flags_registry absl::flags_registry
absl::strings absl::strings
absl::time
gtest_main gtest_main
) )

View file

@ -315,8 +315,8 @@ ABSL_NAMESPACE_END
} }
#define ABSL_FLAG_IMPL_DECLARE_DEF_VAL_WRAPPER(name, Type, default_value) \ #define ABSL_FLAG_IMPL_DECLARE_DEF_VAL_WRAPPER(name, Type, default_value) \
static void* AbslFlagsInitFlag##name() { \ static void AbslFlagsInitFlag##name(void* dst) { \
return absl::flags_internal::MakeFromDefaultValue<Type>(default_value); \ absl::flags_internal::MakeFromDefaultValue<Type>(dst, default_value); \
} }
// ABSL_FLAG_IMPL // ABSL_FLAG_IMPL

View file

@ -19,6 +19,7 @@
#include <cmath> #include <cmath>
#include <string> #include <string>
#include <thread> // NOLINT
#include <vector> #include <vector>
#include "gtest/gtest.h" #include "gtest/gtest.h"
@ -34,6 +35,7 @@
#include "absl/strings/str_cat.h" #include "absl/strings/str_cat.h"
#include "absl/strings/str_split.h" #include "absl/strings/str_split.h"
#include "absl/strings/string_view.h" #include "absl/strings/string_view.h"
#include "absl/time/time.h"
ABSL_DECLARE_FLAG(int64_t, mistyped_int_flag); ABSL_DECLARE_FLAG(int64_t, mistyped_int_flag);
ABSL_DECLARE_FLAG(std::vector<std::string>, mistyped_string_flag); ABSL_DECLARE_FLAG(std::vector<std::string>, mistyped_string_flag);
@ -44,8 +46,8 @@ namespace flags = absl::flags_internal;
std::string TestHelpMsg() { return "dynamic help"; } std::string TestHelpMsg() { return "dynamic help"; }
template <typename T> template <typename T>
void* TestMakeDflt() { void TestMakeDflt(void* dst) {
return new T{}; new (dst) T{};
} }
void TestCallback() {} void TestCallback() {}
@ -74,6 +76,7 @@ class FlagTest : public testing::Test {
#endif #endif
return std::string(fname); return std::string(fname);
} }
flags::FlagSaver flag_saver_;
}; };
struct S1 { struct S1 {
@ -107,15 +110,15 @@ TEST_F(FlagTest, Traits) {
flags::FlagValueStorageKind::kTwoWordsAtomic); flags::FlagValueStorageKind::kTwoWordsAtomic);
#else #else
EXPECT_EQ(flags::StorageKind<S1>(), EXPECT_EQ(flags::StorageKind<S1>(),
flags::FlagValueStorageKind::kHeapAllocated); flags::FlagValueStorageKind::kAlignedBuffer);
EXPECT_EQ(flags::StorageKind<S2>(), EXPECT_EQ(flags::StorageKind<S2>(),
flags::FlagValueStorageKind::kHeapAllocated); flags::FlagValueStorageKind::kAlignedBuffer);
#endif #endif
EXPECT_EQ(flags::StorageKind<std::string>(), EXPECT_EQ(flags::StorageKind<std::string>(),
flags::FlagValueStorageKind::kHeapAllocated); flags::FlagValueStorageKind::kAlignedBuffer);
EXPECT_EQ(flags::StorageKind<std::vector<std::string>>(), EXPECT_EQ(flags::StorageKind<std::vector<std::string>>(),
flags::FlagValueStorageKind::kHeapAllocated); flags::FlagValueStorageKind::kAlignedBuffer);
} }
// -------------------------------------------------------------------- // --------------------------------------------------------------------
@ -190,6 +193,7 @@ ABSL_DECLARE_FLAG(uint64_t, test_flag_08);
ABSL_DECLARE_FLAG(double, test_flag_09); ABSL_DECLARE_FLAG(double, test_flag_09);
ABSL_DECLARE_FLAG(float, test_flag_10); ABSL_DECLARE_FLAG(float, test_flag_10);
ABSL_DECLARE_FLAG(std::string, test_flag_11); ABSL_DECLARE_FLAG(std::string, test_flag_11);
ABSL_DECLARE_FLAG(absl::Duration, test_flag_12);
namespace { namespace {
@ -208,6 +212,7 @@ TEST_F(FlagTest, TestFlagDeclaration) {
EXPECT_EQ(FLAGS_test_flag_09.Name(), "test_flag_09"); EXPECT_EQ(FLAGS_test_flag_09.Name(), "test_flag_09");
EXPECT_EQ(FLAGS_test_flag_10.Name(), "test_flag_10"); EXPECT_EQ(FLAGS_test_flag_10.Name(), "test_flag_10");
EXPECT_EQ(FLAGS_test_flag_11.Name(), "test_flag_11"); EXPECT_EQ(FLAGS_test_flag_11.Name(), "test_flag_11");
EXPECT_EQ(FLAGS_test_flag_12.Name(), "test_flag_12");
} }
#endif // !ABSL_FLAGS_STRIP_NAMES #endif // !ABSL_FLAGS_STRIP_NAMES
@ -226,6 +231,7 @@ ABSL_FLAG(uint64_t, test_flag_08, 9876543, "test flag 08");
ABSL_FLAG(double, test_flag_09, -9.876e-50, "test flag 09"); ABSL_FLAG(double, test_flag_09, -9.876e-50, "test flag 09");
ABSL_FLAG(float, test_flag_10, 1.234e12f, "test flag 10"); ABSL_FLAG(float, test_flag_10, 1.234e12f, "test flag 10");
ABSL_FLAG(std::string, test_flag_11, "", "test flag 11"); ABSL_FLAG(std::string, test_flag_11, "", "test flag 11");
ABSL_FLAG(absl::Duration, test_flag_12, absl::Minutes(10), "test flag 12");
namespace { namespace {
@ -287,6 +293,11 @@ TEST_F(FlagTest, TestFlagDefinition) {
EXPECT_EQ(FLAGS_test_flag_11.Help(), "test flag 11"); EXPECT_EQ(FLAGS_test_flag_11.Help(), "test flag 11");
EXPECT_TRUE(absl::EndsWith(FLAGS_test_flag_11.Filename(), expected_file_name)) EXPECT_TRUE(absl::EndsWith(FLAGS_test_flag_11.Filename(), expected_file_name))
<< FLAGS_test_flag_11.Filename(); << FLAGS_test_flag_11.Filename();
EXPECT_EQ(FLAGS_test_flag_12.Name(), "test_flag_12");
EXPECT_EQ(FLAGS_test_flag_12.Help(), "test flag 12");
EXPECT_TRUE(absl::EndsWith(FLAGS_test_flag_12.Filename(), expected_file_name))
<< FLAGS_test_flag_12.Filename();
} }
#endif // !ABSL_FLAGS_STRIP_NAMES #endif // !ABSL_FLAGS_STRIP_NAMES
@ -304,6 +315,20 @@ TEST_F(FlagTest, TestDefault) {
EXPECT_EQ(FLAGS_test_flag_09.DefaultValue(), "-9.876e-50"); EXPECT_EQ(FLAGS_test_flag_09.DefaultValue(), "-9.876e-50");
EXPECT_EQ(FLAGS_test_flag_10.DefaultValue(), "1.234e+12"); EXPECT_EQ(FLAGS_test_flag_10.DefaultValue(), "1.234e+12");
EXPECT_EQ(FLAGS_test_flag_11.DefaultValue(), ""); EXPECT_EQ(FLAGS_test_flag_11.DefaultValue(), "");
EXPECT_EQ(FLAGS_test_flag_12.DefaultValue(), "10m");
EXPECT_EQ(FLAGS_test_flag_01.CurrentValue(), "true");
EXPECT_EQ(FLAGS_test_flag_02.CurrentValue(), "1234");
EXPECT_EQ(FLAGS_test_flag_03.CurrentValue(), "-34");
EXPECT_EQ(FLAGS_test_flag_04.CurrentValue(), "189");
EXPECT_EQ(FLAGS_test_flag_05.CurrentValue(), "10765");
EXPECT_EQ(FLAGS_test_flag_06.CurrentValue(), "40000");
EXPECT_EQ(FLAGS_test_flag_07.CurrentValue(), "-1234567");
EXPECT_EQ(FLAGS_test_flag_08.CurrentValue(), "9876543");
EXPECT_EQ(FLAGS_test_flag_09.CurrentValue(), "-9.876e-50");
EXPECT_EQ(FLAGS_test_flag_10.CurrentValue(), "1.234e+12");
EXPECT_EQ(FLAGS_test_flag_11.CurrentValue(), "");
EXPECT_EQ(FLAGS_test_flag_12.CurrentValue(), "10m");
EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_01), true); EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_01), true);
EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_02), 1234); EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_02), 1234);
@ -316,6 +341,7 @@ TEST_F(FlagTest, TestDefault) {
EXPECT_NEAR(absl::GetFlag(FLAGS_test_flag_09), -9.876e-50, 1e-55); EXPECT_NEAR(absl::GetFlag(FLAGS_test_flag_09), -9.876e-50, 1e-55);
EXPECT_NEAR(absl::GetFlag(FLAGS_test_flag_10), 1.234e12f, 1e5f); EXPECT_NEAR(absl::GetFlag(FLAGS_test_flag_10), 1.234e12f, 1e5f);
EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_11), ""); EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_11), "");
EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_12), absl::Minutes(10));
} }
// -------------------------------------------------------------------- // --------------------------------------------------------------------
@ -408,6 +434,38 @@ TEST_F(FlagTest, TestGetSet) {
absl::SetFlag(&FLAGS_test_flag_11, "asdf"); absl::SetFlag(&FLAGS_test_flag_11, "asdf");
EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_11), "asdf"); EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_11), "asdf");
absl::SetFlag(&FLAGS_test_flag_12, absl::Seconds(110));
EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_12), absl::Seconds(110));
}
// --------------------------------------------------------------------
TEST_F(FlagTest, TestGetViaReflection) {
auto* handle = flags::FindCommandLineFlag("test_flag_01");
EXPECT_EQ(*handle->Get<bool>(), true);
handle = flags::FindCommandLineFlag("test_flag_02");
EXPECT_EQ(*handle->Get<int>(), 1234);
handle = flags::FindCommandLineFlag("test_flag_03");
EXPECT_EQ(*handle->Get<int16_t>(), -34);
handle = flags::FindCommandLineFlag("test_flag_04");
EXPECT_EQ(*handle->Get<uint16_t>(), 189);
handle = flags::FindCommandLineFlag("test_flag_05");
EXPECT_EQ(*handle->Get<int32_t>(), 10765);
handle = flags::FindCommandLineFlag("test_flag_06");
EXPECT_EQ(*handle->Get<uint32_t>(), 40000);
handle = flags::FindCommandLineFlag("test_flag_07");
EXPECT_EQ(*handle->Get<int64_t>(), -1234567);
handle = flags::FindCommandLineFlag("test_flag_08");
EXPECT_EQ(*handle->Get<uint64_t>(), 9876543);
handle = flags::FindCommandLineFlag("test_flag_09");
EXPECT_NEAR(*handle->Get<double>(), -9.876e-50, 1e-55);
handle = flags::FindCommandLineFlag("test_flag_10");
EXPECT_NEAR(*handle->Get<float>(), 1.234e12f, 1e5f);
handle = flags::FindCommandLineFlag("test_flag_11");
EXPECT_EQ(*handle->Get<std::string>(), "");
handle = flags::FindCommandLineFlag("test_flag_12");
EXPECT_EQ(*handle->Get<absl::Duration>(), absl::Minutes(10));
} }
// -------------------------------------------------------------------- // --------------------------------------------------------------------
@ -416,28 +474,32 @@ int GetDflt1() { return 1; }
} // namespace } // namespace
ABSL_FLAG(int, test_flag_12, GetDflt1(), "test flag 12"); ABSL_FLAG(int, test_int_flag_with_non_const_default, GetDflt1(),
ABSL_FLAG(std::string, test_flag_13, absl::StrCat("AAA", "BBB"), "test int flag non const default");
"test flag 13"); ABSL_FLAG(std::string, test_string_flag_with_non_const_default,
absl::StrCat("AAA", "BBB"), "test string flag non const default");
namespace { namespace {
TEST_F(FlagTest, TestNonConstexprDefault) { TEST_F(FlagTest, TestNonConstexprDefault) {
EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_12), 1); EXPECT_EQ(absl::GetFlag(FLAGS_test_int_flag_with_non_const_default), 1);
EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_13), "AAABBB"); EXPECT_EQ(absl::GetFlag(FLAGS_test_string_flag_with_non_const_default),
"AAABBB");
} }
// -------------------------------------------------------------------- // --------------------------------------------------------------------
} // namespace } // namespace
ABSL_FLAG(bool, test_flag_14, true, absl::StrCat("test ", "flag ", "14")); ABSL_FLAG(bool, test_flag_with_non_const_help, true,
absl::StrCat("test ", "flag ", "non const help"));
namespace { namespace {
#if !ABSL_FLAGS_STRIP_HELP #if !ABSL_FLAGS_STRIP_HELP
TEST_F(FlagTest, TestNonConstexprHelp) { TEST_F(FlagTest, TestNonConstexprHelp) {
EXPECT_EQ(FLAGS_test_flag_14.Help(), "test flag 14"); EXPECT_EQ(FLAGS_test_flag_with_non_const_help.Help(),
"test flag non const help");
} }
#endif //! ABSL_FLAGS_STRIP_HELP #endif //! ABSL_FLAGS_STRIP_HELP
@ -503,14 +565,14 @@ std::string AbslUnparseFlag(const CustomUDT& f) {
} // namespace } // namespace
ABSL_FLAG(CustomUDT, test_flag_15, CustomUDT(), "test flag 15"); ABSL_FLAG(CustomUDT, test_flag_custom_udt, CustomUDT(), "test flag custom UDT");
namespace { namespace {
TEST_F(FlagTest, TestCustomUDT) { TEST_F(FlagTest, TestCustomUDT) {
EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_15), CustomUDT(1, 1)); EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_custom_udt), CustomUDT(1, 1));
absl::SetFlag(&FLAGS_test_flag_15, CustomUDT(2, 3)); absl::SetFlag(&FLAGS_test_flag_custom_udt, CustomUDT(2, 3));
EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_15), CustomUDT(2, 3)); EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_custom_udt), CustomUDT(2, 3));
} }
// MSVC produces link error on the type mismatch. // MSVC produces link error on the type mismatch.
@ -570,16 +632,17 @@ std::string AbslUnparseFlag(const ConversionTestVal& val) {
// Flag default values can be specified with a value that converts to the flag // Flag default values can be specified with a value that converts to the flag
// value type implicitly. // value type implicitly.
ABSL_FLAG(ConversionTestVal, test_flag_16, ABSL_FLAG(ConversionTestVal, test_flag_implicit_conv,
ConversionTestVal::ViaImplicitConv::kTen, "test flag 16"); ConversionTestVal::ViaImplicitConv::kTen,
"test flag init via implicit conversion");
namespace { namespace {
TEST_F(FlagTest, CanSetViaImplicitConversion) { TEST_F(FlagTest, CanSetViaImplicitConversion) {
EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_16).a, 10); EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_implicit_conv).a, 10);
absl::SetFlag(&FLAGS_test_flag_16, absl::SetFlag(&FLAGS_test_flag_implicit_conv,
ConversionTestVal::ViaImplicitConv::kEleven); ConversionTestVal::ViaImplicitConv::kEleven);
EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_16).a, 11); EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_implicit_conv).a, 11);
} }
// -------------------------------------------------------------------- // --------------------------------------------------------------------
@ -646,3 +709,69 @@ TEST_F(FlagTest, TestRetiredFlagRegistration) {
} }
} // namespace } // namespace
// --------------------------------------------------------------------
namespace {
// User-defined type with small alignment, but size exceeding 16.
struct SmallAlignUDT {
SmallAlignUDT() : c('A'), s(12) {}
char c;
int16_t s;
char bytes[14];
};
bool AbslParseFlag(absl::string_view, SmallAlignUDT*, std::string*) {
return true;
}
std::string AbslUnparseFlag(const SmallAlignUDT&) { return ""; }
// User-defined type with small size, but not trivially copyable.
struct NonTriviallyCopyableUDT {
NonTriviallyCopyableUDT() : c('A') {}
NonTriviallyCopyableUDT(const NonTriviallyCopyableUDT& rhs) : c(rhs.c) {}
NonTriviallyCopyableUDT& operator=(const NonTriviallyCopyableUDT& rhs) {
c = rhs.c;
return *this;
}
char c;
};
bool AbslParseFlag(absl::string_view, NonTriviallyCopyableUDT*, std::string*) {
return true;
}
std::string AbslUnparseFlag(const NonTriviallyCopyableUDT&) { return ""; }
} // namespace
ABSL_FLAG(SmallAlignUDT, test_flag_sa_udt, {}, "help");
ABSL_FLAG(NonTriviallyCopyableUDT, test_flag_ntc_udt, {}, "help");
namespace {
TEST_F(FlagTest, TestSmallAlignUDT) {
SmallAlignUDT value = absl::GetFlag(FLAGS_test_flag_sa_udt);
EXPECT_EQ(value.c, 'A');
EXPECT_EQ(value.s, 12);
value.c = 'B';
value.s = 45;
absl::SetFlag(&FLAGS_test_flag_sa_udt, value);
value = absl::GetFlag(FLAGS_test_flag_sa_udt);
EXPECT_EQ(value.c, 'B');
EXPECT_EQ(value.s, 45);
}
TEST_F(FlagTest, TestNonTriviallyCopyableUDT) {
NonTriviallyCopyableUDT value = absl::GetFlag(FLAGS_test_flag_ntc_udt);
EXPECT_EQ(value.c, 'A');
value.c = 'B';
absl::SetFlag(&FLAGS_test_flag_ntc_udt, value);
value = absl::GetFlag(FLAGS_test_flag_ntc_udt);
EXPECT_EQ(value.c, 'B');
}
} // namespace

View file

@ -92,9 +92,9 @@ class FlagState : public flags_internal::FlagStateInterface {
counter_(counter) {} counter_(counter) {}
~FlagState() override { ~FlagState() override {
if (flag_impl_->ValueStorageKind() != FlagValueStorageKind::kHeapAllocated) if (flag_impl_->ValueStorageKind() != FlagValueStorageKind::kAlignedBuffer)
return; return;
flags_internal::Delete(flag_impl_->op_, value_.dynamic); flags_internal::Delete(flag_impl_->op_, value_.heap_allocated);
} }
private: private:
@ -112,11 +112,11 @@ class FlagState : public flags_internal::FlagStateInterface {
// Flag and saved flag data. // Flag and saved flag data.
FlagImpl* flag_impl_; FlagImpl* flag_impl_;
union SavedValue { union SavedValue {
explicit SavedValue(void* v) : dynamic(v) {} explicit SavedValue(void* v) : heap_allocated(v) {}
explicit SavedValue(int64_t v) : one_word(v) {} explicit SavedValue(int64_t v) : one_word(v) {}
explicit SavedValue(flags_internal::AlignedTwoWords v) : two_words(v) {} explicit SavedValue(flags_internal::AlignedTwoWords v) : two_words(v) {}
void* dynamic; void* heap_allocated;
int64_t one_word; int64_t one_word;
flags_internal::AlignedTwoWords two_words; flags_internal::AlignedTwoWords two_words;
} value_; } value_;
@ -128,25 +128,33 @@ class FlagState : public flags_internal::FlagStateInterface {
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// Flag implementation, which does not depend on flag value type. // Flag implementation, which does not depend on flag value type.
DynValueDeleter::DynValueDeleter(FlagOpFn op_arg) : op(op_arg) {}
void DynValueDeleter::operator()(void* ptr) const {
if (op == nullptr) return;
Delete(op, ptr);
}
void FlagImpl::Init() { void FlagImpl::Init() {
new (&data_guard_) absl::Mutex; new (&data_guard_) absl::Mutex;
// At this point the default_value_ always points to gen_func. // At this point the default_value_ always points to gen_func.
std::unique_ptr<void, DynValueDeleter> init_value(
(*default_value_.gen_func)(), DynValueDeleter{op_});
switch (ValueStorageKind()) { switch (ValueStorageKind()) {
case FlagValueStorageKind::kHeapAllocated: case FlagValueStorageKind::kAlignedBuffer:
HeapAllocatedValue() = init_value.release(); (*default_value_.gen_func)(AlignedBufferValue());
break; break;
case FlagValueStorageKind::kOneWordAtomic: { case FlagValueStorageKind::kOneWordAtomic: {
int64_t atomic_value; alignas(int64_t) std::array<char, sizeof(int64_t)> buf{};
std::memcpy(&atomic_value, init_value.get(), Sizeof(op_)); (*default_value_.gen_func)(buf.data());
OneWordValue().store(atomic_value, std::memory_order_release); auto value = absl::bit_cast<int64_t>(buf);
OneWordValue().store(value, std::memory_order_release);
break; break;
} }
case FlagValueStorageKind::kTwoWordsAtomic: { case FlagValueStorageKind::kTwoWordsAtomic: {
AlignedTwoWords atomic_value{0, 0}; alignas(AlignedTwoWords) std::array<char, sizeof(AlignedTwoWords)> buf{};
std::memcpy(&atomic_value, init_value.get(), Sizeof(op_)); (*default_value_.gen_func)(buf.data());
auto atomic_value = absl::bit_cast<AlignedTwoWords>(buf);
TwoWordsValue().store(atomic_value, std::memory_order_release); TwoWordsValue().store(atomic_value, std::memory_order_release);
break; break;
} }
@ -191,15 +199,16 @@ std::unique_ptr<void, DynValueDeleter> FlagImpl::MakeInitValue() const {
if (DefaultKind() == FlagDefaultKind::kDynamicValue) { if (DefaultKind() == FlagDefaultKind::kDynamicValue) {
res = flags_internal::Clone(op_, default_value_.dynamic_value); res = flags_internal::Clone(op_, default_value_.dynamic_value);
} else { } else {
res = (*default_value_.gen_func)(); res = flags_internal::Alloc(op_);
(*default_value_.gen_func)(res);
} }
return {res, DynValueDeleter{op_}}; return {res, DynValueDeleter{op_}};
} }
void FlagImpl::StoreValue(const void* src) { void FlagImpl::StoreValue(const void* src) {
switch (ValueStorageKind()) { switch (ValueStorageKind()) {
case FlagValueStorageKind::kHeapAllocated: case FlagValueStorageKind::kAlignedBuffer:
Copy(op_, src, HeapAllocatedValue()); Copy(op_, src, AlignedBufferValue());
break; break;
case FlagValueStorageKind::kOneWordAtomic: { case FlagValueStorageKind::kOneWordAtomic: {
int64_t one_word_val = 0; int64_t one_word_val = 0;
@ -257,9 +266,9 @@ std::string FlagImpl::DefaultValue() const {
std::string FlagImpl::CurrentValue() const { std::string FlagImpl::CurrentValue() const {
auto* guard = DataGuard(); // Make sure flag initialized auto* guard = DataGuard(); // Make sure flag initialized
switch (ValueStorageKind()) { switch (ValueStorageKind()) {
case FlagValueStorageKind::kHeapAllocated: { case FlagValueStorageKind::kAlignedBuffer: {
absl::MutexLock l(guard); absl::MutexLock l(guard);
return flags_internal::Unparse(op_, HeapAllocatedValue()); return flags_internal::Unparse(op_, AlignedBufferValue());
} }
case FlagValueStorageKind::kOneWordAtomic: { case FlagValueStorageKind::kOneWordAtomic: {
const auto one_word_val = const auto one_word_val =
@ -318,9 +327,9 @@ std::unique_ptr<FlagStateInterface> FlagImpl::SaveState() {
bool modified = modified_; bool modified = modified_;
bool on_command_line = on_command_line_; bool on_command_line = on_command_line_;
switch (ValueStorageKind()) { switch (ValueStorageKind()) {
case FlagValueStorageKind::kHeapAllocated: { case FlagValueStorageKind::kAlignedBuffer: {
return absl::make_unique<FlagState>( return absl::make_unique<FlagState>(
this, flags_internal::Clone(op_, HeapAllocatedValue()), modified, this, flags_internal::Clone(op_, AlignedBufferValue()), modified,
on_command_line, counter_); on_command_line, counter_);
} }
case FlagValueStorageKind::kOneWordAtomic: { case FlagValueStorageKind::kOneWordAtomic: {
@ -345,8 +354,8 @@ bool FlagImpl::RestoreState(const FlagState& flag_state) {
} }
switch (ValueStorageKind()) { switch (ValueStorageKind()) {
case FlagValueStorageKind::kHeapAllocated: case FlagValueStorageKind::kAlignedBuffer:
StoreValue(flag_state.value_.dynamic); StoreValue(flag_state.value_.heap_allocated);
break; break;
case FlagValueStorageKind::kOneWordAtomic: case FlagValueStorageKind::kOneWordAtomic:
StoreValue(&flag_state.value_.one_word); StoreValue(&flag_state.value_.one_word);
@ -363,25 +372,27 @@ bool FlagImpl::RestoreState(const FlagState& flag_state) {
} }
template <typename StorageT> template <typename StorageT>
typename StorageT::value_type& FlagImpl::OffsetValue() const { StorageT* FlagImpl::OffsetValue() const {
char* p = reinterpret_cast<char*>(const_cast<FlagImpl*>(this)); char* p = reinterpret_cast<char*>(const_cast<FlagImpl*>(this));
// The offset is deduced via Flag value type specific op_. // The offset is deduced via Flag value type specific op_.
size_t offset = flags_internal::ValueOffset(op_); size_t offset = flags_internal::ValueOffset(op_);
return reinterpret_cast<StorageT*>(p + offset)->value; return reinterpret_cast<StorageT*>(p + offset);
} }
void*& FlagImpl::HeapAllocatedValue() const { void* FlagImpl::AlignedBufferValue() const {
assert(ValueStorageKind() == FlagValueStorageKind::kHeapAllocated); assert(ValueStorageKind() == FlagValueStorageKind::kAlignedBuffer);
return OffsetValue<FlagHeapAllocatedValue>(); return OffsetValue<void>();
} }
std::atomic<int64_t>& FlagImpl::OneWordValue() const { std::atomic<int64_t>& FlagImpl::OneWordValue() const {
assert(ValueStorageKind() == FlagValueStorageKind::kOneWordAtomic); assert(ValueStorageKind() == FlagValueStorageKind::kOneWordAtomic);
return OffsetValue<FlagOneWordValue>(); return OffsetValue<FlagOneWordValue>()->value;
} }
std::atomic<AlignedTwoWords>& FlagImpl::TwoWordsValue() const { std::atomic<AlignedTwoWords>& FlagImpl::TwoWordsValue() const {
assert(ValueStorageKind() == FlagValueStorageKind::kTwoWordsAtomic); assert(ValueStorageKind() == FlagValueStorageKind::kTwoWordsAtomic);
return OffsetValue<FlagTwoWordsValue>(); return OffsetValue<FlagTwoWordsValue>()->value;
} }
// Attempts to parse supplied `value` string using parsing routine in the `flag` // Attempts to parse supplied `value` string using parsing routine in the `flag`
@ -406,9 +417,9 @@ std::unique_ptr<void, DynValueDeleter> FlagImpl::TryParse(
void FlagImpl::Read(void* dst) const { void FlagImpl::Read(void* dst) const {
auto* guard = DataGuard(); // Make sure flag initialized auto* guard = DataGuard(); // Make sure flag initialized
switch (ValueStorageKind()) { switch (ValueStorageKind()) {
case FlagValueStorageKind::kHeapAllocated: { case FlagValueStorageKind::kAlignedBuffer: {
absl::MutexLock l(guard); absl::MutexLock l(guard);
flags_internal::CopyConstruct(op_, HeapAllocatedValue(), dst); flags_internal::CopyConstruct(op_, AlignedBufferValue(), dst);
break; break;
} }
case FlagValueStorageKind::kOneWordAtomic: { case FlagValueStorageKind::kOneWordAtomic: {

View file

@ -46,8 +46,8 @@ namespace flags_internal {
// by function specific to that type with a signature matching FlagOpFn. // by function specific to that type with a signature matching FlagOpFn.
enum class FlagOp { enum class FlagOp {
kAlloc,
kDelete, kDelete,
kClone,
kCopy, kCopy,
kCopyConstruct, kCopyConstruct,
kSizeof, kSizeof,
@ -63,13 +63,13 @@ using FlagOpFn = void* (*)(FlagOp, const void*, void*, void*);
template <typename T> template <typename T>
void* FlagOps(FlagOp op, const void* v1, void* v2, void* v3); void* FlagOps(FlagOp op, const void* v1, void* v2, void* v3);
// Deletes memory interpreting obj as flag value type pointer. // Allocate aligned memory for a flag value.
inline void Delete(FlagOpFn op, const void* obj) { inline void* Alloc(FlagOpFn op) {
op(FlagOp::kDelete, obj, nullptr, nullptr); return op(FlagOp::kAlloc, nullptr, nullptr, nullptr);
} }
// Makes a copy of flag value pointed by obj. // Deletes memory interpreting obj as flag value type pointer.
inline void* Clone(FlagOpFn op, const void* obj) { inline void Delete(FlagOpFn op, void* obj) {
return op(FlagOp::kClone, obj, nullptr, nullptr); op(FlagOp::kDelete, nullptr, obj, nullptr);
} }
// Copies src to dst interpreting as flag value type pointers. // Copies src to dst interpreting as flag value type pointers.
inline void Copy(FlagOpFn op, const void* src, void* dst) { inline void Copy(FlagOpFn op, const void* src, void* dst) {
@ -80,6 +80,12 @@ inline void Copy(FlagOpFn op, const void* src, void* dst) {
inline void CopyConstruct(FlagOpFn op, const void* src, void* dst) { inline void CopyConstruct(FlagOpFn op, const void* src, void* dst) {
op(FlagOp::kCopyConstruct, src, dst, nullptr); op(FlagOp::kCopyConstruct, src, dst, nullptr);
} }
// Makes a copy of flag value pointed by obj.
inline void* Clone(FlagOpFn op, const void* obj) {
void* res = flags_internal::Alloc(op);
flags_internal::CopyConstruct(op, obj, res);
return res;
}
// Returns true if parsing of input text is successfull. // Returns true if parsing of input text is successfull.
inline bool Parse(FlagOpFn op, absl::string_view text, void* dst, inline bool Parse(FlagOpFn op, absl::string_view text, void* dst,
std::string* error) { std::string* error) {
@ -195,7 +201,7 @@ constexpr FlagHelpArg HelpArg(char) {
// Signature for the function generating the initial flag value (usually // Signature for the function generating the initial flag value (usually
// based on default value supplied in flag's definition) // based on default value supplied in flag's definition)
using FlagDfltGenFunc = void* (*)(); using FlagDfltGenFunc = void (*)(void*);
union FlagDefaultSrc { union FlagDefaultSrc {
constexpr explicit FlagDefaultSrc(FlagDfltGenFunc gen_func_arg) constexpr explicit FlagDefaultSrc(FlagDfltGenFunc gen_func_arg)
@ -253,46 +259,36 @@ using FlagUseTwoWordsStorage =
#endif #endif
template <typename T> template <typename T>
using FlagUseHeapStorage = using FlagUseBufferStorage =
std::integral_constant<bool, !FlagUseOneWordStorage<T>::value && std::integral_constant<bool, !FlagUseOneWordStorage<T>::value &&
!FlagUseTwoWordsStorage<T>::value>; !FlagUseTwoWordsStorage<T>::value>;
enum class FlagValueStorageKind : uint8_t { enum class FlagValueStorageKind : uint8_t {
kHeapAllocated = 0, kAlignedBuffer = 0,
kOneWordAtomic = 1, kOneWordAtomic = 1,
kTwoWordsAtomic = 2 kTwoWordsAtomic = 2
}; };
template <typename T> template <typename T>
static constexpr FlagValueStorageKind StorageKind() { static constexpr FlagValueStorageKind StorageKind() {
return FlagUseHeapStorage<T>::value return FlagUseBufferStorage<T>::value
? FlagValueStorageKind::kHeapAllocated ? FlagValueStorageKind::kAlignedBuffer
: FlagUseOneWordStorage<T>::value : FlagUseOneWordStorage<T>::value
? FlagValueStorageKind::kOneWordAtomic ? FlagValueStorageKind::kOneWordAtomic
: FlagUseTwoWordsStorage<T>::value : FlagValueStorageKind::kTwoWordsAtomic;
? FlagValueStorageKind::kTwoWordsAtomic
: FlagValueStorageKind::kHeapAllocated;
} }
struct FlagHeapAllocatedValue {
using value_type = void*;
value_type value;
};
struct FlagOneWordValue { struct FlagOneWordValue {
using value_type = std::atomic<int64_t>;
constexpr FlagOneWordValue() : value(UninitializedFlagValue()) {} constexpr FlagOneWordValue() : value(UninitializedFlagValue()) {}
value_type value; std::atomic<int64_t> value;
}; };
struct FlagTwoWordsValue { struct FlagTwoWordsValue {
using value_type = std::atomic<AlignedTwoWords>;
constexpr FlagTwoWordsValue() constexpr FlagTwoWordsValue()
: value(AlignedTwoWords{UninitializedFlagValue(), 0}) {} : value(AlignedTwoWords{UninitializedFlagValue(), 0}) {}
value_type value; std::atomic<AlignedTwoWords> value;
}; };
template <typename T, template <typename T,
@ -300,9 +296,10 @@ template <typename T,
struct FlagValue; struct FlagValue;
template <typename T> template <typename T>
struct FlagValue<T, FlagValueStorageKind::kHeapAllocated> struct FlagValue<T, FlagValueStorageKind::kAlignedBuffer> {
: FlagHeapAllocatedValue {
bool Get(T*) const { return false; } bool Get(T*) const { return false; }
alignas(T) char value[sizeof(T)];
}; };
template <typename T> template <typename T>
@ -347,10 +344,8 @@ struct FlagCallback {
// The class encapsulates the Flag's data and access to it. // The class encapsulates the Flag's data and access to it.
struct DynValueDeleter { struct DynValueDeleter {
explicit DynValueDeleter(FlagOpFn op_arg = nullptr) : op(op_arg) {} explicit DynValueDeleter(FlagOpFn op_arg = nullptr);
void operator()(void* ptr) const { void operator()(void* ptr) const;
if (op != nullptr) flags_internal::Delete(op, ptr);
}
FlagOpFn op; FlagOpFn op;
}; };
@ -416,10 +411,10 @@ class FlagImpl final : public flags_internal::CommandLineFlag {
// it is only used inside the three routines below, which are defined in // it is only used inside the three routines below, which are defined in
// flag.cc, we can define it in that file as well. // flag.cc, we can define it in that file as well.
template <typename StorageT> template <typename StorageT>
typename StorageT::value_type& OffsetValue() const; StorageT* OffsetValue() const;
// This is an accessor for a value stored in heap allocated storage. // This is an accessor for a value stored in an aligned buffer storage.
// Returns a mutable reference to a pointer to allow vlaue mutation. // Returns a mutable pointer to the start of a buffer.
void*& HeapAllocatedValue() const; void* AlignedBufferValue() const;
// This is an accessor for a value stored as one word atomic. Returns a // This is an accessor for a value stored as one word atomic. Returns a
// mutable reference to an atomic value. // mutable reference to an atomic value.
std::atomic<int64_t>& OneWordValue() const; std::atomic<int64_t>& OneWordValue() const;
@ -492,17 +487,8 @@ class FlagImpl final : public flags_internal::CommandLineFlag {
// Kind of storage this flag is using for the flag's value. // Kind of storage this flag is using for the flag's value.
const uint8_t value_storage_kind_ : 2; const uint8_t value_storage_kind_ : 2;
// ------------------------------------------------------------------------ uint8_t : 0; // The bytes containing the const bitfields must not be
// The bytes containing the const bitfields must not be shared with bytes // shared with bytes containing the mutable bitfields.
// containing the mutable bitfields.
// ------------------------------------------------------------------------
// Unique tag for absl::call_once call to initialize this flag.
//
// The placement of this variable between the immutable and mutable bitfields
// is important as prevents them from occupying the same byte. If you remove
// this variable, make sure to maintain this property.
absl::once_flag init_control_;
// Mutable flag's state (guarded by `data_guard_`). // Mutable flag's state (guarded by `data_guard_`).
@ -514,6 +500,9 @@ class FlagImpl final : public flags_internal::CommandLineFlag {
// Has this flag been specified on command line. // Has this flag been specified on command line.
bool on_command_line_ : 1 ABSL_GUARDED_BY(*DataGuard()); bool on_command_line_ : 1 ABSL_GUARDED_BY(*DataGuard());
// Unique tag for absl::call_once call to initialize this flag.
absl::once_flag init_control_;
// Mutation counter // Mutation counter
int64_t counter_ ABSL_GUARDED_BY(*DataGuard()); int64_t counter_ ABSL_GUARDED_BY(*DataGuard());
// Optional flag's callback and absl::Mutex to guard the invocations. // Optional flag's callback and absl::Mutex to guard the invocations.
@ -600,11 +589,17 @@ class Flag {
template <typename T> template <typename T>
void* FlagOps(FlagOp op, const void* v1, void* v2, void* v3) { void* FlagOps(FlagOp op, const void* v1, void* v2, void* v3) {
switch (op) { switch (op) {
case FlagOp::kDelete: case FlagOp::kAlloc: {
delete static_cast<const T*>(v1); std::allocator<T> alloc;
return std::allocator_traits<std::allocator<T>>::allocate(alloc, 1);
}
case FlagOp::kDelete: {
T* p = static_cast<T*>(v2);
p->~T();
std::allocator<T> alloc;
std::allocator_traits<std::allocator<T>>::deallocate(alloc, p, 1);
return nullptr; return nullptr;
case FlagOp::kClone: }
return new T(*static_cast<const T*>(v1));
case FlagOp::kCopy: case FlagOp::kCopy:
*static_cast<T*>(v2) = *static_cast<const T*>(v1); *static_cast<T*>(v2) = *static_cast<const T*>(v1);
return nullptr; return nullptr;
@ -675,13 +670,13 @@ class FlagRegistrar {
struct EmptyBraces {}; struct EmptyBraces {};
template <typename T> template <typename T>
T* MakeFromDefaultValue(T t) { void MakeFromDefaultValue(void* dst, T t) {
return new T(std::move(t)); new (dst) T(std::move(t));
} }
template <typename T> template <typename T>
T* MakeFromDefaultValue(EmptyBraces) { void MakeFromDefaultValue(void* dst, EmptyBraces) {
return new T{}; new (dst) T{};
} }
} // namespace flags_internal } // namespace flags_internal

View file

@ -192,8 +192,8 @@ struct stream_u128_helper<absl::uint128> {
template <typename OStream> template <typename OStream>
inline void write(absl::uint128 val, OStream& out) { inline void write(absl::uint128 val, OStream& out) {
uint64_t h = Uint128High64(val); uint64_t h = absl::Uint128High64(val);
uint64_t l = Uint128Low64(val); uint64_t l = absl::Uint128Low64(val);
out << h << out.fill() << l; out << h << out.fill() << l;
} }
}; };

View file

@ -53,7 +53,7 @@ void RunAll(const int argc, char* argv[]) {
// Avoid migrating between cores - important on multi-socket systems. // Avoid migrating between cores - important on multi-socket systems.
int cpu = -1; int cpu = -1;
if (argc == 2) { if (argc == 2) {
if (!SimpleAtoi(argv[1], &cpu)) { if (!absl::SimpleAtoi(argv[1], &cpu)) {
ABSL_RAW_LOG(FATAL, "The optional argument must be a CPU number >= 0.\n"); ABSL_RAW_LOG(FATAL, "The optional argument must be a CPU number >= 0.\n");
} }
} }

View file

@ -38,9 +38,9 @@ namespace random_internal {
// MultiplyU64ToU128 multiplies two 64-bit values to a 128-bit value. // MultiplyU64ToU128 multiplies two 64-bit values to a 128-bit value.
// If an intrinsic is available, it is used, otherwise use native 32-bit // If an intrinsic is available, it is used, otherwise use native 32-bit
// multiplies to construct the result. // multiplies to construct the result.
inline uint128 MultiplyU64ToU128(uint64_t a, uint64_t b) { inline absl::uint128 MultiplyU64ToU128(uint64_t a, uint64_t b) {
#if defined(ABSL_HAVE_INTRINSIC_INT128) #if defined(ABSL_HAVE_INTRINSIC_INT128)
return uint128(static_cast<__uint128_t>(a) * b); return absl::uint128(static_cast<__uint128_t>(a) * b);
#elif defined(ABSL_INTERNAL_USE_UMUL128) #elif defined(ABSL_INTERNAL_USE_UMUL128)
// uint64_t * uint64_t => uint128 multiply using imul intrinsic on MSVC. // uint64_t * uint64_t => uint128 multiply using imul intrinsic on MSVC.
uint64_t high = 0; uint64_t high = 0;
@ -93,14 +93,14 @@ struct wide_multiply {
template <> template <>
struct wide_multiply<uint64_t> { struct wide_multiply<uint64_t> {
using input_type = uint64_t; using input_type = uint64_t;
using result_type = uint128; using result_type = absl::uint128;
static result_type multiply(uint64_t a, uint64_t b) { static result_type multiply(uint64_t a, uint64_t b) {
return MultiplyU64ToU128(a, b); return MultiplyU64ToU128(a, b);
} }
static uint64_t hi(result_type r) { return Uint128High64(r); } static uint64_t hi(result_type r) { return absl::Uint128High64(r); }
static uint64_t lo(result_type r) { return Uint128Low64(r); } static uint64_t lo(result_type r) { return absl::Uint128Low64(r); }
}; };
#endif #endif

View file

@ -732,9 +732,9 @@ void AppendNumberUnit(std::string* out, int64_t n, DisplayUnit unit) {
// Note: unit.prec is limited to double's digits10 value (typically 15) so it // Note: unit.prec is limited to double's digits10 value (typically 15) so it
// always fits in buf[]. // always fits in buf[].
void AppendNumberUnit(std::string* out, double n, DisplayUnit unit) { void AppendNumberUnit(std::string* out, double n, DisplayUnit unit) {
const int buf_size = std::numeric_limits<double>::digits10; constexpr int kBufferSize = std::numeric_limits<double>::digits10;
const int prec = std::min(buf_size, unit.prec); const int prec = std::min(kBufferSize, unit.prec);
char buf[buf_size]; // also large enough to hold integer part char buf[kBufferSize]; // also large enough to hold integer part
char* ep = buf + sizeof(buf); char* ep = buf + sizeof(buf);
double d = 0; double d = 0;
int64_t frac_part = Round(std::modf(n, &d) * unit.pow10); int64_t frac_part = Round(std::modf(n, &d) * unit.pow10);

View file

@ -16,7 +16,7 @@
set -euox pipefail set -euox pipefail
if [ -z ${ABSEIL_ROOT:-} ]; then if [[ -z ${ABSEIL_ROOT:-} ]]; then
ABSEIL_ROOT="$(realpath $(dirname ${0})/..)" ABSEIL_ROOT="$(realpath $(dirname ${0})/..)"
fi fi

View file

@ -20,19 +20,19 @@
set -euox pipefail set -euox pipefail
if [ -z ${ABSEIL_ROOT:-} ]; then if [[ -z ${ABSEIL_ROOT:-} ]]; then
ABSEIL_ROOT="$(realpath $(dirname ${0})/..)" ABSEIL_ROOT="$(realpath $(dirname ${0})/..)"
fi fi
if [ -z ${STD:-} ]; then if [[ -z ${STD:-} ]]; then
STD="c++11 c++14 c++17" STD="c++11 c++14 c++17"
fi fi
if [ -z ${COMPILATION_MODE:-} ]; then if [[ -z ${COMPILATION_MODE:-} ]]; then
COMPILATION_MODE="fastbuild opt" COMPILATION_MODE="fastbuild opt"
fi fi
if [ -z ${EXCEPTIONS_MODE:-} ]; then if [[ -z ${EXCEPTIONS_MODE:-} ]]; then
EXCEPTIONS_MODE="-fno-exceptions -fexceptions" EXCEPTIONS_MODE="-fno-exceptions -fexceptions"
fi fi
@ -41,7 +41,7 @@ readonly DOCKER_CONTAINER=${LINUX_CLANG_LATEST_CONTAINER}
# USE_BAZEL_CACHE=1 only works on Kokoro. # USE_BAZEL_CACHE=1 only works on Kokoro.
# Without access to the credentials this won't work. # Without access to the credentials this won't work.
if [ ${USE_BAZEL_CACHE:-0} -ne 0 ]; then if [[ ${USE_BAZEL_CACHE:-0} -ne 0 ]]; then
DOCKER_EXTRA_ARGS="--volume=${KOKORO_KEYSTORE_DIR}:/keystore:ro ${DOCKER_EXTRA_ARGS:-}" DOCKER_EXTRA_ARGS="--volume=${KOKORO_KEYSTORE_DIR}:/keystore:ro ${DOCKER_EXTRA_ARGS:-}"
# Bazel doesn't track changes to tools outside of the workspace # Bazel doesn't track changes to tools outside of the workspace
# (e.g. /usr/bin/gcc), so by appending the docker container to the # (e.g. /usr/bin/gcc), so by appending the docker container to the
@ -54,7 +54,7 @@ fi
# Avoid depending on external sites like GitHub by checking --distdir for # Avoid depending on external sites like GitHub by checking --distdir for
# external dependencies first. # external dependencies first.
# https://docs.bazel.build/versions/master/guide.html#distdir # https://docs.bazel.build/versions/master/guide.html#distdir
if [ -z ${KOKORO_GFILE_DIR:-} && -d "${KOKORO_GFILE_DIR}/distdir" ]; then if [[ ${KOKORO_GFILE_DIR:-} ]] && [[ -d "${KOKORO_GFILE_DIR}/distdir" ]]; then
DOCKER_EXTRA_ARGS="--volume=${KOKORO_GFILE_DIR}/distdir:/distdir:ro ${DOCKER_EXTRA_ARGS:-}" DOCKER_EXTRA_ARGS="--volume=${KOKORO_GFILE_DIR}/distdir:/distdir:ro ${DOCKER_EXTRA_ARGS:-}"
BAZEL_EXTRA_ARGS="--distdir=/distdir ${BAZEL_EXTRA_ARGS:-}" BAZEL_EXTRA_ARGS="--distdir=/distdir ${BAZEL_EXTRA_ARGS:-}"
fi fi

View file

@ -20,19 +20,19 @@
set -euox pipefail set -euox pipefail
if [ -z ${ABSEIL_ROOT:-} ]; then if [[ -z ${ABSEIL_ROOT:-} ]]; then
ABSEIL_ROOT="$(realpath $(dirname ${0})/..)" ABSEIL_ROOT="$(realpath $(dirname ${0})/..)"
fi fi
if [ -z ${STD:-} ]; then if [[ -z ${STD:-} ]]; then
STD="c++11 c++14 c++17" STD="c++11 c++14 c++17"
fi fi
if [ -z ${COMPILATION_MODE:-} ]; then if [[ -z ${COMPILATION_MODE:-} ]]; then
COMPILATION_MODE="fastbuild opt" COMPILATION_MODE="fastbuild opt"
fi fi
if [ -z ${EXCEPTIONS_MODE:-} ]; then if [[ -z ${EXCEPTIONS_MODE:-} ]]; then
EXCEPTIONS_MODE="-fno-exceptions -fexceptions" EXCEPTIONS_MODE="-fno-exceptions -fexceptions"
fi fi
@ -41,7 +41,7 @@ readonly DOCKER_CONTAINER=${LINUX_CLANG_LATEST_CONTAINER}
# USE_BAZEL_CACHE=1 only works on Kokoro. # USE_BAZEL_CACHE=1 only works on Kokoro.
# Without access to the credentials this won't work. # Without access to the credentials this won't work.
if [ ${USE_BAZEL_CACHE:-0} -ne 0 ]; then if [[ ${USE_BAZEL_CACHE:-0} -ne 0 ]]; then
DOCKER_EXTRA_ARGS="--volume=${KOKORO_KEYSTORE_DIR}:/keystore:ro ${DOCKER_EXTRA_ARGS:-}" DOCKER_EXTRA_ARGS="--volume=${KOKORO_KEYSTORE_DIR}:/keystore:ro ${DOCKER_EXTRA_ARGS:-}"
# Bazel doesn't track changes to tools outside of the workspace # Bazel doesn't track changes to tools outside of the workspace
# (e.g. /usr/bin/gcc), so by appending the docker container to the # (e.g. /usr/bin/gcc), so by appending the docker container to the
@ -54,7 +54,7 @@ fi
# Avoid depending on external sites like GitHub by checking --distdir for # Avoid depending on external sites like GitHub by checking --distdir for
# external dependencies first. # external dependencies first.
# https://docs.bazel.build/versions/master/guide.html#distdir # https://docs.bazel.build/versions/master/guide.html#distdir
if [ -z ${KOKORO_GFILE_DIR:-} && -d "${KOKORO_GFILE_DIR}/distdir" ]; then if [[ ${KOKORO_GFILE_DIR:-} ]] && [[ -d "${KOKORO_GFILE_DIR}/distdir" ]]; then
DOCKER_EXTRA_ARGS="--volume=${KOKORO_GFILE_DIR}/distdir:/distdir:ro ${DOCKER_EXTRA_ARGS:-}" DOCKER_EXTRA_ARGS="--volume=${KOKORO_GFILE_DIR}/distdir:/distdir:ro ${DOCKER_EXTRA_ARGS:-}"
BAZEL_EXTRA_ARGS="--distdir=/distdir ${BAZEL_EXTRA_ARGS:-}" BAZEL_EXTRA_ARGS="--distdir=/distdir ${BAZEL_EXTRA_ARGS:-}"
fi fi

View file

@ -20,19 +20,19 @@
set -euox pipefail set -euox pipefail
if [ -z ${ABSEIL_ROOT:-} ]; then if [[ -z ${ABSEIL_ROOT:-} ]]; then
ABSEIL_ROOT="$(realpath $(dirname ${0})/..)" ABSEIL_ROOT="$(realpath $(dirname ${0})/..)"
fi fi
if [ -z ${STD:-} ]; then if [[ -z ${STD:-} ]]; then
STD="c++11 c++14 c++17" STD="c++11 c++14 c++17"
fi fi
if [ -z ${COMPILATION_MODE:-} ]; then if [[ -z ${COMPILATION_MODE:-} ]]; then
COMPILATION_MODE="fastbuild opt" COMPILATION_MODE="fastbuild opt"
fi fi
if [ -z ${EXCEPTIONS_MODE:-} ]; then if [[ -z ${EXCEPTIONS_MODE:-} ]]; then
EXCEPTIONS_MODE="-fno-exceptions -fexceptions" EXCEPTIONS_MODE="-fno-exceptions -fexceptions"
fi fi
@ -41,7 +41,7 @@ readonly DOCKER_CONTAINER=${LINUX_CLANG_LATEST_CONTAINER}
# USE_BAZEL_CACHE=1 only works on Kokoro. # USE_BAZEL_CACHE=1 only works on Kokoro.
# Without access to the credentials this won't work. # Without access to the credentials this won't work.
if [ ${USE_BAZEL_CACHE:-0} -ne 0 ]; then if [[ ${USE_BAZEL_CACHE:-0} -ne 0 ]]; then
DOCKER_EXTRA_ARGS="--volume=${KOKORO_KEYSTORE_DIR}:/keystore:ro ${DOCKER_EXTRA_ARGS:-}" DOCKER_EXTRA_ARGS="--volume=${KOKORO_KEYSTORE_DIR}:/keystore:ro ${DOCKER_EXTRA_ARGS:-}"
# Bazel doesn't track changes to tools outside of the workspace # Bazel doesn't track changes to tools outside of the workspace
# (e.g. /usr/bin/gcc), so by appending the docker container to the # (e.g. /usr/bin/gcc), so by appending the docker container to the
@ -54,7 +54,7 @@ fi
# Avoid depending on external sites like GitHub by checking --distdir for # Avoid depending on external sites like GitHub by checking --distdir for
# external dependencies first. # external dependencies first.
# https://docs.bazel.build/versions/master/guide.html#distdir # https://docs.bazel.build/versions/master/guide.html#distdir
if [ -z ${KOKORO_GFILE_DIR:-} && -d "${KOKORO_GFILE_DIR}/distdir" ]; then if [[ ${KOKORO_GFILE_DIR:-} ]] && [[ -d "${KOKORO_GFILE_DIR}/distdir" ]]; then
DOCKER_EXTRA_ARGS="--volume=${KOKORO_GFILE_DIR}/distdir:/distdir:ro ${DOCKER_EXTRA_ARGS:-}" DOCKER_EXTRA_ARGS="--volume=${KOKORO_GFILE_DIR}/distdir:/distdir:ro ${DOCKER_EXTRA_ARGS:-}"
BAZEL_EXTRA_ARGS="--distdir=/distdir ${BAZEL_EXTRA_ARGS:-}" BAZEL_EXTRA_ARGS="--distdir=/distdir ${BAZEL_EXTRA_ARGS:-}"
fi fi

View file

@ -20,19 +20,19 @@
set -euox pipefail set -euox pipefail
if [ -z ${ABSEIL_ROOT:-} ]; then if [[ -z ${ABSEIL_ROOT:-} ]]; then
ABSEIL_ROOT="$(realpath $(dirname ${0})/..)" ABSEIL_ROOT="$(realpath $(dirname ${0})/..)"
fi fi
if [ -z ${STD:-} ]; then if [[ -z ${STD:-} ]]; then
STD="c++11 c++14 c++17" STD="c++11 c++14 c++17"
fi fi
if [ -z ${COMPILATION_MODE:-} ]; then if [[ -z ${COMPILATION_MODE:-} ]]; then
COMPILATION_MODE="fastbuild opt" COMPILATION_MODE="fastbuild opt"
fi fi
if [ -z ${EXCEPTIONS_MODE:-} ]; then if [[ -z ${EXCEPTIONS_MODE:-} ]]; then
EXCEPTIONS_MODE="-fno-exceptions -fexceptions" EXCEPTIONS_MODE="-fno-exceptions -fexceptions"
fi fi
@ -41,7 +41,7 @@ readonly DOCKER_CONTAINER=${LINUX_CLANG_LATEST_CONTAINER}
# USE_BAZEL_CACHE=1 only works on Kokoro. # USE_BAZEL_CACHE=1 only works on Kokoro.
# Without access to the credentials this won't work. # Without access to the credentials this won't work.
if [ ${USE_BAZEL_CACHE:-0} -ne 0 ]; then if [[ ${USE_BAZEL_CACHE:-0} -ne 0 ]]; then
DOCKER_EXTRA_ARGS="--volume=${KOKORO_KEYSTORE_DIR}:/keystore:ro ${DOCKER_EXTRA_ARGS:-}" DOCKER_EXTRA_ARGS="--volume=${KOKORO_KEYSTORE_DIR}:/keystore:ro ${DOCKER_EXTRA_ARGS:-}"
# Bazel doesn't track changes to tools outside of the workspace # Bazel doesn't track changes to tools outside of the workspace
# (e.g. /usr/bin/gcc), so by appending the docker container to the # (e.g. /usr/bin/gcc), so by appending the docker container to the
@ -54,7 +54,7 @@ fi
# Avoid depending on external sites like GitHub by checking --distdir for # Avoid depending on external sites like GitHub by checking --distdir for
# external dependencies first. # external dependencies first.
# https://docs.bazel.build/versions/master/guide.html#distdir # https://docs.bazel.build/versions/master/guide.html#distdir
if [ -z ${KOKORO_GFILE_DIR:-} && -d "${KOKORO_GFILE_DIR}/distdir" ]; then if [[ ${KOKORO_GFILE_DIR:-} ]] && [[ -d "${KOKORO_GFILE_DIR}/distdir" ]]; then
DOCKER_EXTRA_ARGS="--volume=${KOKORO_GFILE_DIR}/distdir:/distdir:ro ${DOCKER_EXTRA_ARGS:-}" DOCKER_EXTRA_ARGS="--volume=${KOKORO_GFILE_DIR}/distdir:/distdir:ro ${DOCKER_EXTRA_ARGS:-}"
BAZEL_EXTRA_ARGS="--distdir=/distdir ${BAZEL_EXTRA_ARGS:-}" BAZEL_EXTRA_ARGS="--distdir=/distdir ${BAZEL_EXTRA_ARGS:-}"
fi fi

View file

@ -20,19 +20,19 @@
set -euox pipefail set -euox pipefail
if [ -z ${ABSEIL_ROOT:-} ]; then if [[ -z ${ABSEIL_ROOT:-} ]]; then
ABSEIL_ROOT="$(realpath $(dirname ${0})/..)" ABSEIL_ROOT="$(realpath $(dirname ${0})/..)"
fi fi
if [ -z ${STD:-} ]; then if [[ -z ${STD:-} ]]; then
STD="c++11 c++14" STD="c++11 c++14"
fi fi
if [ -z ${COMPILATION_MODE:-} ]; then if [[ -z ${COMPILATION_MODE:-} ]]; then
COMPILATION_MODE="fastbuild opt" COMPILATION_MODE="fastbuild opt"
fi fi
if [ -z ${EXCEPTIONS_MODE:-} ]; then if [[ -z ${EXCEPTIONS_MODE:-} ]]; then
EXCEPTIONS_MODE="-fno-exceptions -fexceptions" EXCEPTIONS_MODE="-fno-exceptions -fexceptions"
fi fi
@ -41,7 +41,7 @@ readonly DOCKER_CONTAINER=${LINUX_GCC_49_CONTAINER}
# USE_BAZEL_CACHE=1 only works on Kokoro. # USE_BAZEL_CACHE=1 only works on Kokoro.
# Without access to the credentials this won't work. # Without access to the credentials this won't work.
if [ ${USE_BAZEL_CACHE:-0} -ne 0 ]; then if [[ ${USE_BAZEL_CACHE:-0} -ne 0 ]]; then
DOCKER_EXTRA_ARGS="--volume=${KOKORO_KEYSTORE_DIR}:/keystore:ro ${DOCKER_EXTRA_ARGS:-}" DOCKER_EXTRA_ARGS="--volume=${KOKORO_KEYSTORE_DIR}:/keystore:ro ${DOCKER_EXTRA_ARGS:-}"
# Bazel doesn't track changes to tools outside of the workspace # Bazel doesn't track changes to tools outside of the workspace
# (e.g. /usr/bin/gcc), so by appending the docker container to the # (e.g. /usr/bin/gcc), so by appending the docker container to the
@ -54,7 +54,7 @@ fi
# Avoid depending on external sites like GitHub by checking --distdir for # Avoid depending on external sites like GitHub by checking --distdir for
# external dependencies first. # external dependencies first.
# https://docs.bazel.build/versions/master/guide.html#distdir # https://docs.bazel.build/versions/master/guide.html#distdir
if [ -z ${KOKORO_GFILE_DIR:-} && -d "${KOKORO_GFILE_DIR}/distdir" ]; then if [[ ${KOKORO_GFILE_DIR:-} ]] && [[ -d "${KOKORO_GFILE_DIR}/distdir" ]]; then
DOCKER_EXTRA_ARGS="--volume=${KOKORO_GFILE_DIR}/distdir:/distdir:ro ${DOCKER_EXTRA_ARGS:-}" DOCKER_EXTRA_ARGS="--volume=${KOKORO_GFILE_DIR}/distdir:/distdir:ro ${DOCKER_EXTRA_ARGS:-}"
BAZEL_EXTRA_ARGS="--distdir=/distdir ${BAZEL_EXTRA_ARGS:-}" BAZEL_EXTRA_ARGS="--distdir=/distdir ${BAZEL_EXTRA_ARGS:-}"
fi fi

View file

@ -20,19 +20,19 @@
set -euox pipefail set -euox pipefail
if [ -z ${ABSEIL_ROOT:-} ]; then if [[ -z ${ABSEIL_ROOT:-} ]]; then
ABSEIL_ROOT="$(realpath $(dirname ${0})/..)" ABSEIL_ROOT="$(realpath $(dirname ${0})/..)"
fi fi
if [ -z ${STD:-} ]; then if [[ -z ${STD:-} ]]; then
STD="c++11 c++14 c++17" STD="c++11 c++14 c++17"
fi fi
if [ -z ${COMPILATION_MODE:-} ]; then if [[ -z ${COMPILATION_MODE:-} ]]; then
COMPILATION_MODE="fastbuild opt" COMPILATION_MODE="fastbuild opt"
fi fi
if [ -z ${EXCEPTIONS_MODE:-} ]; then if [[ -z ${EXCEPTIONS_MODE:-} ]]; then
EXCEPTIONS_MODE="-fno-exceptions -fexceptions" EXCEPTIONS_MODE="-fno-exceptions -fexceptions"
fi fi
@ -41,7 +41,7 @@ readonly DOCKER_CONTAINER=${LINUX_GCC_LATEST_CONTAINER}
# USE_BAZEL_CACHE=1 only works on Kokoro. # USE_BAZEL_CACHE=1 only works on Kokoro.
# Without access to the credentials this won't work. # Without access to the credentials this won't work.
if [ ${USE_BAZEL_CACHE:-0} -ne 0 ]; then if [[ ${USE_BAZEL_CACHE:-0} -ne 0 ]]; then
DOCKER_EXTRA_ARGS="--volume=${KOKORO_KEYSTORE_DIR}:/keystore:ro ${DOCKER_EXTRA_ARGS:-}" DOCKER_EXTRA_ARGS="--volume=${KOKORO_KEYSTORE_DIR}:/keystore:ro ${DOCKER_EXTRA_ARGS:-}"
# Bazel doesn't track changes to tools outside of the workspace # Bazel doesn't track changes to tools outside of the workspace
# (e.g. /usr/bin/gcc), so by appending the docker container to the # (e.g. /usr/bin/gcc), so by appending the docker container to the
@ -54,7 +54,7 @@ fi
# Avoid depending on external sites like GitHub by checking --distdir for # Avoid depending on external sites like GitHub by checking --distdir for
# external dependencies first. # external dependencies first.
# https://docs.bazel.build/versions/master/guide.html#distdir # https://docs.bazel.build/versions/master/guide.html#distdir
if [ -z ${KOKORO_GFILE_DIR:-} && -d "${KOKORO_GFILE_DIR}/distdir" ]; then if [[ ${KOKORO_GFILE_DIR:-} ]] && [[ -d "${KOKORO_GFILE_DIR}/distdir" ]]; then
DOCKER_EXTRA_ARGS="--volume=${KOKORO_GFILE_DIR}/distdir:/distdir:ro ${DOCKER_EXTRA_ARGS:-}" DOCKER_EXTRA_ARGS="--volume=${KOKORO_GFILE_DIR}/distdir:/distdir:ro ${DOCKER_EXTRA_ARGS:-}"
BAZEL_EXTRA_ARGS="--distdir=/distdir ${BAZEL_EXTRA_ARGS:-}" BAZEL_EXTRA_ARGS="--distdir=/distdir ${BAZEL_EXTRA_ARGS:-}"
fi fi
@ -75,7 +75,7 @@ for std in ${STD}; do
${DOCKER_CONTAINER} \ ${DOCKER_CONTAINER} \
/bin/sh -c " /bin/sh -c "
cp -r /abseil-cpp-ro/* /abseil-cpp/ cp -r /abseil-cpp-ro/* /abseil-cpp/
if [ -n \"${ALTERNATE_OPTIONS:-}\" ]; then if [[ -n \"${ALTERNATE_OPTIONS:-}\" ]]; then
cp ${ALTERNATE_OPTIONS:-} absl/base/options.h || exit 1 cp ${ALTERNATE_OPTIONS:-} absl/base/options.h || exit 1
fi fi
/usr/local/bin/bazel test ... \ /usr/local/bin/bazel test ... \

View file

@ -22,15 +22,15 @@
set -euox pipefail set -euox pipefail
if [ -z ${ABSEIL_ROOT:-} ]; then if [[ -z ${ABSEIL_ROOT:-} ]]; then
ABSEIL_ROOT="$(realpath $(dirname ${0})/..)" ABSEIL_ROOT="$(realpath $(dirname ${0})/..)"
fi fi
if [ -z ${ABSL_CMAKE_CXX_STANDARDS:-} ]; then if [[ -z ${ABSL_CMAKE_CXX_STANDARDS:-} ]]; then
ABSL_CMAKE_CXX_STANDARDS="11 14 17" ABSL_CMAKE_CXX_STANDARDS="11 14 17"
fi fi
if [ -z ${ABSL_CMAKE_BUILD_TYPES:-} ]; then if [[ -z ${ABSL_CMAKE_BUILD_TYPES:-} ]]; then
ABSL_CMAKE_BUILD_TYPES="Debug Release" ABSL_CMAKE_BUILD_TYPES="Debug Release"
fi fi

View file

@ -22,15 +22,15 @@
set -euox pipefail set -euox pipefail
if [ -z ${ABSEIL_ROOT:-} ]; then if [[ -z ${ABSEIL_ROOT:-} ]]; then
ABSEIL_ROOT="$(realpath $(dirname ${0})/..)" ABSEIL_ROOT="$(realpath $(dirname ${0})/..)"
fi fi
if [ -z ${ABSL_CMAKE_CXX_STANDARDS:-} ]; then if [[ -z ${ABSL_CMAKE_CXX_STANDARDS:-} ]]; then
ABSL_CMAKE_CXX_STANDARDS="11 14 17" ABSL_CMAKE_CXX_STANDARDS="11 14 17"
fi fi
if [ -z ${ABSL_CMAKE_BUILD_TYPES:-} ]; then if [[ -z ${ABSL_CMAKE_BUILD_TYPES:-} ]]; then
ABSL_CMAKE_BUILD_TYPES="Debug Release" ABSL_CMAKE_BUILD_TYPES="Debug Release"
fi fi

View file

@ -19,13 +19,13 @@
set -euox pipefail set -euox pipefail
if [ -z ${ABSEIL_ROOT:-} ]; then if [[ -z ${ABSEIL_ROOT:-} ]]; then
ABSEIL_ROOT="$(realpath $(dirname ${0})/..)" ABSEIL_ROOT="$(realpath $(dirname ${0})/..)"
fi fi
# If we are running on Kokoro, check for a versioned Bazel binary. # If we are running on Kokoro, check for a versioned Bazel binary.
KOKORO_GFILE_BAZEL_BIN="bazel-2.0.0-darwin-x86_64" KOKORO_GFILE_BAZEL_BIN="bazel-2.0.0-darwin-x86_64"
if [ ${KOKORO_GFILE_DIR:-} ] && [ -f ${KOKORO_GFILE_DIR}/${KOKORO_GFILE_BAZEL_BIN} ]; then if [[ ${KOKORO_GFILE_DIR:-} ]] && [[ -f ${KOKORO_GFILE_DIR}/${KOKORO_GFILE_BAZEL_BIN} ]]; then
BAZEL_BIN="${KOKORO_GFILE_DIR}/${KOKORO_GFILE_BAZEL_BIN}" BAZEL_BIN="${KOKORO_GFILE_DIR}/${KOKORO_GFILE_BAZEL_BIN}"
chmod +x ${BAZEL_BIN} chmod +x ${BAZEL_BIN}
else else
@ -41,7 +41,7 @@ echo "---------------"
cd ${ABSEIL_ROOT} cd ${ABSEIL_ROOT}
if [ -n "${ALTERNATE_OPTIONS:-}" ]; then if [[ -n "${ALTERNATE_OPTIONS:-}" ]]; then
cp ${ALTERNATE_OPTIONS:-} absl/base/options.h || exit 1 cp ${ALTERNATE_OPTIONS:-} absl/base/options.h || exit 1
fi fi

View file

@ -19,12 +19,12 @@
set -euox pipefail set -euox pipefail
if [ -z ${ABSEIL_ROOT:-} ]; then if [[ -z ${ABSEIL_ROOT:-} ]]; then
ABSEIL_ROOT="$(dirname ${0})/.." ABSEIL_ROOT="$(dirname ${0})/.."
fi fi
ABSEIL_ROOT=$(realpath ${ABSEIL_ROOT}) ABSEIL_ROOT=$(realpath ${ABSEIL_ROOT})
if [ -z ${ABSL_CMAKE_BUILD_TYPES:-} ]; then if [[ -z ${ABSL_CMAKE_BUILD_TYPES:-} ]]; then
ABSL_CMAKE_BUILD_TYPES="Debug" ABSL_CMAKE_BUILD_TYPES="Debug"
fi fi