From 6ec1fd70fa2e3725b8f4aad1cd4b034e81f9bbd6 Mon Sep 17 00:00:00 2001 From: Marko Lindqvist Date: Sat, 18 Mar 2023 04:07:22 +0200 Subject: [PATCH 9/9] 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 | 4 +++- client/gui-qt/diplodlg.cpp | 6 ++++-- client/gui-qt/gui_main.h | 10 ++++++++-- client/gui-qt/plrdlg.cpp | 7 +++++-- configure.ac | 1 + gen_headers/meson_freeciv_config.h.in | 3 +++ m4/c++20.m4 | 20 ++++++++++++++++++++ meson.build | 10 ++++++++++ 11 files changed, 70 insertions(+), 14 deletions(-) create mode 100644 m4/c++20.m4 diff --git a/Makefile.am b/Makefile.am index 9cf3b5f155..38e932666b 100644 --- a/Makefile.am +++ b/Makefile.am @@ -39,6 +39,7 @@ EXTRA_DIST = autogen.sh \ m4/c99.m4 \ m4/c11.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 0e26c54c97..f73b5d66b5 100644 --- a/client/gui-qt/citydlg.cpp +++ b/client/gui-qt/citydlg.cpp @@ -1438,7 +1438,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; @@ -2381,7 +2382,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(); @@ -2628,7 +2630,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(); }); @@ -2701,7 +2704,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(); } @@ -2782,7 +2786,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 fcbfa0c576..40cfaa836f 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; @@ -1138,7 +1140,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 2e06d60309..d478279fcc 100644 --- a/client/gui-qt/dialogs.cpp +++ b/client/gui-qt/dialogs.cpp @@ -59,6 +59,7 @@ // gui-qt #include "dialogs.h" #include "fc_client.h" +#include "gui_main.h" #include "hudwidget.h" #include "qtg_cxxside.h" #include "sprite.h" @@ -1470,7 +1471,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 4d64655be5..ab74c7ee0c 100644 --- a/client/gui-qt/diplodlg.cpp +++ b/client/gui-qt/diplodlg.cpp @@ -388,7 +388,8 @@ void diplo_wdg::show_menu(int player) 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(int player) 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 fe721e545a..d825cba768 100644 --- a/client/gui-qt/gui_main.h +++ b/client/gui-qt/gui_main.h @@ -1,4 +1,4 @@ -/********************************************************************** +/*********************************************************************** Freeciv - Copyright (C) 1996 - A Kjeldberg, L Gregersen, P Unold This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -17,4 +17,10 @@ void popup_quit_dialog(); QApplication *current_app(); -#endif /* FC__GUI_MAIN_H */ +#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 56269466e7..0ad2220034 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; @@ -951,7 +953,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 21ce91369e..2bf03beebd 100644 --- a/configure.ac +++ b/configure.ac @@ -759,6 +759,7 @@ FC_STATIC_STRLEN FC_CXX11_STATIC_ASSERT FC_CXX11_NULLPTR +FC_CXX20_CAPTURE_THIS _CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $WERROR_TEST_FLAGS" diff --git a/gen_headers/meson_freeciv_config.h.in b/gen_headers/meson_freeciv_config.h.in index ab1dcb2ef4..8a147b2c5a 100644 --- a/gen_headers/meson_freeciv_config.h.in +++ b/gen_headers/meson_freeciv_config.h.in @@ -27,6 +27,9 @@ /* Is this freeciv-web instead of regular build */ #mesondefine FREECIV_WEB +/* 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..1787e1eb2b --- /dev/null +++ b/m4/c++20.m4 @@ -0,0 +1,20 @@ +# 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++]) + 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]) + 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 c860a8f52f..39b4014f63 100644 --- a/meson.build +++ b/meson.build @@ -7,6 +7,7 @@ if not get_option('ack_experimental') endif c_compiler = meson.get_compiler('c') +cxx_compiler = meson.get_compiler('cpp') if c_compiler.has_argument('-Wno-nonnull-compare') add_global_arguments('-Wno-nonnull-compare', language : 'c') @@ -616,6 +617,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