On 2024-02-08, Thiago Adams <
thiago...@gmail.com> wrote:
> Let's say C compilers can detect all sorts of bugs at compile time.
>
> How would C compilers report that? As an error or a warning?
ISO C doesn't distinguish "error" from "warning"; it speaks only about
diagnostics. It requires diagnostics for certain situations.
In compiler (not ISO C) parlance, we might understand "error" to be a
situation when a diagnostic is issued, and the implementation terminates
the translation, so that a translated program or translation unit is not
produced.
A "warning" is any other situation when a diagnostic is issued and
translation continues.
(These concepts extend into run-time. There could be a run-time diagnostic
which doesn't terminate the program, and one which does.)
With these definitions ...
> Let's use this sample:
>
> int main() {
> int a = 1;
> a = a / 0;
> }
>
> GCC says:
>
> warning: division by zero is undefined [-Wdivision-by-zero]
> 5 | a = a / 0;
> | ^ ~
> In case GCC or any other compiler reports this as an error, then C
> programmers would likely complain. Am I right?
They might.
A programmer taking a standard-based view might remark that
the program is not required to be diagnosed by ISO C.
It does invoke undefined behavior if executed, though.
Based on the deduction that the program has unconditional undefined
behavior, it is legitimate to terminate translating the program with a
diagnostic, since that is a possible consequence of undefined behavior.
> So, even if we had compile-time checks for bugs, C compilers and the
> standard are not prepared to handle the implications to make C a safer
> language.
>
> From my point of view, we need an error, not a warning.
Implementations are free to implement arbitrary diagnostics, and also
nonconforming modes of translation, which stop translating a program
that does not violate any ISO C syntax or constraint rule.
Thus compilers can provide tools to help programmers enforce
rules that don't exist in the language as such.
> But we also
> need a way to ignore the error in case the programmer wants to see what
> happens, with a division by zero, for instance. (Please note that this
> topic IS NOT about this specific warning; it is just a sample.)
>
> Warnings work more or less like this. The problem with warnings is that
> they are not standardized - the "name/number" and the way to
> disable/enable them.
>
> So this is the first problem we need to solve in C to make the language
> safer. We need a mechanism.
>
> I also believe we can have a standard profile for warnings that will
> change the compiler behaviour; for instance, making undefined behaviour
> an error.
>
> The C standard is complacent with the lack of error messages. Sometimes
> it says "message is encouraged...". This shifts the responsibility from
I don't believe so. The C standard absolutely requires diagnostics
for certain situations. Everywhere else, it doesn't.
I don't remember seeing any text "encouraging" a diagnostic.
That's ambiguous: is it really required or not?
> the language. But when someone says "C is dangerous," the language as a
> whole is blamed, regardless of whether you are using MISRA, for instance.
>
> Thus, not only are the mechanics of the language is unprepared, but the
> standard is also not prepared to assume the responsibility of being a
> source of guidance and safety.
The standard specifies which constructs are required to do what under
what conditions, and those situations are safe.
Sometimes "do what" is unspecified (the implementation choices from a
range of safe behaviors) or implementation-defined (similar, but
implementation also documents the choice).
The standard also specifies that some situations must be diagnosed,
like syntax and type errors and other constraint rule violations.
Everything else is undefined behavior (some of it potentially
defined by the implementation as a "documented extension").
Avoidance of undefined behavior is left to the careful design
of the program, and whatever tools the implementation and third parties
provide for detecting undefined behavior.
Some languages, like Common Lisp, provide a notion of safety level.
Over individual expressions in Lisp, we can declare optimization
parameters: safety (0-3) and speed (0-3). We can also declare facts to
the Common Lisp compiler like types of operands and results. When we
lie to the compiler, the behavior becomes undefined, but the situation
is nuanced. Safe code diagnoses errors. If we tell the Lisp compiler
that some X is a cons cell, and then access (car X), but at run time, X
turns out to be a string, an error will be signaled. However, if we
compile the code with safety 0, all bets are off: the machine code may
blindly access the string object as if it were a cons cell, with
disastrous consequences.
C could benefit from an approach along these lines. The big problem is
that in C it's hard to impossible to make many undefined behaviors
safe (as in detect them and abort the program).
For isntance, there is no way to tell whether a pointer is valid
or not, or how large an array it points to.
Lisp is a safe, dynamic language first, and an aggressively optimized
language second. It's easy to tell that (car X) is accessing a string
and not a cons cell thanks to the run-time information in the objects.
It's easier to strip away safety from a safe language, and generate
unsafe code that works with lower level machine types, than to introduce
safety into a machine-oriented language, because the data
representations don't accomodate the needed run-time bits.
--
TXR Programming Language:
http://nongnu.org/txr
Cygnal: Cygwin Native Application Library:
http://kylheku.com/cygnal
Mastodon: @
Kazi...@mstdn.ca