Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Core: Support c++20 compilation #89660

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/linux_builds.yml
Original file line number Diff line number Diff line change
Expand Up @@ -65,11 +65,11 @@ jobs:
legacy-scons: true
cache-limit: 7

- name: Editor with ThreadSanitizer (target=editor, tests=yes, dev_build=yes, use_tsan=yes, use_llvm=yes, linker=lld)
- name: Editor with ThreadSanitizer and C++20 (target=editor, tests=yes, dev_build=yes, use_tsan=yes, use_llvm=yes, linker=lld, cpp_standard=20)
cache-name: linux-editor-thread-sanitizer
target: editor
tests: true
sconsflags: dev_build=yes use_tsan=yes use_llvm=yes linker=lld
sconsflags: dev_build=yes use_tsan=yes use_llvm=yes linker=lld cpp_standard=20
bin: ./bin/godot.linuxbsd.editor.dev.x86_64.llvm.san
build-mono: false
# Skip 2GiB artifact speeding up action.
Expand Down
70 changes: 55 additions & 15 deletions SConstruct
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,8 @@ opts.Add(BoolVariable("engine_update_check", "Enable engine update checks in the
opts.Add(BoolVariable("steamapi", "Enable minimal SteamAPI integration for usage time tracking (editor only)", False))
opts.Add("cache_path", "Path to a directory where SCons cache files will be stored. No value disables the cache.", "")
opts.Add("cache_limit", "Max size (in GiB) for the SCons cache. 0 means no limit.", "0")
opts.Add(EnumVariable(["cpp_standard", "cpp_std"], "Set the C++ standard (Experimental)", "17", ("17", "20", "23")))
opts.Add(EnumVariable(["c_standard", "c_std"], "Set the C Standard (Experimental)", "17", ("17", "23")))

# Thirdparty libraries
opts.Add(BoolVariable("builtin_brotli", "Use the built-in Brotli library", True))
Expand Down Expand Up @@ -642,14 +644,29 @@ cc_version = methods.get_compiler_version(env)
cc_version_major = cc_version["major"]
cc_version_minor = cc_version["minor"]
cc_version_metadata1 = cc_version["metadata1"]
cpp_std = int(env["cpp_standard"])
c_std = int(env["c_standard"])

if cc_version_major == -1:
print_warning(
"Couldn't detect compiler version, skipping version checks. "
"Build may fail if the compiler doesn't support C++17 fully."
"Couldn't detect compiler version, skipping version checks. Build may "
f"fail if the compiler doesn't support C++{cpp_std}/C{c_std} fully."
)
elif cpp_std == 23:
print_warning(
"Using an experimental C++ standard, skipping version checks. "
"Build may fail if the compiler doesn't support the latest C++ fully."
)
elif methods.using_gcc(env):
if cc_version_major < 9:
if cpp_std == 20 and cc_version_major < 11:
print_error(
"Detected GCC version older than 11, which does not fully support "
"C++20. Supported versions are GCC 11 and later. Use a newer GCC "
'version, or Clang 10 or later by passing "use_llvm=yes" to the '
"SCons command line."
)
Exit(255)
elif cpp_std == 17 and cc_version_major < 9:
print_error(
"Detected GCC version older than 9, which does not fully support "
"C++17, or has bugs when compiling Godot. Supported versions are 9 "
Expand All @@ -669,50 +686,73 @@ elif methods.using_clang(env):
# Apple LLVM versions differ from upstream LLVM version \o/, compare
# in https://en.wikipedia.org/wiki/Xcode#Toolchain_versions
if methods.is_apple_clang(env):
if cc_version_major < 10:
if cpp_std == 20 and cc_version_major < 14:
print_error(
"Detected Apple Clang version older than 14, which does not fully "
"support C++20. Supported versions are Apple Clang 14 and later."
)
Exit(255)
elif cpp_std == 17 and cc_version_major < 10:
print_error(
"Detected Apple Clang version older than 10, which does not fully "
"support C++17. Supported versions are Apple Clang 10 and later."
)
Exit(255)
elif env["debug_paths_relative"] and cc_version_major < 12:
if env["debug_paths_relative"] and cc_version_major < 12:
print_warning(
"Apple Clang < 12 doesn't support -ffile-prefix-map, disabling `debug_paths_relative` option."
)
env["debug_paths_relative"] = False
else:
if cc_version_major < 6:
if cpp_std == 20 and cc_version_major < 10:
print_error(
"Detected Clang version older than 10, which does not fully support "
"C++20. Supported versions are Clang 10 and later."
)
Exit(255)
elif cpp_std == 17 and cc_version_major < 6:
print_error(
"Detected Clang version older than 6, which does not fully support "
"C++17. Supported versions are Clang 6 and later."
)
Exit(255)
elif env["debug_paths_relative"] and cc_version_major < 10:
if env["debug_paths_relative"] and cc_version_major < 10:
print_warning("Clang < 10 doesn't support -ffile-prefix-map, disabling `debug_paths_relative` option.")
env["debug_paths_relative"] = False

elif env.msvc:
# Ensure latest minor builds of Visual Studio 2017/2019.
# https://github.com/godotengine/godot/pull/94995#issuecomment-2336464574
if cc_version_major == 16 and cc_version_minor < 11:
if cpp_std == 20 and cc_version_major < 16:
print_error(
"Detected Visual Studio version older than 2019, which does not fully "
"support C++20. Supported versions are Visual Studio 2019 and later."
)
Exit(255)
elif cc_version_major == 16 and cc_version_minor < 11:
print_error(
"Detected Visual Studio 2019 version older than 16.11, which has bugs "
"when compiling Godot. Use a newer VS2019 version, or VS2022."
)
Exit(255)
if cc_version_major == 15 and cc_version_minor < 9:
elif cc_version_major == 15 and cc_version_minor < 9:
print_error(
"Detected Visual Studio 2017 version older than 15.9, which has bugs "
"when compiling Godot. Use a newer VS2017 version, or VS2019/VS2022."
)
Exit(255)
if cc_version_major < 15:
elif cc_version_major < 15:
print_error(
"Detected Visual Studio 2015 or earlier, which is unsupported in Godot. "
"Supported versions are Visual Studio 2017 and later."
)
Exit(255)

if c_std == 23:
print_warning(
"Using an experimental C standard, skipping version checks. "
"Build may fail if the compiler doesn't support the latest C fully."
)

# Default architecture flags.
if env["arch"] == "x86_32":
if env.msvc:
Expand Down Expand Up @@ -803,16 +843,16 @@ if env["lto"] != "none":
if not env.msvc:
# Specifying GNU extensions support explicitly, which are supported by
# both GCC and Clang. Both currently default to gnu17 and gnu++17.
env.Prepend(CFLAGS=["-std=gnu17"])
env.Prepend(CXXFLAGS=["-std=gnu++17"])
env.Prepend(CFLAGS=[f"-std=gnu{c_std if c_std <= 17 else '2x'}"])
env.Prepend(CXXFLAGS=[f"-std=gnu++{cpp_std if cpp_std <= 20 else '2b'}"])
else:
# MSVC started offering C standard support with Visual Studio 2019 16.8, which covers all
# of our supported VS2019 & VS2022 versions; VS2017 will only pass the C++ standard.
env.Prepend(CXXFLAGS=["/std:c++17"])
env.Prepend(CXXFLAGS=[f"/std:c++{cpp_std if cpp_std <= 20 else 'latest'}"])
if cc_version_major < 16:
print_warning("Visual Studio 2017 cannot specify a C-Standard.")
else:
env.Prepend(CFLAGS=["/std:c17"])
env.Prepend(CFLAGS=[f"/std:c{c_std if c_std <= 17 else 'latest'}"])
# MSVC is non-conforming with the C++ standard by default, so we enable more conformance.
# Note that this is still not complete conformance, as certain Windows-related headers
# don't compile under complete conformance.
Expand Down
4 changes: 2 additions & 2 deletions core/io/image.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -907,7 +907,7 @@ static void _scale_bilinear(const uint8_t *__restrict p_src, uint8_t *__restrict

for (uint32_t i = 0; i < p_dst_height; i++) {
// Add 0.5 in order to interpolate based on pixel center
uint32_t src_yofs_up_fp = (i + 0.5) * p_src_height * FRAC_LEN / p_dst_height;
uint32_t src_yofs_up_fp = (i + 0.5) * p_src_height * (int)FRAC_LEN / p_dst_height;
// Calculate nearest src pixel center above current, and truncate to get y index
uint32_t src_yofs_up = src_yofs_up_fp >= FRAC_HALF ? (src_yofs_up_fp - FRAC_HALF) >> FRAC_BITS : 0;
uint32_t src_yofs_down = (src_yofs_up_fp + FRAC_HALF) >> FRAC_BITS;
Expand All @@ -922,7 +922,7 @@ static void _scale_bilinear(const uint8_t *__restrict p_src, uint8_t *__restrict
uint32_t y_ofs_down = src_yofs_down * p_src_width * CC;

for (uint32_t j = 0; j < p_dst_width; j++) {
uint32_t src_xofs_left_fp = (j + 0.5) * p_src_width * FRAC_LEN / p_dst_width;
uint32_t src_xofs_left_fp = (j + 0.5) * p_src_width * (int)FRAC_LEN / p_dst_width;
uint32_t src_xofs_left = src_xofs_left_fp >= FRAC_HALF ? (src_xofs_left_fp - FRAC_HALF) >> FRAC_BITS : 0;
uint32_t src_xofs_right = (src_xofs_left_fp + FRAC_HALF) >> FRAC_BITS;
if (src_xofs_right >= p_src_width) {
Expand Down
17 changes: 3 additions & 14 deletions core/io/ip_address.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,21 +64,10 @@ struct IPAddress {
}
return true;
}
INEQUALITY_OPERATOR(const IPAddress &)

bool operator!=(const IPAddress &p_ip) const {
if (p_ip.valid != valid) {
return true;
}
if (!valid) {
return true;
}
for (int i = 0; i < 4; i++) {
if (field32[i] != p_ip.field32[i]) {
return true;
}
}
return false;
}
bool operator==(const String &p_ip) const { return operator==(IPAddress(p_ip)); }
INEQUALITY_OPERATOR(const String &)

void clear();
bool is_wildcard() const { return wildcard; }
Expand Down
4 changes: 0 additions & 4 deletions core/math/aabb.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,6 @@ bool AABB::operator==(const AABB &p_rval) const {
return ((position == p_rval.position) && (size == p_rval.size));
}

bool AABB::operator!=(const AABB &p_rval) const {
return ((position != p_rval.position) || (size != p_rval.size));
}

void AABB::merge_with(const AABB &p_aabb) {
#ifdef MATH_CHECKS
if (unlikely(size.x < 0 || size.y < 0 || size.z < 0 || p_aabb.size.x < 0 || p_aabb.size.y < 0 || p_aabb.size.z < 0)) {
Expand Down
2 changes: 1 addition & 1 deletion core/math/aabb.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ struct [[nodiscard]] AABB {
void set_size(const Vector3 &p_size) { size = p_size; }

bool operator==(const AABB &p_rval) const;
bool operator!=(const AABB &p_rval) const;
INEQUALITY_OPERATOR(const AABB &)

bool is_equal_approx(const AABB &p_aabb) const;
bool is_finite() const;
Expand Down
2 changes: 1 addition & 1 deletion core/math/audio_frame.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
#include "core/math/vector2.h"
#include "core/typedefs.h"

static inline float undenormalize(volatile float f) {
static inline float undenormalize(float f) {
union {
uint32_t i;
float f;
Expand Down
4 changes: 0 additions & 4 deletions core/math/basis.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -710,10 +710,6 @@ bool Basis::operator==(const Basis &p_matrix) const {
return true;
}

bool Basis::operator!=(const Basis &p_matrix) const {
return (!(*this == p_matrix));
}

Basis::operator String() const {
return "[X: " + get_column(0).operator String() +
", Y: " + get_column(1).operator String() +
Expand Down
2 changes: 1 addition & 1 deletion core/math/basis.h
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ struct [[nodiscard]] Basis {
bool is_finite() const;

bool operator==(const Basis &p_matrix) const;
bool operator!=(const Basis &p_matrix) const;
INEQUALITY_OPERATOR(const Basis &)

_FORCE_INLINE_ Vector3 xform(const Vector3 &p_vector) const;
_FORCE_INLINE_ Vector3 xform_inv(const Vector3 &p_vector) const;
Expand Down
2 changes: 1 addition & 1 deletion core/math/bvh_abb.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ struct BVH_ABB {
POINT neg_max;

bool operator==(const BVH_ABB &o) const { return (min == o.min) && (neg_max == o.neg_max); }
bool operator!=(const BVH_ABB &o) const { return (*this == o) == false; }
INEQUALITY_OPERATOR(const BVH_ABB &)

void set(const POINT &_min, const POINT &_max) {
min = _min;
Expand Down
2 changes: 1 addition & 1 deletion core/math/bvh_tree.h
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ struct BVHHandle {
void set_id(uint32_t p_id) { _data = p_id; }

bool operator==(const BVHHandle &p_h) const { return _data == p_h._data; }
bool operator!=(const BVHHandle &p_h) const { return (*this == p_h) == false; }
INEQUALITY_OPERATOR(const BVHHandle &)
};

// helper class to make iterative versions of recursive functions
Expand Down
4 changes: 1 addition & 3 deletions core/math/color.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,7 @@ struct [[nodiscard]] Color {
bool operator==(const Color &p_color) const {
return (r == p_color.r && g == p_color.g && b == p_color.b && a == p_color.a);
}
bool operator!=(const Color &p_color) const {
return (r != p_color.r || g != p_color.g || b != p_color.b || a != p_color.a);
}
INEQUALITY_OPERATOR(const Color &)

Color operator+(const Color &p_color) const;
void operator+=(const Color &p_color);
Expand Down
5 changes: 2 additions & 3 deletions core/math/convex_hull.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
* - adapted to Godot's code style
* - replaced Bullet's types (e.g. vectors) with Godot's
* - replaced custom Pool implementation with PagedAllocator
* - replaced Point32's inequality operator with macro
*/

/*
Expand Down Expand Up @@ -139,9 +140,7 @@ class ConvexHullInternal {
return (x == b.x) && (y == b.y) && (z == b.z);
}

bool operator!=(const Point32 &b) const {
return (x != b.x) || (y != b.y) || (z != b.z);
}
INEQUALITY_OPERATOR(const Point32 &)

bool is_zero() {
return (x == 0) && (y == 0) && (z == 0);
Expand Down
6 changes: 1 addition & 5 deletions core/math/plane.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ struct [[nodiscard]] Plane {
bool is_finite() const;

_FORCE_INLINE_ bool operator==(const Plane &p_plane) const;
_FORCE_INLINE_ bool operator!=(const Plane &p_plane) const;
INEQUALITY_OPERATOR(const Plane &)
operator String() const;

_FORCE_INLINE_ Plane() {}
Expand Down Expand Up @@ -129,8 +129,4 @@ bool Plane::operator==(const Plane &p_plane) const {
return normal == p_plane.normal && d == p_plane.d;
}

bool Plane::operator!=(const Plane &p_plane) const {
return normal != p_plane.normal || d != p_plane.d;
}

#endif // PLANE_H
5 changes: 1 addition & 4 deletions core/math/projection.h
Original file line number Diff line number Diff line change
Expand Up @@ -143,10 +143,7 @@ struct [[nodiscard]] Projection {
}
return true;
}

bool operator!=(const Projection &p_cam) const {
return !(*this == p_cam);
}
INEQUALITY_OPERATOR(const Projection &)

real_t get_lod_multiplier() const;

Expand Down
6 changes: 1 addition & 5 deletions core/math/quaternion.h
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ struct [[nodiscard]] Quaternion {
_FORCE_INLINE_ Quaternion operator/(real_t p_s) const;

_FORCE_INLINE_ bool operator==(const Quaternion &p_quaternion) const;
_FORCE_INLINE_ bool operator!=(const Quaternion &p_quaternion) const;
INEQUALITY_OPERATOR(const Quaternion &)

operator String() const;

Expand Down Expand Up @@ -221,10 +221,6 @@ bool Quaternion::operator==(const Quaternion &p_quaternion) const {
return x == p_quaternion.x && y == p_quaternion.y && z == p_quaternion.z && w == p_quaternion.w;
}

bool Quaternion::operator!=(const Quaternion &p_quaternion) const {
return x != p_quaternion.x || y != p_quaternion.y || z != p_quaternion.z || w != p_quaternion.w;
}

_FORCE_INLINE_ Quaternion operator*(real_t p_real, const Quaternion &p_quaternion) {
return p_quaternion * p_real;
}
Expand Down
4 changes: 4 additions & 0 deletions core/math/rect2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ bool Rect2::is_finite() const {
return position.is_finite() && size.is_finite();
}

bool Rect2::operator==(const Rect2i &p_rect) const {
return position == p_rect.get_position() && size == p_rect.get_position();
}

bool Rect2::intersects_segment(const Point2 &p_from, const Point2 &p_to, Point2 *r_pos, Point2 *r_normal) const {
#ifdef MATH_CHECKS
if (unlikely(size.x < 0 || size.y < 0)) {
Expand Down
4 changes: 3 additions & 1 deletion core/math/rect2.h
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,9 @@ struct [[nodiscard]] Rect2 {
bool is_finite() const;

bool operator==(const Rect2 &p_rect) const { return position == p_rect.position && size == p_rect.size; }
bool operator!=(const Rect2 &p_rect) const { return position != p_rect.position || size != p_rect.size; }
INEQUALITY_OPERATOR(const Rect2 &)
bool operator==(const Rect2i &p_rect) const;
INEQUALITY_OPERATOR(const Rect2i &)

inline Rect2 grow(real_t p_amount) const {
Rect2 g = *this;
Expand Down
2 changes: 1 addition & 1 deletion core/math/rect2i.h
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ struct [[nodiscard]] Rect2i {
}

bool operator==(const Rect2i &p_rect) const { return position == p_rect.position && size == p_rect.size; }
bool operator!=(const Rect2i &p_rect) const { return position != p_rect.position || size != p_rect.size; }
INEQUALITY_OPERATOR(const Rect2i &)

Rect2i grow(int p_amount) const {
Rect2i g = *this;
Expand Down
10 changes: 0 additions & 10 deletions core/math/transform_2d.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -201,16 +201,6 @@ bool Transform2D::operator==(const Transform2D &p_transform) const {
return true;
}

bool Transform2D::operator!=(const Transform2D &p_transform) const {
for (int i = 0; i < 3; i++) {
if (columns[i] != p_transform.columns[i]) {
return true;
}
}

return false;
}

void Transform2D::operator*=(const Transform2D &p_transform) {
columns[2] = xform(p_transform.columns[2]);

Expand Down
Loading