Skip to content

Fix -Wsfinae-incomplete warnings when building with GCC 16.x#949

Open
hebasto wants to merge 1 commit into
bitcoin-core:masterfrom
hebasto:260719-sfinae
Open

Fix -Wsfinae-incomplete warnings when building with GCC 16.x#949
hebasto wants to merge 1 commit into
bitcoin-core:masterfrom
hebasto:260719-sfinae

Conversation

@hebasto

@hebasto hebasto commented Jul 19, 2026

Copy link
Copy Markdown
Member

According to the CMake documentation for AUTOMOC, all moc output files that are not included in a source file are aggregated into the CMake-generated <AUTOGEN_BUILD_DIR>/mocs_compilation.cpp, which is added to the target's sources.

Within that single translation unit, moc-generated code checks the completeness of a signal or slot parameter type while it is still only forward-declared, and the type is completed later, when a subsequently included moc_*.cpp file pulls in the header that defines it. GCC 16.x diagnoses this pattern with the -Wsfinae-incomplete warning, which is enabled by default.

Including the moc output files at the end of the corresponding source files excludes them from mocs_compilation.cpp, so each one is compiled in a translation unit where the relevant types are complete.

FWIW, Qt itself uses the same approach throughout its own codebase. Also see https://www.youtube.com/watch?v=Cx_m-qVnEjo.


Steps to reproduce on the master branch @ 18c05d9 on Fedora 44 (GCC 16.1.1):

$ cmake --preset dev-mode
$ cmake --build build_dev_mode -t bitcoind
$ cmake --build build_dev_mode -t bitcoin-qt
[166/172] Building CXX object src/qt/CMakeFiles/bitcoinqt.dir/bitcoinqt_autogen/mocs_compilation.cpp.o
In file included from /home/hebasto/dev/bitcoin-gui/build_dev_mode/src/qt/bitcoinqt_autogen/EWIEGA46WW/moc_bitcoingui.cpp:9,
                 from /home/hebasto/dev/bitcoin-gui/build_dev_mode/src/qt/bitcoinqt_autogen/mocs_compilation.cpp:9:
/home/hebasto/dev/bitcoin-gui/src/qt/bitcoingui.h:67:7: warning: defining ‘BitcoinGUI’, which previously failed to be complete in a SFINAE context [-Wsfinae-incomplete=]
   67 | class BitcoinGUI : public QMainWindow
      |       ^~~~~~~~~~
In file included from /usr/include/qt6/QtCore/qobject.h:19,
                 from /usr/include/qt6/QtWidgets/qwidget.h:10,
                 from /usr/include/qt6/QtWidgets/qdialog.h:9,
                 from /usr/include/qt6/QtWidgets/QDialog:1,
                 from /home/hebasto/dev/bitcoin-gui/src/qt/addressbookpage.h:8,
                 from /home/hebasto/dev/bitcoin-gui/build_dev_mode/src/qt/bitcoinqt_autogen/EWIEGA46WW/moc_addressbookpage.cpp:9,
                 from /home/hebasto/dev/bitcoin-gui/build_dev_mode/src/qt/bitcoinqt_autogen/mocs_compilation.cpp:2:
/usr/include/qt6/QtCore/qmetatype.h:344:64: note: here.  Use ‘-Wsfinae-incomplete=2’ for a diagnostic at that point
  344 |         static auto check(U *) -> std::integral_constant<bool, sizeof(U) != 0>;
      |                                                                ^~~~~~~~~
In file included from /home/hebasto/dev/bitcoin-gui/src/qt/paymentserver.h:35,
                 from /home/hebasto/dev/bitcoin-gui/build_dev_mode/src/qt/bitcoinqt_autogen/EWIEGA46WW/moc_paymentserver.cpp:9,
                 from /home/hebasto/dev/bitcoin-gui/build_dev_mode/src/qt/bitcoinqt_autogen/mocs_compilation.cpp:27:
/home/hebasto/dev/bitcoin-gui/src/qt/sendcoinsrecipient.h:15:7: warning: defining ‘SendCoinsRecipient’, which previously failed to be complete in a SFINAE context [-Wsfinae-incomplete=]
   15 | class SendCoinsRecipient
      |       ^~~~~~~~~~~~~~~~~~
/usr/include/qt6/QtCore/qmetatype.h:344:64: note: here.  Use ‘-Wsfinae-incomplete=2’ for a diagnostic at that point
  344 |         static auto check(U *) -> std::integral_constant<bool, sizeof(U) != 0>;
      |                                                                ^~~~~~~~~
In file included from /home/hebasto/dev/bitcoin-gui/src/qt/psbtoperationsdialog.h:13,
                 from /home/hebasto/dev/bitcoin-gui/build_dev_mode/src/qt/bitcoinqt_autogen/EWIEGA46WW/moc_psbtoperationsdialog.cpp:9,
                 from /home/hebasto/dev/bitcoin-gui/build_dev_mode/src/qt/bitcoinqt_autogen/mocs_compilation.cpp:30:
/home/hebasto/dev/bitcoin-gui/src/qt/walletmodel.h:48:7: warning: defining ‘WalletModel’, which previously failed to be complete in a SFINAE context [-Wsfinae-incomplete=]
   48 | class WalletModel : public QObject
      |       ^~~~~~~~~~~
/usr/include/qt6/QtCore/qmetatype.h:344:64: note: here.  Use ‘-Wsfinae-incomplete=2’ for a diagnostic at that point
  344 |         static auto check(U *) -> std::integral_constant<bool, sizeof(U) != 0>;
      |                                                                ^~~~~~~~~
In file included from /home/hebasto/dev/bitcoin-gui/build_dev_mode/src/qt/bitcoinqt_autogen/EWIEGA46WW/moc_qvalidatedlineedit.cpp:9,
                 from /home/hebasto/dev/bitcoin-gui/build_dev_mode/src/qt/bitcoinqt_autogen/mocs_compilation.cpp:32:
/home/hebasto/dev/bitcoin-gui/src/qt/qvalidatedlineedit.h:13:7: warning: defining ‘QValidatedLineEdit’, which previously failed to be complete in a SFINAE context [-Wsfinae-incomplete=]
   13 | class QValidatedLineEdit : public QLineEdit
      |       ^~~~~~~~~~~~~~~~~~
/usr/include/qt6/QtCore/qmetatype.h:344:64: note: here.  Use ‘-Wsfinae-incomplete=2’ for a diagnostic at that point
  344 |         static auto check(U *) -> std::integral_constant<bool, sizeof(U) != 0>;
      |                                                                ^~~~~~~~~
In file included from /home/hebasto/dev/bitcoin-gui/build_dev_mode/src/qt/bitcoinqt_autogen/EWIEGA46WW/moc_rpcconsole.cpp:9,
                 from /home/hebasto/dev/bitcoin-gui/build_dev_mode/src/qt/bitcoinqt_autogen/mocs_compilation.cpp:37:
/home/hebasto/dev/bitcoin-gui/src/qt/rpcconsole.h:43:7: warning: defining ‘RPCConsole’, which previously failed to be complete in a SFINAE context [-Wsfinae-incomplete=]
   43 | class RPCConsole: public QWidget
      |       ^~~~~~~~~~
/usr/include/qt6/QtCore/qmetatype.h:344:64: note: here.  Use ‘-Wsfinae-incomplete=2’ for a diagnostic at that point
  344 |         static auto check(U *) -> std::integral_constant<bool, sizeof(U) != 0>;
      |                                                                ^~~~~~~~~
In file included from /home/hebasto/dev/bitcoin-gui/build_dev_mode/src/qt/bitcoinqt_autogen/EWIEGA46WW/moc_sendcoinsentry.cpp:9,
                 from /home/hebasto/dev/bitcoin-gui/build_dev_mode/src/qt/bitcoinqt_autogen/mocs_compilation.cpp:39:
/home/hebasto/dev/bitcoin-gui/src/qt/sendcoinsentry.h:26:7: warning: defining ‘SendCoinsEntry’, which previously failed to be complete in a SFINAE context [-Wsfinae-incomplete=]
   26 | class SendCoinsEntry : public QWidget
      |       ^~~~~~~~~~~~~~
/usr/include/qt6/QtCore/qmetatype.h:344:64: note: here.  Use ‘-Wsfinae-incomplete=2’ for a diagnostic at that point
  344 |         static auto check(U *) -> std::integral_constant<bool, sizeof(U) != 0>;
      |                                                                ^~~~~~~~~
[172/172] Linking CXX executable bin/bitcoin-qt

@DrahtBot

DrahtBot commented Jul 19, 2026

Copy link
Copy Markdown
Contributor

The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.

Reviews

See the guideline and AI policy for information on the review process.
A summary of reviews will appear here.

@DrahtBot

Copy link
Copy Markdown
Contributor

🚧 At least one of the CI tasks failed.
Task lint: https://github.com/bitcoin-core/gui/actions/runs/29695312658/job/88214942136
LLM reason (✨ experimental): CI failed because the lint-includes check detected C++ files including .cpp sources (triggering a lint “all_python_linters” failure).

Hints

Try to run the tests locally, according to the documentation. However, a CI failure may still
happen due to a number of reasons, for example:

  • Possibly due to a silent merge conflict (the changes in this pull request being
    incompatible with the current code in the target branch). If so, make sure to rebase on the latest
    commit of the target branch.

  • A sanitizer issue, which can only be found by compiling with the sanitizer and running the
    affected test.

  • An intermittent issue.

Leave a comment here, if you need help tracking down a confusing failure.

According to the CMake documentation for `AUTOMOC`, all `moc` output
files that are not included in a source file are aggregated into the
CMake-generated `<AUTOGEN_BUILD_DIR>/mocs_compilation.cpp`, which is
added to the target's sources.

Within that single translation unit, `moc`-generated code checks the
completeness of a signal or slot parameter type while it is still only
forward-declared, and the type is completed later, when a subsequently
included `moc_*.cpp` file pulls in the header that defines it. GCC 16.x
diagnoses this pattern with the `-Wsfinae-incomplete` warning, which is
enabled by default.

Including the `moc` output files at the end of the corresponding source
files excludes them from `mocs_compilation.cpp`, so each one is
compiled in a translation unit where the relevant types are complete.

Additionally:
1. Some of the `BitcoinGUI` class's private members are gated with
   `#ifdef ENABLE_WALLET` to prevent `-Wunused-private-field` warnings
   when building with `-DENABLE_WALLET=OFF`.
2. `test/lint/lint-includes.py` is adjusted to allow new `#include`
   statements.
@hebasto

hebasto commented Jul 20, 2026

Copy link
Copy Markdown
Member Author

Friendly ping @maflcko @l0rinc

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants