Skip to content

Xcode 16.4 breaks Swift C++ interop when C++ uses forward-decl #81965

@broccolihighkicks

Description

@broccolihighkicks

Description

I upgraded my Xcode from 16.2 to 16.4, and now the same code will not compile.

The errors:

error: invalid application of 'sizeof' to an incomplete type
note: forward declaration of ...

I am using the imgui C++ library.

Was there a change to how the Swift compiler does C++ interop? Should I be setting something in particular in my Swift PM config file? Should it be possible to compile imgui with the C++ interop?

Swift 6 16.4 compile error, copied from xcode build:

<module-includes>:1:9: note: in file included from <module-includes>:1:
#import "/x/Sources/cxx_lib_imgui/include/backends/imgui_impl_glfw.h"
        ^
/x/Sources/cxx_lib_imgui/include/backends/imgui_impl_glfw.h:27:10: note: in file included from /x/Sources/cxx_lib_imgui/include/backends/imgui_impl_glfw.h:27:
#include "imgui.h"      // IMGUI_IMPL_API
         ^

/x/Sources/cxx_lib_imgui/include/imgui.h:2164:142: error: invalid application of 'sizeof' to an incomplete type 'ImGuiDockNodeSettings'
    inline ImVector<T>& operator=(const ImVector<T>& src)   { clear(); resize(src.Size); if (src.Data) memcpy(Data, src.Data, (size_t)Size * sizeof(T)); return *this; }
                                                                                                                                             ^
/x/Sources/cxx_lib_imgui/include/imgui.h:2164:25: note: in instantiation of member function 'ImVector<ImGuiDockNodeSettings>::operator=' requested here
    inline ImVector<T>& operator=(const ImVector<T>& src)   { clear(); resize(src.Size); if (src.Data) memcpy(Data, src.Data, (size_t)Size * sizeof(T)); return *this; }
                        ^
/x/Sources/cxx_lib_imgui/include/imgui_internal.h:154:8: note: forward declaration of 'ImGuiDockNodeSettings'
struct ImGuiDockNodeSettings;
       ^
/x/Sources/cxx_lib_imgui/include/imgui.h:2164:142: error: invalid application of 'sizeof' to an incomplete type 'ImGuiDockRequest'
    inline ImVector<T>& operator=(const ImVector<T>& src)   { clear(); resize(src.Size); if (src.Data) memcpy(Data, src.Data, (size_t)Size * sizeof(T)); return *this; }
                                                                                                                                             ^
/x/Sources/cxx_lib_imgui/include/imgui.h:2164:25: note: in instantiation of member function 'ImVector<ImGuiDockRequest>::operator=' requested here
    inline ImVector<T>& operator=(const ImVector<T>& src)   { clear(); resize(src.Size); if (src.Data) memcpy(Data, src.Data, (size_t)Size * sizeof(T)); return *this; }
                        ^
/x/Sources/cxx_lib_imgui/include/imgui_internal.h:152:8: note: forward declaration of 'ImGuiDockRequest'
struct ImGuiDockRequest;
       ^



imgui_internal.h:
struct ImGuiDockNodeSettings; 

imgui.cpp:
struct ImGuiDockNodeSettings
{
    ImGuiID             ID;
    ImGuiID             ParentNodeId;
    ImGuiID             ParentWindowId;
    ImGuiID             SelectedTabId;
    signed char         SplitAxis;
    char                Depth;
    ImGuiDockNodeFlags  Flags;
    ImVec2ih            Pos;
    ImVec2ih            Size;
    ImVec2ih            SizeRef;
    ImGuiDockNodeSettings() { memset(this, 0, sizeof(*this)); SplitAxis = ImGuiAxis_None; }
};

Thanks, any help much appreciated.

Reproduction

None

Expected behavior

Compiled ok, runs the code.

Environment

swift-driver version: 1.120.5 Apple Swift version 6.1.2 (swiftlang-6.1.2.1.2 clang-1700.0.13.5)
Target: arm64-apple-macosx15.0

Additional information

No response

Activity

added
bugA deviation from expected or documented behavior. Also: expected but undesirable behavior.
triage neededThis issue needs more specific labels
on Jun 4, 2025
adozenlines

adozenlines commented on Jun 7, 2025

@adozenlines

Have you tried passing flags to the C++ compiler? You might have to google specific flags for Xcode but my guess is clang is clang.

Compiler Flags
There are no specific compiler flags that are directly related to forward declarations. However, some compiler flags can help with code organization and dependency management, which can indirectly improve the effectiveness of forward declarations:
-MM or -MD (gcc/clang): These flags generate dependency files that can be used to identify which header files are needed, and which can be replaced with forward declarations.
-Wpendantic (gcc/clang): This flag can help catch issues with forward declarations, such as using an incomplete type where a complete type is expected.
ravikandhadai

ravikandhadai commented on Jun 13, 2025

@ravikandhadai
Contributor

Thanks for filing the report. @broccolihighkicks would it be possible for you to attach a reproducer for this issue?

kersson

kersson commented on Aug 8, 2025

@kersson

We also have this problem in our code base. I was able to boil it down to this minimal example utilizing the pimpl pattern:

// foo.h
#pragma once

#include <memory>

class FooImpl;

class Foo {
   public:
    Foo();
    ~Foo();

    Foo(Foo &&) = default;
    Foo &operator=(Foo &&) = default;

   private:
    std::unique_ptr<FooImpl> pImpl;
};
// foo.c
#include "foo.h"

class FooImpl {};

Foo::Foo() : pImpl(std::make_unique<FooImpl>()) {}
Foo::~Foo() = default;
// module.modulemap
module CxxFoo {
    header "foo.h"

    export *
}
// main.swift
import CxxFoo

class SwiftFoo {
    var foo: Foo = Foo()
}

The following build command works fine on Xcode 16.2:

clang++ --std=c++14 -c foo.cc -o foo.o
swiftc -cxx-interoperability-mode=default -I . -o main main.swift foo.o

but fails on Xcode 16.3 and 16.4 with the following error:

/Users/kersson/dev/playground/swift_cxx_interop/./foo.h:3:2: note: in module 'std_memory' imported from /Users/kersson/dev/playground/swift_cxx_interop/./foo.h:3:
 1 | #pragma once
 2 | 
 3 | #include <memory>
   |  `- note: in module 'std_memory' imported from /Users/kersson/dev/playground/swift_cxx_interop/./foo.h:3:
 4 | 
 5 | class FooImpl;

/Applications/Xcode_16.3.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.4.sdk/usr/include/c++/v1/memory:944:2: note: in module 'std_private_memory_inout_ptr' imported from /Applications/Xcode_16.3.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.4.sdk/usr/include/c++/v1/memory:944:
942 | #include <__memory/allocator_traits.h>
943 | #include <__memory/auto_ptr.h>
944 | #include <__memory/inout_ptr.h>
    |  `- note: in module 'std_private_memory_inout_ptr' imported from /Applications/Xcode_16.3.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.4.sdk/usr/include/c++/v1/memory:944:
945 | #include <__memory/out_ptr.h>
946 | #include <__memory/pointer_traits.h>

/Applications/Xcode_16.3.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.4.sdk/usr/include/c++/v1/__memory/inout_ptr.h:16:2: note: in module 'std_private_memory_shared_ptr' imported from /Applications/Xcode_16.3.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.4.sdk/usr/include/c++/v1/__memory/inout_ptr.h:16:
 14 | #include <__memory/addressof.h>
 15 | #include <__memory/pointer_traits.h>
 16 | #include <__memory/shared_ptr.h>
    |  `- note: in module 'std_private_memory_shared_ptr' imported from /Applications/Xcode_16.3.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.4.sdk/usr/include/c++/v1/__memory/inout_ptr.h:16:
 17 | #include <__memory/unique_ptr.h>
 18 | #include <__type_traits/is_same.h>

/Applications/Xcode_16.3.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.4.sdk/usr/include/c++/v1/__memory/shared_ptr.h:32:2: note: in module 'std_private_memory_unique_ptr' imported from /Applications/Xcode_16.3.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.4.sdk/usr/include/c++/v1/__memory/shared_ptr.h:32:
  30 | #include <__memory/pointer_traits.h>
  31 | #include <__memory/uninitialized_algorithms.h>
  32 | #include <__memory/unique_ptr.h>
     |  `- note: in module 'std_private_memory_unique_ptr' imported from /Applications/Xcode_16.3.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.4.sdk/usr/include/c++/v1/__memory/shared_ptr.h:32:
  33 | #include <__type_traits/add_lvalue_reference.h>
  34 | #include <__type_traits/conditional.h>

/Applications/Xcode_16.3.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.4.sdk/usr/include/c++/v1/__memory/unique_ptr.h:79:19: error: invalid application of 'sizeof' to an incomplete type 'FooImpl'
 76 |   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 default_delete(const default_delete<_Up>&) _NOEXCEPT {}
 77 | 
 78 |   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 void operator()(_Tp* __ptr) const _NOEXCEPT {
    |                                                            `- note: in instantiation of member function 'std::default_delete<FooImpl>::operator()' requested here
 79 |     static_assert(sizeof(_Tp) >= 0, "cannot delete an incomplete type");
    |                   `- error: invalid application of 'sizeof' to an incomplete type 'FooImpl'
 80 |     static_assert(!is_void<_Tp>::value, "cannot delete an incomplete type");
 81 |     delete __ptr;

/Users/kersson/dev/playground/swift_cxx_interop/./foo.h:5:7: note: forward declaration of 'FooImpl'
 3 | #include <memory>
 4 | 
 5 | class FooImpl;
   |       `- note: forward declaration of 'FooImpl'
 6 | 
 7 | class Foo {
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

bugA deviation from expected or documented behavior. Also: expected but undesirable behavior.c++ interopFeature: Interoperability with C++triage neededThis issue needs more specific labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

    Development

    No branches or pull requests

      Participants

      @kersson@adozenlines@ravikandhadai@broccolihighkicks

      Issue actions

        Xcode 16.4 breaks Swift C++ interop when C++ uses forward-decl · Issue #81965 · swiftlang/swift