Issue1406

Title libmpi inlining results in multiple definitions of symbols (when compiled by clang)
Priority bug Status resolved
Category libgcrypt Due Date
Version 1.5.0 ExtLink  (go)
Superseder Nosy List mgorny
Assigned To Topics  (help)

Created on 2012-06-13.07:40:51 by mgorny, last changed 2012-11-08.14:48:10 by werner.

Messages
msg4449 (view) Author: werner Date: 2012-11-07.17:19:14
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.
msg4390 (view) Author: werner Date: 2012-08-09.13:52:49
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__ .
msg4284 (view) Author: mgorny Date: 2012-06-13.20:22:07
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.
msg4282 (view) Author: mgorny Date: 2012-06-13.07:40:51
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.
History
Date User Action Args
2012-11-08 14:48:10wernersetstatus: chatting -> resolved
2012-11-07 17:19:15wernersettopic: - nobug, clangbug
messages: + msg4449
2012-08-09 13:54:15wernersettopic: + clangbug, - patch
2012-08-09 13:52:49wernersettopic: + nobug
messages: + msg4390
2012-06-13 20:22:07mgornysetstatus: unread -> chatting
messages: + msg4284
2012-06-13 20:20:55mgornysetfiles: - 0001-Fix-use-of-inline-to-avoid-multiple-declarations.patch
2012-06-13 07:40:51mgornycreate