Page MenuHome GnuPG

libmpi inlining results in multiple definitions of symbols (when compiled by clang)
Closed, ResolvedPublic

Description

When libgcrypt is compiled using clang, the linking fails because of multiple
definitions of libmpi functions:

/usr/bin/x86_64-pc-linux-gnu-ld: error: ../mpi/.libs/libmpi.a(mpi-bit.o):
multiple definition of '_gcry_mpih_add'
/usr/bin/x86_64-pc-linux-gnu-ld: ../mpi/.libs/libmpi.a(mpi-add.o): previous
definition here
[...]

The reason for this seems to be that the same functions are both declared as
'regular' (in mpi-internal.h) and 'extern inline' (in mpi-inline.h). This does
not conform to any C standard, and the result is completely unpredictable.

I am attaching a patch which seems to be the best way of achieving expected
functionality (if I'm reading the current code correctly) while staying
compliant with the standards.

It declares both the prototypes and the inline functions as 'inline', so the
compiler is forward-aware that there may be inline definitions coming. As the
'inline' keyword is merely a tip, this solution works as well when there are no
inline definitions actually (with mpi-inline.h include removed).

I've used 'inline' rather than 'inline' because the headers seem to be
internal and autoconf uses AC_C_INLINE already, so that symbol should be always
declared.

Details

Version
1.5.0

Event Timeline

It seems that my patch does actually break gcc... i'm not sure how to handle
this correctly anyway. It seems that the problem is actually unsolvable, and
there's no correct way to mix inline functions and external assembly definitions.

Inline is an extension to C90 implemented by almost all compilers.
What we do is what the gcc manual suggest for ages:

   This combination of `inline' and `extern' has almost the effect of
   a macro.  The way to use it is to put a function definition in a
   header file with these keywords, and put another copy of the
   definition (lacking `inline' and `extern') in a library file.  The
   definition in the header file will cause most calls to the function
   to be inlined.  If any uses of the function remain, they will refer
   to the single copy in the library.

I don’t know why clang seems to be the only compiler who does not grok
this. Libgcrypt has been compiled on a wide range of compilers
without any problem.

Wait, I see. Clang pretends to be gcc and defines GNUC. Thus
mpi-internal.h includes the inline functions:

  #ifdef __GNUC__
  #include "mpi-inline.h"
  #endif

which is a valid gcc construct. As with some other bug reports; I can
only suggest to fix clang and don't have it define GNUC .

This problem also happens with gcc if run in -std=c99 mode. It is due to a
change in gcc 4.3. It has been fixed in for stable and master. It is thus
likely that the problem is also solved for clang.

werner claimed this task.