lcm-proj / lcm

Lightweight Communications and Marshalling
GNU Lesser General Public License v2.1
944 stars 385 forks source link

invalid conversion in `_computeHash` (`-fpermissive`) on a type that includes an array of another type #450

Open bluesquall opened 1 year ago

bluesquall commented 1 year ago

If I can't track this down on my own, I'll make a minimum (non)working example in a public repository, probably a personal fork of LCM.

Here's the compiler error:

/usr/local/include/.../raw/countdowns_t.hpp: In static member function 'static uint64_t raw::countdowns_t::_computeHash(const __lcm_hash_ptr*)':
/usr/local/include/.../raw/countdowns_t.hpp:173:36: error: invalid conversion from 'void*' to 'int64_t (*)()' {aka 'long int (*)()'} [-fpermissive]
  173 |     const __lcm_hash_ptr cp = { p, (void*)countdowns_t::getHash };
      |                                    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
      |                                    |
      |                                    void*

and here's a snippet of what lcm-gen --cpp generates when I use any of the releases 1.3.1, 1.4.0, or 1.5.0 installed in a podman container FROM debian:bullseye-slim.

uint64_t countdowns_t::_computeHash(const __lcm_hash_ptr *p)
{
    const __lcm_hash_ptr *fp;
    for(fp = p; fp != NULL; fp = fp->parent)
        if(fp->v == countdowns_t::getHash)
            return 0;
    const __lcm_hash_ptr cp = { p, (void*)countdowns_t::getHash };

    uint64_t hash = 0x890e9cbb16a6f746LL +
         raw::countdown_t::_computeHash(&cp);

    return (hash<<1) + ((hash>>63)&1);
}

compare that to the corresponding snippet from lcm-gen --cpp on my workstation, built from the git repository (i.e., not a release), likely[^1] at commit 91ce7a2a:

uint64_t countdowns_t::_computeHash(const __lcm_hash_ptr *p)
{
    const __lcm_hash_ptr *fp;
    for(fp = p; fp != NULL; fp = fp->parent)
        if(fp->v == countdowns_t::getHash)
            return 0;
    const __lcm_hash_ptr cp = { p, countdowns_t::getHash };

    uint64_t hash = 0x890e9cbb16a6f746LL +
         raw::countdown_t::_computeHash(&cp);

    return (hash<<1) + ((hash>>63)&1);
}

Note the missing (void *) cast on countdowns_t::getHash.

This only seems to affect LCM type definitions that include an array of another LCM type, as far as I can tell.

There are a few other differences between the generated files -- the ones generated on my workstation include extra comment strings (pulled from the .lcm type definitions) and some spelling errors are fixed on my workstation where the errors are still present in the comment strings from the releases in the container.

This looks like a similar problem to the one reported in #337 and #338, but oddly reversed.

[^1]: I'm reluctant to mess with the installation on the workstation until I've tracked this down, so I can't reinstall to confirm that this is the commit I last built from.

bluesquall commented 1 year ago

Rolling the version of LCM installed in the container back to 1.3.1 avoids the compiler error, even though the output from lcm-gen --cpp is the same for 1.3.1, 1.4.0, and 1.5.0, which leads me to suspect there's some inconsistency between the output from lcm-gen and one the LCM headers (possibly <lcm/lcm_coretypes.h>) in the later releases, but only when a type includes an array of another type.

tprk77 commented 11 months ago

Looks like this was changed in 47641ba6d20ef1c619200281333b7e6b08fad4c1. Based on the diff, it appears that the (void *) cast should no longer be there, because it is no longer necessary. Note that __lcm_hash_ptr changed. I'm guessing there's a version mismatch between the installed LCM and the lcmgen you are using.