Yes it is possible. But subtle differences between languages can lead to the fact that they will differ from a similar source. It is rare that an interface module will provide background output to exactly the same inputs. It can be optimized for simple functions and, as a rule, will use the same strategies for things. (for example, on x86, how many LEA commands should be used instead of multiplication.)
eg. in C, overflow overflow is undefined behavior, therefore
void foo(int *p, int n) { for (int i = 0; i <= n ; i++) { p[i] = i/4; } }
can be considered finally completed for all possible n (including INT_MAX ), and for i non-negative.
With an interface for a language in which i++ defined to have 2 complement wrappers (or gcc with -fwrapv -fno-strict-overflow ), i will go from ==INT_MAX to a large negative value, always <= INT_MAX . The compiler will have to make asm, which correctly implements the behavior of the source code even for callers who pass n == INT_MAX , making it an infinite loop, where i can be negative.
But since undefined Behavior is in C and C ++, the compiler can assume that the program does not contain any UB, and thus, no caller can pass INT_MAX . He can assume that i never negative inside a loop and that the loop counter is the same as a int . See Also What Every C Programmer Should Know About Undefined Behavior (clang blog).
A non-negative assumption allows you to implement i / 4 with a simple shift to the right, and not apply the division semantics C of integer division for negative numbers.
Source + asm output in Godbolt compiler explorer .
But if the behavior signed by the wrapper is determined, the signed division by constant takes more instructions, and indexing the array should take into account possible packaging:
The syntax syntax of the array is just sugar for the pointer + integer and does not require the index to be non-negative. Thus, it is permissible for the caller to pass a pointer to the middle of a 4 GB array, which this function should ultimately write. (Endless loops are also questionable, but NVM does.)
As you can see, the tiny difference in language rules required the compiler not to optimize. The differences between language rules are usually greater than the difference between the C ++ ISO and the C ++ flavor set by a signature that g ++ can implement.
In addition, if the “regular” types have a different width or signature in another language, it is very likely that the source code will have different meanings, and in some cases it will matter.
If I used unsigned , then the wrapper would be a certain overflow behavior in C and C ++. But unsigned types are by definition non-negative, so the ability to bypass will not have such an obvious effect on optimizations without a reversal. If the cycle started from zero, then the workaround makes it possible to return to 0 if that matters (for example, x / i is division by zero).