Search code examples
c++adaexternpragma

Avoiding warning 8-bit Ada Boolean return type, use Char


I have been working on cleaning up warnings on pedantic code, and we treat warnings as errors. I have interface code between Ada and C++, which looks like this:

Ada manager.ads:

function Foo(ID_Type : in Integer) return Boolean;
pragma Import(CPP, Foo, "Foo");

C++ Adamanager.cpp:

extern "C" bool Foo(int32_t ID)
{
  return Manager::GetManager()->Bar(ID);
}

C++ Adamanager.h:

extern "C" bool Foo(int32_t ID);

C++ manager.cpp:

bool Manager::Bar(int32_t ID)
{
   //function body
   return answer;
}

C++ manager.h

static bool Bar(int32_t ID);

gcc -c output for manager.ads:

warning: return type of "Foo" is an 8-bit Ada Boolean
warning: use appropriate corresponding type in C (e.g. char)

I have a bunch of these cases.

To get rid of the warnings, do I need to replace all of the bools with char or some other 8-bit type and then do an explicit type conversion in the Ada body code? Why would the compiler choose to have the boolean be 8-bit?


Solution

  • There are a number of problems with this approach. First, your C function should be declared using C types. While there are standard headers that declare bool and int32_t, since you don't include them, you should replace them with corresponding C types, probably char and int:

    extern "C" char Foo (int ID);
    

    Second, since your function is declared to be C, not C++, you should import it with convention C, not CPP. (The whole reason for declaring such C wrappers around C++ is to avoid the problems of interfacing directly to C++.)

    Third, it is a bad idea to interface to C using non-convention-C types such as Integer and Boolean. It may work, but it's not guaranteed to continue working with future versions of the compilers. It's better to use the appropriate types from Interfaces.C.

    Fourth, you have no guarantee that the value returned will be limited to 0 or 1, so you need to treat it as C does, 0 or non-0.

    With all this, your Ada then becomes

    with Interfaces.C;
    
    function Foo (ID : in Integer) return Boolean is
       function Foo (ID : in Interfaces.C.int) return Interfaces.C.unsigned_char
       with Import, Convention => C, External_Name => "Foo";
    
       use type Interfaces.C.unsigned_char;
    begin -- Foo
       return Foo (Interfaces.C.int (ID) ) /= 0;
    end Foo;
    

    though you probably want to use a type other than Integer for IDs on the Ada side.

    This should work correctly, eliminate your warnings, and provide some protection against compiler changes.