I have these two source files that compile and link without any problem.
a.cpp
enum class numbers
{
one,
two,
};
const char* getName(numbers number)
{
switch (number)
{
case numbers::one:
return "one";
break;
case numbers::two:
return "two";
break;
}
}
b.cpp
#include <iostream>
enum class numbers
{
zero,
one,
two,
};
const char* getName(numbers number);
void print(numbers number)
{
std::cout << getName(number);
}
int main()
{
print(numbers::one);
return 0;
}
As you can see the same enum class is defined differently in each file. I am looking for a way to catch these kind of conflicts of enum classes (causing bugs in our very very big code base) in different translation units. Does any compiler/linker has the capability to generate error in such situation?
CodePudding user response:
The shown error is a violation of the One Definition Rule.
The C standard does not require either the compiler or a linker to report a diagnostic when the One Definition Rule is violated. I.e. "no diagnostic required".
In other words: your C compiler is not required to report this specific error. This is because in many cases it's simply not possible to technically detect a violation of the one definition rule, due to low-level technical implementation details of how code gets compiled and linked on some particular operating system, or platform.
In general: it is in every modern C compiler's interest to report as many useful diagnostics as possible. In other words: if it's possible for a C compiler to detect an ODR violation, it would readily do so without being prodded into it. If your C compiler does not produce a diagnostic for an ODR violation, it is unlikely that there's any hidden switch or a button that can be pushed in order to make the error come out.
CodePudding user response:
There is no possibility for the linker to catch this. An enum class definition just defines a number of compile time constants that the compiler will use to generate code. There is no object created for any of the identifiers of the enum that the linker could see and warn about duplicates.
I also don't see why this code would be a problem at all. You aren't exporting the type, it's used solely inside the compilation unit. There is no cross over between the two definitions. While the standard might point at the one definition rule I see no practical problem.
But if you try to create a problem, if you put the type into the header files and try to include both then the compiler will fails with a duplicate definition. Any attempt to call getname()
from both a.cpp and b.cpp or use the enums would include a.h and b.h and then fail. So unless you are careless with writing your header files and use forward declarations without definitions you will always get an error before it matters.