c++gccclang++

A class is defined using __FILE__ in two different files; which definition is used depends whether I use it in a never-invoked function. Why?


main.cpp:

#include <iostream>

struct Cls {
    static void some_method() {
        std::cout << __FILE__ << ": " << __LINE__ << std::endl;
    }
};

extern void call_some_method();

void never_caled() {
    Cls::some_method();  // (1)
}

int main() {
    call_some_method();
    return 0;
}

cls.cpp:

#include <iostream>

struct Cls {
    static void some_method() {
        std::cout << __FILE__ << ": " << __LINE__ << std::endl;
    }
};

void call_some_method() {
    Cls::some_method();
}

When (1) is commented, call_some_method() write "/home/maxim/CLionProjects/bug/cls.cpp: 5" to std::cout.

When (1) is uncommented, call_some_method() write "/home/maxim/CLionProjects/bug/main.cpp: 5" to std::cout.

How it can be possible for different outputs?


Solution

  • __FILE__ and __LINE__ are macros that are expanded by the pre-processor. Since those macros are in different files, and depend on the files they are used in, they expand to different token sequences.

    That means that your definition of Cls::some_method is different across different translation units. This violates the one-definition-rule (ODR) which requires, among other things, that there be exactly one definition of a particular entity in your entire program. If there are multiple definitions, that's fine, so long as the token sequence of those definitions is identical in every translation unit, and those tokens mean the same thing when they are parsed.

    This is obviously not true in your case, so you are violating the ODR, which makes the program ill-formed (No Diagnosis Required). This means the compiler is not obliged to give you an error, but if it does produce a program, executing that program invokes undefined behavior (UB). So your program could do anything at all, including producing the output that you are seeing.