2 ms·
Citing the translation phases in the standard as evidence that undefined behavior is ok, as long as it's divided between two translation units, strikes me as wi
by haberman 11y ago
Citing the translation phases in the standard as evidence that undefined behavior is ok, as long as it's divided between two translation units, strikes me as wishful thinking.
- kazinator 11y agoUndefined behavior is the absence of requirements: there not being any requirements for some situation. Suppose a document tells you that for some special situation X, there is an absence of requirements. However, suppose that some other general rules elsewhere in that document in fact imply a requirement for that situation. That just means that the claim that situation X has no requirements is incorrect. For instance, ISO C says that two struct types appearing in separate translation unit are only compatible of they have the same typed members in the same order ... with the same names. This says that if you do aliasing with otherwise identical structures that don't have the same names, the behavior is undefined: i.e. that there is no requirement that it work. But, we can infer that it must work by the logical fact that during the semantic processing of one translation unit, the translator has no clue what the names of struct members are in another translation unit. They disappear at translation time and turn into offsets. I mean, we can fwrite a struct to a file, right? We can send that file over a network. According to ISO C, every program (or at least every C program) will have to use a structure with the correct names to fread that area of the file! Ridiculous! Suppose we take ISO C and add a statement to it like, "the consequences are undefined if one of the operands of the + operator is the integer 42". The rest of the document would still be exactly what it is, and if we strike out that sentence with a black marker, nothing has changed. The rest of the document continues to inform us that adding 42 to something is well-defined (in the absence of overflow, or overflow-like issues with pointer displacement and so on). Basically, it's a contradiction: the document gives a description which adds up to some requirements, but then some sentence tries to take them away. In such a situation, we can just proceed as if the requirements apply. That is to say, when a requirement conflicts with the claim that there is no requirement, just let the requirement prevail. (In a situation where conflicting requirements are asserted, it's a different story, of course.)
- xorblurb 11y agoYou can't infer shit, because of the way current compiler writers are interpreting the standard today. At one point in the 90's it was obvious for the entire planet including compiler authors that some undefined behaviors did not apply for a given target architecture, so obviously obvious that nobody would even require to have it specified in the compiler doc (still nice to have, but you would not be too much angry if it does not appear) Now they just add their "optimizations" at the highest levels so of course even for targets where it should makes no sense, and without asking for your permission, and even by default, and even some they consider "aggressive". So either you have provisions to avoid all that shit, like having a guy disabling all the new ones each time you upgrade you compiler, and you better have some defenses in depth, and I agree with you that using TU as boundaries is also a good idea, if your compiler+build-sys have an option to NOT do WPO. But it is just not in any way guaranteed by the ISO standard, and still just an implementation detail from its pov. And honestly that's a problem. Because compiler writers will takes more drugs and come up with new imaginative way to break your code more, in the name of their "strictly-conformance and nothing more" crazy ideal.