home bbs files messages ]

Forums before death by AOL, social media and spammers... "We can't have nice things"

   comp.lang.c      Meh, in C you gotta define EVERYTHING      243,242 messages   

[   << oldest   |   < older   |   list   |   newer >   |   newest >>   ]

   Message 242,761 of 243,242   
   David Brown to highcrew   
   Re: On Undefined Behavior   
   04 Jan 26 12:58:03   
   
   From: david.brown@hesbynett.no   
      
   On 03/01/2026 23:47, highcrew wrote:   
   > On 1/2/26 11:52 PM, Kaz Kylheku wrote:   
   >> On 2026-01-01, highcrew  wrote:   
   >> For the situation in your program, it would be unacceptable to have   
   >> implementations stop translating.   
   >   
   > I can somehow get the idea that it is difficult for the compiler   
   > to spot the issue, but why do you think it would be unacceptable   
   > to stop translating?   
   >   
      
   A C compiler definitely should /not/ stop translating just because it   
   finds UB like this - at least, not with "normal" compilation flags.   
   (With additional flags, anything is allowable.)   
      
   Run-time UB is only a problem if the running program attempts to execute   
   it.  So it is only really appropriate for it to be treated as a fatal   
   compile-time error if the compiler knows for sure that it will be   
   executed (i.e., it can trace all execution paths from the start of   
   "main" and see that it is inevitably executed).  That is clearly   
   infeasible for the vast majority of such run-time UB.   
      
   It is entirely normal that code is full of potential run-time UB :   
      
   	extern int xs[10];   
   	int foo(int i) { return xs[i]; }   
      
   The function "foo" has potential UB - but the compiler should not stop   
   translating just because you /might/ call it with an inappropriate argument.   
      
   Functions that have unavoidable UB, such as the example in this thread,   
   are not guaranteed to be called - the compiler cannot reasonably refuse   
   to continue compiling.  But it is also fair to say unavoidable UB in a   
   function is almost certainly a mistake by the programmer, and a warning   
   message (even without specifying any warning flags) would be a very nice   
   thing for the compiler to give you.   
      
   The C standard requires certain mistakes to require a diagnostic - a   
   warning or fatal error message.  It only does that for things that a   
   compiler could reasonably be expected to identify, without having to   
   simulate run-time conditions, or consider multiple translation units at   
   once.   
      
      
      
   >> We really want just a warning (at   
   >> least by default; in specific project and situations, developers   
   >> could elect to treat certain warnings as fatal, even standard-required   
   >> warnings.)   
   >   
   > Even a warning would be enough though.  Btw, my typical way of   
   > working is to enable -Werror while developing, but I don't like   
   > to force it in general.  That would be an interesting digression,   
   > but definitely OT.   
   >   
      
   (I too have "-Werror" enabled, at least once my initial builds are   
   somewhat solidified - it means you can't lose an important warning   
   message somewhere in the output of your build process.)   
      
   >> The second new thing is that to diagnose this, we need to make   
   >> diagnosis dependent on reachability.   
   >>   
   >> We want a rule which is something like "whenever the body of   
   >> a function, or an initializing expression for an external definition   
   >> reaches an expression which has unconditional undefined behavior   
   >> that is not an unreachability assertion and not a documented   
   >> extension, a warning diagnostic must be issued".   
   >   
   > That's an interesting perspective: reachability.   
   > Would you say that the incriminated piece of code is UB only if it   
   > is reachable in the final program, therefore it is acceptable   
   > to keep it as long as unreachable?   
   >   
   > Now that I think of it, the __builtin_unreachable() implemented   
   > by popular compilers is technically UB *if reached* :)   
   >   
      
   "unreachable()" is now standard, in C23.  But that may be what Kaz is   
   referring to as "an unreachability assertion".   
      
   And AFAIUI gcc and clang/llvm have an "UB" instruction or statement in   
   their internal formats, and will use that for "__builtin_unreachable()"   
   and also when generating code from your example.   
      
   >> This kind of diagnostic would be a good thing in my opinion; just   
   >> nobody has stepped up to the plate because of the challenges:   
   >>   
   >> - introducing the concept of a warning versus error diagnostic.   
   >>   
   >> - defining a clear set of rules for trivial reachability which   
   >>    can catch the majority of these situations without too much   
   >>    complexity. (The C++ rules for functions that return value   
   >>    reaching their end without a return statement can be used   
   >>    as inspiration here.)   
   >>   
   >> - specifying exactly what "statically obvious" undefined behavior   
   >>    is and how positively determine that a certain expression   
   >>    exhibits it.   
   > Now I'm wondering how much work it requires to properly define   
   > the rules that the standard mandates!   
   >   
      
   Um, the standard defines the rules - that's the point.  So your question   
   is really "how much work did it take to write the C standard?".  I don't   
   think that's what you meant.   
      
   > As for me the main take-away is that the detection of certain UB   
   > is non-trivial, it would be very evil if the standard was mandating   
   > some nearly-impossible task to the compiler!   
   >   
      
   The standard is quite lenient on what it requires from C compilers   
   (though most don't follow all its rules by default).  Static warnings   
   are a matter of quality of implementation, not requirements of the   
   language.  This lets people write relatively small and simple C   
   compilers if they want, while also giving big toolchains the freedom to   
   add lots more checking and developer help.   
      
   >   
   >  > (The C++ rules for functions that return value   
   >  >    reaching their end without a return statement can be used   
   >  >    as inspiration here.)   
   >   
   > C++ does *what*?? I'm definitely not up to speed with C++, but   
   > I totally have missed that.  Could you please tell me the name   
   > of this bizarre feature? I *need* to look it up :D   
   >   
      
   I believe the difference is in the behaviour of a function that is   
   declared to return a value (i.e., not "void") but which exits without a   
   returning value.  In C, this is allowed - but it is UB to attempt to use   
   the non-existent return value.  In C++, it is UB to fail to return a   
   value - which is far easier for a compiler to diagnose.   
      
   So if you have :   
      
   	int foo(void) { }   
      
   	int bar(void) { return foo(); }   
      
   then in C++, the UB is in the definition of "foo", while in C it is in   
   the run-time use of "foo" inside "bar".   
      
   --- SoupGate-Win32 v1.05   
    * Origin: you cannot sedate... all the things you hate (1:229/2)   

[   << oldest   |   < older   |   list   |   newer >   |   newest >>   ]


(c) 1994,  bbs@darkrealms.ca