mirror of
https://github.com/abseil/abseil-cpp.git
synced 2026-06-04 12:07:05 +08:00
Add ABSL_REQUIRE_EXPLICIT_INIT to Abseil to enable enforcing explicit field initializations
Also include portable fallbacks for other compilers. They don't produce good error messages, but they do prevent silent breakages on other platforms/toolchains. PiperOrigin-RevId: 723629074 Change-Id: I29ee8fbc679b70bb67d42577d0723b52268f7caf
This commit is contained in:
committed by
Copybara-Service
parent
7a03cdb4c0
commit
74058c0f49
@@ -340,6 +340,21 @@ cc_test(
|
||||
],
|
||||
)
|
||||
|
||||
cc_test(
|
||||
name = "attributes_test",
|
||||
srcs = [
|
||||
"attributes_test.cc",
|
||||
],
|
||||
copts = ABSL_TEST_COPTS,
|
||||
linkopts = ABSL_DEFAULT_LINKOPTS,
|
||||
deps = [
|
||||
":config",
|
||||
":core_headers",
|
||||
"@googletest//:gtest",
|
||||
"@googletest//:gtest_main",
|
||||
],
|
||||
)
|
||||
|
||||
cc_test(
|
||||
name = "c_header_test",
|
||||
srcs = ["c_header_test.c"],
|
||||
|
||||
@@ -371,6 +371,19 @@ absl_cc_test(
|
||||
GTest::gtest_main
|
||||
)
|
||||
|
||||
absl_cc_test(
|
||||
NAME
|
||||
attributes_test
|
||||
SRCS
|
||||
"attributes_test.cc"
|
||||
COPTS
|
||||
${ABSL_TEST_COPTS}
|
||||
DEPS
|
||||
absl::config
|
||||
absl::core_headers
|
||||
GTest::gtest_main
|
||||
)
|
||||
|
||||
absl_cc_test(
|
||||
NAME
|
||||
bit_cast_test
|
||||
|
||||
@@ -759,6 +759,71 @@
|
||||
#define ABSL_CONST_INIT
|
||||
#endif
|
||||
|
||||
// ABSL_REQUIRE_EXPLICIT_INIT
|
||||
//
|
||||
// ABSL_REQUIRE_EXPLICIT_INIT is placed *after* the data members of an aggregate
|
||||
// type to indicate that the annotated member must be explicitly initialized by
|
||||
// the user whenever the aggregate is constructed. For example:
|
||||
//
|
||||
// struct Coord {
|
||||
// int x ABSL_REQUIRE_EXPLICIT_INIT;
|
||||
// int y ABSL_REQUIRE_EXPLICIT_INIT;
|
||||
// };
|
||||
// Coord coord = {1}; // warning: field 'y' is not explicitly initialized
|
||||
//
|
||||
// Note that usage on C arrays is not supported in C++.
|
||||
// Use a struct (such as std::array) to wrap the array member instead.
|
||||
//
|
||||
// Avoid applying this attribute to the members of non-aggregate types.
|
||||
// The behavior within non-aggregates is unspecified and subject to change.
|
||||
//
|
||||
// Do NOT attempt to suppress or demote the error generated by this attribute.
|
||||
// Just like with a missing function argument, it is a hard error by design.
|
||||
//
|
||||
// See the upstream documentation for more details:
|
||||
// https://clang.llvm.org/docs/AttributeReference.html#require-explicit-initialization
|
||||
#ifdef __cplusplus
|
||||
#if ABSL_HAVE_CPP_ATTRIBUTE(clang::require_explicit_initialization)
|
||||
// clang-format off
|
||||
#define ABSL_REQUIRE_EXPLICIT_INIT \
|
||||
[[clang::require_explicit_initialization]] = \
|
||||
AbslInternal_YouForgotToExplicitlyInitializeAField::v
|
||||
#else
|
||||
#define ABSL_REQUIRE_EXPLICIT_INIT \
|
||||
= AbslInternal_YouForgotToExplicitlyInitializeAField::v
|
||||
#endif
|
||||
// clang-format on
|
||||
#else
|
||||
// clang-format off
|
||||
#if ABSL_HAVE_ATTRIBUTE(require_explicit_initialization)
|
||||
#define ABSL_REQUIRE_EXPLICIT_INIT \
|
||||
__attribute__((require_explicit_initialization))
|
||||
#else
|
||||
#define ABSL_REQUIRE_EXPLICIT_INIT \
|
||||
/* No portable fallback for C is available */
|
||||
#endif
|
||||
// clang-format on
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
struct AbslInternal_YouForgotToExplicitlyInitializeAField {
|
||||
// A portable version of [[clang::require_explicit_initialization]] that
|
||||
// never builds, as a last resort for all toolchains.
|
||||
// The error messages are poor, so we don't rely on this unless we have to.
|
||||
template <class T>
|
||||
#if !defined(SWIG)
|
||||
constexpr
|
||||
#endif
|
||||
operator T() const /* NOLINT */ {
|
||||
// Infinite loop to prevent constexpr compilation
|
||||
for (;;) {
|
||||
}
|
||||
}
|
||||
// This is deliberately left undefined to prevent linking
|
||||
static AbslInternal_YouForgotToExplicitlyInitializeAField v;
|
||||
};
|
||||
#endif
|
||||
|
||||
// ABSL_ATTRIBUTE_PURE_FUNCTION
|
||||
//
|
||||
// ABSL_ATTRIBUTE_PURE_FUNCTION is used to annotate declarations of "pure"
|
||||
|
||||
43
absl/base/attributes_test.cc
Normal file
43
absl/base/attributes_test.cc
Normal file
@@ -0,0 +1,43 @@
|
||||
// Copyright 2025 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.
|
||||
|
||||
#include "absl/base/attributes.h"
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "absl/base/config.h"
|
||||
|
||||
namespace {
|
||||
|
||||
TEST(Attributes, RequireExplicitInit) {
|
||||
struct Agg {
|
||||
int f1;
|
||||
int f2 ABSL_REQUIRE_EXPLICIT_INIT;
|
||||
};
|
||||
Agg good1 ABSL_ATTRIBUTE_UNUSED = {1, 2};
|
||||
#if ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L
|
||||
Agg good2 ABSL_ATTRIBUTE_UNUSED(1, 2);
|
||||
#endif
|
||||
Agg good3 ABSL_ATTRIBUTE_UNUSED{1, 2};
|
||||
Agg good4 ABSL_ATTRIBUTE_UNUSED = {1, 2};
|
||||
Agg good5 ABSL_ATTRIBUTE_UNUSED = Agg{1, 2};
|
||||
Agg good6[1] ABSL_ATTRIBUTE_UNUSED = {{1, 2}};
|
||||
Agg good7[1] ABSL_ATTRIBUTE_UNUSED = {Agg{1, 2}};
|
||||
union {
|
||||
Agg agg;
|
||||
} good8 ABSL_ATTRIBUTE_UNUSED = {{1, 2}};
|
||||
constexpr Agg good9 ABSL_ATTRIBUTE_UNUSED = {1, 2};
|
||||
constexpr Agg good10 ABSL_ATTRIBUTE_UNUSED{1, 2};
|
||||
}
|
||||
|
||||
} // namespace
|
||||
Reference in New Issue
Block a user