Context: In a recent conversation, the question \"does gcc/clang do strlen(\"static string\")
at compile time?\" came up. After some testing, the answer seems t
Per C 2011 (draft N1570) 7.1.3 1 and 2:
All identifiers with external linkage in any of the following subclauses … are always reserved for use as identifiers with external linkage.
If the program declares or defines an identifier in a context in which it is reserved (other than as allowed by 7.1.4), or defines a reserved identifier as a macro name, the behavior is undefined.
The “following subclauses” specify the standard C library, including strlen
. Your program defines strlen
, so its behavior is undefined.
What is happening in the case you observe is:
strlen
is supposed to behave, regardless of your definition, so, while optimizing strlen("abcd")
in f
, it evaluates strlen
at compile time, resulting in four.g("abcd")
, the compiler fails to recognize that, because of the definition of g
, this is equivalent to strlen("abcd")
, so it does not optimize it at compile time. Instead, it compiles it to a call to g
, and it compiles g
to call strlen
, and it also compiles your definition of strlen
, with the result that g("abcd")
calls g
, which calls your strlen
, which returns ten.The C standard would allow the compiler to discard your definition of strlen
completely, so that g
returned four. However, a good compiler should warn that your program defines a reserved identifier.