Does redefining a function from the standard library violate the one-definition rule?

c++, c-standard-library, language-lawyer, one-definition-rule, std

Solution

Typical scenario.

If `extern "C" double log(double)` is initially declared in the global namespace, then you have redeclared it and provided a definition. The implementation's previous mention of `extern "C"` carries over to your matching redeclaration. Your definition applies to the function belonging to the implementation, and it is an ODR violation.

As for the manifestation of UB: It's apparently common to treat `log` as a weak linker symbol. Your implementation overrides `libc.so` according to ABI rules.

(If the implementation doesn't do `extern "C"`, it's still basically all the same.)

Other likely scenario.

If `log` is declared in `namespace std` and then brought into the global namespace, then your declaration will conflict with it. (Actually, a `using` declaration is technically a declaration.) This error is diagnosed.

Assumption-violating scenario.

then it refers to the same function as the `log` function we defined

One way for the implementation to put `<cmath>` names into the global namespace would be to declare `extern "C"` functions inside `namespace std`, then do `using namespace std`, and to ensure that this always happens as the first thing when any standard header is included. Since `using namespace` isn't "sticky" — it only applies to preceding declarations in the nominated namespace — the rest of the standard library would not be made visible. (This would not declare the names in the global namespace, but the standard only says "placed within the global namespace scope.")

In such an implementation, your declaration would hide the standard one and declare a new function with a new mangled name (say `_Z3logd` instead of simply `log`) and a new fully-qualified name (`::log` instead of `::std::log`). Then there would be no ODR violation (unless some inline function uses one `log` in one TU and the other in a different TU).

Problem

``` #include <cmath> double log(double) {return 1.0;} int main() { log(1.0); } ``` Suppose the function `log()` in `<cmath>` is declared in global namespace (this is unspecified in fact, and we just make this assumption), then it refers to the same function as the `log()` function we defined. So does this code violate the one-definition rule (see here, since no diagnostic required, this code may compile in some compiler and we cannot assert if it is correct)? Note: After recent edits, this is not a duplicate of: What exactly is One Definition Rule in C++?

Original source

Related problems