From 1881ea0d2759b7e84dd2aac81237390ef5158c9a Mon Sep 17 00:00:00 2001 From: Marko Lindqvist Date: Sat, 18 Mar 2023 03:59:52 +0200 Subject: [PATCH 04/25] Fix implicit capture errors in C++20 mode See osdn #47555 Signed-off-by: Marko Lindqvist --- Makefile.am | 1 + client/gui-qt/citydlg.cpp | 15 ++++++++++----- client/gui-qt/cityrep.cpp | 7 +++++-- client/gui-qt/dialogs.cpp | 3 ++- client/gui-qt/diplodlg.cpp | 6 ++++-- client/gui-qt/gui_main.h | 6 ++++++ client/gui-qt/plrdlg.cpp | 7 +++++-- configure.ac | 9 ++++++--- gen_headers/meson_freeciv_config.h.in | 3 +++ m4/c++20.m4 | 23 +++++++++++++++++++++++ meson.build | 9 +++++++++ 11 files changed, 74 insertions(+), 15 deletions(-) create mode 100644 m4/c++20.m4 diff --git a/Makefile.am b/Makefile.am index 34a3d25a29..62cf00942a 100644 --- a/Makefile.am +++ b/Makefile.am @@ -33,6 +33,7 @@ EXTRA_DIST = autogen.sh \ m4/c11.m4 \ m4/c23.m4 \ m4/c++11.m4 \ + m4/c++20.m4 \ m4/codeset.m4 \ m4/compiler.m4 \ m4/debug.m4 \ diff --git a/client/gui-qt/citydlg.cpp b/client/gui-qt/citydlg.cpp index a2ab2a8141..d3b2755730 100644 --- a/client/gui-qt/citydlg.cpp +++ b/client/gui-qt/citydlg.cpp @@ -1414,7 +1414,8 @@ void city_map::context_menu(QPoint point) } con_menu->setAttribute(Qt::WA_DeleteOnClose); - connect(con_menu, &QMenu::triggered, [=](QAction *act) { + connect(con_menu, &QMenu::triggered, + CAPTURE_DEFAULT_THIS (QAction *act) { bool target = false; struct packet_worker_task task; @@ -2357,7 +2358,8 @@ void city_dialog::save_cma() _("Name new preset"), _("new preset")); ask->setAttribute(Qt::WA_DeleteOnClose); - connect(ask, &hud_message_box::accepted, this, [=]() { + connect(ask, &hud_message_box::accepted, this, + CAPTURE_DEFAULT_THIS () { struct cm_parameter param; QByteArray ask_bytes = ask->input_edit.text().toLocal8Bit(); QString text = ask_bytes.data(); @@ -2604,7 +2606,8 @@ void city_dialog::cma_remove() ask->setStandardButtons(QMessageBox::Cancel | QMessageBox::Ok); ask->setDefaultButton(QMessageBox::Cancel); ask->setAttribute(Qt::WA_DeleteOnClose); - connect(ask, &hud_message_box::accepted, this, [=]() { + connect(ask, &hud_message_box::accepted, this, + CAPTURE_DEFAULT_THIS () { cmafec_preset_remove(i); update_cma_tab(); }); @@ -2677,7 +2680,8 @@ void city_dialog::cma_context_menu(const QPoint &p) cma_menu->setAttribute(Qt::WA_DeleteOnClose); cma_del_item = cma_menu->addAction(_("Remove Governor")); - connect(cma_menu, &QMenu::triggered, this, [=](QAction *act) { + connect(cma_menu, &QMenu::triggered, this, + CAPTURE_DEFAULT_THIS (QAction *act) { if (act == cma_del_item) { cma_remove(); } @@ -2763,7 +2767,8 @@ void city_dialog::display_worklist_menu(const QPoint &p) city_set_queue(pcity, worklist); }); - connect(insert_menu, &QMenu::triggered, this, [=](QAction *act) { + connect(insert_menu, &QMenu::triggered, this, + CAPTURE_DEFAULT_THIS (QAction *act) { QVariant id = act->data(); struct city *pcity = game_city_by_number(city_id); const struct worklist *worklist; diff --git a/client/gui-qt/cityrep.cpp b/client/gui-qt/cityrep.cpp index 760c2c453d..26f23ff83a 100644 --- a/client/gui-qt/cityrep.cpp +++ b/client/gui-qt/cityrep.cpp @@ -26,6 +26,7 @@ // gui-qt #include "cityrep.h" #include "fc_client.h" +#include "gui_main.h" #include "hudwidget.h" /***********************************************************************//** @@ -543,7 +544,8 @@ void city_widget::display_list_menu(const QPoint &) } list_menu->setAttribute(Qt::WA_DeleteOnClose); - connect(list_menu, &QMenu::triggered, this, [=](QAction *act) { + connect(list_menu, &QMenu::triggered, this, + CAPTURE_DEFAULT_THIS (QAction *act) { QVariant qvar, qvar2; enum menu_labels m_state; cid id; @@ -1136,7 +1138,8 @@ void city_widget::display_header_menu(const QPoint &) actions.append(myAct); } hideshow_column->setAttribute(Qt::WA_DeleteOnClose); - connect(hideshow_column, &QMenu::triggered, this, [=](QAction *act) { + connect(hideshow_column, &QMenu::triggered, this, + CAPTURE_DEFAULT_THIS (QAction *act) { int col; struct city_report_spec *spec; if (!act) { diff --git a/client/gui-qt/dialogs.cpp b/client/gui-qt/dialogs.cpp index d7cfe01435..d9fdb4abde 100644 --- a/client/gui-qt/dialogs.cpp +++ b/client/gui-qt/dialogs.cpp @@ -1495,7 +1495,8 @@ void choice_dialog::add_item(QString title, pfcn_void func, QVariant data1, data1, data2); int action = buttons_list.count(); - QObject::connect(button, &QPushButton::clicked, [=]() { + QObject::connect(button, &QPushButton::clicked, + CAPTURE_DEFAULT_THIS () { execute_action(action); }); diff --git a/client/gui-qt/diplodlg.cpp b/client/gui-qt/diplodlg.cpp index 8185aced7c..3d8689a064 100644 --- a/client/gui-qt/diplodlg.cpp +++ b/client/gui-qt/diplodlg.cpp @@ -388,7 +388,8 @@ void diplo_wdg::show_menu(struct player *pplayer) while (adv_iter != adv_list.constEnd()) { id = adv_iter.value(); some_action = adv_menu->addAction(adv_iter.key()); - connect(some_action, &QAction::triggered, this, [=]() { + connect(some_action, &QAction::triggered, this, + CAPTURE_DEFAULT_THIS () { give_advance(id); }); adv_iter++; @@ -413,7 +414,8 @@ void diplo_wdg::show_menu(struct player *pplayer) while (city_iter != city_list.constEnd()) { id = city_iter.value(); some_action = city_menu->addAction(city_iter.key()); - connect(some_action, &QAction::triggered, this, [=]() { + connect(some_action, &QAction::triggered, this, + CAPTURE_DEFAULT_THIS () { give_city(id); }); city_iter++; diff --git a/client/gui-qt/gui_main.h b/client/gui-qt/gui_main.h index e0cc87f050..6e675ff855 100644 --- a/client/gui-qt/gui_main.h +++ b/client/gui-qt/gui_main.h @@ -25,4 +25,10 @@ QApplication *current_app(); #define mevent_gpos(__ev__) (__ev__)->globalPos() #endif // FC_QT5_MODE +#ifdef FREECIV_HAVE_CXX20_CAPTURE_THIS +#define CAPTURE_DEFAULT_THIS [=, this] +#else // FREECIV_HAVE_CXX20_CAPTURE_THIS +#define CAPTURE_DEFAULT_THIS [=] +#endif // FREECIV_HAVE_CXX20_CAPTURE_THIS + #endif // FC__GUI_MAIN_H diff --git a/client/gui-qt/plrdlg.cpp b/client/gui-qt/plrdlg.cpp index 80f3ddf70b..3f51861a33 100644 --- a/client/gui-qt/plrdlg.cpp +++ b/client/gui-qt/plrdlg.cpp @@ -27,6 +27,7 @@ // gui-qt #include "fc_client.h" +#include "gui_main.h" #include "plrdlg.h" /**********************************************************************//** @@ -436,7 +437,8 @@ void plr_widget::display_header_menu(const QPoint &) } hideshow_column->setAttribute(Qt::WA_DeleteOnClose); - connect(hideshow_column, &QMenu::triggered, this, [=](QAction *act) { + connect(hideshow_column, &QMenu::triggered, this, + CAPTURE_DEFAULT_THIS (QAction *act) { int col; struct player_dlg_column *pcol; @@ -954,7 +956,8 @@ void plr_report::toggle_ai_mode() } ai_menu->setAttribute(Qt::WA_DeleteOnClose); - connect(ai_menu, &QMenu::triggered, [=](QAction *act) { + connect(ai_menu, &QMenu::triggered, + CAPTURE_DEFAULT_THIS (QAction *act) { int lvl; if (act == toggle_ai_act) { diff --git a/configure.ac b/configure.ac index f88afb1720..e9246f31ed 100644 --- a/configure.ac +++ b/configure.ac @@ -774,8 +774,10 @@ dnl check profiling FC_GPROF dnl Detect flags to be used in configure tests that should fail on warnings -WERROR_TEST_FLAGS="" -FC_C_FLAGS([-Werror -Wall], [], [WERROR_TEST_FLAGS]) +WERROR_C_TEST_FLAGS="" +WERROR_CXX_TEST_FLAGS="" +FC_C_FLAGS([-Werror -Wall], [], [WERROR_C_TEST_FLAGS]) +FC_CXX_FLAGS([-Werror -Wall], [], [WERROR_CXX_TEST_FLAGS]) FC_C99_VARIADIC_MACROS FC_C99_VARIABLE_ARRAYS @@ -795,9 +797,10 @@ FC_C23_NULLPTR FC_CXX11_STATIC_ASSERT FC_CXX11_NULLPTR +FC_CXX20_CAPTURE_THIS _CFLAGS="$CFLAGS" -CFLAGS="$CFLAGS $WERROR_TEST_FLAGS" +CFLAGS="$CFLAGS $WERROR_C_TEST_FLAGS" FC_SIZE_T_FORMAT CFLAGS="$_CFLAGS" diff --git a/gen_headers/meson_freeciv_config.h.in b/gen_headers/meson_freeciv_config.h.in index 2ad90fa6e8..e447ac4789 100644 --- a/gen_headers/meson_freeciv_config.h.in +++ b/gen_headers/meson_freeciv_config.h.in @@ -33,6 +33,9 @@ /* nullptr available at C++ */ #mesondefine FREECIV_HAVE_CXX_NULLPTR +/* C++20 capture this supported */ +#mesondefine FREECIV_HAVE_CXX20_CAPTURE_THIS + /* Use pthreads as thread implementation */ #mesondefine FREECIV_HAVE_PTHREAD diff --git a/m4/c++20.m4 b/m4/c++20.m4 new file mode 100644 index 0000000000..261b0873b8 --- /dev/null +++ b/m4/c++20.m4 @@ -0,0 +1,23 @@ +# Check for the presence of C++20 features. + +# Check for C++20 capture 'this' by value +# +AC_DEFUN([FC_CXX20_CAPTURE_THIS], +[ + if test "x$cxx_works" = "xyes" ; then + AC_CACHE_CHECK([for C++20 capture this], [ac_cv_cxx20_capture_this], + [AC_LANG_PUSH([C++]) + _CXXFLAGS="$CXXFLAGS" + CXXFLAGS="$CXXFLAGS $WERROR_CXX_TEST_FLAGS" + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[class me { +void top(); }; +void me::top() { [=, this]() {}; }; +]])], +[ac_cv_cxx20_capture_this=yes], [ac_cv_cxx20_capture_this=no]) + CXXFLAGS="$_CXXFLAGS" + AC_LANG_POP([C++])]) + if test "x${ac_cv_cxx20_capture_this}" = "xyes" ; then + AC_DEFINE([FREECIV_HAVE_CXX20_CAPTURE_THIS], [1], [C++20 capture 'this' supported]) + fi + fi +]) diff --git a/meson.build b/meson.build index 0ae88e76d3..1389c68181 100644 --- a/meson.build +++ b/meson.build @@ -744,6 +744,15 @@ if crosser pub_conf_data.set('FREECIV_CROSSER', 1) endif +if cxx_compiler.compiles(''' +class me { +void top(); }; +void me::top() { [=, this]() {}; }; +''', + name: 'C++20 capture this') + pub_conf_data.set('FREECIV_HAVE_CXX20_CAPTURE_THIS', 1) +endif + configure_file(input : 'gen_headers/meson_fc_config.h.in', output : 'fc_config.h', configuration: priv_conf_data) -- 2.39.2