gnucash future: Set C and C++ standards to 23.
John Ralls
jralls at code.gnucash.org
Tue Jun 23 17:50:50 EDT 2026
Updated via https://github.com/Gnucash/gnucash/commit/2b93466c (commit)
from https://github.com/Gnucash/gnucash/commit/122cb6dc (commit)
commit 2b93466c213b082bb2d382ee377a936bd695122f
Author: John Ralls <jralls at ceridwen.us>
Date: Mon Jun 22 19:37:33 2026 -0700
Set C and C++ standards to 23.
This required some adjustments:
* New warnings character-conversion and deprecated-volatile are
disabled for the reasons indicated in the adjacent comments.
* C23 is a lot stricter about function pointer signatures so some
callbacks in gnc-frequency.c and dialog-sx-editor had to be cast using
the long-available GLib macros.
* C++23 is stricter about a reference (foo&) parameter taking an
lvalue only; a lambda used in several csv-importer files was trying to
pass an rvalue so the parameter had to be changed to perfect
forward (foo&&).
* C++23 doesn't allow oring together enum values from different enum
types, even anonymous ones, so the two gnc_numeric enums for rounding
and denominators are combined into a single enum GncNumericRoundDenom.
* C++20's new automatic generation of comparison functions combined
with its stricter automatic conversion rules caused trouble with
operator==() and operator!=() for gnc::GUID and GncGUID, complaining
about ambiguity or not being able to find operator==(const GncGuid&,
const GncGuid&). The fix has two parts: Changing operator!=(const
gnc::GUID&, const gnc::GUID&) to operator==(const gnc::GUID&, const
gnc::GUID&) to resolve the conversion problem and changing the call
forwarding operator==(const GncGuid&, const GncGuid&) to only cast the
first argument to gnc::GUID so that it could work unambiguously with
operator==(const gnc::GUID&, const GncGuid&).
* python sqlite3test: C23 apparently makes AppleClang a lot pickier
about includes.
diff --git a/.github/workflows/mac-tests.yaml b/.github/workflows/mac-tests.yaml
index 2cce9cf266..2d9ddb80bd 100644
--- a/.github/workflows/mac-tests.yaml
+++ b/.github/workflows/mac-tests.yaml
@@ -3,7 +3,7 @@ on: [push, pull_request]
permissions: {}
jobs:
ci_tests_mac:
- runs-on: macos-latest
+ runs-on: macos-26
name: macOS CI Tests
env:
TZ: America/Los_Angeles
@@ -28,8 +28,9 @@ jobs:
id: googletest
with:
- file-url: 'https://github.com/google/googletest/archive/release-1.10.0.tar.gz'
- file-name: googletest.tar.gz
+ file-url: 'https://github.com/google/googletest/releases/download/v1.17.0/googletest-1.17.0.tar.gz'
+ file-name: googletest-1.17.0.tar.gz
+ sha256: '65fab701d9829d38cb77c14acdc431d2108bfdbf8979e40eb8ae567edf10b27c'
- name: Extract Dependencies
run: |
mkdir -p $HOME/gnucash/inst
@@ -37,7 +38,7 @@ jobs:
tar -xf $GITHUB_WORKSPACE/gnucash-future-mac-dependencies.tar.xz
mkdir $HOME/gnucash/source
cd $HOME/gnucash/source
- tar -xf $GITHUB_WORKSPACE/googletest.tar.gz
+ tar -xf $GITHUB_WORKSPACE/googletest-1.17.0.tar.gz
mv googletest-* googletest
- name: Configure GnuCash
run: |
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 5d3f18739b..67867ba2c1 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -616,21 +616,31 @@ endif()
add_definitions(-D_GNU_SOURCE)
# Set up the language standards:
-set(CMAKE_CXX_STANDARD 17)
+set(CMAKE_CXX_STANDARD 23)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
-set(CMAKE_C_STANDARD 11)
+set(CMAKE_C_STANDARD 23)
set(CMAKE_C_STANDARD_REQUIRED ON)
set(CMAKE_C_EXTENSIONS ON)
+# -Wno-deprecated-volatile, -Wno-volatile: Guile heavily uses
+# -volatile. Guile is C but we include its headers in C++ swig files.
+if (CMAKE_CXX_COMPILER_ID MATCHES "AppleClang|Clang")
+ set(volatile_warning "-Wno-deprecated-volatile")
+elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
+ set(volatile_warning "-Wno-volatile")
+else()
+ message(FATAL_ERROR "Only clang and gcc are supported compilers.")
+endif()
if (UNIX)
set( CMAKE_C_FLAGS "-Werror -Wall -Wmissing-prototypes -Wmissing-declarations ${CMAKE_C_FLAGS}")
- set( CMAKE_CXX_FLAGS "-Werror -Wall -Wmissing-declarations ${CMAKE_CXX_FLAGS}")
+ # -Wno-character-conversions: Googletest casts char8_t* to char32_t
+ set( CMAKE_CXX_FLAGS "-Werror -Wall -Wmissing-declarations -Wno-character-conversion ${volatile_warning} ${CMAKE_CXX_FLAGS}")
set( CMAKE_C_FLAGS_RELEASE "-O3 -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 ${CMAKE_C_FLAGS}")
endif()
if (MINGW)
set( CMAKE_C_FLAGS "-Werror -Wall -Wmissing-prototypes -Wmissing-declarations ${CMAKE_C_FLAGS}")
- set( CMAKE_CXX_FLAGS "-Werror -Wall -Wmissing-declarations -DWINVER=0x0A00 ${CMAKE_CXX_FLAGS}") # Workaround for bug in gtest on mingw, see https://github.com/google/googletest/issues/893 and https://github.com/google/googletest/issues/920
+ set( CMAKE_CXX_FLAGS "-Werror -Wall -Wmissing-declarations -Wno-character-conversion ${volatile_warning} -DWINVER=0x0A00 ${CMAKE_CXX_FLAGS}") # Workaround for bug in gtest on mingw, see https://github.com/google/googletest/issues/893 and https://github.com/google/googletest/issues/920
endif()
if (APPLE)
diff --git a/bindings/python/sqlite3test.c b/bindings/python/sqlite3test.c
index 9195bcd97d..5d88d674d3 100644
--- a/bindings/python/sqlite3test.c
+++ b/bindings/python/sqlite3test.c
@@ -19,7 +19,9 @@
\********************************************************************/
#include <config.h>
-#include "qofsession.h"
+#include <unistd.h>
+#include <gnc-engine.h>
+#include <qof.h>
#define TESTFILE "/tmp/blah.gnucash"
int main()
{
diff --git a/gnucash/gnome-utils/gnc-frequency.c b/gnucash/gnome-utils/gnc-frequency.c
index e7de0ade15..a69665119b 100644
--- a/gnucash/gnome-utils/gnc-frequency.c
+++ b/gnucash/gnome-utils/gnc-frequency.c
@@ -152,13 +152,13 @@ gnc_frequency_init(GncFrequency *gf)
void (*fn)();
} comboBoxes[] =
{
- { "freq_combobox", freq_combo_changed },
- { "semimonthly_first", semimonthly_sel_changed },
- { "semimonthly_first_weekend", semimonthly_sel_changed },
- { "semimonthly_second", semimonthly_sel_changed },
- { "semimonthly_second_weekend", semimonthly_sel_changed },
- { "monthly_day", monthly_sel_changed },
- { "monthly_weekend", monthly_sel_changed },
+ { "freq_combobox", G_CALLBACK(freq_combo_changed) },
+ { "semimonthly_first", G_CALLBACK(semimonthly_sel_changed) },
+ { "semimonthly_first_weekend", G_CALLBACK(semimonthly_sel_changed) },
+ { "semimonthly_second", G_CALLBACK(semimonthly_sel_changed) },
+ { "semimonthly_second_weekend", G_CALLBACK(semimonthly_sel_changed) },
+ { "monthly_day", G_CALLBACK(monthly_sel_changed) },
+ { "monthly_weekend", G_CALLBACK(monthly_sel_changed) },
{ NULL, NULL }
};
@@ -168,11 +168,11 @@ gnc_frequency_init(GncFrequency *gf)
void (*fn)();
} spinVals[] =
{
- { "daily_spin", spin_changed_helper },
- { "weekly_spin", spin_changed_helper },
- { "semimonthly_spin", spin_changed_helper },
- { "monthly_spin", spin_changed_helper },
- { NULL, NULL }
+ { "daily_spin", G_CALLBACK(spin_changed_helper) },
+ { "weekly_spin", G_CALLBACK(spin_changed_helper) },
+ { "semimonthly_spin", G_CALLBACK(spin_changed_helper) },
+ { "monthly_spin", G_CALLBACK(spin_changed_helper) },
+ { NULL, NULL }
};
gtk_orientable_set_orientation (GTK_ORIENTABLE(gf), GTK_ORIENTATION_VERTICAL);
diff --git a/gnucash/gnome/dialog-sx-editor.c b/gnucash/gnome/dialog-sx-editor.c
index 7e2bc00e1e..1cae867e51 100644
--- a/gnucash/gnome/dialog-sx-editor.c
+++ b/gnucash/gnome/dialog-sx-editor.c
@@ -1193,19 +1193,19 @@ gnc_ui_scheduled_xaction_editor_dialog_create (GtkWindow *parent,
void (*fn)();
gpointer objectData;
} widgets[] =
- {
- { "ok_button", "clicked", editor_ok_button_clicked_cb, NULL },
- { "cancel_button", "clicked", editor_cancel_button_clicked_cb, NULL },
- { "help_button", "clicked", editor_help_button_clicked_cb, NULL },
- { "rb_noend", "toggled", endgroup_rb_toggled_cb, GINT_TO_POINTER (END_NEVER_OPTION) },
- { "rb_enddate", "toggled", endgroup_rb_toggled_cb, GINT_TO_POINTER (END_DATE_OPTION) },
- { "rb_num_occur", "toggled", endgroup_rb_toggled_cb, GINT_TO_POINTER (NUM_OCCUR_OPTION) },
- { "remain_spin" , "value-changed", sxed_excal_update_adapt_cb, NULL },
- { "enabled_opt", "toggled", enabled_toggled_cb, NULL },
- { "autocreate_opt", "toggled", autocreate_toggled_cb, NULL },
- { "advance_opt", "toggled", advance_toggled_cb, NULL },
- { "remind_opt", "toggled", remind_toggled_cb, NULL },
- { NULL, NULL, NULL, NULL }
+ {
+ { "ok_button", "clicked", G_CALLBACK(editor_ok_button_clicked_cb), NULL },
+ { "cancel_button", "clicked", G_CALLBACK(editor_cancel_button_clicked_cb), NULL },
+ { "help_button", "clicked", G_CALLBACK(editor_help_button_clicked_cb), NULL },
+ { "rb_noend", "toggled", G_CALLBACK(endgroup_rb_toggled_cb), GINT_TO_POINTER (END_NEVER_OPTION) },
+ { "rb_enddate", "toggled", G_CALLBACK(endgroup_rb_toggled_cb), GINT_TO_POINTER (END_DATE_OPTION) },
+ { "rb_num_occur", "toggled", G_CALLBACK(endgroup_rb_toggled_cb), GINT_TO_POINTER (NUM_OCCUR_OPTION) },
+ { "remain_spin" , "value-changed", G_CALLBACK(sxed_excal_update_adapt_cb), NULL },
+ { "enabled_opt", "toggled", G_CALLBACK(enabled_toggled_cb), NULL },
+ { "autocreate_opt", "toggled", G_CALLBACK(autocreate_toggled_cb), NULL },
+ { "advance_opt", "toggled", G_CALLBACK(advance_toggled_cb), NULL },
+ { "remind_opt", "toggled", G_CALLBACK(remind_toggled_cb), NULL },
+ { NULL, NULL, NULL, NULL }
};
dlgExists = gnc_find_gui_components (DIALOG_SCHEDXACTION_EDITOR_CM_CLASS,
diff --git a/gnucash/import-export/csv-imp/assistant-csv-trans-import.cpp b/gnucash/import-export/csv-imp/assistant-csv-trans-import.cpp
index c62ed927ae..e88c4d40ff 100644
--- a/gnucash/import-export/csv-imp/assistant-csv-trans-import.cpp
+++ b/gnucash/import-export/csv-imp/assistant-csv-trans-import.cpp
@@ -1431,7 +1431,7 @@ CsvImpTransAssist::preview_row_fill_state_cells (GtkListStore *store, GtkTreeIte
fcolor = "black";
bcolor = "pink";
err_msg = std::string(_("This line has the following parse issues:"));
- auto add_non_acct_err_bullet = [](std::string& a, ErrMap::value_type& b)->std::string
+ auto add_non_acct_err_bullet = [](std::string&& a, ErrMap::value_type& b)->std::string
{
if ((b.first == GncTransPropType::ACCOUNT) ||
(b.first == GncTransPropType::TACCOUNT))
@@ -2130,7 +2130,7 @@ CsvImpTransAssist::assist_match_page_prepare ()
*/
auto err_msg = std::string(err.what());
auto err_msgs = err.errors();
- auto add_bullet_item = [](std::string& a, ErrMap::value_type& b)->std::string { return std::move(a) + "\n⢠" + b.second; };
+ auto add_bullet_item = [](std::string&& a, ErrMap::value_type& b)->std::string { return std::move(a) + "\n⢠" + b.second; };
err_msg = std::accumulate (err_msgs.begin(), err_msgs.end(), std::move (err_msg), add_bullet_item);
gnc_error_dialog (GTK_WINDOW (csv_imp_asst),
diff --git a/gnucash/import-export/csv-imp/gnc-imp-props-tx.cpp b/gnucash/import-export/csv-imp/gnc-imp-props-tx.cpp
index e14d3b4ebb..e9645d2675 100644
--- a/gnucash/import-export/csv-imp/gnc-imp-props-tx.cpp
+++ b/gnucash/import-export/csv-imp/gnc-imp-props-tx.cpp
@@ -332,7 +332,10 @@ std::shared_ptr<DraftTransaction> GncPreTrans::create_trans (QofBook* book, gnc_
if (!check.empty())
{
auto err_msg = std::string("Not creating transaction because essentials not set properly:");
- auto add_bullet_item = [](std::string& a, std::string& b)->std::string { return std::move(a) + "\n⢠" + b; };
+ auto add_bullet_item = [](std::string&& a, std::string& b)->std::string {
+ static const std::string bullet{"\n⢠"};
+ return std::move(a) + "\n⢠" + b;
+ };
err_msg = std::accumulate (check.begin(), check.end(), std::move (err_msg), add_bullet_item);
PWARN ("%s", err_msg.c_str());
return nullptr;
@@ -721,7 +724,7 @@ void GncPreSplit::create_split (std::shared_ptr<DraftTransaction> draft_trans)
if (!check.empty())
{
auto err_msg = std::string("Not creating split because essentials not set properly:");
- auto add_bullet_item = [](std::string& a, std::string& b)->std::string { return std::move(a) + "\n⢠" + b; };
+ auto add_bullet_item = [](std::string&& a, std::string& b)->std::string { return std::move(a) + "\n⢠" + b; };
err_msg = std::accumulate (check.begin(), check.end(), std::move (err_msg), add_bullet_item);
PWARN ("%s", err_msg.c_str());
return;
diff --git a/gnucash/import-export/csv-imp/gnc-imp-settings-csv.cpp b/gnucash/import-export/csv-imp/gnc-imp-settings-csv.cpp
index ae5e6f396f..53dbe18442 100644
--- a/gnucash/import-export/csv-imp/gnc-imp-settings-csv.cpp
+++ b/gnucash/import-export/csv-imp/gnc-imp-settings-csv.cpp
@@ -42,7 +42,6 @@
#include <iostream>
#include <string>
-const std::string csv_group_prefix{"CSV-"};
const std::string no_settings{N_("No Settings")};
const std::string gnc_exp{N_("GnuCash Export Format")};
const std::string gnc_exp_4{N_("GnuCash Export Format (4.x and older)")};
diff --git a/gnucash/import-export/csv-imp/gnc-import-tx.cpp b/gnucash/import-export/csv-imp/gnc-import-tx.cpp
index 9484e0a26a..5b0b53bcc1 100644
--- a/gnucash/import-export/csv-imp/gnc-import-tx.cpp
+++ b/gnucash/import-export/csv-imp/gnc-import-tx.cpp
@@ -471,7 +471,7 @@ std::string ErrorList::str()
auto err_msg = std::string();
if (!m_error.empty())
{
- auto add_bullet_item = [](std::string& a, std::string& b)->std::string { return std::move(a) + "\n⢠" + b; };
+ auto add_bullet_item = [](std::string&& a, std::string& b)->std::string { return std::move(a) + "\n⢠" + b; };
err_msg = std::accumulate (m_error.begin(), m_error.end(), std::move (err_msg), add_bullet_item);
err_msg.erase (0, 1);
}
diff --git a/gnucash/register/ledger-core/split-register.c b/gnucash/register/ledger-core/split-register.c
index 3afd39dcf8..9ae1d7e146 100644
--- a/gnucash/register/ledger-core/split-register.c
+++ b/gnucash/register/ledger-core/split-register.c
@@ -883,7 +883,7 @@ gnc_split_register_copy_current_internal (SplitRegister* reg,
}
copied_item.cursor_class = cursor_class;
- gnc_hook_add_dangler (HOOK_BOOK_CLOSED, clear_copied_item, NULL, NULL);
+ gnc_hook_add_dangler (HOOK_BOOK_CLOSED, (GFunc)clear_copied_item, NULL, NULL);
LEAVE ("%s %s", use_cut_semantics ? "cut" : "copied",
cursor_class == CURSOR_CLASS_SPLIT ? "split" : "transaction");
}
diff --git a/libgnucash/engine/Account.cpp b/libgnucash/engine/Account.cpp
index 019c613a53..5288d505a2 100644
--- a/libgnucash/engine/Account.cpp
+++ b/libgnucash/engine/Account.cpp
@@ -67,7 +67,6 @@ static const std::string KEY_INCLUDE_CHILDREN("include-children");
static const std::string KEY_POSTPONE("postpone");
static const std::string KEY_LOT_MGMT("lot-mgmt");
static const std::string KEY_ONLINE_ID("online_id");
-static const std::string KEY_IMP_APPEND_TEXT("import-append-text");
static const std::string AB_KEY("hbci");
static const std::string AB_ACCOUNT_ID("account-id");
static const std::string AB_ACCOUNT_UID("account-uid");
diff --git a/libgnucash/engine/gnc-numeric.h b/libgnucash/engine/gnc-numeric.h
index 102270f3af..c0a143cc55 100644
--- a/libgnucash/engine/gnc-numeric.h
+++ b/libgnucash/engine/gnc-numeric.h
@@ -140,7 +140,7 @@ typedef struct _gnc_numeric gnc_numeric;
*
* Possible rounding instructions are:
*/
-enum
+enum GncNumericRoundDenom
{
/** Round toward -infinity */
GNC_HOW_RND_FLOOR = 0x01,
@@ -174,12 +174,8 @@ enum
/** Never round at all, and signal an error if there is a
* fractional result in a computation.
*/
- GNC_HOW_RND_NEVER = 0x08
-};
-
+ GNC_HOW_RND_NEVER = 0x08,
/** How to compute a denominator, or'ed into the "how" field. */
-enum
-{
/** Use any denominator which gives an exactly correct ratio of
* numerator to denominator. Use EXACT when you do not wish to
* lose any information in the result but also do not want to
diff --git a/libgnucash/engine/guid.cpp b/libgnucash/engine/guid.cpp
index 946f3c1d03..0b8e928b28 100644
--- a/libgnucash/engine/guid.cpp
+++ b/libgnucash/engine/guid.cpp
@@ -430,9 +430,9 @@ bool operator == (GUID const & lhs, GncGUID const & rhs) noexcept
}
bool
-operator != (GUID const & one, GUID const & two) noexcept
+operator == (GUID const & one, GUID const & two) noexcept
{
- return one.implementation != two.implementation;
+ return one.implementation == two.implementation;
}
GUID & GUID::operator = (GUID && other) noexcept
@@ -453,5 +453,5 @@ GUID::operator GncGUID () const noexcept
bool
operator==(const GncGUID& lhs, const GncGUID& rhs)
{
- return gnc::GUID{lhs} == gnc::GUID{rhs};
+ return gnc::GUID{lhs} == rhs;
}
diff --git a/libgnucash/engine/guid.hpp b/libgnucash/engine/guid.hpp
index 7a883ecd9b..10e48b9a32 100644
--- a/libgnucash/engine/guid.hpp
+++ b/libgnucash/engine/guid.hpp
@@ -58,10 +58,10 @@ struct GUID
auto end () const noexcept -> decltype (implementation.end ());
bool operator < (GUID const &) noexcept;
friend bool operator == (GUID const &, GncGUID const &) noexcept;
- friend bool operator != (GUID const &, GUID const &) noexcept;
+ friend bool operator == (GUID const &, GUID const &) noexcept;
};
-bool operator != (GUID const &, GUID const &) noexcept;
+bool operator == (GUID const &, GUID const &) noexcept;
bool operator == (GUID const &, GncGUID const &) noexcept;
Summary of changes:
.github/workflows/mac-tests.yaml | 9 ++++----
CMakeLists.txt | 18 +++++++++++----
bindings/python/sqlite3test.c | 4 +++-
gnucash/gnome-utils/gnc-frequency.c | 24 ++++++++++----------
gnucash/gnome/dialog-sx-editor.c | 26 +++++++++++-----------
.../csv-imp/assistant-csv-trans-import.cpp | 4 ++--
gnucash/import-export/csv-imp/gnc-imp-props-tx.cpp | 7 ++++--
.../import-export/csv-imp/gnc-imp-settings-csv.cpp | 1 -
gnucash/import-export/csv-imp/gnc-import-tx.cpp | 2 +-
gnucash/register/ledger-core/split-register.c | 2 +-
libgnucash/engine/Account.cpp | 1 -
libgnucash/engine/gnc-numeric.h | 8 ++-----
libgnucash/engine/guid.cpp | 6 ++---
libgnucash/engine/guid.hpp | 4 ++--
14 files changed, 63 insertions(+), 53 deletions(-)
More information about the gnucash-changes
mailing list