emscripten-core / emscripten

Emscripten: An LLVM-to-WebAssembly Compiler
Other
25.35k stars 3.25k forks source link

Compilation error when binding custom types as field in a value_object #22107

Closed schultezb closed 5 days ago

schultezb commented 1 week ago

We encounter a regression after updating Emscripten from 3.1.49 to 3.1.60. Binding custom types as field of an emscripten::value_object now triggers a compilation error 'uses_ref_count' is a private member of 'emscripten::val'. Binding native types as field works as expected. Manually editing val.h to make val::uses_ref_count() public instead of private solves the issue but is obviously a hack.

Details We use a couple of custom types inheriting from emscripten::val so that we can nicely wrap/convert complex C++ types to JS types/objects that can be used more naturally on the JS side. We then bind them to value_objects so that we don't need to worry about lifetime issues.

Minimally reproducable example:

namespace em = emscripten;
struct JsObject : public em::val
{
    JsObject() : em::val(em::val::object()) {}
    explicit JsObject(const em::val& other) : em::val(other) {}

    // conversion code C++ type to/from JsObject omitted for brevity
};

struct Foo
{
    int intVal;
    JsObject jsVal;
};
EMSCRIPTEN_BINDINGS(Foo)
{
    em::register_type<JsObject>("JsObject");
    em::value_object<Foo>("Foo")
        .field("intVal", &Foo::intVal)    // for exposition that primitive types work as expected
        .field("jsVal", &Foo::jsVal);     // triggers compilation error: 'uses_ref_count' is a private member of 'emscripten::val'
}

Please include the following in your bug report:

Version of emscripten/emsdk:

emcc (Emscripten gcc/clang-like replacement + linker emulating GNU ld) 3.1.60 (42a6ea2052f19f70d7d994e8c324bcad2f1f8939)
clang version 19.0.0git (https:/github.com/llvm/llvm-project bc9823cf60bf91cc8b45248c4205cd2c67b2a3d5)
Target: wasm32-unknown-emscripten
Thread model: posix

Failing command line in full:

  FAILED: CMakeFiles/WebSDK.dir/src/main.cpp.o 
  C:\Users\xxx\Documents\_dev\emsdk\upstream\emscripten\em++.bat -DBOOST_CHRONO_NO_LIB -DBOOST_DATE_TIME_NO_LIB -DBOOST_FILESYSTEM_NO_LIB -DBOOST_LOCALE_NO_LIB -DBOOST_PROGRAM_OPTIONS_NO_LIB -DBOOST_REGEX_NO_LIB -DBOOST_SYSTEM_NO_LIB -DEIGEN_MPL2_ONLY -IC:/Users/xxx/Documents/_dev/WebSDK/include -IC:/Users/xxx/Documents/_dev/WebSDK/_build-vs-debug/build/x64-Release -isystem C:/Users/xxx/Documents/_dev/externals-emscripten/eigen/3.3.5/include/eigen3 -isystem C:/Users/xxx/Documents/_dev/externals-emscripten/boost/1.85.0/include -isystem C:/Users/xxx/Documents/_dev/externals-emscripten/minizip/3.0.9/include -isystem C:/Users/xxx/Documents/_dev/externals-emscripten/zstd/1.5.0/include -isystem C:/Users/xxx/Documents/_dev/externals-emscripten/fmt/9.1.0/include -O3 -DNDEBUG -std=gnu++17 -Wall -Wno-unknown-pragmas -Wno-reorder -Wno-sign-compare -Werror=return-type -fwasm-exceptions -Wno-overloaded-virtual -Wno-potentially-evaluated-expression -fvisibility=hidden -s USE_ZLIB=1 -s USE_LIBPNG=1 -s USE_FREETYPE=1 -MD -MT CMakeFiles/WebSDK.dir/src/main.cpp.o -MF CMakeFiles\WebSDK.dir\src\main.cpp.o.d -o CMakeFiles/WebSDK.dir/src/main.cpp.o -c C:/Users/xxx/Documents/_dev/WebSDK/src/main.cpp
  In file included from C:/Users/xxx/Documents/_dev/WebSDK/src/main.cpp:1:
  In file included from C:\Users\xxx\Documents\_dev\emsdk\upstream\emscripten\cache\sysroot/include\emscripten/bind.h:26:
C:\Users\xxx\Documents\_dev\emsdk\upstream\emscripten\cache\sysroot\include\emscripten\val.h(816,11): error G3281C4F0: 'uses_ref_count' is a private member of 'emscripten::val'
    816 |     if (v.uses_ref_count()) {
        |           ^
  C:\Users\xxx\Documents\_dev\emsdk\upstream\emscripten\cache\sysroot/include\emscripten/bind.h:719:31: note: in instantiation of member function 'emscripten::internal::BindingType<JsObject>::toWireType' requested here
    719 |         return MemberBinding::toWireType(ptr.*field, rvp::default_tag{});
        |                               ^
  C:\Users\xxx\Documents\_dev\emsdk\upstream\emscripten\cache\sysroot/include\emscripten/bind.h:1075:24: note: in instantiation of function template specialization 'emscripten::internal::MemberAccess<Foo, JsObject>::getWire<Foo>' requested here
   1075 |             ::template getWire<ClassType>;
        |                        ^
  C:/Users/xxx/Documents/_dev/WebSDK/src/main.cpp:135:4: note: in instantiation of function template specialization 'emscripten::value_object<Foo>::field<Foo, JsObject>' requested here

    135 |                 .field("jsVal", &Foo::jsVal);     // triggers compilation error: 'uses_ref_count' is a private member of 'emscripten::val'

        |                  ^

  C:\Users\xxx\Documents\_dev\emsdk\upstream\emscripten\cache\sysroot/include\emscripten/val.h:645:8: note: declared private here

    645 |   bool uses_ref_count() const {

        |        ^

  1 error generated.
brendandahl commented 1 week ago

I believe this is fixed in 3.1.60 from https://github.com/emscripten-core/emscripten/commit/1336355ab0bc040c9122ef8b93aae40366920fce

schultezb commented 6 days ago

Thank you, I can confirm that this particular bug is fixed in 3.1.61.

We're experiencing different issues with that version such as a LLVM frontend crash with some particular code of ours but that is outside of the scope of this issue.