(Sorry for the extra-long delay; work problems.)
David Thompson said:
On Sat, 03 Jul 2010 07:58:01 -0700, Tim Rentsch
On Thu, 17 Jun 2010 12:31:40 -0700, Tim Rentsch
[snip]
We've had several tries seeking a term
for the (useful!) category of programs that portably work correctly,
and the least bad IMO was 'clc-compliant'.
The term 'clc-compliant' seems reasonable, or at least plausible,
but as a definition this statement falls short. Unless there
is some sort of definition of what it means to "work correctly",
it says nothing.
That is the hard part. My rough version is that a program works
correctly on some implementation if (each run of) it either produces
results consistent with (within the range specified by) a reasonable
understanding (mediated by discussion here if necessary) of the
standard
So... you want a term for a program that portably works
correctly, but you only require the program to run correctly
on one implementation? Where's the "portable" part?
Sorry, I quantified sloppily, I meant 'with respect to some=any'.
For each implementation X, my program run on X should produce results
consistent with my understanding of the standard, or none -- but not
necessarily the same as on Y!=X. In my OpenSSL example, it produces
different results on different implementations so it's not s.c., but
if on any given implementation X it produces either the results I
expect (for X) or indicates error, I call that correct.
This sounds like a tautology. Don't all programs produce results for
each implementation that are (in the context of the implementation in
question) consistent with the Standard, if that implementation is
conforming? Or do you mean to change what it means to be consistent
with the Standard, or what it means for an implementation to be
conforming, or both?
It's not a tautology, just a (over?)detailed statement of a point I
hadn't gotten across. Yes, program P run on conforming implementation
X must produce results consistent with the standard, or detected
error. But in case of UB that doesn't help, because anything at all is
consistent with std; and even some non-UB results are undesired.
P is 'clc-compliant' (or whatever we call it) if it produces *desired*
results (never UB), or error, on all implementations.
I'm satisfied with *implementation* conformance; the issue was about a
useful category of *programs* between s-c and conforming.
[snip] my goal is programs that do some desired thing, on many
platforms. I'm responsible for writing code that expresses that
desire; if my code is 'x-compliant' I claim each implementation is
responsible for carrying it out as written or indicating failure.
Don't conforming implementations already do that (assuming we're
talking just about compliance with ISO C)? If not then that sounds
like you think the Standard's notion of conformance should be
changed -- right? If that's right then changed how?
Implementation conformance is okay.
[snip]
SE/CV, not diagnostic is required. Do you mean to require compilers
(or runtimes) to diagnose all instances of undefined behavior? Because
if a program doesn't have SE/CV, the only choices left are defined
(including unspecified and implementation-defined) and undefined
behavior. For that matter, do you mean to require compliers/runtimes
to diagnose relying on unspecifed behavior or implementation-defined
behavior?
No no no, I didn't say or mean that. I said that if the Standard
allows a range of possibilities as unspec or impl-def, for a given
construct in my program, the implementation must do something in that
range or indicate error. The Standard says (and you reiterate) the
first part; what I'm arguably adding is that the loose wording in 1p2
shouldn't be a loophole:
I don't know what you're getting at with this statement.
Can you be more specific?
1p2 'does not specify ... size or complexity ... that will exceed the
capacity of ... system or ... processor' = part of an implementation.
This admits a (concrete) implementation can't handle the infinite set
of programs for which the Std defines abstract semantics, which must
be true; and silently allows that the boundary varies across
implementations, which in practice is true and unavoidable. AFAICS
nothing quite says what happens when you cross that boundary -- it
isn't SE/CV as defined, although it is a violation of a constraint in
a more general meaning. Is it 'nonportable ...' UB per 3.4.3? Is it
'correct in all other aspects' per 4p3? So keep reading:
I'm not sure what you're saying here. Do you mean a 'clc-compliant'
program can't have undefined behavior on any implementation? Or
if it does then the UB must be diagnosed (on those implemenations
where the UB occurs)? Or something else?
The first. A clc-compliant program can't do something which invokes UB
because then I couldn't have a nontrivial expectation from std of
valid semantics, which was my criterion. But if the *only* problem is
my program exceeds size & complexity limits for an implementation, so
the implementation is unable to execute (the semantics of) the code as
written, I claim that *isn't* UB, and the implementation must
diagnose. (Or slightly weaker -- if it gives me an error indication,
but not one documented as a diagnostic per 3.10, that's fine.)
What I won't accept is just malfunctioning. The classic example: if
(as common) implementation uses 'the stack' for all autos, temps and
returns, and my code calls more deeply than fits in in the available
stack space, and the stack growth just corrupts other data without any
indication, I consider that unacceptable.
In practice I don't have problems. Such misbehavior would be widely
considered bad QoI, and get driven out of the market, at least for
general-purpose systems (roughly, hosted). (For true embedded = tiny
systems, I would be willing to leave this burden on the programmer, or
much better the toolchain, e.g. a call tree analyzer.) But is it
nonconforming? Do 4p3, and 5.1.2.3, apply over 1p2? I'm not 100% sure.
Clearly we can't require a conforming implementation correctly execute
an otherwise correct program whose source code is larger than the
universe -- then no implementation could ever be conforming.
Even a nonnegligible fraction of the planet would be unaffordable.
Fortunately I can't -- *and* don't want to -- write anything that big.