Skip to content

Commit 10f7c5f

Browse files
authored
CXX-2745 Define and use BSONCXX_PRIVATE_INLINE_CXX17 for inline variables (#1468)
1 parent c3130ec commit 10f7c5f

File tree

13 files changed

+103
-87
lines changed

13 files changed

+103
-87
lines changed

src/bsoncxx/include/bsoncxx/v1/detail/compare.hpp

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -93,23 +93,22 @@ class strong_ordering {
9393
#pragma pop_macro("DEFOP")
9494

9595
// nonstd: Swap greater/less values
96-
constexpr strong_ordering inverted() const noexcept {
97-
return *this < nullptr ? greater : *this > nullptr ? less : *this;
98-
}
96+
constexpr strong_ordering inverted() const noexcept;
9997
};
10098

101-
#pragma push_macro("INLINE_VAR")
102-
#undef INLINE_VAR
103-
#define INLINE_VAR \
104-
BSONCXX_PRIVATE_IF_GNU_LIKE([[gnu::weak]]) \
105-
BSONCXX_PRIVATE_IF_MSVC(__declspec(selectany))
106-
107-
INLINE_VAR const strong_ordering strong_ordering::less = strong_ordering(strong_ordering::_construct{}, -1);
108-
INLINE_VAR const strong_ordering strong_ordering::greater = strong_ordering(strong_ordering::_construct{}, 1);
109-
INLINE_VAR const strong_ordering strong_ordering::equivalent = strong_ordering(strong_ordering::_construct{}, 0);
110-
INLINE_VAR const strong_ordering strong_ordering::equal = strong_ordering(strong_ordering::_construct{}, 0);
111-
112-
#pragma pop_macro("INLINE_VAR")
99+
BSONCXX_PRIVATE_INLINE_CXX17 strong_ordering const strong_ordering::less =
100+
strong_ordering(strong_ordering::_construct{}, -1);
101+
BSONCXX_PRIVATE_INLINE_CXX17 strong_ordering const strong_ordering::greater =
102+
strong_ordering(strong_ordering::_construct{}, 1);
103+
BSONCXX_PRIVATE_INLINE_CXX17 strong_ordering const strong_ordering::equivalent =
104+
strong_ordering(strong_ordering::_construct{}, 0);
105+
BSONCXX_PRIVATE_INLINE_CXX17 strong_ordering const strong_ordering::equal =
106+
strong_ordering(strong_ordering::_construct{}, 0);
107+
108+
// Define out-of-line to avoid GCC error: ‘bsoncxx::detail::strong_ordering::*’ declared weak after being used
109+
inline constexpr strong_ordering strong_ordering::inverted() const noexcept {
110+
return *this < nullptr ? greater : *this > nullptr ? less : *this;
111+
}
113112

114113
// Implements a three-way comparison between two objects. That is, in
115114
// a single operation, determine whether the left operand is less-than, greater-than,

src/bsoncxx/include/bsoncxx/v1/detail/macros.hpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,31 @@
107107
#endif
108108
// clang-format on
109109

110+
// Use this on variables that can only be inline in C++17 or newer, such as static constexpr data members.
111+
//
112+
// GCC does not allow __inline__ (even with __extension__) given -std=c++11 and -pedantic-errors (unconditional
113+
// compilation error until GCC 12 which added -Wc++17-extensions suppression), but supports [[gnu::weak]] even with
114+
// constant-evaluation and constant-folding on all currently-supported GCC versions (GCC 4.8.x and newer).
115+
//
116+
// Clang: does not allow using [[gnu::weak]] with constexpr, but supports __inline__ as a language extension even with
117+
// -std=c++11 and -pedantic-errors via diagnostic suppression on all currently-supported Clang versions
118+
// (-Wc++1z-extensions suppression since Clang 3.9 and -Wc++17-extensions suppression since Clang 5.0).
119+
//
120+
// MSVC: supports inline variables since 19.12 (with /std:c++latest), but behavior is broken for static data members
121+
// (multiple definitions) until 19.20 even when __cpp_inline_variables is defined.
122+
#if ( \
123+
!defined(_MSC_VER) && \
124+
(__cplusplus >= 201703L || (defined(__cpp_inline_variables) && __cpp_inline_variables >= 201606L))) || \
125+
(defined(_MSC_VER) && _MSC_VER >= 1920 && defined(_MSVC_LANG) && _MSVC_LANG >= 201703L)
126+
#define BSONCXX_PRIVATE_INLINE_CXX17 inline
127+
#else
128+
#define BSONCXX_PRIVATE_INLINE_CXX17 \
129+
BSONCXX_PRIVATE_IF_GCC([[gnu::weak]]) \
130+
BSONCXX_PRIVATE_IF_CLANG(_Pragma("clang diagnostic push") _Pragma( \
131+
"clang diagnostic ignored \"-Wc++17-extensions\"") __inline__ _Pragma("clang diagnostic pop")) \
132+
BSONCXX_PRIVATE_IF_MSVC(__declspec(selectany))
133+
#endif
134+
110135
// Disable a warning for a particular compiler.
111136
//
112137
// The argument should be of the form:

src/bsoncxx/include/bsoncxx/v1/detail/postlude.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
#pragma pop_macro("BSONCXX_PRIVATE_IF_GCC")
5252
#pragma pop_macro("BSONCXX_PRIVATE_IF_GNU_LIKE")
5353
#pragma pop_macro("BSONCXX_PRIVATE_IF_MSVC")
54+
#pragma pop_macro("BSONCXX_PRIVATE_INLINE_CXX17")
5455
#pragma pop_macro("BSONCXX_PRIVATE_PRAGMA_IMPL")
5556
#pragma pop_macro("BSONCXX_PRIVATE_PRAGMA")
5657
#pragma pop_macro("BSONCXX_PRIVATE_RETURNS")

src/bsoncxx/include/bsoncxx/v1/detail/prelude.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,8 @@
7676
#undef BSONCXX_PRIVATE_IF_GNU_LIKE
7777
#pragma push_macro("BSONCXX_PRIVATE_IF_MSVC")
7878
#undef BSONCXX_PRIVATE_IF_MSVC
79+
#pragma push_macro("BSONCXX_PRIVATE_INLINE_CXX17")
80+
#undef BSONCXX_PRIVATE_INLINE_CXX17
7981
#pragma push_macro("BSONCXX_PRIVATE_PRAGMA")
8082
#undef BSONCXX_PRIVATE_PRAGMA
8183
#pragma push_macro("BSONCXX_PRIVATE_PRAGMA_IMPL")

src/bsoncxx/include/bsoncxx/v1/oid.hpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ class oid {
4343
///
4444
/// The number of bytes required to represent an ObjectID.
4545
///
46-
static constexpr BSONCXX_ABI_EXPORT std::size_t k_oid_length = 12;
46+
static constexpr std::size_t k_oid_length = 12;
4747

4848
private:
4949
std::array<std::uint8_t, k_oid_length> _bytes;
@@ -198,6 +198,8 @@ class oid {
198198
/* explicit(false) */ oid(for_overwrite_tag) : _bytes{} {}
199199
};
200200

201+
BSONCXX_PRIVATE_INLINE_CXX17 constexpr std::size_t oid::k_oid_length;
202+
201203
} // namespace v1
202204
} // namespace bsoncxx
203205

src/bsoncxx/include/bsoncxx/v1/types/view.hpp

Lines changed: 27 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ struct b_double {
4949
///
5050
/// The type represented by this BSON type value.
5151
///
52-
static constexpr BSONCXX_ABI_EXPORT id type_id = id::k_double;
52+
static constexpr id type_id = id::k_double;
5353

5454
///
5555
/// The represented value.
@@ -100,7 +100,7 @@ struct b_string {
100100
///
101101
/// The type represented by this BSON type value.
102102
///
103-
static constexpr BSONCXX_ABI_EXPORT id type_id = id::k_string;
103+
static constexpr id type_id = id::k_string;
104104

105105
///
106106
/// The represented value.
@@ -148,7 +148,7 @@ struct b_document {
148148
///
149149
/// The type represented by this BSON type value.
150150
///
151-
static constexpr BSONCXX_ABI_EXPORT id type_id = id::k_document;
151+
static constexpr id type_id = id::k_document;
152152

153153
///
154154
/// The represented value.
@@ -200,7 +200,7 @@ struct b_array {
200200
///
201201
/// The type represented by this BSON type value.
202202
///
203-
static constexpr BSONCXX_ABI_EXPORT id type_id = id::k_array;
203+
static constexpr id type_id = id::k_array;
204204

205205
///
206206
/// The represented value.
@@ -248,7 +248,7 @@ struct b_binary {
248248
///
249249
/// The type represented by this BSON type value.
250250
///
251-
static constexpr BSONCXX_ABI_EXPORT id type_id = id::k_binary;
251+
static constexpr id type_id = id::k_binary;
252252

253253
///
254254
/// The represented value's binary subtype component.
@@ -317,7 +317,7 @@ struct b_undefined {
317317
///
318318
/// The type represented by this BSON type value.
319319
///
320-
static constexpr BSONCXX_ABI_EXPORT id type_id = id::k_undefined;
320+
static constexpr id type_id = id::k_undefined;
321321

322322
///
323323
/// Return true.
@@ -343,7 +343,7 @@ struct b_oid {
343343
///
344344
/// The type represented by this BSON type value.
345345
///
346-
static constexpr BSONCXX_ABI_EXPORT id type_id = id::k_oid;
346+
static constexpr id type_id = id::k_oid;
347347

348348
///
349349
/// The represented value.
@@ -391,7 +391,7 @@ struct b_bool {
391391
///
392392
/// The type represented by this BSON type value.
393393
///
394-
static constexpr BSONCXX_ABI_EXPORT id type_id = id::k_bool;
394+
static constexpr id type_id = id::k_bool;
395395

396396
///
397397
/// The represented value.
@@ -439,7 +439,7 @@ struct b_date {
439439
///
440440
/// The type represented by this BSON type value.
441441
///
442-
static constexpr BSONCXX_ABI_EXPORT id type_id = id::k_date;
442+
static constexpr id type_id = id::k_date;
443443

444444
///
445445
/// The represented value (milliseconds relative to the Unix epoch).
@@ -498,7 +498,7 @@ struct b_null {
498498
///
499499
/// The type represented by this BSON type value.
500500
///
501-
static constexpr BSONCXX_ABI_EXPORT id type_id = id::k_null;
501+
static constexpr id type_id = id::k_null;
502502

503503
///
504504
/// Return true.
@@ -524,7 +524,7 @@ struct b_regex {
524524
///
525525
/// The type represented by this BSON type value.
526526
///
527-
static constexpr BSONCXX_ABI_EXPORT id type_id = id::k_regex;
527+
static constexpr id type_id = id::k_regex;
528528

529529
///
530530
/// The represented value's "pattern" component.
@@ -577,7 +577,7 @@ struct b_dbpointer {
577577
///
578578
/// The type represented by this BSON type value.
579579
///
580-
static constexpr BSONCXX_ABI_EXPORT id type_id = id::k_dbpointer;
580+
static constexpr id type_id = id::k_dbpointer;
581581

582582
///
583583
/// The represented value's "$ref" (namespace) component.
@@ -623,7 +623,7 @@ struct b_code {
623623
///
624624
/// The type represented by this BSON type value.
625625
///
626-
static constexpr BSONCXX_ABI_EXPORT id type_id = id::k_code;
626+
static constexpr id type_id = id::k_code;
627627

628628
///
629629
/// The represented value.
@@ -673,7 +673,7 @@ struct b_symbol {
673673
///
674674
/// The type represented by this BSON type value.
675675
///
676-
static constexpr BSONCXX_ABI_EXPORT id type_id = id::k_symbol;
676+
static constexpr id type_id = id::k_symbol;
677677

678678
///
679679
/// The represented value.
@@ -723,7 +723,7 @@ struct b_codewscope {
723723
///
724724
/// The type represented by this BSON type value.
725725
///
726-
static constexpr BSONCXX_ABI_EXPORT id type_id = id::k_codewscope;
726+
static constexpr id type_id = id::k_codewscope;
727727

728728
///
729729
/// The represented value's "$code" component.
@@ -769,7 +769,7 @@ struct b_int32 {
769769
///
770770
/// The type represented by this BSON type value.
771771
///
772-
static constexpr BSONCXX_ABI_EXPORT id type_id = id::k_int32;
772+
static constexpr id type_id = id::k_int32;
773773

774774
///
775775
/// The represented value.
@@ -817,7 +817,7 @@ struct b_timestamp {
817817
///
818818
/// The type represented by this BSON type value.
819819
///
820-
static constexpr BSONCXX_ABI_EXPORT id type_id = id::k_timestamp;
820+
static constexpr id type_id = id::k_timestamp;
821821

822822
///
823823
/// The represented value's "i" component.
@@ -863,7 +863,7 @@ struct b_int64 {
863863
///
864864
/// The type represented by this BSON type value.
865865
///
866-
static constexpr BSONCXX_ABI_EXPORT id type_id = id::k_int64;
866+
static constexpr id type_id = id::k_int64;
867867

868868
///
869869
/// The represented value.
@@ -911,7 +911,7 @@ struct b_decimal128 {
911911
///
912912
/// The type represented by this BSON type value.
913913
///
914-
static constexpr BSONCXX_ABI_EXPORT id type_id = id::k_decimal128;
914+
static constexpr id type_id = id::k_decimal128;
915915

916916
///
917917
/// The represented value.
@@ -959,7 +959,7 @@ struct b_maxkey {
959959
///
960960
/// The type represented by this BSON type value.
961961
///
962-
static constexpr BSONCXX_ABI_EXPORT id type_id = id::k_maxkey;
962+
static constexpr id type_id = id::k_maxkey;
963963

964964
///
965965
/// Return true.
@@ -985,7 +985,7 @@ struct b_minkey {
985985
///
986986
/// The type represented by this BSON type value.
987987
///
988-
static constexpr BSONCXX_ABI_EXPORT id type_id = id::k_minkey;
988+
static constexpr id type_id = id::k_minkey;
989989

990990
///
991991
/// Return true.
@@ -1004,6 +1004,12 @@ struct b_minkey {
10041004

10051005
// BSONCXX_V1_TYPES_XMACRO: update above.
10061006

1007+
#pragma push_macro("X")
1008+
#undef X
1009+
#define X(_name, _val) BSONCXX_PRIVATE_INLINE_CXX17 constexpr id b_##_name::type_id;
1010+
BSONCXX_V1_TYPES_XMACRO(X)
1011+
#pragma pop_macro("X")
1012+
10071013
///
10081014
/// A non-owning, read-only union of BSON type values.
10091015
///

src/bsoncxx/include/bsoncxx/v_noabi/bsoncxx/oid.hpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ class oid {
4343
v1::oid _oid;
4444

4545
public:
46-
static constexpr BSONCXX_ABI_EXPORT std::size_t k_oid_length = v1::oid::k_oid_length;
46+
static constexpr std::size_t k_oid_length = v1::oid::k_oid_length;
4747

4848
///
4949
/// Constructs an oid and initializes it to a newly generated ObjectId.
@@ -165,6 +165,8 @@ class oid {
165165
friend BSONCXX_ABI_EXPORT_CDECL(int) oid_compare(oid const& lhs, oid const& rhs);
166166
};
167167

168+
BSONCXX_PRIVATE_INLINE_CXX17 constexpr std::size_t oid::k_oid_length;
169+
168170
///
169171
/// Convert to the @ref bsoncxx::v_noabi equivalent of `v`.
170172
///

0 commit comments

Comments
 (0)