"J. David Bryan" wrote:
On 19 Nov 2002 at 12:00, CBFalconer wrote:
This particular error is **very** hard to detect at run-time in any efficient manner.
I'm not sure I understand this. Is it not a matter of checking, before each component access, whether the variant selector (or selectors) is in the range of the corresponding case-constant-list? Isn't that a simple range check, e.g., equivalent to that performed before an assignment?
No. Let's consider
TYPE r = RECORD CASE a : integer OF 0: ( onebyte : 0..127); 1: ( twobyte : -5..512); END; END;
VAR rcd : r; .... r.twobyte := something; (* something may be an integer *)
The compiler tables hold something describing the location of r, and offsets from there to a, onebyte, and fourbyte. It also holds acceptable ranges for each value. It can generate code (for a stack machine) something like:
LDCA r (* address of r *) LDC offsetof twobyte ADD (forming address of twobyte, or maybe onebyte *) LOD something (* whatever is to be stored *) CHK minval, maxval (* which may cause an exception *) STI 1 (* putting it away *)
Now, where is the compiler going to get the values of minval and maxval? To do so it would have to read a, and translate that somehow into minval and maxval at run time. Where are those tables stored? Nothing insists that a be a valid initialized value before storing something in onebyte. Remember, onebyte and twobyte have the same offsets. They can store different subranges. a may have been set in another procedure far, far away.
In addition, the compiler knows that it is storing a twobyte value. If it got it from something of appropriate type it knows it need not do a check on this store, and can totally elide the CHK operation. No such efficiencies if we have to read and translate the a value first.
Without that check the only differences for storing onebyte and twobyte are the (known at compile time) values of minval and maxval, and quite possibly the operand of STI, which specifies the size of the thing to be written.
In other words full checking here is a monstrous can of worms.
Checking that the variant selector is in range never enters into it (except when storing that value at some other time). The names in the different variants are known to be disjoint (standard specified) so that the name used specifies the variant desired. Also there is no default "otherwise" clause in this flavor of a CASE statement AFAIK.