From 0e7afdcbd24c7e5b7cab4e0217d8886f1525b520 Mon Sep 17 00:00:00 2001 From: Abseil Team Date: Mon, 19 Aug 2019 10:27:18 -0700 Subject: Export of internal Abseil changes -- 62058c9c008e23c787f35c1a5fe05851046a71f1 by Abseil Team : Fix some strange usage of INSTANTIATE_TEST_SUITE_P PiperOrigin-RevId: 264185105 -- 4400d84027d86415a2f9b81996ff22e7fd7aa30f by Derek Mauro : Disable testing std::string_view from nullptr on GCC >= GCC9. PiperOrigin-RevId: 264150587 -- 656d5a742ba48d025589709fad33ddae4b02c620 by Matt Calabrese : Fix `absl::any_cast` such that it properly works with qualifications. PiperOrigin-RevId: 263843429 -- 6ec89214a4ef2170bf069623a56ffd22863b748d by Abseil Team : Use macros to enable inline constexpr variables in compare.h when the compiler supports the feature. PiperOrigin-RevId: 263790677 -- a5171e0897195a0367fc08abce9504f813d027ff by Derek Mauro : Add the Apache License to files that are missing it. PiperOrigin-RevId: 263774164 -- 19e09a7ce8a0aac0a7d534e1799e4d73b63a1bb5 by Abseil Team : Update iter.position when moving up the tree in rebalance_after_delete. This field isn't read after the first iteration in rebalance_after_delete, and I think it's not a correctness issue, but it is read in try_merge_or_rebalance and potentially affects rebalancing decisions so it can affect performance. There's also an extremely unlikely potential for undefined behavior due to signed integer overflow since this field is only ever incremented in try_merge_or_rebalance (and position is an int). Basically though, I just don't think it makes sense to have this invalid iterator floating around here. PiperOrigin-RevId: 263770305 GitOrigin-RevId: 62058c9c008e23c787f35c1a5fe05851046a71f1 Change-Id: I1e2fb7cbfac7507dddedd181414ee35a5778f8f5 --- absl/container/internal/btree.h | 1 + absl/meta/BUILD.bazel | 16 +++ absl/random/BUILD.bazel | 16 +++ absl/random/exponential_distribution_test.cc | 2 +- absl/random/gaussian_distribution_test.cc | 2 +- absl/random/internal/BUILD.bazel | 16 +++ absl/random/log_uniform_int_distribution_test.cc | 2 +- absl/random/poisson_distribution_test.cc | 4 +- absl/strings/string_view_test.cc | 8 +- absl/types/any.h | 12 +- absl/types/compare.h | 150 +++++++++++++++-------- absl/types/compare_test.cc | 26 ++++ absl/utility/BUILD.bazel | 16 +++ 13 files changed, 208 insertions(+), 63 deletions(-) (limited to 'absl') diff --git a/absl/container/internal/btree.h b/absl/container/internal/btree.h index 9561a4d62fe4..b255984174e6 100644 --- a/absl/container/internal/btree.h +++ b/absl/container/internal/btree.h @@ -2082,6 +2082,7 @@ auto btree

::rebalance_after_delete(iterator iter) -> iterator { if (!merged) { break; } + iter.position = iter.node->position(); iter.node = iter.node->parent(); } diff --git a/absl/meta/BUILD.bazel b/absl/meta/BUILD.bazel index 8db8dd6b1581..c06d2d9708c1 100644 --- a/absl/meta/BUILD.bazel +++ b/absl/meta/BUILD.bazel @@ -1,3 +1,19 @@ +# +# Copyright 2019 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. +# + load("@rules_cc//cc:defs.bzl", "cc_library", "cc_test") load( "//absl:copts/configure_copts.bzl", diff --git a/absl/random/BUILD.bazel b/absl/random/BUILD.bazel index 4e210e71d6c8..be6414742f7c 100644 --- a/absl/random/BUILD.bazel +++ b/absl/random/BUILD.bazel @@ -1,3 +1,19 @@ +# +# Copyright 2019 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. +# + # ABSL random-number generation libraries. load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_library", "cc_test") diff --git a/absl/random/exponential_distribution_test.cc b/absl/random/exponential_distribution_test.cc index 6f8865c2599f..dc49044d3b76 100644 --- a/absl/random/exponential_distribution_test.cc +++ b/absl/random/exponential_distribution_test.cc @@ -346,7 +346,7 @@ std::string ParamName(const ::testing::TestParamInfo& info) { return absl::StrReplaceAll(name, {{"+", "_"}, {"-", "_"}, {".", "_"}}); } -INSTANTIATE_TEST_CASE_P(, ExponentialDistributionTests, +INSTANTIATE_TEST_CASE_P(All, ExponentialDistributionTests, ::testing::ValuesIn(GenParams()), ParamName); // NOTE: absl::exponential_distribution is not guaranteed to be stable. diff --git a/absl/random/gaussian_distribution_test.cc b/absl/random/gaussian_distribution_test.cc index 47c2989d340b..49c07513bf22 100644 --- a/absl/random/gaussian_distribution_test.cc +++ b/absl/random/gaussian_distribution_test.cc @@ -394,7 +394,7 @@ std::string ParamName(const ::testing::TestParamInfo& info) { return absl::StrReplaceAll(name, {{"+", "_"}, {"-", "_"}, {".", "_"}}); } -INSTANTIATE_TEST_SUITE_P(, GaussianDistributionTests, +INSTANTIATE_TEST_SUITE_P(All, GaussianDistributionTests, ::testing::ValuesIn(GenParams()), ParamName); // NOTE: absl::gaussian_distribution is not guaranteed to be stable. diff --git a/absl/random/internal/BUILD.bazel b/absl/random/internal/BUILD.bazel index 5e7c16f322a2..21fa43ca8c9e 100644 --- a/absl/random/internal/BUILD.bazel +++ b/absl/random/internal/BUILD.bazel @@ -1,3 +1,19 @@ +# +# Copyright 2019 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. +# + load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_library", "cc_test") # Internal-only implementation classes for Abseil Random diff --git a/absl/random/log_uniform_int_distribution_test.cc b/absl/random/log_uniform_int_distribution_test.cc index 0ff4c32d95d6..5270531d2035 100644 --- a/absl/random/log_uniform_int_distribution_test.cc +++ b/absl/random/log_uniform_int_distribution_test.cc @@ -243,7 +243,7 @@ std::string ParamName( return absl::StrReplaceAll(name, {{"+", "_"}, {"-", "_"}, {".", "_"}}); } -INSTANTIATE_TEST_SUITE_P(, LogUniformIntChiSquaredTest, +INSTANTIATE_TEST_SUITE_P(All, LogUniformIntChiSquaredTest, ::testing::ValuesIn(GenParams()), ParamName); // NOTE: absl::log_uniform_int_distribution is not guaranteed to be stable. diff --git a/absl/random/poisson_distribution_test.cc b/absl/random/poisson_distribution_test.cc index 6d68999a3c54..9d215fbc70f1 100644 --- a/absl/random/poisson_distribution_test.cc +++ b/absl/random/poisson_distribution_test.cc @@ -339,7 +339,7 @@ std::string ZParamName(const ::testing::TestParamInfo& info) { return absl::StrReplaceAll(name, {{"+", "_"}, {"-", "_"}, {".", "_"}}); } -INSTANTIATE_TEST_SUITE_P(, PoissonDistributionZTest, +INSTANTIATE_TEST_SUITE_P(All, PoissonDistributionZTest, ::testing::ValuesIn(GetZParams()), ZParamName); // The PoissonDistributionChiSquaredTest class provides a basic test framework @@ -468,7 +468,7 @@ TEST_P(PoissonDistributionChiSquaredTest, AbslPoissonDistribution) { EXPECT_LE(failures, 4); } -INSTANTIATE_TEST_SUITE_P(, PoissonDistributionChiSquaredTest, +INSTANTIATE_TEST_SUITE_P(All, PoissonDistributionChiSquaredTest, ::testing::Values(0.5, 1.0, 2.0, 10.0, 50.0, 51.0, 200.0)); diff --git a/absl/strings/string_view_test.cc b/absl/strings/string_view_test.cc index b4ed8a74603c..4f531226dfe2 100644 --- a/absl/strings/string_view_test.cc +++ b/absl/strings/string_view_test.cc @@ -822,15 +822,17 @@ TEST(StringViewTest, FrontBackSingleChar) { // "read of dereferenced null pointer is not allowed in a constant expression". // At run time, the behavior of `std::char_traits::length()` on `nullptr` is // undefined by the standard and usually results in crash with libc++. +// GCC also started rejected this in libstdc++ starting in GCC9. // In MSVC, creating a constexpr string_view from nullptr also triggers an // "unevaluable pointer value" error. This compiler implementation conforms // to the standard, but `absl::string_view` implements a different // behavior for historical reasons. We work around tests that construct // `string_view` from `nullptr` when using libc++. -#if !defined(ABSL_HAVE_STD_STRING_VIEW) || \ - (!defined(_LIBCPP_VERSION) && !defined(_MSC_VER)) +#if !defined(ABSL_HAVE_STD_STRING_VIEW) || \ + (!(defined(_GLIBCXX_RELEASE) && _GLIBCXX_RELEASE >= 9) && \ + !defined(_LIBCPP_VERSION) && !defined(_MSC_VER)) #define ABSL_HAVE_STRING_VIEW_FROM_NULLPTR 1 -#endif // !defined(ABSL_HAVE_STD_STRING_VIEW) || !defined(_LIBCPP_VERSION) +#endif TEST(StringViewTest, NULLInput) { absl::string_view s; diff --git a/absl/types/any.h b/absl/types/any.h index f3a32812662f..d2e2533f05bc 100644 --- a/absl/types/any.h +++ b/absl/types/any.h @@ -515,18 +515,22 @@ ValueType any_cast(any&& operand) { // Description at the declaration site (top of file). template const T* any_cast(const any* operand) noexcept { - return operand && operand->GetObjTypeId() == any::IdForType() + using U = + typename std::remove_cv::type>::type; + return operand && operand->GetObjTypeId() == any::IdForType() ? std::addressof( - static_cast*>(operand->obj_.get())->value) + static_cast*>(operand->obj_.get())->value) : nullptr; } // Description at the declaration site (top of file). template T* any_cast(any* operand) noexcept { - return operand && operand->GetObjTypeId() == any::IdForType() + using U = + typename std::remove_cv::type>::type; + return operand && operand->GetObjTypeId() == any::IdForType() ? std::addressof( - static_cast*>(operand->obj_.get())->value) + static_cast*>(operand->obj_.get())->value) : nullptr; } diff --git a/absl/types/compare.h b/absl/types/compare.h index 50361d623025..a213e0b0b682 100644 --- a/absl/types/compare.h +++ b/absl/types/compare.h @@ -79,79 +79,72 @@ enum class ord : value_type { less = -1, greater = 1 }; enum class ncmp : value_type { unordered = -127 }; +// Define macros to allow for creation or emulation of C++17 inline variables +// based on whether the feature is supported. Note: we can't use +// ABSL_INTERNAL_INLINE_CONSTEXPR here because the variables here are of +// incomplete types so they need to be defined after the types are complete. +#ifdef __cpp_inline_variables + +#define ABSL_COMPARE_INLINE_BASECLASS_DECL(name) + +#define ABSL_COMPARE_INLINE_SUBCLASS_DECL(type, name) \ + static const type name + +#define ABSL_COMPARE_INLINE_INIT(type, name, init) \ + inline constexpr type type::name(init) + +#else // __cpp_inline_variables + +#define ABSL_COMPARE_INLINE_BASECLASS_DECL(name) \ + ABSL_CONST_INIT static const T name + +#define ABSL_COMPARE_INLINE_SUBCLASS_DECL(type, name) + +#define ABSL_COMPARE_INLINE_INIT(type, name, init) \ + template \ + const T compare_internal::type##_base::name(init) + +#endif // __cpp_inline_variables + // These template base classes allow for defining the values of the constants // in the header file (for performance) without using inline variables (which // aren't available in C++11). template struct weak_equality_base { - ABSL_CONST_INIT static const T equivalent; - ABSL_CONST_INIT static const T nonequivalent; + ABSL_COMPARE_INLINE_BASECLASS_DECL(equivalent); + ABSL_COMPARE_INLINE_BASECLASS_DECL(nonequivalent); }; -template -const T weak_equality_base::equivalent(eq::equivalent); -template -const T weak_equality_base::nonequivalent(eq::nonequivalent); template struct strong_equality_base { - ABSL_CONST_INIT static const T equal; - ABSL_CONST_INIT static const T nonequal; - ABSL_CONST_INIT static const T equivalent; - ABSL_CONST_INIT static const T nonequivalent; + ABSL_COMPARE_INLINE_BASECLASS_DECL(equal); + ABSL_COMPARE_INLINE_BASECLASS_DECL(nonequal); + ABSL_COMPARE_INLINE_BASECLASS_DECL(equivalent); + ABSL_COMPARE_INLINE_BASECLASS_DECL(nonequivalent); }; -template -const T strong_equality_base::equal(eq::equal); -template -const T strong_equality_base::nonequal(eq::nonequal); -template -const T strong_equality_base::equivalent(eq::equivalent); -template -const T strong_equality_base::nonequivalent(eq::nonequivalent); template struct partial_ordering_base { - ABSL_CONST_INIT static const T less; - ABSL_CONST_INIT static const T equivalent; - ABSL_CONST_INIT static const T greater; - ABSL_CONST_INIT static const T unordered; + ABSL_COMPARE_INLINE_BASECLASS_DECL(less); + ABSL_COMPARE_INLINE_BASECLASS_DECL(equivalent); + ABSL_COMPARE_INLINE_BASECLASS_DECL(greater); + ABSL_COMPARE_INLINE_BASECLASS_DECL(unordered); }; -template -const T partial_ordering_base::less(ord::less); -template -const T partial_ordering_base::equivalent(eq::equivalent); -template -const T partial_ordering_base::greater(ord::greater); -template -const T partial_ordering_base::unordered(ncmp::unordered); template struct weak_ordering_base { - ABSL_CONST_INIT static const T less; - ABSL_CONST_INIT static const T equivalent; - ABSL_CONST_INIT static const T greater; + ABSL_COMPARE_INLINE_BASECLASS_DECL(less); + ABSL_COMPARE_INLINE_BASECLASS_DECL(equivalent); + ABSL_COMPARE_INLINE_BASECLASS_DECL(greater); }; -template -const T weak_ordering_base::less(ord::less); -template -const T weak_ordering_base::equivalent(eq::equivalent); -template -const T weak_ordering_base::greater(ord::greater); template struct strong_ordering_base { - ABSL_CONST_INIT static const T less; - ABSL_CONST_INIT static const T equal; - ABSL_CONST_INIT static const T equivalent; - ABSL_CONST_INIT static const T greater; + ABSL_COMPARE_INLINE_BASECLASS_DECL(less); + ABSL_COMPARE_INLINE_BASECLASS_DECL(equal); + ABSL_COMPARE_INLINE_BASECLASS_DECL(equivalent); + ABSL_COMPARE_INLINE_BASECLASS_DECL(greater); }; -template -const T strong_ordering_base::less(ord::less); -template -const T strong_ordering_base::equal(eq::equal); -template -const T strong_ordering_base::equivalent(eq::equivalent); -template -const T strong_ordering_base::greater(ord::greater); } // namespace compare_internal @@ -162,6 +155,9 @@ class weak_equality friend struct compare_internal::weak_equality_base; public: + ABSL_COMPARE_INLINE_SUBCLASS_DECL(weak_equality, equivalent); + ABSL_COMPARE_INLINE_SUBCLASS_DECL(weak_equality, nonequivalent); + // Comparisons friend constexpr bool operator==( weak_equality v, compare_internal::OnlyLiteralZero<>) noexcept { @@ -183,6 +179,10 @@ class weak_equality private: compare_internal::value_type value_; }; +ABSL_COMPARE_INLINE_INIT(weak_equality, equivalent, + compare_internal::eq::equivalent); +ABSL_COMPARE_INLINE_INIT(weak_equality, nonequivalent, + compare_internal::eq::nonequivalent); class strong_equality : public compare_internal::strong_equality_base { @@ -191,6 +191,11 @@ class strong_equality friend struct compare_internal::strong_equality_base; public: + ABSL_COMPARE_INLINE_SUBCLASS_DECL(strong_equality, equal); + ABSL_COMPARE_INLINE_SUBCLASS_DECL(strong_equality, nonequal); + ABSL_COMPARE_INLINE_SUBCLASS_DECL(strong_equality, equivalent); + ABSL_COMPARE_INLINE_SUBCLASS_DECL(strong_equality, nonequivalent); + // Conversion constexpr operator weak_equality() const noexcept { // NOLINT return value_ == 0 ? weak_equality::equivalent @@ -217,6 +222,13 @@ class strong_equality private: compare_internal::value_type value_; }; +ABSL_COMPARE_INLINE_INIT(strong_equality, equal, compare_internal::eq::equal); +ABSL_COMPARE_INLINE_INIT(strong_equality, nonequal, + compare_internal::eq::nonequal); +ABSL_COMPARE_INLINE_INIT(strong_equality, equivalent, + compare_internal::eq::equivalent); +ABSL_COMPARE_INLINE_INIT(strong_equality, nonequivalent, + compare_internal::eq::nonequivalent); class partial_ordering : public compare_internal::partial_ordering_base { @@ -234,6 +246,11 @@ class partial_ordering } public: + ABSL_COMPARE_INLINE_SUBCLASS_DECL(partial_ordering, less); + ABSL_COMPARE_INLINE_SUBCLASS_DECL(partial_ordering, equivalent); + ABSL_COMPARE_INLINE_SUBCLASS_DECL(partial_ordering, greater); + ABSL_COMPARE_INLINE_SUBCLASS_DECL(partial_ordering, unordered); + // Conversion constexpr operator weak_equality() const noexcept { // NOLINT return value_ == 0 ? weak_equality::equivalent @@ -292,6 +309,13 @@ class partial_ordering private: compare_internal::value_type value_; }; +ABSL_COMPARE_INLINE_INIT(partial_ordering, less, compare_internal::ord::less); +ABSL_COMPARE_INLINE_INIT(partial_ordering, equivalent, + compare_internal::eq::equivalent); +ABSL_COMPARE_INLINE_INIT(partial_ordering, greater, + compare_internal::ord::greater); +ABSL_COMPARE_INLINE_INIT(partial_ordering, unordered, + compare_internal::ncmp::unordered); class weak_ordering : public compare_internal::weak_ordering_base { @@ -302,6 +326,10 @@ class weak_ordering friend struct compare_internal::weak_ordering_base; public: + ABSL_COMPARE_INLINE_SUBCLASS_DECL(weak_ordering, less); + ABSL_COMPARE_INLINE_SUBCLASS_DECL(weak_ordering, equivalent); + ABSL_COMPARE_INLINE_SUBCLASS_DECL(weak_ordering, greater); + // Conversions constexpr operator weak_equality() const noexcept { // NOLINT return value_ == 0 ? weak_equality::equivalent @@ -365,6 +393,11 @@ class weak_ordering private: compare_internal::value_type value_; }; +ABSL_COMPARE_INLINE_INIT(weak_ordering, less, compare_internal::ord::less); +ABSL_COMPARE_INLINE_INIT(weak_ordering, equivalent, + compare_internal::eq::equivalent); +ABSL_COMPARE_INLINE_INIT(weak_ordering, greater, + compare_internal::ord::greater); class strong_ordering : public compare_internal::strong_ordering_base { @@ -375,6 +408,11 @@ class strong_ordering friend struct compare_internal::strong_ordering_base; public: + ABSL_COMPARE_INLINE_SUBCLASS_DECL(strong_ordering, less); + ABSL_COMPARE_INLINE_SUBCLASS_DECL(strong_ordering, equal); + ABSL_COMPARE_INLINE_SUBCLASS_DECL(strong_ordering, equivalent); + ABSL_COMPARE_INLINE_SUBCLASS_DECL(strong_ordering, greater); + // Conversions constexpr operator weak_equality() const noexcept { // NOLINT return value_ == 0 ? weak_equality::equivalent @@ -446,6 +484,16 @@ class strong_ordering private: compare_internal::value_type value_; }; +ABSL_COMPARE_INLINE_INIT(strong_ordering, less, compare_internal::ord::less); +ABSL_COMPARE_INLINE_INIT(strong_ordering, equal, compare_internal::eq::equal); +ABSL_COMPARE_INLINE_INIT(strong_ordering, equivalent, + compare_internal::eq::equivalent); +ABSL_COMPARE_INLINE_INIT(strong_ordering, greater, + compare_internal::ord::greater); + +#undef ABSL_COMPARE_INLINE_BASECLASS_DECL +#undef ABSL_COMPARE_INLINE_SUBCLASS_DECL +#undef ABSL_COMPARE_INLINE_INIT namespace compare_internal { // We also provide these comparator adapter functions for internal absl use. diff --git a/absl/types/compare_test.cc b/absl/types/compare_test.cc index 3a8554219274..ee396fc54d7c 100644 --- a/absl/types/compare_test.cc +++ b/absl/types/compare_test.cc @@ -307,5 +307,31 @@ TEST(DoThreeWayComparison, SanityTest) { absl::compare_internal::do_three_way_comparison(weak, 10, 5) > 0)); } +#ifdef __cpp_inline_variables +TEST(Compare, StaticAsserts) { + static_assert(weak_equality::equivalent == 0, ""); + static_assert(weak_equality::nonequivalent != 0, ""); + + static_assert(strong_equality::equal == 0, ""); + static_assert(strong_equality::nonequal != 0, ""); + static_assert(strong_equality::equivalent == 0, ""); + static_assert(strong_equality::nonequivalent != 0, ""); + + static_assert(partial_ordering::less < 0, ""); + static_assert(partial_ordering::equivalent == 0, ""); + static_assert(partial_ordering::greater > 0, ""); + static_assert(partial_ordering::unordered != 0, ""); + + static_assert(weak_ordering::less < 0, ""); + static_assert(weak_ordering::equivalent == 0, ""); + static_assert(weak_ordering::greater > 0, ""); + + static_assert(strong_ordering::less < 0, ""); + static_assert(strong_ordering::equal == 0, ""); + static_assert(strong_ordering::equivalent == 0, ""); + static_assert(strong_ordering::greater > 0, ""); +} +#endif // __cpp_inline_variables + } // namespace } // namespace absl diff --git a/absl/utility/BUILD.bazel b/absl/utility/BUILD.bazel index 280a7dd56241..61de30be0f68 100644 --- a/absl/utility/BUILD.bazel +++ b/absl/utility/BUILD.bazel @@ -1,3 +1,19 @@ +# +# Copyright 2019 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. +# + load("@rules_cc//cc:defs.bzl", "cc_library", "cc_test") load( "//absl:copts/configure_copts.bzl", -- cgit 1.4.1