summaryrefslogtreecommitdiff
path: root/absl
diff options
context:
space:
mode:
Diffstat (limited to 'absl')
-rw-r--r--absl/algorithm/container.h7
-rw-r--r--absl/base/BUILD.bazel12
-rw-r--r--absl/base/CMakeLists.txt3
-rw-r--r--absl/base/dynamic_annotations.cc75
-rw-r--r--absl/base/dynamic_annotations.h766
-rw-r--r--absl/base/internal/dynamic_annotations.h403
-rw-r--r--absl/flags/BUILD.bazel23
-rw-r--r--absl/flags/CMakeLists.txt17
-rw-r--r--absl/flags/commandlineflag.cc6
-rw-r--r--absl/flags/commandlineflag.h6
-rw-r--r--absl/flags/commandlineflag_test.cc1
-rw-r--r--absl/flags/declare.h1
-rw-r--r--absl/flags/flag.h21
-rw-r--r--absl/flags/flag_benchmark.cc7
-rw-r--r--absl/flags/flag_test.cc354
-rw-r--r--absl/flags/internal/commandlineflag.h7
-rw-r--r--absl/flags/internal/flag.cc11
-rw-r--r--absl/flags/internal/flag.h21
-rw-r--r--absl/flags/internal/parse.h1
-rw-r--r--absl/flags/internal/path_util.h1
-rw-r--r--absl/flags/internal/private_handle_accessor.cc8
-rw-r--r--absl/flags/internal/private_handle_accessor.h6
-rw-r--r--absl/flags/internal/registry.cc1
-rw-r--r--absl/flags/internal/registry.h6
-rw-r--r--absl/flags/internal/type_erased.h1
-rw-r--r--absl/flags/internal/type_erased_test.cc2
-rw-r--r--absl/flags/internal/usage.cc2
-rw-r--r--absl/flags/internal/usage_test.cc2
-rw-r--r--absl/flags/parse.cc1
-rw-r--r--absl/flags/parse.h1
-rw-r--r--absl/flags/usage_config.cc1
-rw-r--r--absl/time/civil_time.cc12
-rw-r--r--absl/time/format.cc13
-rw-r--r--absl/time/format_benchmark.cc2
-rw-r--r--absl/time/internal/cctz/include/cctz/time_zone.h3
-rw-r--r--absl/time/time.h15
36 files changed, 1242 insertions, 577 deletions
diff --git a/absl/algorithm/container.h b/absl/algorithm/container.h
index d72532de..2457d78b 100644
--- a/absl/algorithm/container.h
+++ b/absl/algorithm/container.h
@@ -943,9 +943,10 @@ void c_partial_sort(
// c_partial_sort_copy()
//
// Container-based version of the <algorithm> `std::partial_sort_copy()`
-// function to sort elements within a container such that elements before
-// `middle` are sorted in ascending order, and return the result within an
-// iterator.
+// function to sort the elements in the given range `result` within the larger
+// `sequence` in ascending order (and using `result` as the output parameter).
+// At most min(result.last - result.first, sequence.last - sequence.first)
+// elements from the sequence will be stored in the result.
template <typename C, typename RandomAccessContainer>
container_algorithm_internal::ContainerIter<RandomAccessContainer>
c_partial_sort_copy(const C& sequence, RandomAccessContainer& result) {
diff --git a/absl/base/BUILD.bazel b/absl/base/BUILD.bazel
index 76122dab..35cb2e94 100644
--- a/absl/base/BUILD.bazel
+++ b/absl/base/BUILD.bazel
@@ -115,10 +115,18 @@ cc_library(
cc_library(
name = "dynamic_annotations",
- srcs = ["dynamic_annotations.cc"],
- hdrs = ["dynamic_annotations.h"],
+ srcs = [
+ "dynamic_annotations.cc",
+ "internal/dynamic_annotations.h",
+ ],
+ hdrs = [
+ "dynamic_annotations.h",
+ ],
copts = ABSL_DEFAULT_COPTS,
linkopts = ABSL_DEFAULT_LINKOPTS,
+ deps = [
+ ":config",
+ ],
)
cc_library(
diff --git a/absl/base/CMakeLists.txt b/absl/base/CMakeLists.txt
index 292998b3..b7c01c99 100644
--- a/absl/base/CMakeLists.txt
+++ b/absl/base/CMakeLists.txt
@@ -106,8 +106,11 @@ absl_cc_library(
"dynamic_annotations.h"
SRCS
"dynamic_annotations.cc"
+ "internal/dynamic_annotations.h"
COPTS
${ABSL_DEFAULT_COPTS}
+ DEPS
+ absl::config
PUBLIC
)
diff --git a/absl/base/dynamic_annotations.cc b/absl/base/dynamic_annotations.cc
index 21e822e5..f26e673e 100644
--- a/absl/base/dynamic_annotations.cc
+++ b/absl/base/dynamic_annotations.cc
@@ -17,72 +17,17 @@
#include "absl/base/dynamic_annotations.h"
-#ifndef __has_feature
-#define __has_feature(x) 0
-#endif
-
-/* Compiler-based ThreadSanitizer defines
- DYNAMIC_ANNOTATIONS_EXTERNAL_IMPL = 1
- and provides its own definitions of the functions. */
+// Compiler-based ThreadSanitizer defines
+// DYNAMIC_ANNOTATIONS_EXTERNAL_IMPL = 1
+// and provides its own definitions of the functions.
#ifndef DYNAMIC_ANNOTATIONS_EXTERNAL_IMPL
# define DYNAMIC_ANNOTATIONS_EXTERNAL_IMPL 0
#endif
-/* Each function is empty and called (via a macro) only in debug mode.
- The arguments are captured by dynamic tools at runtime. */
-
#if DYNAMIC_ANNOTATIONS_EXTERNAL_IMPL == 0 && !defined(__native_client__)
-#if __has_feature(memory_sanitizer)
-#include <sanitizer/msan_interface.h>
-#endif
-
-#ifdef __cplusplus
extern "C" {
-#endif
-
-void AnnotateRWLockCreate(const char *, int,
- const volatile void *){}
-void AnnotateRWLockDestroy(const char *, int,
- const volatile void *){}
-void AnnotateRWLockAcquired(const char *, int,
- const volatile void *, long){}
-void AnnotateRWLockReleased(const char *, int,
- const volatile void *, long){}
-void AnnotateBenignRace(const char *, int,
- const volatile void *,
- const char *){}
-void AnnotateBenignRaceSized(const char *, int,
- const volatile void *,
- size_t,
- const char *) {}
-void AnnotateThreadName(const char *, int,
- const char *){}
-void AnnotateIgnoreReadsBegin(const char *, int){}
-void AnnotateIgnoreReadsEnd(const char *, int){}
-void AnnotateIgnoreWritesBegin(const char *, int){}
-void AnnotateIgnoreWritesEnd(const char *, int){}
-void AnnotateEnableRaceDetection(const char *, int, int){}
-void AnnotateMemoryIsInitialized(const char *, int,
- const volatile void *mem, size_t size) {
-#if __has_feature(memory_sanitizer)
- __msan_unpoison(mem, size);
-#else
- (void)mem;
- (void)size;
-#endif
-}
-
-void AnnotateMemoryIsUninitialized(const char *, int,
- const volatile void *mem, size_t size) {
-#if __has_feature(memory_sanitizer)
- __msan_allocated_memory(mem, size);
-#else
- (void)mem;
- (void)size;
-#endif
-}
static int GetRunningOnValgrind(void) {
#ifdef RUNNING_ON_VALGRIND
@@ -95,21 +40,21 @@ static int GetRunningOnValgrind(void) {
return 0;
}
-/* See the comments in dynamic_annotations.h */
+// See the comments in dynamic_annotations.h
int RunningOnValgrind(void) {
static volatile int running_on_valgrind = -1;
int local_running_on_valgrind = running_on_valgrind;
- /* C doesn't have thread-safe initialization of statics, and we
- don't want to depend on pthread_once here, so hack it. */
+ // C doesn't have thread-safe initialization of statics, and we
+ // don't want to depend on pthread_once here, so hack it.
ANNOTATE_BENIGN_RACE(&running_on_valgrind, "safe hack");
if (local_running_on_valgrind == -1)
running_on_valgrind = local_running_on_valgrind = GetRunningOnValgrind();
return local_running_on_valgrind;
}
-/* See the comments in dynamic_annotations.h */
+// See the comments in dynamic_annotations.h
double ValgrindSlowdown(void) {
- /* Same initialization hack as in RunningOnValgrind(). */
+ // Same initialization hack as in RunningOnValgrind().
static volatile double slowdown = 0.0;
double local_slowdown = slowdown;
ANNOTATE_BENIGN_RACE(&slowdown, "safe hack");
@@ -123,7 +68,5 @@ double ValgrindSlowdown(void) {
return local_slowdown;
}
-#ifdef __cplusplus
} // extern "C"
-#endif
-#endif /* DYNAMIC_ANNOTATIONS_EXTERNAL_IMPL == 0 */
+#endif // DYNAMIC_ANNOTATIONS_EXTERNAL_IMPL == 0
diff --git a/absl/base/dynamic_annotations.h b/absl/base/dynamic_annotations.h
index 2d985260..1444dc48 100644
--- a/absl/base/dynamic_annotations.h
+++ b/absl/base/dynamic_annotations.h
@@ -1,386 +1,504 @@
-/*
- * Copyright 2017 The Abseil Authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-/* This file defines dynamic annotations for use with dynamic analysis
- tool such as valgrind, PIN, etc.
-
- Dynamic annotation is a source code annotation that affects
- the generated code (that is, the annotation is not a comment).
- Each such annotation is attached to a particular
- instruction and/or to a particular object (address) in the program.
-
- The annotations that should be used by users are macros in all upper-case
- (e.g., ANNOTATE_THREAD_NAME).
-
- Actual implementation of these macros may differ depending on the
- dynamic analysis tool being used.
-
- This file supports the following configurations:
- - Dynamic Annotations enabled (with static thread-safety warnings disabled).
- In this case, macros expand to functions implemented by Thread Sanitizer,
- when building with TSan. When not provided an external implementation,
- dynamic_annotations.cc provides no-op implementations.
-
- - Static Clang thread-safety warnings enabled.
- When building with a Clang compiler that supports thread-safety warnings,
- a subset of annotations can be statically-checked at compile-time. We
- expand these macros to static-inline functions that can be analyzed for
- thread-safety, but afterwards elided when building the final binary.
-
- - All annotations are disabled.
- If neither Dynamic Annotations nor Clang thread-safety warnings are
- enabled, then all annotation-macros expand to empty. */
+// Copyright 2017 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// This file defines dynamic annotations for use with dynamic analysis tool
+// such as valgrind, PIN, etc.
+//
+// Dynamic annotation is a source code annotation that affects the generated
+// code (that is, the annotation is not a comment). Each such annotation is
+// attached to a particular instruction and/or to a particular object (address)
+// in the program.
+//
+// The annotations that should be used by users are macros in all upper-case
+// (e.g., ABSL_ANNOTATE_THREAD_NAME).
+//
+// Actual implementation of these macros may differ depending on the dynamic
+// analysis tool being used.
+//
+// This file supports the following configurations:
+// - Dynamic Annotations enabled (with static thread-safety warnings disabled).
+// In this case, macros expand to functions implemented by Thread Sanitizer,
+// when building with TSan. When not provided an external implementation,
+// dynamic_annotations.cc provides no-op implementations.
+//
+// - Static Clang thread-safety warnings enabled.
+// When building with a Clang compiler that supports thread-safety warnings,
+// a subset of annotations can be statically-checked at compile-time. We
+// expand these macros to static-inline functions that can be analyzed for
+// thread-safety, but afterwards elided when building the final binary.
+//
+// - All annotations are disabled.
+// If neither Dynamic Annotations nor Clang thread-safety warnings are
+// enabled, then all annotation-macros expand to empty.
#ifndef ABSL_BASE_DYNAMIC_ANNOTATIONS_H_
#define ABSL_BASE_DYNAMIC_ANNOTATIONS_H_
+#include <stddef.h>
+
+#include "absl/base/config.h"
+
+// TODO(rogeeff): Remove after the backward compatibility period.
+#include "absl/base/internal/dynamic_annotations.h" // IWYU pragma: export
+
+// -------------------------------------------------------------------------
+// Decide which features are enabled
+
#ifndef DYNAMIC_ANNOTATIONS_ENABLED
-# define DYNAMIC_ANNOTATIONS_ENABLED 0
+#define DYNAMIC_ANNOTATIONS_ENABLED 0
+#endif
+
+#if defined(__clang__) && !defined(SWIG)
+#define ABSL_INTERNAL_IGNORE_READS_ATTRIBUTE_ENABLED 1
+#else
+#define ABSL_INTERNAL_IGNORE_READS_ATTRIBUTE_ENABLED 0
#endif
#if DYNAMIC_ANNOTATIONS_ENABLED != 0
- /* -------------------------------------------------------------
- Annotations that suppress errors. It is usually better to express the
- program's synchronization using the other annotations, but these can
- be used when all else fails. */
-
- /* Report that we may have a benign race at "pointer", with size
- "sizeof(*(pointer))". "pointer" must be a non-void* pointer. Insert at the
- point where "pointer" has been allocated, preferably close to the point
- where the race happens. See also ANNOTATE_BENIGN_RACE_STATIC. */
- #define ANNOTATE_BENIGN_RACE(pointer, description) \
- AnnotateBenignRaceSized(__FILE__, __LINE__, pointer, \
- sizeof(*(pointer)), description)
-
- /* Same as ANNOTATE_BENIGN_RACE(address, description), but applies to
- the memory range [address, address+size). */
- #define ANNOTATE_BENIGN_RACE_SIZED(address, size, description) \
- AnnotateBenignRaceSized(__FILE__, __LINE__, address, size, description)
-
- /* Enable (enable!=0) or disable (enable==0) race detection for all threads.
- This annotation could be useful if you want to skip expensive race analysis
- during some period of program execution, e.g. during initialization. */
- #define ANNOTATE_ENABLE_RACE_DETECTION(enable) \
- AnnotateEnableRaceDetection(__FILE__, __LINE__, enable)
-
- /* -------------------------------------------------------------
- Annotations useful for debugging. */
-
- /* Report the current thread name to a race detector. */
- #define ANNOTATE_THREAD_NAME(name) \
- AnnotateThreadName(__FILE__, __LINE__, name)
-
- /* -------------------------------------------------------------
- Annotations useful when implementing locks. They are not
- normally needed by modules that merely use locks.
- The "lock" argument is a pointer to the lock object. */
-
- /* Report that a lock has been created at address "lock". */
- #define ANNOTATE_RWLOCK_CREATE(lock) \
- AnnotateRWLockCreate(__FILE__, __LINE__, lock)
-
- /* Report that a linker initialized lock has been created at address "lock".
- */
-#ifdef THREAD_SANITIZER
- #define ANNOTATE_RWLOCK_CREATE_STATIC(lock) \
- AnnotateRWLockCreateStatic(__FILE__, __LINE__, lock)
+#define ABSL_INTERNAL_RACE_ANNOTATIONS_ENABLED 1
+#define ABSL_INTERNAL_READS_ANNOTATIONS_ENABLED 1
+#define ABSL_INTERNAL_WRITES_ANNOTATIONS_ENABLED 1
+#define ABSL_INTERNAL_ANNOTALYSIS_ENABLED 0
+#define ABSL_INTERNAL_READS_WRITES_ANNOTATIONS_ENABLED 1
+
+#else
+
+#define ABSL_INTERNAL_RACE_ANNOTATIONS_ENABLED 0
+#define ABSL_INTERNAL_READS_ANNOTATIONS_ENABLED 0
+#define ABSL_INTERNAL_WRITES_ANNOTATIONS_ENABLED 0
+
+// Clang provides limited support for static thread-safety analysis through a
+// feature called Annotalysis. We configure macro-definitions according to
+// whether Annotalysis support is available. When running in opt-mode, GCC
+// will issue a warning, if these attributes are compiled. Only include them
+// when compiling using Clang.
+
+// ANNOTALYSIS_ENABLED == 1 when IGNORE_READ_ATTRIBUTE_ENABLED == 1
+#define ABSL_INTERNAL_ANNOTALYSIS_ENABLED \
+ ABSL_INTERNAL_IGNORE_READS_ATTRIBUTE_ENABLED
+// Read/write annotations are enabled in Annotalysis mode; disabled otherwise.
+#define ABSL_INTERNAL_READS_WRITES_ANNOTATIONS_ENABLED \
+ ABSL_INTERNAL_ANNOTALYSIS_ENABLED
+#endif
+
+// Memory annotations are also made available to LLVM's Memory Sanitizer
+#if defined(MEMORY_SANITIZER) && defined(__has_feature) && \
+ !defined(__native_client__)
+#if __has_feature(memory_sanitizer)
+#define ABSL_INTERNAL_MEMORY_ANNOTATIONS_ENABLED 1
+#endif
+#endif
+
+#ifndef ABSL_INTERNAL_MEMORY_ANNOTATIONS_ENABLED
+#define ABSL_INTERNAL_MEMORY_ANNOTATIONS_ENABLED 0
+#endif
+
+#ifdef __cplusplus
+#define ABSL_INTERNAL_BEGIN_EXTERN_C extern "C" {
+#define ABSL_INTERNAL_END_EXTERN_C } // extern "C"
+#define ABSL_INTERNAL_GLOBAL_SCOPED(F) ::F
+#define ABSL_INTERNAL_STATIC_INLINE inline
#else
- #define ANNOTATE_RWLOCK_CREATE_STATIC(lock) ANNOTATE_RWLOCK_CREATE(lock)
+#define ABSL_INTERNAL_BEGIN_EXTERN_C // empty
+#define ABSL_INTERNAL_END_EXTERN_C // empty
+#define ABSL_INTERNAL_GLOBAL_SCOPED(F) F
+#define ABSL_INTERNAL_STATIC_INLINE static inline
#endif
- /* Report that the lock at address "lock" is about to be destroyed. */
- #define ANNOTATE_RWLOCK_DESTROY(lock) \
- AnnotateRWLockDestroy(__FILE__, __LINE__, lock)
+// -------------------------------------------------------------------------
+// Define race annotations.
+
+#if ABSL_INTERNAL_RACE_ANNOTATIONS_ENABLED == 1
+
+// -------------------------------------------------------------
+// Annotations that suppress errors. It is usually better to express the
+// program's synchronization using the other annotations, but these can be used
+// when all else fails.
+
+// Report that we may have a benign race at `pointer`, with size
+// "sizeof(*(pointer))". `pointer` must be a non-void* pointer. Insert at the
+// point where `pointer` has been allocated, preferably close to the point
+// where the race happens. See also ABSL_ANNOTATE_BENIGN_RACE_STATIC.
+#define ABSL_ANNOTATE_BENIGN_RACE(pointer, description) \
+ ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateBenignRaceSized) \
+ (__FILE__, __LINE__, pointer, sizeof(*(pointer)), description)
+
+// Same as ABSL_ANNOTATE_BENIGN_RACE(`address`, `description`), but applies to
+// the memory range [`address`, `address`+`size`).
+#define ABSL_ANNOTATE_BENIGN_RACE_SIZED(address, size, description) \
+ ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateBenignRaceSized) \
+ (__FILE__, __LINE__, address, size, description)
+
+// Enable (`enable`!=0) or disable (`enable`==0) race detection for all threads.
+// This annotation could be useful if you want to skip expensive race analysis
+// during some period of program execution, e.g. during initialization.
+#define ABSL_ANNOTATE_ENABLE_RACE_DETECTION(enable) \
+ ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateEnableRaceDetection) \
+ (__FILE__, __LINE__, enable)
+
+// -------------------------------------------------------------
+// Annotations useful for debugging.
+
+// Report the current thread `name` to a race detector.
+#define ABSL_ANNOTATE_THREAD_NAME(name) \
+ ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateThreadName)(__FILE__, __LINE__, name)
+
+// -------------------------------------------------------------
+// Annotations useful when implementing locks. They are not normally needed by
+// modules that merely use locks. The `lock` argument is a pointer to the lock
+// object.
+
+// Report that a lock has been created at address `lock`.
+#define ABSL_ANNOTATE_RWLOCK_CREATE(lock) \
+ ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateRWLockCreate)(__FILE__, __LINE__, lock)
+
+// Report that a linker initialized lock has been created at address `lock`.
+#ifdef THREAD_SANITIZER
+#define ABSL_ANNOTATE_RWLOCK_CREATE_STATIC(lock) \
+ ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateRWLockCreateStatic) \
+ (__FILE__, __LINE__, lock)
+#else
+#define ABSL_ANNOTATE_RWLOCK_CREATE_STATIC(lock) \
+ ABSL_ANNOTATE_RWLOCK_CREATE(lock)
+#endif
- /* Report that the lock at address "lock" has been acquired.
- is_w=1 for writer lock, is_w=0 for reader lock. */
- #define ANNOTATE_RWLOCK_ACQUIRED(lock, is_w) \
- AnnotateRWLockAcquired(__FILE__, __LINE__, lock, is_w)
+// Report that the lock at address `lock` is about to be destroyed.
+#define ABSL_ANNOTATE_RWLOCK_DESTROY(lock) \
+ ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateRWLockDestroy)(__FILE__, __LINE__, lock)
+
+// Report that the lock at address `lock` has been acquired.
+// `is_w`=1 for writer lock, `is_w`=0 for reader lock.
+#define ABSL_ANNOTATE_RWLOCK_ACQUIRED(lock, is_w) \
+ ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateRWLockAcquired) \
+ (__FILE__, __LINE__, lock, is_w)
+
+// Report that the lock at address `lock` is about to be released.
+// `is_w`=1 for writer lock, `is_w`=0 for reader lock.
+#define ABSL_ANNOTATE_RWLOCK_RELEASED(lock, is_w) \
+ ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateRWLockReleased) \
+ (__FILE__, __LINE__, lock, is_w)
+
+// Apply ABSL_ANNOTATE_BENIGN_RACE_SIZED to a static variable `static_var`.
+#define ABSL_ANNOTATE_BENIGN_RACE_STATIC(static_var, description) \
+ namespace { \
+ class static_var##_annotator { \
+ public: \
+ static_var##_annotator() { \
+ ABSL_ANNOTATE_BENIGN_RACE_SIZED(&static_var, sizeof(static_var), \
+ #static_var ": " description); \
+ } \
+ }; \
+ static static_var##_annotator the##static_var##_annotator; \
+ } // namespace
+
+// Function prototypes of annotations provided by the compiler-based sanitizer
+// implementation.
+ABSL_INTERNAL_BEGIN_EXTERN_C
+void AnnotateRWLockCreate(const char* file, int line,
+ const volatile void* lock);
+void AnnotateRWLockCreateStatic(const char* file, int line,
+ const volatile void* lock);
+void AnnotateRWLockDestroy(const char* file, int line,
+ const volatile void* lock);
+void AnnotateRWLockAcquired(const char* file, int line,
+ const volatile void* lock, long is_w); // NOLINT
+void AnnotateRWLockReleased(const char* file, int line,
+ const volatile void* lock, long is_w); // NOLINT
+void AnnotateBenignRace(const char* file, int line,
+ const volatile void* address, const char* description);
+void AnnotateBenignRaceSized(const char* file, int line,
+ const volatile void* address, size_t size,
+ const char* description);
+void AnnotateThreadName(const char* file, int line, const char* name);
+void AnnotateEnableRaceDetection(const char* file, int line, int enable);
+ABSL_INTERNAL_END_EXTERN_C
+
+#else // ABSL_INTERNAL_RACE_ANNOTATIONS_ENABLED == 0
+
+#define ABSL_ANNOTATE_RWLOCK_CREATE(lock) // empty
+#define ABSL_ANNOTATE_RWLOCK_CREATE_STATIC(lock) // empty
+#define ABSL_ANNOTATE_RWLOCK_DESTROY(lock) // empty
+#define ABSL_ANNOTATE_RWLOCK_ACQUIRED(lock, is_w) // empty
+#define ABSL_ANNOTATE_RWLOCK_RELEASED(lock, is_w) // empty
+#define ABSL_ANNOTATE_BENIGN_RACE(address, description) // empty
+#define ABSL_ANNOTATE_BENIGN_RACE_SIZED(address, size, description) // empty
+#define ABSL_ANNOTATE_THREAD_NAME(name) // empty
+#define ABSL_ANNOTATE_ENABLE_RACE_DETECTION(enable) // empty
+#define ABSL_ANNOTATE_BENIGN_RACE_STATIC(static_var, description) // empty
+
+#endif // ABSL_INTERNAL_RACE_ANNOTATIONS_ENABLED
+
+// -------------------------------------------------------------------------
+// Define memory annotations.
+
+#if ABSL_INTERNAL_MEMORY_ANNOTATIONS_ENABLED == 1
+
+#include <sanitizer/msan_interface.h>
+
+#define ABSL_ANNOTATE_MEMORY_IS_INITIALIZED(address, size) \
+ __msan_unpoison(address, size)
+
+#define ABSL_ANNOTATE_MEMORY_IS_UNINITIALIZED(address, size) \
+ __msan_allocated_memory(address, size)
+
+#else // ABSL_INTERNAL_MEMORY_ANNOTATIONS_ENABLED == 0
+
+#if DYNAMIC_ANNOTATIONS_ENABLED == 1
+#define ABSL_ANNOTATE_MEMORY_IS_INITIALIZED(address, size) \
+ do { \
+ (void)(address); \
+ (void)(size); \
+ } while (0)
+#define ABSL_ANNOTATE_MEMORY_IS_UNINITIALIZED(address, size) \
+ do { \
+ (void)(address); \
+ (void)(size); \
+ } while (0)
+#else
- /* Report that the lock at address "lock" is about to be released. */
- #define ANNOTATE_RWLOCK_RELEASED(lock, is_w) \
- AnnotateRWLockReleased(__FILE__, __LINE__, lock, is_w)
+#define ABSL_ANNOTATE_MEMORY_IS_INITIALIZED(address, size) // empty
+#define ABSL_ANNOTATE_MEMORY_IS_UNINITIALIZED(address, size) // empty
-#else /* DYNAMIC_ANNOTATIONS_ENABLED == 0 */
+#endif
- #define ANNOTATE_RWLOCK_CREATE(lock) /* empty */
- #define ANNOTATE_RWLOCK_CREATE_STATIC(lock) /* empty */
- #define ANNOTATE_RWLOCK_DESTROY(lock) /* empty */
- #define ANNOTATE_RWLOCK_ACQUIRED(lock, is_w) /* empty */
- #define ANNOTATE_RWLOCK_RELEASED(lock, is_w) /* empty */
- #define ANNOTATE_BENIGN_RACE(address, description) /* empty */
- #define ANNOTATE_BENIGN_RACE_SIZED(address, size, description) /* empty */
- #define ANNOTATE_THREAD_NAME(name) /* empty */
- #define ANNOTATE_ENABLE_RACE_DETECTION(enable) /* empty */
+#endif // ABSL_INTERNAL_MEMORY_ANNOTATIONS_ENABLED
-#endif /* DYNAMIC_ANNOTATIONS_ENABLED */
+// -------------------------------------------------------------------------
+// Define IGNORE_READS_BEGIN/_END attributes.
-/* These annotations are also made available to LLVM's Memory Sanitizer */
-#if DYNAMIC_ANNOTATIONS_ENABLED == 1 || defined(MEMORY_SANITIZER)
- #define ANNOTATE_MEMORY_IS_INITIALIZED(address, size) \
- AnnotateMemoryIsInitialized(__FILE__, __LINE__, address, size)
+#if ABSL_INTERNAL_IGNORE_READS_ATTRIBUTE_ENABLED == 1
- #define ANNOTATE_MEMORY_IS_UNINITIALIZED(address, size) \
- AnnotateMemoryIsUninitialized(__FILE__, __LINE__, address, size)
-#else
- #define ANNOTATE_MEMORY_IS_INITIALIZED(address, size) /* empty */
- #define ANNOTATE_MEMORY_IS_UNINITIALIZED(address, size) /* empty */
-#endif /* DYNAMIC_ANNOTATIONS_ENABLED || MEMORY_SANITIZER */
+#define ABSL_INTERNAL_IGNORE_READS_BEGIN_ATTRIBUTE \
+ __attribute((exclusive_lock_function("*")))
+#define ABSL_INTERNAL_IGNORE_READS_END_ATTRIBUTE \
+ __attribute((unlock_function("*")))
-#if defined(__clang__) && !defined(SWIG)
+#else // ABSL_INTERNAL_IGNORE_READS_ATTRIBUTE_ENABLED == 0
- #if DYNAMIC_ANNOTATIONS_ENABLED == 0
- #define ANNOTALYSIS_ENABLED
- #endif
+#define ABSL_INTERNAL_IGNORE_READS_BEGIN_ATTRIBUTE // empty
+#define ABSL_INTERNAL_IGNORE_READS_END_ATTRIBUTE // empty
- /* When running in opt-mode, GCC will issue a warning, if these attributes are
- compiled. Only include them when compiling using Clang. */
- #define ATTRIBUTE_IGNORE_READS_BEGIN \
- __attribute((exclusive_lock_function("*")))
- #define ATTRIBUTE_IGNORE_READS_END \
- __attribute((unlock_function("*")))
-#else
- #define ATTRIBUTE_IGNORE_READS_BEGIN /* empty */
- #define ATTRIBUTE_IGNORE_READS_END /* empty */
-#endif /* defined(__clang__) && ... */
+#endif // ABSL_INTERNAL_IGNORE_READS_ATTRIBUTE_ENABLED
-#if (DYNAMIC_ANNOTATIONS_ENABLED != 0) || defined(ANNOTALYSIS_ENABLED)
- #define ANNOTATIONS_ENABLED
-#endif
+// -------------------------------------------------------------------------
+// Define IGNORE_READS_BEGIN/_END annotations.
-#if (DYNAMIC_ANNOTATIONS_ENABLED != 0)
+#if ABSL_INTERNAL_READS_ANNOTATIONS_ENABLED == 1
- /* Request the analysis tool to ignore all reads in the current thread
- until ANNOTATE_IGNORE_READS_END is called.
- Useful to ignore intentional racey reads, while still checking
- other reads and all writes.
- See also ANNOTATE_UNPROTECTED_READ. */
- #define ANNOTATE_IGNORE_READS_BEGIN() \
- AnnotateIgnoreReadsBegin(__FILE__, __LINE__)
+// Request the analysis tool to ignore all reads in the current thread until
+// ABSL_ANNOTATE_IGNORE_READS_END is called. Useful to ignore intentional racey
+// reads, while still checking other reads and all writes.
+// See also ABSL_ANNOTATE_UNPROTECTED_READ.
+#define ABSL_ANNOTATE_IGNORE_READS_BEGIN() \
+ ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateIgnoreReadsBegin)(__FILE__, __LINE__)
- /* Stop ignoring reads. */
- #define ANNOTATE_IGNORE_READS_END() \
- AnnotateIgnoreReadsEnd(__FILE__, __LINE__)
+// Stop ignoring reads.
+#define ABSL_ANNOTATE_IGNORE_READS_END() \
+ ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateIgnoreReadsEnd)(__FILE__, __LINE__)
- /* Similar to ANNOTATE_IGNORE_READS_BEGIN, but ignore writes instead. */
- #define ANNOTATE_IGNORE_WRITES_BEGIN() \
- AnnotateIgnoreWritesBegin(__FILE__, __LINE__)
+// Function prototypes of annotations provided by the compiler-based sanitizer
+// implementation.
+ABSL_INTERNAL_BEGIN_EXTERN_C
+void AnnotateIgnoreReadsBegin(const char* file, int line)
+ ABSL_INTERNAL_IGNORE_READS_BEGIN_ATTRIBUTE;
+void AnnotateIgnoreReadsEnd(const char* file,
+ int line) ABSL_INTERNAL_IGNORE_READS_END_ATTRIBUTE;
+ABSL_INTERNAL_END_EXTERN_C
- /* Stop ignoring writes. */
- #define ANNOTATE_IGNORE_WRITES_END() \
- AnnotateIgnoreWritesEnd(__FILE__, __LINE__)
+#elif defined(ABSL_INTERNAL_ANNOTALYSIS_ENABLED)
-/* Clang provides limited support for static thread-safety analysis
- through a feature called Annotalysis. We configure macro-definitions
- according to whether Annotalysis support is available. */
-#elif defined(ANNOTALYSIS_ENABLED)
+// When Annotalysis is enabled without Dynamic Annotations, the use of
+// static-inline functions allows the annotations to be read at compile-time,
+// while still letting the compiler elide the functions from the final build.
+//
+// TODO(delesley) -- The exclusive lock here ignores writes as well, but
+// allows IGNORE_READS_AND_WRITES to work properly.
- #define ANNOTATE_IGNORE_READS_BEGIN() \
- StaticAnnotateIgnoreReadsBegin(__FILE__, __LINE__)
+#define ABSL_ANNOTATE_IGNORE_READS_BEGIN() \
+ ABSL_INTERNAL_GLOBAL_SCOPED(AbslInternalAnnotateIgnoreReadsBegin)()
- #define ANNOTATE_IGNORE_READS_END() \
- StaticAnnotateIgnoreReadsEnd(__FILE__, __LINE__)
+#define ABSL_ANNOTATE_IGNORE_READS_END() \
+ ABSL_INTERNAL_GLOBAL_SCOPED(AbslInternalAnnotateIgnoreReadsEnd)()
- #define ANNOTATE_IGNORE_WRITES_BEGIN() \
- StaticAnnotateIgnoreWritesBegin(__FILE__, __LINE__)
+ABSL_INTERNAL_STATIC_INLINE void AbslInternalAnnotateIgnoreReadsBegin()
+ ABSL_INTERNAL_IGNORE_READS_BEGIN_ATTRIBUTE {}
- #define ANNOTATE_IGNORE_WRITES_END() \
- StaticAnnotateIgnoreWritesEnd(__FILE__, __LINE__)
+ABSL_INTERNAL_STATIC_INLINE void AbslInternalAnnotateIgnoreReadsEnd()
+ ABSL_INTERNAL_IGNORE_READS_END_ATTRIBUTE {}
#else
- #define ANNOTATE_IGNORE_READS_BEGIN() /* empty */
- #define ANNOTATE_IGNORE_READS_END() /* empty */
- #define ANNOTATE_IGNORE_WRITES_BEGIN() /* empty */
- #define ANNOTATE_IGNORE_WRITES_END() /* empty */
+
+#define ABSL_ANNOTATE_IGNORE_READS_BEGIN() // empty
+#define ABSL_ANNOTATE_IGNORE_READS_END() // empty
+
#endif
-/* Implement the ANNOTATE_IGNORE_READS_AND_WRITES_* annotations using the more
- primitive annotations defined above. */
-#if defined(ANNOTATIONS_ENABLED)
+// -------------------------------------------------------------------------
+// Define IGNORE_WRITES_BEGIN/_END annotations.
+
+#if ABSL_INTERNAL_WRITES_ANNOTATIONS_ENABLED == 1
+
+// Similar to ABSL_ANNOTATE_IGNORE_READS_BEGIN, but ignore writes instead.
+#define ABSL_ANNOTATE_IGNORE_WRITES_BEGIN() \
+ ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateIgnoreWritesBegin)(__FILE__, __LINE__)
- /* Start ignoring all memory accesses (both reads and writes). */
- #define ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN() \
- do { \
- ANNOTATE_IGNORE_READS_BEGIN(); \
- ANNOTATE_IGNORE_WRITES_BEGIN(); \
- }while (0)
+// Stop ignoring writes.
+#define ABSL_ANNOTATE_IGNORE_WRITES_END() \
+ ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateIgnoreWritesEnd)(__FILE__, __LINE__)
- /* Stop ignoring both reads and writes. */
- #define ANNOTATE_IGNORE_READS_AND_WRITES_END() \
- do { \
- ANNOTATE_IGNORE_WRITES_END(); \
- ANNOTATE_IGNORE_READS_END(); \
- }while (0)
+// Function prototypes of annotations provided by the compiler-based sanitizer
+// implementation.
+ABSL_INTERNAL_BEGIN_EXTERN_C
+void AnnotateIgnoreWritesBegin(const char* file, int line);
+void AnnotateIgnoreWritesEnd(const char* file, int line);
+ABSL_INTERNAL_END_EXTERN_C
#else
- #define ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN() /* empty */
- #define ANNOTATE_IGNORE_READS_AND_WRITES_END() /* empty */
-#endif
-/* Use the macros above rather than using these functions directly. */
-#include <stddef.h>
-#ifdef __cplusplus
-extern "C" {
-#endif
-void AnnotateRWLockCreate(const char *file, int line,
- const volatile void *lock);
-void AnnotateRWLockCreateStatic(const char *file, int line,
- const volatile void *lock);
-void AnnotateRWLockDestroy(const char *file, int line,
- const volatile void *lock);
-void AnnotateRWLockAcquired(const char *file, int line,
- const volatile void *lock, long is_w); /* NOLINT */
-void AnnotateRWLockReleased(const char *file, int line,
- const volatile void *lock, long is_w); /* NOLINT */
-void AnnotateBenignRace(const char *file, int line,
- const volatile void *address,
- const char *description);
-void AnnotateBenignRaceSized(const char *file, int line,
- const volatile void *address,
- size_t size,
- const char *description);
-void AnnotateThreadName(const char *file, int line,
- const char *name);
-void AnnotateEnableRaceDetection(const char *file, int line, int enable);
-void AnnotateMemoryIsInitialized(const char *file, int line,
- const volatile void *mem, size_t size);
-void AnnotateMemoryIsUninitialized(const char *file, int line,
- const volatile void *mem, size_t size);
-
-/* Annotations expand to these functions, when Dynamic Annotations are enabled.
- These functions are either implemented as no-op calls, if no Sanitizer is
- attached, or provided with externally-linked implementations by a library
- like ThreadSanitizer. */
-void AnnotateIgnoreReadsBegin(const char *file, int line)
- ATTRIBUTE_IGNORE_READS_BEGIN;
-void AnnotateIgnoreReadsEnd(const char *file, int line)
- ATTRIBUTE_IGNORE_READS_END;
-void AnnotateIgnoreWritesBegin(const char *file, int line);
-void AnnotateIgnoreWritesEnd(const char *file, int line);
-
-#if defined(ANNOTALYSIS_ENABLED)
-/* When Annotalysis is enabled without Dynamic Annotations, the use of
- static-inline functions allows the annotations to be read at compile-time,
- while still letting the compiler elide the functions from the final build.
-
- TODO(delesley) -- The exclusive lock here ignores writes as well, but
- allows IGNORE_READS_AND_WRITES to work properly. */
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wunused-function"
-static inline void StaticAnnotateIgnoreReadsBegin(const char *file, int line)
- ATTRIBUTE_IGNORE_READS_BEGIN { (void)file; (void)line; }
-static inline void StaticAnnotateIgnoreReadsEnd(const char *file, int line)
- ATTRIBUTE_IGNORE_READS_END { (void)file; (void)line; }
-static inline void StaticAnnotateIgnoreWritesBegin(
- const char *file, int line) { (void)file; (void)line; }
-static inline void StaticAnnotateIgnoreWritesEnd(
- const char *file, int line) { (void)file; (void)line; }
-#pragma GCC diagnostic pop
-#endif
+#define ABSL_ANNOTATE_IGNORE_WRITES_BEGIN() // empty
+#define ABSL_ANNOTATE_IGNORE_WRITES_END() // empty
-/* Return non-zero value if running under valgrind.
-
- If "valgrind.h" is included into dynamic_annotations.cc,
- the regular valgrind mechanism will be used.
- See http://valgrind.org/docs/manual/manual-core-adv.html about
- RUNNING_ON_VALGRIND and other valgrind "client requests".
- The file "valgrind.h" may be obtained by doing
- svn co svn://svn.valgrind.org/valgrind/trunk/include
-
- If for some reason you can't use "valgrind.h" or want to fake valgrind,
- there are two ways to make this function return non-zero:
- - Use environment variable: export RUNNING_ON_VALGRIND=1
- - Make your tool intercept the function RunningOnValgrind() and
- change its return value.
- */
-int RunningOnValgrind(void);
+#endif
-/* ValgrindSlowdown returns:
- * 1.0, if (RunningOnValgrind() == 0)
- * 50.0, if (RunningOnValgrind() != 0 && getenv("VALGRIND_SLOWDOWN") == NULL)
- * atof(getenv("VALGRIND_SLOWDOWN")) otherwise
- This function can be used to scale timeout values:
- EXAMPLE:
- for (;;) {
- DoExpensiveBackgroundTask();
- SleepForSeconds(5 * ValgrindSlowdown());
- }
- */
-double ValgrindSlowdown(void);
+// -------------------------------------------------------------------------
+// Define the ABSL_ANNOTATE_IGNORE_READS_AND_WRITES_* annotations using the more
+// primitive annotations defined above.
+//
+// Instead of doing
+// ABSL_ANNOTATE_IGNORE_READS_BEGIN();
+// ... = x;
+// ABSL_ANNOTATE_IGNORE_READS_END();
+// one can use
+// ... = ABSL_ANNOTATE_UNPROTECTED_READ(x);
+
+#if defined(ABSL_INTERNAL_READS_WRITES_ANNOTATIONS_ENABLED)
+
+// Start ignoring all memory accesses (both reads and writes).
+#define ABSL_ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN() \
+ do { \
+ ABSL_ANNOTATE_IGNORE_READS_BEGIN(); \
+ ABSL_ANNOTATE_IGNORE_WRITES_BEGIN(); \
+ } while (0)
+
+// Stop ignoring both reads and writes.
+#define ABSL_ANNOTATE_IGNORE_READS_AND_WRITES_END() \
+ do { \
+ ABSL_ANNOTATE_IGNORE_WRITES_END(); \
+ ABSL_ANNOTATE_IGNORE_READS_END(); \
+ } while (0)
#ifdef __cplusplus
-}
-#endif
+// ABSL_ANNOTATE_UNPROTECTED_READ is the preferred way to annotate racey reads.
+#define ABSL_ANNOTATE_UNPROTECTED_READ(x) \
+ absl::base_internal::AnnotateUnprotectedRead(x)
-/* ANNOTATE_UNPROTECTED_READ is the preferred way to annotate racey reads.
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace base_internal {
- Instead of doing
- ANNOTATE_IGNORE_READS_BEGIN();
- ... = x;
- ANNOTATE_IGNORE_READS_END();
- one can use
- ... = ANNOTATE_UNPROTECTED_READ(x); */
-#if defined(__cplusplus) && defined(ANNOTATIONS_ENABLED)
template <typename T>
-inline T ANNOTATE_UNPROTECTED_READ(const volatile T &x) { /* NOLINT */
- ANNOTATE_IGNORE_READS_BEGIN();
+inline T AnnotateUnprotectedRead(const volatile T& x) { // NOLINT
+ ABSL_ANNOTATE_IGNORE_READS_BEGIN();
T res = x;
- ANNOTATE_IGNORE_READS_END();
+ ABSL_ANNOTATE_IGNORE_READS_END();
return res;
- }
+}
+
+} // namespace base_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+#endif
+
#else
- #define ANNOTATE_UNPROTECTED_READ(x) (x)
+
+#define ABSL_ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN() // empty
+#define ABSL_ANNOTATE_IGNORE_READS_AND_WRITES_END() // empty
+#define ABSL_ANNOTATE_UNPROTECTED_READ(x) (x)
+
#endif
-#if DYNAMIC_ANNOTATIONS_ENABLED != 0 && defined(__cplusplus)
- /* Apply ANNOTATE_BENIGN_RACE_SIZED to a static variable. */
- #define ANNOTATE_BENIGN_RACE_STATIC(static_var, description) \
- namespace { \
- class static_var ## _annotator { \
- public: \
- static_var ## _annotator() { \
- ANNOTATE_BENIGN_RACE_SIZED(&static_var, \
- sizeof(static_var), \
- # static_var ": " description); \
- } \
- }; \
- static static_var ## _annotator the ## static_var ## _annotator;\
- } // namespace
-#else /* DYNAMIC_ANNOTATIONS_ENABLED == 0 */
- #define ANNOTATE_BENIGN_RACE_STATIC(static_var, description) /* empty */
-#endif /* DYNAMIC_ANNOTATIONS_ENABLED */
+ABSL_INTERNAL_BEGIN_EXTERN_C
+
+// -------------------------------------------------------------------------
+// Return non-zero value if running under valgrind.
+//
+// If "valgrind.h" is included into dynamic_annotations.cc,
+// the regular valgrind mechanism will be used.
+// See http://valgrind.org/docs/manual/manual-core-adv.html about
+// RUNNING_ON_VALGRIND and other valgrind "client requests".
+// The file "valgrind.h" may be obtained by doing
+// svn co svn://svn.valgrind.org/valgrind/trunk/include
+//
+// If for some reason you can't use "valgrind.h" or want to fake valgrind,
+// there are two ways to make this function return non-zero:
+// - Use environment variable: export RUNNING_ON_VALGRIND=1
+// - Make your tool intercept the function RunningOnValgrind() and
+// change its return value.
+//
+int RunningOnValgrind(void);
+
+// ValgrindSlowdown returns:
+// * 1.0, if (RunningOnValgrind() == 0)
+// * 50.0, if (RunningOnValgrind() != 0 && getenv("VALGRIND_SLOWDOWN") ==
+// NULL)
+// * atof(getenv("VALGRIND_SLOWDOWN")) otherwise
+// This function can be used to scale timeout values:
+// EXAMPLE:
+// for (;;) {
+// DoExpensiveBackgroundTask();
+// SleepForSeconds(5 * ValgrindSlowdown());
+// }
+//
+double ValgrindSlowdown(void);
+
+ABSL_INTERNAL_END_EXTERN_C
+
+// -------------------------------------------------------------------------
+// Address sanitizer annotations
#ifdef ADDRESS_SANITIZER
-/* Describe the current state of a contiguous container such as e.g.
- * std::vector or std::string. For more details see
- * sanitizer/common_interface_defs.h, which is provided by the compiler. */
+// Describe the current state of a contiguous container such as e.g.
+// std::vector or std::string. For more details see
+// sanitizer/common_interface_defs.h, which is provided by the compiler.
#include <sanitizer/common_interface_defs.h>
-#define ANNOTATE_CONTIGUOUS_CONTAINER(beg, end, old_mid, new_mid) \
+
+#define ABSL_ANNOTATE_CONTIGUOUS_CONTAINER(beg, end, old_mid, new_mid) \
__sanitizer_annotate_contiguous_container(beg, end, old_mid, new_mid)
-#define ADDRESS_SANITIZER_REDZONE(name) \
- struct { char x[8] __attribute__ ((aligned (8))); } name
+#define ABSL_ADDRESS_SANITIZER_REDZONE(name) \
+ struct { \
+ char x[8] __attribute__((aligned(8))); \
+ } name
+
#else
-#define ANNOTATE_CONTIGUOUS_CONTAINER(beg, end, old_mid, new_mid)
-#define ADDRESS_SANITIZER_REDZONE(name) static_assert(true, "")
+
+#define ABSL_ANNOTATE_CONTIGUOUS_CONTAINER(beg, end, old_mid, new_mid)
+#define ABSL_ADDRESS_SANITIZER_REDZONE(name) static_assert(true, "")
+
#endif // ADDRESS_SANITIZER
-/* Undefine the macros intended only in this file. */
-#undef ANNOTALYSIS_ENABLED
-#undef ANNOTATIONS_ENABLED
-#undef ATTRIBUTE_IGNORE_READS_BEGIN
-#undef ATTRIBUTE_IGNORE_READS_END
+// -------------------------------------------------------------------------
+// Undefine the macros intended only for this file.
+
+#undef ABSL_INTERNAL_RACE_ANNOTATIONS_ENABLED
+#undef ABSL_INTERNAL_MEMORY_ANNOTATIONS_ENABLED
+#undef ABSL_INTERNAL_READS_ANNOTATIONS_ENABLED
+#undef ABSL_INTERNAL_WRITES_ANNOTATIONS_ENABLED
+#undef ABSL_INTERNAL_ANNOTALYSIS_ENABLED
+#undef ABSL_INTERNAL_READS_WRITES_ANNOTATIONS_ENABLED
+#undef ABSL_INTERNAL_BEGIN_EXTERN_C
+#undef ABSL_INTERNAL_END_EXTERN_C
+#undef ABSL_INTERNAL_STATIC_INLINE
-#endif /* ABSL_BASE_DYNAMIC_ANNOTATIONS_H_ */
+#endif // ABSL_BASE_DYNAMIC_ANNOTATIONS_H_
diff --git a/absl/base/internal/dynamic_annotations.h b/absl/base/internal/dynamic_annotations.h
new file mode 100644
index 00000000..7d80f41c
--- /dev/null
+++ b/absl/base/internal/dynamic_annotations.h
@@ -0,0 +1,403 @@
+// Copyright 2017 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// This file defines dynamic annotations for use with dynamic analysis tool
+// such as valgrind, PIN, etc.
+//
+// Dynamic annotation is a source code annotation that affects the generated
+// code (that is, the annotation is not a comment). Each such annotation is
+// attached to a particular instruction and/or to a particular object (address)
+// in the program.
+//
+// The annotations that should be used by users are macros in all upper-case
+// (e.g., ANNOTATE_THREAD_NAME).
+//
+// Actual implementation of these macros may differ depending on the dynamic
+// analysis tool being used.
+//
+// This file supports the following configurations:
+// - Dynamic Annotations enabled (with static thread-safety warnings disabled).
+// In this case, macros expand to functions implemented by Thread Sanitizer,
+// when building with TSan. When not provided an external implementation,
+// dynamic_annotations.cc provides no-op implementations.
+//
+// - Static Clang thread-safety warnings enabled.
+// When building with a Clang compiler that supports thread-safety warnings,
+// a subset of annotations can be statically-checked at compile-time. We
+// expand these macros to static-inline functions that can be analyzed for
+// thread-safety, but afterwards elided when building the final binary.
+//
+// - All annotations are disabled.
+// If neither Dynamic Annotations nor Clang thread-safety warnings are
+// enabled, then all annotation-macros expand to empty.
+
+#ifndef ABSL_BASE_INTERNAL_DYNAMIC_ANNOTATIONS_H_
+#define ABSL_BASE_INTERNAL_DYNAMIC_ANNOTATIONS_H_
+
+#include <stddef.h>
+
+#include "absl/base/config.h"
+
+// -------------------------------------------------------------------------
+// Decide which features are enabled
+
+#ifndef DYNAMIC_ANNOTATIONS_ENABLED
+#define DYNAMIC_ANNOTATIONS_ENABLED 0
+#endif
+
+#if defined(__clang__) && !defined(SWIG)
+#define ABSL_INTERNAL_IGNORE_READS_ATTRIBUTE_ENABLED 1
+#else
+#define ABSL_INTERNAL_IGNORE_READS_ATTRIBUTE_ENABLED 0
+#endif
+
+#if DYNAMIC_ANNOTATIONS_ENABLED != 0
+
+#define ABSL_INTERNAL_RACE_ANNOTATIONS_ENABLED 1
+#define ABSL_INTERNAL_READS_ANNOTATIONS_ENABLED 1
+#define ABSL_INTERNAL_WRITES_ANNOTATIONS_ENABLED 1
+#define ABSL_INTERNAL_ANNOTALYSIS_ENABLED 0
+#define ABSL_INTERNAL_READS_WRITES_ANNOTATIONS_ENABLED 1
+
+#else
+
+#define ABSL_INTERNAL_RACE_ANNOTATIONS_ENABLED 0
+#define ABSL_INTERNAL_READS_ANNOTATIONS_ENABLED 0
+#define ABSL_INTERNAL_WRITES_ANNOTATIONS_ENABLED 0
+
+// Clang provides limited support for static thread-safety analysis through a
+// feature called Annotalysis. We configure macro-definitions according to
+// whether Annotalysis support is available. When running in opt-mode, GCC
+// will issue a warning, if these attributes are compiled. Only include them
+// when compiling using Clang.
+
+// ANNOTALYSIS_ENABLED == 1 when IGNORE_READ_ATTRIBUTE_ENABLED == 1
+#define ABSL_INTERNAL_ANNOTALYSIS_ENABLED \
+ ABSL_INTERNAL_IGNORE_READS_ATTRIBUTE_ENABLED
+// Read/write annotations are enabled in Annotalysis mode; disabled otherwise.
+#define ABSL_INTERNAL_READS_WRITES_ANNOTATIONS_ENABLED \
+ ABSL_INTERNAL_ANNOTALYSIS_ENABLED
+#endif
+
+// Memory annotations are also made available to LLVM's Memory Sanitizer
+#if defined(MEMORY_SANITIZER) && defined(__has_feature) && \
+ !defined(__native_client__)
+#if __has_feature(memory_sanitizer)
+#define ABSL_INTERNAL_MEMORY_ANNOTATIONS_ENABLED 1
+#endif
+#endif
+
+#ifndef ABSL_INTERNAL_MEMORY_ANNOTATIONS_ENABLED
+#define ABSL_INTERNAL_MEMORY_ANNOTATIONS_ENABLED 0
+#endif
+
+#ifdef __cplusplus
+#define ABSL_INTERNAL_BEGIN_EXTERN_C extern "C" {
+#define ABSL_INTERNAL_END_EXTERN_C } // extern "C"
+#define ABSL_INTERNAL_GLOBAL_SCOPED(F) ::F
+#define ABSL_INTERNAL_STATIC_INLINE inline
+#else
+#define ABSL_INTERNAL_BEGIN_EXTERN_C // empty
+#define ABSL_INTERNAL_END_EXTERN_C // empty
+#define ABSL_INTERNAL_GLOBAL_SCOPED(F) F
+#define ABSL_INTERNAL_STATIC_INLINE static inline
+#endif
+
+// -------------------------------------------------------------------------
+// Define race annotations.
+
+#if ABSL_INTERNAL_RACE_ANNOTATIONS_ENABLED == 1
+
+// -------------------------------------------------------------
+// Annotations that suppress errors. It is usually better to express the
+// program's synchronization using the other annotations, but these can be used
+// when all else fails.
+
+// Report that we may have a benign race at `pointer`, with size
+// "sizeof(*(pointer))". `pointer` must be a non-void* pointer. Insert at the
+// point where `pointer` has been allocated, preferably close to the point
+// where the race happens. See also ANNOTATE_BENIGN_RACE_STATIC.
+#define ANNOTATE_BENIGN_RACE(pointer, description) \
+ ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateBenignRaceSized) \
+ (__FILE__, __LINE__, pointer, sizeof(*(pointer)), description)
+
+// Same as ANNOTATE_BENIGN_RACE(`address`, `description`), but applies to
+// the memory range [`address`, `address`+`size`).
+#define ANNOTATE_BENIGN_RACE_SIZED(address, size, description) \
+ ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateBenignRaceSized) \
+ (__FILE__, __LINE__, address, size, description)
+
+// Enable (`enable`!=0) or disable (`enable`==0) race detection for all threads.
+// This annotation could be useful if you want to skip expensive race analysis
+// during some period of program execution, e.g. during initialization.
+#define ANNOTATE_ENABLE_RACE_DETECTION(enable) \
+ ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateEnableRaceDetection) \
+ (__FILE__, __LINE__, enable)
+
+// -------------------------------------------------------------
+// Annotations useful for debugging.
+
+// Report the current thread `name` to a race detector.
+#define ANNOTATE_THREAD_NAME(name) \
+ ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateThreadName)(__FILE__, __LINE__, name)
+
+// -------------------------------------------------------------
+// Annotations useful when implementing locks. They are not normally needed by
+// modules that merely use locks. The `lock` argument is a pointer to the lock
+// object.
+
+// Report that a lock has been created at address `lock`.
+#define ANNOTATE_RWLOCK_CREATE(lock) \
+ ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateRWLockCreate)(__FILE__, __LINE__, lock)
+
+// Report that a linker initialized lock has been created at address `lock`.
+#ifdef THREAD_SANITIZER
+#define ANNOTATE_RWLOCK_CREATE_STATIC(lock) \
+ ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateRWLockCreateStatic) \
+ (__FILE__, __LINE__, lock)
+#else
+#define ANNOTATE_RWLOCK_CREATE_STATIC(lock) ANNOTATE_RWLOCK_CREATE(lock)
+#endif
+
+// Report that the lock at address `lock` is about to be destroyed.
+#define ANNOTATE_RWLOCK_DESTROY(lock) \
+ ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateRWLockDestroy)(__FILE__, __LINE__, lock)
+
+// Report that the lock at address `lock` has been acquired.
+// `is_w`=1 for writer lock, `is_w`=0 for reader lock.
+#define ANNOTATE_RWLOCK_ACQUIRED(lock, is_w) \
+ ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateRWLockAcquired) \
+ (__FILE__, __LINE__, lock, is_w)
+
+// Report that the lock at address `lock` is about to be released.
+// `is_w`=1 for writer lock, `is_w`=0 for reader lock.
+#define ANNOTATE_RWLOCK_RELEASED(lock, is_w) \
+ ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateRWLockReleased) \
+ (__FILE__, __LINE__, lock, is_w)
+
+// Apply ANNOTATE_BENIGN_RACE_SIZED to a static variable `static_var`.
+#define ANNOTATE_BENIGN_RACE_STATIC(static_var, description) \
+ namespace { \
+ class static_var##_annotator { \
+ public: \
+ static_var##_annotator() { \
+ ANNOTATE_BENIGN_RACE_SIZED(&static_var, sizeof(static_var), \
+ #static_var ": " description); \
+ } \
+ }; \
+ static static_var##_annotator the##static_var##_annotator; \
+ } // namespace
+
+#else // ABSL_INTERNAL_RACE_ANNOTATIONS_ENABLED == 0
+
+#define ANNOTATE_RWLOCK_CREATE(lock) // empty
+#define ANNOTATE_RWLOCK_CREATE_STATIC(lock) // empty
+#define ANNOTATE_RWLOCK_DESTROY(lock) // empty
+#define ANNOTATE_RWLOCK_ACQUIRED(lock, is_w) // empty
+#define ANNOTATE_RWLOCK_RELEASED(lock, is_w) // empty
+#define ANNOTATE_BENIGN_RACE(address, description) // empty
+#define ANNOTATE_BENIGN_RACE_SIZED(address, size, description) // empty
+#define ANNOTATE_THREAD_NAME(name) // empty
+#define ANNOTATE_ENABLE_RACE_DETECTION(enable) // empty
+#define ANNOTATE_BENIGN_RACE_STATIC(static_var, description) // empty
+
+#endif // ABSL_INTERNAL_RACE_ANNOTATIONS_ENABLED
+
+// -------------------------------------------------------------------------
+// Define memory annotations.
+
+#if ABSL_INTERNAL_MEMORY_ANNOTATIONS_ENABLED == 1
+
+#include <sanitizer/msan_interface.h>
+
+#define ANNOTATE_MEMORY_IS_INITIALIZED(address, size) \
+ __msan_unpoison(address, size)
+
+#define ANNOTATE_MEMORY_IS_UNINITIALIZED(address, size) \
+ __msan_allocated_memory(address, size)
+
+#else // ABSL_INTERNAL_MEMORY_ANNOTATIONS_ENABLED == 0
+
+#if DYNAMIC_ANNOTATIONS_ENABLED == 1
+#define ANNOTATE_MEMORY_IS_INITIALIZED(address, size) \
+ do { \
+ (void)(address); \
+ (void)(size); \
+ } while (0)
+#define ANNOTATE_MEMORY_IS_UNINITIALIZED(address, size) \
+ do { \
+ (void)(address); \
+ (void)(size); \
+ } while (0)
+#else
+#define ANNOTATE_MEMORY_IS_INITIALIZED(address, size) // empty
+#define ANNOTATE_MEMORY_IS_UNINITIALIZED(address, size) // empty
+#endif
+
+#endif // ABSL_INTERNAL_MEMORY_ANNOTATIONS_ENABLED
+
+// -------------------------------------------------------------------------
+// Define IGNORE_READS_BEGIN/_END attributes.
+
+#if ABSL_INTERNAL_IGNORE_READS_ATTRIBUTE_ENABLED == 1
+
+#define ABSL_INTERNAL_IGNORE_READS_BEGIN_ATTRIBUTE \
+ __attribute((exclusive_lock_function("*")))
+#define ABSL_INTERNAL_IGNORE_READS_END_ATTRIBUTE \
+ __attribute((unlock_function("*")))
+
+#else // ABSL_INTERNAL_IGNORE_READS_ATTRIBUTE_ENABLED == 0
+
+#define ABSL_INTERNAL_IGNORE_READS_BEGIN_ATTRIBUTE // empty
+#define ABSL_INTERNAL_IGNORE_READS_END_ATTRIBUTE // empty
+
+#endif // ABSL_INTERNAL_IGNORE_READS_ATTRIBUTE_ENABLED
+
+// -------------------------------------------------------------------------
+// Define IGNORE_READS_BEGIN/_END annotations.
+
+#if ABSL_INTERNAL_READS_ANNOTATIONS_ENABLED == 1
+
+// Request the analysis tool to ignore all reads in the current thread until
+// ANNOTATE_IGNORE_READS_END is called. Useful to ignore intentional racey
+// reads, while still checking other reads and all writes.
+// See also ANNOTATE_UNPROTECTED_READ.
+#define ANNOTATE_IGNORE_READS_BEGIN() \
+ ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateIgnoreReadsBegin)(__FILE__, __LINE__)
+
+// Stop ignoring reads.
+#define ANNOTATE_IGNORE_READS_END() \
+ ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateIgnoreReadsEnd)(__FILE__, __LINE__)
+
+#elif defined(ABSL_INTERNAL_ANNOTALYSIS_ENABLED)
+
+// When Annotalysis is enabled without Dynamic Annotations, the use of
+// static-inline functions allows the annotations to be read at compile-time,
+// while still letting the compiler elide the functions from the final build.
+//
+// TODO(delesley) -- The exclusive lock here ignores writes as well, but
+// allows IGNORE_READS_AND_WRITES to work properly.
+
+#define ANNOTATE_IGNORE_READS_BEGIN() \
+ ABSL_INTERNAL_GLOBAL_SCOPED(AbslInternalAnnotateIgnoreReadsBegin)()
+
+#define ANNOTATE_IGNORE_READS_END() \
+ ABSL_INTERNAL_GLOBAL_SCOPED(AbslInternalAnnotateIgnoreReadsEnd)()
+
+#else
+
+#define ANNOTATE_IGNORE_READS_BEGIN() // empty
+#define ANNOTATE_IGNORE_READS_END() // empty
+
+#endif
+
+// -------------------------------------------------------------------------
+// Define IGNORE_WRITES_BEGIN/_END annotations.
+
+#if ABSL_INTERNAL_WRITES_ANNOTATIONS_ENABLED == 1
+
+// Similar to ANNOTATE_IGNORE_READS_BEGIN, but ignore writes instead.
+#define ANNOTATE_IGNORE_WRITES_BEGIN() \
+ ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateIgnoreWritesBegin)(__FILE__, __LINE__)
+
+// Stop ignoring writes.
+#define ANNOTATE_IGNORE_WRITES_END() \
+ ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateIgnoreWritesEnd)(__FILE__, __LINE__)
+
+#else
+
+#define ANNOTATE_IGNORE_WRITES_BEGIN() // empty
+#define ANNOTATE_IGNORE_WRITES_END() // empty
+
+#endif
+
+// -------------------------------------------------------------------------
+// Define the ANNOTATE_IGNORE_READS_AND_WRITES_* annotations using the more
+// primitive annotations defined above.
+//
+// Instead of doing
+// ANNOTATE_IGNORE_READS_BEGIN();
+// ... = x;
+// ANNOTATE_IGNORE_READS_END();
+// one can use
+// ... = ANNOTATE_UNPROTECTED_READ(x);
+
+#if defined(ABSL_INTERNAL_READS_WRITES_ANNOTATIONS_ENABLED)
+
+// Start ignoring all memory accesses (both reads and writes).
+#define ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN() \
+ do { \
+ ANNOTATE_IGNORE_READS_BEGIN(); \
+ ANNOTATE_IGNORE_WRITES_BEGIN(); \
+ } while (0)
+
+// Stop ignoring both reads and writes.
+#define ANNOTATE_IGNORE_READS_AND_WRITES_END() \
+ do { \
+ ANNOTATE_IGNORE_WRITES_END(); \
+ ANNOTATE_IGNORE_READS_END(); \
+ } while (0)
+
+#ifdef __cplusplus
+// ANNOTATE_UNPROTECTED_READ is the preferred way to annotate racey reads.
+#define ANNOTATE_UNPROTECTED_READ(x) \
+ absl::base_internal::AnnotateUnprotectedRead(x)
+
+#endif
+
+#else
+
+#define ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN() // empty
+#define ANNOTATE_IGNORE_READS_AND_WRITES_END() // empty
+#define ANNOTATE_UNPROTECTED_READ(x) (x)
+
+#endif
+
+// -------------------------------------------------------------------------
+// Address sanitizer annotations
+
+#ifdef ADDRESS_SANITIZER
+// Describe the current state of a contiguous container such as e.g.
+// std::vector or std::string. For more details see
+// sanitizer/common_interface_defs.h, which is provided by the compiler.
+#include <sanitizer/common_interface_defs.h>
+
+#define ANNOTATE_CONTIGUOUS_CONTAINER(beg, end, old_mid, new_mid) \
+ __sanitizer_annotate_contiguous_container(beg, end, old_mid, new_mid)
+#define ADDRESS_SANITIZER_REDZONE(name) \
+ struct { \
+ char x[8] __attribute__((aligned(8))); \
+ } name
+
+#else
+
+#define ANNOTATE_CONTIGUOUS_CONTAINER(beg, end, old_mid, new_mid)
+#define ADDRESS_SANITIZER_REDZONE(name) static_assert(true, "")
+
+#endif // ADDRESS_SANITIZER
+
+// -------------------------------------------------------------------------
+// Undefine the macros intended only for this file.
+
+#undef ABSL_INTERNAL_RACE_ANNOTATIONS_ENABLED
+#undef ABSL_INTERNAL_MEMORY_ANNOTATIONS_ENABLED
+#undef ABSL_INTERNAL_READS_ANNOTATIONS_ENABLED
+#undef ABSL_INTERNAL_WRITES_ANNOTATIONS_ENABLED
+#undef ABSL_INTERNAL_ANNOTALYSIS_ENABLED
+#undef ABSL_INTERNAL_READS_WRITES_ANNOTATIONS_ENABLED
+#undef ABSL_INTERNAL_BEGIN_EXTERN_C
+#undef ABSL_INTERNAL_END_EXTERN_C
+#undef ABSL_INTERNAL_STATIC_INLINE
+
+#endif // ABSL_BASE_INTERNAL_DYNAMIC_ANNOTATIONS_H_
diff --git a/absl/flags/BUILD.bazel b/absl/flags/BUILD.bazel
index 2d6f799e..6ffd07ce 100644
--- a/absl/flags/BUILD.bazel
+++ b/absl/flags/BUILD.bazel
@@ -114,9 +114,7 @@ cc_library(
visibility = ["//visibility:private"],
deps = [
"//absl/base:config",
- "//absl/base:core_headers",
"//absl/base:fast_type_id",
- "//absl/strings",
],
)
@@ -132,6 +130,9 @@ cc_library(
linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
":commandlineflag_internal",
+ "//absl/base:config",
+ "//absl/base:fast_type_id",
+ "//absl/strings",
"//absl/types:optional",
],
)
@@ -149,7 +150,12 @@ cc_library(
visibility = [
"//absl/flags:__pkg__",
],
- deps = [":commandlineflag"],
+ deps = [
+ ":commandlineflag",
+ ":commandlineflag_internal",
+ "//absl/base:config",
+ "//absl/strings",
+ ],
)
cc_library(
@@ -193,6 +199,7 @@ cc_library(
visibility = ["//absl/base:__subpackages__"],
deps = [
":commandlineflag",
+ ":commandlineflag_internal",
":config",
":marshalling",
":registry",
@@ -203,6 +210,7 @@ cc_library(
"//absl/meta:type_traits",
"//absl/strings",
"//absl/synchronization",
+ "//absl/utility",
],
)
@@ -220,7 +228,6 @@ cc_library(
deps = [
":config",
":flag_internal",
- ":marshalling",
":registry",
"//absl/base",
"//absl/base:config",
@@ -287,6 +294,7 @@ cc_library(
linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
":commandlineflag",
+ ":commandlineflag_internal",
":config",
":flag",
":flag_internal",
@@ -315,6 +323,7 @@ cc_test(
linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
":commandlineflag",
+ ":commandlineflag_internal",
":config",
":flag",
":private_handle_accessor",
@@ -352,6 +361,7 @@ cc_test(
":config",
":flag",
":flag_internal",
+ ":marshalling",
":registry",
"//absl/base:core_headers",
"//absl/base:malloc_internal",
@@ -372,6 +382,8 @@ cc_binary(
visibility = ["//visibility:private"],
deps = [
":flag",
+ ":marshalling",
+ "//absl/strings",
"//absl/time",
"//absl/types:optional",
"@com_github_google_benchmark//:benchmark_main",
@@ -450,8 +462,8 @@ cc_test(
copts = ABSL_TEST_COPTS,
linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
+ ":commandlineflag_internal",
":flag",
- ":marshalling",
":registry",
"//absl/memory",
"@com_google_googletest//:gtest_main",
@@ -492,7 +504,6 @@ cc_test(
":registry",
":usage",
":usage_internal",
- "//absl/memory",
"//absl/strings",
"@com_google_googletest//:gtest",
],
diff --git a/absl/flags/CMakeLists.txt b/absl/flags/CMakeLists.txt
index 6ecf3b48..2dc7cf45 100644
--- a/absl/flags/CMakeLists.txt
+++ b/absl/flags/CMakeLists.txt
@@ -103,9 +103,7 @@ absl_cc_library(
${ABSL_DEFAULT_LINKOPTS}
DEPS
absl::config
- absl::core_headers
absl::fast_type_id
- absl::strings
)
absl_cc_library(
@@ -120,8 +118,11 @@ absl_cc_library(
LINKOPTS
${ABSL_DEFAULT_LINKOPTS}
DEPS
+ absl::config
+ absl::fast_type_id
absl::flags_commandlineflag_internal
absl::optional
+ absl::strings
)
# Internal-only target, do not depend on directly.
@@ -137,7 +138,10 @@ absl_cc_library(
LINKOPTS
${ABSL_DEFAULT_LINKOPTS}
DEPS
+ absl::config
absl::flags_commandlineflag
+ absl::flags_commandlineflag_internal
+ absl::strings
)
# Internal-only target, do not depend on directly.
@@ -180,11 +184,13 @@ absl_cc_library(
DEPS
absl::base
absl::config
+ absl::flags_commandlineflag_internal
absl::flags_config
absl::flags_marshalling
absl::flags_registry
absl::synchronization
absl::meta
+ absl::utility
PUBLIC
)
@@ -205,7 +211,6 @@ absl_cc_library(
absl::flags_commandlineflag
absl::flags_config
absl::flags_internal
- absl::flags_marshalling
absl::flags_registry
absl::base
absl::core_headers
@@ -275,6 +280,7 @@ absl_cc_library(
absl::flags_config
absl::flags
absl::flags_commandlineflag
+ absl::flags_commandlineflag_internal
absl::flags_internal
absl::flags_private_handle_accessor
absl::flags_program_name
@@ -297,6 +303,7 @@ absl_cc_test(
DEPS
absl::flags
absl::flags_commandlineflag
+ absl::flags_commandlineflag_internal
absl::flags_config
absl::flags_private_handle_accessor
absl::flags_registry
@@ -330,6 +337,7 @@ absl_cc_test(
absl::flags
absl::flags_config
absl::flags_internal
+ absl::flags_marshalling
absl::flags_registry
absl::strings
absl::time
@@ -399,8 +407,8 @@ absl_cc_test(
COPTS
${ABSL_TEST_COPTS}
DEPS
+ absl::flags_commandlineflag_internal
absl::flags
- absl::flags_marshalling
absl::flags_registry
absl::memory
absl::strings
@@ -437,7 +445,6 @@ absl_cc_test(
absl::flags_parse
absl::flags_registry
absl::flags_usage
- absl::memory
absl::strings
gtest
)
diff --git a/absl/flags/commandlineflag.cc b/absl/flags/commandlineflag.cc
index cea57234..217b2d87 100644
--- a/absl/flags/commandlineflag.cc
+++ b/absl/flags/commandlineflag.cc
@@ -15,6 +15,12 @@
#include "absl/flags/commandlineflag.h"
+#include <string>
+
+#include "absl/base/config.h"
+#include "absl/flags/internal/commandlineflag.h"
+#include "absl/strings/string_view.h"
+
namespace absl {
ABSL_NAMESPACE_BEGIN
diff --git a/absl/flags/commandlineflag.h b/absl/flags/commandlineflag.h
index 43055d04..7e21d05d 100644
--- a/absl/flags/commandlineflag.h
+++ b/absl/flags/commandlineflag.h
@@ -26,7 +26,13 @@
#ifndef ABSL_FLAGS_COMMANDLINEFLAG_H_
#define ABSL_FLAGS_COMMANDLINEFLAG_H_
+#include <memory>
+#include <string>
+
+#include "absl/base/config.h"
+#include "absl/base/internal/fast_type_id.h"
#include "absl/flags/internal/commandlineflag.h"
+#include "absl/strings/string_view.h"
#include "absl/types/optional.h"
namespace absl {
diff --git a/absl/flags/commandlineflag_test.cc b/absl/flags/commandlineflag_test.cc
index 4b9718e9..570bbe2f 100644
--- a/absl/flags/commandlineflag_test.cc
+++ b/absl/flags/commandlineflag_test.cc
@@ -20,6 +20,7 @@
#include "gtest/gtest.h"
#include "absl/flags/flag.h"
+#include "absl/flags/internal/commandlineflag.h"
#include "absl/flags/internal/private_handle_accessor.h"
#include "absl/flags/internal/registry.h"
#include "absl/flags/usage_config.h"
diff --git a/absl/flags/declare.h b/absl/flags/declare.h
index 0f8cc6a5..b9794d8b 100644
--- a/absl/flags/declare.h
+++ b/absl/flags/declare.h
@@ -26,7 +26,6 @@
#define ABSL_FLAGS_DECLARE_H_
#include "absl/base/config.h"
-#include "absl/strings/string_view.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
diff --git a/absl/flags/flag.h b/absl/flags/flag.h
index dd36e6c7..90dc2894 100644
--- a/absl/flags/flag.h
+++ b/absl/flags/flag.h
@@ -33,13 +33,11 @@
#include <type_traits>
#include "absl/base/attributes.h"
-#include "absl/base/casts.h"
#include "absl/base/config.h"
+#include "absl/base/optimization.h"
#include "absl/flags/config.h"
-#include "absl/flags/declare.h"
#include "absl/flags/internal/flag.h"
#include "absl/flags/internal/registry.h"
-#include "absl/flags/marshalling.h"
#include "absl/strings/string_view.h"
namespace absl {
@@ -150,6 +148,8 @@ class Flag {
void Set(const T& v) { GetImpl().Set(v); }
void InvokeCallback() { GetImpl().InvokeCallback(); }
+ const CommandLineFlag& Reflect() const { return GetImpl().Reflect(); }
+
// The data members are logically private, but they need to be public for
// this to be an aggregate type.
const char* name_;
@@ -204,6 +204,21 @@ void SetFlag(absl::Flag<T>* flag, const V& v) {
flag->Set(value);
}
+// GetFlagReflectionHandle()
+//
+// Returns the reflection handle corresponding to specified Abseil Flag
+// instance. Use this handle to access flag's reflection information, like name,
+// location, default value etc.
+//
+// Example:
+//
+// std::string = absl::GetFlagReflectionHandle(FLAGS_count).DefaultValue();
+
+template <typename T>
+const CommandLineFlag& GetFlagReflectionHandle(const absl::Flag<T>& f) {
+ return f.Reflect();
+}
+
ABSL_NAMESPACE_END
} // namespace absl
diff --git a/absl/flags/flag_benchmark.cc b/absl/flags/flag_benchmark.cc
index ff95bb5d..7b52c9bc 100644
--- a/absl/flags/flag_benchmark.cc
+++ b/absl/flags/flag_benchmark.cc
@@ -13,7 +13,14 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+#include <stdint.h>
+
+#include <string>
+#include <vector>
+
#include "absl/flags/flag.h"
+#include "absl/flags/marshalling.h"
+#include "absl/strings/string_view.h"
#include "absl/time/time.h"
#include "absl/types/optional.h"
#include "benchmark/benchmark.h"
diff --git a/absl/flags/flag_test.cc b/absl/flags/flag_test.cc
index 58a07999..71661d39 100644
--- a/absl/flags/flag_test.cc
+++ b/absl/flags/flag_test.cc
@@ -15,9 +15,11 @@
#include "absl/flags/flag.h"
+#include <stddef.h>
#include <stdint.h>
#include <cmath>
+#include <new>
#include <string>
#include <thread> // NOLINT
#include <vector>
@@ -28,6 +30,7 @@
#include "absl/flags/declare.h"
#include "absl/flags/internal/flag.h"
#include "absl/flags/internal/registry.h"
+#include "absl/flags/marshalling.h"
#include "absl/flags/usage_config.h"
#include "absl/strings/match.h"
#include "absl/strings/numbers.h"
@@ -44,6 +47,9 @@ namespace {
namespace flags = absl::flags_internal;
std::string TestHelpMsg() { return "dynamic help"; }
+#if defined(_MSC_VER) && !defined(__clang__)
+std::string TestLiteralHelpMsg() { return "literal help"; }
+#endif
template <typename T>
void TestMakeDflt(void* dst) {
new (dst) T{};
@@ -127,15 +133,29 @@ constexpr flags::FlagHelpArg help_arg{flags::FlagHelpMsg("literal help"),
using String = std::string;
-#define DEFINE_CONSTRUCTED_FLAG(T, dflt, dflt_kind) \
- constexpr flags::FlagDefaultArg f1default##T{ \
- flags::FlagDefaultSrc{dflt}, flags::FlagDefaultKind::dflt_kind}; \
- constexpr flags::Flag<T> f1##T("f1", "file", help_arg, f1default##T); \
- ABSL_CONST_INIT flags::Flag<T> f2##T( \
- "f2", "file", \
- {flags::FlagHelpMsg(&TestHelpMsg), flags::FlagHelpKind::kGenFunc}, \
- flags::FlagDefaultArg{flags::FlagDefaultSrc(&TestMakeDflt<T>), \
- flags::FlagDefaultKind::kGenFunc})
+#if !defined(_MSC_VER) || defined(__clang__)
+#define DEFINE_CONSTRUCTED_FLAG(T, dflt, dflt_kind) \
+ constexpr flags::FlagDefaultArg f1default##T{ \
+ flags::FlagDefaultSrc{dflt}, flags::FlagDefaultKind::dflt_kind}; \
+ constexpr absl::Flag<T> f1##T{"f1", "file", help_arg, f1default##T}; \
+ ABSL_CONST_INIT absl::Flag<T> f2##T { \
+ "f2", "file", \
+ {flags::FlagHelpMsg(&TestHelpMsg), flags::FlagHelpKind::kGenFunc}, \
+ flags::FlagDefaultArg { \
+ flags::FlagDefaultSrc(&TestMakeDflt<T>), \
+ flags::FlagDefaultKind::kGenFunc \
+ } \
+ }
+#else
+#define DEFINE_CONSTRUCTED_FLAG(T, dflt, dflt_kind) \
+ constexpr flags::FlagDefaultArg f1default##T{ \
+ flags::FlagDefaultSrc{dflt}, flags::FlagDefaultKind::dflt_kind}; \
+ constexpr absl::Flag<T> f1##T{"f1", "file", &TestLiteralHelpMsg, \
+ &TestMakeDflt<T>}; \
+ ABSL_CONST_INIT absl::Flag<T> f2##T { \
+ "f2", "file", &TestHelpMsg, &TestMakeDflt<T> \
+ }
+#endif
DEFINE_CONSTRUCTED_FLAG(bool, true, kOneWord);
DEFINE_CONSTRUCTED_FLAG(int16_t, 1, kOneWord);
@@ -150,16 +170,17 @@ DEFINE_CONSTRUCTED_FLAG(String, &TestMakeDflt<String>, kGenFunc);
DEFINE_CONSTRUCTED_FLAG(UDT, &TestMakeDflt<UDT>, kGenFunc);
template <typename T>
-bool TestConstructionFor(const flags::Flag<T>& f1, flags::Flag<T>& f2) {
- EXPECT_EQ(f1.Name(), "f1");
- EXPECT_EQ(f1.Help(), "literal help");
- EXPECT_EQ(f1.Filename(), "file");
+bool TestConstructionFor(const absl::Flag<T>& f1, absl::Flag<T>& f2) {
+ EXPECT_EQ(absl::GetFlagReflectionHandle(f1).Name(), "f1");
+ EXPECT_EQ(absl::GetFlagReflectionHandle(f1).Help(), "literal help");
+ EXPECT_EQ(absl::GetFlagReflectionHandle(f1).Filename(), "file");
- flags::FlagRegistrar<T, false>(f2).OnUpdate(TestCallback);
+ flags::FlagRegistrar<T, false>(ABSL_FLAG_IMPL_FLAG_PTR(f2))
+ .OnUpdate(TestCallback);
- EXPECT_EQ(f2.Name(), "f2");
- EXPECT_EQ(f2.Help(), "dynamic help");
- EXPECT_EQ(f2.Filename(), "file");
+ EXPECT_EQ(absl::GetFlagReflectionHandle(f2).Name(), "f2");
+ EXPECT_EQ(absl::GetFlagReflectionHandle(f2).Help(), "dynamic help");
+ EXPECT_EQ(absl::GetFlagReflectionHandle(f2).Filename(), "file");
return true;
}
@@ -203,18 +224,30 @@ namespace {
TEST_F(FlagTest, TestFlagDeclaration) {
// test that we can access flag objects.
- EXPECT_EQ(FLAGS_test_flag_01.Name(), "test_flag_01");
- EXPECT_EQ(FLAGS_test_flag_02.Name(), "test_flag_02");
- EXPECT_EQ(FLAGS_test_flag_03.Name(), "test_flag_03");
- EXPECT_EQ(FLAGS_test_flag_04.Name(), "test_flag_04");
- EXPECT_EQ(FLAGS_test_flag_05.Name(), "test_flag_05");
- EXPECT_EQ(FLAGS_test_flag_06.Name(), "test_flag_06");
- EXPECT_EQ(FLAGS_test_flag_07.Name(), "test_flag_07");
- EXPECT_EQ(FLAGS_test_flag_08.Name(), "test_flag_08");
- 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_11.Name(), "test_flag_11");
- EXPECT_EQ(FLAGS_test_flag_12.Name(), "test_flag_12");
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_01).Name(),
+ "test_flag_01");
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_02).Name(),
+ "test_flag_02");
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_03).Name(),
+ "test_flag_03");
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_04).Name(),
+ "test_flag_04");
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_05).Name(),
+ "test_flag_05");
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_06).Name(),
+ "test_flag_06");
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_07).Name(),
+ "test_flag_07");
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_08).Name(),
+ "test_flag_08");
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_09).Name(),
+ "test_flag_09");
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_10).Name(),
+ "test_flag_10");
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_11).Name(),
+ "test_flag_11");
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_12).Name(),
+ "test_flag_12");
}
#endif // !ABSL_FLAGS_STRIP_NAMES
@@ -241,96 +274,168 @@ namespace {
TEST_F(FlagTest, TestFlagDefinition) {
absl::string_view expected_file_name = "absl/flags/flag_test.cc";
- EXPECT_EQ(FLAGS_test_flag_01.Name(), "test_flag_01");
- EXPECT_EQ(FLAGS_test_flag_01.Help(), "test flag 01");
- EXPECT_TRUE(absl::EndsWith(FLAGS_test_flag_01.Filename(), expected_file_name))
- << FLAGS_test_flag_01.Filename();
-
- EXPECT_EQ(FLAGS_test_flag_02.Name(), "test_flag_02");
- EXPECT_EQ(FLAGS_test_flag_02.Help(), "test flag 02");
- EXPECT_TRUE(absl::EndsWith(FLAGS_test_flag_02.Filename(), expected_file_name))
- << FLAGS_test_flag_02.Filename();
-
- EXPECT_EQ(FLAGS_test_flag_03.Name(), "test_flag_03");
- EXPECT_EQ(FLAGS_test_flag_03.Help(), "test flag 03");
- EXPECT_TRUE(absl::EndsWith(FLAGS_test_flag_03.Filename(), expected_file_name))
- << FLAGS_test_flag_03.Filename();
-
- EXPECT_EQ(FLAGS_test_flag_04.Name(), "test_flag_04");
- EXPECT_EQ(FLAGS_test_flag_04.Help(), "test flag 04");
- EXPECT_TRUE(absl::EndsWith(FLAGS_test_flag_04.Filename(), expected_file_name))
- << FLAGS_test_flag_04.Filename();
-
- EXPECT_EQ(FLAGS_test_flag_05.Name(), "test_flag_05");
- EXPECT_EQ(FLAGS_test_flag_05.Help(), "test flag 05");
- EXPECT_TRUE(absl::EndsWith(FLAGS_test_flag_05.Filename(), expected_file_name))
- << FLAGS_test_flag_05.Filename();
-
- EXPECT_EQ(FLAGS_test_flag_06.Name(), "test_flag_06");
- EXPECT_EQ(FLAGS_test_flag_06.Help(), "test flag 06");
- EXPECT_TRUE(absl::EndsWith(FLAGS_test_flag_06.Filename(), expected_file_name))
- << FLAGS_test_flag_06.Filename();
-
- EXPECT_EQ(FLAGS_test_flag_07.Name(), "test_flag_07");
- EXPECT_EQ(FLAGS_test_flag_07.Help(), "test flag 07");
- EXPECT_TRUE(absl::EndsWith(FLAGS_test_flag_07.Filename(), expected_file_name))
- << FLAGS_test_flag_07.Filename();
-
- EXPECT_EQ(FLAGS_test_flag_08.Name(), "test_flag_08");
- EXPECT_EQ(FLAGS_test_flag_08.Help(), "test flag 08");
- EXPECT_TRUE(absl::EndsWith(FLAGS_test_flag_08.Filename(), expected_file_name))
- << FLAGS_test_flag_08.Filename();
-
- EXPECT_EQ(FLAGS_test_flag_09.Name(), "test_flag_09");
- EXPECT_EQ(FLAGS_test_flag_09.Help(), "test flag 09");
- EXPECT_TRUE(absl::EndsWith(FLAGS_test_flag_09.Filename(), expected_file_name))
- << FLAGS_test_flag_09.Filename();
-
- EXPECT_EQ(FLAGS_test_flag_10.Name(), "test_flag_10");
- EXPECT_EQ(FLAGS_test_flag_10.Help(), "test flag 10");
- EXPECT_TRUE(absl::EndsWith(FLAGS_test_flag_10.Filename(), expected_file_name))
- << FLAGS_test_flag_10.Filename();
-
- EXPECT_EQ(FLAGS_test_flag_11.Name(), "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))
- << 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();
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_01).Name(),
+ "test_flag_01");
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_01).Help(),
+ "test flag 01");
+ EXPECT_TRUE(absl::EndsWith(
+ absl::GetFlagReflectionHandle(FLAGS_test_flag_01).Filename(),
+ expected_file_name))
+ << absl::GetFlagReflectionHandle(FLAGS_test_flag_01).Filename();
+
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_02).Name(),
+ "test_flag_02");
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_02).Help(),
+ "test flag 02");
+ EXPECT_TRUE(absl::EndsWith(
+ absl::GetFlagReflectionHandle(FLAGS_test_flag_02).Filename(),
+ expected_file_name))
+ << absl::GetFlagReflectionHandle(FLAGS_test_flag_02).Filename();
+
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_03).Name(),
+ "test_flag_03");
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_03).Help(),
+ "test flag 03");
+ EXPECT_TRUE(absl::EndsWith(
+ absl::GetFlagReflectionHandle(FLAGS_test_flag_03).Filename(),
+ expected_file_name))
+ << absl::GetFlagReflectionHandle(FLAGS_test_flag_03).Filename();
+
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_04).Name(),
+ "test_flag_04");
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_04).Help(),
+ "test flag 04");
+ EXPECT_TRUE(absl::EndsWith(
+ absl::GetFlagReflectionHandle(FLAGS_test_flag_04).Filename(),
+ expected_file_name))
+ << absl::GetFlagReflectionHandle(FLAGS_test_flag_04).Filename();
+
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_05).Name(),
+ "test_flag_05");
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_05).Help(),
+ "test flag 05");
+ EXPECT_TRUE(absl::EndsWith(
+ absl::GetFlagReflectionHandle(FLAGS_test_flag_05).Filename(),
+ expected_file_name))
+ << absl::GetFlagReflectionHandle(FLAGS_test_flag_05).Filename();
+
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_06).Name(),
+ "test_flag_06");
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_06).Help(),
+ "test flag 06");
+ EXPECT_TRUE(absl::EndsWith(
+ absl::GetFlagReflectionHandle(FLAGS_test_flag_06).Filename(),
+ expected_file_name))
+ << absl::GetFlagReflectionHandle(FLAGS_test_flag_06).Filename();
+
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_07).Name(),
+ "test_flag_07");
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_07).Help(),
+ "test flag 07");
+ EXPECT_TRUE(absl::EndsWith(
+ absl::GetFlagReflectionHandle(FLAGS_test_flag_07).Filename(),
+ expected_file_name))
+ << absl::GetFlagReflectionHandle(FLAGS_test_flag_07).Filename();
+
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_08).Name(),
+ "test_flag_08");
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_08).Help(),
+ "test flag 08");
+ EXPECT_TRUE(absl::EndsWith(
+ absl::GetFlagReflectionHandle(FLAGS_test_flag_08).Filename(),
+ expected_file_name))
+ << absl::GetFlagReflectionHandle(FLAGS_test_flag_08).Filename();
+
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_09).Name(),
+ "test_flag_09");
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_09).Help(),
+ "test flag 09");
+ EXPECT_TRUE(absl::EndsWith(
+ absl::GetFlagReflectionHandle(FLAGS_test_flag_09).Filename(),
+ expected_file_name))
+ << absl::GetFlagReflectionHandle(FLAGS_test_flag_09).Filename();
+
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_10).Name(),
+ "test_flag_10");
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_10).Help(),
+ "test flag 10");
+ EXPECT_TRUE(absl::EndsWith(
+ absl::GetFlagReflectionHandle(FLAGS_test_flag_10).Filename(),
+ expected_file_name))
+ << absl::GetFlagReflectionHandle(FLAGS_test_flag_10).Filename();
+
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_11).Name(),
+ "test_flag_11");
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_11).Help(),
+ "test flag 11");
+ EXPECT_TRUE(absl::EndsWith(
+ absl::GetFlagReflectionHandle(FLAGS_test_flag_11).Filename(),
+ expected_file_name))
+ << absl::GetFlagReflectionHandle(FLAGS_test_flag_11).Filename();
+
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_12).Name(),
+ "test_flag_12");
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_12).Help(),
+ "test flag 12");
+ EXPECT_TRUE(absl::EndsWith(
+ absl::GetFlagReflectionHandle(FLAGS_test_flag_12).Filename(),
+ expected_file_name))
+ << absl::GetFlagReflectionHandle(FLAGS_test_flag_12).Filename();
}
#endif // !ABSL_FLAGS_STRIP_NAMES
// --------------------------------------------------------------------
TEST_F(FlagTest, TestDefault) {
- EXPECT_EQ(FLAGS_test_flag_01.DefaultValue(), "true");
- EXPECT_EQ(FLAGS_test_flag_02.DefaultValue(), "1234");
- EXPECT_EQ(FLAGS_test_flag_03.DefaultValue(), "-34");
- EXPECT_EQ(FLAGS_test_flag_04.DefaultValue(), "189");
- EXPECT_EQ(FLAGS_test_flag_05.DefaultValue(), "10765");
- EXPECT_EQ(FLAGS_test_flag_06.DefaultValue(), "40000");
- EXPECT_EQ(FLAGS_test_flag_07.DefaultValue(), "-1234567");
- EXPECT_EQ(FLAGS_test_flag_08.DefaultValue(), "9876543");
- 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_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::GetFlagReflectionHandle(FLAGS_test_flag_01).DefaultValue(),
+ "true");
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_02).DefaultValue(),
+ "1234");
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_03).DefaultValue(),
+ "-34");
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_04).DefaultValue(),
+ "189");
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_05).DefaultValue(),
+ "10765");
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_06).DefaultValue(),
+ "40000");
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_07).DefaultValue(),
+ "-1234567");
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_08).DefaultValue(),
+ "9876543");
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_09).DefaultValue(),
+ "-9.876e-50");
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_10).DefaultValue(),
+ "1.234e+12");
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_11).DefaultValue(),
+ "");
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_12).DefaultValue(),
+ "10m");
+
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_01).CurrentValue(),
+ "true");
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_02).CurrentValue(),
+ "1234");
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_03).CurrentValue(),
+ "-34");
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_04).CurrentValue(),
+ "189");
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_05).CurrentValue(),
+ "10765");
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_06).CurrentValue(),
+ "40000");
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_07).CurrentValue(),
+ "-1234567");
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_08).CurrentValue(),
+ "9876543");
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_09).CurrentValue(),
+ "-9.876e-50");
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_10).CurrentValue(),
+ "1.234e+12");
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_11).CurrentValue(),
+ "");
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_12).CurrentValue(),
+ "10m");
EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_01), true);
EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_02), 1234);
@@ -385,12 +490,18 @@ ABSL_FLAG(NonTriviallyCopyableAggregate, test_flag_eb_06, {}, "");
namespace {
TEST_F(FlagTest, TestEmptyBracesDefault) {
- EXPECT_EQ(FLAGS_test_flag_eb_01.DefaultValue(), "false");
- EXPECT_EQ(FLAGS_test_flag_eb_02.DefaultValue(), "0");
- EXPECT_EQ(FLAGS_test_flag_eb_03.DefaultValue(), "0");
- EXPECT_EQ(FLAGS_test_flag_eb_04.DefaultValue(), "0");
- EXPECT_EQ(FLAGS_test_flag_eb_05.DefaultValue(), "");
- EXPECT_EQ(FLAGS_test_flag_eb_06.DefaultValue(), "0");
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_eb_01).DefaultValue(),
+ "false");
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_eb_02).DefaultValue(),
+ "0");
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_eb_03).DefaultValue(),
+ "0");
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_eb_04).DefaultValue(),
+ "0");
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_eb_05).DefaultValue(),
+ "");
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_eb_06).DefaultValue(),
+ "0");
EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_eb_01), false);
EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_eb_02), 0);
@@ -500,8 +611,9 @@ namespace {
#if !ABSL_FLAGS_STRIP_HELP
TEST_F(FlagTest, TestNonConstexprHelp) {
- EXPECT_EQ(FLAGS_test_flag_with_non_const_help.Help(),
- "test flag non const help");
+ EXPECT_EQ(
+ absl::GetFlagReflectionHandle(FLAGS_test_flag_with_non_const_help).Help(),
+ "test flag non const help");
}
#endif //! ABSL_FLAGS_STRIP_HELP
diff --git a/absl/flags/internal/commandlineflag.h b/absl/flags/internal/commandlineflag.h
index 3c149788..cb46fe2e 100644
--- a/absl/flags/internal/commandlineflag.h
+++ b/absl/flags/internal/commandlineflag.h
@@ -16,13 +16,8 @@
#ifndef ABSL_FLAGS_INTERNAL_COMMANDLINEFLAG_H_
#define ABSL_FLAGS_INTERNAL_COMMANDLINEFLAG_H_
-#include <memory>
-#include <string>
-
#include "absl/base/config.h"
#include "absl/base/internal/fast_type_id.h"
-#include "absl/base/macros.h"
-#include "absl/strings/string_view.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
@@ -33,7 +28,7 @@ namespace flags_internal {
// cases this id is enough to uniquely identify the flag's value type. In a few
// cases we'll have to resort to using actual RTTI implementation if it is
// available.
-using FlagFastTypeId = base_internal::FastTypeIdType;
+using FlagFastTypeId = absl::base_internal::FastTypeIdType;
// Options that control SetCommandLineOptionWithMode.
enum FlagSettingMode {
diff --git a/absl/flags/internal/flag.cc b/absl/flags/internal/flag.cc
index ee974244..1502e7f1 100644
--- a/absl/flags/internal/flag.cc
+++ b/absl/flags/internal/flag.cc
@@ -15,21 +15,26 @@
#include "absl/flags/internal/flag.h"
+#include <assert.h>
#include <stddef.h>
#include <stdint.h>
#include <string.h>
+#include <array>
#include <atomic>
#include <memory>
+#include <new>
#include <string>
-#include <vector>
+#include <typeinfo>
-#include "absl/base/attributes.h"
+#include "absl/base/call_once.h"
#include "absl/base/casts.h"
#include "absl/base/config.h"
-#include "absl/base/const_init.h"
#include "absl/base/optimization.h"
+#include "absl/flags/config.h"
+#include "absl/flags/internal/commandlineflag.h"
#include "absl/flags/usage_config.h"
+#include "absl/memory/memory.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h"
#include "absl/synchronization/mutex.h"
diff --git a/absl/flags/internal/flag.h b/absl/flags/internal/flag.h
index e1885809..2cc44e00 100644
--- a/absl/flags/internal/flag.h
+++ b/absl/flags/internal/flag.h
@@ -16,31 +16,36 @@
#ifndef ABSL_FLAGS_INTERNAL_FLAG_H_
#define ABSL_FLAGS_INTERNAL_FLAG_H_
+#include <stddef.h>
#include <stdint.h>
#include <atomic>
#include <cstring>
#include <memory>
+#include <new>
#include <string>
#include <type_traits>
#include <typeinfo>
+#include "absl/base/attributes.h"
#include "absl/base/call_once.h"
#include "absl/base/config.h"
+#include "absl/base/optimization.h"
#include "absl/base/thread_annotations.h"
#include "absl/flags/commandlineflag.h"
#include "absl/flags/config.h"
+#include "absl/flags/internal/commandlineflag.h"
#include "absl/flags/internal/registry.h"
#include "absl/flags/marshalling.h"
-#include "absl/memory/memory.h"
#include "absl/meta/type_traits.h"
-#include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h"
#include "absl/synchronization/mutex.h"
+#include "absl/utility/utility.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
+///////////////////////////////////////////////////////////////////////////////
// Forward declaration of absl::Flag<T> public API.
namespace flags_internal {
template <typename T>
@@ -64,12 +69,15 @@ void SetFlag(absl::Flag<T>* flag, const T& v);
template <typename T, typename V>
void SetFlag(absl::Flag<T>* flag, const V& v);
-namespace flags_internal {
+template <typename U>
+const CommandLineFlag& GetFlagReflectionHandle(const absl::Flag<U>& f);
///////////////////////////////////////////////////////////////////////////////
// Flag value type operations, eg., parsing, copying, etc. are provided
// by function specific to that type with a signature matching FlagOpFn.
+namespace flags_internal {
+
enum class FlagOp {
kAlloc,
kDelete,
@@ -659,6 +667,13 @@ class Flag {
impl_.Write(&v);
}
+ template <typename U>
+ friend const CommandLineFlag& absl::GetFlagReflectionHandle(
+ const absl::Flag<U>& f);
+
+ // Access to the reflection.
+ const CommandLineFlag& Reflect() const { return impl_; }
+
// Flag's data
// The implementation depends on value_ field to be placed exactly after the
// impl_ field, so that impl_ can figure out the offset to the value and
diff --git a/absl/flags/internal/parse.h b/absl/flags/internal/parse.h
index d259be73..de706c89 100644
--- a/absl/flags/internal/parse.h
+++ b/absl/flags/internal/parse.h
@@ -21,6 +21,7 @@
#include "absl/base/config.h"
#include "absl/flags/declare.h"
+#include "absl/strings/string_view.h"
ABSL_DECLARE_FLAG(std::vector<std::string>, flagfile);
ABSL_DECLARE_FLAG(std::vector<std::string>, fromenv);
diff --git a/absl/flags/internal/path_util.h b/absl/flags/internal/path_util.h
index 365c8305..a6594d33 100644
--- a/absl/flags/internal/path_util.h
+++ b/absl/flags/internal/path_util.h
@@ -17,7 +17,6 @@
#define ABSL_FLAGS_INTERNAL_PATH_UTIL_H_
#include "absl/base/config.h"
-#include "absl/strings/match.h"
#include "absl/strings/string_view.h"
namespace absl {
diff --git a/absl/flags/internal/private_handle_accessor.cc b/absl/flags/internal/private_handle_accessor.cc
index 24b49136..a7eb58b6 100644
--- a/absl/flags/internal/private_handle_accessor.cc
+++ b/absl/flags/internal/private_handle_accessor.cc
@@ -15,6 +15,14 @@
#include "absl/flags/internal/private_handle_accessor.h"
+#include <memory>
+#include <string>
+
+#include "absl/base/config.h"
+#include "absl/flags/commandlineflag.h"
+#include "absl/flags/internal/commandlineflag.h"
+#include "absl/strings/string_view.h"
+
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace flags_internal {
diff --git a/absl/flags/internal/private_handle_accessor.h b/absl/flags/internal/private_handle_accessor.h
index 9a327a07..c64435cd 100644
--- a/absl/flags/internal/private_handle_accessor.h
+++ b/absl/flags/internal/private_handle_accessor.h
@@ -16,7 +16,13 @@
#ifndef ABSL_FLAGS_INTERNAL_PRIVATE_HANDLE_ACCESSOR_H_
#define ABSL_FLAGS_INTERNAL_PRIVATE_HANDLE_ACCESSOR_H_
+#include <memory>
+#include <string>
+
+#include "absl/base/config.h"
#include "absl/flags/commandlineflag.h"
+#include "absl/flags/internal/commandlineflag.h"
+#include "absl/strings/string_view.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
diff --git a/absl/flags/internal/registry.cc b/absl/flags/internal/registry.cc
index 4bcebfa9..e582d79d 100644
--- a/absl/flags/internal/registry.cc
+++ b/absl/flags/internal/registry.cc
@@ -29,6 +29,7 @@
#include "absl/base/internal/raw_logging.h"
#include "absl/base/thread_annotations.h"
#include "absl/flags/commandlineflag.h"
+#include "absl/flags/internal/commandlineflag.h"
#include "absl/flags/internal/private_handle_accessor.h"
#include "absl/flags/usage_config.h"
#include "absl/strings/str_cat.h"
diff --git a/absl/flags/internal/registry.h b/absl/flags/internal/registry.h
index a118865a..d207c225 100644
--- a/absl/flags/internal/registry.h
+++ b/absl/flags/internal/registry.h
@@ -17,11 +17,9 @@
#define ABSL_FLAGS_INTERNAL_REGISTRY_H_
#include <functional>
-#include <map>
-#include <string>
#include "absl/base/config.h"
-#include "absl/base/macros.h"
+#include "absl/flags/commandlineflag.h"
#include "absl/flags/internal/commandlineflag.h"
#include "absl/strings/string_view.h"
@@ -30,8 +28,6 @@
namespace absl {
ABSL_NAMESPACE_BEGIN
-class CommandLineFlag;
-
namespace flags_internal {
CommandLineFlag* FindCommandLineFlag(absl::string_view name);
diff --git a/absl/flags/internal/type_erased.h b/absl/flags/internal/type_erased.h
index fd9663e2..437a8c28 100644
--- a/absl/flags/internal/type_erased.h
+++ b/absl/flags/internal/type_erased.h
@@ -20,6 +20,7 @@
#include "absl/base/config.h"
#include "absl/flags/commandlineflag.h"
+#include "absl/flags/internal/commandlineflag.h"
#include "absl/flags/internal/registry.h"
#include "absl/strings/string_view.h"
diff --git a/absl/flags/internal/type_erased_test.cc b/absl/flags/internal/type_erased_test.cc
index bb0ff23e..42f374dc 100644
--- a/absl/flags/internal/type_erased_test.cc
+++ b/absl/flags/internal/type_erased_test.cc
@@ -20,8 +20,8 @@
#include "gtest/gtest.h"
#include "absl/flags/flag.h"
+#include "absl/flags/internal/commandlineflag.h"
#include "absl/flags/internal/registry.h"
-#include "absl/flags/marshalling.h"
#include "absl/memory/memory.h"
ABSL_FLAG(int, int_flag, 1, "int_flag help");
diff --git a/absl/flags/internal/usage.cc b/absl/flags/internal/usage.cc
index 2a2231a7..35b6427b 100644
--- a/absl/flags/internal/usage.cc
+++ b/absl/flags/internal/usage.cc
@@ -15,6 +15,8 @@
#include "absl/flags/internal/usage.h"
+#include <stdint.h>
+
#include <functional>
#include <map>
#include <ostream>
diff --git a/absl/flags/internal/usage_test.cc b/absl/flags/internal/usage_test.cc
index 8dd3532e..53b4d983 100644
--- a/absl/flags/internal/usage_test.cc
+++ b/absl/flags/internal/usage_test.cc
@@ -21,7 +21,6 @@
#include <string>
#include "gtest/gtest.h"
-#include "absl/flags/declare.h"
#include "absl/flags/flag.h"
#include "absl/flags/internal/parse.h"
#include "absl/flags/internal/path_util.h"
@@ -29,7 +28,6 @@
#include "absl/flags/internal/registry.h"
#include "absl/flags/usage.h"
#include "absl/flags/usage_config.h"
-#include "absl/memory/memory.h"
#include "absl/strings/match.h"
#include "absl/strings/string_view.h"
diff --git a/absl/flags/parse.cc b/absl/flags/parse.cc
index 15300786..f0a131f2 100644
--- a/absl/flags/parse.cc
+++ b/absl/flags/parse.cc
@@ -37,6 +37,7 @@
#include "absl/flags/commandlineflag.h"
#include "absl/flags/config.h"
#include "absl/flags/flag.h"
+#include "absl/flags/internal/commandlineflag.h"
#include "absl/flags/internal/flag.h"
#include "absl/flags/internal/parse.h"
#include "absl/flags/internal/private_handle_accessor.h"
diff --git a/absl/flags/parse.h b/absl/flags/parse.h
index f37b0602..929de2cb 100644
--- a/absl/flags/parse.h
+++ b/absl/flags/parse.h
@@ -23,7 +23,6 @@
#ifndef ABSL_FLAGS_PARSE_H_
#define ABSL_FLAGS_PARSE_H_
-#include <string>
#include <vector>
#include "absl/base/config.h"
diff --git a/absl/flags/usage_config.cc b/absl/flags/usage_config.cc
index 0d21bce6..ae2f548a 100644
--- a/absl/flags/usage_config.cc
+++ b/absl/flags/usage_config.cc
@@ -15,6 +15,7 @@
#include "absl/flags/usage_config.h"
+#include <functional>
#include <iostream>
#include <string>
diff --git a/absl/time/civil_time.cc b/absl/time/civil_time.cc
index c4202c73..bdfe9ce0 100644
--- a/absl/time/civil_time.cc
+++ b/absl/time/civil_time.cc
@@ -98,26 +98,26 @@ bool ParseLenient(string_view s, CivilT* c) {
} // namespace
std::string FormatCivilTime(CivilSecond c) {
- return FormatYearAnd("-%m-%dT%H:%M:%S", c);
+ return FormatYearAnd("-%m-%d%ET%H:%M:%S", c);
}
std::string FormatCivilTime(CivilMinute c) {
- return FormatYearAnd("-%m-%dT%H:%M", c);
+ return FormatYearAnd("-%m-%d%ET%H:%M", c);
}
std::string FormatCivilTime(CivilHour c) {
- return FormatYearAnd("-%m-%dT%H", c);
+ return FormatYearAnd("-%m-%d%ET%H", c);
}
std::string FormatCivilTime(CivilDay c) { return FormatYearAnd("-%m-%d", c); }
std::string FormatCivilTime(CivilMonth c) { return FormatYearAnd("-%m", c); }
std::string FormatCivilTime(CivilYear c) { return FormatYearAnd("", c); }
bool ParseCivilTime(string_view s, CivilSecond* c) {
- return ParseYearAnd("-%m-%dT%H:%M:%S", s, c);
+ return ParseYearAnd("-%m-%d%ET%H:%M:%S", s, c);
}
bool ParseCivilTime(string_view s, CivilMinute* c) {
- return ParseYearAnd("-%m-%dT%H:%M", s, c);
+ return ParseYearAnd("-%m-%d%ET%H:%M", s, c);
}
bool ParseCivilTime(string_view s, CivilHour* c) {
- return ParseYearAnd("-%m-%dT%H", s, c);
+ return ParseYearAnd("-%m-%d%ET%H", s, c);
}
bool ParseCivilTime(string_view s, CivilDay* c) {
return ParseYearAnd("-%m-%d", s, c);
diff --git a/absl/time/format.cc b/absl/time/format.cc
index 228940ed..4005fb70 100644
--- a/absl/time/format.cc
+++ b/absl/time/format.cc
@@ -27,14 +27,11 @@ namespace cctz = absl::time_internal::cctz;
namespace absl {
ABSL_NAMESPACE_BEGIN
-ABSL_DLL extern const char RFC3339_full[] =
- "%Y-%m-%dT%H:%M:%E*S%Ez";
-ABSL_DLL extern const char RFC3339_sec[] = "%Y-%m-%dT%H:%M:%S%Ez";
-
-ABSL_DLL extern const char RFC1123_full[] =
- "%a, %d %b %E4Y %H:%M:%S %z";
-ABSL_DLL extern const char RFC1123_no_wday[] =
- "%d %b %E4Y %H:%M:%S %z";
+ABSL_DLL extern const char RFC3339_full[] = "%Y-%m-%d%ET%H:%M:%E*S%Ez";
+ABSL_DLL extern const char RFC3339_sec[] = "%Y-%m-%d%ET%H:%M:%S%Ez";
+
+ABSL_DLL extern const char RFC1123_full[] = "%a, %d %b %E4Y %H:%M:%S %z";
+ABSL_DLL extern const char RFC1123_no_wday[] = "%d %b %E4Y %H:%M:%S %z";
namespace {
diff --git a/absl/time/format_benchmark.cc b/absl/time/format_benchmark.cc
index 249c51d8..19e481db 100644
--- a/absl/time/format_benchmark.cc
+++ b/absl/time/format_benchmark.cc
@@ -26,7 +26,7 @@ const char* const kFormats[] = {
absl::RFC1123_no_wday, // 1
absl::RFC3339_full, // 2
absl::RFC3339_sec, // 3
- "%Y-%m-%dT%H:%M:%S", // 4
+ "%Y-%m-%d%ET%H:%M:%S", // 4
"%Y-%m-%d", // 5
};
const int kNumFormats = sizeof(kFormats) / sizeof(kFormats[0]);
diff --git a/absl/time/internal/cctz/include/cctz/time_zone.h b/absl/time/internal/cctz/include/cctz/time_zone.h
index b33e0c0a..5562a37b 100644
--- a/absl/time/internal/cctz/include/cctz/time_zone.h
+++ b/absl/time/internal/cctz/include/cctz/time_zone.h
@@ -322,7 +322,8 @@ inline std::string format(const std::string& fmt, const time_point<D>& tp,
// returns the corresponding time_point. Uses strftime()-like formatting
// options, with the same extensions as cctz::format(), but with the
// exceptions that %E#S is interpreted as %E*S, and %E#f as %E*f. %Ez
-// and %E*z also accept the same inputs. %ET accepts either 'T' or 't'.
+// and %E*z also accept the same inputs, which (along with %z) includes
+// 'z' and 'Z' as synonyms for +00:00. %ET accepts either 'T' or 't'.
//
// %Y consumes as many numeric characters as it can, so the matching data
// should always be terminated with a non-numeric. %E4Y always consumes
diff --git a/absl/time/time.h b/absl/time/time.h
index b456a13e..37f6131d 100644
--- a/absl/time/time.h
+++ b/absl/time/time.h
@@ -1203,18 +1203,15 @@ struct tm ToTM(Time t, TimeZone tz);
// time with UTC offset. Also note the use of "%Y": RFC3339 mandates that
// years have exactly four digits, but we allow them to take their natural
// width.
-ABSL_DLL extern const char
- RFC3339_full[]; // %Y-%m-%dT%H:%M:%E*S%Ez
-ABSL_DLL extern const char RFC3339_sec[]; // %Y-%m-%dT%H:%M:%S%Ez
+ABSL_DLL extern const char RFC3339_full[]; // %Y-%m-%d%ET%H:%M:%E*S%Ez
+ABSL_DLL extern const char RFC3339_sec[]; // %Y-%m-%d%ET%H:%M:%S%Ez
// RFC1123_full
// RFC1123_no_wday
//
// FormatTime()/ParseTime() format specifiers for RFC1123 date/time strings.
-ABSL_DLL extern const char
- RFC1123_full[]; // %a, %d %b %E4Y %H:%M:%S %z
-ABSL_DLL extern const char
- RFC1123_no_wday[]; // %d %b %E4Y %H:%M:%S %z
+ABSL_DLL extern const char RFC1123_full[]; // %a, %d %b %E4Y %H:%M:%S %z
+ABSL_DLL extern const char RFC1123_no_wday[]; // %d %b %E4Y %H:%M:%S %z
// FormatTime()
//
@@ -1229,6 +1226,7 @@ ABSL_DLL extern const char
// - %E#f - Fractional seconds with # digits of precision
// - %E*f - Fractional seconds with full precision (a literal '*')
// - %E4Y - Four-character years (-999 ... -001, 0000, 0001 ... 9999)
+// - %ET - The RFC3339 "date-time" separator "T"
//
// Note that %E0S behaves like %S, and %E0f produces no characters. In
// contrast %E*f always produces at least one digit, which may be '0'.
@@ -1271,7 +1269,8 @@ inline std::ostream& operator<<(std::ostream& os, Time t) {
// returns the corresponding `absl::Time`. Uses strftime()-like formatting
// options, with the same extensions as FormatTime(), but with the
// exceptions that %E#S is interpreted as %E*S, and %E#f as %E*f. %Ez
-// and %E*z also accept the same inputs.
+// and %E*z also accept the same inputs, which (along with %z) includes
+// 'z' and 'Z' as synonyms for +00:00. %ET accepts either 'T' or 't'.
//
// %Y consumes as many numeric characters as it can, so the matching data
// should always be terminated with a non-numeric. %E4Y always consumes