Skip to content

Commit 5eec6ac

Browse files
authored
Merge pull request #2013 from Ivorforce/defs-10.x
Sync `defs.hpp` with godot upstream.
2 parents 51d1866 + 5a0945e commit 5eec6ac

7 files changed

Lines changed: 319 additions & 113 deletions

File tree

cmake/common_compiler_flags.cmake

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,9 @@ function(common_compiler_flags)
8888

8989
# Interpret source files as utf-8
9090
/utf-8
91+
92+
# Allow use of `__cplusplus` macro to determine C++ standard universally.
93+
/Zc:__cplusplus
9194
>
9295

9396
# Warnings below, these do not need to propagate to consumers.

include/godot_cpp/core/binder_common.hpp

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,7 @@ template <typename T, typename... P, size_t... Is>
232232
void call_with_variant_args_helper(T *p_instance, void (T::*p_method)(P...), const Variant **p_args, GDExtensionCallError &r_error, IndexSequence<Is...>) {
233233
r_error.error = GDEXTENSION_CALL_OK;
234234

235-
#ifdef DEBUG_METHODS_ENABLED
235+
#ifdef DEBUG_ENABLED
236236
(p_instance->*p_method)(VariantCasterAndValidate<P>::cast(p_args, Is, r_error)...);
237237
#else
238238
(p_instance->*p_method)(VariantCaster<P>::cast(*p_args[Is])...);
@@ -244,7 +244,7 @@ template <typename T, typename... P, size_t... Is>
244244
void call_with_variant_argsc_helper(T *p_instance, void (T::*p_method)(P...) const, const Variant **p_args, GDExtensionCallError &r_error, IndexSequence<Is...>) {
245245
r_error.error = GDEXTENSION_CALL_OK;
246246

247-
#ifdef DEBUG_METHODS_ENABLED
247+
#ifdef DEBUG_ENABLED
248248
(p_instance->*p_method)(VariantCasterAndValidate<P>::cast(p_args, Is, r_error)...);
249249
#else
250250
(p_instance->*p_method)(VariantCaster<P>::cast(*p_args[Is])...);
@@ -256,7 +256,7 @@ template <typename T, typename R, typename... P, size_t... Is>
256256
void call_with_variant_args_ret_helper(T *p_instance, R (T::*p_method)(P...), const Variant **p_args, Variant &r_ret, GDExtensionCallError &r_error, IndexSequence<Is...>) {
257257
r_error.error = GDEXTENSION_CALL_OK;
258258

259-
#ifdef DEBUG_METHODS_ENABLED
259+
#ifdef DEBUG_ENABLED
260260
r_ret = (p_instance->*p_method)(VariantCasterAndValidate<P>::cast(p_args, Is, r_error)...);
261261
#else
262262
r_ret = (p_instance->*p_method)(VariantCaster<P>::cast(*p_args[Is])...);
@@ -268,7 +268,7 @@ template <typename T, typename R, typename... P, size_t... Is>
268268
void call_with_variant_args_retc_helper(T *p_instance, R (T::*p_method)(P...) const, const Variant **p_args, Variant &r_ret, GDExtensionCallError &r_error, IndexSequence<Is...>) {
269269
r_error.error = GDEXTENSION_CALL_OK;
270270

271-
#ifdef DEBUG_METHODS_ENABLED
271+
#ifdef DEBUG_ENABLED
272272
r_ret = (p_instance->*p_method)(VariantCasterAndValidate<P>::cast(p_args, Is, r_error)...);
273273
#else
274274
r_ret = (p_instance->*p_method)(VariantCaster<P>::cast(*p_args[Is])...);
@@ -472,7 +472,7 @@ void call_with_variant_args_retc_dv(T *p_instance, R (T::*p_method)(P...) const,
472472

473473
// GCC raises "parameter 'p_args' set but not used" when P = {},
474474
// it's not clever enough to treat other P values as making this branch valid.
475-
#if defined(DEBUG_METHODS_ENABLED) && defined(__GNUC__) && !defined(__clang__)
475+
#if defined(DEBUG_ENABLED) && defined(__GNUC__) && !defined(__clang__)
476476
#pragma GCC diagnostic push
477477
#pragma GCC diagnostic ignored "-Wunused-but-set-parameter"
478478
#endif
@@ -540,7 +540,7 @@ template <typename... P, size_t... Is>
540540
void call_with_variant_args_static(void (*p_method)(P...), const Variant **p_args, GDExtensionCallError &r_error, IndexSequence<Is...>) {
541541
r_error.error = GDEXTENSION_CALL_OK;
542542

543-
#ifdef DEBUG_METHODS_ENABLED
543+
#ifdef DEBUG_ENABLED
544544
(p_method)(VariantCasterAndValidate<P>::cast(p_args, Is, r_error)...);
545545
#else
546546
(p_method)(VariantCaster<P>::cast(*p_args[Is])...);
@@ -632,7 +632,7 @@ template <typename R, typename... P, size_t... Is>
632632
void call_with_variant_args_static_ret(R (*p_method)(P...), const Variant **p_args, Variant &r_ret, GDExtensionCallError &r_error, IndexSequence<Is...>) {
633633
r_error.error = GDEXTENSION_CALL_OK;
634634

635-
#ifdef DEBUG_METHODS_ENABLED
635+
#ifdef DEBUG_ENABLED
636636
r_ret = (p_method)(VariantCasterAndValidate<P>::cast(p_args, Is, r_error)...);
637637
#else
638638
r_ret = (p_method)(VariantCaster<P>::cast(*p_args[Is])...);

include/godot_cpp/core/defs.hpp

Lines changed: 108 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -30,17 +30,64 @@
3030

3131
#pragma once
3232

33+
/**
34+
* Basic definitions and simple functions to be used everywhere.
35+
*/
36+
37+
// IWYU pragma: always_keep
38+
39+
// Ensure that C++ standard is at least C++17.
40+
// If on MSVC, also ensures that the `Zc:__cplusplus` flag is present.
41+
static_assert(__cplusplus >= 201703L, "Minimum of C++17 required.");
42+
43+
// IWYU pragma: begin_exports
44+
3345
#include <cstddef>
3446
#include <cstdint>
47+
#include <cstring>
3548
#include <type_traits>
3649
#include <utility>
3750

3851
#if __has_include(<godot_cpp/core/version.hpp>)
3952
#include <godot_cpp/core/version.hpp>
4053
#endif
4154

55+
// IWYU pragma: end_exports
56+
4257
namespace godot {
4358

59+
#if defined(__has_feature)
60+
#define GD_HAS_FEATURE(m_feature) __has_feature(m_feature)
61+
#else
62+
#define GD_HAS_FEATURE(m_feature) 0
63+
#endif
64+
65+
#if defined(__has_cpp_attribute)
66+
#define GD_HAS_CPP_ATTRIBUTE(m_feature) __has_cpp_attribute(m_feature)
67+
#else
68+
#define GD_HAS_CPP_ATTRIBUTE(m_feature) 0
69+
#endif
70+
71+
#if (GD_HAS_FEATURE(address_sanitizer) || defined(__SANITIZE_ADDRESS__)) && !defined(ASAN_ENABLED)
72+
#error Address sanitizer was enabled without defining `ASAN_ENABLED`
73+
#endif
74+
75+
#if (GD_HAS_FEATURE(leak_sanitizer) || defined(__SANITIZE_LEAKS__)) && !defined(LSAN_ENABLED)
76+
#error Leak sanitizer was enabled without defining `LSAN_ENABLED`
77+
#endif
78+
79+
#if (GD_HAS_FEATURE(memory_sanitizer) || defined(__SANITIZE_MEMORY__)) && !defined(MSAN_ENABLED)
80+
#error Memory sanitizer was enabled without defining `MSAN_ENABLED`
81+
#endif
82+
83+
#if (GD_HAS_FEATURE(thread_sanitizer) || defined(__SANITIZE_THREAD__)) && !defined(TSAN_ENABLED)
84+
#error Thread sanitizer was enabled without defining `TSAN_ENABLED`
85+
#endif
86+
87+
#if (GD_HAS_FEATURE(undefined_behavior_sanitizer) || defined(__UNDEFINED_SANITIZER__)) && !defined(UBSAN_ENABLED)
88+
#error Undefined behavior sanitizer was enabled without defining `UBSAN_ENABLED`
89+
#endif
90+
4491
#if !defined(GDE_EXPORT)
4592
#if defined(_WIN32)
4693
#define GDE_EXPORT __declspec(dllexport)
@@ -96,6 +143,18 @@ namespace godot {
96143
#define _ALLOW_DISCARD_ (void)
97144
#endif
98145

146+
#if GD_HAS_CPP_ATTRIBUTE(clang::lifetimebound)
147+
#define _LIFETIME_BOUND_ [[clang::lifetimebound]]
148+
#elif GD_HAS_CPP_ATTRIBUTE(gnu::lifetimebound)
149+
#define _LIFETIME_BOUND_ [[gnu::lifetimebound]]
150+
#elif GD_HAS_CPP_ATTRIBUTE(msvc::lifetimebound)
151+
#define _LIFETIME_BOUND_ [[msvc::lifetimebound]]
152+
#elif GD_HAS_CPP_ATTRIBUTE(lifetimebound)
153+
#define _LIFETIME_BOUND_ [[lifetimebound]]
154+
#else
155+
#define _LIFETIME_BOUND_
156+
#endif
157+
99158
// Windows badly defines a lot of stuff we'll never use. Undefine it.
100159
#ifdef _WIN32
101160
#undef min // override standard definition
@@ -136,106 +195,17 @@ constexpr auto CLAMP(const T m_a, const T2 m_min, const T3 m_max) {
136195
return m_a < m_min ? m_min : (m_a > m_max ? m_max : m_a);
137196
}
138197

198+
// Like std::size, but without requiring any additional includes.
199+
template <typename T, size_t SIZE>
200+
constexpr size_t std_size(const T (&)[SIZE]) {
201+
return SIZE;
202+
}
203+
139204
// Generic swap template.
140205
#ifndef SWAP
141206
#define SWAP(m_x, m_y) std::swap((m_x), (m_y))
142207
#endif // SWAP
143208

144-
/* Functions to handle powers of 2 and shifting. */
145-
146-
// Returns `true` if a positive integer is a power of 2, `false` otherwise.
147-
template <typename T>
148-
constexpr bool is_power_of_2(const T x) {
149-
return x && ((x & (x - 1)) == 0);
150-
}
151-
152-
// Function to find the next power of 2 to an integer.
153-
constexpr unsigned int next_power_of_2(unsigned int x) {
154-
if (x == 0) {
155-
return 0;
156-
}
157-
158-
--x;
159-
x |= x >> 1;
160-
x |= x >> 2;
161-
x |= x >> 4;
162-
x |= x >> 8;
163-
x |= x >> 16;
164-
165-
return ++x;
166-
}
167-
168-
// Function to find the previous power of 2 to an integer.
169-
constexpr unsigned int previous_power_of_2(unsigned int x) {
170-
x |= x >> 1;
171-
x |= x >> 2;
172-
x |= x >> 4;
173-
x |= x >> 8;
174-
x |= x >> 16;
175-
return x - (x >> 1);
176-
}
177-
178-
// Function to find the closest power of 2 to an integer.
179-
constexpr unsigned int closest_power_of_2(unsigned int x) {
180-
unsigned int nx = next_power_of_2(x);
181-
unsigned int px = previous_power_of_2(x);
182-
return (nx - x) > (x - px) ? px : nx;
183-
}
184-
185-
// Get a shift value from a power of 2.
186-
constexpr int get_shift_from_power_of_2(unsigned int p_bits) {
187-
for (unsigned int i = 0; i < 32; i++) {
188-
if (p_bits == (unsigned int)(1 << i)) {
189-
return i;
190-
}
191-
}
192-
193-
return -1;
194-
}
195-
196-
template <typename T>
197-
constexpr T nearest_power_of_2_templated(T x) {
198-
--x;
199-
200-
// The number of operations on x is the base two logarithm
201-
// of the number of bits in the type. Add three to account
202-
// for sizeof(T) being in bytes.
203-
constexpr size_t num = get_shift_from_power_of_2(sizeof(T)) + 3;
204-
205-
// If the compiler is smart, it unrolls this loop.
206-
// If it's dumb, this is a bit slow.
207-
for (size_t i = 0; i < num; i++) {
208-
x |= x >> (1 << i);
209-
}
210-
211-
return ++x;
212-
}
213-
214-
// Function to find the nearest (bigger) power of 2 to an integer.
215-
constexpr unsigned int nearest_shift(unsigned int p_number) {
216-
for (int i = 30; i >= 0; i--) {
217-
if (p_number & (1 << i)) {
218-
return i + 1;
219-
}
220-
}
221-
222-
return 0;
223-
}
224-
225-
// constexpr function to find the floored log2 of a number
226-
template <typename T>
227-
constexpr T floor_log2(T x) {
228-
return x < 2 ? x : 1 + floor_log2(x >> 1);
229-
}
230-
231-
// Get the number of bits needed to represent the number.
232-
// IE, if you pass in 8, you will get 4.
233-
// If you want to know how many bits are needed to store 8 values however, pass in (8 - 1).
234-
template <typename T>
235-
constexpr T get_num_bits(T x) {
236-
return floor_log2(x);
237-
}
238-
239209
// Swap 16, 32 and 64 bits value for endianness.
240210
#if defined(__GNUC__)
241211
#define BSWAP16(x) __builtin_bswap16(x)
@@ -313,10 +283,6 @@ struct BuildIndexSequence<0, Is...> : IndexSequence<Is...> {};
313283
// Limit the depth of recursive algorithms when dealing with Array/Dictionary
314284
#define MAX_RECURSION 100
315285

316-
#ifdef DEBUG_ENABLED
317-
#define DEBUG_METHODS_ENABLED
318-
#endif
319-
320286
// Macro GD_IS_DEFINED() allows to check if a macro is defined. It needs to be defined to anything (say 1) to work.
321287
#define __GDARG_PLACEHOLDER_1 false,
322288
#define __gd_take_second_arg(__ignored, val, ...) val
@@ -372,17 +338,58 @@ inline constexpr bool is_zero_constructible_v = is_zero_constructible<T>::value;
372338
#endif
373339

374340
#if defined(_MSC_VER) && !defined(__clang__)
375-
#define GODOT_MSVC_PRAGMA(m_content) __pragma(m_content)
341+
#define GODOT_MSVC_PRAGMA(m_command) __pragma(m_command)
376342
#define GODOT_MSVC_WARNING_PUSH GODOT_MSVC_PRAGMA(warning(push))
377343
#define GODOT_MSVC_WARNING_IGNORE(m_warning) GODOT_MSVC_PRAGMA(warning(disable : m_warning))
378344
#define GODOT_MSVC_WARNING_POP GODOT_MSVC_PRAGMA(warning(pop))
379345
#define GODOT_MSVC_WARNING_PUSH_AND_IGNORE(m_warning) GODOT_MSVC_WARNING_PUSH GODOT_MSVC_WARNING_IGNORE(m_warning)
380346
#else
381-
#define GODOT_MSVC_PRAGMA(m_content)
347+
#define GODOT_MSVC_PRAGMA(m_command)
382348
#define GODOT_MSVC_WARNING_PUSH
383349
#define GODOT_MSVC_WARNING_IGNORE(m_warning)
384350
#define GODOT_MSVC_WARNING_POP
385351
#define GODOT_MSVC_WARNING_PUSH_AND_IGNORE(m_warning)
386352
#endif
387353

354+
// Deprecation warning suppression helper macros.
355+
#if defined(__clang__)
356+
#define GODOT_PUSH_IGNORE_DEPRECATION() GODOT_CLANG_WARNING_PUSH_AND_IGNORE("-Wdeprecated-declarations")
357+
#define GODOT_POP_IGNORE_DEPRECATION() GODOT_CLANG_WARNING_POP
358+
#endif
359+
360+
#if defined(__GNUC__) && !defined(__clang__)
361+
#define GODOT_PUSH_IGNORE_DEPRECATION() GODOT_GCC_WARNING_PUSH_AND_IGNORE("-Wdeprecated-declarations")
362+
#define GODOT_POP_IGNORE_DEPRECATION() GODOT_GCC_WARNING_POP
363+
#endif
364+
365+
#if defined(_MSC_VER) && !defined(__clang__)
366+
#define GODOT_PUSH_IGNORE_DEPRECATION() GODOT_MSVC_WARNING_PUSH_AND_IGNORE(4996)
367+
#define GODOT_POP_IGNORE_DEPRECATION() GODOT_MSVC_WARNING_POP
368+
#endif
369+
370+
template <typename T, typename = void>
371+
struct is_fully_defined : std::false_type {};
372+
373+
template <typename T>
374+
struct is_fully_defined<T, std::void_t<decltype(sizeof(T))>> : std::true_type {};
375+
376+
template <typename T>
377+
constexpr bool is_fully_defined_v = is_fully_defined<T>::value;
378+
379+
#ifndef SCU_BUILD_ENABLED
380+
/// Enforces the requirement that a class is not fully defined.
381+
/// This can be used to reduce include coupling and keep compile times low.
382+
/// The check must be made at the top of the corresponding .cpp file of a header.
383+
#define STATIC_ASSERT_INCOMPLETE_TYPE(m_keyword, m_type) \
384+
m_keyword m_type; \
385+
static_assert(!is_fully_defined_v<m_type>, #m_type " was unexpectedly fully defined. Please check the include hierarchy of '" __FILE__ "' and remove includes that resolve the " #m_keyword ".");
386+
#else
387+
#define STATIC_ASSERT_INCOMPLETE_TYPE(m_keyword, m_type)
388+
#endif
389+
390+
#define _GD_VARNAME_CONCAT_B_(m_ignore, m_name) m_name
391+
#define _GD_VARNAME_CONCAT_A_(m_a, m_b, m_c) _GD_VARNAME_CONCAT_B_(hello there, m_a##m_b##m_c)
392+
#define _GD_VARNAME_CONCAT_(m_a, m_b, m_c) _GD_VARNAME_CONCAT_A_(m_a, m_b, m_c)
393+
#define GD_UNIQUE_NAME(m_name) _GD_VARNAME_CONCAT_(m_name, _, __COUNTER__)
394+
388395
} //namespace godot

0 commit comments

Comments
 (0)