Archived

This forum has been archived. Please start a new discussion on GitHub.

Patch for Ice 3.5.0: slice2cpp generates invalid code under certain circumstances

Problem description
If a slice contains interface declarations, but no interface definitions and makes use of a proxies of these types in a struct with a default initializer, the generated code won't compile because Proxy.h didn't get included in the generated header.

Patch
Include Proxy.h in case non local declarations exist.

To apply the patch Attachment not found. do:
cd Ice-3.5.0
patch -p0 < slice2cpp-decl.patch.txt

Example demonstrating the problem:
#ifndef TEST_ICE
#define TEST_ICE

module Test
{
  interface ForwardDeclared;

  struct Init
  {
    ForwardDeclared* member;
    int x = 0;
  };
};

#endif

Build using gcc:
[compile ~/testcase]$ slice2cpp Test.ice
[compile ~/testcase]$ g++ -I. -I/usr/local/include -c Test.cpp -o Test.o
/usr/local/include/Ice/ProxyHandle.h: In constructor 'IceInternal::ProxyHandle<T>::ProxyHandle(T*) [with T = IceProxy::Test::ForwardDeclared]':
./Test.h:78:   instantiated from here
/usr/local/include/Ice/ProxyHandle.h:124: error: invalid use of incomplete type 'struct IceProxy::Ice::Object'
/usr/local/include/Ice/ProxyHandle.h:31: error: forward declaration of 'struct IceProxy::Ice::Object'
/usr/local/include/Ice/ProxyHandle.h: In destructor 'IceInternal::ProxyHandle<T>::~ProxyHandle() [with T = IceProxy::Test::ForwardDeclared]':
./Test.h:78:   instantiated from here
/usr/local/include/Ice/ProxyHandle.h:164: error: invalid use of incomplete type 'struct IceProxy::Ice::Object'
/usr/local/include/Ice/ProxyHandle.h:31: error: forward declaration of 'struct IceProxy::Ice::Object'
/usr/local/include/Ice/ProxyHandle.h: In copy constructor 'IceInternal::ProxyHandle<T>::ProxyHandle(const IceInternal::ProxyHandle<T>&) [with T = IceProxy::Test::ForwardDeclared]':
./Test.h:84:   instantiated from here
/usr/local/include/Ice/ProxyHandle.h:156: error: invalid use of incomplete type 'struct IceProxy::Ice::Object'
/usr/local/include/Ice/ProxyHandle.h:31: error: forward declaration of 'struct IceProxy::Ice::Object'

Build using clang:
[compile ~/testcase]$ slice2cpp Test.ice
[compile ~/testcase]$  clang++ -I. -I/usr/local/include -c Test.cpp -o Test.o
In file included from Test.cpp:21:
In file included from ./Test.h:24:
In file included from /usr/local/include/Ice/ProxyF.h:16:
/usr/local/include/Ice/ProxyHandle.h:124:31: error: member access into incomplete type
      '::IceProxy::Ice::Object'
            upCast(this->_ptr)->__incRef();
                              ^
./Test.h:77:5: note: in instantiation of member function
      'IceInternal::ProxyHandle<IceProxy::Test::ForwardDeclared>::ProxyHandle' requested here
    Init() :
    ^
/usr/local/include/Ice/ProxyHandle.h:31:7: note: forward declaration of 'IceProxy::Ice::Object'
class Object;
      ^
/usr/local/include/Ice/ProxyHandle.h:164:31: error: member access into incomplete type
      '::IceProxy::Ice::Object'
            upCast(this->_ptr)->__decRef();
                              ^
./Test.h:77:5: note: in instantiation of member function
      'IceInternal::ProxyHandle<IceProxy::Test::ForwardDeclared>::~ProxyHandle' requested here
    Init() :
    ^
/usr/local/include/Ice/ProxyHandle.h:31:7: note: forward declaration of 'IceProxy::Ice::Object'
class Object;
      ^
/usr/local/include/Ice/ProxyHandle.h:156:31: error: member access into incomplete type
      '::IceProxy::Ice::Object'
            upCast(this->_ptr)->__incRef();
                              ^
./Test.h:83:9: note: in instantiation of member function
      'IceInternal::ProxyHandle<IceProxy::Test::ForwardDeclared>::ProxyHandle' requested here
        member(__ice_member),
        ^
/usr/local/include/Ice/ProxyHandle.h:31:7: note: forward declaration of 'IceProxy::Ice::Object'
class Object;
      ^
3 errors generated.

Analysis
slice2cpp/Gen.cpp only handles the cases
  • hasNonLocalClassDefs)
  • hasLocalClassDefsWithAsync

But not:
  • hasNonLocalClassDecls

The attached patch fixes this.

Comments

  • Addendum

    When starting from a clean source distribution, the dependency tree in cpp/src/Ice/.depend has to be changed as well. The patch attached takes care of this.

    Therefore the full procedure to apply both patch to a clean source distribution is:
    cd Ice-3.5.0
    patch -p0 < slice2cpp-decl.patch.txt
    patch -p0 < slice2cpp-decl-depend.patch.txt
    

    Cheers,
    Michael

    P.S. I assume that ZeroC has proper/better tools to manage dependencies automatically
  • bernard
    bernard Jupiter, FL
    Hi Michael,

    Thank you for these patches. We'll try to incorporate them into Ice 3.5.1.

    Regarding the .depend files, you can regenerate them with 'make depend'. See the depend:: target in cpp/config/Make.rules.

    Cheers,
    Bernard
  • Make depend fails

    Hi Bernard,

    Unfortunately the depend target fails on my system (see below).

    Regardless of this failure it seems to me like config/makedepend.py is written for Python 2.x and therefore won't work on a Python 3 only system, so adding it to an automatic from source build process might be difficult.

    Cheers,
    Michael

    Last few lines of gmake depend failing:
    gmake[3]: Leaving directory `/var/ports/basejail/usr/ports/devel/ice/work/Ice-3.5.0/cpp/src/slice2html'
    making depend in Ice
    gmake[3]: Entering directory `/var/ports/basejail/usr/ports/devel/ice/work/Ice-3.5.0/cpp/src/Ice'
    gmake[3]: *** No rule to make target `../../bin/slice2cpp', needed by `BuiltinSequences.cpp'.  Stop.
    gmake[3]: Leaving directory `/var/ports/basejail/usr/ports/devel/ice/work/Ice-3.5.0/cpp/src/Ice'
    gmake[2]: *** [depend] Error 1
    gmake[2]: Leaving directory `/var/ports/basejail/usr/ports/devel/ice/work/Ice-3.5.0/cpp/src'
    gmake[1]: *** [depend] Error 1
    gmake[1]: Leaving directory `/var/ports/basejail/usr/ports/devel/ice/work/Ice-3.5.0/cpp'
    gmake: *** [depend] Error 1
    *** [pre-build] Error code 2
    
  • benoit
    benoit Rennes, France
    Hi Michael,

    "make depend" isn't designed to be run from the source build. It's typically run on a Linux platform with Python 2.7.x. You need to build slice2cpp prior to run it since slice2cpp is required to compute slice file dependencies.

    Cheers,
    Benoit.