Some problem about inline function in VS2019

740 views Asked by At

I'm doing some (maybe exotic) experiments about C++ inline functions in VS2019:

source1:

#include "pch.h"

inline int inline_func(int i) {
    return  i;
}

void testinline1()
{
    inline_func(0);
}

source2:

#include "pch.h"

inline int inline_func(int i) {
    return  i*i ;
}

void testinline2()
{
    inline_func(0);
}

main source:

#include "pch.h"

inline int inline_func(int i);
int main(int argc,char* argv[])
{   
    int i = inline_func(2);
}

According to "Storage classes of inline functions" section of http://en.wikipedia.org/wiki/Inline_function,

In C++, a function defined inline will, if required, emit a function shared among translation units, typically by putting it into the common section of the object file for which it is needed. The function must have the same definition everywhere, always with the inline qualifier.

The definitions of inline_func in source1 and source2 is different so there should be errors, but there is no such error in VS2019.

The result of i in main() is 2 which is from the inline_func in source1, this seems to be a random choice by the building process since if I comment testinline1 in source1, then i will become 4 since the inline_func in source1 won't show up in the object file without being used in the same source. When I comment testinline2 in source2 too there will be undefined symbol error for inline_func as expected.

Why does these happen? Is this where C++ doesn't cover or only MSVC doesn't cover?

Updated after answered:

Here is a better example:

source1:

#include "pch.h"

int non_inline_func();
inline int inline_func2() {
    return  non_inline_func();
}

static int non_inline_func()
{
    return 1;
}

int public_func1() 
{
    return inline_func2();
}

source2:

#include "pch.h"

int non_inline_func();
inline int inline_func2() {
    return  non_inline_func();
}

static int non_inline_func()
{
    return 2;
}

int public_func2()
{
    return inline_func2();
}

main source:

#include "pch.h"

int public_func1();
int public_func2();

void TestInline()
{
    int i =public_func1();
    int j= public_func2();
}

The result is i=j=1. The definition of the inline functions are the same here. This should violate this: https://en.cppreference.com/w/cpp/language/definition#One_Definition_Rule

name lookup from within each definition finds the same entities (after overload-resolution)

2

There are 2 answers

2
Some programmer dude On BEST ANSWER

From this One Definition Rule (ODR) reference:

If all these requirements are satisfied, the program behaves as if there is only one definition in the entire program. Otherwise, the program is ill-formed, no diagnostic required.

[Emphasis mine]

If you have an ODR-violation (which you have since the two definitions are not identical) the compiler doesn't have to emit a warning or error message.

0
Gary C On

Interestingly, in MSVS2019 ISO C++ 14...

The inline function :

inline uint32_t hanoi(int a) { __asm  bsf eax, a } // Solve arbitrary 'Tower of Hanoi' round

Called with either :

int numMoves = (1<<numDisks)-1; /* Calculate number of moves needed to solve */

// Print full Tower Of Hanoi solution
for (int i = 1;i < numMoves;i++) {
    printf("move disk %u %s\n", hanoi(i), hanoi(i) & 1 ? "left" : "right");
}

or, just :

hanoi(1);

Doesn't inline. It always results in a "Call" being emitted by the compiler : /

Same when I :

  • use std::cout ... like a good boy ; )
  • call the function directly (discarding) or;
  • call the function directly (utilizing return value)

and irrespective of whether :

  • Passed parameter is immediate/literal
  • Passed parameter is stack local variable
  • Passed parameter is heap allocated static global
  • Function is changed to be uint32_t f(void) { return 1; } <-- surprised me!

I notice that folks far cleverer than I have complained about similar in-lining issues in VS2015 and VS2017 - each comparing it to identical code in CLANG and GCC, whos compilers don't seem to have any issue : / Each time MS appear to have identified it as a compiler issue.

TBH, it looks like VS may just be a little 'fragile' when it comes to in-lining functions :(

Just my 2c

\o/ - "don't shoot!"