cgccinlinec99

gcc - 2 versions, different treatment of inline functions


Recently I've come across a problem in my project. I normally compile it in gcc-4, but after trying to compile in gcc-3, I noticed a different treatment of inline functions. To illustrate this I've created a simple example:

main.c:

#include "header.h"
#include <stdio.h>

int main()
{
    printf("f() %i\n", f());
    return 0;
}

file.c:

#include "header.h"
int some_function()
{
    return f();
}

header.h

inline int f()
{
    return 2;
}

When I compile the code in gcc-3.4.6 with:

gcc main.c file.c -std=c99 -O2

I get linker error (multiple definition of f), the same if I remove the -O2 flag. I know the compiler does not have to inline anything if it doesn't want to, so I assumed it placed f in the object file instead of inlining it in case of both main.c and file.c, thus multiple definition error. Obviously I could fix this by making f static, then, in the worst case, having a few f's in the binary.

But I tried compiling this code in gcc-4.3.5 with:

gcc main.c file.c -std=c99 -O2

And everything worked fine, so I assumed the newer gcc inlined f in both cases and there was no function f in the binary at all (checked in gdb and I was right).

However, when I removed the -O2 flag, I got two undefined references to int f(). And here, I really don't understand what is happening. It seems like gcc assumed f would be inlined, so it didn't add it to the object file, but later (because there was no -O2) it decided to generate calls to these functions instead of inlining and that's where the linker error came from.

Now comes the question: how should I define and declare simple and small functions, which I want inline, so that they can be used throughout the project without the fear of problems in various compilers? And is making all of them static the right thing to do? Or maybe gcc-4 is broken and I should never have multiple definitions of inline functions in a few translation units unless they're static?


Solution

  • Yes, the behavior has been changed from gcc-4.3 onwards. The gcc inline doc (http://gcc.gnu.org/onlinedocs/gcc-4.1.2/gcc/Inline.html) details this.

    Short story: plain inline only serves to tell gcc (in the old version anyway) to inline calls to the from the same file scope. However, it does not tell gcc that all callers would be from the file scope, thus gcc also keeps a linkable version of f() around: which explains your duplicate symbols error above.

    Gcc 4.3 changed this behavior to be compatible with c99.

    And, to answer your specific question:

    Now comes the question: how should I define and declare simple and small functions, which I want inline, so that they can be used throughout the project without the fear of problems in various compilers? And is making all of them static the right thing to do? Or maybe gcc-4 is broken and I should never have multiple definitions of inline functions in a few translation units unless they're static?

    If you want portability across gcc versions use static inline.