Skip to content

Fix GCC warnings about incomplete classes#1488

Open
Vekhir wants to merge 7 commits into
OpenBoard-org:devfrom
Vekhir:refactor-import-sfinae
Open

Fix GCC warnings about incomplete classes#1488
Vekhir wants to merge 7 commits into
OpenBoard-org:devfrom
Vekhir:refactor-import-sfinae

Conversation

@Vekhir
Copy link
Copy Markdown
Contributor

@Vekhir Vekhir commented May 12, 2026

GCC 16.1 introduces a new warning for SFINAE issues. They can cause a change in behaviour when imports get reordered, leading to hard to debug issues.
Additionally, many used definitions are now included directly instead of relying on transitive includes. Relying on transitivity is brittle and can easily cause issues in lots of files if that transitive chain is broken.


Some forward declarations cause SFINAE issues, because the definition is needed to choose the correct template. This affects the classes UBGraphicsMediaItem, UBGraphicsTextItem, UBBackgroundRuling, UBToolWidget, and WebView.

To eliminate these forward declarations, the imports need to be restructured. The easiest case is replacing the forward declaration with the include of the definition.

This doesn't quite work for UBGraphicsMediaItem as it causes an include cycle:
src/domain/UBGraphicsMediaItem.h includes src/domain/UBItem.h which includes src/domain/UBGraphicsItemDelegate.h which includes src/domain/UBGraphicsMediaItem.h
The solution provided here is to turn the UBGraphicsMediaItem class into a forward declaration in src/domain/UBGraphicsItemDelegate.h

In the course of this work, UBGraphicsItem has been split from UBItem into its own file; this surfaced a lot of transitive includes that weren't properly declared.

@letsfindaway
Copy link
Copy Markdown
Collaborator

I think I need a little bit more explanation to understand the issue. I read some explanations about SFINAE, but I did not catch how this applies e.g. to UBGraphicsTextItem.

Just looking at the first header file where this was replaced: UBSvgSubsetAdaptor. The header uses this class just twice: UBGraphicsTextItem* is once used as return type and once as argument type. So on first sight this is a perfect candidate for a forward declaration, as only the size of the pointer is needed for the compiler at this stage.

I also failed to find a template, which could be problematic. So it seems I was just looking in the wrong places.

Could you explain the problem to me, probably just on that example? Or have you some more good literature for me to read?

Thanks!

@Vekhir
Copy link
Copy Markdown
Contributor Author

Vekhir commented May 13, 2026

I also failed to find a template, which could be problematic. So it seems I was just looking in the wrong places.

The problematic template that GCC pointed me to is this one:
https://github.com/qt/qtbase/blob/48075acd8faac4a9c6f621e4957905ef60b2b0b1/src/corelib/kernel/qmetatype.h#L344

    struct is_complete_helper
    {
        template<typename U>
        static auto check(U *) -> std::integral_constant<bool, sizeof(U) != 0>; // problematic template
        static auto check(...) -> std::false_type;
        using type = decltype(check(static_cast<T *>(nullptr)));
    };

I don't know how or why this template is called. It isn't used for all Qt derived classes.
This template uses the class itself, not just the pointer. This works both with a forward declaration as well as a complete type; I believe the forward declaration implies sizeof(U) == 0.

Perhaps this quote from the GCC enablement of -Wsfinae-incomplete (https://gcc.gnu.org/pipermail/gcc-patches/2025-June/686778.html) helps here:

So -Wsfinae-incomplete remembers if we've failed a requirement for a complete type in a non-tf_error context, and later warns if the type becomes complete.


Honestly, I don't quite understand how this all works either. It already took me some time to figure out that the forward declarations are the issue in the first place.
The practical argument for this PR is: There were warnings with what looked correct. Now it is still correct, and the warnings are gone.

@Vekhir
Copy link
Copy Markdown
Contributor Author

Vekhir commented May 13, 2026

For completeness, these are the warnings I encountered:

warning: defining ‘UBGraphicsTextItem’, which previously failed to be complete in a SFINAE context [-Wsfinae-incomplete=]
[ 29%] Building CXX object CMakeFiles/openboard.dir/src/core/UBApplicationController.cpp.o
In file included from /build/openboard-git/src/build/openboard_autogen/A7EWVEEJ67/moc_UBGraphicsMediaItem.cpp:9,
                 from /build/openboard-git/src/build/openboard_autogen/mocs_compilation.cpp:46:
/build/openboard-git/src/build/openboard_autogen/A7EWVEEJ67/../../../OpenBoard/src/domain/UBGraphicsMediaItem.h:47:7: warning: defining ‘UBGraphicsMediaItem’, which previously failed to be complete in a SFINAE context [-Wsfinae-incomplete=]
   47 | class UBGraphicsMediaItem : public QObject, public UBMediaAssetItem, public UBGraphicsItem, public QGraphicsRectItem, public UBResizableGraphicsItem
      |       ^~~~~~~~~~~~~~~~~~~
In file included from /usr/include/qt6/QtCore/qobject.h:18,
                 from /usr/include/qt6/QtCore/qabstractanimation.h:8,
                 from /usr/include/qt6/QtCore/QtCore:20,
                 from /usr/include/qt6/QtGui/QtGuiDepends:3,
                 from /usr/include/qt6/QtGui/QtGui:3,
                 from /build/openboard-git/src/build/openboard_autogen/4TYOLK647N/../../../OpenBoard/src/adaptors/UBExportAdaptor.h:33,
                 from /build/openboard-git/src/build/openboard_autogen/4TYOLK647N/moc_UBExportAdaptor.cpp:9,
                 from /build/openboard-git/src/build/openboard_autogen/mocs_compilation.cpp:2:
/usr/include/qt6/QtCore/qmetatype.h:343:64: note: here.  Use ‘-Wsfinae-incomplete=2’ for a diagnostic at that point
  343 |         static auto check(U *) -> std::integral_constant<bool, sizeof(U) != 0>;
      |                                                                ^~~~~~~~~
[ 29%] Building CXX object CMakeFiles/openboard.dir/src/core/UBDisplayManager.cpp.o
[ 29%] Building CXX object CMakeFiles/openboard.dir/src/core/UBDocumentManager.cpp.o
In file included from /build/openboard-git/src/build/openboard_autogen/A7EWVEEJ67/moc_UBGraphicsTextItem.cpp:9,
                 from /build/openboard-git/src/build/openboard_autogen/mocs_compilation.cpp:50:
/build/openboard-git/src/build/openboard_autogen/A7EWVEEJ67/../../../OpenBoard/src/domain/UBGraphicsTextItem.h:41:7: warning: defining ‘UBGraphicsTextItem’, which previously failed to be complete in a SFINAE context [-Wsfinae-incomplete=]
   41 | class UBGraphicsTextItem : public QGraphicsTextItem, public UBItem, public UBResizableGraphicsItem, public UBGraphicsItem
      |       ^~~~~~~~~~~~~~~~~~
/usr/include/qt6/QtCore/qmetatype.h:343:64: note: here.  Use ‘-Wsfinae-incomplete=2’ for a diagnostic at that point
  343 |         static auto check(U *) -> std::integral_constant<bool, sizeof(U) != 0>;
      |                                                                ^~~~~~~~~
[ 30%] Building CXX object CMakeFiles/openboard.dir/src/core/UBDownloadManager.cpp.o
In file included from /build/openboard-git/src/build/openboard_autogen/MXUWEOXILK/../../../OpenBoard/src/gui/UBBackgroundManager.h:26,
                 from /build/openboard-git/src/build/openboard_autogen/MXUWEOXILK/moc_UBBackgroundManager.cpp:9,
                 from /build/openboard-git/src/build/openboard_autogen/mocs_compilation.cpp:64:
/build/openboard-git/src/OpenBoard/src/gui/UBBackgroundRuling.h:40:7: warning: defining ‘UBBackgroundRuling’, which previously failed to be complete in a SFINAE context [-Wsfinae-incomplete=]
   40 | class UBBackgroundRuling
      |       ^~~~~~~~~~~~~~~~~~
/usr/include/qt6/QtCore/qmetatype.h:343:64: note: here.  Use ‘-Wsfinae-incomplete=2’ for a diagnostic at that point
  343 |         static auto check(U *) -> std::integral_constant<bool, sizeof(U) != 0>;
      |                                                                ^~~~~~~~~
[ 30%] Building CXX object CMakeFiles/openboard.dir/src/core/UBDownloadThread.cpp.o
In file included from /build/openboard-git/src/build/openboard_autogen/MXUWEOXILK/moc_UBToolWidget.cpp:9,
                 from /build/openboard-git/src/build/openboard_autogen/mocs_compilation.cpp:102:
/build/openboard-git/src/build/openboard_autogen/MXUWEOXILK/../../../OpenBoard/src/gui/UBToolWidget.h:45:7: warning: defining ‘UBToolWidget’, which previously failed to be complete in a SFINAE context [-Wsfinae-incomplete=]
   45 | class UBToolWidget : public QWidget
      |       ^~~~~~~~~~~~
/usr/include/qt6/QtCore/qmetatype.h:343:64: note: here.  Use ‘-Wsfinae-incomplete=2’ for a diagnostic at that point
  343 |         static auto check(U *) -> std::integral_constant<bool, sizeof(U) != 0>;
      |                                                                ^~~~~~~~~
In file included from /build/openboard-git/src/build/openboard_autogen/JHUTH3BBPQ/moc_webview.cpp:9,
                 from /build/openboard-git/src/build/openboard_autogen/mocs_compilation.cpp:144:
/build/openboard-git/src/build/openboard_autogen/JHUTH3BBPQ/../../../OpenBoard/src/web/simplebrowser/webview.h:60:7: warning: defining ‘WebView’, which previously failed to be complete in a SFINAE context [-Wsfinae-incomplete=]
   60 | class WebView : public QWebEngineView
      |       ^~~~~~~
/usr/include/qt6/QtCore/qmetatype.h:343:64: note: here.  Use ‘-Wsfinae-incomplete=2’ for a diagnostic at that point
  343 |         static auto check(U *) -> std::integral_constant<bool, sizeof(U) != 0>;
      |                                                                ^~~~~~~~~

Using -Wsfinae-incomplete=2 just hides the backtrace without any additional information.

@letsfindaway
Copy link
Copy Markdown
Collaborator

Thanks for this. I think I have now more understanding. I analyzed the case for UBBackgroundRuling, because it is not so often used. I think the problem is the following.

In UBBoardController.h:232 a slot setBackground is defined using UBBackgroundRuling* as parameter. The MOC compiler tries to generate code for this slot. In order to do so, it requires that the class is fully defined, because it might be used in a queued connection. There is some code in https://github.com/qt/qtbase/blob/48075acd8faac4a9c6f621e4957905ef60b2b0b1/src/corelib/kernel/qtmochelpers.h#L160-L176 which does this check, and which finally uses the is_complete_helper.

In the end this is not a real problem because setBackground is never used in a connection, but this might trigger this warning.

So in this specific case it could also be an option not to define this function as a slot, or to include UBBackgroundRuling.h in UBBoardController.h.

If my analysis is correct, then at least it opens more ways to mitigate this problem.

Vekhir added 7 commits May 14, 2026 22:04
Include QGraphicsSvgItem directly instead
UBItem.h is needed for UBGraphicsItem

UBGraphicsItemDelegate is used via UBGraphicsItem::Delegate

UB.h is needed for UBGraphicsItemData
The two classes are unrelated to each other. The split allows more
precise includes in downstream users, and better separation of
concerns for development.
Using a class as a slot parameter requires it to be fully
defined. Qt checks that to ensure correct behaviour.

The checking is done via templates, where the SFINAE principle
means that an incomplete class doesn't lead to errors. This
can lead to issues when selecting the appropriate template, hence
GCC warns about that.

In the cases where issues can occur, this commit includes the full
class definition.

Thanks to @letsfindaway for the precise investigation.
@Vekhir Vekhir force-pushed the refactor-import-sfinae branch from aa15931 to 9c4ae16 Compare May 14, 2026 21:33
@Vekhir
Copy link
Copy Markdown
Contributor Author

Vekhir commented May 14, 2026

The PR is now split into 7 smaller commits. Each commit deals with a small part of the refactoring, grouped by the kind of change for easier review. I've also removed a few changes to reduce the complexity.

The last commit solves the warning by including the definition where necessary. A noted above, it's only needed where the class is used as the parameter for a slot. In all other cases, the declaration is enough as only the pointer size is needed.

@Vekhir Vekhir changed the title refactor: Improve imports and fix SFINAE issues Fix GCC warnings about incomplete classes May 15, 2026
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