Changes imported from Abseil "staging" branch:
- 46a4bd582619bfc4799c1a907316e914ed0c0105 Fixes to mutex_nonprod. Apparently this has never built.... by Greg Falcon <gfalcon@google.com> - 4bcf6f013aeee53057527d70100de8535aec9b93 Add some comments to copts.bzl by Tom Manshreck <shreck@google.com> - 54cf717b1c5dfb814721f92a8eb9df5587f5f758 Internal change by Abseil Team <absl-team@google.com> - d1f1c7e6e61358300963b7bd50c203740a49297d Eliminate kFast{UInt,Int}{32,64}ToBufferSize constants by Jorg Brown <jorg@google.com> GitOrigin-RevId: 46a4bd582619bfc4799c1a907316e914ed0c0105 Change-Id: I129b6b3d27d9ae2c6eb21d6e44a52d10399ef8aa
This commit is contained in:
parent
dc0282d098
commit
04edad3801
6 changed files with 47 additions and 45 deletions
|
@ -243,7 +243,7 @@
|
|||
// Windows _WIN32
|
||||
// NaCL __native_client__
|
||||
// AsmJS __asmjs__
|
||||
// Fuschia __Fuchsia__
|
||||
// Fuchsia __Fuchsia__
|
||||
//
|
||||
// Note that since Android defines both __ANDROID__ and __linux__, one
|
||||
// may probe for either Linux or Android by simply testing for __linux__.
|
||||
|
|
|
@ -29,12 +29,18 @@ GCC_TEST_FLAGS = [
|
|||
"-Wno-unused-private-field",
|
||||
]
|
||||
|
||||
|
||||
# Docs on single flags is preceded by a comment.
|
||||
# Docs on groups of flags is preceded by ###.
|
||||
|
||||
LLVM_FLAGS = [
|
||||
"-Wall",
|
||||
"-Wextra",
|
||||
"-Weverything",
|
||||
# Abseil does not support C++98
|
||||
"-Wno-c++98-compat-pedantic",
|
||||
"-Wno-comma",
|
||||
# Turns off all implicit conversion warnings. Most are re-enabled below.
|
||||
"-Wno-conversion",
|
||||
"-Wno-covered-switch-default",
|
||||
"-Wno-deprecated",
|
||||
|
@ -47,6 +53,7 @@ LLVM_FLAGS = [
|
|||
"-Wno-float-conversion",
|
||||
"-Wno-float-equal",
|
||||
"-Wno-format-nonliteral",
|
||||
# Too aggressive: warns on Clang extensions enclosed in Clang-only code paths.
|
||||
"-Wno-gcc-compat",
|
||||
"-Wno-global-constructors",
|
||||
"-Wno-nested-anon-types",
|
||||
|
@ -54,6 +61,7 @@ LLVM_FLAGS = [
|
|||
"-Wno-old-style-cast",
|
||||
"-Wno-packed",
|
||||
"-Wno-padded",
|
||||
# Warns on preferred usage of non-POD types such as string_view
|
||||
"-Wno-range-loop-analysis",
|
||||
"-Wno-reserved-id-macro",
|
||||
"-Wno-shorten-64-to-32",
|
||||
|
@ -63,9 +71,12 @@ LLVM_FLAGS = [
|
|||
"-Wno-undef",
|
||||
"-Wno-unknown-warning-option",
|
||||
"-Wno-unreachable-code",
|
||||
# Causes warnings on include guards
|
||||
"-Wno-unused-macros",
|
||||
"-Wno-weak-vtables",
|
||||
# flags below are also controlled by -Wconversion which is disabled
|
||||
###
|
||||
# Implicit conversion warnings turned off by -Wno-conversion
|
||||
# which are re-enabled below.
|
||||
"-Wbitfield-enum-conversion",
|
||||
"-Wbool-conversion",
|
||||
"-Wconstant-conversion",
|
||||
|
@ -76,6 +87,7 @@ LLVM_FLAGS = [
|
|||
"-Wnull-conversion",
|
||||
"-Wobjc-literal-conversion",
|
||||
"-Wstring-conversion",
|
||||
###
|
||||
]
|
||||
|
||||
LLVM_TEST_FLAGS = [
|
||||
|
|
|
@ -17,16 +17,6 @@
|
|||
|
||||
namespace {
|
||||
|
||||
// Previously documented minimum buffer sizes for Fast*ToBuffer functions.
|
||||
// NOTE(edk): These should be deleted and uses replaced with kFastToBufferSize
|
||||
// once existing code has been fixed to use kFastToBufferSize.
|
||||
enum {
|
||||
kFastInt32ToBufferSize = 12,
|
||||
kFastInt64ToBufferSize = 22,
|
||||
kFastUInt32ToBufferSize = 12,
|
||||
kFastUInt64ToBufferSize = 22
|
||||
};
|
||||
|
||||
template <typename IntType>
|
||||
bool Itoa(IntType value, int base, std::string* destination) {
|
||||
destination->clear();
|
||||
|
|
|
@ -28,11 +28,6 @@
|
|||
|
||||
namespace {
|
||||
|
||||
using absl::numbers_internal::FastInt32ToBuffer;
|
||||
using absl::numbers_internal::FastInt64ToBuffer;
|
||||
using absl::numbers_internal::FastUInt32ToBuffer;
|
||||
using absl::numbers_internal::FastUInt64ToBuffer;
|
||||
using absl::numbers_internal::kFastToBufferSize;
|
||||
using absl::numbers_internal::kSixDigitsToBufferSize;
|
||||
using absl::numbers_internal::safe_strto32_base;
|
||||
using absl::numbers_internal::safe_strto64_base;
|
||||
|
@ -116,22 +111,22 @@ TEST(ToString, PerfectDtoa) {
|
|||
}
|
||||
|
||||
void CheckInt32(int32_t x) {
|
||||
char buffer[kFastInt32ToBufferSize];
|
||||
char* actual = FastInt32ToBuffer(x, buffer);
|
||||
char buffer[absl::numbers_internal::kFastToBufferSize];
|
||||
char* actual = absl::numbers_internal::FastInt32ToBuffer(x, buffer);
|
||||
std::string expected = std::to_string(x);
|
||||
ASSERT_TRUE(expected == actual)
|
||||
ASSERT_TRUE(expected == std::string(buffer, actual))
|
||||
<< "Expected \"" << expected << "\", Actual \"" << actual << "\", Input "
|
||||
<< x;
|
||||
}
|
||||
|
||||
void CheckInt64(int64_t x) {
|
||||
char buffer[kFastInt64ToBufferSize + 3];
|
||||
char buffer[absl::numbers_internal::kFastToBufferSize + 3];
|
||||
buffer[0] = '*';
|
||||
buffer[23] = '*';
|
||||
buffer[24] = '*';
|
||||
char* actual = FastInt64ToBuffer(x, &buffer[1]);
|
||||
char* actual = absl::numbers_internal::FastInt64ToBuffer(x, &buffer[1]);
|
||||
std::string expected = std::to_string(x);
|
||||
ASSERT_TRUE(expected == actual)
|
||||
ASSERT_TRUE(expected == std::string(&buffer[1], actual))
|
||||
<< "Expected \"" << expected << "\", Actual \"" << actual << "\", Input "
|
||||
<< x;
|
||||
ASSERT_EQ(buffer[0], '*');
|
||||
|
@ -140,32 +135,32 @@ void CheckInt64(int64_t x) {
|
|||
}
|
||||
|
||||
void CheckUInt32(uint32_t x) {
|
||||
char buffer[kFastUInt64ToBufferSize];
|
||||
char* actual = FastUInt32ToBuffer(x, buffer);
|
||||
char buffer[absl::numbers_internal::kFastToBufferSize];
|
||||
char* actual = absl::numbers_internal::FastUInt32ToBuffer(x, buffer);
|
||||
std::string expected = std::to_string(x);
|
||||
ASSERT_TRUE(expected == actual)
|
||||
ASSERT_TRUE(expected == std::string(buffer, actual))
|
||||
<< "Expected \"" << expected << "\", Actual \"" << actual << "\", Input "
|
||||
<< x;
|
||||
}
|
||||
|
||||
void CheckUInt64(uint64_t x) {
|
||||
char buffer[kFastUInt64ToBufferSize + 1];
|
||||
char* actual = FastUInt64ToBuffer(x, &buffer[1]);
|
||||
char buffer[absl::numbers_internal::kFastToBufferSize + 1];
|
||||
char* actual = absl::numbers_internal::FastUInt64ToBuffer(x, &buffer[1]);
|
||||
std::string expected = std::to_string(x);
|
||||
ASSERT_TRUE(expected == actual)
|
||||
ASSERT_TRUE(expected == std::string(&buffer[1], actual))
|
||||
<< "Expected \"" << expected << "\", Actual \"" << actual << "\", Input "
|
||||
<< x;
|
||||
}
|
||||
|
||||
void CheckHex64(uint64_t v) {
|
||||
char expected[kFastUInt64ToBufferSize];
|
||||
char expected[16 + 1];
|
||||
std::string actual = absl::StrCat(absl::Hex(v, absl::kZeroPad16));
|
||||
snprintf(expected, sizeof(expected), "%016" PRIx64, static_cast<uint64_t>(v));
|
||||
ASSERT_TRUE(expected == actual)
|
||||
<< "Expected \"" << expected << "\", Actual \"" << actual << "\"";
|
||||
}
|
||||
|
||||
void TestFastPrints() {
|
||||
TEST(Numbers, TestFastPrints) {
|
||||
for (int i = -100; i <= 100; i++) {
|
||||
CheckInt32(i);
|
||||
CheckInt64(i);
|
||||
|
@ -700,7 +695,7 @@ class SimpleDtoaTest : public testing::Test {
|
|||
}
|
||||
|
||||
std::string ToNineDigits(double value) {
|
||||
char buffer[kFastToBufferSize]; // more than enough for %.9g
|
||||
char buffer[16]; // more than enough for %.9g
|
||||
snprintf(buffer, sizeof(buffer), "%.9g", value);
|
||||
return buffer;
|
||||
}
|
||||
|
|
|
@ -231,6 +231,11 @@ bool Mutex::LockWhenWithTimeout(const Condition& cond, absl::Duration timeout) {
|
|||
cond, synchronization_internal::DeadlineFromTimeout(timeout));
|
||||
}
|
||||
|
||||
void Mutex::ReaderLockWhen(const Condition& cond) {
|
||||
ReaderLock();
|
||||
Await(cond);
|
||||
}
|
||||
|
||||
bool Mutex::ReaderLockWhenWithTimeout(const Condition& cond,
|
||||
absl::Duration timeout) {
|
||||
return LockWhenWithTimeout(cond, timeout);
|
||||
|
|
|
@ -105,16 +105,16 @@ class MutexImpl {
|
|||
};
|
||||
|
||||
// Do not use this implementation detail of CondVar and Mutex. A storage
|
||||
// space for T that supports a base::LinkerInitialized constructor. T must
|
||||
// space for T that supports a LinkerInitialized constructor. T must
|
||||
// have a default constructor, which is called by the first call to
|
||||
// get(). T's destructor is never called if the base::LinkerInitialized
|
||||
// get(). T's destructor is never called if the LinkerInitialized
|
||||
// constructor is called.
|
||||
//
|
||||
// Objects constructed with the default constructor are constructed and
|
||||
// destructed like any other object, and should never be allocated in
|
||||
// static storage.
|
||||
//
|
||||
// Objects constructed with the base::LinkerInitialized constructor should
|
||||
// Objects constructed with the LinkerInitialized constructor should
|
||||
// always be in static storage. For such objects, calls to get() are always
|
||||
// valid, except from signal handlers.
|
||||
//
|
||||
|
@ -126,7 +126,7 @@ class MutexImpl {
|
|||
//
|
||||
// [basic.life] says an object has non-trivial initialization if it is of
|
||||
// class type and it is initialized by a constructor other than a trivial
|
||||
// default constructor. (the base::LinkerInitialized constructor is
|
||||
// default constructor. (the LinkerInitialized constructor is
|
||||
// non-trivial)
|
||||
//
|
||||
// [basic.life] says the lifetime of an object with a non-trivial
|
||||
|
@ -139,34 +139,34 @@ class MutexImpl {
|
|||
// members of an instance outside its
|
||||
// lifetime. (SynchronizationStorage::get() access non-static members)
|
||||
//
|
||||
// So, base::LinkerInitialized object of SynchronizationStorage uses a
|
||||
// So, LinkerInitialized object of SynchronizationStorage uses a
|
||||
// non-trivial constructor, which is called at some point during dynamic
|
||||
// initialization, and is therefore subject to order of dynamic
|
||||
// initialization bugs, where get() is called before the object's
|
||||
// constructor is, resulting in undefined behavior.
|
||||
//
|
||||
// Similarly, a base::LinkerInitialized SynchronizationStorage object has a
|
||||
// Similarly, a LinkerInitialized SynchronizationStorage object has a
|
||||
// non-trivial destructor, and so its lifetime ends at some point during
|
||||
// destruction of objects with static storage duration [basic.start.term]
|
||||
// p4. There is a window where other exit code could call get() after this
|
||||
// occurs, resulting in undefined behavior.
|
||||
//
|
||||
// Combined, these statements imply that base::LinkerInitialized instances
|
||||
// Combined, these statements imply that LinkerInitialized instances
|
||||
// of SynchronizationStorage<T> rely on undefined behavior.
|
||||
//
|
||||
// However, in practice, the implementation works on all supported
|
||||
// compilers. Specifically, we rely on:
|
||||
//
|
||||
// a) zero-initialization being sufficient to initialize
|
||||
// base::LinkerInitialized instances for the purposes of calling
|
||||
// LinkerInitialized instances for the purposes of calling
|
||||
// get(), regardless of when the constructor is called. This is
|
||||
// because the is_dynamic_ boolean is correctly zero-initialized to
|
||||
// false.
|
||||
//
|
||||
// b) the base::LinkerInitialized constructor is a NOP, and immaterial to
|
||||
// b) the LinkerInitialized constructor is a NOP, and immaterial to
|
||||
// even to concurrent calls to get().
|
||||
//
|
||||
// c) the destructor being a NOP for base::LinkerInitialized objects
|
||||
// c) the destructor being a NOP for LinkerInitialized objects
|
||||
// (guaranteed by a check for !is_dynamic_), and so any concurrent and
|
||||
// subsequent calls to get() functioning as if the destructor were not
|
||||
// called, by virtue of the instances' storage remaining valid after the
|
||||
|
@ -212,7 +212,7 @@ class SynchronizationStorage {
|
|||
|
||||
// Instances allocated in static storage (not on the heap, not on the
|
||||
// stack) should use this constructor.
|
||||
explicit SynchronizationStorage(base::LinkerInitialized) {}
|
||||
explicit SynchronizationStorage(base_internal::LinkerInitialized) {}
|
||||
|
||||
SynchronizationStorage(SynchronizationStorage&) = delete;
|
||||
SynchronizationStorage& operator=(SynchronizationStorage&) = delete;
|
||||
|
@ -227,7 +227,7 @@ class SynchronizationStorage {
|
|||
// incur the cost of absl::call_once().
|
||||
//
|
||||
// For instances in static storage constructed with the
|
||||
// base::LinkerInitialized constructor, may be called at any time without
|
||||
// LinkerInitialized constructor, may be called at any time without
|
||||
// regard for order of dynamic initialization or destruction of objects
|
||||
// in static storage. See the class comment for caveats.
|
||||
T* get() {
|
||||
|
@ -242,7 +242,7 @@ class SynchronizationStorage {
|
|||
|
||||
// When true, T's destructor is run when this is destructed.
|
||||
//
|
||||
// The base::LinkerInitialized constructor assumes this value will be set
|
||||
// The LinkerInitialized constructor assumes this value will be set
|
||||
// false by static initialization.
|
||||
bool is_dynamic_;
|
||||
|
||||
|
|
Loading…
Reference in a new issue