4

After reading static variables in an inlined function, I wrote this test program:

main.cpp:

#include <iostream>
#include "a.h"
#include "f.h"

void g();

int main()
{
    std::cout << "int main()\n";
    f().info();
    g();
}

a.h:

struct A
{
    A() { std::cout << "A::A()\n"; }
    void info() { std::cout << this << '\n'; }
};

f.h: (singleton local to each compilation unit because of the unnamed namespace)

namespace {
inline A& f()
{
    static A x;
    return x;
}
}

g.cpp:

#include <iostream>
#include "a.h"
#include "f.h"

void g()
{
    std::cout << "void g()\n";
    f().info();
}

The problem is that I don't get the same results with different compilers:

g++ 4.8.2: OK

int main()
A::A()
0x6014e8
void g()
A::A()
0x6014d0

clang++ 3.7.0: OK

int main()
A::A()
0x6015d1
void g()
A::A()
0x6015c1

icpc 15.0.2: no call to A::A() inside g() !

int main()
A::A()
0x601624
void g()
0x601620

Is this a bug in icpc ? Is the behaviour of the program not defined ? If I replace "namespace {...}" with "static" in f.h, A::A() is called inside g() as expected. Shouldn't the behaviour be the same?

If I remove "namespace {...}" in f.h, A::info() prints the same object address in main() and g(), and A::A() is called only once (with all compilers) as expected.

Community
  • 1
  • 1
Jac
  • 41
  • 2
  • 1
    Maybe related: http://stackoverflow.com/questions/8784892/is-stdcout-guaranteed-to-be-initialized. You cannot really say, that you don't get the constructor call, just that the output doesn't happen. And since you are in static constructor country, you might run into another other bug, instead. – dhke Jan 21 '16 at 15:23
  • The program has been compiled with "-std=c++11" with all compilers. – Jac Jan 21 '16 at 15:27
  • 1
    Your source code and program output don't match up. `main()` outputs `"void g()\n"`. – Arne Vogel Jan 21 '16 at 17:14
  • @Arne Thanks, corrected – Jac Jan 21 '16 at 19:12

1 Answers1

3

Since C++11 mandates names in unnamed namespaces to have internal linkage, every translation unit should have it's own version of f() and, as a result, it's own version of static A x. So gcc and clang are correct.

Seems like icpc is not following C++11 standard and instead following C++03, which allowed those names to be declared with external linkage. Since when you explicitly make f() internal by using static icpc follows the suit, I have a strong suspicion this is simply a bug.

SergeyA
  • 61,605
  • 5
  • 78
  • 137
  • The program has been compiled with "-std=c++11" with all compilers. – Jac Jan 21 '16 at 15:27
  • 3
    @Jac That does not protect a compiler from having bugs. – Angew is no longer proud of SO Jan 21 '16 at 15:30
  • If it was externally linked wouldn't there be a single object at a single memory location? The icpc run returns two different memory locations. Seems like you are just not getting the output in the constructor call... – efunkh Jan 21 '16 at 16:36
  • No: there should be (and there is) 1 object per compilation unit (g.cpp and main.cpp) as f() is in unnamed namespace. – Jac Jan 21 '16 at 17:59