Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ODR bug in MSVC?

This program prints 1 1 instead of 1 2 when compiled with MSVC (up to VS 2015).

f1.cpp:

#include <functional>

static std::function<int ()> helper() {
    struct F { int operator()() { return 1; } };
    return F();
}

std::function<int ()> f1() { return helper(); }

f2.cpp:

#include <functional>

static std::function<int ()> helper() {
    struct F { int operator()() { return 2; } };
    return F();
}

std::function<int ()> f2() { return helper(); }

main.cpp:

#include <functional>
#include <iostream>

std::function<int ()> f1();
std::function<int ()> f2();

int main() {
    std::cout << f1()() << " " << f2()() << "\n";
}

It's as if the different definitions of F are breaking ODR. But shouldn't local classes be distinct? Interestingly, if we replace F with lambda functions there is no conflict.

So is this a compiler bug or am I misunderstanding the one definition rule?

like image 599
Valentin Milea Avatar asked Nov 05 '15 12:11

Valentin Milea


1 Answers

It's clearly a bug in MSVC, as all the types are unique. Perhaps for structs defined inside some function (in this case helper) MSVC internally treats them as if they are defined as helper::F while if helper is static it should have done something like this f1_cpp::helper::F instead. As a result at link time linker sees two identically named inline functions and merges them into one.

Most likely by reordering input files you can get 2 2 if you weren't happy with 1 1 :)

like image 87
Pavel P Avatar answered Oct 31 '22 23:10

Pavel P